alinea
Version:
Headless git-based CMS
131 lines (129 loc) • 4.22 kB
JavaScript
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
};