UNPKG

@vivliostyle/vfm

Version:

Custom Markdown syntax specialized in book authoring.

108 lines (107 loc) 4.06 kB
import rehypeFormat from 'rehype-format'; import rehypeStringify from 'rehype-stringify'; import unified from 'unified'; import { mdast as doc } from './plugins/document.js'; import { hast as hastMath } from './plugins/math.js'; import { readMetadata } from './plugins/metadata.js'; import { replace as handleReplace } from './plugins/replace.js'; import { reviveParse as markdown } from './revive-parse.js'; import { reviveRehype as html } from './revive-rehype.js'; import { debug } from './utils.js'; // Expose metadata reading by VFM export * from './plugins/metadata.js'; /** * Check and update metadata with options. * @param metadata Metadata. * @param options Options. */ const checkMetadata = (metadata, options) => { if (metadata.title === undefined && options.title !== undefined) { metadata.title = options.title; } if (metadata.lang === undefined && options.language !== undefined) { metadata.lang = options.language; } if (options.style) { if (metadata.link === undefined) { metadata.link = []; } if (typeof options.style === 'string') { metadata.link.push([ { name: 'rel', value: 'stylesheet' }, { name: 'type', value: 'text/css' }, { name: 'href', value: options.style }, ]); } else if (Array.isArray(options.style)) { for (const style of options.style) { metadata.link.push([ { name: 'rel', value: 'stylesheet' }, { name: 'type', value: 'text/css' }, { name: 'href', value: style }, ]); } } } }; /** * Create Unified processor for Markdown AST and Hypertext AST. * @param options Options. * @returns Unified processor. */ export function VFM({ style = undefined, partial = false, title = undefined, language = undefined, replace = undefined, hardLineBreaks = false, disableFormatHtml = false, math = true, imgFigcaptionOrder = undefined, assignIdToFigcaption = false, } = {}, metadata = {}) { checkMetadata(metadata, { style, title, language }); // Prioritize metadata `vfm` settings over options if (metadata.vfm) { if (metadata.vfm.math !== undefined) { math = metadata.vfm.math; } if (metadata.vfm.partial !== undefined) { partial = metadata.vfm.partial; } if (metadata.vfm.hardLineBreaks !== undefined) { hardLineBreaks = metadata.vfm.hardLineBreaks; } if (metadata.vfm.disableFormatHtml !== undefined) { disableFormatHtml = metadata.vfm.disableFormatHtml; } if (metadata.vfm.imgFigcaptionOrder !== undefined) { imgFigcaptionOrder = metadata.vfm.imgFigcaptionOrder; } if (metadata.vfm.assignIdToFigcaption !== undefined) { assignIdToFigcaption = metadata.vfm.assignIdToFigcaption; } } const processor = unified() .use(markdown(hardLineBreaks, math)) .data('settings', { position: true }) .use(html({ imgFigcaptionOrder, assignIdToFigcaption })); if (replace) { processor.use(handleReplace, { rules: replace }); } if (!partial) { processor.use(doc, metadata); } processor.use(rehypeStringify); // Must be run after `rehype-document` to write to `<head>` if (math) { processor.use(hastMath); } // Explicitly specify true if want unformatted HTML during development or debug if (!disableFormatHtml) { processor.use(rehypeFormat); } return processor; } /** * Convert markdown to a stringify (HTML). * @param markdownString Markdown string. * @param options Options. * @returns HTML string. */ export function stringify(markdownString, options = {}, metadata = readMetadata(markdownString)) { const processor = VFM(options, metadata); const vfile = processor.processSync(markdownString); debug(vfile.data); return String(vfile); }