alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
124 lines (122 loc) • 4 kB
JavaScript
import "../chunks/chunk-U5RRZUYZ.js";
// src/ui/RichText.tsx
import { slugify } from "alinea/core";
import { Fragment, isValidElement } from "react";
import { Fragment as Fragment2, jsx } from "react/jsx-runtime";
var Elements = /* @__PURE__ */ ((Elements2) => {
Elements2["h1"] = "h1";
Elements2["h2"] = "h2";
Elements2["h3"] = "h3";
Elements2["h4"] = "h4";
Elements2["h5"] = "h5";
Elements2["h6"] = "h6";
Elements2["p"] = "p";
Elements2["b"] = "b";
Elements2["i"] = "i";
Elements2["ul"] = "ul";
Elements2["ol"] = "ol";
Elements2["li"] = "li";
Elements2["a"] = "a";
Elements2["hr"] = "hr";
Elements2["br"] = "br";
Elements2["small"] = "small";
return Elements2;
})(Elements || {});
function textContent(doc) {
return doc.reduce((text, node) => {
switch (node.type) {
case "text":
return text + node.text;
default:
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 "link":
return /* @__PURE__ */ jsx("a", { ...attributes });
}
}
function RichTextNodeView({ views, node }) {
switch (node.type) {
case "text": {
const { text, marks } = node;
const content = typeof views.text === "function" ? /* @__PURE__ */ jsx(views.text, { children: text }) : text;
const wrappers = marks?.map((mark) => nodeElement(mark.type, mark.attrs)) || [];
return wrappers.reduce((children, element) => {
if (!element?.type)
return /* @__PURE__ */ jsx(Fragment2, { children });
const View = views[element.type];
if (View && !isValidElement(View)) {
return /* @__PURE__ */ jsx(View, { ...element.props, children });
} else {
const node2 = View ?? element;
return /* @__PURE__ */ jsx(node2.type, { ...element?.props, ...node2.props, children });
}
}, /* @__PURE__ */ jsx(Fragment2, { children: content }));
}
default: {
const { type, 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 });
} else {
const node2 = View ?? element ?? { type: Fragment };
return /* @__PURE__ */ jsx(node2.type, { ...element?.props, ...node2.props, children: inner });
}
}
}
}
function RichText({
doc,
...views
}) {
if (!Array.isArray(doc))
return null;
return /* @__PURE__ */ jsx(Fragment2, { children: doc.map((node, i) => {
return /* @__PURE__ */ jsx(
RichTextNodeView,
{
views,
node
},
i
);
}) });
}
export {
Elements,
RichText
};