@uniformdev/richtext 19.14.1-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.txt ADDED
@@ -0,0 +1,2 @@
1
+ © 2023 Uniform Systems, Inc. All Rights Reserved.
2
+ See details of Uniform Systems, Inc. Master Subscription Agreement here: https://uniform.dev/eula
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ RichText parameter functionality for Uniform Platform
2
+
3
+ part of the [Uniform Platform](https://uniform.app). See our [documentation](https://docs.uniform.app) for more details.
@@ -0,0 +1,123 @@
1
+ import { LinkParamValue } from '@uniformdev/canvas';
2
+
3
+ declare function purifyText(text: string): string;
4
+ declare function isPureTextAlign(format?: string): format is string;
5
+ declare function isPureDirection(direction?: string): direction is string;
6
+ declare function renderHtmlElement(tag: string, attributes: Map<string, string> | null, children?: string): string;
7
+
8
+ interface RichTextNode extends Record<string, unknown> {
9
+ type: string;
10
+ children?: RichTextNode[];
11
+ }
12
+ type RichTextNodeWithChildren = RichTextNode & {
13
+ children: RichTextNode[];
14
+ };
15
+ type ResolveStringRenderer = (context: StringRenderContext) => NodeStringRenderer | null | undefined;
16
+ interface StringRenderContext {
17
+ currentNode: RichTextNode;
18
+ ancestorNodes: RichTextNode[];
19
+ resolveRenderer?: ResolveStringRenderer;
20
+ }
21
+ interface NodeStringRendererProps {
22
+ context: StringRenderContext;
23
+ renderChildren(children?: RichTextNode[] | unknown): string;
24
+ }
25
+ type NodeStringRenderer = (props: NodeStringRendererProps) => string;
26
+ type ParameterRichTextValue = {
27
+ root: RichTextNode;
28
+ } | undefined;
29
+
30
+ interface HeadingNode extends RichTextNode {
31
+ tag: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
32
+ }
33
+ declare const headingHtmlRenderer: NodeStringRenderer;
34
+
35
+ interface LinkNode extends RichTextNode {
36
+ link: NonNullable<LinkParamValue>;
37
+ }
38
+ declare const linkHtmlRenderer: NodeStringRenderer;
39
+ declare function linkParamValueToHref(link: LinkParamValue): string | undefined;
40
+
41
+ interface ListNode extends RichTextNode {
42
+ tag: 'ul' | 'ol';
43
+ start: number;
44
+ }
45
+ declare const listHtmlRenderer: NodeStringRenderer;
46
+
47
+ interface ListItemNode extends RichTextNode {
48
+ value: number;
49
+ }
50
+ declare const listitemHtmlRenderer: NodeStringRenderer;
51
+
52
+ interface ParagraphNode extends RichTextNode {
53
+ format?: 'center' | 'end' | 'justify' | 'left' | 'match-parent' | 'right' | 'start';
54
+ direction?: 'ltr' | 'rtl';
55
+ }
56
+ declare const paragraphHtmlRenderer: NodeStringRenderer;
57
+
58
+ declare const rootHtmlRenderer: NodeStringRenderer;
59
+
60
+ interface TextNode extends RichTextNode {
61
+ /**
62
+ * The format is a bitflag value
63
+ * flags:
64
+ * position 1: bold
65
+ * position 2: italic
66
+ * position 3: strikethrough
67
+ * position 4: underline
68
+ * position 5: code
69
+ * position 6: subscript
70
+ * position 7: superscript
71
+ */
72
+ format: number;
73
+ text: string;
74
+ }
75
+ declare const textHtmlRenderer: NodeStringRenderer;
76
+ /**
77
+ * Convert format bitflag for holding text formats
78
+ * into relevant tags
79
+ */
80
+ declare function getRichTextTagsFromTextFormat(format: number): string[];
81
+
82
+ declare function isArrayWithLength<T>(arr: T[] | unknown | undefined): arr is T[];
83
+ declare function isRichTextNode(node: unknown): node is RichTextNode;
84
+ declare function isRichTextNodeType(node: unknown, type: 'heading'): node is HeadingNode;
85
+ declare function isRichTextNodeType(node: unknown, type: 'paragraph'): node is ParagraphNode;
86
+ declare function isRichTextNodeType(node: unknown, type: 'text'): node is TextNode;
87
+ declare function isRichTextNodeType(node: unknown, type: 'list'): node is ListNode;
88
+ declare function isRichTextNodeType(node: unknown, type: 'listitem'): node is ListItemNode;
89
+ declare function isRichTextNodeType(node: unknown, type: 'link'): node is LinkNode;
90
+ declare function isRichTextNodeType(node: unknown, type: string): node is RichTextNode;
91
+ declare function hasChildren<TRichTextNode extends RichTextNode>(node: TRichTextNode): node is TRichTextNode & {
92
+ children: RichTextNode[];
93
+ };
94
+
95
+ /**
96
+ * When a custom renderer has not been provided we
97
+ * check to see if there is a renderer for the type
98
+ * within the map above. These are for any node types
99
+ * which include extra logic.
100
+ *
101
+ * Some node types like quote just map directly to a
102
+ * HTML tag (ie blockquote). For those there is a simple
103
+ * type -> tag Map.
104
+ */
105
+ declare const resolveDefaultRenderer: ResolveStringRenderer;
106
+ /**
107
+ * Render a node and it's children to HTML
108
+ *
109
+ * This could be the root node or a nested node
110
+ */
111
+ declare function renderToHtml(node: RichTextNode | null | undefined, parentContext?: Partial<StringRenderContext>): string;
112
+ /**
113
+ * Render an array of RichTextNodes to a string based
114
+ * on a particular context.
115
+ *
116
+ * This will often be called from within a NodeRenderer
117
+ * using the `renderChildren` prop.
118
+ */
119
+ declare function renderChildrenToHtml(children: RichTextNode[] | undefined, context: StringRenderContext): string;
120
+
121
+ declare const walkRichTextTree: (node: RichTextNode, callback: (node: RichTextNode, parent: RichTextNode | undefined) => void, parent?: RichTextNode) => void;
122
+
123
+ export { HeadingNode, LinkNode, ListItemNode, ListNode, NodeStringRenderer, NodeStringRendererProps, ParagraphNode, ParameterRichTextValue, ResolveStringRenderer, RichTextNode, RichTextNodeWithChildren, StringRenderContext, TextNode, getRichTextTagsFromTextFormat, hasChildren, headingHtmlRenderer, isArrayWithLength, isPureDirection, isPureTextAlign, isRichTextNode, isRichTextNodeType, linkHtmlRenderer, linkParamValueToHref, listHtmlRenderer, listitemHtmlRenderer, paragraphHtmlRenderer, purifyText, renderChildrenToHtml, renderHtmlElement, renderToHtml, resolveDefaultRenderer, rootHtmlRenderer, textHtmlRenderer, walkRichTextTree };
@@ -0,0 +1,257 @@
1
+ // src/elements.ts
2
+ var rendererTypeTagMap = /* @__PURE__ */ new Map([
3
+ ["linebreak", "br"],
4
+ ["quote", "blockquote"]
5
+ ]);
6
+ function purifyText(text) {
7
+ return text.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
8
+ }
9
+ function isPureTextAlign(format) {
10
+ return Boolean(format && ["center", "end", "justify", "left", "right", "start"].includes(format));
11
+ }
12
+ function isPureDirection(direction) {
13
+ return Boolean(direction && ["ltr", "rtl"].includes(direction));
14
+ }
15
+ var voidElements = /* @__PURE__ */ new Set([
16
+ "area",
17
+ "base",
18
+ "br",
19
+ "col",
20
+ "embed",
21
+ "hr",
22
+ "img",
23
+ "input",
24
+ "link",
25
+ "meta",
26
+ "source",
27
+ "track",
28
+ "wbr"
29
+ ]);
30
+ function renderHtmlElement(tag, attributes, children) {
31
+ const attributesString = attributes && attributes.size > 0 ? " " + Array.from(attributes).reduce((result, [key, value]) => [...result, `${key}="${value}"`], []).join(" ") : "";
32
+ return voidElements.has(tag) ? `<${tag}${attributesString}>` : `<${tag}${attributesString}>${children != null ? children : ""}</${tag}>`;
33
+ }
34
+
35
+ // src/guards.ts
36
+ function isArrayWithLength(arr) {
37
+ return Array.isArray(arr) && arr.length > 0;
38
+ }
39
+ function isRichTextNode(node) {
40
+ return !!node && typeof node === "object" && "type" in node;
41
+ }
42
+ function isRichTextNodeType(node, type) {
43
+ return isRichTextNode(node) && node.type === type;
44
+ }
45
+ function hasChildren(node) {
46
+ return "children" in node && isArrayWithLength(node.children);
47
+ }
48
+
49
+ // src/nodes/heading.ts
50
+ var headingHtmlRenderer = ({ context, renderChildren }) => {
51
+ var _a;
52
+ const node = context.currentNode;
53
+ return renderHtmlElement((_a = node.tag) != null ? _a : "h1", null, renderChildren(context.currentNode.children));
54
+ };
55
+
56
+ // src/nodes/link.ts
57
+ var linkHtmlRenderer = ({ context, renderChildren }) => {
58
+ const node = context.currentNode;
59
+ const attributes = /* @__PURE__ */ new Map();
60
+ const href = linkParamValueToHref(node.link);
61
+ if (href) {
62
+ attributes.set("href", href);
63
+ }
64
+ return renderHtmlElement("a", attributes, renderChildren(context.currentNode.children));
65
+ };
66
+ function linkParamValueToHref(link) {
67
+ switch (link == null ? void 0 : link.type) {
68
+ case "email":
69
+ return `mailto:${link.path}`;
70
+ case "tel":
71
+ return `tel:${link.path}`;
72
+ case "url":
73
+ return link.path;
74
+ case "projectMapNode":
75
+ return link.path;
76
+ }
77
+ }
78
+
79
+ // src/nodes/list.ts
80
+ var listHtmlRenderer = ({ context, renderChildren }) => {
81
+ var _a;
82
+ const node = context.currentNode;
83
+ const attributes = /* @__PURE__ */ new Map();
84
+ if (node.start > 1) {
85
+ attributes.set("start", node.start.toString());
86
+ }
87
+ return renderHtmlElement((_a = node.tag) != null ? _a : "ul", attributes, renderChildren(context.currentNode.children));
88
+ };
89
+
90
+ // src/nodes/listitem.ts
91
+ var listitemHtmlRenderer = ({ context, renderChildren }) => {
92
+ const node = context.currentNode;
93
+ const attributes = /* @__PURE__ */ new Map();
94
+ if (Number.isFinite(node.value)) {
95
+ attributes.set("value", (node.value + 1).toString());
96
+ }
97
+ return renderHtmlElement("li", attributes, renderChildren(context.currentNode.children));
98
+ };
99
+
100
+ // src/nodes/paragraph.ts
101
+ var paragraphHtmlRenderer = ({ context, renderChildren }) => {
102
+ const node = context.currentNode;
103
+ const attributes = /* @__PURE__ */ new Map();
104
+ if (isPureTextAlign(node.format)) {
105
+ attributes.set("style", `text-align: ${node.format};`);
106
+ }
107
+ if (isPureDirection(node.direction)) {
108
+ attributes.set("dir", node.direction);
109
+ }
110
+ return renderHtmlElement(
111
+ "p",
112
+ attributes,
113
+ hasChildren(context.currentNode) ? renderChildren(context.currentNode.children) : "<br>"
114
+ );
115
+ };
116
+
117
+ // src/nodes/root.ts
118
+ var rootHtmlRenderer = ({ context, renderChildren }) => {
119
+ return hasChildren(context.currentNode) ? renderChildren(context.currentNode.children) : "";
120
+ };
121
+
122
+ // src/nodes/text.ts
123
+ var textHtmlRenderer = ({ context }) => {
124
+ const node = context.currentNode;
125
+ const tags = getRichTextTagsFromTextFormat(node.format);
126
+ const pureText = purifyText(node.text);
127
+ return tags.length === 0 ? pureText : tags.reduceRight((children, tag) => {
128
+ return renderHtmlElement(tag, null, children);
129
+ }, pureText);
130
+ };
131
+ function getRichTextTagsFromTextFormat(format) {
132
+ const tags = [];
133
+ if (format & 1 << 0) {
134
+ tags.push("strong");
135
+ }
136
+ if (format & 1 << 1) {
137
+ tags.push("em");
138
+ }
139
+ if (format & 1 << 2) {
140
+ tags.push("s");
141
+ }
142
+ if (format & 1 << 3) {
143
+ tags.push("u");
144
+ }
145
+ if (format & 1 << 4) {
146
+ tags.push("code");
147
+ }
148
+ if (format & 1 << 5) {
149
+ tags.push("sub");
150
+ }
151
+ if (format & 1 << 6) {
152
+ tags.push("sup");
153
+ }
154
+ return tags;
155
+ }
156
+
157
+ // src/nodes/tab.ts
158
+ var tabHtmlRenderer = () => {
159
+ return " ";
160
+ };
161
+
162
+ // src/renderToHtml.ts
163
+ var rendererTypeMap = /* @__PURE__ */ new Map([
164
+ ["heading", headingHtmlRenderer],
165
+ ["link", linkHtmlRenderer],
166
+ ["list", listHtmlRenderer],
167
+ ["listitem", listitemHtmlRenderer],
168
+ ["paragraph", paragraphHtmlRenderer],
169
+ ["root", rootHtmlRenderer],
170
+ ["text", textHtmlRenderer],
171
+ ["tab", tabHtmlRenderer]
172
+ ]);
173
+ var resolveDefaultRenderer = (context) => {
174
+ const renderer = rendererTypeMap.get(context.currentNode.type);
175
+ if (renderer) {
176
+ return renderer;
177
+ }
178
+ const tag = rendererTypeTagMap.get(context.currentNode.type);
179
+ if (tag) {
180
+ return ({ renderChildren }) => renderHtmlElement(
181
+ tag,
182
+ null,
183
+ hasChildren(context.currentNode) ? renderChildren(context.currentNode.children) : void 0
184
+ );
185
+ }
186
+ return () => `<!-- WARNING: No renderer for type ${context.currentNode.type} -->`;
187
+ };
188
+ function initializeRenderContext(node, parentContext) {
189
+ let ancestorNodes = [];
190
+ if (parentContext == null ? void 0 : parentContext.ancestorNodes) {
191
+ ancestorNodes = ancestorNodes.concat(parentContext.ancestorNodes);
192
+ }
193
+ if (parentContext == null ? void 0 : parentContext.currentNode) {
194
+ ancestorNodes.unshift(parentContext.currentNode);
195
+ }
196
+ return {
197
+ ...parentContext != null ? parentContext : {},
198
+ currentNode: node,
199
+ ancestorNodes
200
+ };
201
+ }
202
+ function renderToHtml(node, parentContext) {
203
+ var _a;
204
+ if (!isRichTextNode(node))
205
+ return "";
206
+ const context = initializeRenderContext(node, parentContext);
207
+ let renderer = (_a = context.resolveRenderer) == null ? void 0 : _a.call(context, context);
208
+ if (typeof renderer === "undefined") {
209
+ renderer = resolveDefaultRenderer(context);
210
+ } else if (renderer === null) {
211
+ return "";
212
+ }
213
+ const renderChildren = (children) => renderChildrenToHtml(children, context);
214
+ if (renderer) {
215
+ return renderer({ context, renderChildren });
216
+ } else {
217
+ throw new Error(`There is no renderer for node type: ${context.currentNode.type}`);
218
+ }
219
+ }
220
+ function renderChildrenToHtml(children, context) {
221
+ return Array.isArray(children) ? children.map((node) => renderToHtml(node, context)).join("") : "";
222
+ }
223
+
224
+ // src/utils.ts
225
+ var walkRichTextTree = (node, callback, parent) => {
226
+ callback(node, parent);
227
+ if (Array.isArray(node.children)) {
228
+ let i = 0;
229
+ while (node.children.length > i) {
230
+ walkRichTextTree(node.children[i], callback, node);
231
+ i += 1;
232
+ }
233
+ }
234
+ };
235
+ export {
236
+ getRichTextTagsFromTextFormat,
237
+ hasChildren,
238
+ headingHtmlRenderer,
239
+ isArrayWithLength,
240
+ isPureDirection,
241
+ isPureTextAlign,
242
+ isRichTextNode,
243
+ isRichTextNodeType,
244
+ linkHtmlRenderer,
245
+ linkParamValueToHref,
246
+ listHtmlRenderer,
247
+ listitemHtmlRenderer,
248
+ paragraphHtmlRenderer,
249
+ purifyText,
250
+ renderChildrenToHtml,
251
+ renderHtmlElement,
252
+ renderToHtml,
253
+ resolveDefaultRenderer,
254
+ rootHtmlRenderer,
255
+ textHtmlRenderer,
256
+ walkRichTextTree
257
+ };
package/dist/index.js ADDED
@@ -0,0 +1,304 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ getRichTextTagsFromTextFormat: () => getRichTextTagsFromTextFormat,
24
+ hasChildren: () => hasChildren,
25
+ headingHtmlRenderer: () => headingHtmlRenderer,
26
+ isArrayWithLength: () => isArrayWithLength,
27
+ isPureDirection: () => isPureDirection,
28
+ isPureTextAlign: () => isPureTextAlign,
29
+ isRichTextNode: () => isRichTextNode,
30
+ isRichTextNodeType: () => isRichTextNodeType,
31
+ linkHtmlRenderer: () => linkHtmlRenderer,
32
+ linkParamValueToHref: () => linkParamValueToHref,
33
+ listHtmlRenderer: () => listHtmlRenderer,
34
+ listitemHtmlRenderer: () => listitemHtmlRenderer,
35
+ paragraphHtmlRenderer: () => paragraphHtmlRenderer,
36
+ purifyText: () => purifyText,
37
+ renderChildrenToHtml: () => renderChildrenToHtml,
38
+ renderHtmlElement: () => renderHtmlElement,
39
+ renderToHtml: () => renderToHtml,
40
+ resolveDefaultRenderer: () => resolveDefaultRenderer,
41
+ rootHtmlRenderer: () => rootHtmlRenderer,
42
+ textHtmlRenderer: () => textHtmlRenderer,
43
+ walkRichTextTree: () => walkRichTextTree
44
+ });
45
+ module.exports = __toCommonJS(src_exports);
46
+
47
+ // src/elements.ts
48
+ var rendererTypeTagMap = /* @__PURE__ */ new Map([
49
+ ["linebreak", "br"],
50
+ ["quote", "blockquote"]
51
+ ]);
52
+ function purifyText(text) {
53
+ return text.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
54
+ }
55
+ function isPureTextAlign(format) {
56
+ return Boolean(format && ["center", "end", "justify", "left", "right", "start"].includes(format));
57
+ }
58
+ function isPureDirection(direction) {
59
+ return Boolean(direction && ["ltr", "rtl"].includes(direction));
60
+ }
61
+ var voidElements = /* @__PURE__ */ new Set([
62
+ "area",
63
+ "base",
64
+ "br",
65
+ "col",
66
+ "embed",
67
+ "hr",
68
+ "img",
69
+ "input",
70
+ "link",
71
+ "meta",
72
+ "source",
73
+ "track",
74
+ "wbr"
75
+ ]);
76
+ function renderHtmlElement(tag, attributes, children) {
77
+ const attributesString = attributes && attributes.size > 0 ? " " + Array.from(attributes).reduce((result, [key, value]) => [...result, `${key}="${value}"`], []).join(" ") : "";
78
+ return voidElements.has(tag) ? `<${tag}${attributesString}>` : `<${tag}${attributesString}>${children != null ? children : ""}</${tag}>`;
79
+ }
80
+
81
+ // src/guards.ts
82
+ function isArrayWithLength(arr) {
83
+ return Array.isArray(arr) && arr.length > 0;
84
+ }
85
+ function isRichTextNode(node) {
86
+ return !!node && typeof node === "object" && "type" in node;
87
+ }
88
+ function isRichTextNodeType(node, type) {
89
+ return isRichTextNode(node) && node.type === type;
90
+ }
91
+ function hasChildren(node) {
92
+ return "children" in node && isArrayWithLength(node.children);
93
+ }
94
+
95
+ // src/nodes/heading.ts
96
+ var headingHtmlRenderer = ({ context, renderChildren }) => {
97
+ var _a;
98
+ const node = context.currentNode;
99
+ return renderHtmlElement((_a = node.tag) != null ? _a : "h1", null, renderChildren(context.currentNode.children));
100
+ };
101
+
102
+ // src/nodes/link.ts
103
+ var linkHtmlRenderer = ({ context, renderChildren }) => {
104
+ const node = context.currentNode;
105
+ const attributes = /* @__PURE__ */ new Map();
106
+ const href = linkParamValueToHref(node.link);
107
+ if (href) {
108
+ attributes.set("href", href);
109
+ }
110
+ return renderHtmlElement("a", attributes, renderChildren(context.currentNode.children));
111
+ };
112
+ function linkParamValueToHref(link) {
113
+ switch (link == null ? void 0 : link.type) {
114
+ case "email":
115
+ return `mailto:${link.path}`;
116
+ case "tel":
117
+ return `tel:${link.path}`;
118
+ case "url":
119
+ return link.path;
120
+ case "projectMapNode":
121
+ return link.path;
122
+ }
123
+ }
124
+
125
+ // src/nodes/list.ts
126
+ var listHtmlRenderer = ({ context, renderChildren }) => {
127
+ var _a;
128
+ const node = context.currentNode;
129
+ const attributes = /* @__PURE__ */ new Map();
130
+ if (node.start > 1) {
131
+ attributes.set("start", node.start.toString());
132
+ }
133
+ return renderHtmlElement((_a = node.tag) != null ? _a : "ul", attributes, renderChildren(context.currentNode.children));
134
+ };
135
+
136
+ // src/nodes/listitem.ts
137
+ var listitemHtmlRenderer = ({ context, renderChildren }) => {
138
+ const node = context.currentNode;
139
+ const attributes = /* @__PURE__ */ new Map();
140
+ if (Number.isFinite(node.value)) {
141
+ attributes.set("value", (node.value + 1).toString());
142
+ }
143
+ return renderHtmlElement("li", attributes, renderChildren(context.currentNode.children));
144
+ };
145
+
146
+ // src/nodes/paragraph.ts
147
+ var paragraphHtmlRenderer = ({ context, renderChildren }) => {
148
+ const node = context.currentNode;
149
+ const attributes = /* @__PURE__ */ new Map();
150
+ if (isPureTextAlign(node.format)) {
151
+ attributes.set("style", `text-align: ${node.format};`);
152
+ }
153
+ if (isPureDirection(node.direction)) {
154
+ attributes.set("dir", node.direction);
155
+ }
156
+ return renderHtmlElement(
157
+ "p",
158
+ attributes,
159
+ hasChildren(context.currentNode) ? renderChildren(context.currentNode.children) : "<br>"
160
+ );
161
+ };
162
+
163
+ // src/nodes/root.ts
164
+ var rootHtmlRenderer = ({ context, renderChildren }) => {
165
+ return hasChildren(context.currentNode) ? renderChildren(context.currentNode.children) : "";
166
+ };
167
+
168
+ // src/nodes/text.ts
169
+ var textHtmlRenderer = ({ context }) => {
170
+ const node = context.currentNode;
171
+ const tags = getRichTextTagsFromTextFormat(node.format);
172
+ const pureText = purifyText(node.text);
173
+ return tags.length === 0 ? pureText : tags.reduceRight((children, tag) => {
174
+ return renderHtmlElement(tag, null, children);
175
+ }, pureText);
176
+ };
177
+ function getRichTextTagsFromTextFormat(format) {
178
+ const tags = [];
179
+ if (format & 1 << 0) {
180
+ tags.push("strong");
181
+ }
182
+ if (format & 1 << 1) {
183
+ tags.push("em");
184
+ }
185
+ if (format & 1 << 2) {
186
+ tags.push("s");
187
+ }
188
+ if (format & 1 << 3) {
189
+ tags.push("u");
190
+ }
191
+ if (format & 1 << 4) {
192
+ tags.push("code");
193
+ }
194
+ if (format & 1 << 5) {
195
+ tags.push("sub");
196
+ }
197
+ if (format & 1 << 6) {
198
+ tags.push("sup");
199
+ }
200
+ return tags;
201
+ }
202
+
203
+ // src/nodes/tab.ts
204
+ var tabHtmlRenderer = () => {
205
+ return " ";
206
+ };
207
+
208
+ // src/renderToHtml.ts
209
+ var rendererTypeMap = /* @__PURE__ */ new Map([
210
+ ["heading", headingHtmlRenderer],
211
+ ["link", linkHtmlRenderer],
212
+ ["list", listHtmlRenderer],
213
+ ["listitem", listitemHtmlRenderer],
214
+ ["paragraph", paragraphHtmlRenderer],
215
+ ["root", rootHtmlRenderer],
216
+ ["text", textHtmlRenderer],
217
+ ["tab", tabHtmlRenderer]
218
+ ]);
219
+ var resolveDefaultRenderer = (context) => {
220
+ const renderer = rendererTypeMap.get(context.currentNode.type);
221
+ if (renderer) {
222
+ return renderer;
223
+ }
224
+ const tag = rendererTypeTagMap.get(context.currentNode.type);
225
+ if (tag) {
226
+ return ({ renderChildren }) => renderHtmlElement(
227
+ tag,
228
+ null,
229
+ hasChildren(context.currentNode) ? renderChildren(context.currentNode.children) : void 0
230
+ );
231
+ }
232
+ return () => `<!-- WARNING: No renderer for type ${context.currentNode.type} -->`;
233
+ };
234
+ function initializeRenderContext(node, parentContext) {
235
+ let ancestorNodes = [];
236
+ if (parentContext == null ? void 0 : parentContext.ancestorNodes) {
237
+ ancestorNodes = ancestorNodes.concat(parentContext.ancestorNodes);
238
+ }
239
+ if (parentContext == null ? void 0 : parentContext.currentNode) {
240
+ ancestorNodes.unshift(parentContext.currentNode);
241
+ }
242
+ return {
243
+ ...parentContext != null ? parentContext : {},
244
+ currentNode: node,
245
+ ancestorNodes
246
+ };
247
+ }
248
+ function renderToHtml(node, parentContext) {
249
+ var _a;
250
+ if (!isRichTextNode(node))
251
+ return "";
252
+ const context = initializeRenderContext(node, parentContext);
253
+ let renderer = (_a = context.resolveRenderer) == null ? void 0 : _a.call(context, context);
254
+ if (typeof renderer === "undefined") {
255
+ renderer = resolveDefaultRenderer(context);
256
+ } else if (renderer === null) {
257
+ return "";
258
+ }
259
+ const renderChildren = (children) => renderChildrenToHtml(children, context);
260
+ if (renderer) {
261
+ return renderer({ context, renderChildren });
262
+ } else {
263
+ throw new Error(`There is no renderer for node type: ${context.currentNode.type}`);
264
+ }
265
+ }
266
+ function renderChildrenToHtml(children, context) {
267
+ return Array.isArray(children) ? children.map((node) => renderToHtml(node, context)).join("") : "";
268
+ }
269
+
270
+ // src/utils.ts
271
+ var walkRichTextTree = (node, callback, parent) => {
272
+ callback(node, parent);
273
+ if (Array.isArray(node.children)) {
274
+ let i = 0;
275
+ while (node.children.length > i) {
276
+ walkRichTextTree(node.children[i], callback, node);
277
+ i += 1;
278
+ }
279
+ }
280
+ };
281
+ // Annotate the CommonJS export names for ESM import in node:
282
+ 0 && (module.exports = {
283
+ getRichTextTagsFromTextFormat,
284
+ hasChildren,
285
+ headingHtmlRenderer,
286
+ isArrayWithLength,
287
+ isPureDirection,
288
+ isPureTextAlign,
289
+ isRichTextNode,
290
+ isRichTextNodeType,
291
+ linkHtmlRenderer,
292
+ linkParamValueToHref,
293
+ listHtmlRenderer,
294
+ listitemHtmlRenderer,
295
+ paragraphHtmlRenderer,
296
+ purifyText,
297
+ renderChildrenToHtml,
298
+ renderHtmlElement,
299
+ renderToHtml,
300
+ resolveDefaultRenderer,
301
+ rootHtmlRenderer,
302
+ textHtmlRenderer,
303
+ walkRichTextTree
304
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,257 @@
1
+ // src/elements.ts
2
+ var rendererTypeTagMap = /* @__PURE__ */ new Map([
3
+ ["linebreak", "br"],
4
+ ["quote", "blockquote"]
5
+ ]);
6
+ function purifyText(text) {
7
+ return text.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
8
+ }
9
+ function isPureTextAlign(format) {
10
+ return Boolean(format && ["center", "end", "justify", "left", "right", "start"].includes(format));
11
+ }
12
+ function isPureDirection(direction) {
13
+ return Boolean(direction && ["ltr", "rtl"].includes(direction));
14
+ }
15
+ var voidElements = /* @__PURE__ */ new Set([
16
+ "area",
17
+ "base",
18
+ "br",
19
+ "col",
20
+ "embed",
21
+ "hr",
22
+ "img",
23
+ "input",
24
+ "link",
25
+ "meta",
26
+ "source",
27
+ "track",
28
+ "wbr"
29
+ ]);
30
+ function renderHtmlElement(tag, attributes, children) {
31
+ const attributesString = attributes && attributes.size > 0 ? " " + Array.from(attributes).reduce((result, [key, value]) => [...result, `${key}="${value}"`], []).join(" ") : "";
32
+ return voidElements.has(tag) ? `<${tag}${attributesString}>` : `<${tag}${attributesString}>${children != null ? children : ""}</${tag}>`;
33
+ }
34
+
35
+ // src/guards.ts
36
+ function isArrayWithLength(arr) {
37
+ return Array.isArray(arr) && arr.length > 0;
38
+ }
39
+ function isRichTextNode(node) {
40
+ return !!node && typeof node === "object" && "type" in node;
41
+ }
42
+ function isRichTextNodeType(node, type) {
43
+ return isRichTextNode(node) && node.type === type;
44
+ }
45
+ function hasChildren(node) {
46
+ return "children" in node && isArrayWithLength(node.children);
47
+ }
48
+
49
+ // src/nodes/heading.ts
50
+ var headingHtmlRenderer = ({ context, renderChildren }) => {
51
+ var _a;
52
+ const node = context.currentNode;
53
+ return renderHtmlElement((_a = node.tag) != null ? _a : "h1", null, renderChildren(context.currentNode.children));
54
+ };
55
+
56
+ // src/nodes/link.ts
57
+ var linkHtmlRenderer = ({ context, renderChildren }) => {
58
+ const node = context.currentNode;
59
+ const attributes = /* @__PURE__ */ new Map();
60
+ const href = linkParamValueToHref(node.link);
61
+ if (href) {
62
+ attributes.set("href", href);
63
+ }
64
+ return renderHtmlElement("a", attributes, renderChildren(context.currentNode.children));
65
+ };
66
+ function linkParamValueToHref(link) {
67
+ switch (link == null ? void 0 : link.type) {
68
+ case "email":
69
+ return `mailto:${link.path}`;
70
+ case "tel":
71
+ return `tel:${link.path}`;
72
+ case "url":
73
+ return link.path;
74
+ case "projectMapNode":
75
+ return link.path;
76
+ }
77
+ }
78
+
79
+ // src/nodes/list.ts
80
+ var listHtmlRenderer = ({ context, renderChildren }) => {
81
+ var _a;
82
+ const node = context.currentNode;
83
+ const attributes = /* @__PURE__ */ new Map();
84
+ if (node.start > 1) {
85
+ attributes.set("start", node.start.toString());
86
+ }
87
+ return renderHtmlElement((_a = node.tag) != null ? _a : "ul", attributes, renderChildren(context.currentNode.children));
88
+ };
89
+
90
+ // src/nodes/listitem.ts
91
+ var listitemHtmlRenderer = ({ context, renderChildren }) => {
92
+ const node = context.currentNode;
93
+ const attributes = /* @__PURE__ */ new Map();
94
+ if (Number.isFinite(node.value)) {
95
+ attributes.set("value", (node.value + 1).toString());
96
+ }
97
+ return renderHtmlElement("li", attributes, renderChildren(context.currentNode.children));
98
+ };
99
+
100
+ // src/nodes/paragraph.ts
101
+ var paragraphHtmlRenderer = ({ context, renderChildren }) => {
102
+ const node = context.currentNode;
103
+ const attributes = /* @__PURE__ */ new Map();
104
+ if (isPureTextAlign(node.format)) {
105
+ attributes.set("style", `text-align: ${node.format};`);
106
+ }
107
+ if (isPureDirection(node.direction)) {
108
+ attributes.set("dir", node.direction);
109
+ }
110
+ return renderHtmlElement(
111
+ "p",
112
+ attributes,
113
+ hasChildren(context.currentNode) ? renderChildren(context.currentNode.children) : "<br>"
114
+ );
115
+ };
116
+
117
+ // src/nodes/root.ts
118
+ var rootHtmlRenderer = ({ context, renderChildren }) => {
119
+ return hasChildren(context.currentNode) ? renderChildren(context.currentNode.children) : "";
120
+ };
121
+
122
+ // src/nodes/text.ts
123
+ var textHtmlRenderer = ({ context }) => {
124
+ const node = context.currentNode;
125
+ const tags = getRichTextTagsFromTextFormat(node.format);
126
+ const pureText = purifyText(node.text);
127
+ return tags.length === 0 ? pureText : tags.reduceRight((children, tag) => {
128
+ return renderHtmlElement(tag, null, children);
129
+ }, pureText);
130
+ };
131
+ function getRichTextTagsFromTextFormat(format) {
132
+ const tags = [];
133
+ if (format & 1 << 0) {
134
+ tags.push("strong");
135
+ }
136
+ if (format & 1 << 1) {
137
+ tags.push("em");
138
+ }
139
+ if (format & 1 << 2) {
140
+ tags.push("s");
141
+ }
142
+ if (format & 1 << 3) {
143
+ tags.push("u");
144
+ }
145
+ if (format & 1 << 4) {
146
+ tags.push("code");
147
+ }
148
+ if (format & 1 << 5) {
149
+ tags.push("sub");
150
+ }
151
+ if (format & 1 << 6) {
152
+ tags.push("sup");
153
+ }
154
+ return tags;
155
+ }
156
+
157
+ // src/nodes/tab.ts
158
+ var tabHtmlRenderer = () => {
159
+ return " ";
160
+ };
161
+
162
+ // src/renderToHtml.ts
163
+ var rendererTypeMap = /* @__PURE__ */ new Map([
164
+ ["heading", headingHtmlRenderer],
165
+ ["link", linkHtmlRenderer],
166
+ ["list", listHtmlRenderer],
167
+ ["listitem", listitemHtmlRenderer],
168
+ ["paragraph", paragraphHtmlRenderer],
169
+ ["root", rootHtmlRenderer],
170
+ ["text", textHtmlRenderer],
171
+ ["tab", tabHtmlRenderer]
172
+ ]);
173
+ var resolveDefaultRenderer = (context) => {
174
+ const renderer = rendererTypeMap.get(context.currentNode.type);
175
+ if (renderer) {
176
+ return renderer;
177
+ }
178
+ const tag = rendererTypeTagMap.get(context.currentNode.type);
179
+ if (tag) {
180
+ return ({ renderChildren }) => renderHtmlElement(
181
+ tag,
182
+ null,
183
+ hasChildren(context.currentNode) ? renderChildren(context.currentNode.children) : void 0
184
+ );
185
+ }
186
+ return () => `<!-- WARNING: No renderer for type ${context.currentNode.type} -->`;
187
+ };
188
+ function initializeRenderContext(node, parentContext) {
189
+ let ancestorNodes = [];
190
+ if (parentContext == null ? void 0 : parentContext.ancestorNodes) {
191
+ ancestorNodes = ancestorNodes.concat(parentContext.ancestorNodes);
192
+ }
193
+ if (parentContext == null ? void 0 : parentContext.currentNode) {
194
+ ancestorNodes.unshift(parentContext.currentNode);
195
+ }
196
+ return {
197
+ ...parentContext != null ? parentContext : {},
198
+ currentNode: node,
199
+ ancestorNodes
200
+ };
201
+ }
202
+ function renderToHtml(node, parentContext) {
203
+ var _a;
204
+ if (!isRichTextNode(node))
205
+ return "";
206
+ const context = initializeRenderContext(node, parentContext);
207
+ let renderer = (_a = context.resolveRenderer) == null ? void 0 : _a.call(context, context);
208
+ if (typeof renderer === "undefined") {
209
+ renderer = resolveDefaultRenderer(context);
210
+ } else if (renderer === null) {
211
+ return "";
212
+ }
213
+ const renderChildren = (children) => renderChildrenToHtml(children, context);
214
+ if (renderer) {
215
+ return renderer({ context, renderChildren });
216
+ } else {
217
+ throw new Error(`There is no renderer for node type: ${context.currentNode.type}`);
218
+ }
219
+ }
220
+ function renderChildrenToHtml(children, context) {
221
+ return Array.isArray(children) ? children.map((node) => renderToHtml(node, context)).join("") : "";
222
+ }
223
+
224
+ // src/utils.ts
225
+ var walkRichTextTree = (node, callback, parent) => {
226
+ callback(node, parent);
227
+ if (Array.isArray(node.children)) {
228
+ let i = 0;
229
+ while (node.children.length > i) {
230
+ walkRichTextTree(node.children[i], callback, node);
231
+ i += 1;
232
+ }
233
+ }
234
+ };
235
+ export {
236
+ getRichTextTagsFromTextFormat,
237
+ hasChildren,
238
+ headingHtmlRenderer,
239
+ isArrayWithLength,
240
+ isPureDirection,
241
+ isPureTextAlign,
242
+ isRichTextNode,
243
+ isRichTextNodeType,
244
+ linkHtmlRenderer,
245
+ linkParamValueToHref,
246
+ listHtmlRenderer,
247
+ listitemHtmlRenderer,
248
+ paragraphHtmlRenderer,
249
+ purifyText,
250
+ renderChildrenToHtml,
251
+ renderHtmlElement,
252
+ renderToHtml,
253
+ resolveDefaultRenderer,
254
+ rootHtmlRenderer,
255
+ textHtmlRenderer,
256
+ walkRichTextTree
257
+ };
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@uniformdev/richtext",
3
+ "version": "19.14.1-alpha.1+597b21eaa",
4
+ "description": "Common functionality and types for Uniform Rich Text parameters",
5
+ "license": "SEE LICENSE IN LICENSE.txt",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.esm.js",
8
+ "exports": {
9
+ "import": {
10
+ "types": "./dist/index.d.ts",
11
+ "node": "./dist/index.mjs",
12
+ "default": "./dist/index.esm.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ }
18
+ },
19
+ "types": "./dist/index.d.ts",
20
+ "typesVersions": {
21
+ "*": {
22
+ ".": [
23
+ "./dist/index.d.ts"
24
+ ],
25
+ "cli": [
26
+ "./dist/cli/cli.d.ts"
27
+ ]
28
+ }
29
+ },
30
+ "sideEffects": false,
31
+ "scripts": {
32
+ "build": "run-s build:ts",
33
+ "build:ts": "tsup",
34
+ "dev": "run-s dev:ts",
35
+ "dev:ts": "tsup --watch",
36
+ "clean": "rimraf dist",
37
+ "test": "jest --maxWorkers=1",
38
+ "lint": "eslint \"src/**/*.{js,ts,tsx}\"",
39
+ "format": "prettier --write \"src/**/*.{js,ts,tsx}\"",
40
+ "document": "api-extractor run --local"
41
+ },
42
+ "devDependencies": {
43
+ "@lexical/headless": "^0.11.0",
44
+ "@lexical/html": "^0.11.0",
45
+ "@lexical/link": "^0.11.0",
46
+ "@lexical/list": "^0.11.0",
47
+ "@lexical/rich-text": "^0.11.0",
48
+ "@uniformdev/canvas": "^19.14.1-alpha.1+597b21eaa",
49
+ "lexical": "^0.11.0"
50
+ },
51
+ "files": [
52
+ "/dist"
53
+ ],
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "gitHead": "597b21eaa0a61271b8951de1d443019868f7699c"
58
+ }