import loader from "../core/loaders/text.ts";import { merge } from "../core/utils/object.ts";import { rehypeRaw, rehypeSanitize, rehypeStringify, remarkGfm, remarkParse, remarkRehype, unified,} from "../deps/remark.ts";
import type Site from "../core/site.ts";import type { Engine, Helper } from "../core/renderer.ts";import type { Page } from "../core/file.ts";import type { PluggableList, RehypeOptions } from "../deps/remark.ts";
export interface Options { extensions?: string[];
remarkPlugins?: PluggableList;
rehypeOptions?: RehypeOptions;
rehypePlugins?: PluggableList;
sanitize?: boolean;
useDefaultPlugins?: boolean;}
export const defaults: Options = { extensions: [".md"], sanitize: false, useDefaultPlugins: true, rehypeOptions: { allowDangerousHtml: true, },};
const remarkDefaultPlugins = [ remarkGfm,];
export class MarkdownEngine implements Engine { engine: unified.Processor;
constructor(engine: unified.Processor) { this.engine = engine; }
deleteCache() {}
async render( content: string, data?: Record<string, unknown>, filename?: string, ): Promise<string> { const page = data?.page as Page | undefined; return (await this.engine.process({ value: content, data: page?.data, path: filename, })).toString(); }
renderComponent( content: string, data?: Record<string, unknown>, filename?: string, ): string { const page = data?.page as Page | undefined; return this.engine.processSync({ value: content, data: page?.data, path: filename, }).toString(); }
addHelper() {}}
export default function (userOptions?: Options) { const options = merge(defaults, userOptions);
return function (site: Site) { const plugins = [];
plugins.push(remarkParse);
if (options.useDefaultPlugins) { options.remarkPlugins ??= []; options.remarkPlugins.unshift(...remarkDefaultPlugins); }
plugins.push(...options.remarkPlugins);
plugins.push([remarkRehype, options.rehypeOptions ?? {}]);
if (options.sanitize) { plugins.push(rehypeRaw); }
plugins.push(...options.rehypePlugins ?? []);
if (options.sanitize) { plugins.push(rehypeSanitize); plugins.push(rehypeStringify); } else { plugins.push([rehypeStringify, { allowDangerousHtml: true }]); }
const engine = unified.unified();
engine.use(plugins);
const remarkEngine = new MarkdownEngine(engine); site.loadPages(options.extensions, { loader, engine: remarkEngine, });
site.filter("md", filter as Helper, true);
async function filter(content: string): Promise<string> { return (await remarkEngine.render(content)).trim(); } };}