markpage
Version:
Build and manage markdown-based content with distributed navigation - framework agnostic content management system
189 lines (188 loc) • 5.66 kB
JavaScript
;
const builtinTokenNames = [
"blockquote",
"heading",
"list",
"list_item",
"br",
"code",
"codespan",
"table",
"html",
"paragraph",
"link",
"text",
"def",
"del",
"em",
"hr",
"strong",
"image",
"space"
];
const TAG = "[A-Z][A-Za-z0-9:_-]*";
const SELF = new RegExp(`^<(${TAG})\\s*([^>]*)/>`);
const OPEN = new RegExp(`^<(${TAG})\\s*([^>]*)>`);
function parseProps(attrs) {
const props = {};
if (!attrs) return props;
const re = /([a-zA-Z_][\w:-]*)=(?:"([^"]*)"|\{([\s\S]*?)\})|\b([a-zA-Z_][\w:-]*)\b/g;
let m;
while (m = re.exec(attrs)) {
const key = m[1] || m[4];
if (!key) continue;
if (m[2] !== void 0) {
props[key] = m[2];
} else if (m[3] !== void 0) {
try {
props[key] = JSON.parse(m[3]);
} catch {
props[key] = m[3];
}
} else if (m[4] !== void 0) {
props[key] = true;
}
}
return props;
}
function findMatchingClose(src, name, startIndex) {
const openTag = new RegExp(`<${name}(?:s[^>]*)?>`, "g");
const closeTag = new RegExp(`(?:</${name}>|</${name}>)`, "g");
openTag.lastIndex = startIndex;
closeTag.lastIndex = startIndex;
let depth = 1;
while (true) {
const nextOpen = openTag.exec(src);
const nextClose = closeTag.exec(src);
if (!nextClose) return -1;
if (nextOpen && nextOpen.index < nextClose.index) {
depth++;
continue;
}
depth--;
if (depth === 0) {
return nextClose.index + nextClose[0].length;
}
}
}
function createComponentExtension(markedInstance) {
return {
name: "component",
level: "block",
start(src) {
const i = src.search(/^\s*<[A-Z]/m);
return i < 0 ? void 0 : i;
},
tokenizer(src) {
let m = SELF.exec(src);
if (m) {
const raw = m[0];
const name = m[1];
const attrs = m[2] ?? "";
return { type: "component", raw, name, props: parseProps(attrs) };
}
m = OPEN.exec(src);
if (m) {
const openRaw = m[0];
const name = m[1];
const attrs = m[2] ?? "";
const innerStart = openRaw.length;
const endIndex = findMatchingClose(src, name, innerStart);
if (endIndex > -1) {
let lineEnd = endIndex;
while (lineEnd < src.length && src[lineEnd] !== "\n") {
lineEnd++;
}
if (lineEnd < src.length && src[lineEnd] === "\n") {
lineEnd++;
}
const raw = src.slice(0, lineEnd);
const inner = src.slice(innerStart, endIndex - `</${name}>`.length);
let children;
if (inner.trim()) {
try {
const { Marked: Marked2 } = require("marked");
const nestedMarked = new Marked2();
const nestedTokens = nestedMarked.lexer(inner);
children = nestedTokens.flatMap((token2) => {
if (token2.type === "paragraph" && token2.tokens) {
return token2.tokens;
}
return [token2];
});
} catch (error) {
children = [{ type: "text", raw: inner, text: inner.trim() }];
}
} else {
children = [];
}
const token = { type: "component", raw, name, props: parseProps(attrs), children };
return token;
} else {
const raw = openRaw;
return { type: "component", raw, name, props: parseProps(attrs) };
}
}
}
};
}
function createInlineComponentExtension(markedInstance) {
return {
name: "inline-component",
level: "inline",
start(src) {
const i = src.search(/<[A-Z]/);
return i < 0 ? void 0 : i;
},
tokenizer(src) {
let m = SELF.exec(src);
if (m) {
const raw = m[0];
const name = m[1];
const attrs = m[2] ?? "";
return { type: "component", raw, name, props: parseProps(attrs) };
}
m = OPEN.exec(src);
if (m) {
const openRaw = m[0];
const name = m[1];
const attrs = m[2] ?? "";
const innerStart = openRaw.length;
const endIndex = findMatchingClose(src, name, innerStart);
if (endIndex > -1) {
const raw = src.slice(0, endIndex + `</${name}>`.length);
const inner = src.slice(innerStart, endIndex - `</${name}>`.length);
let children;
if (inner.trim()) {
try {
const { Marked: Marked2 } = require("marked");
const nestedMarked = new Marked2();
const nestedTokens = nestedMarked.lexer(inner);
children = nestedTokens.flatMap((token2) => {
if (token2.type === "paragraph" && token2.tokens) {
return token2.tokens;
}
return [token2];
});
} catch (error) {
children = [{ type: "text", raw: inner, text: inner.trim() }];
}
} else {
children = [];
}
const token = { type: "component", raw, name, props: parseProps(attrs), children };
return token;
} else {
const raw = openRaw;
return { type: "component", raw, name, props: parseProps(attrs) };
}
}
}
};
}
const componentExtension = createComponentExtension();
exports.builtinTokenNames = builtinTokenNames;
exports.componentExtension = componentExtension;
exports.createComponentExtension = createComponentExtension;
exports.createInlineComponentExtension = createInlineComponentExtension;
//# sourceMappingURL=component-o8uZ9l7y.cjs.map