deno.land / x / lume@v2.1.4 / plugins / remark.ts
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154import 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 { /** List of extensions this plugin applies to */ extensions?: string[];
/** * List of remark plugins to use * @default `[remarkGfm]` */ remarkPlugins?: PluggableList;
/** Options to pass to rehype */ rehypeOptions?: RehypeOptions;
/** List of rehype plugins to use */ rehypePlugins?: PluggableList;
/** Flag to turn on HTML sanitization to prevent XSS */ sanitize?: boolean;
/** Set `false` to remove the default plugins */ useDefaultPlugins?: boolean;}
// Default optionsexport const defaults: Options = { extensions: [".md"], sanitize: false, useDefaultPlugins: true, rehypeOptions: { allowDangerousHtml: true, },};
const remarkDefaultPlugins = [ remarkGfm,];
/** Template engine to render Markdown files with Remark */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() {}}
/** Register the plugin to support Markdown */export default function (userOptions?: Options) { const options = merge(defaults, userOptions);
return function (site: Site) { const plugins = [];
// Add remark-parse to generate MDAST plugins.push(remarkParse);
if (options.useDefaultPlugins) { options.remarkPlugins ??= []; options.remarkPlugins.unshift(...remarkDefaultPlugins); }
// Add remark plugins plugins.push(...options.remarkPlugins);
// Add remark-rehype to generate HAST plugins.push([remarkRehype, options.rehypeOptions ?? {}]);
if (options.sanitize) { // Add rehype-raw to convert raw HTML to HAST plugins.push(rehypeRaw); }
// Add rehype plugins plugins.push(...options.rehypePlugins ?? []);
if (options.sanitize) { // Add rehype-sanitize to make sure HTML is safe plugins.push(rehypeSanitize); // Add rehype-stringify to output HTML ignoring raw HTML nodes plugins.push(rehypeStringify); } else { // Add rehype-stringify to output HTML plugins.push([rehypeStringify, { allowDangerousHtml: true }]); }
const engine = unified.unified();
// Register all plugins // @ts-ignore: let unified take care of loading all the plugins engine.use(plugins);
// Load the pages const remarkEngine = new MarkdownEngine(engine); site.loadPages(options.extensions, { loader, engine: remarkEngine, });
// Register the filter site.filter("md", filter as Helper, true);
async function filter(content: string): Promise<string> { return (await remarkEngine.render(content)).trim(); } };}
Version Info