@intlayer/core
Version:
Includes core Intlayer functions like translation, dictionary, and utility functions shared across multiple packages.
840 lines (838 loc) • 34.3 kB
JavaScript
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_markdown_constants = require('./constants.cjs');
const require_markdown_utils = require('./utils.cjs');
const require_markdown_parser = require('./parser.cjs');
const require_markdown_renderer = require('./renderer.cjs');
//#region src/markdown/compiler.ts
const IMAGE_R = /^!\[(.*?)\]\( *((?:\([^)]*\)|[^() ])*) *"?([^)"]*)?"?\)/;
const LINK_R = new RegExp(`^\\[((?:\\[[^\\[\\]]*(?:\\[[^\\[\\]]*\\][^\\[\\]]*)*\\]|[^\\[\\]])*)\\]\\(\\s*<?((?:\\([^)]*\\)|[^\\s\\\\]|\\\\.)*?)>?(?:\\s+['"]([\\s\\S]*?)['"])?\\s*\\)`);
const getTag = (tag, components) => {
if (typeof tag !== "string") return tag;
let override = require_markdown_utils.get(components, tag);
if (!override && typeof tag === "string") {
const lowercaseTag = tag.toLowerCase();
const key = Object.keys(components).find((k) => k.toLowerCase() === lowercaseTag);
if (key) override = require_markdown_utils.get(components, key);
}
if (!override) return tag;
return override;
};
const createElementFactory = (ctx, options) => {
const { runtime, components = {} } = ctx;
const filteredTags = options.tagfilter ? [
"title",
"textarea",
"style",
"xmp",
"iframe",
"noembed",
"noframes",
"script",
"plaintext"
] : [];
return (tag, props, ...children) => {
if (typeof tag === "string" && filteredTags.includes(tag.toLowerCase())) return null;
const isStringTag = typeof tag === "string";
const className = require_markdown_utils.cx(props?.className, props?.class);
const mergedProps = {};
let classNameHandled = false;
if (props) for (const key in props) {
const value = props[key];
if (value === void 0 || value === null) continue;
if (key === "className" || key === "class") {
if (!classNameHandled) {
if (className) mergedProps.className = className;
classNameHandled = true;
}
} else mergedProps[key] = value;
}
if (!classNameHandled && className) mergedProps.className = className;
let finalProps = mergedProps;
if (runtime.normalizeProps && isStringTag) finalProps = runtime.normalizeProps(tag, mergedProps);
const component = getTag(tag, components);
return runtime.createElement(component, finalProps, ...children.length === 1 ? [children[0]] : children);
};
};
const createRules = (createElement, ctx, options, footnotes, refs, attrStringToMap, containsBlockSyntax, nonParagraphBlockSyntaxes) => {
const slug = (input) => {
if (process.env.NODE_ENV === "test" && input === "中文") {
const def = require_markdown_utils.slugify(input);
console.log("Slug check:", {
input,
ctxSlugify: !!ctx.slugify,
defaultSlugifyResult: def
});
}
return ctx.slugify ? ctx.slugify(input, require_markdown_utils.slugify) : require_markdown_utils.slugify(input);
};
const sanitize = ctx.sanitizer ?? require_markdown_utils.sanitizer;
const namedCodesToUnicode = ctx.namedCodesToUnicode ? {
...require_markdown_constants.NAMED_CODES_TO_UNICODE,
...ctx.namedCodesToUnicode
} : require_markdown_constants.NAMED_CODES_TO_UNICODE;
const generateListRule = (type) => {
const ordered = type === 1;
const LIST_R = ordered ? require_markdown_constants.ORDERED_LIST_R : require_markdown_constants.UNORDERED_LIST_R;
const LIST_ITEM_R = ordered ? require_markdown_constants.ORDERED_LIST_ITEM_R : require_markdown_constants.UNORDERED_LIST_ITEM_R;
const LIST_ITEM_PREFIX_R = ordered ? require_markdown_constants.ORDERED_LIST_ITEM_PREFIX_R : require_markdown_constants.UNORDERED_LIST_ITEM_PREFIX_R;
return {
_qualify: (source) => LIST_ITEM_PREFIX_R.test(source),
_match: require_markdown_utils.allowInline((source, state) => {
const isStartOfLine = require_markdown_constants.LIST_LOOKBEHIND_R.exec(state.prevCapture ?? "");
const isListAllowed = state.list ?? (!state.inline && !state.simple);
if (isStartOfLine && isListAllowed) {
const matchSource = (isStartOfLine[1] || "") + source;
return LIST_R.exec(matchSource);
}
return null;
}),
_order: require_markdown_constants.Priority.HIGH,
_parse(capture, parse, state) {
const bullet = capture[2];
const startValue = ordered ? +bullet.slice(0, -1) : void 0;
const items = capture[0].replace(require_markdown_constants.BLOCK_END_R, "\n").match(LIST_ITEM_R);
if (!items) return {
items: [],
ordered,
start: startValue
};
let lastItemWasAParagraph = false;
return {
items: items.map((item, i) => {
const prefixCapture = LIST_ITEM_PREFIX_R.exec(item);
const space = prefixCapture ? prefixCapture[0].length : 0;
const spaceRegex = new RegExp(`^ {1,${space}}`, "gm");
const content = item.replace(spaceRegex, "").replace(LIST_ITEM_PREFIX_R, "");
const isLastItem = i === items.length - 1;
const thisItemIsAParagraph = content.indexOf("\n\n") !== -1 || isLastItem && lastItemWasAParagraph;
lastItemWasAParagraph = thisItemIsAParagraph;
const oldStateInline = state.inline;
const oldStateList = state.list;
state.list = true;
let adjustedContent;
if (thisItemIsAParagraph) {
state.inline = false;
adjustedContent = `${require_markdown_utils.trimEnd(content)}\n\n`;
} else {
state.inline = true;
adjustedContent = require_markdown_utils.trimEnd(content);
}
const parsed = parse(adjustedContent, state);
state.inline = oldStateInline;
state.list = oldStateList;
return parsed;
}),
ordered,
start: startValue
};
},
_render(node, output, state = {}) {
const Tag = node.ordered ? "ol" : "ul";
const props = { key: state.key };
if (node.ordered && node.start != null) props.start = node.start;
return createElement(Tag, props, ...node.items.map((item, i) => createElement("li", { key: i }, output(item, state))));
}
};
};
const matchParagraph = (source, state) => {
if (state.inline || state.simple || state.inHTML && source.indexOf("\n\n") === -1 && state.prevCapture?.indexOf("\n\n") === -1) return null;
let start = 0;
while (true) {
const newlineIndex = source.indexOf("\n", start);
const line = source.slice(start, newlineIndex === -1 ? void 0 : newlineIndex + 1);
if (require_markdown_utils.some(nonParagraphBlockSyntaxes, line)) break;
if (newlineIndex === -1 || !line.trim()) break;
start = newlineIndex + 1;
}
const match = source.slice(0, start);
if (match === "") return null;
const captured = require_markdown_utils.trimEnd(match);
if (captured === "") return null;
return [
match,
void 0,
captured
];
};
return {
[require_markdown_constants.RuleType.blockQuote]: {
_qualify: [">"],
_match: require_markdown_utils.blockRegex(require_markdown_constants.BLOCKQUOTE_R),
_order: require_markdown_constants.Priority.HIGH,
_parse(capture, parse, state) {
const matchAlert = capture[0].replace(require_markdown_constants.BLOCKQUOTE_TRIM_LEFT_MULTILINE_R, "").match(require_markdown_constants.BLOCKQUOTE_ALERT_R);
const alert = matchAlert?.[1];
const content = matchAlert?.[2] ?? "";
return {
alert,
children: content.indexOf("\n") !== -1 ? require_markdown_utils.parseBlock(parse, content, state) : require_markdown_utils.parseInline(parse, content, state)
};
},
_render(node, output, state = {}) {
const props = { key: state.key };
if (node.alert) {
props.className = `markdown-alert-${slug(node.alert.toLowerCase())}`;
node.children.unshift({
attrs: {},
children: [{
type: require_markdown_constants.RuleType.text,
text: node.alert
}],
noInnerParse: true,
type: require_markdown_constants.RuleType.htmlBlock,
tag: "header"
});
}
return createElement("blockquote", props, output(node.children, state));
}
},
[require_markdown_constants.RuleType.breakLine]: {
_qualify: [" "],
_match: require_markdown_utils.anyScopeRegex(require_markdown_constants.BREAK_LINE_R),
_order: require_markdown_constants.Priority.HIGH,
_parse: require_markdown_utils.captureNothing,
_render(_, __, state = {}) {
return createElement("br", { key: state.key });
}
},
[require_markdown_constants.RuleType.breakThematic]: {
_qualify: [
"--",
"__",
"**",
"- ",
"* ",
"_ "
],
_match: require_markdown_utils.blockRegex(require_markdown_constants.BREAK_THEMATIC_R),
_order: require_markdown_constants.Priority.HIGH,
_parse: require_markdown_utils.captureNothing,
_render(_, __, state = {}) {
return createElement("hr", { key: state.key });
}
},
[require_markdown_constants.RuleType.codeBlock]: {
_qualify: [" "],
_match: require_markdown_utils.blockRegex(require_markdown_constants.CODE_BLOCK_R),
_order: require_markdown_constants.Priority.MAX,
_parse(capture) {
return {
type: require_markdown_constants.RuleType.codeBlock,
lang: void 0,
text: require_markdown_utils.unescapeString(require_markdown_utils.trimEnd(capture[0].replace(/^ {4}/gm, "")))
};
},
_render(node, _, state = {}) {
const attrs = { ...node.attrs ?? {} };
const langClass = node.lang ? `lang-${node.lang}` : "lang-plaintext";
attrs.className = attrs.className ? `${attrs.className} ${langClass}` : langClass;
return createElement("pre", { key: state.key }, createElement("code", attrs, node.text));
}
},
[require_markdown_constants.RuleType.codeFenced]: {
_qualify: ["```", "~~~"],
_match: require_markdown_utils.blockRegex(require_markdown_constants.CODE_BLOCK_FENCED_R),
_order: require_markdown_constants.Priority.MAX,
_parse(capture) {
return {
attrs: attrStringToMap("code", capture[3] ?? ""),
lang: capture[2] || void 0,
text: capture[4],
type: require_markdown_constants.RuleType.codeBlock
};
}
},
[require_markdown_constants.RuleType.codeInline]: {
_qualify: ["`"],
_match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.CODE_INLINE_R),
_order: require_markdown_constants.Priority.LOW,
_parse(capture) {
return { text: require_markdown_utils.unescapeString(capture[2]) };
},
_render(node, _, state = {}) {
return createElement("code", { key: state.key }, node.text);
}
},
[require_markdown_constants.RuleType.footnote]: {
_qualify: ["[^"],
_match: require_markdown_utils.blockRegex(require_markdown_constants.FOOTNOTE_R),
_order: require_markdown_constants.Priority.MAX,
_parse(capture) {
footnotes.push({
footnote: capture[2],
identifier: capture[1]
});
return {};
},
_render: require_markdown_utils.renderNothing
},
[require_markdown_constants.RuleType.footnoteReference]: {
_qualify: ["[^"],
_match: require_markdown_utils.inlineRegex(require_markdown_constants.FOOTNOTE_REFERENCE_R),
_order: require_markdown_constants.Priority.HIGH,
_parse(capture) {
return {
target: `#${slug(capture[1])}`,
text: capture[1]
};
},
_render(node, _, state = {}) {
return createElement("a", {
key: state.key,
href: sanitize(node.target, "a", "href") ?? void 0
}, createElement("sup", { key: state.key }, node.text));
}
},
[require_markdown_constants.RuleType.gfmTask]: {
_qualify: ["[ ]", "[x]"],
_match: require_markdown_utils.inlineRegex(require_markdown_constants.GFM_TASK_R),
_order: require_markdown_constants.Priority.HIGH,
_parse(capture) {
return { completed: capture[1].toLowerCase() === "x" };
},
_render(node, _, state = {}) {
return createElement("input", {
checked: node.completed,
key: state.key,
readOnly: true,
type: "checkbox"
});
}
},
[require_markdown_constants.RuleType.heading]: {
_qualify: ["#"],
_match: require_markdown_utils.blockRegex(options.enforceAtxHeadings ? require_markdown_constants.HEADING_ATX_COMPLIANT_R : require_markdown_constants.HEADING_R),
_order: require_markdown_constants.Priority.HIGH,
_parse(capture, parse, state) {
return {
children: require_markdown_utils.parseInline(parse, capture[2], state),
id: slug(capture[2]),
level: capture[1].length
};
},
_render(node, output, state = {}) {
return createElement(`h${node.level}`, {
id: node.id,
key: state.key
}, output(node.children, state));
}
},
[require_markdown_constants.RuleType.headingSetext]: {
_qualify: (source) => {
const nlIndex = source.indexOf("\n");
return nlIndex > 0 && nlIndex < source.length - 1 && (source[nlIndex + 1] === "=" || source[nlIndex + 1] === "-");
},
_match: require_markdown_utils.blockRegex(require_markdown_constants.HEADING_SETEXT_R),
_order: require_markdown_constants.Priority.MAX,
_parse(capture, parse, state) {
return {
children: require_markdown_utils.parseInline(parse, capture[1], state),
level: capture[2] === "=" ? 1 : 2,
type: require_markdown_constants.RuleType.heading
};
}
},
[require_markdown_constants.RuleType.htmlBlock]: {
_qualify: (source) => {
if (options.disableParsingRawHTML) return false;
const match = source.match(/^ *<([a-z][a-z0-9:-]*)\b/i);
if (!match) return false;
const tag = match[1];
return source.toLowerCase().indexOf(`</${tag.toLowerCase()}>`) !== -1;
},
_match: require_markdown_utils.anyScopeRegex(require_markdown_constants.HTML_BLOCK_ELEMENT_R),
_order: require_markdown_constants.Priority.HIGH,
_parse(capture, parse, state) {
const whitespace = capture[3].match(require_markdown_constants.HTML_LEFT_TRIM_AMOUNT_R)?.[1] ?? "";
const trimmed = require_markdown_utils.trimLeadingWhitespaceOutsideFences(capture[3], whitespace);
const parseFunc = containsBlockSyntax(trimmed) ? require_markdown_utils.parseBlock : require_markdown_utils.parseInline;
const tagName = capture[1].trim();
const noInnerParse = require_markdown_constants.DO_NOT_PROCESS_HTML_ELEMENTS.indexOf(tagName.toLowerCase()) !== -1;
const tag = noInnerParse ? tagName.toLowerCase() : tagName;
const ast = {
attrs: attrStringToMap(tag, capture[2] ?? ""),
noInnerParse,
tag
};
state.inAnchor = state.inAnchor || tagName.toLowerCase() === "a";
if (noInnerParse) ast.text = capture[3];
else {
const prevInHTML = state.inHTML;
state.inHTML = true;
ast.children = parseFunc(parse, trimmed, state);
state.inHTML = prevInHTML;
}
state.inAnchor = false;
return ast;
},
_render(node, output, state = {}) {
return createElement(node.tag, {
key: state.key,
...node.attrs ?? {}
}, node.text ?? (node.children ? output(node.children, state) : ""));
}
},
[require_markdown_constants.RuleType.htmlComment]: {
_qualify: ["<!"],
_match: require_markdown_utils.anyScopeRegex(require_markdown_constants.HTML_COMMENT_R),
_order: require_markdown_constants.Priority.HIGH,
_parse: require_markdown_utils.captureNothing,
_render: require_markdown_utils.renderNothing
},
[require_markdown_constants.RuleType.htmlSelfClosing]: {
_qualify: (source) => {
if (options.disableParsingRawHTML) return false;
return /^ *<([a-zA-Z][a-zA-Z0-9:]*)[\s>/]/.test(source);
},
_match: require_markdown_utils.anyScopeRegex(require_markdown_constants.HTML_SELF_CLOSING_ELEMENT_R),
_order: require_markdown_constants.Priority.HIGH,
_parse(capture) {
const tag = capture[1].trim();
return {
attrs: attrStringToMap(tag, capture[2] || ""),
tag
};
},
_render(node, _, state = {}) {
return createElement(node.tag, {
key: state.key,
...node.attrs ?? {}
});
}
},
[require_markdown_constants.RuleType.customComponent]: {
_qualify: (source) => /^ *<([A-Z][a-zA-Z0-9]*)/.test(source),
_match: require_markdown_utils.anyScopeRegex(require_markdown_constants.CUSTOM_COMPONENT_R),
_order: require_markdown_constants.Priority.MAX,
_parse(capture, parse, state) {
const whitespace = capture[3].match(require_markdown_constants.HTML_LEFT_TRIM_AMOUNT_R)?.[1] ?? "";
const trimmed = require_markdown_utils.trimLeadingWhitespaceOutsideFences(capture[3], whitespace);
const parseFunc = containsBlockSyntax(trimmed) ? require_markdown_utils.parseBlock : require_markdown_utils.parseInline;
const tag = capture[1].trim();
const ast = {
attrs: attrStringToMap(tag, capture[2] ?? ""),
noInnerParse: false,
tag
};
const prevInHTML = state.inHTML;
state.inHTML = true;
ast.children = parseFunc(parse, trimmed, state);
state.inHTML = prevInHTML;
return ast;
},
_render(node, output, state = {}) {
return createElement(node.tag, {
key: state.key,
...node.attrs ?? {}
}, node.text ?? (node.children ? output(node.children, state) : ""));
}
},
[require_markdown_constants.RuleType.paragraph]: {
_match: matchParagraph,
_order: require_markdown_constants.Priority.LOW,
_parse: require_markdown_utils.parseCaptureInline,
_render(node, output, state = {}) {
return createElement("p", { key: state.key }, output(node.children, state));
}
},
[require_markdown_constants.RuleType.image]: {
_qualify: ["!["],
_match: require_markdown_utils.simpleInlineRegex(IMAGE_R),
_order: require_markdown_constants.Priority.HIGH,
_parse(capture) {
return {
alt: require_markdown_utils.unescapeString(capture[1]),
target: require_markdown_utils.unescapeString(capture[2]),
title: require_markdown_utils.unescapeString(capture[3])
};
},
_render(node, _, state = {}) {
return createElement("img", {
key: state.key,
alt: node.alt ?? void 0,
title: node.title ?? void 0,
src: sanitize(node.target, "img", "src") ?? void 0
});
}
},
[require_markdown_constants.RuleType.link]: {
_qualify: ["["],
_match: require_markdown_utils.inlineRegex(LINK_R),
_order: require_markdown_constants.Priority.LOW,
_parse(capture, parse, state) {
return {
children: require_markdown_utils.parseSimpleInline(parse, capture[1], state),
target: require_markdown_utils.unescapeString(capture[2]),
title: require_markdown_utils.unescapeString(capture[3])
};
},
_render(node, output, state = {}) {
const sanitizedHref = sanitize(node.target, "a", "href");
if (process.env.NODE_ENV === "test" && node.target.includes("javascript:")) console.log("Compiler sanitize result:", {
target: node.target,
sanitizedHref,
finalHref: sanitizedHref ?? void 0
});
return createElement("a", {
key: state.key,
href: sanitizedHref ?? void 0,
title: node.title ?? void 0
}, output(node.children, state));
}
},
[require_markdown_constants.RuleType.linkAngleBraceStyleDetector]: {
_qualify: ["<"],
_match: require_markdown_utils.inlineRegex(require_markdown_constants.LINK_AUTOLINK_R),
_order: require_markdown_constants.Priority.MAX,
_parse(capture) {
let target = capture[1];
let isEmail = false;
if (target.indexOf("@") !== -1 && target.indexOf("//") === -1) {
isEmail = true;
target = target.replace("mailto:", "");
}
return {
children: [{
text: target,
type: require_markdown_constants.RuleType.text
}],
target: isEmail ? `mailto:${target}` : target,
type: require_markdown_constants.RuleType.link
};
}
},
[require_markdown_constants.RuleType.linkBareUrlDetector]: {
_qualify: (source, state) => !!(state.inline && !state.inAnchor && !options.disableAutoLink && (require_markdown_utils.startsWith(source, "http://") || require_markdown_utils.startsWith(source, "https://"))),
_match: require_markdown_utils.inlineRegex(require_markdown_constants.LINK_AUTOLINK_BARE_URL_R),
_order: require_markdown_constants.Priority.MAX,
_parse(capture) {
return {
children: [{
text: capture[1],
type: require_markdown_constants.RuleType.text
}],
target: capture[1],
type: require_markdown_constants.RuleType.link
};
}
},
[require_markdown_constants.RuleType.newlineCoalescer]: {
_match: require_markdown_utils.blockRegex(require_markdown_constants.CONSECUTIVE_NEWLINE_R),
_order: require_markdown_constants.Priority.LOW,
_parse: require_markdown_utils.captureNothing,
_render() {
return "\n";
}
},
[require_markdown_constants.RuleType.orderedList]: generateListRule(1),
[require_markdown_constants.RuleType.unorderedList]: generateListRule(2),
[require_markdown_constants.RuleType.ref]: {
_qualify: ["["],
_match: require_markdown_utils.anyScopeRegex(require_markdown_constants.REFERENCE_IMAGE_OR_LINK),
_order: require_markdown_constants.Priority.MAX,
_parse(capture) {
refs[capture[1]] = {
target: capture[2],
title: capture[4]
};
return {};
},
_render: require_markdown_utils.renderNothing
},
[require_markdown_constants.RuleType.refImage]: {
_qualify: ["!["],
_match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.REFERENCE_IMAGE_R),
_order: require_markdown_constants.Priority.MAX,
_parse(capture) {
return {
alt: capture[1] ? require_markdown_utils.unescapeString(capture[1]) : void 0,
ref: capture[2]
};
},
_render(node, _, state = {}) {
const ref = refs[node.ref];
if (!ref) return null;
return createElement("img", {
key: state.key,
alt: node.alt,
src: sanitize(ref.target, "img", "src") ?? void 0,
title: ref.title
});
}
},
[require_markdown_constants.RuleType.refLink]: {
_qualify: (source) => source[0] === "[" && source.indexOf("](") === -1,
_match: require_markdown_utils.inlineRegex(require_markdown_constants.REFERENCE_LINK_R),
_order: require_markdown_constants.Priority.MAX,
_parse(capture, parse, state) {
return {
children: require_markdown_utils.parseSimpleInline(parse, capture[1], state),
fallbackChildren: capture[0],
ref: capture[2]
};
},
_render(node, output, state = {}) {
const ref = refs[node.ref];
if (!ref) return createElement("span", { key: state.key }, node.fallbackChildren);
return createElement("a", {
key: state.key,
href: sanitize(ref.target, "a", "href") ?? void 0,
title: ref.title
}, output(node.children, state));
}
},
[require_markdown_constants.RuleType.table]: {
_qualify: ["|"],
_match: require_markdown_utils.blockRegex(require_markdown_constants.NP_TABLE_R),
_order: require_markdown_constants.Priority.HIGH,
_parse(capture, parse, state) {
state.inline = true;
const align = capture[2] ? require_markdown_utils.parseTableAlign(capture[2]) : [];
const cells = capture[3] ? require_markdown_utils.parseTableCells(capture[3], parse, state) : [];
const header = require_markdown_utils.parseTableRow(capture[1], parse, state, !!cells.length);
state.inline = false;
return cells.length ? {
align,
cells,
header,
type: require_markdown_constants.RuleType.table
} : {
children: header.flat(),
type: require_markdown_constants.RuleType.paragraph
};
},
_render(node, output, state = {}) {
const table = node;
const getStyle = (i) => table.align[i] && table.align[i] !== "left" ? { textAlign: table.align[i] } : {};
return createElement("table", { key: state.key }, createElement("thead", null, createElement("tr", null, ...table.header.map((c, i) => createElement("th", {
key: i,
style: getStyle(i)
}, output(c, state))))), createElement("tbody", null, ...table.cells.map((row, i) => createElement("tr", { key: i }, ...row.map((c, j) => createElement("td", {
key: j,
style: getStyle(j)
}, output(c, state)))))));
}
},
[require_markdown_constants.RuleType.tableSeparator]: {
_match: (source, state) => state.inTable && source[0] === "|" ? /^\|/.exec(source) : null,
_order: require_markdown_constants.Priority.HIGH,
_parse() {
return { type: require_markdown_constants.RuleType.tableSeparator };
},
_render() {
return " | ";
}
},
[require_markdown_constants.RuleType.text]: {
_match: require_markdown_utils.allowInline((source, _state) => {
const shortMatch = require_markdown_constants.SHORTCODE_R.exec(source);
if (shortMatch) return shortMatch;
return require_markdown_constants.TEXT_PLAIN_R.exec(source) || /^[\s\S]/.exec(source);
}),
_order: require_markdown_constants.Priority.MIN,
_parse(capture) {
const text = capture[0];
return { text: text.indexOf("&") === -1 ? text : text.replace(require_markdown_constants.HTML_CHAR_CODE_R, (f, i) => {
if (i.startsWith("#x")) return String.fromCharCode(parseInt(i.slice(2), 16));
if (i.startsWith("#")) return String.fromCharCode(parseInt(i.slice(1), 10));
return namedCodesToUnicode[i] || f;
}) };
},
_render(node) {
return node.text;
}
},
[require_markdown_constants.RuleType.textBolded]: {
_qualify: ["**", "__"],
_match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.TEXT_BOLD_R),
_order: require_markdown_constants.Priority.MED,
_parse(capture, parse, state) {
return { children: parse(capture[2], state) };
},
_render(node, output, state = {}) {
return createElement("strong", { key: state.key }, output(node.children, state));
}
},
[require_markdown_constants.RuleType.textEmphasized]: {
_qualify: ["*", "_"],
_match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.TEXT_EMPHASIZED_R),
_order: require_markdown_constants.Priority.LOW,
_parse(capture, parse, state) {
return { children: parse(capture[2], state) };
},
_render(node, output, state = {}) {
return createElement("em", { key: state.key }, output(node.children, state));
}
},
[require_markdown_constants.RuleType.textEscaped]: {
_qualify: ["\\"],
_match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.TEXT_ESCAPED_R),
_order: require_markdown_constants.Priority.HIGH,
_parse(capture) {
return {
text: capture[1],
type: require_markdown_constants.RuleType.text
};
}
},
[require_markdown_constants.RuleType.textMarked]: {
_qualify: ["=="],
_match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.TEXT_MARKED_R),
_order: require_markdown_constants.Priority.LOW,
_parse: require_markdown_utils.parseCaptureInline,
_render(node, output, state = {}) {
return createElement("mark", { key: state.key }, output(node.children, state));
}
},
[require_markdown_constants.RuleType.textStrikethroughed]: {
_qualify: ["~~"],
_match: require_markdown_utils.simpleInlineRegex(require_markdown_constants.TEXT_STRIKETHROUGHED_R),
_order: require_markdown_constants.Priority.LOW,
_parse: require_markdown_utils.parseCaptureInline,
_render(node, output, state = {}) {
return createElement("del", { key: state.key }, output(node.children, state));
}
}
};
};
const parseMarkdown = (markdown = "", ctx, options = {}) => {
const dummyCreateElement = () => null;
const footnotes = [];
const refs = {};
const attrStringToMap = (tag, str) => {
if (!str?.trim()) return null;
const attributes = str.match(require_markdown_constants.ATTR_EXTRACTOR_R);
if (!attributes) return null;
return attributes.reduce((map, raw) => {
const delimiterIdx = raw.indexOf("=");
if (delimiterIdx !== -1) {
const key = require_markdown_utils.normalizeAttributeKey(raw.slice(0, delimiterIdx)).trim();
const value = require_markdown_utils.unquote(raw.slice(delimiterIdx + 1).trim());
const mappedKey = require_markdown_constants.ATTRIBUTE_TO_NODE_PROP_MAP[key] ?? key;
if (mappedKey === "ref") return map;
map[mappedKey] = require_markdown_utils.attributeValueToNodePropValue(tag, key, value, ctx.sanitizer ?? require_markdown_utils.sanitizer);
if (typeof map[mappedKey] === "string" && (require_markdown_constants.HTML_BLOCK_ELEMENT_R.test(map[mappedKey]) || require_markdown_constants.HTML_SELF_CLOSING_ELEMENT_R.test(map[mappedKey]))) map[mappedKey] = parseMarkdown(map[mappedKey].trim(), ctx, options).ast;
} else if (raw !== "style") map[require_markdown_constants.ATTRIBUTE_TO_NODE_PROP_MAP[raw] ?? raw] = true;
return map;
}, {});
};
const nonParagraphBlockSyntaxes = [
require_markdown_constants.BLOCKQUOTE_R,
require_markdown_constants.CODE_BLOCK_FENCED_R,
require_markdown_constants.CODE_BLOCK_R,
options.enforceAtxHeadings ? require_markdown_constants.HEADING_ATX_COMPLIANT_R : require_markdown_constants.HEADING_R,
require_markdown_constants.HEADING_SETEXT_R,
require_markdown_constants.NP_TABLE_R,
require_markdown_constants.ORDERED_LIST_R,
require_markdown_constants.UNORDERED_LIST_R,
require_markdown_constants.CUSTOM_COMPONENT_R
];
const containsBlockSyntax = (input) => {
const cleaned = input.replace(require_markdown_constants.TRIM_STARTING_NEWLINES, "");
const slice = cleaned.length > 2048 ? cleaned.slice(0, 2048) : cleaned;
if (slice.indexOf("\n\n") !== -1) return true;
return require_markdown_utils.some(options.disableParsingRawHTML ? nonParagraphBlockSyntaxes : [
...nonParagraphBlockSyntaxes,
require_markdown_constants.PARAGRAPH_R,
require_markdown_constants.HTML_BLOCK_ELEMENT_R,
require_markdown_constants.HTML_COMMENT_R,
require_markdown_constants.HTML_SELF_CLOSING_ELEMENT_R,
require_markdown_constants.CUSTOM_COMPONENT_R
], slice);
};
const baseRules = createRules(dummyCreateElement, ctx, options, footnotes, refs, attrStringToMap, containsBlockSyntax, nonParagraphBlockSyntaxes);
const parser = require_markdown_parser.parserFor(options.disableParsingRawHTML ? Object.keys(baseRules).reduce((acc, key) => {
if (key !== require_markdown_constants.RuleType.htmlBlock && key !== require_markdown_constants.RuleType.htmlSelfClosing) acc[key] = baseRules[key];
return acc;
}, {}) : baseRules);
const result = options.preserveFrontmatter ? markdown : markdown.replace(require_markdown_constants.FRONT_MATTER_R, "");
const inline = options.forceInline || !options.forceBlock && require_markdown_constants.SHOULD_RENDER_AS_BLOCK_R.test(result.replace(require_markdown_constants.TRIM_STARTING_NEWLINES, "")) === false;
const ast = parser(inline ? result : `${require_markdown_utils.trimEnd(result).replace(require_markdown_constants.TRIM_STARTING_NEWLINES, "")}\n\n`, { inline });
if (footnotes.length > 0) for (const def of footnotes) def.parsedAst = parser(def.footnote, { inline: true });
return {
ast,
footnotes,
inline
};
};
const renderMarkdownAst = (parsed, ctx, options = {}) => {
const components = ctx.components ?? {};
const slug = (input) => {
if (process.env.NODE_ENV === "test" && input === "中文") {
const def = require_markdown_utils.slugify(input);
console.log("Slug check:", {
input,
ctxSlugify: !!ctx.slugify,
defaultSlugifyResult: def
});
}
return ctx.slugify ? ctx.slugify(input, require_markdown_utils.slugify) : require_markdown_utils.slugify(input);
};
const createElement = createElementFactory(ctx, options);
const footnotes = parsed.footnotes || [];
const refs = {};
const attrStringToMap = () => null;
const containsBlockSyntax = () => false;
const baseRules = createRules(createElement, ctx, options, footnotes, refs, attrStringToMap, containsBlockSyntax, []);
const emitter = require_markdown_renderer.renderFor(require_markdown_renderer.createRenderer(options.disableParsingRawHTML ? Object.keys(baseRules).reduce((acc, key) => {
if (key !== require_markdown_constants.RuleType.htmlBlock && key !== require_markdown_constants.RuleType.htmlSelfClosing) acc[key] = baseRules[key];
return acc;
}, {}) : baseRules, options.renderRule));
const inline = parsed.inline;
const arr = emitter(parsed.ast, { inline });
while (typeof arr[arr.length - 1] === "string" && !arr[arr.length - 1].trim()) arr.pop();
const getOuterNode = () => {
if (options.wrapper === null) return arr;
const wrapper = options.wrapper ?? (inline ? "span" : "div");
if (arr.length > 1 || options.forceWrapper) return createElement(wrapper, { key: "outer" }, arr);
if (arr.length === 1) {
const node = arr[0];
if (typeof node === "string") {
const spanProps = { key: "outer" };
if (!inline && components) {
const pOverrideProps = require_markdown_utils.get(components, "p.props", {}) ?? {};
const mergedClassName = require_markdown_utils.cx(spanProps.className, pOverrideProps.className);
const finalSpanProps = {
...spanProps,
...pOverrideProps
};
if (mergedClassName) finalSpanProps.className = mergedClassName;
return createElement("span", finalSpanProps, node);
}
return createElement("span", spanProps, node);
}
return node;
}
return createElement(wrapper, { key: "outer" }, null);
};
const node = getOuterNode();
return footnotes.length ? createElement("div", null, node, createElement("footer", { key: "footer" }, ...footnotes.map((def) => createElement("div", {
id: slug(def.identifier),
key: def.identifier
}, def.identifier, emitter(def.parsedAst || def.footnote, { inline: true }))))) : node;
};
const compile = (markdown = "", ctx, options = {}) => {
if (typeof markdown !== "string") {
if (process.env.NODE_ENV !== "production") console.error("intlayer: the first argument must be a string. Received", typeof markdown);
throw new Error("intlayer: the first argument must be a string");
}
return renderMarkdownAst(parseMarkdown(markdown, ctx, options), ctx, options);
};
const createCompiler = (ctx) => (markdown, options) => compile(markdown, ctx, options);
const compileWithOptions = (markdown, runtime, options = {}) => {
const { components, namedCodesToUnicode, sanitizer, slugify, ...compilerOptions } = options;
return compile(markdown, {
runtime,
components,
namedCodesToUnicode,
sanitizer,
slugify
}, compilerOptions);
};
//#endregion
exports.compile = compile;
exports.compileWithOptions = compileWithOptions;
exports.createCompiler = createCompiler;
exports.parseMarkdown = parseMarkdown;
exports.renderMarkdownAst = renderMarkdownAst;
//# sourceMappingURL=compiler.cjs.map