237 lines
9.3 KiB
TypeScript
237 lines
9.3 KiB
TypeScript
/**
|
||
* 文件:settings.ts
|
||
* 作用:插件全局设置模型(单例)与序列化/反序列化逻辑。
|
||
* 内容:
|
||
* - 默认值初始化
|
||
* - loadSettings: 反序列化存储数据并兼容旧字段
|
||
* - allSettings: 统一导出用于持久化
|
||
* - 会员 / 授权信息校验(isAuthKeyVaild)
|
||
* - 批量发布预设 / 图片处理 / 样式控制等选项
|
||
*/
|
||
|
||
import { wxKeyInfo } from './wechat/weixin-api';
|
||
|
||
export class NMPSettings {
|
||
defaultStyle: string;
|
||
defaultHighlight: string;
|
||
showStyleUI: boolean;
|
||
linkStyle: string;
|
||
embedStyle: string;
|
||
lineNumber: boolean;
|
||
authKey: string;
|
||
useCustomCss: boolean;
|
||
customCSSNote: string;
|
||
expertSettingsNote: string;
|
||
wxInfo: {name:string, appid:string, secret:string}[];
|
||
math: string;
|
||
expireat: Date | null = null;
|
||
isVip: boolean = false;
|
||
baseCSS: string;
|
||
watermark: string;
|
||
useFigcaption: boolean;
|
||
excalidrawToPNG: boolean;
|
||
isLoaded: boolean = false;
|
||
enableEmptyLine: boolean = false;
|
||
needOpenComment: boolean = true;
|
||
enableMarkdownImageToWikilink: boolean = true; // 自动将  转为 ![[file.ext]]
|
||
// gallery 相关配置:根目录前缀 & 选取图片数量
|
||
galleryPrePath: string;
|
||
galleryNumPic: number;
|
||
// 无图片时的默认封面(wikilink 或 URL 均可)
|
||
defaultCoverPic: string;
|
||
// 是否忽略 frontmatter 中的 cover/image 字段(用户要求:封面不使用 frontmatter image)
|
||
ignoreFrontmatterImage: boolean;
|
||
// 批量发布筛选条件预设
|
||
batchPublishPresets: Array<{
|
||
name: string;
|
||
tags?: string[];
|
||
folders?: string[];
|
||
filenameKeywords?: string[];
|
||
}>;
|
||
// 切图相关配置
|
||
sliceImageSavePath: string; // 切图保存路径
|
||
sliceImageWidth: number; // 切图宽度(像素)
|
||
sliceImageAspectRatio: string; // 横竖比例,格式 "3:4"
|
||
xhsPreviewWidth: number; // 小红书预览宽度(像素)
|
||
|
||
private static instance: NMPSettings;
|
||
|
||
// 静态方法,用于获取实例
|
||
public static getInstance(): NMPSettings {
|
||
if (!NMPSettings.instance) {
|
||
NMPSettings.instance = new NMPSettings();
|
||
}
|
||
return NMPSettings.instance;
|
||
}
|
||
|
||
private constructor() {
|
||
this.defaultStyle = 'obsidian-light';
|
||
this.defaultHighlight = '默认';
|
||
this.showStyleUI = true;
|
||
this.linkStyle = 'inline';
|
||
this.embedStyle = 'content';
|
||
this.lineNumber = true;
|
||
this.useCustomCss = false;
|
||
this.authKey = '';
|
||
this.wxInfo = [];
|
||
this.math = 'latex';
|
||
this.baseCSS = '';
|
||
this.watermark = '';
|
||
this.useFigcaption = false;
|
||
this.customCSSNote = '';
|
||
this.excalidrawToPNG = false;
|
||
this.expertSettingsNote = '';
|
||
this.enableEmptyLine = false;
|
||
this.needOpenComment = true;
|
||
this.enableMarkdownImageToWikilink = true;
|
||
// 默认值:用户原先硬编码路径 & 前 2 张
|
||
this.galleryPrePath = '/Users/gavin/myweb/static';
|
||
this.galleryNumPic = 2;
|
||
// 默认封面:使用当前笔记同目录下的 cover.png (若存在会被后续流程正常解析;不存在则无效但可被用户覆盖)
|
||
this.defaultCoverPic = 'cover.png';
|
||
this.ignoreFrontmatterImage = false;
|
||
// 批量发布预设
|
||
this.batchPublishPresets = [
|
||
{
|
||
name: '篆刻文章',
|
||
tags: ['篆刻'],
|
||
folders: [],
|
||
filenameKeywords: []
|
||
}
|
||
];
|
||
// 切图配置默认值(使用 vault 相对路径)
|
||
this.sliceImageSavePath = 'xhs-images';
|
||
this.sliceImageWidth = 1080;
|
||
this.sliceImageAspectRatio = '3:4';
|
||
this.xhsPreviewWidth = 540;
|
||
}
|
||
|
||
resetStyelAndHighlight() {
|
||
this.defaultStyle = 'obsidian-light';
|
||
this.defaultHighlight = '默认';
|
||
}
|
||
|
||
public static loadSettings(data: any) {
|
||
if (!data) return;
|
||
|
||
const {
|
||
defaultStyle,
|
||
defaultHighlight,
|
||
showStyleUI,
|
||
linkStyle,
|
||
embedStyle,
|
||
lineNumber,
|
||
authKey,
|
||
wxInfo,
|
||
math,
|
||
useCustomCss,
|
||
baseCSS,
|
||
watermark,
|
||
useFigcaption,
|
||
customCSSNote,
|
||
excalidrawToPNG,
|
||
expertSettingsNote,
|
||
ignoreEmptyLine,
|
||
enableMarkdownImageToWikilink,
|
||
needOpenComment,
|
||
galleryPrePath,
|
||
galleryNumPic,
|
||
defaultCoverPic,
|
||
ignoreFrontmatterImage,
|
||
batchPublishPresets = [],
|
||
sliceImageSavePath,
|
||
sliceImageWidth,
|
||
sliceImageAspectRatio,
|
||
xhsPreviewWidth
|
||
} = data;
|
||
|
||
const settings = NMPSettings.getInstance();
|
||
if (defaultStyle) settings.defaultStyle = defaultStyle;
|
||
if (defaultHighlight) settings.defaultHighlight = defaultHighlight;
|
||
if (showStyleUI !== undefined) settings.showStyleUI = showStyleUI;
|
||
if (linkStyle) settings.linkStyle = linkStyle;
|
||
if (embedStyle) settings.embedStyle = embedStyle;
|
||
if (lineNumber !== undefined) settings.lineNumber = lineNumber;
|
||
if (authKey) settings.authKey = authKey;
|
||
if (wxInfo) settings.wxInfo = wxInfo;
|
||
if (math) settings.math = math;
|
||
if (useCustomCss !== undefined) settings.useCustomCss = useCustomCss;
|
||
if (baseCSS) settings.baseCSS = baseCSS;
|
||
if (watermark) settings.watermark = watermark;
|
||
if (useFigcaption !== undefined) settings.useFigcaption = useFigcaption;
|
||
if (customCSSNote) settings.customCSSNote = customCSSNote;
|
||
if (excalidrawToPNG !== undefined) settings.excalidrawToPNG = excalidrawToPNG;
|
||
if (expertSettingsNote) settings.expertSettingsNote = expertSettingsNote;
|
||
if (ignoreEmptyLine !== undefined) settings.enableEmptyLine = !!ignoreEmptyLine;
|
||
if (needOpenComment !== undefined) settings.needOpenComment = !!needOpenComment;
|
||
if (enableMarkdownImageToWikilink !== undefined) settings.enableMarkdownImageToWikilink = !!enableMarkdownImageToWikilink;
|
||
if (galleryPrePath) settings.galleryPrePath = galleryPrePath;
|
||
if (galleryNumPic !== undefined && Number.isFinite(galleryNumPic)) settings.galleryNumPic = Math.max(1, parseInt(galleryNumPic));
|
||
if (defaultCoverPic !== undefined) settings.defaultCoverPic = String(defaultCoverPic).trim();
|
||
if (ignoreFrontmatterImage !== undefined) settings.ignoreFrontmatterImage = !!ignoreFrontmatterImage;
|
||
if (Array.isArray(batchPublishPresets)) settings.batchPublishPresets = batchPublishPresets;
|
||
if (sliceImageSavePath) settings.sliceImageSavePath = sliceImageSavePath;
|
||
if (sliceImageWidth !== undefined && Number.isFinite(sliceImageWidth)) settings.sliceImageWidth = Math.max(100, parseInt(sliceImageWidth));
|
||
if (sliceImageAspectRatio) settings.sliceImageAspectRatio = sliceImageAspectRatio;
|
||
if (xhsPreviewWidth !== undefined && Number.isFinite(xhsPreviewWidth)) {
|
||
settings.xhsPreviewWidth = Math.max(100, parseInt(xhsPreviewWidth));
|
||
}
|
||
|
||
settings.getExpiredDate();
|
||
settings.isLoaded = true;
|
||
}
|
||
|
||
public static allSettings() {
|
||
const settings = NMPSettings.getInstance();
|
||
return {
|
||
'defaultStyle': settings.defaultStyle,
|
||
'defaultHighlight': settings.defaultHighlight,
|
||
'showStyleUI': settings.showStyleUI,
|
||
'linkStyle': settings.linkStyle,
|
||
'embedStyle': settings.embedStyle,
|
||
'lineNumber': settings.lineNumber,
|
||
'authKey': settings.authKey,
|
||
'wxInfo': settings.wxInfo,
|
||
'math': settings.math,
|
||
'useCustomCss': settings.useCustomCss,
|
||
'baseCSS': settings.baseCSS,
|
||
'watermark': settings.watermark,
|
||
'useFigcaption': settings.useFigcaption,
|
||
'customCSSNote': settings.customCSSNote,
|
||
'excalidrawToPNG': settings.excalidrawToPNG,
|
||
'expertSettingsNote': settings.expertSettingsNote,
|
||
'ignoreEmptyLine': settings.enableEmptyLine,
|
||
'needOpenComment': settings.needOpenComment,
|
||
'enableMarkdownImageToWikilink': settings.enableMarkdownImageToWikilink,
|
||
'galleryPrePath': settings.galleryPrePath,
|
||
'galleryNumPic': settings.galleryNumPic,
|
||
'defaultCoverPic': settings.defaultCoverPic,
|
||
'ignoreFrontmatterImage': settings.ignoreFrontmatterImage,
|
||
'batchPublishPresets': settings.batchPublishPresets,
|
||
'sliceImageSavePath': settings.sliceImageSavePath,
|
||
'sliceImageWidth': settings.sliceImageWidth,
|
||
'sliceImageAspectRatio': settings.sliceImageAspectRatio,
|
||
'xhsPreviewWidth': settings.xhsPreviewWidth,
|
||
}
|
||
}
|
||
|
||
getExpiredDate() {
|
||
if (this.authKey.length == 0) return;
|
||
wxKeyInfo(this.authKey).then((res) => {
|
||
if (res.status == 200) {
|
||
if (res.json.vip) {
|
||
this.isVip = true;
|
||
}
|
||
this.expireat = new Date(res.json.expireat);
|
||
}
|
||
})
|
||
}
|
||
|
||
isAuthKeyVaild() {
|
||
if (this.authKey.length == 0) return false;
|
||
if (this.isVip) return true;
|
||
if (this.expireat == null) return false;
|
||
return this.expireat > new Date();
|
||
}
|
||
}
|