feat: 附件(图片)文件保存本地支持自定义

fix: 修复有些图片无法下问题
fix: 修复同步汇总文件中文件名和真实保存不一致问题
feat: 调整别名的转义
This commit is contained in:
wanxp 2025-11-09 22:43:17 +08:00
parent 266cfb3901
commit 08749116f3
20 changed files with 144 additions and 66 deletions

@ -51,6 +51,7 @@ export const DEFAULT_SETTINGS: DoubanPluginSetting = {
cacheImage: true, cacheImage: true,
cacheHighQuantityImage: true, cacheHighQuantityImage: true,
attachmentPath: 'assets', attachmentPath: 'assets',
attachmentFileName: "{{title}}",
syncHandledDataArray: [], syncHandledDataArray: [],
// syncLastUpdateTime: new Map<string, string>(), // syncLastUpdateTime: new Map<string, string>(),
scoreSetting: { scoreSetting: {

@ -49,13 +49,7 @@ export default class DoubanTheaterAiLoadHandler extends DoubanAbstractLoadHandle
extract.author, extract.author,
extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c) extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c)
)); ));
super.parseAliases(beforeContent, variableMap, extract, context);
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 { support(extract: DoubanSubject): boolean {

@ -150,6 +150,7 @@ ${syncStatus.getHandle() == 0? '...' : i18nHelper.getMessage('110042') + ':' + T
cacheImage: ( settings.cacheImage == null) ? DEFAULT_SETTINGS.cacheImage : settings.cacheImage, cacheImage: ( settings.cacheImage == null) ? DEFAULT_SETTINGS.cacheImage : settings.cacheImage,
cacheHighQuantityImage: ( settings.cacheHighQuantityImage == null) ? DEFAULT_SETTINGS.cacheHighQuantityImage : settings.cacheHighQuantityImage, cacheHighQuantityImage: ( settings.cacheHighQuantityImage == null) ? DEFAULT_SETTINGS.cacheHighQuantityImage : settings.cacheHighQuantityImage,
attachmentPath: (settings.attachmentPath == '' || settings.attachmentPath == null) ? DEFAULT_SETTINGS.attachmentPath : settings.attachmentPath, attachmentPath: (settings.attachmentPath == '' || settings.attachmentPath == null) ? DEFAULT_SETTINGS.attachmentPath : settings.attachmentPath,
attachmentFileName: (settings.attachmentFileName == '' || settings.attachmentFileName == null) ? DEFAULT_SETTINGS.attachmentFileName : settings.attachmentFileName,
templateFile: (settings.movieTemplateFile == '' || settings.movieTemplateFile == null) ? DEFAULT_SETTINGS.movieTemplateFile : settings.movieTemplateFile, templateFile: (settings.movieTemplateFile == '' || settings.movieTemplateFile == null) ? DEFAULT_SETTINGS.movieTemplateFile : settings.movieTemplateFile,
incrementalUpdate: true, incrementalUpdate: true,
syncConditionType: SyncConditionType.ALL, syncConditionType: SyncConditionType.ALL,
@ -427,6 +428,20 @@ ${syncStatus.getHandle() == 0? '...' : i18nHelper.getMessage('110042') + ':' + T
}); });
}) })
.setDisabled(disable); .setDisabled(disable);
new Setting(containerEl)
.setName( i18nHelper.getMessage('121452'))
.setDesc( i18nHelper.getMessage('121453'))
.addSearch(async (search: SearchComponent) => {
new FolderSuggest(this.plugin.app, search.inputEl);
// @ts-ignore
search.setValue(config.attachmentFileName)
// @ts-ignore
.setPlaceholder(i18nHelper.getMessage('121454'))
.onChange(async (value: string) => {
config.attachmentFileName = value;
});
})
.setDisabled(disable);
new Setting(containerEl) new Setting(containerEl)
.setName(i18nHelper.getMessage('121435')) .setName(i18nHelper.getMessage('121435'))

@ -5,7 +5,7 @@ import {moment, Platform, TFile} from "obsidian";
import {i18nHelper} from 'src/org/wanxp/lang/helper'; import {i18nHelper} from 'src/org/wanxp/lang/helper';
import {log} from "src/org/wanxp/utils/Logutil"; import {log} from "src/org/wanxp/utils/Logutil";
import {CheerioAPI, load} from "cheerio"; import {CheerioAPI, load} from "cheerio";
import YamlUtil from "../../../utils/YamlUtil"; import YamlUtil, {TITLE_ALIASES_SPECIAL_CHAR_REG_G} from "../../../utils/YamlUtil";
import { import {
BasicConst, BasicConst,
DataValueType, DataValueType,
@ -47,7 +47,11 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
async parse(extract: T, context: HandleContext): Promise<HandleResult> { async parse(extract: T, context: HandleContext): Promise<HandleResult> {
const template: string = await this.getTemplate(extract, context); const template: string = await this.getTemplate(extract, context);
await this.saveImage(extract, context); const variableMap = this.buildVariableMap(extract, context);
this.parseUserInfo(template, variableMap, extract, context);
this.parseVariable(template, variableMap, extract, context);
await this.saveImage(extract, context, variableMap);
const frontMatterStart: number = template.indexOf(BasicConst.YAML_FRONT_MATTER_SYMBOL, 0); const frontMatterStart: number = template.indexOf(BasicConst.YAML_FRONT_MATTER_SYMBOL, 0);
const frontMatterEnd: number = template.indexOf(BasicConst.YAML_FRONT_MATTER_SYMBOL, frontMatterStart + 1); const frontMatterEnd: number = template.indexOf(BasicConst.YAML_FRONT_MATTER_SYMBOL, frontMatterStart + 1);
let frontMatter = ''; let frontMatter = '';
@ -55,10 +59,6 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
let frontMatterAfter = ''; let frontMatterAfter = '';
let result = ''; let result = '';
const variableMap = this.buildVariableMap(extract, context);
this.parseUserInfo(template, variableMap, extract, context);
this.parseVariable(template, variableMap, extract, context);
if (frontMatterStart > -1 && frontMatterEnd > -1) { if (frontMatterStart > -1 && frontMatterEnd > -1) {
frontMatterBefore = template.substring(0, frontMatterStart); frontMatterBefore = template.substring(0, frontMatterStart);
frontMatter = template.substring(frontMatterStart, frontMatterEnd + 3); frontMatter = template.substring(frontMatterStart, frontMatterEnd + 3);
@ -111,7 +111,19 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
abstract getSupportType(): SupportType; abstract getSupportType(): SupportType;
abstract parseVariable(beforeContent: string, variableMap:Map<string, DataField>, extract: T, context: HandleContext): void; parseVariable(beforeContent: string, variableMap:Map<string, DataField>, extract: T, context: HandleContext): void;
parseAliases(beforeContent: string, variableMap:Map<string, DataField>, extract: T, context: HandleContext): string[] {
// variableMap.set("aliases", new DataField("aliases", DataValueType.array, extract.aliases,
// extract.aliases.map(a=>a
// .trim()
// .replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')
// //replase multiple _ to single _
// .replace(/_+/g, '_')
// .replace(/^_/, '')
// .replace(/_$/, '')
// )));
}
abstract support(extract: DoubanSubject): boolean; abstract support(extract: DoubanSubject): boolean;
@ -522,43 +534,69 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
} }
} }
private async saveImage(extract: T, context: HandleContext) { private async saveImage(extract: T, context: HandleContext, variableMap : Map<string, DataField>) {
const {syncConfig} = context; const {syncConfig} = context;
if (!extract.image || (syncConfig && !syncConfig.cacheImage) || !context.settings.cacheImage) { if (!extract.image || (syncConfig && !syncConfig.cacheImage) || !context.settings.cacheImage) {
return; return;
} }
const image = extract.image; const image = extract.image;
const filename = image.split('/').pop();
let folder = syncConfig? syncConfig.attachmentPath : context.settings.attachmentPath; let folder = syncConfig? syncConfig.attachmentPath : context.settings.attachmentPath;
if (!folder) { if (!folder) {
folder = DEFAULT_SETTINGS.attachmentPath; folder = DEFAULT_SETTINGS.attachmentPath;
} }
folder = this.parsePartText(folder, extract, context) folder = this.parsePartPath(folder, extract, context, variableMap)
let fileName = syncConfig? syncConfig.attachmentFileName : context.settings.attachmentFileName;
const referHeaders = {'referer': image}; if (!fileName) {
fileName = DEFAULT_SETTINGS.attachmentFileName;
}
let fileNameSuffix = image ? image.substring(image.lastIndexOf('.')) : '.jpg';
if (fileNameSuffix && fileNameSuffix.length > 10) {
fileNameSuffix = '.jpg';
}
fileName = this.parsePartPath(fileName, extract, context, variableMap)
fileName = fileName + fileNameSuffix;
// const referHeaders = {'referer': image};
const referHeaders = context.settings.loginHeadersContent ? JSON.parse(context.settings.loginHeadersContent) : {};
if ((syncConfig ? syncConfig.cacheHighQuantityImage : context.settings.cacheHighQuantityImage) && context.userComponent.isLogin()) { if ((syncConfig ? syncConfig.cacheHighQuantityImage : context.settings.cacheHighQuantityImage) && context.userComponent.isLogin()) {
try { try {
const fileNameSpilt = filename.split('.'); const fileNameSpilt = fileName.split('.');
const highFilename = fileNameSpilt.first() + '.jpg'; const highFilename = fileNameSpilt.first() + '.jpg';
const highImage = this.getHighQuantityImageUrl(highFilename); const highImage = this.getHighQuantityImageUrl(highFilename);
const resultValue = await this.handleImage(highImage, folder, highFilename, context, false, referHeaders); const resultValue = await this.handleImage(highImage, folder, highFilename, context, false, referHeaders);
if (resultValue && resultValue.success) { if (resultValue && resultValue.success) {
extract.image = resultValue.filepath; extract.image = resultValue.filepath;
this.initImageVariableMap(extract, context, variableMap);
return; return;
} }
}catch (e) { }catch (e) {
console.error(e); console.error(e);
console.error('下载高清封面失败,将会使用普通封面') console.error('下载高清封面失败,将会使用普通封面')
} }
} }
const resultValue = await this.handleImage(image, folder, filename, context, true, referHeaders); const resultValue = await this.handleImage(image, folder, fileName, context, true, referHeaders);
if (resultValue && resultValue.success) { if (resultValue && resultValue.success) {
extract.image = resultValue.filepath; extract.image = resultValue.filepath;
this.initImageVariableMap(extract, context, variableMap);
} }
} }
private initImageVariableMap(extract: T, context: HandleContext, variableMap : Map<string, DataField>) {
variableMap.set(DoubanParameterName.IMAGE_URL, new DataField(
DoubanParameterName.IMAGE_URL,
DataValueType.url,
extract.imageUrl,
extract.imageUrl
));
variableMap.set(DoubanParameterName.IMAGE, new DataField(
DoubanParameterName.IMAGE,
DataValueType.path,
extract.image,
extract.image
));
}
private async handleImage(image: string, folder: string, filename: string, context: HandleContext, showError: boolean, headers?: any) { private async handleImage(image: string, folder: string, filename: string, context: HandleContext, showError: boolean, headers?: any) {
//只有在桌面版且开启了图片上传才会使用PicGo并且开启图床功能 //只有在桌面版且开启了图片上传才会使用PicGo并且开启图床功能
if (context.settings.pictureBedFlag && Platform.isDesktopApp) { if (context.settings.pictureBedFlag && Platform.isDesktopApp) {

@ -28,7 +28,7 @@ export default class DoubanBookLoadHandler extends DoubanAbstractLoadHandler<Dou
return `https://book.douban.com/subject/${id}/`; return `https://book.douban.com/subject/${id}/`;
} }
parseVariable(beforeContent: string, variableMap:Map<string, DataField>, extract: DoubanBookSubject, context: HandleContext, textMode: TemplateTextMode): void { parseVariable(beforeContent: string, variableMap:Map<string, DataField>, extract: DoubanBookSubject, context: HandleContext): void {
variableMap.set(DoubanBookParameter.author, new DataField(DoubanBookParameter.author, variableMap.set(DoubanBookParameter.author, new DataField(DoubanBookParameter.author,
DataValueType.array, extract.author, extract.author.map(this.handleSpecialAuthorName))); DataValueType.array, extract.author, extract.author.map(this.handleSpecialAuthorName)));
variableMap.set(DoubanBookParameter.translator, new DataField(DoubanBookParameter.translator, variableMap.set(DoubanBookParameter.translator, new DataField(DoubanBookParameter.translator,

@ -9,6 +9,7 @@ import {UserStateSubject} from "../model/UserStateSubject";
import {moment} from "obsidian"; import {moment} from "obsidian";
import {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"; import {DataField} from "../../../utils/model/DataField";
import {b} from "@shikijs/engine-javascript/dist/shared/engine-javascript.BnuFKbIS";
export default class DoubanGameLoadHandler extends DoubanAbstractLoadHandler<DoubanGameSubject> { export default class DoubanGameLoadHandler extends DoubanAbstractLoadHandler<DoubanGameSubject> {
@ -28,7 +29,7 @@ export default class DoubanGameLoadHandler extends DoubanAbstractLoadHandler<Dou
} }
parseVariable(beforeContent: string, variableMap:Map<string, DataField>, extract: DoubanGameSubject, context: HandleContext): void { parseVariable(beforeContent: string, variableMap:Map<string, DataField>, 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, '_')))); super.parseAliases(beforeContent, variableMap, extract, context);
} }
support(extract: DoubanSubject): boolean { support(extract: DoubanSubject): boolean {

@ -51,13 +51,7 @@ export default class DoubanMovieLoadHandler extends DoubanAbstractLoadHandler<Do
extract.author, extract.author,
extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c) extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c)
)); ));
super.parseAliases(beforeContent, variableMap, extract, context);
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 { support(extract: DoubanSubject): boolean {

@ -39,13 +39,7 @@ export class DoubanTeleplayLoadHandler extends DoubanAbstractLoadHandler<DoubanT
extract.author, extract.author,
extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c) extract.author.map(SchemaOrg.getPersonName).map(name => super.getPersonName(name, context)).filter(c => c)
)); ));
super.parseAliases(beforeContent, variableMap, extract, context);
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 { support(extract: DoubanSubject): boolean {

@ -54,7 +54,15 @@ export default class DoubanTheaterLoadHandler extends DoubanAbstractLoadHandler<
"aliases", "aliases",
DataValueType.array, DataValueType.array,
extract.aliases, extract.aliases,
extract.aliases.map(a => a.replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')) extract.aliases.map(a => a
.trim()
.replace(TITLE_ALIASES_SPECIAL_CHAR_REG_G, '_')
//replace multiple _ to single _
.replace(/_+/g, '_')
.replace(/^_/, '')
.replace(/_$/, '')
)
)); ));
} }

@ -31,7 +31,7 @@ class DoubanFuzzySuggester extends FuzzySuggestModal<DoubanSearchResultSubject>
private searchItem:string; private searchItem:string;
constructor(plugin: DoubanPlugin, context: HandleContext, searchItem:string) { constructor(plugin: DoubanPlugin, context: HandleContext, searchItem:string) {
super(app); super(plugin.app);
this.plugin = plugin; this.plugin = plugin;
this.context = context; this.context = context;
this.searchItem = searchItem; this.searchItem = searchItem;

@ -223,7 +223,8 @@ export function constructAttachmentFileSettingsUI(containerEl: HTMLElement, mana
}else { }else {
new Setting(containerEl).then(createFolderSelectionSetting({containerEl: containerEl, name: '121432', desc: '121433', placeholder: null, key: null, manager: manager})); new Setting(containerEl).then(createFolderSelectionSetting({containerEl: containerEl, name: '121432', desc: '121433', placeholder: null, key: null, manager: manager}));
new Setting(containerEl).then(createFolderSelectionSettingInput({containerEl: containerEl, name: null, desc: null, placeholder: '121434', key: 'attachmentPath', manager: manager})); new Setting(containerEl).then(createFolderSelectionSettingInput({containerEl: containerEl, name: null, desc: null, placeholder: '121434', key: 'attachmentPath', manager: manager}));
new Setting(containerEl).then(createFolderSelectionSetting({containerEl: containerEl, name: '121452', desc: '121453', placeholder: null, key: null, manager: manager}));
new Setting(containerEl).then(createFolderSelectionSettingInput({containerEl: containerEl, name: null, desc: null, placeholder: '121454', key: 'attachmentFileName', manager: manager}));
; ;
} }

@ -33,6 +33,7 @@ export interface DoubanPluginSetting {
cacheImage: boolean, cacheImage: boolean,
cacheHighQuantityImage: boolean, cacheHighQuantityImage: boolean,
attachmentPath: string, attachmentPath: string,
attachmentFileName: string,
pictureBedFlag: boolean pictureBedFlag: boolean
pictureBedType: string; pictureBedType: string;
pictureBedSetting: PictureBedSetting; pictureBedSetting: PictureBedSetting;

@ -11,6 +11,9 @@ import {i18nHelper} from "../../../lang/helper";
import {DoubanTeleplaySyncHandler} from "./DoubanTeleplaySyncHandler"; import {DoubanTeleplaySyncHandler} from "./DoubanTeleplaySyncHandler";
import {SyncConditionType} from "../../../constant/Constsant"; import {SyncConditionType} from "../../../constant/Constsant";
import {DoubanGameSyncHandler} from "./DoubanGameSyncHandler"; import {DoubanGameSyncHandler} from "./DoubanGameSyncHandler";
import {DataField} from "../../../utils/model/DataField";
import {VariableUtil} from "../../../utils/VariableUtil";
import {FileUtil} from "../../../utils/FileUtil";
export default class SyncHandler { export default class SyncHandler {
private app: App; private app: App;
@ -101,7 +104,7 @@ export default class SyncHandler {
`; `;
}else { }else {
// @ts-ignore // @ts-ignore
details+= `${value.id}-[[${value.title}]]: ${i18nHelper.getMessage(value.status)} details+= `${value.id}-[[${FileUtil.replaceSpecialCharactersForFileName(value.title)}]]: ${i18nHelper.getMessage(value.status)}
`; `;
} }

@ -13,6 +13,7 @@ export interface SyncConfig {
cacheHighQuantityImage:boolean; cacheHighQuantityImage:boolean;
attachmentPath: string; attachmentPath: string;
attachmentFileName: string;
templateFile: string; templateFile: string;
incrementalUpdate: boolean; incrementalUpdate: boolean;
} }

@ -248,12 +248,16 @@ PS: This file could be delete if you want to.
'121410': `Search Default Type`, '121410': `Search Default Type`,
'121411': `Search defuault type when open command palette 'search douban and create file'`, '121411': `Search defuault type when open command palette 'search douban and create file'`,
'121430': `Save Attachment File`, '121430': `Save Attachment(Picture) File`,
'121431': `Save attachment file to local disk, such as image ? If you do not enable this feature, it will not show cover image in note`, '121431': `Save attachment file to local disk, such as image ? If you do not enable this feature, it will not show cover image in note`,
'121432': `Attachment folder`, '121432': `Attachment(Picture) folder`,
'121433': `Attachment file created from Obsidian-Douban will be placed in this folder, '121433': `Attachment file created from Obsidian-Douban will be placed in this folder,
If blank, they will be created by default name. support all basic template variables. example: {{type}}/assets`, If blank, they will be created by default name. support all basic template variables. example: {{type}}/assets`,
'121434': `assets`, '121434': `assets`,
'121452': `Attachment(Picture) File Name`,
'121453': `Attachment file name, If blank, they will be created by default name '{{title}}'. support all basic template variables. example: {{type}}-{{title}}`,
'121454': `{{title}}`,
'121435': `Save High Definition Cover`, '121435': `Save High Definition Cover`,
'121436': `High Definition Cover looks better but it will take more space, and you must login douban in this plugin`, '121436': `High Definition Cover looks better but it will take more space, and you must login douban in this plugin`,
'121437': `Please login first, Then this function could be enable`, '121437': `Please login first, Then this function could be enable`,
@ -330,6 +334,8 @@ PS: This file could be delete if you want to.
'140102': `subject type is different, will not sync this, chosen sync type is {0} but this {1} subject type is {2}`, '140102': `subject type is different, will not sync this, chosen sync type is {0} but this {1} subject type is {2}`,
'130105': `Can not use Douban this time, Please try again after 12 hour or 24 hour. Or you can reset your connection `, '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 `, '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 `,
'130404': `404 Url Not Found`,
'130107': `Can not find array setting for {1} in {0} , Please add it in array settings`, '130107': `Can not find array setting for {1} in {0} , Please add it in array settings`,
'130108': `Redirect times too much, please check your network or proxy`, '130108': `Redirect times too much, please check your network or proxy`,

@ -1,4 +1,5 @@
//简体中文 //简体中文
//简体中文
import {SyncItemStatus} from "../../constant/Constsant"; import {SyncItemStatus} from "../../constant/Constsant";
@ -302,9 +303,12 @@ export default {
'121430': `保存图片附件`, '121430': `保存图片附件`,
'121431': `导入数据会同步保存图片附件到本地文件夹, 如电影封面,书籍封面。如果需要显示封面,请保持开启该功能。`, '121431': `导入数据会同步保存图片附件到本地文件夹, 如电影封面,书籍封面。如果需要显示封面,请保持开启该功能。`,
'121432': `附件存放位置`, '121432': `附件(图片)存放位置`,
'121433': `保存的附件将会存放至该文件夹中. 如果为空, 笔记将会存放到默认位置(assets), 且支持所有'通用'的参数。如:{{myType}}/attachments`, '121433': `保存的附件将会存放至该文件夹中. 如果为空, 笔记将会存放到默认位置(assets), 且支持所有'通用'的参数。如:{{myType}}/attachments`,
'121452': `附件(图片)文件名`,
'121453': `附件的文件名模板, 支持所有'通用'的参数作为名称(如:{{type}}-{{title}}),且支持路径, 比如: '{{myType}}/附件-{{title}}'。如果为空, 则使用默认名称{{title}}`,
'121434': `assets`, '121434': `assets`,
'121454': `{{title}}`,
'121435': `保存高清封面`, '121435': `保存高清封面`,
'121436': `高清封面图片质量更高清晰度更好, 需要您在此插件 登录豆瓣 才能生效, 若未登录则默认使用低精度版本封面`, '121436': `高清封面图片质量更高清晰度更好, 需要您在此插件 登录豆瓣 才能生效, 若未登录则默认使用低精度版本封面`,
'121437': `登录后此功能才会生效`, '121437': `登录后此功能才会生效`,

@ -282,7 +282,7 @@ export default class DoubanPlugin extends Plugin {
this.settingsManager = new SettingsManager(app, this); this.settingsManager = new SettingsManager(this.app, this);
// this.fetchOnlineData(this.settingsManager); // this.fetchOnlineData(this.settingsManager);
this.userComponent = new UserComponent(this.settingsManager); this.userComponent = new UserComponent(this.settingsManager);
this.netFileHandler = new NetFileHandler(this.fileHandler); this.netFileHandler = new NetFileHandler(this.fileHandler);

@ -19,15 +19,25 @@ export default class NetFileHandler {
const filePath:string = FileUtil.join(folder, filename); const filePath:string = FileUtil.join(folder, filename);
return HttpUtil.httpRequestBuffer(url, headers, context.plugin.settingsManager) return HttpUtil.httpRequestBuffer(url, headers, context.plugin.settingsManager)
.then((response) => { .then((response) => {
if (response.status == 404) {
throw new Error(i18nHelper.getMessage('130404'));
}
if (response.status == 403) { if (response.status == 403) {
throw new Error(i18nHelper.getMessage('130106')); throw new Error(i18nHelper.getMessage('130106'));
} }
return response.textArrayBuffer; return response.textArrayBuffer;
}) })
.then((buffer) => { .then((buffer) => {
if (!buffer || buffer.byteLength == 0) {
return 0;
}
this.fileHandler.creatAttachmentWithData(filePath, buffer); this.fileHandler.creatAttachmentWithData(filePath, buffer);
}).then(() => { return buffer.byteLength;
return {success: true, error: '', filepath: filePath}; }).then((size) => {
if (size == 0) {
return {success: false, size: size, error: '文件唯恐', filepath: null};
}
return {success: true, size: size, error: '', filepath: filePath};
}) })
.catch(e => { .catch(e => {
if (showError) { if (showError) {

@ -96,7 +96,7 @@ export class VariableUtil {
} else if(value instanceof DataField) { } else if(value instanceof DataField) {
content = this.replaceDataField(variable, value, content, settingManager, targetType); content = this.replaceDataField(variable, value, content, settingManager, targetType);
} else { } else {
content = this.replaceString(variable, value, content, settingManager, targetType); content = this.replaceString(variable, value, value, content, settingManager, targetType);
} }
return content; return content;
} }
@ -135,12 +135,12 @@ export class VariableUtil {
return `{{${key}}}`; return `{{${key}}}`;
} }
static replaceString(variable: FieldVariable, value: any, content: string, settingManager:SettingsManager, targetType: TargetType): string { static replaceString(variable: FieldVariable, valueField: DataField, value: any, content: string, settingManager:SettingsManager, targetType: TargetType): string {
if (!content) { if (!content) {
return content; return content;
} }
let strValue = value? value.toString() : ""; let strValue = value? value.toString() : "";
return content.replaceAll(variable.variable, this.handleText(strValue, targetType)); return content.replaceAll(variable.variable, this.handleText(strValue, targetType, valueField));
} }
/** /**
@ -220,19 +220,19 @@ export class VariableUtil {
} }
switch (value.type) { switch (value.type) {
case DataValueType.string: case DataValueType.string:
content = this.replaceString(variable, value.value, content, settingManager, targetType); content = this.replaceString(variable, value, value.value, content, settingManager, targetType);
break; break;
case DataValueType.number: case DataValueType.number:
content = content.replaceAll(variableStr, this.handleText(value.value.toString(), targetType)); content = content.replaceAll(variableStr, this.handleText(value.value.toString(), targetType, value));
break; break;
case DataValueType.date: case DataValueType.date:
content = content.replaceAll(variableStr, this.handleText(value.value, targetType)); content = content.replaceAll(variableStr, this.handleText(value.value, targetType, value));
break; break;
case DataValueType.array: case DataValueType.array:
content = this.replaceArray(variable, value.value, content, settingManager, targetType); content = this.replaceArray(variable, value.value, content, settingManager, targetType);
break; break;
default: default:
content = content.replaceAll(variableStr, this.handleText(value.value, targetType)); content = content.replaceAll(variableStr, this.handleText(value.value, targetType, value));
break; break;
} }
@ -277,9 +277,9 @@ export class VariableUtil {
return map; return map;
} }
private static handleText(v: string, targetType: TargetType) { private static handleText(v: string, targetType: TargetType, dataField: DataField = null): string {
if (targetType === 'yml_text') { if (targetType === 'yml_text') {
return YamlUtil.handleText(v); return YamlUtil.handleText(v, dataField);
} }
if (targetType === 'text') { if (targetType === 'text') {
return v; return v;

@ -1,5 +1,7 @@
export default class YamlUtil { import {DataField} from "./model/DataField";
import {DataValueType} from "../constant/Constsant";
export default class YamlUtil {
public static hasSpecialChar(str: string): boolean { public static hasSpecialChar(str: string): boolean {
return SPECIAL_CHAR_REG.test(str); return SPECIAL_CHAR_REG.test(str);
@ -14,15 +16,20 @@ export default class YamlUtil {
return '"' + text + '"'; return '"' + text + '"';
} }
public static handleText(text: string) { public static handleText(text: string, dataField: DataField = null): string {
return YamlUtil.hasSpecialChar(text) if (YamlUtil.hasSpecialChar(text)) {
? YamlUtil.handleSpecialChar(text.replaceAll('"', '\\"')) text = text.replaceAll('"', '\\"')
.replaceAll(/\s+/g, ' ') .replaceAll(/\s+/g, ' ')
.replaceAll('\n', '。') .replaceAll('\n', '。')
.replaceAll('。。', '。') .replaceAll('。。', '。')
.replace(/^" /, '"') // Remove leading " .replace(/^" /, '"') // Remove leading "
.replace(/ "$/, '"') // Remove trailing " .replace(/ "$/, '"') // Remove trailing "
: text; if (dataField && dataField.type === DataValueType.date) {
return text;
}
YamlUtil.handleSpecialChar(text);
}
return text;
} }
} }