2011 lines
59 KiB
JavaScript
2011 lines
59 KiB
JavaScript
import { kebabCase } from 'scule';
|
|
import { visit } from 'unist-util-visit';
|
|
import { stringify, parse } from 'yaml';
|
|
import * as flat from 'flat';
|
|
import { stringifyEntitiesLight } from 'stringify-entities';
|
|
import { defaultHandlers } from 'mdast-util-to-markdown';
|
|
import { parseEntities } from 'parse-entities';
|
|
import { markdownLineEnding, markdownSpace, asciiAlpha, markdownLineEndingOrSpace, asciiAlphanumeric } from 'micromark-util-character';
|
|
import { factorySpace } from 'micromark-factory-space';
|
|
import { factoryWhitespace } from 'micromark-factory-whitespace';
|
|
import { codeFenced } from 'micromark-core-commonmark';
|
|
|
|
const FRONTMATTER_DELIMITER_DEFAULT = "---";
|
|
const FRONTMATTER_DELIMITER_CODEBLOCK_STYLE = "```yaml [props]";
|
|
const LF = "\n";
|
|
const CR = "\r";
|
|
function stringifyFrontMatter(data, content = "") {
|
|
if (!Object.keys(data).length) {
|
|
return content.trim();
|
|
}
|
|
data = flat.unflatten(data || {}, {});
|
|
const frontmatter = [
|
|
FRONTMATTER_DELIMITER_DEFAULT,
|
|
stringify(data).trim(),
|
|
FRONTMATTER_DELIMITER_DEFAULT,
|
|
""
|
|
].join("\n");
|
|
if (content) {
|
|
return [frontmatter, content.trim(), ""].join("\n");
|
|
}
|
|
return frontmatter;
|
|
}
|
|
function stringifyCodeBlockProps(data, content = "") {
|
|
if (!Object.keys(data).length) {
|
|
return "";
|
|
}
|
|
data = flat.unflatten(data || {}, {});
|
|
return [
|
|
FRONTMATTER_DELIMITER_CODEBLOCK_STYLE,
|
|
stringify(data).trim(),
|
|
"```",
|
|
content
|
|
].join("\n");
|
|
}
|
|
function parseFrontMatter(content) {
|
|
let data = {};
|
|
if (content.startsWith(FRONTMATTER_DELIMITER_DEFAULT)) {
|
|
const idx = content.indexOf(LF + FRONTMATTER_DELIMITER_DEFAULT);
|
|
if (idx !== -1) {
|
|
const hasCarriageReturn = content[idx - 1] === CR;
|
|
const frontmatter = content.slice(4, idx - (hasCarriageReturn ? 1 : 0));
|
|
if (frontmatter) {
|
|
data = parse(frontmatter);
|
|
content = content.slice(idx + 4 + (hasCarriageReturn ? 1 : 0));
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
content,
|
|
// unflatten frontmatter data. convert `parent.child` keys into `parent: { child: ... }`
|
|
data: flat.unflatten(data || {}, {})
|
|
};
|
|
}
|
|
|
|
function track(options_) {
|
|
const options = options_ || {};
|
|
const now = options.now || {};
|
|
let lineShift = options.lineShift || 0;
|
|
let line = now.line || 1;
|
|
let column = now.column || 1;
|
|
return { move, current, shift };
|
|
function current() {
|
|
return { now: { line, column }, lineShift };
|
|
}
|
|
function shift(value) {
|
|
lineShift += value;
|
|
}
|
|
function move(value = "") {
|
|
const chunks = value.split(/\r?\n|\r/g);
|
|
const tail = chunks[chunks.length - 1];
|
|
line += chunks.length - 1;
|
|
column = chunks.length === 1 ? column + tail.length : 1 + tail.length + lineShift;
|
|
return value;
|
|
}
|
|
}
|
|
function inlineContainerFlow(parent, context, safeOptions = {}) {
|
|
const indexStack = context.indexStack;
|
|
const children = parent.children || [];
|
|
const tracker = track(safeOptions);
|
|
const results = [];
|
|
let index = -1;
|
|
indexStack.push(-1);
|
|
while (++index < children.length) {
|
|
const child = children[index];
|
|
indexStack[indexStack.length - 1] = index;
|
|
results.push(
|
|
tracker.move(
|
|
context.handle(child, parent, context, {
|
|
before: "",
|
|
after: "",
|
|
...tracker.current()
|
|
})
|
|
)
|
|
);
|
|
}
|
|
indexStack.pop();
|
|
return results.join("");
|
|
}
|
|
function containerFlow(parent, context, safeOptions = {}) {
|
|
const indexStack = context.indexStack;
|
|
const children = parent.children || [];
|
|
const tracker = track(safeOptions);
|
|
const results = [];
|
|
let index = -1;
|
|
indexStack.push(-1);
|
|
while (++index < children.length) {
|
|
const child = children[index];
|
|
indexStack[indexStack.length - 1] = index;
|
|
results.push(
|
|
tracker.move(
|
|
context.handle(child, parent, context, {
|
|
before: "\n",
|
|
after: "\n",
|
|
...tracker.current()
|
|
})
|
|
)
|
|
);
|
|
if (child.type !== "list") {
|
|
context.bulletLastUsed = void 0;
|
|
}
|
|
if (index < children.length - 1) {
|
|
results.push(tracker.move(between(child, children[index + 1])));
|
|
}
|
|
}
|
|
indexStack.pop();
|
|
return results.join("");
|
|
function between(left, right) {
|
|
let index2 = context.join.length;
|
|
while (index2--) {
|
|
const result = context.join[index2](left, right, parent, context);
|
|
if (result === true || result === 1) {
|
|
break;
|
|
}
|
|
if (typeof result === "number") {
|
|
return "\n".repeat(1 + result);
|
|
}
|
|
if (result === false) {
|
|
return "\n\n<!---->\n\n";
|
|
}
|
|
}
|
|
return "\n\n";
|
|
}
|
|
}
|
|
function containerPhrasing(parent, context, safeOptions) {
|
|
const indexStack = context.indexStack;
|
|
const children = parent.children || [];
|
|
const results = [];
|
|
let index = -1;
|
|
let before = safeOptions.before;
|
|
indexStack.push(-1);
|
|
let tracker = track(safeOptions);
|
|
while (++index < children.length) {
|
|
const child = children[index];
|
|
let after;
|
|
indexStack[indexStack.length - 1] = index;
|
|
if (index + 1 < children.length) {
|
|
let handle = context.handle.handlers[children[index + 1].type];
|
|
if (handle && handle.peek) {
|
|
handle = handle.peek;
|
|
}
|
|
after = "";
|
|
if (handle) {
|
|
after = handle(
|
|
children[index + 1],
|
|
parent,
|
|
context,
|
|
{
|
|
before: "",
|
|
after: "",
|
|
...tracker.current()
|
|
}
|
|
).charAt(0);
|
|
}
|
|
} else {
|
|
after = safeOptions.after;
|
|
}
|
|
if (results.length > 0 && (before === "\r" || before === "\n") && child.type === "html") {
|
|
results[results.length - 1] = results[results.length - 1].replace(
|
|
/(\r?\n|\r)$/,
|
|
" "
|
|
);
|
|
before = " ";
|
|
tracker = track(safeOptions);
|
|
tracker.move(results.join(""));
|
|
}
|
|
results.push(
|
|
tracker.move(
|
|
context.handle(child, parent, context, {
|
|
...tracker.current(),
|
|
before,
|
|
after
|
|
})
|
|
)
|
|
);
|
|
before = results[results.length - 1].slice(-1);
|
|
}
|
|
indexStack.pop();
|
|
return results.join("");
|
|
}
|
|
function checkQuote(context) {
|
|
const marker = context.options.quote || '"';
|
|
if (marker !== '"' && marker !== "'") {
|
|
throw new Error(
|
|
"Cannot serialize title with `" + marker + "` for `options.quote`, expected `\"`, or `'`"
|
|
);
|
|
}
|
|
return marker;
|
|
}
|
|
|
|
const CONTAINER_NODE_TYPES = /* @__PURE__ */ new Set([
|
|
"componentContainerSection",
|
|
"containerComponent",
|
|
"leafComponent"
|
|
]);
|
|
const NON_UNWRAPPABLE_TYPES = /* @__PURE__ */ new Set([
|
|
"componentContainerSection",
|
|
"componentContainerDataSection",
|
|
"containerComponent",
|
|
"leafComponent",
|
|
"table",
|
|
"pre",
|
|
"code",
|
|
"textComponent"
|
|
]);
|
|
function convertHtmlEntitiesToChars(text) {
|
|
return text.replace(/&#x([0-9A-Fa-f]+);/g, (_, hexCode) => {
|
|
return String.fromCodePoint(Number.parseInt(hexCode, 16));
|
|
});
|
|
}
|
|
|
|
const own = {}.hasOwnProperty;
|
|
const shortcut = /^[^\t\n\r "#'.<=>`}]+$/;
|
|
const baseFence = 2;
|
|
function compilePattern(pattern) {
|
|
if (!pattern._compiled) {
|
|
const before = (pattern.atBreak ? "[\\r\\n][\\t ]*" : "") + (pattern.before ? "(?:" + pattern.before + ")" : "");
|
|
pattern._compiled = new RegExp(
|
|
(before ? "(" + before + ")" : "") + (/[|\\{}()[\]^$+*?.-]/.test(pattern.character) ? "\\" : "") + pattern.character + (pattern.after ? "(?:" + pattern.after + ")" : ""),
|
|
"g"
|
|
);
|
|
}
|
|
return pattern._compiled;
|
|
}
|
|
const toMarkdown = (opts = {}) => {
|
|
const applyAutomaticUnwrap = (node, { safeTypes = [] }) => {
|
|
const isSafe = (type) => NON_UNWRAPPABLE_TYPES.has(type) || safeTypes.includes(type);
|
|
if (!node.mdc?.unwrapped) {
|
|
return;
|
|
}
|
|
node.children = [
|
|
{
|
|
type: node.mdc.unwrapped,
|
|
children: node.children.filter((child) => !isSafe(child.type))
|
|
},
|
|
...node.children.filter((child) => isSafe(child.type))
|
|
];
|
|
};
|
|
const frontmatter = (node) => {
|
|
const entries = Object.entries(node.fmAttributes || {});
|
|
if (entries.length === 0) {
|
|
return "";
|
|
}
|
|
const attrs = entries.sort(([key1], [key2]) => key1.localeCompare(key2)).reduce((acc, [key, value2]) => {
|
|
if (key?.startsWith(":") && isValidJSON(value2)) {
|
|
try {
|
|
value2 = JSON.parse(value2);
|
|
} catch {
|
|
}
|
|
key = key.slice(1);
|
|
}
|
|
acc[key] = value2;
|
|
return acc;
|
|
}, {});
|
|
return "\n" + (opts?.yamlCodeBlockProps ? stringifyCodeBlockProps(attrs).trim() : stringifyFrontMatter(attrs).trim());
|
|
};
|
|
const processNode = (node) => {
|
|
if (opts.autoUnwrap) {
|
|
applyAutomaticUnwrap(node, typeof opts.autoUnwrap === "boolean" ? {} : opts.autoUnwrap);
|
|
}
|
|
};
|
|
function componentContainerSection(node, _, context) {
|
|
context.indexStack = context.stack;
|
|
processNode(node);
|
|
return `#${node.name}${attributes(node, context)}
|
|
${content(node, context)}`.trim();
|
|
}
|
|
function textComponent(node, _, context) {
|
|
let value;
|
|
context.indexStack = context.stack;
|
|
const exit = context.enter(node.type);
|
|
if (node.name === "span") {
|
|
value = `[${content(node, context)}]${attributes(node, context)}`;
|
|
} else if (node.name === "binding") {
|
|
const attrs = node.attributes || {};
|
|
value = attrs.defaultValue ? `{{ ${attrs.value} || '${attrs.defaultValue}' }}` : `{{ ${attrs.value} }}`;
|
|
} else {
|
|
value = ":" + (node.name || "") + label(node, context) + attributes(node, context);
|
|
}
|
|
exit();
|
|
return value;
|
|
}
|
|
let nest = 0;
|
|
function containerComponent(node, _, context) {
|
|
context.indexStack = context.stack;
|
|
const prefix = ":".repeat(baseFence + nest);
|
|
nest += 1;
|
|
const exit = context.enter(node.type);
|
|
let value = prefix + (node.name || "") + label(node, context);
|
|
const defaultSlotChildren = node.children.filter((child) => child.type !== "componentContainerSection");
|
|
const slots = node.children.filter((child) => child.type === "componentContainerSection");
|
|
node.children = [
|
|
...defaultSlotChildren,
|
|
...slots
|
|
];
|
|
node.fmAttributes = node.fmAttributes || {};
|
|
const attributesText = attributes(node, context);
|
|
if ((value + attributesText).length > (opts?.maxAttributesLength || 80) || Object.keys(node.fmAttributes).length > 0 || node.children?.some((child) => child.type === "componentContainerSection")) {
|
|
Object.assign(node.fmAttributes, node.attributes);
|
|
node.attributes = [];
|
|
}
|
|
processNode(node);
|
|
value += attributes(node, context);
|
|
value += frontmatter(node);
|
|
let subvalue;
|
|
if (node.type === "containerComponent") {
|
|
subvalue = content(node, context);
|
|
if (subvalue) {
|
|
value += "\n" + subvalue;
|
|
}
|
|
value += "\n" + prefix;
|
|
if (nest > 1) {
|
|
value = value.split("\n").map((line) => " " + line).join("\n");
|
|
}
|
|
}
|
|
nest -= 1;
|
|
exit();
|
|
return value;
|
|
}
|
|
containerComponent.peek = function peekComponent() {
|
|
return ":";
|
|
};
|
|
function label(node, context) {
|
|
let label2 = node;
|
|
if (node.type === "containerComponent") {
|
|
if (!inlineComponentLabel(node)) {
|
|
return "";
|
|
}
|
|
label2 = node.children[0];
|
|
}
|
|
const exit = context.enter("label");
|
|
const subexit = context.enter(node.type + "Label");
|
|
const value = containerPhrasing(label2, context, { before: "[", after: "]" });
|
|
subexit();
|
|
exit();
|
|
return value ? "[" + value + "]" : "";
|
|
}
|
|
const isValidJSON = (str) => {
|
|
try {
|
|
JSON.parse(str);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
};
|
|
function attributes(node, context) {
|
|
const quote = checkQuote(context);
|
|
const subset = node.type === "textComponent" ? [quote] : [quote, "\n", "\r"];
|
|
const attrs = Object.fromEntries(
|
|
Object.entries(node.attributes || {}).sort(([key1], [key2]) => key1.localeCompare(key2))
|
|
);
|
|
const values = [];
|
|
let id;
|
|
let classesFull = "";
|
|
let classes = "";
|
|
let value;
|
|
let key;
|
|
let index;
|
|
for (key in attrs) {
|
|
if (own.call(attrs, key) && attrs[key] != null) {
|
|
value = String(attrs[key]);
|
|
if (key === "id") {
|
|
id = shortcut.test(value) ? "#" + value : quoted("id", value);
|
|
} else if (key === "class" || key === "className") {
|
|
value = Array.isArray(attrs[key]) ? attrs[key].join(" ") : value;
|
|
value = value.split(/[\t\n\r ]+/g).filter(Boolean);
|
|
classesFull = [];
|
|
classes = [];
|
|
index = -1;
|
|
while (++index < value.length) {
|
|
(shortcut.test(value[index]) ? classes : classesFull).push(value[index]);
|
|
}
|
|
classesFull = classesFull.length ? quoted("class", classesFull.join(" ")) : "";
|
|
classes = classes.length ? "." + classes.join(".") : "";
|
|
} else if (key.startsWith(":") && value === "true") {
|
|
values.push(key.slice(1));
|
|
} else if (key.startsWith(":") && isValidJSON(value)) {
|
|
values.push(`${key}='${value.replace(/([^/])'/g, "$1\\'")}'`);
|
|
} else {
|
|
values.push(quoted(key, value));
|
|
}
|
|
}
|
|
}
|
|
if (classesFull) {
|
|
values.unshift(classesFull);
|
|
}
|
|
if (classes) {
|
|
values.unshift(classes);
|
|
}
|
|
if (id) {
|
|
values.unshift(id);
|
|
}
|
|
return values.length ? "{" + values.join(" ") + "}" : "";
|
|
function quoted(key2, value2) {
|
|
return key2 + "=" + quote + stringifyEntitiesLight(value2, { subset }) + quote;
|
|
}
|
|
}
|
|
function content(node, context) {
|
|
const content2 = inlineComponentLabel(node) ? Object.assign({}, node, { children: node.children.slice(1) }) : node;
|
|
let result = node.type === "textComponent" ? inlineContainerFlow(content2, context) : containerFlow(content2, context);
|
|
if (result.includes("&#x")) {
|
|
result = convertHtmlEntitiesToChars(result);
|
|
}
|
|
return result;
|
|
}
|
|
function inlineComponentLabel(node) {
|
|
return node.children && node.children[0] && node.children[0].data && node.children[0].data.componentLabel;
|
|
}
|
|
return {
|
|
compilePattern,
|
|
unsafe: [
|
|
{
|
|
character: "\r",
|
|
inConstruct: ["leafComponentLabel", "containerComponentLabel"]
|
|
},
|
|
{
|
|
character: "\n",
|
|
inConstruct: ["leafComponentLabel", "containerComponentLabel"]
|
|
},
|
|
{
|
|
before: "[^:]",
|
|
character: ":",
|
|
after: "[A-Za-z]",
|
|
inConstruct: ["phrasing"]
|
|
},
|
|
{ atBreak: true, character: ":", after: ":" }
|
|
],
|
|
handlers: {
|
|
containerComponent,
|
|
textComponent,
|
|
componentContainerSection,
|
|
image: (node, _, state, info) => {
|
|
return defaultHandlers.image(node, _, state, info) + attributes(node, state);
|
|
},
|
|
link: (node, _, state, info) => {
|
|
return defaultHandlers.link(node, _, state, info) + attributes(node, state);
|
|
},
|
|
linkReference: (node, _, state, info) => {
|
|
return defaultHandlers.linkReference(node, _, state, info) + attributes(node, state);
|
|
},
|
|
strong: (node, _, state, info) => {
|
|
return defaultHandlers.strong(node, _, state, info) + attributes(node, state);
|
|
},
|
|
inlineCode: (node, _, state) => {
|
|
state.compilePattern = state.compilePattern || compilePattern;
|
|
return defaultHandlers.inlineCode(node, _, state) + attributes(node, state);
|
|
},
|
|
emphasis: (node, _, state, info) => {
|
|
return defaultHandlers.emphasis(node, _, state, info) + attributes(node, state);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
const fromMarkdown = (opts = {}) => {
|
|
const canContainEols = ["textComponent"];
|
|
const applyYamlCodeBlockProps = (node) => {
|
|
const firstSection = node.children[0];
|
|
if (firstSection && firstSection.children?.length && firstSection.children[0].type === "code" && firstSection.children[0].lang === "yaml" && firstSection.children[0].meta === "[props]") {
|
|
node.rawData = firstSection.children[0].value;
|
|
node.mdc = node.mdc || {};
|
|
node.mdc.codeBlockProps = true;
|
|
firstSection.children.splice(0, 1);
|
|
}
|
|
};
|
|
const applyAutomaticUnwrap = (node, { safeTypes = [] }) => {
|
|
if (!CONTAINER_NODE_TYPES.has(node.type)) {
|
|
return;
|
|
}
|
|
const nonSlotChildren = node.children.filter((child2) => child2.type !== "componentContainerSection");
|
|
if (nonSlotChildren.length !== 1) {
|
|
return;
|
|
}
|
|
const child = nonSlotChildren[0];
|
|
if (NON_UNWRAPPABLE_TYPES.has(child.type) || safeTypes.includes(child.type)) {
|
|
return;
|
|
}
|
|
const childIndex = node.children.indexOf(child);
|
|
node.children.splice(childIndex, 1, ...child?.children || []);
|
|
node.mdc = node.mdc || {};
|
|
node.mdc.unwrapped = child.type;
|
|
};
|
|
const processNode = (node) => {
|
|
if (opts.yamlCodeBlockProps) {
|
|
applyYamlCodeBlockProps(node);
|
|
}
|
|
if (opts.autoUnwrap) {
|
|
applyAutomaticUnwrap(node, typeof opts.autoUnwrap === "boolean" ? {} : opts.autoUnwrap);
|
|
}
|
|
};
|
|
const enter = {
|
|
componentContainer: enterContainer,
|
|
componentContainerSection: enterContainerSection,
|
|
componentContainerDataSection: enterContainerDataSection,
|
|
componentContainerAttributes: enterAttributes,
|
|
componentContainerLabel: enterContainerLabel,
|
|
bindingContent: enterBindingContent,
|
|
componentLeaf: enterLeaf,
|
|
componentLeafAttributes: enterAttributes,
|
|
componentText: enterText,
|
|
textSpan: enterTextSpan,
|
|
componentTextAttributes: enterAttributes
|
|
};
|
|
const exit = {
|
|
bindingContent: exitBindingContent,
|
|
componentContainerSectionTitle: exitContainerSectionTitle,
|
|
listUnordered: conditionalExit,
|
|
listOrdered: conditionalExit,
|
|
listItem: conditionalExit,
|
|
componentContainerSection: exitContainerSection,
|
|
componentContainerDataSection: exitContainerDataSection,
|
|
componentContainer: exitContainer,
|
|
componentContainerAttributeClassValue: exitAttributeClassValue,
|
|
componentContainerAttributeIdValue: exitAttributeIdValue,
|
|
componentContainerAttributeName: exitAttributeName,
|
|
componentContainerAttributeValue: exitAttributeValue,
|
|
componentContainerAttributes: exitAttributes,
|
|
componentContainerLabel: exitContainerLabel,
|
|
componentContainerName,
|
|
componentContainerAttributeInitializerMarker() {
|
|
const attributes = this.data.componentAttributes;
|
|
attributes[attributes.length - 1][1] = "";
|
|
},
|
|
componentLeaf: exitToken,
|
|
componentLeafAttributeClassValue: exitAttributeClassValue,
|
|
componentLeafAttributeIdValue: exitAttributeIdValue,
|
|
componentLeafAttributeName: exitAttributeName,
|
|
componentLeafAttributeValue: exitAttributeValue,
|
|
componentLeafAttributes: exitAttributes,
|
|
componentLeafName: exitName,
|
|
componentText: exitToken,
|
|
textSpan: exitToken,
|
|
componentTextAttributeClassValue: exitAttributeClassValue,
|
|
componentTextAttributeIdValue: exitAttributeIdValue,
|
|
componentTextAttributeName: exitAttributeName,
|
|
componentTextAttributeValue: exitAttributeValue,
|
|
componentTextAttributes: exitAttributes,
|
|
componentTextName: componentContainerName
|
|
};
|
|
function enterBindingContent(token) {
|
|
const regex = /([^|]*)(?:\|\|\s*'(.*)')?/;
|
|
const values = regex.exec(this.sliceSerialize(token));
|
|
this.enter({
|
|
type: "textComponent",
|
|
name: "binding",
|
|
attributes: {
|
|
value: values?.[1]?.trim(),
|
|
defaultValue: values?.[2]
|
|
}
|
|
}, token);
|
|
}
|
|
function exitBindingContent(token) {
|
|
this.exit(token);
|
|
}
|
|
function enterContainer(token) {
|
|
enterToken.call(this, "containerComponent", token);
|
|
}
|
|
function exitContainer(token) {
|
|
const container = this.stack[this.stack.length - 1];
|
|
if (container.children.length > 1) {
|
|
const dataSection = container.children.find((child) => child.rawData);
|
|
container.rawData = dataSection?.rawData;
|
|
}
|
|
processNode(container);
|
|
container.children = container.children.flatMap((child) => {
|
|
if (child.rawData) {
|
|
return [];
|
|
}
|
|
if (child.name === "default" && Object.keys(child.attributes).length === 0 || !child.name) {
|
|
if (child.mdc?.unwrapped) {
|
|
container.mdc = container.mdc || {};
|
|
container.mdc.unwrapped = child.mdc?.unwrapped;
|
|
}
|
|
return child.children;
|
|
}
|
|
child.data = {
|
|
hName: "component-slot",
|
|
hProperties: {
|
|
...child.attributes,
|
|
[`v-slot:${child.name}`]: ""
|
|
}
|
|
};
|
|
return child;
|
|
});
|
|
this.exit(token);
|
|
}
|
|
function enterContainerSection(token) {
|
|
enterToken.call(this, "componentContainerSection", token);
|
|
}
|
|
function enterContainerDataSection(token) {
|
|
enterToken.call(this, "componentContainerDataSection", token);
|
|
}
|
|
function exitContainerSection(token) {
|
|
const section = this.stack[this.stack.length - 1];
|
|
attemptClosingOpenListSection.call(this, section);
|
|
processNode(section);
|
|
this.exit(token);
|
|
}
|
|
function exitContainerDataSection(token) {
|
|
let section = this.stack[this.stack.length - 1];
|
|
section = attemptClosingOpenListSection.call(this, section);
|
|
if (section.type === "componentContainerDataSection") {
|
|
section.rawData = this.sliceSerialize(token);
|
|
this.exit(token);
|
|
}
|
|
}
|
|
function exitContainerSectionTitle(token) {
|
|
this.stack[this.stack.length - 1].name = this.sliceSerialize(token)?.trim();
|
|
}
|
|
function enterLeaf(token) {
|
|
enterToken.call(this, "leafComponent", token);
|
|
}
|
|
function enterTextSpan(token) {
|
|
this.enter({ type: "textComponent", name: "span", attributes: {}, children: [] }, token);
|
|
}
|
|
function enterText(token) {
|
|
enterToken.call(this, "textComponent", token);
|
|
}
|
|
function enterToken(type, token) {
|
|
this.enter({ type, name: "", attributes: {}, children: [] }, token);
|
|
}
|
|
function componentContainerName(token) {
|
|
this.stack[this.stack.length - 1].name = kebabCase(this.sliceSerialize(token));
|
|
}
|
|
function exitName(token) {
|
|
this.stack[this.stack.length - 1].name = this.sliceSerialize(token);
|
|
}
|
|
function enterContainerLabel(token) {
|
|
this.enter({ type: "paragraph", data: { componentLabel: true }, children: [] }, token);
|
|
}
|
|
function exitContainerLabel(token) {
|
|
this.exit(token);
|
|
}
|
|
function enterAttributes() {
|
|
this.data.componentAttributes = [];
|
|
this.buffer();
|
|
}
|
|
function exitAttributeIdValue(token) {
|
|
this.data.componentAttributes.push(["id", parseEntities(this.sliceSerialize(token))]);
|
|
}
|
|
function exitAttributeClassValue(token) {
|
|
this.data.componentAttributes.push(["class", parseEntities(this.sliceSerialize(token))]);
|
|
}
|
|
function exitAttributeValue(token) {
|
|
const attributes = this.data.componentAttributes;
|
|
const lastAttribute = attributes[attributes.length - 1];
|
|
lastAttribute[1] = (typeof lastAttribute[1] === "string" ? lastAttribute[1] : "") + parseEntities(this.sliceSerialize(token));
|
|
}
|
|
function exitAttributeName(token) {
|
|
this.data.componentAttributes.push([this.sliceSerialize(token), true]);
|
|
}
|
|
function exitAttributes() {
|
|
const attributes = this.data.componentAttributes;
|
|
const cleaned = {};
|
|
let index = -1;
|
|
let attribute;
|
|
while (++index < attributes.length) {
|
|
attribute = attributes[index];
|
|
const name = kebabCase(attribute[0]);
|
|
if (name === "class" && cleaned.class) {
|
|
cleaned.class += " " + attribute[1];
|
|
} else {
|
|
cleaned[name] = attribute[1];
|
|
}
|
|
}
|
|
this.data.componentAttributes = attributes;
|
|
this.resume();
|
|
let stackTop = this.stack[this.stack.length - 1];
|
|
if (stackTop.type !== "textComponent" || stackTop.name === "span") {
|
|
while (!stackTop.position?.end && stackTop.children?.length > 0) {
|
|
stackTop = stackTop.children[stackTop.children.length - 1];
|
|
}
|
|
}
|
|
stackTop.attributes = cleaned;
|
|
}
|
|
function exitToken(token) {
|
|
this.exit(token);
|
|
}
|
|
function conditionalExit(token) {
|
|
const [section] = this.tokenStack[this.tokenStack.length - 1];
|
|
if (section.type === token.type) {
|
|
this.exit(token);
|
|
}
|
|
}
|
|
function attemptClosingOpenListSection(section) {
|
|
while (section.type === "listItem" || section.type === "list") {
|
|
const [stackToken] = this.tokenStack[this.tokenStack.length - 1];
|
|
this.exit(stackToken);
|
|
section = this.stack[this.stack.length - 1];
|
|
}
|
|
return section;
|
|
}
|
|
return {
|
|
canContainEols,
|
|
enter,
|
|
exit
|
|
};
|
|
};
|
|
|
|
const ContainerSequenceSize = 2;
|
|
const SectionSequenceSize = 3;
|
|
const slotSeparatorCode = 35;
|
|
const slotSeparatorLength = 1;
|
|
const Codes = {
|
|
/**
|
|
* null
|
|
*/
|
|
EOF: null,
|
|
/**
|
|
* ' '
|
|
*/
|
|
space: 32,
|
|
/**
|
|
* '"'
|
|
*/
|
|
quotationMark: 34,
|
|
/**
|
|
* '#'
|
|
*/
|
|
hash: 35,
|
|
/**
|
|
* ' ' '
|
|
*/
|
|
apostrophe: 39,
|
|
/**
|
|
* '('
|
|
*/
|
|
openingParentheses: 40,
|
|
/**
|
|
* '*'
|
|
*/
|
|
star: 42,
|
|
/**
|
|
* '-'
|
|
*/
|
|
dash: 45,
|
|
/**
|
|
* '.'
|
|
*/
|
|
dot: 46,
|
|
/**
|
|
* ':'
|
|
*/
|
|
colon: 58,
|
|
/**
|
|
* '<'
|
|
*/
|
|
LessThan: 60,
|
|
/**
|
|
* '='
|
|
*/
|
|
equals: 61,
|
|
/**
|
|
* '>'
|
|
*/
|
|
greaterThan: 62,
|
|
/**
|
|
* 'X'
|
|
*/
|
|
uppercaseX: 88,
|
|
/**
|
|
* '['
|
|
*/
|
|
openingSquareBracket: 91,
|
|
/**
|
|
* '\'
|
|
*/
|
|
backSlash: 92,
|
|
/**
|
|
* ']'
|
|
*/
|
|
closingSquareBracket: 93,
|
|
/**
|
|
* '_'
|
|
*/
|
|
underscore: 95,
|
|
/**
|
|
* '`'
|
|
*/
|
|
backTick: 96,
|
|
/**
|
|
* 'x'
|
|
*/
|
|
lowercaseX: 120,
|
|
/**
|
|
* '{'
|
|
*/
|
|
openingCurlyBracket: 123,
|
|
/**
|
|
* '}'
|
|
*/
|
|
closingCurlyBracket: 125
|
|
};
|
|
|
|
function createLabel(effects, ok, nok, type, markerType, stringType, disallowEol) {
|
|
let size = 0;
|
|
let balance = 0;
|
|
return start;
|
|
function start(code) {
|
|
if (code !== Codes.openingSquareBracket) {
|
|
throw new Error("expected `[`");
|
|
}
|
|
effects.enter(type);
|
|
effects.enter(markerType);
|
|
effects.consume(code);
|
|
effects.exit(markerType);
|
|
return afterStart;
|
|
}
|
|
function afterStart(code) {
|
|
if (code === Codes.closingSquareBracket) {
|
|
effects.enter(markerType);
|
|
effects.consume(code);
|
|
effects.exit(markerType);
|
|
effects.exit(type);
|
|
return ok;
|
|
}
|
|
effects.enter(stringType);
|
|
return atBreak(code);
|
|
}
|
|
function atBreak(code) {
|
|
if (code === Codes.EOF || size > 999) {
|
|
return nok(code);
|
|
}
|
|
if (code === Codes.closingSquareBracket && !balance--) {
|
|
return atClosingBrace(code);
|
|
}
|
|
if (markdownLineEnding(code)) {
|
|
if (disallowEol) {
|
|
return nok(code);
|
|
}
|
|
effects.enter("lineEnding");
|
|
effects.consume(code);
|
|
effects.exit("lineEnding");
|
|
return atBreak;
|
|
}
|
|
effects.enter("chunkText", { contentType: "text" });
|
|
return label(code);
|
|
}
|
|
function label(code) {
|
|
if (code === Codes.EOF || markdownLineEnding(code) || size > 999) {
|
|
effects.exit("chunkText");
|
|
return atBreak(code);
|
|
}
|
|
if (code === Codes.openingSquareBracket && ++balance > 3) {
|
|
return nok(code);
|
|
}
|
|
if (code === Codes.closingSquareBracket && !balance--) {
|
|
effects.exit("chunkText");
|
|
return atClosingBrace(code);
|
|
}
|
|
effects.consume(code);
|
|
return code === Codes.backSlash ? labelEscape : label;
|
|
}
|
|
function atClosingBrace(code) {
|
|
effects.exit(stringType);
|
|
effects.enter(markerType);
|
|
effects.consume(code);
|
|
effects.exit(markerType);
|
|
effects.exit(type);
|
|
return ok;
|
|
}
|
|
function labelEscape(code) {
|
|
if (code === Codes.openingSquareBracket || code === Codes.backSlash || code === Codes.closingSquareBracket) {
|
|
effects.consume(code);
|
|
size++;
|
|
return label;
|
|
}
|
|
return label(code);
|
|
}
|
|
}
|
|
|
|
const label$2 = { tokenize: tokenizeLabel$2, partial: true };
|
|
const gfmCheck = { tokenize: checkGfmTaskCheckbox, partial: true };
|
|
const doubleBracketCheck = { tokenize: checkDoubleBracket, partial: true };
|
|
function tokenize$6(effects, ok, nok) {
|
|
const self = this;
|
|
return start;
|
|
function start(code) {
|
|
if (code !== Codes.openingSquareBracket) {
|
|
throw new Error("expected `[`");
|
|
}
|
|
if (self.previous === Codes.EOF && self._gfmTasklistFirstContentOfListItem) {
|
|
return effects.check(gfmCheck, nok, attemptLabel)(code);
|
|
}
|
|
if (self.previous === Codes.openingSquareBracket) {
|
|
return nok(code);
|
|
}
|
|
return effects.check(doubleBracketCheck, nok, attemptLabel)(code);
|
|
}
|
|
function attemptLabel(code) {
|
|
effects.enter("textSpan");
|
|
return effects.attempt(label$2, exit, nok)(code);
|
|
}
|
|
function exit(code) {
|
|
if (code === Codes.openingParentheses || code === Codes.openingSquareBracket) {
|
|
return nok(code);
|
|
}
|
|
return exitOK(code);
|
|
}
|
|
function exitOK(code) {
|
|
effects.exit("textSpan");
|
|
return ok(code);
|
|
}
|
|
}
|
|
function tokenizeLabel$2(effects, ok, nok) {
|
|
return createLabel(effects, ok, nok, "componentTextLabel", "componentTextLabelMarker", "componentTextLabelString");
|
|
}
|
|
const tokenizeSpan = {
|
|
tokenize: tokenize$6
|
|
};
|
|
function checkGfmTaskCheckbox(effects, ok, nok) {
|
|
return enter;
|
|
function enter(code) {
|
|
effects.enter("formGfmTaskCheckbox");
|
|
effects.consume(code);
|
|
return check;
|
|
}
|
|
function check(code) {
|
|
if (markdownSpace(code)) {
|
|
effects.consume(code);
|
|
return check;
|
|
}
|
|
if (code === Codes.uppercaseX || code === Codes.lowercaseX) {
|
|
effects.consume(code);
|
|
return check;
|
|
}
|
|
if (code === Codes.closingSquareBracket) {
|
|
effects.exit("formGfmTaskCheckbox");
|
|
return ok(code);
|
|
}
|
|
return nok(code);
|
|
}
|
|
}
|
|
function checkDoubleBracket(effects, ok, nok) {
|
|
return enter;
|
|
function enter(code) {
|
|
effects.enter("doubleBracket");
|
|
effects.consume(code);
|
|
return check;
|
|
}
|
|
function check(code) {
|
|
if (code !== Codes.openingSquareBracket) {
|
|
return nok(code);
|
|
}
|
|
effects.exit("doubleBracket");
|
|
return ok(code);
|
|
}
|
|
}
|
|
|
|
function createAttributes(effects, ok, nok, attributesType, attributesMarkerType, attributeType, attributeIdType, attributeClassType, attributeNameType, attributeInitializerType, attributeValueLiteralType, attributeValueType, attributeValueMarker, attributeValueData, disallowEol) {
|
|
let type;
|
|
let marker;
|
|
let isBindAttribute = false;
|
|
return start;
|
|
function start(code) {
|
|
effects.enter(attributesType);
|
|
effects.enter(attributesMarkerType);
|
|
effects.consume(code);
|
|
effects.exit(attributesMarkerType);
|
|
return between;
|
|
}
|
|
function between(code) {
|
|
if (code === Codes.hash) {
|
|
type = attributeIdType;
|
|
return shortcutStart(code);
|
|
}
|
|
if (code === Codes.dot) {
|
|
type = attributeClassType;
|
|
return shortcutStart(code);
|
|
}
|
|
if (code === Codes.colon || code === Codes.underscore || asciiAlpha(code)) {
|
|
effects.enter(attributeType);
|
|
effects.enter(attributeNameType);
|
|
effects.consume(code);
|
|
isBindAttribute = code === Codes.colon;
|
|
return code === Codes.colon ? bindAttributeName : name;
|
|
}
|
|
if (disallowEol && markdownSpace(code)) {
|
|
return factorySpace(effects, between, "whitespace")(code);
|
|
}
|
|
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
|
return factoryWhitespace(effects, between)(code);
|
|
}
|
|
return end(code);
|
|
}
|
|
function shortcutStart(code) {
|
|
effects.enter(attributeType);
|
|
effects.enter(type);
|
|
effects.enter(type + "Marker");
|
|
effects.consume(code);
|
|
effects.exit(type + "Marker");
|
|
return shortcutStartAfter;
|
|
}
|
|
function shortcutStartAfter(code) {
|
|
if (code === Codes.EOF || code === Codes.quotationMark || code === Codes.hash || code === Codes.apostrophe || code === Codes.dot || code === Codes.LessThan || code === Codes.equals || code === Codes.greaterThan || code === Codes.backTick || code === Codes.closingCurlyBracket || markdownLineEndingOrSpace(code)) {
|
|
return nok(code);
|
|
}
|
|
effects.enter(type + "Value");
|
|
effects.consume(code);
|
|
return shortcut;
|
|
}
|
|
function shortcut(code) {
|
|
if (code === Codes.EOF || code === Codes.quotationMark || code === Codes.apostrophe || code === Codes.LessThan || code === Codes.equals || code === Codes.greaterThan || code === Codes.backTick) {
|
|
return nok(code);
|
|
}
|
|
if (code === Codes.hash || code === Codes.dot || code === Codes.closingCurlyBracket || markdownLineEndingOrSpace(code)) {
|
|
effects.exit(type + "Value");
|
|
effects.exit(type);
|
|
effects.exit(attributeType);
|
|
return between(code);
|
|
}
|
|
effects.consume(code);
|
|
return shortcut;
|
|
}
|
|
function bindAttributeName(code) {
|
|
if (code === Codes.dash || asciiAlphanumeric(code)) {
|
|
effects.consume(code);
|
|
return bindAttributeName;
|
|
}
|
|
effects.exit(attributeNameType);
|
|
if (disallowEol && markdownSpace(code)) {
|
|
return factorySpace(effects, bindAttributeNameAfter, "whitespace")(code);
|
|
}
|
|
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
|
return factoryWhitespace(effects, bindAttributeNameAfter)(code);
|
|
}
|
|
return bindAttributeNameAfter(code);
|
|
}
|
|
function bindAttributeNameAfter(code) {
|
|
if (code === Codes.equals) {
|
|
effects.enter(attributeInitializerType);
|
|
effects.consume(code);
|
|
effects.exit(attributeInitializerType);
|
|
return valueBefore;
|
|
}
|
|
effects.exit(attributeType);
|
|
return nok(code);
|
|
}
|
|
function name(code) {
|
|
if (code === Codes.dash || code === Codes.dot || code === Codes.colon || code === Codes.underscore || asciiAlphanumeric(code)) {
|
|
effects.consume(code);
|
|
return name;
|
|
}
|
|
effects.exit(attributeNameType);
|
|
if (disallowEol && markdownSpace(code)) {
|
|
return factorySpace(effects, nameAfter, "whitespace")(code);
|
|
}
|
|
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
|
return factoryWhitespace(effects, nameAfter)(code);
|
|
}
|
|
return nameAfter(code);
|
|
}
|
|
function nameAfter(code) {
|
|
if (code === Codes.equals) {
|
|
effects.enter(attributeInitializerType);
|
|
effects.consume(code);
|
|
effects.exit(attributeInitializerType);
|
|
return valueBefore;
|
|
}
|
|
effects.exit(attributeType);
|
|
return between(code);
|
|
}
|
|
function valueBefore(code) {
|
|
if (code === Codes.EOF || code === Codes.LessThan || code === Codes.equals || code === Codes.greaterThan || code === Codes.backTick || code === Codes.closingCurlyBracket || disallowEol && markdownLineEnding(code)) {
|
|
return nok(code);
|
|
}
|
|
if (code === Codes.quotationMark || code === Codes.apostrophe) {
|
|
effects.enter(attributeValueLiteralType);
|
|
effects.enter(attributeValueMarker);
|
|
effects.consume(code);
|
|
effects.exit(attributeValueMarker);
|
|
marker = code;
|
|
return valueQuotedStart;
|
|
}
|
|
if (disallowEol && markdownSpace(code)) {
|
|
return factorySpace(effects, valueBefore, "whitespace")(code);
|
|
}
|
|
if (!disallowEol && markdownLineEndingOrSpace(code)) {
|
|
return factoryWhitespace(effects, valueBefore)(code);
|
|
}
|
|
effects.enter(attributeValueType);
|
|
effects.enter(attributeValueData);
|
|
effects.consume(code);
|
|
marker = void 0;
|
|
return valueUnquoted;
|
|
}
|
|
function valueUnquoted(code) {
|
|
if (code === Codes.EOF || code === Codes.quotationMark || code === Codes.apostrophe || code === Codes.LessThan || code === Codes.equals || code === Codes.greaterThan || code === Codes.backTick) {
|
|
return nok(code);
|
|
}
|
|
if (code === Codes.closingCurlyBracket || markdownLineEndingOrSpace(code)) {
|
|
effects.exit(attributeValueData);
|
|
effects.exit(attributeValueType);
|
|
effects.exit(attributeType);
|
|
return between(code);
|
|
}
|
|
effects.consume(code);
|
|
return valueUnquoted;
|
|
}
|
|
function valueQuotedStart(code) {
|
|
if (code === marker) {
|
|
effects.enter(attributeValueMarker);
|
|
effects.consume(code);
|
|
effects.exit(attributeValueMarker);
|
|
effects.exit(attributeValueLiteralType);
|
|
effects.exit(attributeType);
|
|
return valueQuotedAfter;
|
|
}
|
|
effects.enter(attributeValueType);
|
|
return valueQuotedBetween(code);
|
|
}
|
|
function valueQuotedBetween(code) {
|
|
if (code === marker) {
|
|
effects.exit(attributeValueType);
|
|
return valueQuotedStart(code);
|
|
}
|
|
if (code === Codes.EOF) {
|
|
return nok(code);
|
|
}
|
|
if (markdownLineEnding(code)) {
|
|
return disallowEol ? nok(code) : factoryWhitespace(effects, valueQuotedBetween)(code);
|
|
}
|
|
effects.enter(attributeValueData);
|
|
effects.consume(code);
|
|
return valueQuoted;
|
|
}
|
|
function valueQuoted(code) {
|
|
if (isBindAttribute && code === Codes.backSlash) {
|
|
effects.exit(attributeValueData);
|
|
effects.exit(attributeValueType);
|
|
effects.enter("escapeCharacter");
|
|
effects.consume(code);
|
|
effects.exit("escapeCharacter");
|
|
effects.enter(attributeValueType);
|
|
effects.enter(attributeValueData);
|
|
return valueQuotedEscape;
|
|
}
|
|
if (code === marker || code === Codes.EOF || markdownLineEnding(code)) {
|
|
effects.exit(attributeValueData);
|
|
return valueQuotedBetween(code);
|
|
}
|
|
effects.consume(code);
|
|
return valueQuoted;
|
|
}
|
|
function valueQuotedEscape(code) {
|
|
effects.consume(code);
|
|
return valueQuoted;
|
|
}
|
|
function valueQuotedAfter(code) {
|
|
return code === Codes.closingCurlyBracket || markdownLineEndingOrSpace(code) ? between(code) : end(code);
|
|
}
|
|
function end(code) {
|
|
if (code === Codes.closingCurlyBracket) {
|
|
effects.enter(attributesMarkerType);
|
|
effects.consume(code);
|
|
effects.exit(attributesMarkerType);
|
|
effects.exit(attributesType);
|
|
return ok;
|
|
}
|
|
return nok(code);
|
|
}
|
|
}
|
|
|
|
const attributes$2 = { tokenize: tokenizeAttributes$2, partial: true };
|
|
const validEvents = [
|
|
/**
|
|
* Span
|
|
*/
|
|
"textSpan",
|
|
/**
|
|
* Bold & Italic
|
|
*/
|
|
"attentionSequence",
|
|
/**
|
|
* Inline Code
|
|
*/
|
|
"codeText",
|
|
/**
|
|
* Link
|
|
*/
|
|
"link",
|
|
/**
|
|
* Image
|
|
*/
|
|
"image"
|
|
];
|
|
function tokenize$5(effects, ok, nok) {
|
|
const self = this;
|
|
return start;
|
|
function start(code) {
|
|
if (code !== Codes.openingCurlyBracket) {
|
|
throw new Error("expected `{`");
|
|
}
|
|
const event = self.events[self.events.length - 1];
|
|
if (markdownLineEnding(self.previous) || !event || !validEvents.includes(event[1].type)) {
|
|
return nok(code);
|
|
}
|
|
return effects.attempt(attributes$2, ok, nok)(code);
|
|
}
|
|
}
|
|
function tokenizeAttributes$2(effects, ok, nok) {
|
|
return createAttributes(
|
|
effects,
|
|
ok,
|
|
nok,
|
|
"componentTextAttributes",
|
|
"componentTextAttributesMarker",
|
|
"componentTextAttribute",
|
|
"componentTextAttributeId",
|
|
"componentTextAttributeClass",
|
|
"componentTextAttributeName",
|
|
"componentTextAttributeInitializerMarker",
|
|
"componentTextAttributeValueLiteral",
|
|
"componentTextAttributeValue",
|
|
"componentTextAttributeValueMarker",
|
|
"componentTextAttributeValueData"
|
|
);
|
|
}
|
|
const tokenizeAttribute = {
|
|
tokenize: tokenize$5
|
|
};
|
|
|
|
function attempClose(effects, ok, nok) {
|
|
return start;
|
|
function start(code) {
|
|
if (code !== Codes.closingCurlyBracket) {
|
|
return nok(code);
|
|
}
|
|
effects.exit("bindingContent");
|
|
effects.enter("bindingFence");
|
|
effects.consume(code);
|
|
return secondBracket;
|
|
}
|
|
function secondBracket(code) {
|
|
if (code !== Codes.closingCurlyBracket) {
|
|
return nok(code);
|
|
}
|
|
effects.consume(code);
|
|
effects.exit("bindingFence");
|
|
return ok;
|
|
}
|
|
}
|
|
function tokenize$4(effects, ok, nok) {
|
|
return start;
|
|
function start(code) {
|
|
if (code !== Codes.openingCurlyBracket) {
|
|
throw new Error("expected `{`");
|
|
}
|
|
effects.enter("bindingFence");
|
|
effects.consume(code);
|
|
return secondBracket;
|
|
}
|
|
function secondBracket(code) {
|
|
if (code !== Codes.openingCurlyBracket) {
|
|
return nok(code);
|
|
}
|
|
effects.consume(code);
|
|
effects.exit("bindingFence");
|
|
effects.enter("bindingContent");
|
|
return content;
|
|
}
|
|
function content(code) {
|
|
if (code === Codes.closingCurlyBracket) {
|
|
return effects.attempt({ tokenize: attempClose, partial: true }, close, (code2) => {
|
|
effects.consume(code2);
|
|
return content;
|
|
})(code);
|
|
}
|
|
effects.consume(code);
|
|
return content;
|
|
}
|
|
function close(code) {
|
|
return ok(code);
|
|
}
|
|
}
|
|
const tokenizeBinding = {
|
|
tokenize: tokenize$4
|
|
};
|
|
|
|
function createName(effects, ok, nok, nameType) {
|
|
const self = this;
|
|
return start;
|
|
function start(code) {
|
|
if (asciiAlpha(code)) {
|
|
effects.enter(nameType);
|
|
effects.consume(code);
|
|
return name;
|
|
}
|
|
return nok(code);
|
|
}
|
|
function name(code) {
|
|
if (code === Codes.dash || code === Codes.underscore || asciiAlphanumeric(code)) {
|
|
effects.consume(code);
|
|
return name;
|
|
}
|
|
effects.exit(nameType);
|
|
return self.previous === Codes.underscore ? nok(code) : ok(code);
|
|
}
|
|
}
|
|
|
|
const label$1 = { tokenize: tokenizeLabel$1, partial: true };
|
|
const attributes$1 = { tokenize: tokenizeAttributes$1, partial: true };
|
|
function previous(code) {
|
|
return code !== Codes.colon || this.events[this.events.length - 1][1].type === "characterEscape";
|
|
}
|
|
function tokenize$3(effects, ok, nok) {
|
|
const self = this;
|
|
return start;
|
|
function start(code) {
|
|
if (code !== Codes.colon) {
|
|
throw new Error("expected `:`");
|
|
}
|
|
if (self.previous !== null && !markdownLineEndingOrSpace(self.previous) && ![Codes.openingSquareBracket, Codes.star, Codes.underscore, Codes.openingParentheses].includes(self.previous)) {
|
|
return nok(code);
|
|
}
|
|
if (!previous.call(self, self.previous)) {
|
|
throw new Error("expected correct previous");
|
|
}
|
|
effects.enter("componentText");
|
|
effects.enter("componentTextMarker");
|
|
effects.consume(code);
|
|
effects.exit("componentTextMarker");
|
|
return createName.call(self, effects, afterName, nok, "componentTextName");
|
|
}
|
|
function afterName(code) {
|
|
if (code === Codes.colon) {
|
|
return nok(code);
|
|
}
|
|
if (code === Codes.openingSquareBracket) {
|
|
return effects.attempt(label$1, afterLabel, afterLabel)(code);
|
|
}
|
|
if (code === Codes.openingCurlyBracket) {
|
|
return effects.attempt(attributes$1, afterAttributes, afterAttributes)(code);
|
|
}
|
|
return exit(code);
|
|
}
|
|
function afterAttributes(code) {
|
|
if (code === Codes.openingSquareBracket) {
|
|
return effects.attempt(label$1, afterLabel, afterLabel)(code);
|
|
}
|
|
return exit(code);
|
|
}
|
|
function afterLabel(code) {
|
|
if (code === Codes.openingCurlyBracket) {
|
|
return effects.attempt(attributes$1, exit, exit)(code);
|
|
}
|
|
return exit(code);
|
|
}
|
|
function exit(code) {
|
|
effects.exit("componentText");
|
|
return ok(code);
|
|
}
|
|
}
|
|
function tokenizeLabel$1(effects, ok, nok) {
|
|
return createLabel(effects, ok, nok, "componentTextLabel", "componentTextLabelMarker", "componentTextLabelString");
|
|
}
|
|
function tokenizeAttributes$1(effects, ok, nok) {
|
|
return createAttributes(
|
|
effects,
|
|
ok,
|
|
nok,
|
|
"componentTextAttributes",
|
|
"componentTextAttributesMarker",
|
|
"componentTextAttribute",
|
|
"componentTextAttributeId",
|
|
"componentTextAttributeClass",
|
|
"componentTextAttributeName",
|
|
"componentTextAttributeInitializerMarker",
|
|
"componentTextAttributeValueLiteral",
|
|
"componentTextAttributeValue",
|
|
"componentTextAttributeValueMarker",
|
|
"componentTextAttributeValueData"
|
|
);
|
|
}
|
|
const tokenizeInline = {
|
|
tokenize: tokenize$3,
|
|
previous
|
|
};
|
|
|
|
function sizeChunks(chunks) {
|
|
let index = -1;
|
|
let size = 0;
|
|
while (++index < chunks.length) {
|
|
size += typeof chunks[index] === "string" ? chunks[index].length : 1;
|
|
}
|
|
return size;
|
|
}
|
|
function prefixSize(events, type) {
|
|
const tail = events[events.length - 1];
|
|
if (!tail || tail[1].type !== type) {
|
|
return 0;
|
|
}
|
|
return sizeChunks(tail[2].sliceStream(tail[1]));
|
|
}
|
|
function linePrefixSize(events) {
|
|
let size = 0;
|
|
let index = events.length - 1;
|
|
let tail = events[index];
|
|
while (index >= 0 && tail && tail[1].type === "linePrefix" && tail[0] === "exit") {
|
|
size += sizeChunks(tail[2].sliceStream(tail[1]));
|
|
index -= 1;
|
|
tail = events[index];
|
|
}
|
|
return size;
|
|
}
|
|
const useTokenState = (tokenName) => {
|
|
const token = {
|
|
isOpen: false,
|
|
/**
|
|
* Enter into token, close previous open token if any
|
|
*/
|
|
enter: (effects) => {
|
|
const initialState = token.isOpen;
|
|
token.exit(effects);
|
|
effects.enter(tokenName);
|
|
token.isOpen = true;
|
|
return () => {
|
|
token.isOpen = initialState;
|
|
};
|
|
},
|
|
/**
|
|
* Enter into token only once, if token is already open, do nothing
|
|
*/
|
|
enterOnce: (effects) => {
|
|
const initialState = token.isOpen;
|
|
if (!token.isOpen) {
|
|
effects.enter(tokenName);
|
|
token.isOpen = true;
|
|
}
|
|
return () => {
|
|
token.isOpen = initialState;
|
|
};
|
|
},
|
|
/**
|
|
* Exit from token if it is open
|
|
*/
|
|
exit: (effects) => {
|
|
const initialState = token.isOpen;
|
|
if (token.isOpen) {
|
|
effects.exit(tokenName);
|
|
token.isOpen = false;
|
|
}
|
|
return () => {
|
|
token.isOpen = initialState;
|
|
};
|
|
}
|
|
};
|
|
return token;
|
|
};
|
|
const tokenizeCodeFence = { tokenize: checkCodeFenced, partial: true };
|
|
function checkCodeFenced(effects, ok, nok) {
|
|
let backTickCount = 0;
|
|
return start;
|
|
function start(code) {
|
|
effects.enter("codeFenced");
|
|
return after(code);
|
|
}
|
|
function after(code) {
|
|
if (code === Codes.backTick) {
|
|
backTickCount++;
|
|
effects.consume(code);
|
|
return after;
|
|
}
|
|
effects.exit("codeFenced");
|
|
if (backTickCount >= 3) {
|
|
return ok(code);
|
|
}
|
|
return nok(code);
|
|
}
|
|
}
|
|
|
|
function tokenizeFrontMatter(effects, ok, _nok, next, initialPrefix) {
|
|
let previous;
|
|
return effects.attempt({
|
|
tokenize: tokenizeDataSection,
|
|
partial: true
|
|
}, dataSectionOpen, next);
|
|
function tokenizeDataSection(effects2, ok2, nok) {
|
|
const self = this;
|
|
let size = 0;
|
|
let sectionIndentSize = 0;
|
|
return closingPrefixAfter;
|
|
function dataLineFirstSpaces(code) {
|
|
if (markdownSpace(code)) {
|
|
effects2.consume(code);
|
|
sectionIndentSize += 1;
|
|
return dataLineFirstSpaces;
|
|
}
|
|
effects2.exit("space");
|
|
return closingPrefixAfter(code);
|
|
}
|
|
function closingPrefixAfter(code) {
|
|
if (markdownSpace(code)) {
|
|
effects2.enter("space");
|
|
return dataLineFirstSpaces(code);
|
|
}
|
|
if (sectionIndentSize === 0) {
|
|
sectionIndentSize = linePrefixSize(self.events);
|
|
}
|
|
effects2.enter("componentContainerSectionSequence");
|
|
return closingSectionSequence(code);
|
|
}
|
|
function closingSectionSequence(code) {
|
|
if (code === Codes.dash || markdownSpace(code)) {
|
|
effects2.consume(code);
|
|
size++;
|
|
return closingSectionSequence;
|
|
}
|
|
if (size < SectionSequenceSize) {
|
|
return nok(code);
|
|
}
|
|
if (sectionIndentSize !== initialPrefix) {
|
|
return nok(code);
|
|
}
|
|
if (!markdownLineEnding(code)) {
|
|
return nok(code);
|
|
}
|
|
effects2.exit("componentContainerSectionSequence");
|
|
return factorySpace(effects2, ok2, "whitespace")(code);
|
|
}
|
|
}
|
|
function dataSectionOpen(code) {
|
|
effects.enter("componentContainerDataSection");
|
|
return effects.attempt({
|
|
tokenize: tokenizeDataSection,
|
|
partial: true
|
|
}, dataSectionClose, dataChunkStart)(code);
|
|
}
|
|
function dataChunkStart(code) {
|
|
if (code === null) {
|
|
effects.exit("componentContainerDataSection");
|
|
effects.exit("componentContainer");
|
|
return ok(code);
|
|
}
|
|
const token = effects.enter("chunkDocument", {
|
|
contentType: "document",
|
|
previous
|
|
});
|
|
if (previous) {
|
|
previous.next = token;
|
|
}
|
|
previous = token;
|
|
return dataContentContinue(code);
|
|
}
|
|
function dataContentContinue(code) {
|
|
if (code === null) {
|
|
effects.exit("chunkDocument");
|
|
effects.exit("componentContainerDataSection");
|
|
effects.exit("componentContainer");
|
|
return ok(code);
|
|
}
|
|
if (markdownLineEnding(code)) {
|
|
effects.consume(code);
|
|
effects.exit("chunkDocument");
|
|
return effects.attempt({
|
|
tokenize: tokenizeDataSection,
|
|
partial: true
|
|
}, dataSectionClose, dataChunkStart);
|
|
}
|
|
effects.consume(code);
|
|
return dataContentContinue;
|
|
}
|
|
function dataSectionClose(code) {
|
|
effects.exit("componentContainerDataSection");
|
|
return factorySpace(effects, next, "whitespace")(code);
|
|
}
|
|
}
|
|
|
|
const label = { tokenize: tokenizeLabel, partial: true };
|
|
const attributes = { tokenize: tokenizeAttributes, partial: true };
|
|
function tokenize$2(effects, ok, nok) {
|
|
const self = this;
|
|
const initialPrefix = linePrefixSize(this.events);
|
|
let sizeOpen = 0;
|
|
let previous;
|
|
const childContainersSequenceSize = [];
|
|
let containerFirstLine = true;
|
|
let visitingCodeFenced = false;
|
|
const section = useTokenState("componentContainerSection");
|
|
return start;
|
|
function start(code) {
|
|
if (code !== Codes.colon) {
|
|
throw new Error("expected `:`");
|
|
}
|
|
effects.enter("componentContainer");
|
|
effects.enter("componentContainerFence");
|
|
effects.enter("componentContainerSequence");
|
|
return sequenceOpen(code);
|
|
}
|
|
function tokenizeSectionClosing(effects2, ok2, nok2) {
|
|
let size = 0;
|
|
let sectionIndentSize = 0;
|
|
let revertSectionState;
|
|
return closingPrefixAfter;
|
|
function closingPrefixAfter(code) {
|
|
sectionIndentSize = linePrefixSize(self.events);
|
|
revertSectionState = section.exit(effects2);
|
|
effects2.enter("componentContainerSectionSequence");
|
|
return closingSectionSequence(code);
|
|
}
|
|
function closingSectionSequence(code) {
|
|
if (code === slotSeparatorCode) {
|
|
effects2.consume(code);
|
|
size++;
|
|
return closingSectionSequence;
|
|
}
|
|
if (size !== slotSeparatorLength) {
|
|
revertSectionState();
|
|
return nok2(code);
|
|
}
|
|
if (sectionIndentSize !== initialPrefix) {
|
|
revertSectionState();
|
|
return nok2(code);
|
|
}
|
|
if (!asciiAlpha(code)) {
|
|
revertSectionState();
|
|
return nok2(code);
|
|
}
|
|
effects2.exit("componentContainerSectionSequence");
|
|
return factorySpace(effects2, ok2, "whitespace")(code);
|
|
}
|
|
}
|
|
function sectionOpen(code) {
|
|
section.enter(effects);
|
|
if (markdownLineEnding(code)) {
|
|
return factorySpace(effects, lineStart, "whitespace")(code);
|
|
}
|
|
effects.enter("componentContainerSectionTitle");
|
|
return sectionTitle(code);
|
|
}
|
|
function sectionTitle(code) {
|
|
if (code === Codes.openingCurlyBracket) {
|
|
return effects.check(
|
|
attributes,
|
|
(code2) => {
|
|
effects.exit("componentContainerSectionTitle");
|
|
return effects.attempt(attributes, factorySpace(effects, lineStart, "linePrefix", 4), nok)(code2);
|
|
},
|
|
(code2) => {
|
|
effects.consume(code2);
|
|
return sectionTitle;
|
|
}
|
|
)(code);
|
|
}
|
|
if (markdownLineEnding(code)) {
|
|
effects.exit("componentContainerSectionTitle");
|
|
return factorySpace(effects, lineStart, "linePrefix", 4)(code);
|
|
}
|
|
effects.consume(code);
|
|
return sectionTitle;
|
|
}
|
|
function sequenceOpen(code) {
|
|
if (code === Codes.colon) {
|
|
effects.consume(code);
|
|
sizeOpen++;
|
|
return sequenceOpen;
|
|
}
|
|
if (sizeOpen < ContainerSequenceSize) {
|
|
return nok(code);
|
|
}
|
|
effects.exit("componentContainerSequence");
|
|
return createName.call(self, effects, afterName, nok, "componentContainerName")(code);
|
|
}
|
|
function afterName(code) {
|
|
return code === Codes.openingSquareBracket ? effects.attempt(label, afterLabel, afterLabel)(code) : afterLabel(code);
|
|
}
|
|
function afterLabel(code) {
|
|
return code === Codes.openingCurlyBracket ? effects.attempt(attributes, afterAttributes, afterAttributes)(code) : afterAttributes(code);
|
|
}
|
|
function afterAttributes(code) {
|
|
return factorySpace(effects, openAfter, "whitespace")(code);
|
|
}
|
|
function openAfter(code) {
|
|
effects.exit("componentContainerFence");
|
|
if (code === null) {
|
|
effects.exit("componentContainer");
|
|
return ok(code);
|
|
}
|
|
if (markdownLineEnding(code)) {
|
|
effects.enter("lineEnding");
|
|
effects.consume(code);
|
|
effects.exit("lineEnding");
|
|
return self.interrupt ? ok : contentStart;
|
|
}
|
|
return nok(code);
|
|
}
|
|
function contentStart(code) {
|
|
if (code === null) {
|
|
effects.exit("componentContainer");
|
|
return ok(code);
|
|
}
|
|
if (containerFirstLine && (code === Codes.dash || markdownSpace(code))) {
|
|
containerFirstLine = false;
|
|
return tokenizeFrontMatter(effects, ok, nok, contentStart, initialPrefix)(code);
|
|
}
|
|
effects.enter("componentContainerContent");
|
|
return lineStart(code);
|
|
}
|
|
function lineStartAfterPrefix(code) {
|
|
if (code === null) {
|
|
return after(code);
|
|
}
|
|
if (code === Codes.backTick) {
|
|
return effects.check(
|
|
tokenizeCodeFence,
|
|
(code2) => {
|
|
visitingCodeFenced = !visitingCodeFenced;
|
|
return chunkStart(code2);
|
|
},
|
|
chunkStart
|
|
)(code);
|
|
}
|
|
if (visitingCodeFenced) {
|
|
return chunkStart(code);
|
|
}
|
|
if (!childContainersSequenceSize.length && (code === slotSeparatorCode || code === Codes.space)) {
|
|
return effects.attempt(
|
|
{ tokenize: tokenizeSectionClosing, partial: true },
|
|
sectionOpen,
|
|
chunkStart
|
|
)(code);
|
|
}
|
|
if (code === Codes.colon) {
|
|
return effects.attempt(
|
|
{ tokenize: tokenizeClosingFence, partial: true },
|
|
after,
|
|
chunkStart
|
|
)(code);
|
|
}
|
|
return chunkStart(code);
|
|
}
|
|
function lineStart(code) {
|
|
if (code === null) {
|
|
return after(code);
|
|
}
|
|
return initialPrefix ? factorySpace(effects, lineStartAfterPrefix, "linePrefix", initialPrefix + 1)(code) : lineStartAfterPrefix(code);
|
|
}
|
|
function chunkStart(code) {
|
|
if (code === null) {
|
|
return after(code);
|
|
}
|
|
section.enterOnce(effects);
|
|
const token = effects.enter("chunkDocument", {
|
|
contentType: "document",
|
|
previous
|
|
});
|
|
if (previous) {
|
|
previous.next = token;
|
|
}
|
|
previous = token;
|
|
return contentContinue(code);
|
|
}
|
|
function contentContinue(code) {
|
|
if (code === null) {
|
|
effects.exit("chunkDocument");
|
|
return after(code);
|
|
}
|
|
if (markdownLineEnding(code)) {
|
|
effects.consume(code);
|
|
effects.exit("chunkDocument");
|
|
return lineStart;
|
|
}
|
|
effects.consume(code);
|
|
return contentContinue;
|
|
}
|
|
function after(code) {
|
|
section.exit(effects);
|
|
effects.exit("componentContainerContent");
|
|
effects.exit("componentContainer");
|
|
return ok(code);
|
|
}
|
|
function tokenizeClosingFence(effects2, ok2, nok2) {
|
|
let size = 0;
|
|
return factorySpace(effects2, closingPrefixAfter, "linePrefix", 4);
|
|
function closingPrefixAfter(code) {
|
|
effects2.enter("componentContainerFence");
|
|
effects2.enter("componentContainerSequence");
|
|
return closingSequence(code);
|
|
}
|
|
function closingSequence(code) {
|
|
if (code === Codes.colon) {
|
|
effects2.consume(code);
|
|
size++;
|
|
return closingSequence;
|
|
}
|
|
if (childContainersSequenceSize.length) {
|
|
if (size === childContainersSequenceSize[childContainersSequenceSize.length - 1]) {
|
|
childContainersSequenceSize.pop();
|
|
}
|
|
return nok2(code);
|
|
}
|
|
if (size !== sizeOpen) {
|
|
return nok2(code);
|
|
}
|
|
effects2.exit("componentContainerSequence");
|
|
return factorySpace(effects2, closingSequenceEnd, "whitespace")(code);
|
|
}
|
|
function closingSequenceEnd(code) {
|
|
if (code === null || markdownLineEnding(code)) {
|
|
effects2.exit("componentContainerFence");
|
|
return ok2(code);
|
|
}
|
|
childContainersSequenceSize.push(size);
|
|
return nok2(code);
|
|
}
|
|
}
|
|
}
|
|
function tokenizeLabel(effects, ok, nok) {
|
|
return createLabel(
|
|
effects,
|
|
ok,
|
|
nok,
|
|
"componentContainerLabel",
|
|
"componentContainerLabelMarker",
|
|
"componentContainerLabelString",
|
|
true
|
|
);
|
|
}
|
|
function tokenizeAttributes(effects, ok, nok) {
|
|
return createAttributes(
|
|
effects,
|
|
ok,
|
|
nok,
|
|
"componentContainerAttributes",
|
|
"componentContainerAttributesMarker",
|
|
"componentContainerAttribute",
|
|
"componentContainerAttributeId",
|
|
"componentContainerAttributeClass",
|
|
"componentContainerAttributeName",
|
|
"componentContainerAttributeInitializerMarker",
|
|
"componentContainerAttributeValueLiteral",
|
|
"componentContainerAttributeValue",
|
|
"componentContainerAttributeValueMarker",
|
|
"componentContainerAttributeValueData",
|
|
true
|
|
);
|
|
}
|
|
const tokenizeContainer = {
|
|
tokenize: tokenize$2,
|
|
concrete: true
|
|
};
|
|
|
|
function tokenize$1(effects, ok, nok) {
|
|
const self = this;
|
|
return factorySpace(effects, lineStart, "linePrefix");
|
|
function lineStart(code) {
|
|
if (prefixSize(self.events, "linePrefix") < 4) {
|
|
return nok(code);
|
|
}
|
|
switch (code) {
|
|
case Codes.backTick:
|
|
return codeFenced.tokenize.call(self, effects, ok, nok)(code);
|
|
case Codes.colon:
|
|
return tokenizeContainer.tokenize.call(self, effects, ok, nok)(code);
|
|
default:
|
|
return nok(code);
|
|
}
|
|
}
|
|
}
|
|
const tokenizeContainerIndented = {
|
|
tokenize: tokenize$1
|
|
};
|
|
|
|
function tokenize(effects, ok, nok) {
|
|
const self = this;
|
|
const tokenizeSugerSyntax = tokenizeInline.tokenize.call(
|
|
self,
|
|
effects,
|
|
factorySpace(effects, exit, "linePrefix"),
|
|
nok
|
|
);
|
|
return factorySpace(effects, lineStart, "linePrefix");
|
|
function lineStart(code) {
|
|
if (code === Codes.colon) {
|
|
return tokenizeSugerSyntax(code);
|
|
}
|
|
return nok(code);
|
|
}
|
|
function exit(code) {
|
|
if (markdownLineEnding(code) || code === Codes.EOF) {
|
|
return ok(code);
|
|
}
|
|
return nok(code);
|
|
}
|
|
}
|
|
const tokenizeContainerSuger = {
|
|
tokenize
|
|
};
|
|
|
|
function micromarkComponentsExtension() {
|
|
return {
|
|
text: {
|
|
[Codes.colon]: tokenizeInline,
|
|
[Codes.openingSquareBracket]: [tokenizeSpan],
|
|
[Codes.openingCurlyBracket]: [tokenizeBinding, tokenizeAttribute]
|
|
},
|
|
flow: {
|
|
[Codes.colon]: [tokenizeContainer, tokenizeContainerSuger]
|
|
},
|
|
flowInitial: {
|
|
"-2": tokenizeContainerIndented,
|
|
"-1": tokenizeContainerIndented,
|
|
[Codes.space]: tokenizeContainerIndented
|
|
}
|
|
};
|
|
}
|
|
|
|
const toFrontMatter = (yamlString) => `---
|
|
${yamlString}
|
|
---`;
|
|
const remarkMDC = (function remarkMDC(opts = {}) {
|
|
const data = this.data();
|
|
if (opts.autoUnwrap === void 0 && opts.experimental?.autoUnwrap) {
|
|
opts.autoUnwrap = opts.experimental.autoUnwrap ? { safeTypes: [] } : false;
|
|
}
|
|
if (opts.yamlCodeBlockProps === void 0 && opts.experimental?.componentCodeBlockYamlProps) {
|
|
opts.yamlCodeBlockProps = opts.experimental.componentCodeBlockYamlProps;
|
|
}
|
|
add("micromarkExtensions", micromarkComponentsExtension());
|
|
add("fromMarkdownExtensions", fromMarkdown(opts));
|
|
add("toMarkdownExtensions", toMarkdown(opts));
|
|
function add(field, value) {
|
|
if (!data[field]) {
|
|
data[field] = [];
|
|
}
|
|
data[field].push(value);
|
|
}
|
|
if (opts?.components?.length) {
|
|
return async (tree, { data: data2 }) => {
|
|
const jobs = [];
|
|
visit(tree, ["textComponent", "leafComponent", "containerComponent"], (node) => {
|
|
bindNode(node);
|
|
const { instance: handler, options } = opts.components.find((c) => c.name === node.name) || {};
|
|
if (handler) {
|
|
jobs.push(handler(options)(node, data2));
|
|
}
|
|
});
|
|
await Promise.all(jobs);
|
|
return tree;
|
|
};
|
|
}
|
|
return (tree) => {
|
|
visit(tree, ["textComponent", "leafComponent", "containerComponent"], (node) => {
|
|
bindNode(node);
|
|
});
|
|
};
|
|
});
|
|
function bindNode(node) {
|
|
const nodeData = node.data || (node.data = {});
|
|
node.fmAttributes = getNodeData(node);
|
|
nodeData.hName = kebabCase(node.name);
|
|
nodeData.hProperties = bindData(
|
|
{
|
|
...node.attributes,
|
|
// Parse data slots and retrieve data
|
|
...node.fmAttributes
|
|
}
|
|
);
|
|
}
|
|
function getNodeData(node) {
|
|
if (node.rawData) {
|
|
const yaml = node.rawData.replace(/\s-+$/, "");
|
|
const { data } = parseFrontMatter(toFrontMatter(yaml));
|
|
return data;
|
|
}
|
|
return {};
|
|
}
|
|
function bindData(data) {
|
|
const entries = Object.entries(data).map(([key, value]) => {
|
|
if (key.startsWith(":")) {
|
|
return [key, value];
|
|
}
|
|
if (typeof value === "string") {
|
|
return [key, value];
|
|
}
|
|
return [`:${key}`, JSON.stringify(value)];
|
|
});
|
|
return Object.fromEntries(entries);
|
|
}
|
|
|
|
export { convertHtmlEntitiesToChars, remarkMDC as default, micromarkComponentsExtension as micromarkExtension, parseFrontMatter, stringifyFrontMatter };
|