/* 文件: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(); } 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: '

' + content + '

', }); 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 = `${body}`; }, extensions: [{ name: 'heading', level: 'block', renderer: (token: Tokens.Generic) => { return token.html; }, }] } } }