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
JavaScript
// 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