UNPKG

comrak

Version:

Comrak is an efficient, extensible, and highly configurable Markdown parser and renderer, written in Rust and compiled to WebAssembly. Portable and agnostic, it works seamlessly in any WebAssembly-friendly JS runtime.

129 lines (128 loc) 4.26 kB
// deno-coverage-ignore-file // deno-coverage-ignore-start import { HeadingAdapter, SyntaxHighlighterAdapter } from "./_wasm.js"; import { Options, } from "./options.js"; const ObjectEntries = Object.entries; const JSONStringify = JSON.stringify; function serializeAttrs(attrs) { return ObjectEntries(attrs).reduce((a, [k, v]) => `${a} ${k}="${JSONStringify(v).replace(/^"|"$/g, "")}"`, ""); } function defaultOpenTag(tag) { return (attrs) => `<${tag}${serializeAttrs(attrs)}>`; } export function collectOptions(options) { const defaultOptions = Options.default(); const { plugins, ...opts } = { ...defaultOptions, extension: { ...defaultOptions.extension, ...options?.extension, }, parse: { ...defaultOptions.parse, ...options?.parse, }, render: { ...defaultOptions.render, ...options?.render, }, plugins: { ...defaultOptions.plugins, ...options?.plugins, render: { ...defaultOptions.plugins.render, ...options?.plugins?.render, }, }, }; let { brokenLinkCallback = null } = opts.parse; if (brokenLinkCallback && typeof brokenLinkCallback !== "function") { if (typeof brokenLinkCallback === "object" && typeof brokenLinkCallback.resolve === "function") { const blc = brokenLinkCallback; brokenLinkCallback = (ref) => blc.resolve(ref); } else { brokenLinkCallback = null; } } let { imageURLRewriter = null, linkURLRewriter = null, } = opts.extension; if (imageURLRewriter && typeof imageURLRewriter !== "function") { if (typeof imageURLRewriter === "object" && typeof imageURLRewriter.toHTML === "function") { const rewriter = imageURLRewriter; imageURLRewriter = (url) => rewriter.toHTML(url); } else { imageURLRewriter = null; } } if (linkURLRewriter && typeof linkURLRewriter !== "function") { if (typeof linkURLRewriter === "object" && typeof linkURLRewriter.toHTML === "function") { const rewriter = linkURLRewriter; linkURLRewriter = (url) => rewriter.toHTML(url); } else { linkURLRewriter = null; } } const { render } = plugins; let syntaxAdapter = null; if (render?.codefenceSyntaxHighlighter) { // deno-lint-ignore no-explicit-any const sh = render.codefenceSyntaxHighlighter; if (sh instanceof SyntaxHighlighterAdapter) { syntaxAdapter = sh; } else if (typeof sh === "object" && typeof sh?.highlight === "function") { syntaxAdapter = new SyntaxHighlighterAdapter(sh.highlight.bind(sh), sh.pre?.bind(sh) ?? defaultOpenTag("pre"), sh.code?.bind(sh) ?? defaultOpenTag("code")); } else { syntaxAdapter = null; } } let headingAdapter = null; if (render?.headingAdapter) { const ha = render.headingAdapter; if (ha instanceof HeadingAdapter) { headingAdapter = ha; } else if (typeof ha === "object" && typeof ha?.enter === "function" && typeof ha.exit === "function") { headingAdapter = new HeadingAdapter(ha.enter.bind(ha), ha.exit.bind(ha)); } else { headingAdapter = null; } } return [ opts, syntaxAdapter, headingAdapter, brokenLinkCallback, imageURLRewriter, linkURLRewriter, ]; } const isArray = Array.isArray; const hasOwnProperty = Object.prototype.hasOwnProperty; /** * Creates a deep clone of an object. */ export function cloneDeep(obj) { if (typeof obj !== "object" || obj === null) return obj; if (isArray(obj)) return obj.map(cloneDeep); const cloned = {}; for (const key in obj) { if (!hasOwnProperty.call(obj, key)) continue; // deno-lint-ignore no-explicit-any cloned[key] = cloneDeep(obj[key]); } return cloned; } // deno-coverage-ignore-stop