111 lines
3.4 KiB
TypeScript
111 lines
3.4 KiB
TypeScript
/* 文件:markdown/heading.ts — 标题(h1..h6)解析与锚点生成逻辑。 */
|
||
|
||
import { Tokens, MarkedExtension } from "marked";
|
||
import { Extension } from "./extension";
|
||
import AssetsManager from "src/assets";
|
||
import { ExpertSettings } from "src/expert-settings";
|
||
import { wxWidget } from 'src/wechat/weixin-api';
|
||
|
||
export class HeadingRenderer extends Extension {
|
||
index = [0, 0, 0, 0];
|
||
expertSettings: ExpertSettings;
|
||
headingSettings: any[]
|
||
|
||
async prepare() {
|
||
this.index = [0, 0, 0, 0];
|
||
this.expertSettings = AssetsManager.getInstance().expertSettings;
|
||
this.headingSettings = [undefined, undefined, undefined, undefined];
|
||
if (!this.expertSettings.render) {
|
||
return;
|
||
}
|
||
if (this.expertSettings.render.h1) {
|
||
this.headingSettings[1] = this.expertSettings.render.h1;
|
||
}
|
||
if (this.expertSettings.render.h2) {
|
||
this.headingSettings[2] = this.expertSettings.render.h2;
|
||
}
|
||
if (this.expertSettings.render.h3) {
|
||
this.headingSettings[3] = this.expertSettings.render.h3;
|
||
}
|
||
}
|
||
|
||
async renderWithTemplate(token: Tokens.Heading, template: string) {
|
||
const content = await this.marked.parseInline(token.text);
|
||
return template.replace('{content}', content);
|
||
}
|
||
|
||
async renderWithWidgetId(token: Tokens.Heading, widgetId: number) {
|
||
const authkey = this.settings.authKey;
|
||
const content = await this.marked.parseInline(token.text);
|
||
const params = JSON.stringify({
|
||
id: `${widgetId}`,
|
||
title: content,
|
||
});
|
||
return await wxWidget(authkey, params);
|
||
}
|
||
|
||
async renderWithWidget(token: Tokens.Heading, widgetId: number, counter: boolean|undefined, len: number|undefined, style: object|undefined = undefined) {
|
||
const authkey = this.settings.authKey;
|
||
let title = token.text;
|
||
if (counter === undefined) {
|
||
counter = false;
|
||
}
|
||
if (len === undefined) {
|
||
len = 1;
|
||
}
|
||
if (style === undefined) {
|
||
style = new Map<string, string>();
|
||
}
|
||
if (counter) {
|
||
title = `${this.index[token.depth]}`;
|
||
if (title.length < len) {
|
||
title = title.padStart(len, '0');
|
||
}
|
||
}
|
||
const content = await this.marked.parseInline(token.text);
|
||
const params = JSON.stringify({
|
||
id: `${widgetId}`,
|
||
title,
|
||
style,
|
||
content: '<p>' + content + '</p>',
|
||
});
|
||
return await wxWidget(authkey, params);
|
||
}
|
||
|
||
markedExtension(): MarkedExtension {
|
||
return {
|
||
async: true,
|
||
walkTokens: async (token: Tokens.Generic) => {
|
||
if (token.type !== 'heading') {
|
||
return;
|
||
}
|
||
|
||
const setting = this.headingSettings[token.depth];
|
||
this.index[token.depth] += 1;
|
||
if (setting) {
|
||
if (typeof setting === 'string') {
|
||
token.html = await this.renderWithTemplate(token as Tokens.Heading, setting);
|
||
}
|
||
else if (typeof setting === 'number') {
|
||
token.html = await this.renderWithWidgetId(token as Tokens.Heading, setting);
|
||
}
|
||
else {
|
||
const { id, counter, len, style } = setting;
|
||
token.html = await this.renderWithWidget(token as Tokens.Heading, id, counter, len, style);
|
||
}
|
||
return;
|
||
}
|
||
|
||
const body = await this.marked.parseInline(token.text);
|
||
token.html = `<h${token.depth}>${body}</h${token.depth}>`;
|
||
},
|
||
extensions: [{
|
||
name: 'heading',
|
||
level: 'block',
|
||
renderer: (token: Tokens.Generic) => {
|
||
return token.html;
|
||
},
|
||
}]
|
||
}
|
||
}
|
||
} |