From 446a37e03ba85f53529ef3b9a4c8cda641f44b03 Mon Sep 17 00:00:00 2001 From: HughWan <977741432@qq.com> Date: Tue, 26 Dec 2023 15:18:11 +0800 Subject: [PATCH] add array display type fix write enter to editor when search item fix desc has "\" " error --- README.md | 64 +++--- doc/Obsidian-Douban-BlueTopaz.md | 100 ++++++++ src/org/wanxp/constant/Constsant.ts | 17 ++ src/org/wanxp/constant/DefaultSettings.ts | 11 + .../data/handler/DoubanAbstractLoadHandler.ts | 190 ++++++++-------- .../data/handler/DoubanBookLoadHandler.ts | 22 +- .../data/handler/DoubanGameLoadHandler.ts | 13 +- .../data/handler/DoubanMovieLoadHandler.ts | 44 ++-- .../data/handler/DoubanMusicLoadHandler.ts | 19 +- .../data/handler/DoubanNoteLoadHandler.ts | 28 +-- .../data/handler/DoubanOtherLoadHandler.ts | 4 +- .../data/handler/DoubanTeleplayLoadHandler.ts | 56 +++-- .../data/handler/DoubanTheaterLoadHandler.ts | 54 +++-- .../douban/data/model/DoubanBookSubject.ts | 22 +- .../wanxp/douban/data/model/DoubanSubject.ts | 19 ++ .../douban/data/model/UserStateSubject.ts | 8 + .../douban/data/search/DoubanSearchModal.ts | 31 ++- .../setting/ArrayDisplayTypeSettingsHelper.ts | 162 +++++++++++++ .../wanxp/douban/setting/DoubanSettingTab.ts | 12 +- .../douban/setting/OutputSettingsHelper.ts | 107 +-------- .../wanxp/douban/setting/SettingsManager.ts | 70 +++++- .../douban/setting/model/ArraySetting.ts | 22 ++ .../setting/model/DoubanPluginSetting.ts | 3 +- .../handler/DoubanPageBroadcastLoadHandler.ts | 2 +- src/org/wanxp/lang/locale/en.ts | 9 +- src/org/wanxp/lang/locale/zh-cn.ts | 12 +- src/org/wanxp/utils/StringUtil.ts | 13 +- src/org/wanxp/utils/TimeUtil.ts | 3 - src/org/wanxp/utils/VariableUtil.ts | 214 ++++++++++++++++++ src/org/wanxp/utils/YamlUtil.ts | 12 +- src/org/wanxp/utils/model/DataField.ts | 32 +++ src/org/wanxp/utils/model/FieldVariable.ts | 25 ++ 32 files changed, 1011 insertions(+), 389 deletions(-) create mode 100644 doc/Obsidian-Douban-BlueTopaz.md create mode 100644 src/org/wanxp/douban/setting/ArrayDisplayTypeSettingsHelper.ts create mode 100644 src/org/wanxp/douban/setting/model/ArraySetting.ts create mode 100644 src/org/wanxp/utils/VariableUtil.ts create mode 100644 src/org/wanxp/utils/model/DataField.ts create mode 100644 src/org/wanxp/utils/model/FieldVariable.ts diff --git a/README.md b/README.md index 13fdbf2..5ee783e 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ ## 效果 1. 结合Timeline插件 __构建个人观影时间线__,请参照[结合timeline插件实现时间线效果](./doc/Obsidian-Douban-TimeLine.md) -2. 结合主题 __构建类豆瓣网页效果__,请参照[结合Blue Topaz实现网页效果](./doc/Obsidian-Douban-TimeLine.md) +2. 结合主题 __构建类豆瓣网页效果__,请参照[结合Blue Topaz实现网页效果](./doc/Obsidian-Douban-BlueTopaz.md) ## 如何使用 @@ -62,38 +62,38 @@ ## 支持的字段 (若有缺少想导入的字段, 欢迎提issues反馈) -| 字段 | 电影 | 电视剧 | 书籍 | 音乐 | 日记 | 游戏 | * | -|------------------|-------------------|------------------|-------------------|----------------|----------------|---------------|-------| -| id | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | id | -| title | 电影名称 | 电视剧名称 | 书名 | 音乐名 | 日记标题 | 游戏名称 | 剧名 | -| type | 类型 | 类型 | 类型 | 类型 | 类型 | 类型 | 类型 | -| score | 评分 | 评分 | 评分 | 评分 | 评分 | 评分 | 评分 | -| image | 封面 | 封面 | 封面 | 封面 | 图片 | 封面 | 封面 | -| imageData.url | 封面url | 封面url | 封面url | 封面url | 封面url | 封面url | 封面url | -| url | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | - | -| desc | 简介 | 简介 | 内容简介 | 简介 | 简介 | 简介 | - | -| publisher | - | - | 出版社 | 出版者 | 发布者 | 发行商 | - | -| datePublished | 上映日期 | 上映日期 | 出版年 | 发行时间 | 发布时间 | 发行日期 | - | -| yearPublished | 上映年份 | 上映年份 | 出版年份 | 发行年份 | 发布年份 | 发行年份 | - | -| genre | 类型 | 类型 | - | 流派 | - | 类型 | - | -| currentDate | 今日日期 | 今日日期 | 今日日期 | 今日日期 | 今日日期 | 今日日期 | | -| currentTime | 当前时间 | 当前时间 | 当前时间 | 当前时间 | 当前时间 | 当前时间 | | -| myTags | 我标记的标签 | 我标记的标签 | 我标记的标签 | 我标记的标签 | - | 我标记的标签 | | -| myRating | 我的评分 | 我的评分 | 我的评分 | 我的评分 | - | 我的评分 | -| myState | 状态:想看/在看/看过 | 状态:想看/在看/看过 | 状态:想看/在看/看过 | 状态:想听/在听/听过 | - | 状态:想玩/在玩/玩过 | | -| myComment | 我的评语 | 我的评语 | 我的评语 | 我的评语 | - | 我的评语 | | -| myCollectionDate | 我标记的时间 | 我标记的时间 | 我标记的时间 | 我标记的时间 | - | 我标记的时间 | | -| 扩展1 | director:导演 | director:导演 | author:原作者 | actor: 表演者 | author:作者 | aliases:别名 | | -| 扩展2 | author:编剧 | author:编剧 | translator:译者 | albumType:专辑类型 | authorUrl:作者网址 | developer:开发商 | | -| 扩展3 | actor:主演 | actor:主演 | isbn:isbn | medium:介质 | content:日记内容 | platform:平台 | | +| 字段 | 电影 | 电视剧 | 书籍 | 音乐 | 日记 | 游戏 | 人物 | +|------------------|-------------------|-------------------|-------------------|----------------|----------------|---------------|-------| +| id | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | 豆瓣ID | id | +| title | 电影名称 | 电视剧名称 | 书名 | 音乐名 | 日记标题 | 游戏名称 | 姓名 | +| type | 类型 | 类型 | 类型 | 类型 | 类型 | 类型 | 类型 | +| score | 评分 | 评分 | 评分 | 评分 | 评分 | 评分 | | +| image | 封面 | 封面 | 封面 | 封面 | 图片 | 封面 | 照片 | +| imageData.url | 封面url | 封面url | 封面url | 封面url | 封面url | 封面url | 照片url | +| url | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | 豆瓣网址 | +| desc | 简介 | 简介 | 内容简介 | 简介 | 简介 | 简介 | 简介 | +| publisher | - | - | 出版社 | 出版者 | 发布者 | 发行商 | - | +| datePublished | 上映日期 | 上映日期 | 出版年 | 发行时间 | 发布时间 | 发行日期 | - | +| yearPublished | 上映年份 | 上映年份 | 出版年份 | 发行年份 | 发布年份 | 发行年份 | - | +| genre | 类型 | 类型 | - | 流派 | - | 类型 | - | +| currentDate | 今日日期 | 今日日期 | 今日日期 | 今日日期 | 今日日期 | 今日日期 | | +| currentTime | 当前时间 | 当前时间 | 当前时间 | 当前时间 | 当前时间 | 当前时间 | | +| myTags | 我标记的标签 | 我标记的标签 | 我标记的标签 | 我标记的标签 | - | 我标记的标签 | | +| myRating | 我的评分 | 我的评分 | 我的评分 | 我的评分 | - | 我的评分 | +| myState | 状态:想看/在看/看过 | 状态:想看/在看/看过 | 状态:想看/在看/看过 | 状态:想听/在听/听过 | - | 状态:想玩/在玩/玩过 | | +| myComment | 我的评语 | 我的评语 | 我的评语 | 我的评语 | - | 我的评语 | | +| myCollectionDate | 我标记的时间 | 我标记的时间 | 我标记的时间 | 我标记的时间 | - | 我标记的时间 | | +| 扩展1 | director:导演 | director:导演 | author:原作者 | actor: 表演者 | author:作者 | aliases:别名 | | +| 扩展2 | author:编剧 | author:编剧 | translator:译者 | albumType:专辑类型 | authorUrl:作者网址 | developer:开发商 | | +| 扩展3 | actor:主演 | actor:主演 | isbn:isbn | medium:介质 | content:日记内容 | platform:平台 | | | 扩展4 | originalTitle:原作名 | originalTitle:原作名 | originalTitle:原作名 | records:唱片数 | | | | -| 扩展5 | country:国家 | country:国家 | subTitle:副标题 | barcode:条形码 | | | | -| 扩展6 | language:语言 | language:语言 | totalPage:页数 | | | | | -| 扩展7 | time:片长 | time:片长 | series:丛书 | | | | | -| 扩展8 | aliases:又名 | aliases:又名 | menu:目录 | | | | | -| 扩展9 | IMDb | IMDb | price:定价 | | | | | -| 扩展7 | | episode:集数 | binding:装帧 | | | | | -| 扩展8 | | | producer: 出品方 | | | | | +| 扩展5 | country:国家 | country:国家 | subTitle:副标题 | barcode:条形码 | | | | +| 扩展6 | language:语言 | language:语言 | totalPage:页数 | | | | | +| 扩展7 | time:片长 | time:片长 | series:丛书 | | | | | +| 扩展8 | aliases:又名 | aliases:又名 | menu:目录 | | | | | +| 扩展9 | IMDb | IMDb | price:定价 | | | | | +| 扩展7 | | episode:集数 | binding:装帧 | | | | | +| 扩展8 | | | producer: 出品方 | | | | | - 注: myTags, myRating, myState, myComment, myCollectionDate 参数均为在插件中登录后可用 diff --git a/doc/Obsidian-Douban-BlueTopaz.md b/doc/Obsidian-Douban-BlueTopaz.md new file mode 100644 index 0000000..e27c95c --- /dev/null +++ b/doc/Obsidian-Douban-BlueTopaz.md @@ -0,0 +1,100 @@ +## 效果如下 +![](./background.png) +## 适用人群 +1. 在豆瓣有标记/评论/评分的习惯的人 +比如看完电影,会在豆瓣进行评分或评论。或者阅读完的书籍,进行评分或评论。支持包含:电影、书籍、电视剧、音乐、游戏 +## 实现步骤 +1. 安装[Blue Topaz](https://github.com/PKM-er/Blue-Topaz_Obsidian-css)插件, 可在Obsidian主题搜索中找到 `Blue Topaz` +2. 安装[Obsidian-Douban](https://github.com/Wanxp/obsidian-douban)插件(本插件) +3. 在Obsidian-Douban插件配置中登录Douban +4. 配置需要的模板, 在模板最后增加以下内容,如下所示 + +````markdown +--- +# {{title}} +
{{originalTitle}}
+
⭐⭐⭐⭐⭐
+ +--- + +> [!bookinfo|noicon]+ 🗒️ **简介** +> ![bookcover|250]( {{image}}) +> + +| 属性 | 内容 | +|:-------- |:------------------------ | +| 笔记 | [[摘录:{{title}}]] | +| 作者 | [[{{author}}]] | +| 译者 | [[{{translator(ArrayType1)}}]] | +| 来源 | [ {{title}} ]( {{url}} ) | +| 网站评分 | {{score}} | +| 出版发行 | {{publisher}} | +| 原作名 | {{originalTitle}} | +| 出版年份 | {{yearPublished}} | + +> [!note]- 书籍简介\ +> {{desc}} + +--- + +### 评论 + +{{myComment}} +```` +5. 同时,在电影/书籍... 模板中的 **最后增加** timeline插件需要的html标签如下: + +```html +{{myComment}} |简介: {{desc}} + +``` +6. 选择上述模板导入 电影/书籍...,操作方式是打开obsidian命令窗口,输入豆瓣,找到导入功能,在导入界面配置 选择模板进行导入 +7. 导入需要一定时间,每条内容导入需要15-30s左右,所有有导入完成后会有导入汇总 +8. 导入完成后,新建一个笔记,笔记内容加入timeline的代码块,代码块的内容就是你上面指定的tags的内容,如`我看过的电影`,代码块如下: +````markdown +```timeline +我看过的电影 +``` +```` +9. 预览这个笔记就能看出已经出现了时间线 +## 模板参考 +### 电影 +````markdown +--- +doubanId: {{id}} +title: {{title}} +type: {{type}} +score: {{score}} +myRate: {{myRate}} +originalTitle: {{originalTitle}} +genre: {{genre}} +datePublished: {{datePublished}} +director: {{director}} +actor: {{actor}} +author: {{author}} +tags: {{type}}, 我看过的电影, {{myTags}} +state: {{myState}} +url: {{url}} +coverUrl: {{imageData.url}} +createTime: {{currentDate}} {{currentTime}} +collectionDate: {{myCollectionDate}} +desc: {{desc}} +--- + +![image]({{image}}) + +Comment: +--- +{{myComment}} + + +{{myComment}} |简介: {{desc}} + +```` +### 书籍、电视剧、音乐、游戏 +请参照电影模板 +## 更多 +参照讨论 [结合timeline插件的妙用](https://github.com/Wanxp/obsidian-douban/issues/19#issuecomment-1428307130) diff --git a/src/org/wanxp/constant/Constsant.ts b/src/org/wanxp/constant/Constsant.ts index c7a76c8..578183d 100644 --- a/src/org/wanxp/constant/Constsant.ts +++ b/src/org/wanxp/constant/Constsant.ts @@ -395,5 +395,22 @@ export enum SubjectHandledStatus { syncTypeDiffAbort = 'syncTypeDiffAbort', } +export const DEFAULT_SETTINGS_ARRAY_INPUT_SIZE = 2; +export enum DataValueType { + date, + number, + string, + person, + array, + url, + path, +} + +export enum DataTargetType { + fileName, + yaml, + content, +} + diff --git a/src/org/wanxp/constant/DefaultSettings.ts b/src/org/wanxp/constant/DefaultSettings.ts index a47e528..08a16fc 100644 --- a/src/org/wanxp/constant/DefaultSettings.ts +++ b/src/org/wanxp/constant/DefaultSettings.ts @@ -2,6 +2,17 @@ import {DoubanPluginSetting} from "../douban/setting/model/DoubanPluginSetting"; import {PersonNameMode, SupportType} from "./Constsant"; export const DEFAULT_SETTINGS: DoubanPluginSetting = { + arraySettings: [ + { + "arrayName": "ArrayType1", + "arrayStart": "", + "arrayElementStart": "[[", + "arraySpiltV2": ",", + "arrayElementEnd": "]]", + "arrayEnd": "", + "index": 1 + } + ], onlineSettingsFileName: "obsidian_douban_plugin_online_settings.json", onlineSettingsGistId: "35693f9ece9bd6abba98f94e81afde19", movieTemplateFile: ``, diff --git a/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts index d8cb279..6520938 100644 --- a/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts +++ b/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts @@ -1,14 +1,16 @@ import DoubanPlugin from "../../../main"; -import DoubanSubject, {DoubanParameter} from '../model/DoubanSubject'; +import DoubanSubject, {DoubanParameterName} from '../model/DoubanSubject'; import DoubanSubjectLoadHandler from "./DoubanSubjectLoadHandler"; -import {moment, request, RequestUrlParam, TFile} from "obsidian"; +import {moment, TFile} from "obsidian"; import {i18nHelper} from 'src/org/wanxp/lang/helper'; import {log} from "src/org/wanxp/utils/Logutil"; import {CheerioAPI, load} from "cheerio"; import YamlUtil from "../../../utils/YamlUtil"; import { BasicConst, - PersonNameMode, PropertyName, + DataValueType, + PersonNameMode, + PropertyName, SearchHandleMode, SupportType, TemplateKey, @@ -19,18 +21,17 @@ import HandleResult from "../model/HandleResult"; import {getDefaultTemplateContent} from "../../../constant/DefaultTemplateContent"; import StringUtil from "../../../utils/StringUtil"; import {DEFAULT_SETTINGS} from "../../../constant/DefaultSettings"; -import {DoubanUserParameter, UserStateSubject} from "../model/UserStateSubject"; +import {DoubanUserParameter, DoubanUserParameterName, UserStateSubject} from "../model/UserStateSubject"; import { DoubanSubjectState, DoubanSubjectStateRecords, DoubanSubjectStateRecords_KEY_WORD_TYPE } from "../../../constant/DoubanUserState"; -import DoubanLoginModel from "../../component/DoubanLoginModel"; -import DoubanHumanCheckModel from "../../component/DoubanHumanCheckModel"; -import DoubanMovieSubject from "../model/DoubanMovieSubject"; import {Person} from "schema-dts"; import HttpUtil from "../../../utils/HttpUtil"; import HtmlUtil from "../../../utils/HtmlUtil"; +import {VariableUtil} from "../../../utils/VariableUtil"; +import {DataField} from "../../../utils/model/DataField"; export default abstract class DoubanAbstractLoadHandler implements DoubanSubjectLoadHandler { @@ -46,10 +47,10 @@ export default abstract class DoubanAbstractLoadHandler await this.saveImage(extract, context); const frontMatterStart: number = template.indexOf(BasicConst.YAML_FRONT_MATTER_SYMBOL, 0); const frontMatterEnd: number = template.indexOf(BasicConst.YAML_FRONT_MATTER_SYMBOL, frontMatterStart + 1); - let frontMatter: string = ''; - let frontMatterBefore: string = ''; - let frontMatterAfter: string = ''; - let result: string = ''; + let frontMatter = ''; + let frontMatterBefore = ''; + let frontMatterAfter = ''; + let result = ''; if (frontMatterStart > -1 && frontMatterEnd > -1) { frontMatterBefore = template.substring(0, frontMatterStart); frontMatter = template.substring(frontMatterStart, frontMatterEnd + 3); @@ -67,7 +68,7 @@ export default abstract class DoubanAbstractLoadHandler } else { result = this.parsePartText(template, extract, context); } - let fileName: string = ''; + let fileName = ''; if (SearchHandleMode.FOR_CREATE == context.mode) { fileName = this.parsePartText(this.getFileName(context), extract, context); } @@ -99,48 +100,11 @@ export default abstract class DoubanAbstractLoadHandler return result; } - /** - * 处理内容数组 - * @param array - * @param settings - * @param textMode - */ - handleContentArray(array: any[], context: HandleContext, textMode: TemplateTextMode): string { - let result; - switch (textMode) { - // case TemplateTextMode.YAML: - // result = array.map(YamlUtil.handleText).join(', '); - // break; - default: - result = this.handleArray(array, context); - } - return result; - } - /** - * 处理特殊内容 - * @param value - * @param textMode - * @param settings - */ - handleSpecialContent(value: any, textMode: TemplateTextMode = TemplateTextMode.NORMAL, context: HandleContext = null): string { - let result; - if (!value) { - return ''; - } - if (value instanceof Array) { - result = this.handleContentArray(value, context, textMode); - } else if (value instanceof Number) { - result = value.toString(); - } else { - result = this.handleSpecialText(value, textMode); - } - return result; - } abstract getSupportType(): SupportType; - abstract parseText(beforeContent: string, extract: T, context: HandleContext, textMode: TemplateTextMode): string; + abstract parseVariable(beforeContent: string, variableMap:Map, extract: T, context: HandleContext, textMode: TemplateTextMode): void; abstract support(extract: DoubanSubject): boolean; @@ -184,9 +148,9 @@ export default abstract class DoubanAbstractLoadHandler */ private getGuessType(data: CheerioAPI):SupportType { if (data) { - let text = data.html(); + const text = data.html(); if (text) { - for (let [key, value] of DoubanSubjectStateRecords_KEY_WORD_TYPE) { + for (const [key, value] of DoubanSubjectStateRecords_KEY_WORD_TYPE) { if (text.indexOf(key) >= 0) { return value; } @@ -243,7 +207,7 @@ export default abstract class DoubanAbstractLoadHandler let regValue: RegExpExecArray; switch (personNameMode) { case PersonNameMode.CH_NAME: - regValue = /[\u4e00-\u9fa50-9\. ·\:\u3002|\uff1f|\uff01|\uff0c|\u3001|\uff1b|\uff1a|\u201c|\u201d|\u2018|\u2019|\uff08|\uff09|\u300a|\u300b|\u3008|\u3009|\u3010|\u3011|\u300e|\u300f|\u300c|\u300d|\ufe43|\ufe44|\u3014|\u3015|\u2026|\u2014|\uff5e|\ufe4f|\uffe5\(\)]{2,}/g.exec(name); + regValue = /[\u4e00-\u9fa50-9. ·:\u3002|\uff1f|\uff01|\uff0c|\u3001|\uff1b|\uff1a|\u201c|\u201d|\u2018|\u2019|\uff08|\uff09|\u300a|\u300b|\u3008|\u3009|\u3010|\u3011|\u300e|\u300f|\u300c|\u300d|\ufe43|\ufe44|\u3014|\u3015|\u2026|\u2014|\uff5e|\ufe4f|\uffe5()]{2,}/g.exec(name); resultName = regValue ? regValue[0] : name; break; case PersonNameMode.EN_NAME: @@ -294,35 +258,63 @@ export default abstract class DoubanAbstractLoadHandler s = s.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(//g, "\n"); return s; } private parsePartText(template: string, extract: T, context: HandleContext, textMode: TemplateTextMode = TemplateTextMode.NORMAL): string { - let resultContent = this.handleCustomVariable(template, context); - resultContent = resultContent.replaceAll(DoubanParameter.ID, extract.id) - .replaceAll(DoubanParameter.TITLE, this.handleSpecialContent(extract.title, textMode)) - .replaceAll(DoubanParameter.TYPE, extract.type) - .replaceAll(DoubanParameter.SCORE, this.handleSpecialContent(extract.score)) - .replaceAll(DoubanParameter.IMAGE, extract.image) - .replaceAll(DoubanParameter.IMAGE_URL, extract.imageUrl) - .replaceAll(DoubanParameter.URL, extract.url) - .replaceAll(DoubanParameter.DESC, this.handleSpecialContent(extract.desc, textMode)) - .replaceAll(DoubanParameter.PUBLISHER, extract.publisher) - .replaceAll(DoubanParameter.YEAR_PUBLISHED, extract.datePublished ? moment(extract.datePublished).format('yyyy') : '') - .replaceAll(DoubanParameter.DATE_PUBLISHED, extract.datePublished ? moment(extract.datePublished).format(context.settings.dateFormat) : '') - .replaceAll(DoubanParameter.TIME_PUBLISHED, extract.datePublished ? moment(extract.datePublished).format(context.settings.timeFormat) : '') - .replaceAll(DoubanParameter.CURRENT_DATE, moment(new Date()).format(context.settings.dateFormat)) - .replaceAll(DoubanParameter.CURRENT_TIME, moment(new Date()).format(context.settings.timeFormat)) - .replaceAll(DoubanParameter.GENRE, this.handleSpecialContent(extract.genre, textMode, context)) - ; - resultContent = this.parseUserInfo(resultContent, extract, context, textMode); - return this.parseText(resultContent, extract, context, textMode); + const variableMap:Map = new Map(); + for (const [key, value] of Object.entries(extract)) { + const type:DataValueType = VariableUtil.getType(value); + variableMap.set(key, new DataField(key, type, value, value)); + } + variableMap.set(DoubanParameterName.IMAGE_URL, new DataField( + DoubanParameterName.IMAGE_URL, + DataValueType.url, + extract.imageUrl, + extract.imageUrl + )); + variableMap.set(DoubanParameterName.YEAR_PUBLISHED, new DataField( + DoubanParameterName.YEAR_PUBLISHED, + DataValueType.date, + extract.datePublished, + extract.datePublished ? moment(extract.datePublished).format('yyyy') : '' + )); + variableMap.set(DoubanParameterName.DATE_PUBLISHED, new DataField( + DoubanParameterName.DATE_PUBLISHED, + DataValueType.date, + extract.datePublished, + extract.datePublished ? moment(extract.datePublished).format(context.settings.dateFormat) : '' + )); + variableMap.set(DoubanParameterName.TIME_PUBLISHED, new DataField( + DoubanParameterName.TIME_PUBLISHED, + DataValueType.date, + extract.datePublished, + extract.datePublished ? moment(extract.datePublished).format(context.settings.timeFormat) : '' + )); + const currentDate = new Date(); + variableMap.set(DoubanParameterName.CURRENT_DATE, new DataField( + DoubanParameterName.CURRENT_DATE, + DataValueType.date, + currentDate, + moment(currentDate).format(context.settings.dateFormat) + )); + variableMap.set(DoubanParameterName.CURRENT_TIME, new DataField( + DoubanParameterName.CURRENT_TIME, + DataValueType.date, + currentDate, + moment(currentDate).format(context.settings.timeFormat) + )); + this.parseUserInfo(template, variableMap, extract, context, textMode); + this.parseVariable(template, variableMap, extract, context, textMode); + this.handleCustomVariable(template, variableMap, context); + return VariableUtil.replace(variableMap, template, this.doubanPlugin.settingsManager); + } - private parseUserInfo(resultContent: string, extract: T, context: HandleContext, textMode: TemplateTextMode) { + private parseUserInfo(resultContent: string, variableMap:Map, extract: T, context: HandleContext, textMode: TemplateTextMode) { const userState = extract.userState; if ((resultContent.indexOf(DoubanUserParameter.MY_TAGS) >= 0 || resultContent.indexOf(DoubanUserParameter.MY_RATING) >= 0 || @@ -341,11 +333,23 @@ export default abstract class DoubanAbstractLoadHandler }else { tags = [extract.type]; } - return resultContent.replaceAll(DoubanUserParameter.MY_TAGS, this.handleSpecialContent(tags, textMode, context)) - .replaceAll(DoubanUserParameter.MY_RATING, this.handleSpecialContent(userState.rate, textMode)) - .replaceAll(DoubanUserParameter.MY_STATE, this.getUserStateName(userState.state)) - .replaceAll(DoubanUserParameter.MY_COMMENT, this.handleSpecialContent(userState.comment, textMode)) - .replaceAll(DoubanUserParameter.MY_COLLECTION_DATE, userState.collectionDate?moment(userState.collectionDate).format(context.settings.dateFormat): '') + Object.entries(userState).forEach(([key, value]) => { + variableMap.set(key, value); + }); + variableMap.set(DoubanUserParameterName.MY_TAGS, new DataField(DoubanUserParameterName.MY_TAGS, DataValueType.array, tags, tags)); + variableMap.set(DoubanUserParameterName.MY_STATE, new DataField( + DoubanUserParameterName.MY_STATE, + DataValueType.string, + userState, + this.getUserStateName(userState.state) + )); + + variableMap.set(DoubanUserParameterName.MY_COLLECTION_DATE, new DataField( + DoubanUserParameterName.MY_COLLECTION_DATE, + DataValueType.date, + userState.collectionDate, + userState.collectionDate ? moment(userState.collectionDate).format(context.settings.dateFormat) : '' + )); } /** @@ -354,19 +358,24 @@ export default abstract class DoubanAbstractLoadHandler * @param context * @private */ - private handleCustomVariable(template: string, context: HandleContext): string { - let customProperties = context.settings.customProperties; - let resultContent = template; + private handleCustomVariable(template: string, variableMap:Map, context: HandleContext): void { + const customProperties = context.settings.customProperties; if (!customProperties) { - return resultContent; + return ; } + const customPropertiesMap= new Map(); customProperties.filter(customProperty => customProperty.name && customProperty.field && (customProperty.field.toLowerCase() == SupportType.ALL || customProperty.field.toLowerCase() == this.getSupportType())).forEach(customProperty => { - resultContent = resultContent.replaceAll(`{{${customProperty.name}}}`, customProperty.value); + customPropertiesMap.set(customProperty.name, customProperty.value); }); - return resultContent; + customPropertiesMap.forEach((value, key) => { + variableMap.set(key, + new DataField( + key, DataValueType.string, value, + VariableUtil.replace(variableMap, value, this.doubanPlugin.settingsManager))); + }) } private getTemplateKey():TemplateKey { @@ -421,7 +430,7 @@ export default abstract class DoubanAbstractLoadHandler return getDefaultTemplateContent(tempKey, useUserState); } const defaultContent = getDefaultTemplateContent(tempKey, useUserState); - let firstLinkpathDest: TFile = this.doubanPlugin.app.metadataCache.getFirstLinkpathDest(templatePath, ''); + const firstLinkpathDest: TFile = this.doubanPlugin.app.metadataCache.getFirstLinkpathDest(templatePath, ''); if (!firstLinkpathDest) { return defaultContent; } else { @@ -465,7 +474,7 @@ export default abstract class DoubanAbstractLoadHandler if (!state) { return ''; } - let v = DoubanSubjectStateRecords[this.getSupportType()]; + const v = DoubanSubjectStateRecords[this.getSupportType()]; switch (state) { case DoubanSubjectState.wish: return v.wish; @@ -520,7 +529,7 @@ export default abstract class DoubanAbstractLoadHandler handlePersonNameByMeta(html: CheerioAPI, movie: DoubanSubject, context: HandleContext, metaProperty:string, objectProperty:string) { - let metaProperties: string[] = html(`head > meta[property='${metaProperty}']`).get() + const metaProperties: string[] = html(`head > meta[property='${metaProperty}']`).get() .map((e) => { return html(e).attr('content'); }); @@ -544,10 +553,7 @@ export default abstract class DoubanAbstractLoadHandler return HtmlUtil.getHtmlText(html, this.doubanPlugin.settingsManager.getSelector(this.getSupportType(), name)); } - protected handleArray(arr: string[], context: HandleContext): string { - const {settings} = context; - return StringUtil.handleArray(arr, settings); - } + } diff --git a/src/org/wanxp/douban/data/handler/DoubanBookLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanBookLoadHandler.ts index 983fdf5..0ce0808 100644 --- a/src/org/wanxp/douban/data/handler/DoubanBookLoadHandler.ts +++ b/src/org/wanxp/douban/data/handler/DoubanBookLoadHandler.ts @@ -3,11 +3,12 @@ import DoubanAbstractLoadHandler from "./DoubanAbstractLoadHandler"; import DoubanBookSubject, {DoubanBookParameter} from "../model/DoubanBookSubject"; import DoubanPlugin from "../../../main"; import DoubanSubject from "../model/DoubanSubject"; -import {PropertyName, SupportType, TemplateTextMode} from "../../../constant/Constsant"; +import {DataValueType, PropertyName, SupportType, TemplateTextMode} from "../../../constant/Constsant"; import HandleContext from "../model/HandleContext"; import StringUtil from "../../../utils/StringUtil"; import {UserStateSubject} from "../model/UserStateSubject"; import {moment} from "obsidian"; +import {DataField} from "../../../utils/model/DataField"; export default class DoubanBookLoadHandler extends DoubanAbstractLoadHandler { @@ -27,22 +28,9 @@ export default class DoubanBookLoadHandler extends DoubanAbstractLoadHandler, extract: DoubanBookSubject, context: HandleContext, textMode: TemplateTextMode): void { + variableMap.set(DoubanBookParameter.author, new DataField(DoubanBookParameter.author, + DataValueType.array, extract.author, extract.author.map(this.handleSpecialAuthorName))); } support(extract: DoubanSubject): boolean { diff --git a/src/org/wanxp/douban/data/handler/DoubanGameLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanGameLoadHandler.ts index daf909c..bb770b2 100644 --- a/src/org/wanxp/douban/data/handler/DoubanGameLoadHandler.ts +++ b/src/org/wanxp/douban/data/handler/DoubanGameLoadHandler.ts @@ -3,11 +3,12 @@ import DoubanAbstractLoadHandler from "./DoubanAbstractLoadHandler"; import DoubanPlugin from "../../../main"; import DoubanSubject from '../model/DoubanSubject'; import DoubanGameSubject from '../model/DoubanGameSubject'; -import StringUtil from "../../../utils/StringUtil"; import HandleContext from "../model/HandleContext"; -import {PersonNameMode, SupportType, TemplateKey} from "../../../constant/Constsant"; +import {DataValueType, PersonNameMode, SupportType} from "../../../constant/Constsant"; import {UserStateSubject} from "../model/UserStateSubject"; import {moment} from "obsidian"; +import {TITLE_ALIASES_SPECIAL_CHAR_REG_G} from "../../../utils/YamlUtil"; +import {DataField} from "../../../utils/model/DataField"; export default class DoubanGameLoadHandler extends DoubanAbstractLoadHandler { @@ -26,12 +27,8 @@ export default class DoubanGameLoadHandler extends DoubanAbstractLoadHandler, extract: DoubanGameSubject, context: HandleContext): void { + variableMap.set("aliases", new DataField("aliases", DataValueType.array, extract.aliases, extract.aliases.map(a=>a.replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')))); } support(extract: DoubanSubject): boolean { diff --git a/src/org/wanxp/douban/data/handler/DoubanMovieLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanMovieLoadHandler.ts index e4d864c..e7f8947 100644 --- a/src/org/wanxp/douban/data/handler/DoubanMovieLoadHandler.ts +++ b/src/org/wanxp/douban/data/handler/DoubanMovieLoadHandler.ts @@ -6,10 +6,11 @@ import DoubanSubject from '../model/DoubanSubject'; import DoubanMovieSubject from '../model/DoubanMovieSubject'; import StringUtil from "../../../utils/StringUtil"; import HandleContext from "../model/HandleContext"; -import {PersonNameMode, PropertyName, SupportType, TemplateKey} from "../../../constant/Constsant"; +import {DataValueType, PersonNameMode, PropertyName, SupportType, TemplateKey} from "../../../constant/Constsant"; import {UserStateSubject} from "../model/UserStateSubject"; import {moment} from "obsidian"; import YamlUtil, {SPECIAL_CHAR_REG, TITLE_ALIASES_SPECIAL_CHAR_REG_G} from "../../../utils/YamlUtil"; +import {DataField} from "../../../utils/model/DataField"; export default class DoubanMovieLoadHandler extends DoubanAbstractLoadHandler { @@ -29,19 +30,34 @@ export default class DoubanMovieLoadHandler extends DoubanAbstractLoadHandler c), context)) - .replaceAll("{{actor}}", this.handleArray( extract.actor.map(SchemaOrg.getPersonName).filter(c => c), context)) - .replaceAll("{{author}}", this.handleArray(extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c), context)) - .replaceAll("{{aliases}}", this.handleArray(extract.aliases.map(a=>a.replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')), context)) - .replaceAll("{{country}}", this.handleArray( extract.country, context)) - .replaceAll("{{language}}",this.handleArray( extract.language, context)) - .replaceAll("{{IMDb}}", extract.IMDb ??"") - .replaceAll("{{time}}", extract.time ??"") - ; + parseVariable(beforeContent: string, variableMap:Map, extract: DoubanMovieSubject, context: HandleContext): void { + variableMap.set("director", new DataField( + "director", + DataValueType.array, + extract.director, + extract.director.map(SchemaOrg.getPersonName).filter(c => c) + )); + + variableMap.set("actor", new DataField( + "actor", + DataValueType.array, + extract.actor, + extract.actor.map(SchemaOrg.getPersonName).filter(c => c) + )); + + variableMap.set("author", new DataField( + "author", + DataValueType.array, + extract.author, + extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c) + )); + + variableMap.set("aliases", new DataField( + "aliases", + DataValueType.array, + extract.aliases, + extract.aliases.map(a => a.replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')) + )); } support(extract: DoubanSubject): boolean { diff --git a/src/org/wanxp/douban/data/handler/DoubanMusicLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanMusicLoadHandler.ts index cdacc31..f6750ff 100644 --- a/src/org/wanxp/douban/data/handler/DoubanMusicLoadHandler.ts +++ b/src/org/wanxp/douban/data/handler/DoubanMusicLoadHandler.ts @@ -4,9 +4,10 @@ import DoubanMusicSubject from '../model/DoubanMusicSubject'; import DoubanPlugin from "../../../main"; import DoubanSubject from '../model/DoubanSubject'; import HandleContext from "../model/HandleContext"; -import {SupportType, TemplateKey} from "../../../constant/Constsant"; +import {SupportType} from "../../../constant/Constsant"; import {UserStateSubject} from "../model/UserStateSubject"; import {moment} from "obsidian"; +import {DataField} from "../../../utils/model/DataField"; export default class DoubanMusicLoadHandler extends DoubanAbstractLoadHandler { @@ -26,15 +27,7 @@ export default class DoubanMusicLoadHandler extends DoubanAbstractLoadHandler, extract: DoubanMusicSubject, context: HandleContext): void { } support(extract: DoubanSubject): boolean { @@ -83,7 +76,7 @@ export default class DoubanMusicLoadHandler extends DoubanAbstractLoadHandler= 0) { // value = html(info.next.next).text().trim(); - let vas: string[] = key.split("\n \n "); + const vas: string[] = key.split("\n \n "); value = vas && vas.length > 1 ? vas[1] : ""; key = vas && vas.length > 0 ? vas[0] : ""; } else { @@ -92,8 +85,8 @@ export default class DoubanMusicLoadHandler extends DoubanAbstractLoadHandler { @@ -26,12 +27,7 @@ export default class DoubanNoteLoadHandler extends DoubanAbstractLoadHandler, extract: DoubanNoteSubject, context: HandleContext): void { } support(extract: DoubanSubject): boolean { @@ -43,16 +39,16 @@ export default class DoubanNoteLoadHandler extends DoubanAbstractLoadHandler meta[property= 'og:title']").get(0)).attr("content"); - let desc = html(html("head > meta[property= 'og:description']").get(0)).attr("content"); - let url = html(html("head > meta[property= 'og:url']").get(0)).attr("content"); - let image = html(html("head > meta[property= 'og:image']").get(0)).attr("content"); - let type = html(html("head > meta[property= 'og:type']").get(0)).attr("content"); - let authorA = html(html("a.note-author").get(0)); - let timePublished = html(html(".pub-date").get(0)).text(); - let content = html(html(".note").get(1)); - let idPattern = /(\d){5,10}/g; - let id = idPattern.exec(url); + const title = html(html("head > meta[property= 'og:title']").get(0)).attr("content"); + const desc = html(html("head > meta[property= 'og:description']").get(0)).attr("content"); + const url = html(html("head > meta[property= 'og:url']").get(0)).attr("content"); + const image = html(html("head > meta[property= 'og:image']").get(0)).attr("content"); + const type = html(html("head > meta[property= 'og:type']").get(0)).attr("content"); + const authorA = html(html("a.note-author").get(0)); + const timePublished = html(html(".pub-date").get(0)).text(); + const content = html(html(".note").get(1)); + const idPattern = /(\d){5,10}/g; + const id = idPattern.exec(url); const result: DoubanNoteSubject = { image: image, diff --git a/src/org/wanxp/douban/data/handler/DoubanOtherLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanOtherLoadHandler.ts index 379c61f..9bdc98e 100644 --- a/src/org/wanxp/douban/data/handler/DoubanOtherLoadHandler.ts +++ b/src/org/wanxp/douban/data/handler/DoubanOtherLoadHandler.ts @@ -6,6 +6,7 @@ import {log} from "src/org/wanxp/utils/Logutil"; import HandleContext from "../model/HandleContext"; import {SupportType, TemplateKey} from "../../../constant/Constsant"; import {UserStateSubject} from "../model/UserStateSubject"; +import {DataField} from "../../../utils/model/DataField"; /** * 默认的处理器 @@ -15,9 +16,8 @@ export default class DoubanOtherLoadHandler extends DoubanAbstractLoadHandler, extract: DoubanSubject, context: HandleContext): void { log.warn(i18nHelper.getMessage('140101')); - return ""; } support(extract: DoubanSubject): boolean { diff --git a/src/org/wanxp/douban/data/handler/DoubanTeleplayLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanTeleplayLoadHandler.ts index 461888b..5cb6810 100644 --- a/src/org/wanxp/douban/data/handler/DoubanTeleplayLoadHandler.ts +++ b/src/org/wanxp/douban/data/handler/DoubanTeleplayLoadHandler.ts @@ -5,11 +5,11 @@ import DoubanSubject from "../model/DoubanSubject"; import DoubanTeleplaySubject from "../model/DoubanTeleplaySubject"; import SchemaOrg from "src/org/wanxp/utils/SchemaOrg"; import HandleContext from "../model/HandleContext"; -import {PersonNameMode, SupportType, TemplateKey} from "../../../constant/Constsant"; -import {aliases} from "css-select"; +import {DataValueType, PersonNameMode, SupportType} from "../../../constant/Constsant"; import {UserStateSubject} from "../model/UserStateSubject"; import {moment} from "obsidian"; -import YamlUtil, {SPECIAL_CHAR_REG, TITLE_ALIASES_SPECIAL_CHAR_REG_G} from "../../../utils/YamlUtil"; +import {TITLE_ALIASES_SPECIAL_CHAR_REG_G} from "../../../utils/YamlUtil"; +import {DataField} from "../../../utils/model/DataField"; /** * teleplay @@ -24,20 +24,28 @@ export class DoubanTeleplayLoadHandler extends DoubanAbstractLoadHandler c), context)) - .replaceAll("{{actor}}", this.handleArray( extract.actor.map(SchemaOrg.getPersonName).filter(c => c), context)) - .replaceAll("{{author}}", this.handleArray( extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c), context)) - .replaceAll("{{aliases}}", this.handleArray( extract.aliases.map(a=>a.replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')), context)) - .replaceAll("{{country}}", this.handleArray( extract.country, context)) - .replaceAll("{{language}}", this.handleArray(extract.language, context)) - .replaceAll("{{IMDb}}", extract.IMDb?? "") - .replaceAll("{{time}}", extract.time ?? "") - .replaceAll("{{episode}}", extract.episode ?? "") -; + parseVariable(beforeContent: string, variableMap:Map, extract: DoubanTeleplaySubject, context: HandleContext): void { + variableMap.set("director", new DataField("director", DataValueType.array, extract.director,extract.director.map(SchemaOrg.getPersonName).filter(c => c))); + variableMap.set("actor", new DataField( + "actor", + DataValueType.array, + extract.actor, + extract.actor.map(SchemaOrg.getPersonName).filter(c => c) + )); + + variableMap.set("author", new DataField( + "author", + DataValueType.array, + extract.author, + extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c) + )); + + variableMap.set("aliases", new DataField( + "aliases", + DataValueType.array, + extract.aliases, + extract.aliases.map(a => a.replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')) + )); } support(extract: DoubanSubject): boolean { @@ -52,14 +60,14 @@ export class DoubanTeleplayLoadHandler extends DoubanAbstractLoadHandler div.a_stars > span.mr10').text().trim(); - let collectionDateStr = html('div#interest_sect_level > div.a_stars > span.mr10 > span.collection_date').text().trim(); - let userState1 = DoubanAbstractLoadHandler.getUserState(stateWord); - let component = rating.next().next().next().next().text().trim(); + const tagsStr = rating.next().next().text().trim(); + const tags = tagsStr ? tagsStr.replace('标签:', '').trim().split(' ') : null; + const stateWord = html('div#interest_sect_level > div.a_stars > span.mr10').text().trim(); + const collectionDateStr = html('div#interest_sect_level > div.a_stars > span.mr10 > span.collection_date').text().trim(); + const userState1 = DoubanAbstractLoadHandler.getUserState(stateWord); + const component = rating.next().next().next().next().text().trim(); const userState: UserStateSubject = { tags: tags, diff --git a/src/org/wanxp/douban/data/handler/DoubanTheaterLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanTheaterLoadHandler.ts index baf9924..faa3cef 100644 --- a/src/org/wanxp/douban/data/handler/DoubanTheaterLoadHandler.ts +++ b/src/org/wanxp/douban/data/handler/DoubanTheaterLoadHandler.ts @@ -4,11 +4,12 @@ import DoubanPlugin from "../../../main"; import SchemaOrg from "src/org/wanxp/utils/SchemaOrg"; import DoubanSubject from '../model/DoubanSubject'; import HandleContext from "../model/HandleContext"; -import {PropertyName, SupportType} from "../../../constant/Constsant"; +import {DataValueType, PropertyName, SupportType} from "../../../constant/Constsant"; import {UserStateSubject} from "../model/UserStateSubject"; import {moment} from "obsidian"; import {TITLE_ALIASES_SPECIAL_CHAR_REG_G} from "../../../utils/YamlUtil"; import DoubanTheaterSubject from "../model/DoubanTheaterSubject"; +import {DataField} from "../../../utils/model/DataField"; export default class DoubanTheaterLoadHandler extends DoubanAbstractLoadHandler { constructor(doubanPlugin: DoubanPlugin) { @@ -27,15 +28,34 @@ export default class DoubanTheaterLoadHandler extends DoubanAbstractLoadHandler< return `https://www.douban.com/location/drama/${id}/`; } - parseText(beforeContent: string, extract: DoubanTheaterSubject, context: HandleContext): string { - return beforeContent - .replaceAll("{{originalTitle}}", extract.originalTitle ? extract.originalTitle : "") - .replaceAll("{{director}}", this.handleArray(extract.director.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c), context)) - .replaceAll("{{actor}}", this.handleArray(extract.actor.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c), context)) - .replaceAll("{{author}}", this.handleArray(extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c), context)) - .replaceAll("{{aliases}}", this.handleArray(extract.aliases.map(a => a.replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')), context)) - .replaceAll("{{language}}", this.handleArray(extract.language, context)) - ; + parseVariable(beforeContent: string, variableMap:Map, extract: DoubanTheaterSubject, context: HandleContext): void { + variableMap.set("director", new DataField( + "director", + DataValueType.array, + extract.director, + extract.director.map(SchemaOrg.getPersonName).filter(c => c) + )); + + variableMap.set("actor", new DataField( + "actor", + DataValueType.array, + extract.actor, + extract.actor.map(SchemaOrg.getPersonName).filter(c => c) + )); + + variableMap.set("author", new DataField( + "author", + DataValueType.array, + extract.author, + extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c) + )); + + variableMap.set("aliases", new DataField( + "aliases", + DataValueType.array, + extract.aliases, + extract.aliases.map(a => a.replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')) + )); } support(extract: DoubanSubject): boolean { @@ -43,13 +63,13 @@ export default class DoubanTheaterLoadHandler extends DoubanAbstractLoadHandler< } analysisUser(html: CheerioAPI, context: HandleContext): { data: CheerioAPI, userState: UserStateSubject } { - let rate = html('input#n_rating').val(); - let tagsStr = html('div#interest_sect_level > div.a_stars > span.color_gray').text().trim(); - let tags = tagsStr ? tagsStr.replace('标签:', '').trim().split(' ') : null; - let stateWord = html('#interest_sect_level > h2').text().trim(); - let collectionDateStr = html('div#interest_sect_level > div.a_stars > span.mr10 > span.collection_date').text().trim(); - let userState1 = DoubanAbstractLoadHandler.getUserState(stateWord); - let component = this.getPropertyValue(html, PropertyName.comment); + const rate = html('input#n_rating').val(); + const tagsStr = html('div#interest_sect_level > div.a_stars > span.color_gray').text().trim(); + const tags = tagsStr ? tagsStr.replace('标签:', '').trim().split(' ') : null; + const stateWord = html('#interest_sect_level > h2').text().trim(); + const collectionDateStr = html('div#interest_sect_level > div.a_stars > span.mr10 > span.collection_date').text().trim(); + const userState1 = DoubanAbstractLoadHandler.getUserState(stateWord); + const component = this.getPropertyValue(html, PropertyName.comment); const userState: UserStateSubject = { tags: tags, rate: rate ? Number(rate) : null, diff --git a/src/org/wanxp/douban/data/model/DoubanBookSubject.ts b/src/org/wanxp/douban/data/model/DoubanBookSubject.ts index b3e8422..0457ceb 100644 --- a/src/org/wanxp/douban/data/model/DoubanBookSubject.ts +++ b/src/org/wanxp/douban/data/model/DoubanBookSubject.ts @@ -15,15 +15,15 @@ export default class DoubanBookSubject extends DoubanSubject { } export const DoubanBookParameter = { - author: '{{author}}', - translator: '{{translator}}', - isbn: '{{isbn}}', - originalTitle: '{{originalTitle}}', - subTitle: '{{subTitle}}', - totalPage: '{{totalPage}}', - series: '{{series}}', - menu: '{{menu}}', - price: '{{price}}', - binding: '{{binding}}', - producer: '{{producer}}', + author: 'author', + translator: 'translator', + isbn: 'isbn', + originalTitle: 'originalTitle', + subTitle: 'subTitle', + totalPage: 'totalPage', + series: 'series', + menu: 'menu', + price: 'price', + binding: 'binding', + producer: 'producer', } diff --git a/src/org/wanxp/douban/data/model/DoubanSubject.ts b/src/org/wanxp/douban/data/model/DoubanSubject.ts index 3b678ae..7e77f85 100644 --- a/src/org/wanxp/douban/data/model/DoubanSubject.ts +++ b/src/org/wanxp/douban/data/model/DoubanSubject.ts @@ -39,3 +39,22 @@ export const DoubanParameter = { CURRENT_DATE: '{{currentDate}}', CURRENT_TIME: '{{currentTime}}', } + +export const DoubanParameterName = { + ID: 'id', + TITLE: 'title', + TYPE: 'type', + SCORE: 'score', + IMAGE: 'image', + IMAGE_URL: 'imageData.url', + URL: 'url', + DESC: 'desc', + PUBLISHER: 'publisher', + DATE_PUBLISHED: 'datePublished', + TIME_PUBLISHED: 'timePublished', + YEAR_PUBLISHED: 'yearPublished', + GENRE: 'genre', + CURRENT_DATE: 'currentDate', + CURRENT_TIME: 'currentTime', +} + diff --git a/src/org/wanxp/douban/data/model/UserStateSubject.ts b/src/org/wanxp/douban/data/model/UserStateSubject.ts index a1f93e1..4ef2b00 100644 --- a/src/org/wanxp/douban/data/model/UserStateSubject.ts +++ b/src/org/wanxp/douban/data/model/UserStateSubject.ts @@ -15,3 +15,11 @@ export const DoubanUserParameter = { MY_COMMENT: '{{myComment}}', MY_COLLECTION_DATE: '{{myCollectionDate}}', } + +export const DoubanUserParameterName = { + MY_TAGS: 'myTags', + MY_RATING: 'myRating', + MY_STATE: 'myState', + MY_COMMENT: 'myComment', + MY_COLLECTION_DATE: 'myCollectionDate', +} diff --git a/src/org/wanxp/douban/data/search/DoubanSearchModal.ts b/src/org/wanxp/douban/data/search/DoubanSearchModal.ts index 8a5c2e4..4990606 100644 --- a/src/org/wanxp/douban/data/search/DoubanSearchModal.ts +++ b/src/org/wanxp/douban/data/search/DoubanSearchModal.ts @@ -1,9 +1,10 @@ -import {App, DropdownComponent, Modal, TextComponent} from "obsidian"; +import {App, ButtonComponent, DropdownComponent, Modal, Setting, TextComponent} from "obsidian"; import DoubanPlugin from "../../../main"; import {i18nHelper} from "src/org/wanxp/lang/helper"; import HandleContext from "../model/HandleContext"; import {SearchTypeRecords, SupportType} from "../../../constant/Constsant"; +import {sleep} from "../../../utils/TimeUtil"; export class DoubanSearchModal extends Modal { searchTerm: string; @@ -32,6 +33,7 @@ export class DoubanSearchModal extends Modal { searchInput.inputEl.addEventListener("keydown", (event) => { if (event.key === "Enter") { + sleep(1000); this.close(); } }); @@ -49,21 +51,17 @@ export class DoubanSearchModal extends Modal { const controls = contentEl.createDiv("controls"); controls.addClass("obsidian_douban_search_controls") - const searchButton = controls.createEl("button", { - text: i18nHelper.getMessage('110004'), - cls: "mod-cta", - attr: { - autofocus: true, - }, - }); - searchButton.addClass("obsidian_douban_search_button"); - - searchButton.addEventListener("click", this.close.bind(this)); - const cancelButton = controls.createEl("button", {text: i18nHelper.getMessage('110005')}); - cancelButton.addEventListener("click", this.close.bind(this)); - cancelButton.addClass("obsidian_douban_cancel_button"); - searchInput.inputEl.focus(); - + new ButtonComponent(controls) + .setButtonText(i18nHelper.getMessage('110004')) + .setCta() + .onClick(() => { + this.close(); + }).setClass( "obsidian_douban_search_button"); + new ButtonComponent(controls) + .setButtonText(i18nHelper.getMessage('110005')) + .onClick(() => { + this.close(); + }).setClass( "obsidian_douban_cancel_button"); } @@ -76,3 +74,4 @@ export class DoubanSearchModal extends Modal { } } + diff --git a/src/org/wanxp/douban/setting/ArrayDisplayTypeSettingsHelper.ts b/src/org/wanxp/douban/setting/ArrayDisplayTypeSettingsHelper.ts new file mode 100644 index 0000000..cc09879 --- /dev/null +++ b/src/org/wanxp/douban/setting/ArrayDisplayTypeSettingsHelper.ts @@ -0,0 +1,162 @@ +import SettingsManager from "./SettingsManager"; +import {ArraySetting, DEFAULT_SETTINGS_ARRAY_NAME} from "./model/ArraySetting"; +import {Setting, TextComponent} from "obsidian"; +import {i18nHelper} from "../../lang/helper"; +import {DEFAULT_SETTINGS} from "../../constant/DefaultSettings"; +import {DEFAULT_SETTINGS_ARRAY_INPUT_SIZE} from "../../constant/Constsant"; + + +export function arraySettingDisplayUI(containerEl: HTMLElement, manager: SettingsManager) { + containerEl.createEl('h3', {text: i18nHelper.getMessage('120601')}); + arraySettingDisplay(containerEl.createDiv('array-settings'), manager, false); +} + +export function arraySettingDisplay(containerEl: HTMLElement, manager: SettingsManager, displayExtraListTypeFlag: boolean = false) { + containerEl.empty(); + const arraySet = new Setting(containerEl) + .setName(i18nHelper.getMessage('120601')) + .setDesc( i18nHelper.getMessage('120602')) + .addButton((button) => { + button + .setIcon('plus') + .setTooltip(i18nHelper.getMessage('120607')) + .onClick(async () => { + await manager.addArraySetting(); + arraySettingDisplay(containerEl, manager, true); + }); + }); + if (displayExtraListTypeFlag) { + arraySettingDisplayItem(containerEl, manager, manager.getArraySetting(DEFAULT_SETTINGS_ARRAY_NAME)); + displayExtraListType(manager, containerEl); + arraySet.addButton((button) => { + button + .setIcon('down-chevron-glyph') + .setTooltip(i18nHelper.getMessage('120608')) + .onClick(async () => { + arraySettingDisplay(containerEl, manager, false); + }); + }); + }else { + arraySet.addButton((button) => { + button + .setIcon('right-chevron-glyph') + .setTooltip(i18nHelper.getMessage('120608')) + .onClick(async () => { + arraySettingDisplay(containerEl, manager, true); + }); + }); + } +} + +function arraySettingDisplayItem(containerEl: HTMLElement, manager: SettingsManager, arraySetting:ArraySetting) { + const arrSettingsUI = containerEl.createDiv('array-settings'); + const arrShow = containerEl.createDiv('array-show'); + const typeName = arraySetting.arrayName; + const arraySettingItems = new Setting(arrSettingsUI) + .setName(i18nHelper.getMessage('120604') + typeName ) + .setDesc(i18nHelper.getMessage(`120605`) + (typeName == DEFAULT_SETTINGS_ARRAY_NAME ? '' : `(${typeName})`) +`}}`) + ; + if(typeName != DEFAULT_SETTINGS_ARRAY_NAME) { + arraySettingItems.addButton((button) => { + button + .setIcon('trash') + .setTooltip(i18nHelper.getMessage('120606')) + .onClick(async () => { + await manager.removeArraySetting(arraySetting.arrayName); + arraySettingDisplay(containerEl, manager, true); + }); + }); + } + + arrSettingsUI.createEl('label', {text: i18nHelper.getMessage('124109')}) + const arrayStart = new TextComponent(arrSettingsUI); + arrayStart.setPlaceholder(DEFAULT_SETTINGS.arrayStart) + .setValue(arraySetting.arrayStart) + .onChange(async (value) => { + arraySetting.arrayStart = value; + await manager.updateArraySetting(arraySetting); + showArrayExample(arrShow, manager, arraySetting); + }); + const arrayStartEl = arrayStart.inputEl; + arrayStartEl.size = DEFAULT_SETTINGS_ARRAY_INPUT_SIZE; + arrayStartEl.addClass('obsidian_douban_settings_input') + arrSettingsUI.appendChild(arrayStartEl).appendText(" "); + + arrSettingsUI.createEl('label', {text: i18nHelper.getMessage('124110')}) + const arrayElementStart = new TextComponent(arrSettingsUI); + arrayElementStart.setPlaceholder(DEFAULT_SETTINGS.arrayElementStart) + .setValue(arraySetting.arrayElementStart) + .onChange(async (value) => { + arraySetting.arrayElementStart = value; + await manager.updateArraySetting(arraySetting); + showArrayExample(arrShow, manager, arraySetting); + }); + const arrayElementStartEl = arrayElementStart.inputEl; + arrayElementStartEl.addClass('obsidian_douban_settings_input') + arrayElementStartEl.size = DEFAULT_SETTINGS_ARRAY_INPUT_SIZE; + arrSettingsUI.appendChild(arrayElementStartEl).appendText(" "); + + arrSettingsUI.createEl('label', {text: i18nHelper.getMessage('124111')}) + const arraySpiltV2 = new TextComponent(arrSettingsUI); + arraySpiltV2.setPlaceholder(DEFAULT_SETTINGS.arraySpiltV2) + .setValue(arraySetting.arraySpiltV2) + .onChange(async (value) => { + arraySetting.arraySpiltV2 = value; + await manager.updateArraySetting(arraySetting); + showArrayExample(arrShow, manager, arraySetting); + }); + const arraySpiltV2El = arraySpiltV2.inputEl; + arraySpiltV2El.addClass('obsidian_douban_settings_input') + arraySpiltV2El.size = 2; + arrSettingsUI.appendChild(arraySpiltV2El).appendText(" "); + + arrSettingsUI.createEl('label', {text: i18nHelper.getMessage('124112')}) + const arrayElementEnd = new TextComponent(arrSettingsUI); + arrayElementEnd.setPlaceholder(DEFAULT_SETTINGS.arrayElementEnd) + .setValue(arraySetting.arrayElementEnd) + .onChange(async (value) => { + arraySetting.arrayElementEnd = value; + await manager.updateArraySetting(arraySetting); + showArrayExample(arrShow, manager, arraySetting); + }); + const arrayElementEndEl = arrayElementEnd.inputEl; + arrayElementEndEl.addClass('obsidian_douban_settings_input') + arrayElementEndEl.size = DEFAULT_SETTINGS_ARRAY_INPUT_SIZE; + arrSettingsUI.appendChild(arrayElementEndEl).appendText(" "); + + arrSettingsUI.createEl('label', {text: i18nHelper.getMessage('124113')}) + const arrayEnd = new TextComponent(arrSettingsUI); + arrayEnd.setPlaceholder(DEFAULT_SETTINGS.arrayEnd) + .setValue(arraySetting.arrayEnd) + .onChange(async (value) => { + arraySetting.arrayEnd = value; + await manager.updateArraySetting(arraySetting); + showArrayExample(arrShow, manager, arraySetting); + }); + const arrayEndEl = arrayEnd.inputEl; + arrayEndEl.addClass('obsidian_douban_settings_input') + arrayEndEl.size = DEFAULT_SETTINGS_ARRAY_INPUT_SIZE; + arrSettingsUI.appendChild(arrayEndEl).appendText(" "); + + showArrayExample(arrShow, manager, arraySetting); +} + +function displayExtraListType(manager: SettingsManager, containerEl: HTMLElement) { + manager.settings.arraySettings.forEach(arraySetting => { + new Setting(containerEl) + arraySettingDisplayItem(containerEl, manager, arraySetting); + }) +} + + +function showArrayExample(arrShow: HTMLDivElement, manager: SettingsManager, arraySetting:ArraySetting) { + arrShow.empty(); + const document = new DocumentFragment(); + document.createDiv('array-show-title') + .innerHTML = `propertyName:${manager.handleArray(['value1', 'value2', 'value3'], arraySetting)}`; + + new Setting(arrShow) + .setName(i18nHelper.getMessage('120603')) + .setDesc(document); + +} diff --git a/src/org/wanxp/douban/setting/DoubanSettingTab.ts b/src/org/wanxp/douban/setting/DoubanSettingTab.ts index a055460..43363c2 100644 --- a/src/org/wanxp/douban/setting/DoubanSettingTab.ts +++ b/src/org/wanxp/douban/setting/DoubanSettingTab.ts @@ -1,18 +1,14 @@ -import {App, PluginSettingTab, SearchComponent, Setting} from "obsidian"; +import {App, PluginSettingTab, Setting} from "obsidian"; import DoubanPlugin from "../../main"; -import {i18nHelper} from "src/org/wanxp/lang/helper"; -import {PersonNameMode, PersonNameModeRecords} from "../../constant/Constsant"; import SettingsManager from "./SettingsManager"; -import {FolderSuggest} from "./model/FolderSuggest"; -import { DEFAULT_SETTINGS } from "src/org/wanxp/constant/DefaultSettings"; import { constructOutUI } from "./OutputSettingsHelper"; import { constructTemplateUI } from "./TemplateSettingHelper"; import { constructBasicUI } from "./BasicSettingsHelper"; import { constructTemplateVariablesUI } from "./TemplateVariableSettingsHelper"; -import {constructCustomPropertySettingsUI, constructCustomPropertyUI} from "./CustomPropertySettingsHelper"; -import {log} from "../../utils/Logutil"; +import {constructCustomPropertySettingsUI } from "./CustomPropertySettingsHelper"; import { constructAdvancedUI } from "./AdvancedSettingsHelper"; +import {arraySettingDisplay, arraySettingDisplayUI} from "./ArrayDisplayTypeSettingsHelper"; /** * 部分逻辑参考以下项目 @@ -36,9 +32,11 @@ export class DoubanSettingTab extends PluginSettingTab { constructBasicUI(containerEl, this.settingsManager); constructTemplateUI(containerEl, this.settingsManager); constructOutUI(containerEl, this.settingsManager); + arraySettingDisplayUI(containerEl, this.settingsManager); constructCustomPropertySettingsUI(containerEl, this.settingsManager); constructTemplateVariablesUI(containerEl, this.settingsManager); constructAdvancedUI(containerEl, this.settingsManager); + } hide(): void { diff --git a/src/org/wanxp/douban/setting/OutputSettingsHelper.ts b/src/org/wanxp/douban/setting/OutputSettingsHelper.ts index 6077487..05cc314 100644 --- a/src/org/wanxp/douban/setting/OutputSettingsHelper.ts +++ b/src/org/wanxp/douban/setting/OutputSettingsHelper.ts @@ -1,106 +1,22 @@ import {i18nHelper} from "../../lang/helper"; -import {Setting, TextComponent} from "obsidian"; +import {Setting} from "obsidian"; import {createFolderSelectionSetting} from "./TemplateSettingHelper"; import {DEFAULT_SETTINGS} from "../../constant/DefaultSettings"; -import {PersonNameMode, PersonNameModeRecords} from "../../constant/Constsant"; +import { PersonNameMode, PersonNameModeRecords} from "../../constant/Constsant"; import SettingsManager from "./SettingsManager"; - export function constructOutUI(containerEl: HTMLElement, manager: SettingsManager) { containerEl.createEl('h3', { text: i18nHelper.getMessage('1220') }); new Setting(containerEl); - let attachmentFileSetting = containerEl.createDiv({ cls: 'settings-item-attachment' }); + const attachmentFileSetting = containerEl.createDiv({ cls: 'settings-item-attachment' }); constructAttachmentFileSettingsUI(attachmentFileSetting, manager); new Setting(containerEl).then(createFolderSelectionSetting({name: '121501', desc: '121502', placeholder: '121503', key: 'dataFilePath', manager: manager})); - let outfolder = containerEl.createDiv({ cls: 'settings-item' }); - - constructOutputFileNameUI(outfolder, manager); - - let arrSettings = containerEl.createDiv('array-settings'); - let arrShow = containerEl.createDiv('array-show'); - - const descFrag:DocumentFragment = new DocumentFragment(); - const desc: HTMLElement = descFrag.createDiv('array-setting-desc') - desc.innerHTML = i18nHelper.getMessage('120602'); - new Setting(arrSettings) - .setName(i18nHelper.getMessage('120601')) - .setDesc(descFrag); - arrSettings; - - arrSettings.createEl('label', { text: i18nHelper.getMessage('124109') }) - const arrayStart = new TextComponent(arrSettings); - arrayStart.setPlaceholder(DEFAULT_SETTINGS.arrayStart) - .setValue(manager.settings.arrayStart) - .onChange(async (value) => { - manager.plugin.settings.arrayStart = value; - await manager.plugin.saveSettings(); - showArrayExample(arrShow, manager); - }); - let arrayStartEl = arrayStart.inputEl; - arrayStartEl.size = 3; - arrayStartEl.addClass('obsidian_douban_settings_input') - arrSettings.appendChild(arrayStartEl).appendText(" "); - - arrSettings.createEl('label', { text: i18nHelper.getMessage('124110') }) - const arrayElementStart = new TextComponent(arrSettings); - arrayElementStart.setPlaceholder(DEFAULT_SETTINGS.arrayElementStart) - .setValue(manager.settings.arrayElementStart) - .onChange(async (value) => { - manager.plugin.settings.arrayElementStart = value; - await manager.plugin.saveSettings(); - showArrayExample(arrShow, manager); - }); - let arrayElementStartEl = arrayElementStart.inputEl; - arrayElementStartEl.addClass('obsidian_douban_settings_input') - arrayElementStartEl.size = 3; - arrSettings.appendChild(arrayElementStartEl).appendText(" "); - - arrSettings.createEl('label', { text: i18nHelper.getMessage('124111') }) - const arraySpiltV2 = new TextComponent(arrSettings); - arraySpiltV2.setPlaceholder(DEFAULT_SETTINGS.arraySpiltV2) - .setValue(manager.settings.arraySpiltV2) - .onChange(async (value) => { - manager.plugin.settings.arraySpiltV2 = value; - await manager.plugin.saveSettings(); - showArrayExample(arrShow, manager); - }); - let arraySpiltV2El = arraySpiltV2.inputEl; - arraySpiltV2El.addClass('obsidian_douban_settings_input') - arraySpiltV2El.size = 3; - arrSettings.appendChild(arraySpiltV2El).appendText(" "); - - arrSettings.createEl('label', { text: i18nHelper.getMessage('124112') }) - const arrayElementEnd = new TextComponent(arrSettings); - arrayElementEnd.setPlaceholder(DEFAULT_SETTINGS.arrayElementEnd) - .setValue(manager.settings.arrayElementEnd) - .onChange(async (value) => { - manager.plugin.settings.arrayElementEnd = value; - await manager.plugin.saveSettings(); - showArrayExample(arrShow, manager); - }); - let arrayElementEndEl = arrayElementEnd.inputEl; - arrayElementEndEl.addClass('obsidian_douban_settings_input') - arrayElementEndEl.size = 3; - arrSettings.appendChild(arrayElementEndEl).appendText(" "); - - arrSettings.createEl('label', { text: i18nHelper.getMessage('124113') }) - const arrayEnd = new TextComponent(arrSettings); - arrayEnd.setPlaceholder(DEFAULT_SETTINGS.arrayEnd) - .setValue(manager.settings.arrayEnd) - .onChange(async (value) => { - manager.plugin.settings.arrayEnd = value; - await manager.plugin.saveSettings(); - showArrayExample(arrShow, manager); - }); - let arrayEndEl = arrayEnd.inputEl; - arrayEndEl.addClass('obsidian_douban_settings_input') - arrayEndEl.size = 3; - arrSettings.appendChild(arrayEndEl).appendText(" "); - showArrayExample(arrShow, manager); + const outFolder = containerEl.createDiv({ cls: 'settings-item' }); + constructOutputFileNameUI(outFolder, manager); new Setting(containerEl).setName(i18nHelper.getMessage('121201')).then((setting) => { setting.addDropdown((dropdwon) => { @@ -128,6 +44,9 @@ export function constructOutUI(containerEl: HTMLElement, manager: SettingsManage }); }); }); + + + } @@ -190,14 +109,4 @@ export function constructAttachmentFileSettingsUI(containerEl: HTMLElement, mana }); } } -function showArrayExample(arrShow: HTMLDivElement, manager: SettingsManager) { - arrShow.empty(); - let document = new DocumentFragment(); - document.createDiv('array-show-title') - .innerHTML = `propertyName:${manager.handleArray(['value1', 'value2', 'value3'])}`; - new Setting(arrShow) - .setName(i18nHelper.getMessage('120603')) - .setDesc(document); - -} diff --git a/src/org/wanxp/douban/setting/SettingsManager.ts b/src/org/wanxp/douban/setting/SettingsManager.ts index 685060a..d3ab862 100644 --- a/src/org/wanxp/douban/setting/SettingsManager.ts +++ b/src/org/wanxp/douban/setting/SettingsManager.ts @@ -11,6 +11,12 @@ import {DoubanPluginOnlineSettings} from "./model/DoubanPluginOnlineSettings"; import {DoubanPluginSubjectProperty} from "./model/DoubanPluginSubjectProperty"; import HandleContext from "../data/model/HandleContext"; import HtmlUtil from "../../utils/HtmlUtil"; +import { + ARRAY_NAME_PREFIX_NAME, + ArraySetting, + ArraySettingFieldName, + DEFAULT_SETTINGS_ARRAY_NAME +} from "./model/ArraySetting"; export default class SettingsManager { app: App; @@ -97,9 +103,69 @@ export default class SettingsManager { return []; } - handleArray(arr: string[]): string { - let result:string = StringUtil.handleArray(arr, this.settings); + handleArray(arr: string[], arraySetting:ArraySetting): string { + let result:string = StringUtil.handleArray(arr, arraySetting); return HtmlUtil.strToHtml(result); } + async updateArraySetting(arraySetting: ArraySetting) { + if (arraySetting.arrayName == DEFAULT_SETTINGS_ARRAY_NAME) { + this.settings.arrayStart = arraySetting.arrayStart; + this.settings.arrayElementStart = arraySetting.arrayElementStart; + this.settings.arraySpiltV2 = arraySetting.arraySpiltV2; + this.settings.arrayElementEnd = arraySetting.arrayElementEnd; + this.settings.arrayEnd = arraySetting.arrayEnd; + }else { + const index = this.settings.arraySettings.findIndex(as => as.arrayName == arraySetting.arrayName); + if (index == -1) { + this.settings.arraySettings.push(arraySetting); + } else { + this.settings.arraySettings[index] = arraySetting; + } + } + await this.plugin.saveSettings(); + } + + async removeArraySetting(arrayName: string) { + if (arrayName == DEFAULT_SETTINGS_ARRAY_NAME) { + return; + }else { + this.settings.arraySettings = this.settings.arraySettings.filter(arraySetting => arraySetting.arrayName !== arrayName); + } + await this.plugin.saveSettings(); + } + + getArraySetting(arrayName: string) { + if (!this.settings.arraySettings) { + this.settings.arraySettings = []; + } + if (arrayName == DEFAULT_SETTINGS_ARRAY_NAME) { + return this.getDefaultArraySetting(DEFAULT_SETTINGS_ARRAY_NAME, 0); + }else { + const arraySetting = this.settings.arraySettings.find(arraySetting => arraySetting.arrayName == arrayName); + if (arraySetting) { + return arraySetting; + } + } + return null; + } + + getDefaultArraySetting(arrayName:string, index:number): ArraySetting { + return {arrayName: arrayName, + arrayStart: this.settings.arrayStart, + arrayElementStart: this.settings.arrayElementStart, + arraySpiltV2: this.settings.arraySpiltV2, + arrayElementEnd: this.settings.arrayElementEnd, + arrayEnd: this.settings.arrayEnd, + index: index + }; + } + + async addArraySetting() { + const index = this.settings.arraySettings.length + 1; + const arraySetting = this.getDefaultArraySetting(ARRAY_NAME_PREFIX_NAME + index, index); + this.settings.arraySettings.push(arraySetting); + await this.plugin.saveSettings(); + return arraySetting; + } } diff --git a/src/org/wanxp/douban/setting/model/ArraySetting.ts b/src/org/wanxp/douban/setting/model/ArraySetting.ts new file mode 100644 index 0000000..5b2f940 --- /dev/null +++ b/src/org/wanxp/douban/setting/model/ArraySetting.ts @@ -0,0 +1,22 @@ +export interface ArraySetting { + index: number; + arrayName: string; + arrayStart: string; + arrayElementStart: string; + arraySpiltV2: string; + arrayElementEnd: string; + arrayEnd: string; +} + +export enum ArraySettingFieldName { + index = "index", + arrayName = "arrayName", + arrayStart = "arrayStart", + arrayElementStart = "arrayElementStart", + arraySpiltV2 = "arraySpiltV2", + arrayElementEnd = "arrayElementEnd", + arrayEnd = "arrayEnd", +} + +export const DEFAULT_SETTINGS_ARRAY_NAME = "default"; +export const ARRAY_NAME_PREFIX_NAME = "ArrayType"; diff --git a/src/org/wanxp/douban/setting/model/DoubanPluginSetting.ts b/src/org/wanxp/douban/setting/model/DoubanPluginSetting.ts index e0a4888..2650481 100644 --- a/src/org/wanxp/douban/setting/model/DoubanPluginSetting.ts +++ b/src/org/wanxp/douban/setting/model/DoubanPluginSetting.ts @@ -1,5 +1,6 @@ import {CustomProperty} from "./CustomProperty"; import {SyncHandledData} from "./SyncHandledData"; +import {ArraySetting} from "./ArraySetting"; export interface DoubanPluginSetting { onlineSettingsFileName: string; @@ -28,7 +29,7 @@ export interface DoubanPluginSetting { loginHeadersContent: string, cacheImage: boolean, cacheHighQuantityImage: boolean, - attachmentPath: string, syncHandledDataArray: SyncHandledData[], + arraySettings: ArraySetting[] } diff --git a/src/org/wanxp/douban/sync/handler/DoubanPageBroadcastLoadHandler.ts b/src/org/wanxp/douban/sync/handler/DoubanPageBroadcastLoadHandler.ts index bea71e9..71842fb 100644 --- a/src/org/wanxp/douban/sync/handler/DoubanPageBroadcastLoadHandler.ts +++ b/src/org/wanxp/douban/sync/handler/DoubanPageBroadcastLoadHandler.ts @@ -25,7 +25,7 @@ class DoubanPageBroadcastLoadHandler extends DoubanAbstractLoadHandler, extract: DoubanNoteSubject, context: HandleContext): void { return null; } diff --git a/src/org/wanxp/lang/locale/en.ts b/src/org/wanxp/lang/locale/en.ts index 456fad2..0a2c77b 100644 --- a/src/org/wanxp/lang/locale/en.ts +++ b/src/org/wanxp/lang/locale/en.ts @@ -218,7 +218,13 @@ PS: This file could be delete if you want to. '121601': `Note Name`, '121602': `Nodes created from Obsidian-Douban will use this fileName as template(also support filePath), If blank, they will be created by default name. support all basic template variables. example: {{type}}/{{title}}`, - '120603': `Array Display Example`, + '120603': `Display Preview`, + '120604': `ArrayTypeName:`, + '120605': `Template use example: propertyName:{{actor`, + '120606': `Delete Array Display Type`, + '120607': `Add Array Display Type`, + '120608': `Display/Hidden Array Setting`, + '121603': `assets`, @@ -244,6 +250,7 @@ PS: This file could be delete if you want to. '130105': `Can not use Douban this time, Please try again after 12 hour or 24 hour. Or you can reset your connection `, '130106': `Can not use Douban this time, Please try Login In Douban Plugin. If not working please again after 12 hour or 24 hour. Or you can reset your connection `, + '130107': `Can not find array setting for {1} in {0} , Please add it in array settings`, '140201': `[OB-Douban]: searching '{0}'...`, diff --git a/src/org/wanxp/lang/locale/zh-cn.ts b/src/org/wanxp/lang/locale/zh-cn.ts index aaa4c78..17954b6 100644 --- a/src/org/wanxp/lang/locale/zh-cn.ts +++ b/src/org/wanxp/lang/locale/zh-cn.ts @@ -186,7 +186,7 @@ export default { '120508': `格式参考`, '120601': `数组显示形式`, '120602': `当模板中的变量存在数组, 则需要设定数组元素中的分割符号以及起始与结束符号, 比如演员列表, - 支持转义字符\n(回车)`, + 支持转义字符\\n(回车)。并且同时支持多种方式输出内容,显示更多配置可点击右侧[>>]展开或点击[+]新增不同输出形式,且支持输出结果预览。`, '124109': `首:`, '124110': `元素首:`, '124111': `分隔符:`, @@ -229,7 +229,13 @@ export default { '121601': `笔记名称`, '121602': `创建的笔记将会使用此名称作为模板, 支持所有'通用'的参数作为名称(如:{{type}}/{{title}}), 且支持路径, 比如: 'MyData/{{title}}'. 如果为空, 笔记将会使用默认名称. `, - '120603': `数组分割字符串显示效果`, + '120603': `输出效果预览`, + '120604': `数组类型名称:`, + '120605': `模板中使用举例: propertyName:{{actor`, + '120606': `删除列表类型字段显示方式`, + '120607': `新增列表类型字段显示方式:`, + '120608': `显示或隐藏列表输出设置`, + '121701': `选择模板文件`, @@ -246,7 +252,7 @@ export default { '140102': `同步的对象和选择对象不一致,将不会同步, 现在选择同步的类型:{0},但是获取[{1}]的类型:{2}`, '130105': `由于多次频繁请求数据,豆瓣当前暂时不可用. 请于12小时或24小时后再重试,或重置你的网络(如重新拨号或更换网络) `, '130106': `请尝试在Douban插件中登录后操作. 若还是无效果则尝试于12小时或24小时后再重试,或重置你的网络(如重新拨号或更换网络) `, - + '130107': `参数{0}中指定的数组输出类型{1}不存在,请前往配置进行设置`, '140201': `[OB-Douban]: 开始搜索'{0}'...`, diff --git a/src/org/wanxp/utils/StringUtil.ts b/src/org/wanxp/utils/StringUtil.ts index 31fe0ef..e9230bc 100644 --- a/src/org/wanxp/utils/StringUtil.ts +++ b/src/org/wanxp/utils/StringUtil.ts @@ -1,4 +1,5 @@ import {DoubanPluginSetting} from "../douban/setting/model/DoubanPluginSetting"; +import {ArraySetting} from "../douban/setting/model/ArraySetting"; export default class StringUtil { @@ -85,13 +86,13 @@ export default class StringUtil { return newText; } - public static handleArray(arr: string[], settings: DoubanPluginSetting): string { + public static handleArray(arr: string[], arraySetting: ArraySetting): string { let content :string = ""; - const elementStart:string = StringUtil.escape(settings.arrayElementStart); - const elementEnd:string = StringUtil.escape(settings.arrayElementEnd); - const spilt:string = StringUtil.escape(settings.arraySpiltV2); - const start:string = StringUtil.escape(settings.arrayStart); - const end:string = StringUtil.escape(settings.arrayEnd); + const elementStart:string = StringUtil.escape(arraySetting.arrayElementStart); + const elementEnd:string = StringUtil.escape(arraySetting.arrayElementEnd); + const spilt:string = StringUtil.escape(arraySetting.arraySpiltV2); + const start:string = StringUtil.escape(arraySetting.arrayStart); + const end:string = StringUtil.escape(arraySetting.arrayEnd); for (let i = 0; i < arr.length; i++) { let el = arr[i]; if (!el) { diff --git a/src/org/wanxp/utils/TimeUtil.ts b/src/org/wanxp/utils/TimeUtil.ts index fb5d5c1..7f3e416 100644 --- a/src/org/wanxp/utils/TimeUtil.ts +++ b/src/org/wanxp/utils/TimeUtil.ts @@ -1,8 +1,5 @@ import NumberUtil from "./NumberUtil"; -import {log} from "./Logutil"; import {BasicConst, ESTIMATE_TIME_PER_WITH_REQUEST, ESTIMATE_TIME_PER_WITH_REQUEST_SLOW} from "../constant/Constsant"; -import {moment} from "obsidian"; -import {Moment} from "moment"; import {i18nHelper} from "../lang/helper"; export default class TimeUtil { diff --git a/src/org/wanxp/utils/VariableUtil.ts b/src/org/wanxp/utils/VariableUtil.ts new file mode 100644 index 0000000..80b8b66 --- /dev/null +++ b/src/org/wanxp/utils/VariableUtil.ts @@ -0,0 +1,214 @@ +import SettingsManager from "../douban/setting/SettingsManager"; +import {ArraySetting, DEFAULT_SETTINGS_ARRAY_NAME} from "../douban/setting/model/ArraySetting"; +import StringUtil from "./StringUtil"; +import YamlUtil from "./YamlUtil"; +import {log} from "./Logutil"; +import {i18nHelper} from "../lang/helper"; +import {DataValueType} from "../constant/Constsant"; +import {DataField} from "./model/DataField"; +import {FieldVariable} from "./model/FieldVariable"; + +export class VariableUtil { + /** + + * + * @param obj + * @param content + * @param settingManager + */ + + static replace(obj: any, content: string, settingManager:SettingsManager): string { + if (!content || !obj) { + return content; + } + const allVariables = this.getAllVariables(content, settingManager); + if (!allVariables || allVariables.length == 0) { + return content; + } + if (obj instanceof Map) { + content = this.replaceMap(obj, allVariables, content, settingManager); + }else { + content = this.replaceObject(obj, allVariables, content, settingManager); + } + + return content; + } + + /** + *

type

+ *
  • Number
  • + *
  • String
  • + *
  • Array
  • + * + *

    name

    + *
  • aliases
  • + * @param variable + * @param value + * @param content + * @param settingManager + */ + static replaceVariable(variable: FieldVariable, value: any, content: string, settingManager:SettingsManager): string { + if (!content) { + return content; + } + //根据value的类型,替换对应的变量 + if (value instanceof Array) { + content = this.replaceArray(variable, value, content, settingManager); + } else if(value instanceof DataField) { + content = this.replaceDataField(variable, value, content, settingManager); + } else { + content = this.replaceString(variable, value, content, settingManager); + } + return content; + } + + static replaceArray(variable: FieldVariable, value: any[], content: string, settingManager:SettingsManager): string { + if (!content) { + return content; + } + const variableStr = variable.variable; + const outTypeName = variable.outTypeName; + if (!value) { + return content.replaceAll(variableStr, ""); + } + const arraySettings = this.getArraySetting(outTypeName, settingManager); + if (!arraySettings) { + log.warn(i18nHelper.getMessage(`130107`, variable.variable, outTypeName)); + return content; + } + + const strValues:string[] = value.map((v) => { + if (typeof v === 'string') { + return v; + } else { + return v?v.toString() : null; + } + }) + .filter(v => v) + .map(v => YamlUtil.handleText(v)) + ; + const arrayValue = StringUtil.handleArray(strValues, arraySettings); + content = content.replaceAll(variableStr, arrayValue); + return content; + } + + static keyToVariable(key: string): string { + return `{{${key}}}`; + } + + static replaceString(variable: FieldVariable, value: any, content: string, settingManager:SettingsManager): string { + if (!content) { + return content; + } + let strValue = value? value.toString() : ""; + strValue = YamlUtil.handleText(strValue); + return content.replaceAll(variable.variable, strValue); + } + + /** + * 从key中提取 arrayName, 然后从settings中获取对应的ArraySetting + * @param key + * @private + */ + private static getAllVariables(content: string, settingManager:SettingsManager): FieldVariable[] { + const reg =/\{\{[a-zA-Z-0-9_.]+([(a-zA-Z-0-9)]+)?}}/g + const result = content.match(reg); + if (!result) { + return []; + } + return result.map((v) => { + const reg2 = new RegExp(`[a-zA-Z-0-9_.]+`, 'g'); + const result2 = v.match(reg2); + if (!result2) { + return null; + } + if (result2.length == 1) { + return new FieldVariable(result2[0], v, null); + } + return new FieldVariable(result2[0], v, result2[1]); + }).filter(v => v); + } + + /** + * 从key中提取 arrayName, 然后从settings中获取对应的ArraySetting + * @param outTypeName + * @private + */ + private static getArraySetting(outTypeName: string, settingManager:SettingsManager): ArraySetting { + if (!outTypeName) { + return settingManager.getArraySetting(DEFAULT_SETTINGS_ARRAY_NAME); + } else { + return settingManager.getArraySetting(outTypeName); + } + } + + private static replaceObject(obj: any, allVariables:FieldVariable[], content: string, settingManager: SettingsManager) { + allVariables.forEach(variable => { + const key = variable.key; + const value = obj.get(key); + if (obj.hasOwnProperty(key)) { + const value = obj[key]; + content = this.replaceVariable(variable,value, content, settingManager); + } + content = this.replaceVariable(variable, value, content, settingManager); + }); + return content; + } + + private static replaceMap(obj: Map, allVariables:FieldVariable[], content: string, settingManager: SettingsManager) { + allVariables.forEach(variable => { + const value = obj.get(variable.key); + content = this.replaceVariable(variable, value,content, settingManager); + }); + return content; + } + + static getType(value: any):DataValueType { + if (typeof value === 'number') { + return DataValueType.number; + } else if (typeof value === 'string') { + if (value.startsWith('http://') || value.startsWith('https://')) { + return DataValueType.url; + }else if (/^(\/|\.\/|\.\.\/|~\/|.*\.[a-zA-Z0-9]+$)/.test(value)) { + return DataValueType.path; + } + return DataValueType.string; + } else if (value instanceof Date) { + return DataValueType.date; + } else if (value instanceof Array) { + return DataValueType.array; + } else { + return DataValueType.string; + } + } + + private static replaceDataField(variable: FieldVariable, value: DataField, content: string, settingManager: SettingsManager) { + if (!content) { + return content; + } + const variableStr = variable.variable; + if (!value) { + return content.replaceAll(variableStr, ""); + } + switch (value.type) { + case DataValueType.string: + content = this.replaceString(variable, value.value, content, settingManager); + break; + case DataValueType.number: + content = content.replaceAll(variableStr, value.value.toString()); + break; + case DataValueType.date: + content = content.replaceAll(variableStr, value.value); + break; + case DataValueType.array: + content = this.replaceArray(variable, value.value, content, settingManager); + break; + default: + content = content.replaceAll(variableStr, value.value); + break; + + } + + return content; + } +} diff --git a/src/org/wanxp/utils/YamlUtil.ts b/src/org/wanxp/utils/YamlUtil.ts index 5a98d73..53651bf 100644 --- a/src/org/wanxp/utils/YamlUtil.ts +++ b/src/org/wanxp/utils/YamlUtil.ts @@ -15,10 +15,14 @@ export default class YamlUtil { } public static handleText(text: string) { - return YamlUtil.hasSpecialChar(text) ? YamlUtil.handleSpecialChar(text.replaceAll('"', '\\"')) - .replaceAll(/\s+/g,' ') - .replaceAll('\n', '。') - .replaceAll('。。', '。') : text; + return YamlUtil.hasSpecialChar(text) + ? YamlUtil.handleSpecialChar(text.replaceAll('"', '\\"')) + .replaceAll(/\s+/g,' ') + .replaceAll('\n', '。') + .replaceAll('。。', '。') + .replace(/^" /, '"') // Remove leading " + .replace(/ "$/, '"') // Remove trailing " + : text; } } diff --git a/src/org/wanxp/utils/model/DataField.ts b/src/org/wanxp/utils/model/DataField.ts new file mode 100644 index 0000000..9f08737 --- /dev/null +++ b/src/org/wanxp/utils/model/DataField.ts @@ -0,0 +1,32 @@ +import {DataValueType} from "../../constant/Constsant"; + +export class DataField { + private _name: string; + private _type: DataValueType; + private _origin: any; + private _value: any; + constructor(name: string, type: DataValueType, origin: any, value: any) { + this._name = name; + this._type = type; + this._origin = origin; + this._value = value; + } + + public get name():string{ + return this._name; + } + + public get type():DataValueType{ + return this._type; + } + + public get origin():any{ + return this._origin; + } + + public get value():any{ + return this._value; + } + + +} diff --git a/src/org/wanxp/utils/model/FieldVariable.ts b/src/org/wanxp/utils/model/FieldVariable.ts new file mode 100644 index 0000000..a6f88b8 --- /dev/null +++ b/src/org/wanxp/utils/model/FieldVariable.ts @@ -0,0 +1,25 @@ +export class FieldVariable { + private _key:string; + private _variable:string; + private _outTypeName:string; + + constructor(key:string, variable:string, outTypeName:string) { + this._key = key; + this._variable = variable; + this._outTypeName = outTypeName; + } + + public get key():string{ + return this._key; + } + + public get variable():string{ + return this._variable; + } + + public get outTypeName():string{ + return this._outTypeName; + } + + +}