mirror of
https://github.com/Wanxp/obsidian-douban.git
synced 2026-04-04 08:38:41 +08:00
complete version 1.0.1
This commit is contained in:
parent
9b55b3b88e
commit
20f49a685c
87
README.md
87
README.md
@ -1,73 +1,18 @@
|
||||
# Obsidian Sample Plugin
|
||||
|
||||
This is a sample plugin for Obsidian (https://obsidian.md).
|
||||
|
||||
This project uses Typescript to provide type checking and documentation.
|
||||
The repo depends on the latest plugin API (obsidian.d.ts) in Typescript Definition format, which contains TSDoc comments describing what it does.
|
||||
|
||||
**Note:** The Obsidian API is still in early alpha and is subject to change at any time!
|
||||
|
||||
This sample plugin demonstrates some of the basic functionality the plugin API can do.
|
||||
- Changes the default font color to red using `styles.css`.
|
||||
- Adds a ribbon icon, which shows a Notice when clicked.
|
||||
- Adds a command "Open Sample Modal" which opens a Modal.
|
||||
- Adds a plugin setting tab to the settings page.
|
||||
- Registers a global click event and output 'click' to the console.
|
||||
- Registers a global interval which logs 'setInterval' to the console.
|
||||
|
||||
## First time developing plugins?
|
||||
|
||||
Quick starting guide for new plugin devs:
|
||||
|
||||
- Check if [someone already developed a plugin for what you want](https://obsidian.md/plugins)! There might be an existing plugin similar enough that you can partner up with.
|
||||
- Make a copy of this repo as a template with the "Use this template" button (login to GitHub if you don't see it).
|
||||
- Clone your repo to a local development folder. For convenience, you can place this folder in your `.obsidian/plugins/your-plugin-name` folder.
|
||||
- Install NodeJS, then run `npm i` in the command line under your repo folder.
|
||||
- Run `npm run dev` to compile your plugin from `main.ts` to `main.js`.
|
||||
- Make changes to `main.ts` (or create new `.ts` files). Those changes should be automatically compiled into `main.js`.
|
||||
- Reload Obsidian to load the new version of your plugin.
|
||||
- Enable plugin in settings window.
|
||||
- For updates to the Obsidian API run `npm update` in the command line under your repo folder.
|
||||
|
||||
## Releasing new releases
|
||||
|
||||
- Update your `manifest.json` with your new version number, such as `1.0.1`, and the minimum Obsidian version required for your latest release.
|
||||
- Update your `versions.json` file with `"new-plugin-version": "minimum-obsidian-version"` so older versions of Obsidian can download an older version of your plugin that's compatible.
|
||||
- Create new GitHub release using your new version number as the "Tag version". Use the exact version number, don't include a prefix `v`. See here for an example: https://github.com/obsidianmd/obsidian-sample-plugin/releases
|
||||
- Upload the files `manifest.json`, `main.js`, `styles.css` as binary attachments. Note: The manifest.json file must be in two places, first the root path of your repository and also in the release.
|
||||
- Publish the release.
|
||||
|
||||
> You can simplify the version bump process by running `npm version patch`, `npm version minor` or `npm version major` after updating `minAppVersion` manually in `manifest.json`.
|
||||
> The command will bump version in `manifest.json` and `package.json`, and add the entry for the new version to `versions.json`
|
||||
|
||||
## Adding your plugin to the community plugin list
|
||||
|
||||
- Check https://github.com/obsidianmd/obsidian-releases/blob/master/plugin-review.md
|
||||
- Publish an initial version.
|
||||
- Make sure you have a `README.md` file in the root of your repo.
|
||||
- Make a pull request at https://github.com/obsidianmd/obsidian-releases to add your plugin.
|
||||
# Obsidian Douban Plugin
|
||||

|
||||
Import Movies, Books, Music Data from Douban in [Obsidian](https://obsidian.md/)
|
||||
在[Obsidian](https://obsidian.md/)使用并导入豆瓣中的电影/音乐/以及书籍等, 评分/发布日期/演员表等信息
|
||||
- [Bugs, Issues, & Feature Requests](https://github.com/Wanxp/obsidian-douban/issues)
|
||||
- [Development Roadmap](https://github.com/users/Wanxp/projects/1)
|
||||
|
||||
## How to use
|
||||
|
||||
- Clone this repo.
|
||||
- `npm i` or `yarn` to install dependencies
|
||||
- `npm run dev` to start compilation in watch mode.
|
||||
|
||||
## Manually installing the plugin
|
||||
|
||||
- Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/your-plugin-id/`.
|
||||
|
||||
## Improve code quality with eslint (optional)
|
||||
- [ESLint](https://eslint.org/) is a tool that analyzes your code to quickly find problems. You can run ESLint against your plugin to find common bugs and ways to improve your code.
|
||||
- To use eslint with this project, make sure to install eslint from terminal:
|
||||
- `npm install -g eslint`
|
||||
- To use eslint to analyze this project use this command:
|
||||
- `eslint main.ts`
|
||||
- eslint will then create a report with suggestions for code improvement by file and line number.
|
||||
- If your source code is in a folder, such as `src`, you can use eslint with this command to analyze all files in that folder:
|
||||
- `eslint .\src\`
|
||||
|
||||
|
||||
## API Documentation
|
||||
|
||||
See https://github.com/obsidianmd/obsidian-api
|
||||
### Movie
|
||||
- Search Movie By File Name/通过文件名搜索
|
||||

|
||||
- Search Movie By Input Text/通过输入文本搜索
|
||||

|
||||
## Settings
|
||||
- Setting Example1/设置案例1
|
||||

|
||||
- Setting Example2/设置案例2
|
||||

|
||||
|
||||
BIN
doc/search_by_file_name.gif
Normal file
BIN
doc/search_by_file_name.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 594 KiB |
BIN
doc/search_by_input.gif
Normal file
BIN
doc/search_by_input.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 MiB |
BIN
doc/setting_en.gif
Normal file
BIN
doc/setting_en.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
BIN
doc/setting_zh.gif
Normal file
BIN
doc/setting_zh.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
@ -1,11 +1,19 @@
|
||||
import { i18nHelper } from "lang/helper";
|
||||
import { type } from "os";
|
||||
|
||||
interface DoubanPluginSettings {
|
||||
export interface DoubanPluginSettings {
|
||||
movieTemplate:string,
|
||||
dateFormat:string,
|
||||
searchUrl:string,
|
||||
arraySpilt:string,
|
||||
searchHeaders?:string,
|
||||
personNameMode:PersonNameMode,
|
||||
}
|
||||
|
||||
export enum PersonNameMode {
|
||||
CH_NAME = "CH",
|
||||
EN_NAME = "EN",
|
||||
CH_EN_NAME = "CH_EN",
|
||||
}
|
||||
|
||||
|
||||
@ -32,15 +40,15 @@ export const DEFAULT_SETTINGS:DoubanPluginSettings = {
|
||||
searchUrl: 'https://www.douban.com/search?q=',
|
||||
searchHeaders: JSON.stringify(doubanHeadrs),
|
||||
dateFormat: "yyyy_MM_DD",
|
||||
arraySpilt: ", "
|
||||
|
||||
|
||||
arraySpilt: ", ",
|
||||
personNameMode: PersonNameMode.CH_NAME
|
||||
|
||||
}
|
||||
|
||||
export const personNameModeRecords: {[key in PersonNameMode]: string} = {
|
||||
[PersonNameMode.CH_NAME]: i18nHelper.getMessage("Chinese Name"),
|
||||
[PersonNameMode.EN_NAME]: i18nHelper.getMessage("English Name"),
|
||||
[PersonNameMode.CH_EN_NAME]: i18nHelper.getMessage("Chinese And English Name"),
|
||||
}
|
||||
|
||||
export class DefaultSettingsContent {
|
||||
|
||||
}
|
||||
|
||||
export type {DoubanPluginSettings}
|
||||
@ -1,8 +1,9 @@
|
||||
import { App, PluginSettingTab, Setting } from "obsidian";
|
||||
import { DEFAULT_SETTINGS, PersonNameMode, personNameModeRecords } from "./Douban";
|
||||
|
||||
import { DEFAULT_SETTINGS } from "./Douban";
|
||||
import DoubanPlugin from "main";
|
||||
import { i18nHelper } from "lang/helper";
|
||||
import { log } from "utils/Logutil";
|
||||
|
||||
export class DoubanSettingTab extends PluginSettingTab {
|
||||
plugin: DoubanPlugin;
|
||||
@ -87,6 +88,33 @@ export class DoubanSettingTab extends PluginSettingTab {
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl).setName(i18nHelper.getMessage("Person Name Language Mode")).then((setting) => {
|
||||
setting.addDropdown((dropdwon) => {
|
||||
setting.descEl.appendChild(
|
||||
createFragment((frag) => {
|
||||
frag.appendText(i18nHelper.getMessage('options:'));
|
||||
frag.createEl('br');
|
||||
frag.appendText(i18nHelper.getMessage('Chinese Name mode, only show Chinese name'));
|
||||
frag.createEl('br');
|
||||
frag.appendText(i18nHelper.getMessage('English Name mode, only show English name'));
|
||||
frag.createEl('br');
|
||||
frag.appendText(i18nHelper.getMessage('Chinese English Name mode, show Chinese English name both'));
|
||||
frag.createEl('br');
|
||||
})
|
||||
);
|
||||
// dropdwon.inputEl.addClass("settings_area");
|
||||
// dropdwon.inputEl.setAttr("rows", 10);
|
||||
dropdwon.addOption(PersonNameMode.CH_NAME, personNameModeRecords.CH)
|
||||
dropdwon.addOption(PersonNameMode.EN_NAME, personNameModeRecords.EN)
|
||||
dropdwon.addOption(PersonNameMode.CH_EN_NAME, personNameModeRecords.CH_EN)
|
||||
dropdwon.setValue(this.plugin.settings.personNameMode)
|
||||
.onChange(async (value:string) => {
|
||||
this.plugin.settings.personNameMode = value as PersonNameMode;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import { DoubanPluginSettings, PersonNameMode } from "douban/Douban";
|
||||
import cheerio, { CheerioAPI } from "cheerio";
|
||||
import { get, readStream } from "tiny-network";
|
||||
|
||||
import DoubanPlugin from "main";
|
||||
import { DoubanPluginSettings } from "douban/Douban";
|
||||
import DoubanSubject from "douban/model/DoubanSubject";
|
||||
import DoubanSubjectLoadHandler from "./DoubanSubjectLoadHandler";
|
||||
import { Editor } from "obsidian";
|
||||
import HttpUtil from "utils/HttpUtil";
|
||||
import { log } from "utils/logutil";
|
||||
import { json } from "stream/consumers";
|
||||
import { log } from "utils/Logutil";
|
||||
|
||||
export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject> implements DoubanSubjectLoadHandler<T> {
|
||||
|
||||
@ -18,7 +19,7 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
|
||||
this.doubanPlugin = doubanPlugin;
|
||||
}
|
||||
|
||||
abstract parseText(template: string, arraySpilt:string, extract: T): string;
|
||||
abstract parseText(extract: T, settings:DoubanPluginSettings): string;
|
||||
|
||||
abstract support(extract: DoubanSubject): boolean;
|
||||
|
||||
@ -41,4 +42,52 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
|
||||
return extract;
|
||||
}
|
||||
|
||||
getPersonName(name:string, settings:DoubanPluginSettings):string {
|
||||
if(!name || !settings || !settings.personNameMode) {
|
||||
return "";
|
||||
}
|
||||
var resultName = "";
|
||||
switch(settings.personNameMode) {
|
||||
case PersonNameMode.CH_NAME:
|
||||
var regValue = /[\u4e00-\u9fa5]{2,20}/g.exec(name);
|
||||
resultName = regValue?regValue[0]:name;
|
||||
break;
|
||||
case PersonNameMode.EN_NAME:
|
||||
var regValue = /[a-zA-Z.\s\-]{2,50}/g.exec(name);
|
||||
resultName = regValue?regValue[0]:name;
|
||||
break;
|
||||
default:
|
||||
resultName = name;
|
||||
}
|
||||
return resultName;
|
||||
}
|
||||
|
||||
html_encode(str:string):string
|
||||
{
|
||||
var s = "";
|
||||
if (str.length == 0) return "";
|
||||
s = str.replace(/&/g, "&");
|
||||
s = s.replace(/</g, "<");
|
||||
s = s.replace(/>/g, ">");
|
||||
s = s.replace(/ /g, " ");
|
||||
s = s.replace(/\'/g, "'");
|
||||
s = s.replace(/\"/g, """);
|
||||
s = s.replace(/\n/g, "<br/>");
|
||||
return s;
|
||||
}
|
||||
|
||||
html_decode(str:string):string
|
||||
{
|
||||
var s = "";
|
||||
if (str.length == 0) return "";
|
||||
s = str.replace(/&/g, "&");
|
||||
s = s.replace(/</g, "<");
|
||||
s = s.replace(/>/g, ">");
|
||||
s = s.replace(/ /g, " ");
|
||||
s = s.replace(/'/g, "\'");
|
||||
s = s.replace(/"/g, "\"");
|
||||
s = s.replace(/<br\/>/g, "\n");
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
@ -30,7 +30,7 @@ export class DoubanEtractHandler {
|
||||
return;
|
||||
}
|
||||
var doubanSubjectHandlers:DoubanSubjectLoadHandler<DoubanSubject>[] = this._doubanSubjectHandlers
|
||||
.filter(h => h.support);
|
||||
.filter(h => h.support(searchExtract));
|
||||
if(doubanSubjectHandlers && doubanSubjectHandlers.length > 0) {
|
||||
var result = doubanSubjectHandlers.map(h => h.handle(searchExtract.url, editor))
|
||||
if(result && result.length > 0) {
|
||||
@ -41,21 +41,21 @@ export class DoubanEtractHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public parseText(template: string, arraySpilt:string, extract:DoubanSubject):string {
|
||||
if(!template) {
|
||||
public parseText(extract:DoubanSubject, settings:DoubanPluginSettings):string {
|
||||
if(!settings) {
|
||||
return "";
|
||||
}
|
||||
var doubanSubjectHandlers:DoubanSubjectLoadHandler<DoubanSubject>[] = this._doubanSubjectHandlers
|
||||
.filter(h => h.support);
|
||||
.filter(h => h.support(extract));
|
||||
if(doubanSubjectHandlers && doubanSubjectHandlers.length > 0) {
|
||||
var result = doubanSubjectHandlers.map(h => h.parseText(template, arraySpilt, extract));
|
||||
var result = doubanSubjectHandlers.map(h => h.parseText(extract, settings));
|
||||
if(result && result.length > 0) {
|
||||
return result[0];
|
||||
}else {
|
||||
return "";
|
||||
}
|
||||
}else {
|
||||
return this._doubanSubjectHandlerDefault.parseText(template, arraySpilt, extract);
|
||||
return this._doubanSubjectHandlerDefault.parseText(extract, settings);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Editor, renderResults } from "obsidian";
|
||||
import { Editor, moment, renderResults } from "obsidian";
|
||||
import cheerio, { CheerioAPI } from 'cheerio';
|
||||
import { get, readStream } from "tiny-network";
|
||||
|
||||
@ -7,29 +7,32 @@ import DoubanMovieSubject from "douban/model/DoubanMovieSubject";
|
||||
import DoubanPlugin from "main";
|
||||
import { DoubanPluginSettings } from "douban/Douban";
|
||||
import DoubanSubject from "douban/model/DoubanSubject";
|
||||
import { log } from "utils/logutil";
|
||||
import SchemaOrg from "utils/SchemaOrg";
|
||||
import { log } from "utils/Logutil";
|
||||
|
||||
export default class DoubanMovieLoadHandler extends DoubanAbstractLoadHandler<DoubanMovieSubject> {
|
||||
|
||||
parseText(template: string, arraySpilt:string, extract: DoubanMovieSubject): string {
|
||||
return template ? template.replace("{{id}}", extract.id)
|
||||
.replace("{{type}}", extract.type ? extract.type : "")
|
||||
.replace("{{title}}", extract.title ? extract.title : "")
|
||||
.replace("{{desc}}", extract.desc ? extract.desc : "")
|
||||
.replace("{{image}}", extract.image ? extract.image : "")
|
||||
.replace("{{director}}", extract.director ? extract.director.join(arraySpilt) : "")
|
||||
.replace("{{actor}}", extract.actor ? extract.actor.join(arraySpilt) : "")
|
||||
.replace("{{author}}", extract.author ? extract.author.join(arraySpilt) : "")
|
||||
.replace("{{datePublished}}", extract.datePublished ? extract.datePublished : "")
|
||||
.replace("{{url}}", extract.url ? extract.url : "")
|
||||
.replace("{{score}}", extract.aggregateRating && extract.aggregateRating.ratingValue ? extract.aggregateRating.ratingValue + "" : "")
|
||||
parseText(extract: DoubanMovieSubject, settings:DoubanPluginSettings): string {
|
||||
return settings.movieTemplate ? settings.movieTemplate.replaceAll("{{id}}", extract.id)
|
||||
.replaceAll("{{type}}", extract.type ? extract.type : "")
|
||||
.replaceAll("{{title}}", extract.title ? extract.title : "")
|
||||
.replaceAll("{{desc}}", extract.desc ? extract.desc : "")
|
||||
.replaceAll("{{image}}", extract.image ? extract.image : "")
|
||||
.replaceAll("{{director}}", extract.director ? extract.director.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, settings)).filter(c => c).join(settings.arraySpilt) : "")
|
||||
.replaceAll("{{actor}}", extract.actor ? extract.actor.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, settings)).filter(c => c).join(settings.arraySpilt) : "")
|
||||
.replaceAll("{{author}}", extract.author ? extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, settings)).filter(c => c).join(settings.arraySpilt) : "")
|
||||
.replaceAll("{{datePublished}}", extract.datePublished ? moment(extract.datePublished).format(settings.dateFormat) : "")
|
||||
.replaceAll("{{url}}", extract.url ? extract.url : "")
|
||||
.replaceAll("{{score}}", extract.aggregateRating && extract.aggregateRating.ratingValue ? extract.aggregateRating.ratingValue + "" : "")
|
||||
: undefined; }
|
||||
support(extract: DoubanSubject): boolean {
|
||||
return extract && ('[电影]'==extract.type || 'Movie' == extract.type);
|
||||
return extract && extract.type && (extract.type.contains("电影") || extract.type.contains("Movie") || extract.type.contains("movie"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
constructor(doubanPlugin:DoubanPlugin) {
|
||||
super(doubanPlugin);
|
||||
}
|
||||
@ -40,10 +43,10 @@ export default class DoubanMovieLoadHandler extends DoubanAbstractLoadHandler<Do
|
||||
.filter(scd => "application/ld+json" == data(scd).attr("type"))
|
||||
.map(i => {
|
||||
var item = data(i).text();
|
||||
var obj = JSON.parse(item);
|
||||
item = super.html_decode(item);
|
||||
var obj = JSON.parse(item.replace(/[\r\n\s+]/g, ''));
|
||||
var idPattern = /(\d){5,10}/g;
|
||||
var id = idPattern.exec(obj.url);
|
||||
log.info(item);
|
||||
const result:DoubanMovieSubject = {
|
||||
id: id?id[0]:'',
|
||||
type: 'Movie',
|
||||
@ -54,10 +57,9 @@ export default class DoubanMovieLoadHandler extends DoubanAbstractLoadHandler<Do
|
||||
author: obj.author,
|
||||
actor: obj.actor,
|
||||
aggregateRating: obj.aggregateRating,
|
||||
datePublished:obj.datePublished,
|
||||
datePublished: obj.datePublished ? new Date(obj.datePublished) : undefined,
|
||||
image:obj.image
|
||||
}
|
||||
log.info(result);
|
||||
return result;
|
||||
})[0];
|
||||
}
|
||||
|
||||
@ -2,15 +2,16 @@ import { Editor, Notice } from "obsidian";
|
||||
|
||||
import { CheerioAPI } from "cheerio";
|
||||
import DoubanAbstractLoadHandler from "./DoubanAbstractLoadHandler";
|
||||
import { DoubanPluginSettings } from "douban/Douban";
|
||||
import DoubanSubject from "douban/model/DoubanSubject";
|
||||
import { i18nHelper } from "lang/helper";
|
||||
import { log } from "utils/logutil";
|
||||
import { log } from "utils/Logutil";
|
||||
|
||||
/**
|
||||
* 默认的处理器
|
||||
*/
|
||||
export default class DoubanOtherLoadHandler extends DoubanAbstractLoadHandler<DoubanSubject> {
|
||||
parseText(template: string, arraySpilt: string, extract: DoubanSubject): string {
|
||||
parseText(extract: DoubanSubject, settings:DoubanPluginSettings): string {
|
||||
log.warn(i18nHelper.getMessage('current version not support type'));
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import { DoubanPluginSettings } from "douban/Douban";
|
||||
import DoubanSubject from "douban/model/DoubanSubject";
|
||||
import { Editor } from "obsidian";
|
||||
|
||||
export default interface DoubanSubjectLoadHandler<T extends DoubanSubject> {
|
||||
|
||||
parseText(template: string, arraySpilt:string, extract: DoubanSubject): string;
|
||||
parseText(extract: T, settings:DoubanPluginSettings): string;
|
||||
|
||||
support(extract:DoubanSubject):boolean;
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import DoubanSubject from "./DoubanSubject";
|
||||
import {AggregateRating, Person, WithContext} from 'schema-dts';
|
||||
|
||||
import DoubanSubject from "./DoubanSubject";
|
||||
|
||||
export default class DoubanMovieSubject extends DoubanSubject {
|
||||
director:Person[];
|
||||
author:Person[];
|
||||
actor:Person[];
|
||||
aggregateRating:AggregateRating;
|
||||
datePublished:string;
|
||||
datePublished:Date;
|
||||
image:string
|
||||
}
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import DoubanSearchResultSubject from "douban/model/DoubanSearchResultSubject";
|
||||
import DoubanPlugin from "main";
|
||||
import { FuzzySuggestModal,App, Editor } from "obsidian";
|
||||
import { log } from "utils/logutil";
|
||||
import { App, Editor, FuzzySuggestModal } from "obsidian";
|
||||
|
||||
import DoubanPlugin from "main";
|
||||
import DoubanSearchResultSubject from "douban/model/DoubanSearchResultSubject";
|
||||
import { log } from "utils/Logutil";
|
||||
|
||||
export {DoubanFuzzySuggester}
|
||||
|
||||
@ -19,13 +19,6 @@ class DoubanFuzzySuggester extends FuzzySuggestModal<DoubanSearchResultSubject>
|
||||
this.plugin = plugin;
|
||||
this.setPlaceholder("Choose an item...");
|
||||
|
||||
// this.inputEl.addEventListener("keydown", (event) => {
|
||||
// if (event.key === "Enter") {
|
||||
// log.info("enter")
|
||||
// this.reloadSearch();
|
||||
// }
|
||||
// })
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -40,7 +33,6 @@ class DoubanFuzzySuggester extends FuzzySuggestModal<DoubanSearchResultSubject>
|
||||
}
|
||||
|
||||
onChooseItem(item: DoubanSearchResultSubject, evt: MouseEvent | KeyboardEvent): void {
|
||||
log.warn(`choose itme ${JSON.stringify(item)}`);
|
||||
this.plugin.doubanEtractHandler.handle(item, this.editor);
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { App, Editor, Modal, TextComponent } from "obsidian";
|
||||
import { log } from "utils/logutil";
|
||||
|
||||
import DoubanPlugin from "../../main";
|
||||
import { i18nHelper } from "lang/helper";
|
||||
import { log } from "utils/Logutil";
|
||||
|
||||
export class DoubanSearchModal extends Modal {
|
||||
searchTerm: string;
|
||||
@ -16,16 +18,18 @@ export class DoubanSearchModal extends Modal {
|
||||
onOpen() {
|
||||
let { contentEl } = this;
|
||||
|
||||
contentEl.createEl("h2", { text: "Enter Search Term:" });
|
||||
contentEl.createEl("h2", { text: i18nHelper.getMessage('Enter Search Term:') });
|
||||
|
||||
const inputs = contentEl.createDiv("inputs");
|
||||
const searchInput = new TextComponent(inputs).onChange((searchTerm) => {
|
||||
this.searchTerm = searchTerm;
|
||||
});
|
||||
searchInput.inputEl.addClass("search_input");
|
||||
|
||||
searchInput.inputEl.focus();
|
||||
searchInput.inputEl.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Enter") {
|
||||
this.search();
|
||||
this.close();
|
||||
}
|
||||
});
|
||||
|
||||
@ -33,26 +37,20 @@ export class DoubanSearchModal extends Modal {
|
||||
|
||||
const controls = contentEl.createDiv("controls");
|
||||
const searchButton = controls.createEl("button", {
|
||||
text: "Search",
|
||||
text: i18nHelper.getMessage('Search'),
|
||||
cls: "mod-cta",
|
||||
attr: {
|
||||
autofocus: true,
|
||||
},
|
||||
});
|
||||
searchButton.addClass("search_button");
|
||||
|
||||
searchButton.addEventListener("click", this.close.bind(this));
|
||||
const cancelButton = controls.createEl("button", { text: "Cancel" });
|
||||
const cancelButton = controls.createEl("button", { text: i18nHelper.getMessage('Cancel') });
|
||||
cancelButton.addEventListener("click", this.close.bind(this));
|
||||
}
|
||||
async search() {
|
||||
let { contentEl } = this;
|
||||
contentEl.empty();
|
||||
if (this.searchTerm) {
|
||||
this.close();
|
||||
await this.plugin.search(this.searchTerm, this.editor);
|
||||
cancelButton.addClass("search_button");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
async onClose() {
|
||||
@ -60,7 +58,7 @@ export class DoubanSearchModal extends Modal {
|
||||
|
||||
contentEl.empty();
|
||||
if (this.searchTerm) {
|
||||
// await this.plugin.pasteIntoEditor(this.editor, this.searchTerm);
|
||||
await this.plugin.search(this.searchTerm, this.editor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import cheerio from 'cheerio';
|
||||
import { doubanHeadrs, DoubanPluginSettings } from 'douban/Douban';
|
||||
import { DoubanPluginSettings, doubanHeadrs } from 'douban/Douban';
|
||||
import { get, readStream } from 'tiny-network';
|
||||
import { ensureStatusCode } from 'douban/ResponseHandle';
|
||||
import { log } from 'utils/logutil';
|
||||
|
||||
import DoubanSearchResultSubject from 'douban/model/DoubanSearchResultSubject';
|
||||
import SearchParserHandler from './SearchParser';
|
||||
import cheerio from 'cheerio';
|
||||
import { ensureStatusCode } from 'douban/ResponseHandle';
|
||||
import { log } from 'utils/Logutil';
|
||||
|
||||
export default class Searcher {
|
||||
static search(searchItem:string, doubanSettings:DoubanPluginSettings):Promise<DoubanSearchResultSubject[]> {
|
||||
@ -17,6 +18,7 @@ export default class Searcher {
|
||||
.then(ensureStatusCode(200))
|
||||
.then(readStream)
|
||||
.then(cheerio.load)
|
||||
.then(SearchParserHandler.parseSearch);
|
||||
.then(SearchParserHandler.parseSearch)
|
||||
.then(log.trace);
|
||||
};
|
||||
}
|
||||
|
||||
@ -2,7 +2,10 @@
|
||||
export default {
|
||||
//main.ts
|
||||
'search douban by current file name':'search douban by current file name',
|
||||
'search douban and input current file':'search douban and input current file',
|
||||
'search douban and import to current file':'search douban and import to current file',
|
||||
'Enter Search Term:':`Enter Search Term:`,
|
||||
'Search':`Search`,
|
||||
'Cancel':`Cancel`,
|
||||
//DoubanSettingTab
|
||||
'douban search url': `Douban Search Url`,
|
||||
'douban search url desc 1': `Douban search page request address. `,
|
||||
@ -30,5 +33,12 @@ export default {
|
||||
'Douban Request Headers':`Douban Request Headers`,
|
||||
'current version not support type': `This type of import is not supported temporarily, please go to github to submit issues for help`,
|
||||
'Douban': `Douban`,
|
||||
|
||||
'Person Name Language Mode':'Person Name Language Mode',
|
||||
'options:':"options:",
|
||||
'Chinese Name mode, only show Chinese name':'Chinese Name mode, person name only show Chinese name',
|
||||
'English Name mode, only show English name':'English Name mode, person name only show English name',
|
||||
'Chinese English Name mode, show Chinese English name both':'Chinese English Name mode, show Chinese and English name both',
|
||||
'Chinese Name': 'Chinese Name',
|
||||
'English Name': 'English Name',
|
||||
'Chinese And English Name': 'Chinese And English Name',
|
||||
}
|
||||
@ -1,8 +1,12 @@
|
||||
//简体中文
|
||||
export default {
|
||||
//main.ts
|
||||
'search in douban by current file name':'用当前文档名搜索豆瓣并写入当前文档',
|
||||
'search douban and input current file':'在豆瓣搜索并写入到当前文档',
|
||||
'search douban by current file name':'用当前文档名搜索豆瓣并写入当前文档',
|
||||
'search douban and import to current file':'在豆瓣搜索并写入到当前文档',
|
||||
'Enter Search Term:':`输入搜索内容:`,
|
||||
'Search':`搜索`,
|
||||
'Cancel':`取消`,
|
||||
|
||||
//DoubanSettingTab
|
||||
'douban search url': `豆瓣搜索地址`,
|
||||
'douban search url desc 1': `豆瓣搜索页面请求地址, 通常是网页搜索的地址. `,
|
||||
@ -33,5 +37,15 @@ export default {
|
||||
1. 访问http://www.douban.com
|
||||
2. 复制请求头,仅复制以下请求头 `,
|
||||
'current version not support type': `暂时不支持该类型导入,请至github提交issuess获取帮助`,
|
||||
'Douban': `豆瓣网`
|
||||
'Douban': `豆瓣网`,
|
||||
|
||||
'Person Name Language Mode':'人名显示模式',
|
||||
'options:':"可选项:",
|
||||
'Chinese Name mode, only show Chinese name':'中文名称模式, 人名只显示中文名',
|
||||
'English Name mode, only show English name':'英文名称模式, 人名只显示英文名',
|
||||
'Chinese English Name mode, show Chinese English name both':'中文和英文名称模式, 人名同时显示中文和英文名',
|
||||
'Chinese Name': '中文名',
|
||||
'English Name': '英文名',
|
||||
'Chinese And English Name': '中文名和英文名',
|
||||
|
||||
}
|
||||
11
main.ts
11
main.ts
@ -9,14 +9,17 @@ import { DoubanSettingTab } from "douban/DoubanSettingTab";
|
||||
import DoubanSubject from "douban/model/DoubanSubject";
|
||||
import Searcher from "douban/search/Search";
|
||||
import { i18nHelper } from './lang/helper';
|
||||
import { log } from "utils/Logutil";
|
||||
|
||||
export default class DoubanPlugin extends Plugin {
|
||||
public settings: DoubanPluginSettings;
|
||||
public doubanEtractHandler: DoubanEtractHandler;
|
||||
|
||||
async putToEditor(editor:Editor, extract:DoubanSubject) {
|
||||
var content:string = this.doubanEtractHandler.parseText(this.settings.movieTemplate,
|
||||
this.settings.arraySpilt, extract)
|
||||
if(!editor || !extract) {
|
||||
return;
|
||||
}
|
||||
var content:string = this.doubanEtractHandler.parseText(extract, this.settings)
|
||||
if(content) {
|
||||
editor.replaceSelection(content);
|
||||
}
|
||||
@ -24,7 +27,9 @@ export default class DoubanPlugin extends Plugin {
|
||||
|
||||
|
||||
async search(searchTerm:string, editor: Editor) {
|
||||
log.trace("[main] start search:" + searchTerm);
|
||||
const resultList = await Searcher.search(searchTerm, this.settings);
|
||||
log.trace("[main] complete search:" + searchTerm + ",\n result list:" + JSON.stringify(resultList));
|
||||
new DoubanFuzzySuggester(this, editor).showSearchList(resultList);
|
||||
}
|
||||
|
||||
@ -55,7 +60,7 @@ export default class DoubanPlugin extends Plugin {
|
||||
|
||||
this.addCommand({
|
||||
id: "search-douban-and-input-current-file",
|
||||
name: i18nHelper.getMessage("search douban and input current file"),
|
||||
name: i18nHelper.getMessage("search douban and import to current file"),
|
||||
editorCallback: (editor: Editor) =>
|
||||
this.geDoubanMovieTextForSearchTerm(editor),
|
||||
});
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
{
|
||||
"id": "obsidian-sample-plugin",
|
||||
"name": "Sample Plugin",
|
||||
"id": "obsidian-douban-plugin",
|
||||
"name": "Douban",
|
||||
"version": "1.0.1",
|
||||
"minAppVersion": "0.12.0",
|
||||
"description": "This is a sample plugin for Obsidian. This plugin demonstrates some of the capabilities of the Obsidian API.",
|
||||
"author": "Obsidian",
|
||||
"authorUrl": "https://obsidian.md",
|
||||
"description": "This is a plugin that can import movies , books or musics info data from Douban for Obsidian .",
|
||||
"author": "Wanxp",
|
||||
"authorUrl": "https://wanxuping.com",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
|
||||
14
styles.css
14
styles.css
@ -11,3 +11,17 @@
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.search_input {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
font-size: 14px;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.search_button {
|
||||
margin-top: 10px;
|
||||
margin-left: 10px;
|
||||
margin-right: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
@ -14,7 +14,8 @@
|
||||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7"
|
||||
"ES7",
|
||||
"ES2021.String"
|
||||
],
|
||||
"outDir": "dist",
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import * as https from 'https';
|
||||
|
||||
import { get } from 'tiny-network';
|
||||
import { log } from './logutil';
|
||||
import { log } from './Logutil';
|
||||
|
||||
export default class HttpUtil {
|
||||
|
||||
|
||||
25
utils/SchemaOrg.ts
Normal file
25
utils/SchemaOrg.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Person } from "schema-dts";
|
||||
|
||||
export default class SchemaOrg {
|
||||
public static getPersonName(p:Person):string {
|
||||
if(isString(p)) {
|
||||
return p;
|
||||
}else {
|
||||
let name: any = getProperty(p, 'name');
|
||||
return name + "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function isString(s:any): s is string {
|
||||
return typeof s === 'string';
|
||||
}
|
||||
|
||||
|
||||
function getProperty<T, K extends keyof T>(o: T, name: K): T[K] {
|
||||
return o[name];
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { Notice } from "obsidian";
|
||||
import SchemaOrg from "./SchemaOrg";
|
||||
|
||||
class Logger {
|
||||
|
||||
@ -13,9 +14,15 @@ class Logger {
|
||||
}
|
||||
|
||||
public info(e:any):any {
|
||||
console.log("Douban Plugin Info: " + e);
|
||||
console.log(`Douban Plugin info: ${typeof e == 'string' ? e : JSON.stringify(e)}`);
|
||||
return e;
|
||||
}
|
||||
|
||||
public trace(e:any):any {
|
||||
return e;
|
||||
// console.log(`Douban Plugin trace: ${typeof e == 'string' ? e : JSON.stringify(e)}`);
|
||||
// return e;
|
||||
}
|
||||
}
|
||||
|
||||
export const log:Logger = new Logger();
|
||||
Loading…
Reference in New Issue
Block a user