@lobehub/ui
Version:
Lobe UI is an open-source UI component library for building AIGC web apps
70 lines (68 loc) • 1.84 kB
JavaScript
import { visit } from "../../node_modules/unist-util-visit/lib/index.mjs";
//#region src/Markdown/plugins/rehypeStreamAnimated.ts
const BLOCK_TAGS = new Set([
"p",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"li"
]);
const SKIP_TAGS = new Set([
"pre",
"code",
"table",
"svg"
]);
function hasClass(node, cls) {
const cn = node.properties?.className;
if (Array.isArray(cn)) return cn.some((c) => String(c).includes(cls));
if (typeof cn === "string") return cn.includes(cls);
return false;
}
const rehypeStreamAnimated = (options = {}) => {
const { charDelay = 20, baseCharCount = 0, revealed = false } = options;
return (tree) => {
let globalCharIndex = 0;
const shouldSkip = (node) => {
return SKIP_TAGS.has(node.tagName) || hasClass(node, "katex");
};
const wrapText = (node) => {
const newChildren = [];
for (const child of node.children) if (child.type === "text") for (const char of child.value) {
const properties = { className: revealed ? "stream-char stream-char-revealed" : "stream-char" };
if (!revealed) {
const delay = Math.max(0, globalCharIndex - baseCharCount) * charDelay;
if (delay > 0) properties.style = `animation-delay:${delay}ms`;
}
newChildren.push({
children: [{
type: "text",
value: char
}],
properties,
tagName: "span",
type: "element"
});
globalCharIndex++;
}
else if (child.type === "element") {
if (!shouldSkip(child)) wrapText(child);
newChildren.push(child);
} else newChildren.push(child);
node.children = newChildren;
};
visit(tree, "element", ((node) => {
if (shouldSkip(node)) return "skip";
if (BLOCK_TAGS.has(node.tagName)) {
wrapText(node);
return "skip";
}
}));
};
};
//#endregion
export { rehypeStreamAnimated };
//# sourceMappingURL=rehypeStreamAnimated.mjs.map