82 lines
2.2 KiB
JavaScript
82 lines
2.2 KiB
JavaScript
export const TEXT_TAGS = ["p", "h1", "h2", "h3", "h4", "h5", "h6", "li"];
|
|
export function isTag(vnode, tag) {
|
|
if (vnode.type === tag) {
|
|
return true;
|
|
}
|
|
if (typeof vnode.type === "object" && vnode.type.tag === tag) {
|
|
return true;
|
|
}
|
|
if (vnode.tag === tag) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
export function isText(vnode) {
|
|
return isTag(vnode, "text") || isTag(vnode, Symbol.for("v-txt"));
|
|
}
|
|
export function nodeChildren(node) {
|
|
if (Array.isArray(node.children) || typeof node.children === "string") {
|
|
return node.children;
|
|
}
|
|
if (typeof node.children?.default === "function") {
|
|
return node.children.default();
|
|
}
|
|
return [];
|
|
}
|
|
export function nodeTextContent(node) {
|
|
if (!node) {
|
|
return "";
|
|
}
|
|
if (Array.isArray(node)) {
|
|
return node.map(nodeTextContent).join("");
|
|
}
|
|
if (isText(node)) {
|
|
return node.children || node.value || "";
|
|
}
|
|
const children = nodeChildren(node);
|
|
if (Array.isArray(children)) {
|
|
return children.map(nodeTextContent).filter(Boolean).join("");
|
|
}
|
|
return "";
|
|
}
|
|
export function unwrap(vnode, tags = []) {
|
|
if (Array.isArray(vnode)) {
|
|
return vnode.flatMap((node) => unwrap(node, tags));
|
|
}
|
|
let result = vnode;
|
|
if (tags.some((tag) => tag === "*" || isTag(vnode, tag))) {
|
|
result = nodeChildren(vnode) || vnode;
|
|
if (!Array.isArray(result) && TEXT_TAGS.some((tag) => isTag(vnode, tag))) {
|
|
result = [result];
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
function _flatUnwrap(vnodes, tags = []) {
|
|
vnodes = Array.isArray(vnodes) ? vnodes : [vnodes];
|
|
if (!tags.length) {
|
|
return vnodes;
|
|
}
|
|
return vnodes.flatMap((vnode) => _flatUnwrap(unwrap(vnode, [tags[0]]), tags.slice(1))).filter((vnode) => !(isText(vnode) && nodeTextContent(vnode).trim() === ""));
|
|
}
|
|
export function flatUnwrap(vnodes, tags = []) {
|
|
if (typeof tags === "string") {
|
|
tags = tags.split(/[,\s]/).map((tag) => tag.trim()).filter(Boolean);
|
|
}
|
|
if (!tags.length) {
|
|
return vnodes;
|
|
}
|
|
return _flatUnwrap(vnodes, tags).reduce((acc, item) => {
|
|
if (isText(item)) {
|
|
if (typeof acc[acc.length - 1] === "string") {
|
|
acc[acc.length - 1] += item.children;
|
|
} else {
|
|
acc.push(item.children);
|
|
}
|
|
} else {
|
|
acc.push(item);
|
|
}
|
|
return acc;
|
|
}, []);
|
|
}
|