// const _text_styles_ = ["bold", "underline", "italic", "sup", "sub"]; import { RichTextBlockJSON, RichTextJSON, RichTextSectionJSON } from "@/types"; let _container = document.createElement("div"); /** * 将富文本 JSON 渲染到指定的元素中 * * @param {RichTextJSON} body * @param {HTMLDivElement} container */ export function renderRichText(body: RichTextJSON, container?: HTMLDivElement) { _container = container || document.createElement("div"); let sections = body?.sections || []; let nodes = [] as Array; sections.forEach((section) => { nodes.push(renderSection(section)); }); if (_container != undefined) { // container.classList.add("rich-text"); while (_container.hasChildNodes()) { _container.removeChild(_container.lastChild as Node); } nodes.forEach((node) => { _container.appendChild(node); }); } return _container; } /** * @param {RichTextSectionJSON} section * @returns {HTMLDivElement} 返回根据 section 渲染好的 HTMLDivElement */ function renderSection(section: RichTextSectionJSON) { let blocks = section.blocks || []; let inline = blocks.length > 1; let node = document.createElement("div"); // node.style = "display: flex;"; blocks.forEach((block) => { node.appendChild(renderBlock(block, inline)); }); return node; } /** * @param {RichTextBlockJSON} block * @param {Boolean} inline 图片是否以 inline 的样式展示 * @returns {HTMLElement} 返回根据 block 渲染好的 HTMLElement */ function renderBlock(block: RichTextBlockJSON, inline: boolean) { // let node = document.createElement('span') // let classList = node.classList let node; if (block.type === "text") { // classList.add('text') // if (block.param != undefined) { // _text_styles_.forEach(style => { // if (block.param[style] === true) { // classList.add(style) // } // }) // } if ( block.param && (block.param.underline || block.param.bold || block.param.italic) ) { let uNode: Node | null = null, bNode: Node | null = null, iNode: Node | null = null; if (block.param.underline) { uNode = document.createElement("u"); } if (block.param.bold) { bNode = document.createElement("b"); } if (block.param.italic) { iNode = document.createElement("i"); } // 将不为空的元素依次append node = ([uNode, bNode, iNode] as Array) .filter((v) => v) .reduceRight((p, c) => { c.appendChild(p); return c; }); let childNode = node; for (let i = 0; i < 3; i++) { if (childNode && childNode.hasChildNodes()) { childNode = childNode.childNodes[0]; } } childNode.textContent = block.value; } else { node = document.createTextNode(block.value); } } else if (block.type === "image") { node = document.createElement("img"); if (inline === true) { node.classList.add("inline"); } node.src = block.value; // param if (block.param) { const { width, height } = block.param; width && (node.style.width = width + "px"); height && (node.style.height = height + "px"); } } else if (block.type === "audio") { node = document.createElement("audio"); node.className = "audio"; node.src = block.value; node.controls = true; } return node as Node; }