@scalar/code-highlight
Version:
Central methods and themes for code highlighting in Scalar projects
95 lines (94 loc) • 3.39 kB
JavaScript
import { visit } from "unist-util-visit";
const ALERT_TYPES = ["note", "tip", "important", "warning", "caution", "success"];
function isWhitespace(node) {
return node.type === "text" && typeof node.value === "string" && /^\s*$/.test(node.value);
}
function rehypeAlert() {
return (tree) => {
visit(tree, "element", (node, index, parent) => {
if (node.tagName !== "blockquote" || typeof index !== "number" || !parent || parent.type !== "root") {
return;
}
const headIndex = node.children.findIndex((child) => !isWhitespace(child));
if (headIndex === -1) {
return;
}
const head = node.children[headIndex];
if (!head || head.type !== "element" || head.tagName !== "p") {
return;
}
const text = head.children[0];
if (!text || text.type !== "text" || !text.value.startsWith("[!")) {
return;
}
const end = text.value.indexOf("]");
if (end === -1) {
return;
}
const alertType = text.value.slice(2, end).toLowerCase();
if (!ALERT_TYPES.includes(alertType)) {
return;
}
if (end + 1 === text.value.length) {
const next = head.children[1];
if (next) {
if (next.type !== "element" || next.tagName !== "br") {
return;
}
if (!head.children[2]) {
return;
}
head.children = head.children.slice(2);
const node2 = head.children[0];
if (node2 && node2.type === "text" && node2.value.charAt(0) === "\n") {
node2.value = node2.value.slice(1);
}
} else {
const skipped = headIndex + 1 < node.children.length && isWhitespace(node.children[headIndex + 1]);
const nextIndex = skipped ? headIndex + 2 : headIndex + 1;
if (nextIndex >= node.children.length || node.children[nextIndex]?.type !== "element") {
return;
}
node.children = node.children.slice(nextIndex);
}
} else if (text.value.charAt(end + 1) === "\n" && // Check if the next character is a newline or a non-whitespace character
(end + 2 === text.value.length || !/^\s*$/.test(text.value.slice(end + 2)))) {
text.value = text.value.slice(end + 2);
} else {
text.value = text.value.replace(/^\s*\[!.*?\]\s*/, "");
}
const contentChildren = [];
for (let i = headIndex; i < node.children.length; i++) {
const child = node.children[i];
if (child?.type === "element" && child.tagName === "p" && child.children) {
contentChildren.push(...child.children);
} else {
contentChildren.push(child);
}
}
parent.children[index] = {
type: "element",
tagName: "div",
properties: { className: ["markdown-alert", `markdown-alert-${alertType}`] },
children: [
{
type: "element",
tagName: "div",
properties: { className: ["markdown-alert-icon"] },
children: []
},
{
type: "element",
tagName: "div",
properties: { className: ["markdown-alert-content"] },
children: [{ type: "text", value: " " }, ...contentChildren]
}
]
};
});
};
}
export {
rehypeAlert
};
//# sourceMappingURL=rehype-alert.js.map