UNPKG

alinea

Version:
131 lines (129 loc) 4.22 kB
import "../chunks/chunk-NZLE2WMY.js"; // src/ui/RichText.tsx import { BlockNode, ElementNode, Mark, Node, TextNode } from "alinea/core/TextDoc"; import { slugify } from "alinea/core/util/Slugs"; import { Fragment, isValidElement } from "react"; import { jsx } from "react/jsx-runtime"; function textContent(doc) { return doc.reduce((text, node) => { if (Node.isText(node)) return text + node.text; if ("content" in node && Array.isArray(node.content)) return text + textContent(node.content); return text; }, ""); } function nodeElement(type, attributes, content) { const style = { textAlign: attributes?.textAlign === "left" ? void 0 : attributes?.textAlign }; switch (type) { case "heading": { const Tag = `h${attributes?.level || 1}`; const id = attributes?.id ?? (content ? slugify(textContent(content)) : void 0); return /* @__PURE__ */ jsx(Tag, { style, id }); } case "paragraph": return /* @__PURE__ */ jsx("p", { style }); case "bold": return /* @__PURE__ */ jsx("b", {}); case "italic": return /* @__PURE__ */ jsx("i", {}); case "bulletList": return /* @__PURE__ */ jsx("ul", { style }); case "orderedList": return /* @__PURE__ */ jsx("ol", { style }); case "listItem": return /* @__PURE__ */ jsx("li", {}); case "blockquote": return /* @__PURE__ */ jsx("blockquote", { style }); case "horizontalRule": return /* @__PURE__ */ jsx("hr", {}); case "hardBreak": return /* @__PURE__ */ jsx("br", {}); case "small": return /* @__PURE__ */ jsx("small", {}); case "subscript": return /* @__PURE__ */ jsx("sub", {}); case "superscript": return /* @__PURE__ */ jsx("sup", {}); case "link": { const props = { href: attributes?.href, target: attributes?.target, title: attributes?.title }; return /* @__PURE__ */ jsx("a", { ...props }); } case "table": return /* @__PURE__ */ jsx("table", {}); case "tableBody": return /* @__PURE__ */ jsx("tbody", {}); case "tableCell": return /* @__PURE__ */ jsx("td", {}); case "tableHeader": return /* @__PURE__ */ jsx("th", {}); case "tableRow": return /* @__PURE__ */ jsx("tr", {}); } } function RichTextNodeView({ views, node }) { if (Node.isText(node)) { const { [TextNode.text]: text, [TextNode.marks]: marks } = node; const content = typeof views.text === "function" ? /* @__PURE__ */ jsx(views.text, { children: text }) : text; const wrappers = marks?.map((mark) => nodeElement(mark[Mark.type], mark)) || []; return wrappers.reduce((children, element) => { if (!element?.type) return children; const View = views[element.type]; if (View && !isValidElement(View)) { return /* @__PURE__ */ jsx(View, { ...element.props, children }); } const node2 = View ?? element; return /* @__PURE__ */ jsx(node2.type, { ...element?.props, ...node2.props, children }); }, content); } if (Node.isElement(node)) { const { [Node.type]: type, [ElementNode.content]: content, ...attrs } = node; const element = nodeElement(type, attrs, content); const View = views[element?.type || type]; const inner = content?.map((node2, i) => /* @__PURE__ */ jsx(RichTextNodeView, { views, node: node2 }, i)) || null; if (View && !isValidElement(View)) { return /* @__PURE__ */ jsx(View, { ...element?.props || attrs, children: inner }); } const el = View ?? element ?? { type: Fragment }; return /* @__PURE__ */ jsx(el.type, { ...element?.props, ...el.props, children: inner }); } if (Node.isBlock(node)) { const { [Node.type]: type, [BlockNode.id]: id, ...attrs } = node; const View = views[type]; if (!View) return null; return /* @__PURE__ */ jsx(View, { ...attrs }); } } function RichText({ doc, ...views }) { if (!Array.isArray(doc)) return null; return /* @__PURE__ */ jsx(Fragment, { children: doc.map((node, i) => { return /* @__PURE__ */ jsx( RichTextNodeView, { views, node }, i ); }) }); } export { RichText };