123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- // 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<Node>;
- 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<Node>)
- .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;
- }
|