@withl5e/richtext-payload 0.1.0-alpha.0
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 +21 -0
- package/README.md +26 -0
- package/dist/index.js +316 -0
- package/dist/index.js.map +1 -0
- package/dist/stringToLexical.js +36 -0
- package/dist/stringToLexical.js.map +1 -0
- package/index.ts +1 -0
- package/package.json +52 -0
- package/src/richtext-render/converters/blockquote.tsx +12 -0
- package/src/richtext-render/converters/heading.tsx +14 -0
- package/src/richtext-render/converters/horizontalRule.tsx +5 -0
- package/src/richtext-render/converters/linebreak.tsx +6 -0
- package/src/richtext-render/converters/link.tsx +47 -0
- package/src/richtext-render/converters/list.tsx +60 -0
- package/src/richtext-render/converters/paragraph.tsx +24 -0
- package/src/richtext-render/converters/tab.tsx +6 -0
- package/src/richtext-render/converters/table.tsx +60 -0
- package/src/richtext-render/converters/text.tsx +37 -0
- package/src/richtext-render/converters/upload.tsx +83 -0
- package/src/richtext-render/defaultConverters.ts +28 -0
- package/src/richtext-render/index.tsx +190 -0
- package/src/richtext-render/types.ts +70 -0
- package/src/richtext-render/utils/genFragmentIdentifier.ts +12 -0
- package/src/richtext-render/utils/getTableOfContents.ts +93 -0
- package/src/richtext-render/utils/getTextOfLexical.ts +11 -0
- package/src/richtext-render/utils/getTimeRead.ts +12 -0
- package/src/richtext-render/utils/stringToLexical.ts +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 L5E contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# @withl5e/richtext-payload
|
|
2
|
+
|
|
3
|
+
Payload Lexical rich text rendering is kept outside `@withl5e/l5e` so the framework core does not
|
|
4
|
+
force Payload, Lexical or CMS-specific types into every L5E app.
|
|
5
|
+
|
|
6
|
+
Install it only in apps that render Payload rich text:
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
pnpm add @withl5e/richtext-payload @payloadcms/richtext-lexical lexical payload
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Usage:
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
import {
|
|
16
|
+
convertLexicalToJSX,
|
|
17
|
+
defaultJSXConverters,
|
|
18
|
+
} from '@withl5e/richtext-payload';
|
|
19
|
+
|
|
20
|
+
export function ArticleBody({ content }) {
|
|
21
|
+
return convertLexicalToJSX({
|
|
22
|
+
converters: defaultJSXConverters,
|
|
23
|
+
data: content,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
```
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
import { jsxFactory as n, Fragment as y, isValidElement as S, cloneElement as b } from "@withl5e/l5e/jsx-runtime";
|
|
2
|
+
import { hasText as v } from "@payloadcms/richtext-lexical/shared";
|
|
3
|
+
import { v4 as T } from "uuid";
|
|
4
|
+
import { NodeFormat as p } from "@payloadcms/richtext-lexical";
|
|
5
|
+
import { stringToLexical as W } from "./stringToLexical.js";
|
|
6
|
+
const w = {
|
|
7
|
+
quote: ({ node: e, nodesToJSX: t }) => {
|
|
8
|
+
const r = t({
|
|
9
|
+
nodes: e.children
|
|
10
|
+
});
|
|
11
|
+
return /* @__PURE__ */ n("blockquote", null, r);
|
|
12
|
+
}
|
|
13
|
+
}, C = {
|
|
14
|
+
heading: ({ node: e, nodesToJSX: t }) => {
|
|
15
|
+
const r = t({
|
|
16
|
+
nodes: e.children
|
|
17
|
+
}), l = e.tag;
|
|
18
|
+
return /* @__PURE__ */ n(l, null, r);
|
|
19
|
+
}
|
|
20
|
+
}, J = {
|
|
21
|
+
horizontalrule: /* @__PURE__ */ n("hr", null)
|
|
22
|
+
}, X = {
|
|
23
|
+
linebreak: /* @__PURE__ */ n("br", null)
|
|
24
|
+
}, L = ({ internalDocToHref: e }) => ({
|
|
25
|
+
autolink: ({ node: t, nodesToJSX: r }) => {
|
|
26
|
+
const l = r({
|
|
27
|
+
nodes: t.children
|
|
28
|
+
}), i = t.fields.newTab ? "noopener noreferrer" : void 0, o = t.fields.newTab ? "_blank" : void 0;
|
|
29
|
+
return /* @__PURE__ */ n("a", { href: t.fields.url, rel: i, target: o }, l);
|
|
30
|
+
},
|
|
31
|
+
link: ({ node: t, nodesToJSX: r }) => {
|
|
32
|
+
const l = r({
|
|
33
|
+
nodes: t.children
|
|
34
|
+
}), i = t.fields.newTab ? "noopener noreferrer" : void 0, o = t.fields.newTab ? "_blank" : void 0;
|
|
35
|
+
let s = t.fields.url ?? "";
|
|
36
|
+
return t.fields.linkType === "internal" && (e ? s = e({ linkNode: t }) : (console.error(
|
|
37
|
+
"Lexical => JSX converter: Link converter: found internal link, but internalDocToHref is not provided"
|
|
38
|
+
), s = "#")), /* @__PURE__ */ n("a", { href: s, rel: i, target: o }, l);
|
|
39
|
+
}
|
|
40
|
+
}), I = {
|
|
41
|
+
list: ({ node: e, nodesToJSX: t }) => {
|
|
42
|
+
const r = t({
|
|
43
|
+
nodes: e.children
|
|
44
|
+
}), l = e.tag;
|
|
45
|
+
return /* @__PURE__ */ n(l, { class: `list-${e?.listType}` }, r);
|
|
46
|
+
},
|
|
47
|
+
listitem: ({ node: e, nodesToJSX: t, parent: r }) => {
|
|
48
|
+
const l = e.children.some((o) => o.type === "list"), i = t({
|
|
49
|
+
nodes: e.children
|
|
50
|
+
});
|
|
51
|
+
if ("listType" in r && r?.listType === "check") {
|
|
52
|
+
const o = T();
|
|
53
|
+
return /* @__PURE__ */ n(
|
|
54
|
+
"li",
|
|
55
|
+
{
|
|
56
|
+
"aria-checked": e.checked ? "true" : "false",
|
|
57
|
+
class: `list-item-checkbox${e.checked ? " list-item-checkbox-checked" : " list-item-checkbox-unchecked"}${l ? " nestedListItem" : ""}`,
|
|
58
|
+
role: "checkbox",
|
|
59
|
+
style: "list-style-type: none;",
|
|
60
|
+
tabindex: "-1",
|
|
61
|
+
value: e?.value
|
|
62
|
+
},
|
|
63
|
+
l ? i : /* @__PURE__ */ n(y, null, /* @__PURE__ */ n("input", { checked: e.checked, id: o, readonly: !0, type: "checkbox" }), /* @__PURE__ */ n("label", { for: o }, i), /* @__PURE__ */ n("br", null))
|
|
64
|
+
);
|
|
65
|
+
} else
|
|
66
|
+
return /* @__PURE__ */ n(
|
|
67
|
+
"li",
|
|
68
|
+
{
|
|
69
|
+
class: `${l ? "nestedListItem" : ""}`,
|
|
70
|
+
style: l ? "list-style-type: none;" : "",
|
|
71
|
+
value: e?.value
|
|
72
|
+
},
|
|
73
|
+
i
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
}, N = {
|
|
77
|
+
paragraph: ({ node: e, nodesToJSX: t }) => {
|
|
78
|
+
const r = t({
|
|
79
|
+
nodes: e.children
|
|
80
|
+
});
|
|
81
|
+
return r?.length ? /* @__PURE__ */ n("p", null, r) : /* @__PURE__ */ n("p", null, /* @__PURE__ */ n("br", null));
|
|
82
|
+
}
|
|
83
|
+
}, E = {
|
|
84
|
+
tab: " "
|
|
85
|
+
}, $ = {
|
|
86
|
+
table: ({ node: e, nodesToJSX: t }) => {
|
|
87
|
+
const r = t({
|
|
88
|
+
nodes: e.children
|
|
89
|
+
});
|
|
90
|
+
return /* @__PURE__ */ n("div", { class: "lexical-table-container" }, /* @__PURE__ */ n("table", { class: "lexical-table", style: "border-collapse: collapse;" }, /* @__PURE__ */ n("tbody", null, r)));
|
|
91
|
+
},
|
|
92
|
+
tablecell: ({ node: e, nodesToJSX: t }) => {
|
|
93
|
+
const r = t({
|
|
94
|
+
nodes: e.children
|
|
95
|
+
}), l = e.headerState > 0 ? "th" : "td", i = `lexical-table-cell-header-${e.headerState}`;
|
|
96
|
+
let o = "";
|
|
97
|
+
e.backgroundColor && (o += `background-color: ${e.backgroundColor};`), o += "border: 1px solid #ccc;", o += "padding: 8px;";
|
|
98
|
+
const s = e.colSpan && e.colSpan > 1 ? e.colSpan : void 0, c = e.rowSpan && e.rowSpan > 1 ? e.rowSpan : void 0;
|
|
99
|
+
return /* @__PURE__ */ n(
|
|
100
|
+
l,
|
|
101
|
+
{
|
|
102
|
+
class: `lexical-table-cell ${i}`,
|
|
103
|
+
colspan: s,
|
|
104
|
+
rowspan: c,
|
|
105
|
+
style: o
|
|
106
|
+
},
|
|
107
|
+
r
|
|
108
|
+
);
|
|
109
|
+
},
|
|
110
|
+
tablerow: ({ node: e, nodesToJSX: t }) => {
|
|
111
|
+
const r = t({
|
|
112
|
+
nodes: e.children
|
|
113
|
+
});
|
|
114
|
+
return /* @__PURE__ */ n("tr", { class: "lexical-table-row" }, r);
|
|
115
|
+
}
|
|
116
|
+
}, z = {
|
|
117
|
+
text: ({ node: e }) => {
|
|
118
|
+
let t = e.text;
|
|
119
|
+
return e.format & p.IS_BOLD && (t = /* @__PURE__ */ n("strong", null, t)), e.format & p.IS_ITALIC && (t = /* @__PURE__ */ n("em", null, t)), e.format & p.IS_STRIKETHROUGH && (t = /* @__PURE__ */ n("span", { style: "text-decoration: line-through;" }, t)), e.format & p.IS_UNDERLINE && (t = /* @__PURE__ */ n("span", { style: "text-decoration: underline;" }, t)), e.format & p.IS_CODE && (t = /* @__PURE__ */ n("code", null, t)), e.format & p.IS_SUBSCRIPT && (t = /* @__PURE__ */ n("sub", null, t)), e.format & p.IS_SUPERSCRIPT && (t = /* @__PURE__ */ n("sup", null, t)), t;
|
|
120
|
+
}
|
|
121
|
+
}, _ = {
|
|
122
|
+
upload: ({ node: e }) => {
|
|
123
|
+
const t = e;
|
|
124
|
+
if (typeof t.value != "object")
|
|
125
|
+
return null;
|
|
126
|
+
const r = t.value, l = r.url;
|
|
127
|
+
if (!r.mimeType.startsWith("image"))
|
|
128
|
+
return /* @__PURE__ */ n("a", { href: l, rel: "noopener noreferrer" }, r.filename);
|
|
129
|
+
if (!r.sizes || !Object.keys(r.sizes).length)
|
|
130
|
+
return /* @__PURE__ */ n("img", { alt: r.filename, height: r.height, src: l, width: r.width });
|
|
131
|
+
const i = [];
|
|
132
|
+
for (const o in r.sizes) {
|
|
133
|
+
const s = r.sizes[o];
|
|
134
|
+
if (!s || !s.width || !s.height || !s.mimeType || !s.filesize || !s.filename || !s.url)
|
|
135
|
+
continue;
|
|
136
|
+
const c = s?.url;
|
|
137
|
+
i.push(
|
|
138
|
+
/* @__PURE__ */ n(
|
|
139
|
+
"source",
|
|
140
|
+
{
|
|
141
|
+
key: o,
|
|
142
|
+
media: `(max-width: ${s.width}px)`,
|
|
143
|
+
srcset: c,
|
|
144
|
+
type: s.mimeType
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return i.push(
|
|
150
|
+
/* @__PURE__ */ n(
|
|
151
|
+
"img",
|
|
152
|
+
{
|
|
153
|
+
alt: r?.filename,
|
|
154
|
+
height: r?.height,
|
|
155
|
+
key: "image",
|
|
156
|
+
src: l,
|
|
157
|
+
width: r?.width
|
|
158
|
+
}
|
|
159
|
+
)
|
|
160
|
+
), /* @__PURE__ */ n("picture", null, i);
|
|
161
|
+
}
|
|
162
|
+
}, D = {
|
|
163
|
+
...N,
|
|
164
|
+
...z,
|
|
165
|
+
...X,
|
|
166
|
+
...w,
|
|
167
|
+
...$,
|
|
168
|
+
...C,
|
|
169
|
+
...J,
|
|
170
|
+
...I,
|
|
171
|
+
...L({}),
|
|
172
|
+
..._,
|
|
173
|
+
...E
|
|
174
|
+
};
|
|
175
|
+
function U(e) {
|
|
176
|
+
return e.toLowerCase().normalize("NFD").replace(/[\u0300-\u036F]/g, "").replace(/đ/g, "d").replace(/[\u2010-\u2015\u2212\uFE58\uFE63\uFF0D]/g, "-").replace(/[\s\u00A0\/\\|_.,;:+=@&]+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
177
|
+
}
|
|
178
|
+
function g(e) {
|
|
179
|
+
return e ? e.type === "text" ? e.text || "" : !("children" in e) || !Array.isArray(e.children) ? "" : e.children.map((t) => g(t)).join("") : "";
|
|
180
|
+
}
|
|
181
|
+
function k(e) {
|
|
182
|
+
const t = [];
|
|
183
|
+
if ("root" in e && e.root)
|
|
184
|
+
return k(e.root);
|
|
185
|
+
const r = e;
|
|
186
|
+
if (r.type === "heading") {
|
|
187
|
+
const i = r.tag || "", o = i === "h2" ? 2 : i === "h3" ? 3 : i === "h4" ? 4 : i === "h5" ? 5 : i === "h6" ? 6 : 0;
|
|
188
|
+
if (o > 0) {
|
|
189
|
+
const s = g(r);
|
|
190
|
+
s && t.push({
|
|
191
|
+
text: s,
|
|
192
|
+
level: o
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return "children" in r && Array.isArray(r.children) && r.children.forEach((l) => {
|
|
197
|
+
t.push(...k(l));
|
|
198
|
+
}), t;
|
|
199
|
+
}
|
|
200
|
+
function O(e) {
|
|
201
|
+
const t = [], r = [];
|
|
202
|
+
return e.forEach((l) => {
|
|
203
|
+
const i = {
|
|
204
|
+
...l,
|
|
205
|
+
children: []
|
|
206
|
+
};
|
|
207
|
+
for (; r.length > 0 && r[r.length - 1].level >= l.level; )
|
|
208
|
+
r.pop();
|
|
209
|
+
r.length === 0 ? t.push(i) : r[r.length - 1].children.push(i), r.push(i);
|
|
210
|
+
}), t;
|
|
211
|
+
}
|
|
212
|
+
const A = 210;
|
|
213
|
+
function H(e) {
|
|
214
|
+
if (!e) return 0;
|
|
215
|
+
const r = g(e).trim().split(/\s+/).length, l = Math.ceil(r / A);
|
|
216
|
+
return Math.max(1, l);
|
|
217
|
+
}
|
|
218
|
+
function P({
|
|
219
|
+
converters: e,
|
|
220
|
+
data: t,
|
|
221
|
+
disableIndent: r,
|
|
222
|
+
disableTextAlign: l
|
|
223
|
+
}) {
|
|
224
|
+
return v(t) ? /* @__PURE__ */ n(y, null, x({
|
|
225
|
+
converters: e,
|
|
226
|
+
disableIndent: r,
|
|
227
|
+
disableTextAlign: l,
|
|
228
|
+
nodes: t?.root?.children,
|
|
229
|
+
parent: t?.root
|
|
230
|
+
})) : /* @__PURE__ */ n(y, null);
|
|
231
|
+
}
|
|
232
|
+
function x({
|
|
233
|
+
converters: e,
|
|
234
|
+
disableIndent: t,
|
|
235
|
+
disableTextAlign: r,
|
|
236
|
+
nodes: l,
|
|
237
|
+
parent: i
|
|
238
|
+
}) {
|
|
239
|
+
const o = e.unknown;
|
|
240
|
+
return l.map((c, d) => {
|
|
241
|
+
let a;
|
|
242
|
+
c.type === "block" ? (a = e?.blocks?.[c?.fields?.blockType], !a && !o && console.error(
|
|
243
|
+
`Lexical => JSX converter: Blocks converter: found ${c?.fields?.blockType} block, but no converter is provided`
|
|
244
|
+
)) : c.type === "inlineBlock" ? (a = e?.inlineBlocks?.[c?.fields?.blockType], !a && !o && console.error(
|
|
245
|
+
`Lexical => JSX converter: Inline Blocks converter: found ${c?.fields?.blockType} inline block, but no converter is provided`
|
|
246
|
+
)) : a = e[c.type];
|
|
247
|
+
try {
|
|
248
|
+
!a && o && (a = o);
|
|
249
|
+
let u;
|
|
250
|
+
a ? u = typeof a == "function" ? a({
|
|
251
|
+
childIndex: d,
|
|
252
|
+
converters: e,
|
|
253
|
+
node: c,
|
|
254
|
+
nodesToJSX: (f) => x({
|
|
255
|
+
converters: f.converters ?? e,
|
|
256
|
+
disableIndent: f.disableIndent ?? t,
|
|
257
|
+
disableTextAlign: f.disableTextAlign ?? r,
|
|
258
|
+
nodes: f.nodes,
|
|
259
|
+
parent: f.parent ?? {
|
|
260
|
+
...c,
|
|
261
|
+
parent: i
|
|
262
|
+
}
|
|
263
|
+
}),
|
|
264
|
+
parent: i
|
|
265
|
+
}) : a : u = /* @__PURE__ */ n("span", { key: d }, "unknown node");
|
|
266
|
+
let h = "";
|
|
267
|
+
if (!r && (!Array.isArray(r) || !r?.includes(c.type)) && "format" in c && c.format)
|
|
268
|
+
switch (c.format) {
|
|
269
|
+
case "center":
|
|
270
|
+
h += "text-align: center;";
|
|
271
|
+
break;
|
|
272
|
+
case "end":
|
|
273
|
+
h += "text-align: right;";
|
|
274
|
+
break;
|
|
275
|
+
case "justify":
|
|
276
|
+
h += "text-align: justify;";
|
|
277
|
+
break;
|
|
278
|
+
case "left":
|
|
279
|
+
break;
|
|
280
|
+
case "right":
|
|
281
|
+
h += "text-align: right;";
|
|
282
|
+
break;
|
|
283
|
+
case "start":
|
|
284
|
+
h += "text-align: left;";
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
if (!t && (!Array.isArray(t) || !t?.includes(c.type)) && "indent" in c && c.indent && c.type !== "listitem" && (h += `padding-inline-start: ${Number(c.indent) * 40}px;`), S(u)) {
|
|
288
|
+
if (h) {
|
|
289
|
+
const m = typeof u?.props?.style == "string" ? u.props.style : "", f = `${h} ${m}`.trim();
|
|
290
|
+
return b(u, {
|
|
291
|
+
key: d,
|
|
292
|
+
style: f
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
return b(u, {
|
|
296
|
+
key: d
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
return u;
|
|
300
|
+
} catch (u) {
|
|
301
|
+
return console.error("Error converting lexical node to JSX:", u, "node:", c), null;
|
|
302
|
+
}
|
|
303
|
+
}).filter(Boolean);
|
|
304
|
+
}
|
|
305
|
+
export {
|
|
306
|
+
O as buildTableOfContents,
|
|
307
|
+
x as convertLexicalNodesToJSX,
|
|
308
|
+
P as convertLexicalToJSX,
|
|
309
|
+
D as defaultJSXConverters,
|
|
310
|
+
U as genFragmentIdentifier,
|
|
311
|
+
k as getHeaders,
|
|
312
|
+
g as getTextLexicalNode,
|
|
313
|
+
H as getTimeRead,
|
|
314
|
+
W as stringToLexical
|
|
315
|
+
};
|
|
316
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/richtext-render/converters/blockquote.tsx","../src/richtext-render/converters/heading.tsx","../src/richtext-render/converters/horizontalRule.tsx","../src/richtext-render/converters/linebreak.tsx","../src/richtext-render/converters/link.tsx","../src/richtext-render/converters/list.tsx","../src/richtext-render/converters/paragraph.tsx","../src/richtext-render/converters/tab.tsx","../src/richtext-render/converters/table.tsx","../src/richtext-render/converters/text.tsx","../src/richtext-render/converters/upload.tsx","../src/richtext-render/defaultConverters.ts","../src/richtext-render/utils/genFragmentIdentifier.ts","../src/richtext-render/utils/getTextOfLexical.ts","../src/richtext-render/utils/getTableOfContents.ts","../src/richtext-render/utils/getTimeRead.ts","../src/richtext-render/index.tsx"],"sourcesContent":["import type { SerializedQuoteNode } from '@payloadcms/richtext-lexical';\nimport type { JSXConverters } from '../types.js';\n\nexport const BlockquoteJSXConverter: JSXConverters<SerializedQuoteNode> = {\n quote: ({ node, nodesToJSX }) => {\n const children = nodesToJSX({\n nodes: node.children,\n });\n\n return <blockquote>{children}</blockquote>;\n },\n};\n","import { SerializedHeadingNode } from '@payloadcms/richtext-lexical';\nimport type { JSXConverters } from '../types.js';\n\nexport const HeadingJSXConverter: JSXConverters<SerializedHeadingNode> = {\n heading: ({ node, nodesToJSX }) => {\n const children = nodesToJSX({\n nodes: node.children,\n });\n\n const NodeTag = node.tag;\n\n return <NodeTag>{children}</NodeTag>;\n },\n};\n","import { SerializedHorizontalRuleNode } from '@payloadcms/richtext-lexical';\nimport type { JSXConverters } from '../types.js';\nexport const HorizontalRuleJSXConverter: JSXConverters<SerializedHorizontalRuleNode> = {\n horizontalrule: <hr />,\n};\n","import type { SerializedLineBreakNode } from 'lexical';\nimport type { JSXConverters } from '../types.js';\n\nexport const LinebreakJSXConverter: JSXConverters<SerializedLineBreakNode> = {\n linebreak: <br />,\n};\n","import type { SerializedAutoLinkNode, SerializedLinkNode } from '@payloadcms/richtext-lexical';\nimport type { JSXConverters } from '../types.js';\n\nexport const LinkJSXConverter: (args: {\n internalDocToHref?: (args: { linkNode: SerializedLinkNode }) => string;\n}) => JSXConverters<SerializedAutoLinkNode | SerializedLinkNode> = ({ internalDocToHref }) => ({\n autolink: ({ node, nodesToJSX }) => {\n const children = nodesToJSX({\n nodes: node.children,\n });\n\n const rel: string | undefined = node.fields.newTab ? 'noopener noreferrer' : undefined;\n const target: string | undefined = node.fields.newTab ? '_blank' : undefined;\n\n return (\n <a href={node.fields.url} {...{ rel, target }}>\n {children}\n </a>\n );\n },\n link: ({ node, nodesToJSX }) => {\n const children = nodesToJSX({\n nodes: node.children,\n });\n\n const rel: string | undefined = node.fields.newTab ? 'noopener noreferrer' : undefined;\n const target: string | undefined = node.fields.newTab ? '_blank' : undefined;\n\n let href: string = node.fields.url ?? '';\n if (node.fields.linkType === 'internal') {\n if (internalDocToHref) {\n href = internalDocToHref({ linkNode: node });\n } else {\n console.error(\n 'Lexical => JSX converter: Link converter: found internal link, but internalDocToHref is not provided',\n );\n href = '#'; // fallback\n }\n }\n\n return (\n <a href={href} {...{ rel, target }}>\n {children}\n </a>\n );\n },\n});\n","import { v4 as uuidv4 } from 'uuid';\nimport { Fragment } from '@withl5e/l5e/jsx-runtime';\n\nimport type { SerializedListItemNode, SerializedListNode } from '@payloadcms/richtext-lexical';\nimport type { JSXConverters } from '../types.js';\n\nexport const ListJSXConverter: JSXConverters<SerializedListItemNode | SerializedListNode> = {\n list: ({ node, nodesToJSX }) => {\n const children = nodesToJSX({\n nodes: node.children,\n });\n\n const NodeTag = node.tag;\n\n return <NodeTag class={`list-${node?.listType}`}>{children}</NodeTag>;\n },\n listitem: ({ node, nodesToJSX, parent }) => {\n const hasSubLists = node.children.some((child) => child.type === 'list');\n\n const children = nodesToJSX({\n nodes: node.children,\n });\n\n if ('listType' in parent && parent?.listType === 'check') {\n const uuid = uuidv4();\n\n return (\n <li\n aria-checked={node.checked ? 'true' : 'false'}\n class={`list-item-checkbox${node.checked ? ' list-item-checkbox-checked' : ' list-item-checkbox-unchecked'}${hasSubLists ? ' nestedListItem' : ''}`}\n // eslint-disable-next-line jsx-a11y/no-noninteractive-element-to-interactive-role\n role=\"checkbox\"\n style=\"list-style-type: none;\"\n tabindex={'-1'}\n value={node?.value}\n >\n {hasSubLists ? (\n children\n ) : (\n <>\n <input checked={node.checked} id={uuid} readonly={true} type=\"checkbox\" />\n <label for={uuid}>{children}</label>\n <br />\n </>\n )}\n </li>\n );\n } else {\n return (\n <li\n class={`${hasSubLists ? 'nestedListItem' : ''}`}\n style={hasSubLists ? 'list-style-type: none;' : ''}\n value={node?.value}\n >\n {children}\n </li>\n );\n }\n },\n};\n","import type { SerializedParagraphNode } from 'lexical';\nimport type { JSXConverter, JSXConverters } from '../types.js';\n\ntype ParagraphConverterArgs = Parameters<\n Extract<JSXConverter<SerializedParagraphNode>, (...args: any[]) => JSX.Element>\n>[0];\n\nexport const ParagraphJSXConverter: JSXConverters<SerializedParagraphNode> = {\n paragraph: ({ node, nodesToJSX }: ParagraphConverterArgs) => {\n const children = nodesToJSX({\n nodes: node.children,\n });\n\n if (!children?.length) {\n return (\n <p>\n <br />\n </p>\n );\n }\n\n return <p>{children}</p>;\n },\n};\n","import type { SerializedTabNode } from 'lexical';\nimport type { JSXConverters } from '../types.js';\n\nexport const TabJSXConverter: JSXConverters<SerializedTabNode> = {\n tab: '\\t',\n};\n","import type {\n SerializedTableCellNode,\n SerializedTableNode,\n SerializedTableRowNode,\n} from '@payloadcms/richtext-lexical';\nimport type { JSXConverters } from '../types.js';\n\nexport const TableJSXConverter: JSXConverters<\n SerializedTableCellNode | SerializedTableNode | SerializedTableRowNode\n> = {\n table: ({ node, nodesToJSX }) => {\n const children = nodesToJSX({\n nodes: node.children,\n });\n return (\n <div class=\"lexical-table-container\">\n <table class=\"lexical-table\" style=\"border-collapse: collapse;\">\n <tbody>{children}</tbody>\n </table>\n </div>\n );\n },\n tablecell: ({ node, nodesToJSX }) => {\n const children = nodesToJSX({\n nodes: node.children,\n });\n\n const TagName = node.headerState > 0 ? 'th' : 'td'; // Use capital letter to denote a component\n const headerStateClass = `lexical-table-cell-header-${node.headerState}`;\n let style = '';\n if (node.backgroundColor) {\n style += `background-color: ${node.backgroundColor};`;\n }\n\n style += `border: 1px solid #ccc;`;\n\n style += `padding: 8px;`;\n\n // Note: JSX does not support setting attributes directly as strings, so you must convert the colSpan and rowSpan to numbers\n const colSpan = node.colSpan && node.colSpan > 1 ? node.colSpan : undefined;\n const rowSpan = node.rowSpan && node.rowSpan > 1 ? node.rowSpan : undefined;\n\n return (\n <TagName\n class={`lexical-table-cell ${headerStateClass}`}\n colspan={colSpan} // colSpan and rowSpan will only be added if they are not null\n rowspan={rowSpan}\n style={style}\n >\n {children}\n </TagName>\n );\n },\n tablerow: ({ node, nodesToJSX }) => {\n const children = nodesToJSX({\n nodes: node.children,\n });\n return <tr class=\"lexical-table-row\">{children}</tr>;\n },\n};\n","import { NodeFormat } from '@payloadcms/richtext-lexical';\nimport type { SerializedTextNode } from 'lexical';\nimport type { JSXConverter, JSXConverters } from '../types.js';\n\ntype TextConverterArgs = Parameters<\n Extract<JSXConverter<SerializedTextNode>, (...args: any[]) => JSX.Element>\n>[0];\n\nexport const TextJSXConverter: JSXConverters<SerializedTextNode> = {\n text: ({ node }: TextConverterArgs) => {\n let text: JSX.Element = node.text;\n\n if (node.format & NodeFormat.IS_BOLD) {\n text = <strong>{text}</strong>;\n }\n if (node.format & NodeFormat.IS_ITALIC) {\n text = <em>{text}</em>;\n }\n if (node.format & NodeFormat.IS_STRIKETHROUGH) {\n text = <span style=\"text-decoration: line-through;\">{text}</span>;\n }\n if (node.format & NodeFormat.IS_UNDERLINE) {\n text = <span style=\"text-decoration: underline;\">{text}</span>;\n }\n if (node.format & NodeFormat.IS_CODE) {\n text = <code>{text}</code>;\n }\n if (node.format & NodeFormat.IS_SUBSCRIPT) {\n text = <sub>{text}</sub>;\n }\n if (node.format & NodeFormat.IS_SUPERSCRIPT) {\n text = <sup>{text}</sup>;\n }\n\n return text;\n },\n};\n","import type { FileData, FileSizeImproved, TypeWithID } from 'payload';\n\nimport type { SerializedUploadNode } from '@payloadcms/richtext-lexical';\nimport type { JSXConverters } from '../types.js';\n\nexport const UploadJSXConverter: JSXConverters<SerializedUploadNode> = {\n upload: ({ node }) => {\n // TO-DO (v4): SerializedUploadNode should use UploadData_P4\n const uploadNode = node as any;\n if (typeof uploadNode.value !== 'object') {\n return null;\n }\n\n const uploadDoc = uploadNode.value as FileData & TypeWithID;\n\n const url = uploadDoc.url;\n\n /**\n * If the upload is not an image, return a link to the upload\n */\n if (!uploadDoc.mimeType.startsWith('image')) {\n return (\n <a href={url} rel=\"noopener noreferrer\">\n {uploadDoc.filename}\n </a>\n );\n }\n\n /**\n * If the upload is a simple image with no different sizes, return a simple img tag\n */\n if (!uploadDoc.sizes || !Object.keys(uploadDoc.sizes).length) {\n return (\n <img alt={uploadDoc.filename} height={uploadDoc.height} src={url} width={uploadDoc.width} />\n );\n }\n\n /**\n * If the upload is an image with different sizes, return a picture element\n */\n const pictureJSX: JSX.Element[] = [];\n\n // Iterate through each size in the data.sizes object\n for (const size in uploadDoc.sizes) {\n const imageSize = uploadDoc.sizes[size] as FileSizeImproved;\n\n // Skip if any property of the size object is null\n if (\n !imageSize ||\n !imageSize.width ||\n !imageSize.height ||\n !imageSize.mimeType ||\n !imageSize.filesize ||\n !imageSize.filename ||\n !imageSize.url\n ) {\n continue;\n }\n const imageSizeURL = imageSize?.url;\n\n pictureJSX.push(\n <source\n key={size}\n media={`(max-width: ${imageSize.width}px)`}\n srcset={imageSizeURL}\n type={imageSize.mimeType}\n />,\n );\n }\n\n // Add the default img tag\n pictureJSX.push(\n <img\n alt={uploadDoc?.filename}\n height={uploadDoc?.height}\n key={'image'}\n src={url}\n width={uploadDoc?.width}\n />,\n );\n return <picture>{pictureJSX}</picture>;\n },\n};\n","import type { JSXConverters } from './types.js';\n\nimport { DefaultNodeTypes } from '@payloadcms/richtext-lexical';\nimport { BlockquoteJSXConverter } from './converters/blockquote.js';\nimport { HeadingJSXConverter } from './converters/heading.js';\nimport { HorizontalRuleJSXConverter } from './converters/horizontalRule.js';\nimport { LinebreakJSXConverter } from './converters/linebreak.js';\nimport { LinkJSXConverter } from './converters/link.js';\nimport { ListJSXConverter } from './converters/list.js';\nimport { ParagraphJSXConverter } from './converters/paragraph.js';\nimport { TabJSXConverter } from './converters/tab.js';\nimport { TableJSXConverter } from './converters/table.js';\nimport { TextJSXConverter } from './converters/text.js';\nimport { UploadJSXConverter } from './converters/upload.js';\n\nexport const defaultJSXConverters: JSXConverters<DefaultNodeTypes> = {\n ...ParagraphJSXConverter,\n ...TextJSXConverter,\n ...LinebreakJSXConverter,\n ...BlockquoteJSXConverter,\n ...TableJSXConverter,\n ...HeadingJSXConverter,\n ...HorizontalRuleJSXConverter,\n ...ListJSXConverter,\n ...LinkJSXConverter({}),\n ...UploadJSXConverter,\n ...TabJSXConverter,\n};\n","export function genFragmentIdentifier(text: string): string {\n return text\n .toLowerCase()\n .normalize('NFD') // tách dấu ra khỏi ký tự\n .replace(/[\\u0300-\\u036F]/g, '') // bỏ dấu VN\n .replace(/đ/g, 'd')\n .replace(/[\\u2010-\\u2015\\u2212\\uFE58\\uFE63\\uFF0D]/g, '-') // quy mọi dạng gạch ngang Unicode → '-'\n .replace(/[\\s\\u00A0\\/\\\\|_.,;:+=@&]+/g, '-') // khoảng trắng & dấu phân tách → '-'\n .replace(/[^a-z0-9-]/g, '') // giữ lại a-z, số, dấu '-'\n .replace(/-+/g, '-') // gộp nhiều dấu - liên tiếp bằng 1 dấu -\n .replace(/^-|-$/g, ''); // bỏ - ở đầu/cuối (nếu có)\n}\n","import type { SerializedLexicalNode } from '@payloadcms/richtext-lexical/lexical';\nimport type { SerializedTextNode } from 'lexical';\n\nexport function getTextLexicalNode(node: SerializedLexicalNode | null | undefined): string {\n if (!node) return '';\n if (node.type === 'text') {\n return (node as SerializedTextNode).text || '';\n }\n if (!('children' in node) || !Array.isArray(node.children)) return '';\n return node.children.map((child) => getTextLexicalNode(child)).join('');\n}\n","import type { SerializedHeadingNode } from '@payloadcms/richtext-lexical';\nimport type { SerializedLexicalNode } from '@payloadcms/richtext-lexical/lexical';\nimport type { SerializedEditorState } from 'lexical';\nimport { getTextLexicalNode } from './getTextOfLexical.js';\n\nexport interface TableOfContentsHeading {\n text: string;\n level: number;\n}\n\nexport interface TableOfContentsHeadingWithChildren extends TableOfContentsHeading {\n children: TableOfContentsHeadingWithChildren[];\n}\n\n// Hàm lấy tất cả các heading từ content\nexport function getHeaders(\n node: SerializedLexicalNode | SerializedEditorState,\n): TableOfContentsHeading[] {\n const headers: TableOfContentsHeading[] = [];\n\n // Handle SerializedEditorState\n if ('root' in node && node.root) {\n return getHeaders(node.root);\n }\n\n // At this point, node must be SerializedLexicalNode\n const lexicalNode = node as SerializedLexicalNode;\n\n // Handle heading node\n if (lexicalNode.type === 'heading') {\n const headingNode = lexicalNode as SerializedHeadingNode;\n const tag = headingNode.tag || '';\n const level =\n tag === 'h2'\n ? 2\n : tag === 'h3'\n ? 3\n : tag === 'h4'\n ? 4\n : tag === 'h5'\n ? 5\n : tag === 'h6'\n ? 6\n : 0;\n if (level > 0) {\n const text = getTextLexicalNode(lexicalNode);\n if (text) {\n headers.push({\n text,\n level,\n });\n }\n }\n }\n\n // Recursively process children\n if ('children' in lexicalNode && Array.isArray(lexicalNode.children)) {\n lexicalNode.children.forEach((child) => {\n headers.push(...getHeaders(child));\n });\n }\n\n return headers;\n}\n\n// Xây dựng cấu trúc mục lục\nexport function buildTableOfContents(\n headers: TableOfContentsHeading[],\n): TableOfContentsHeadingWithChildren[] {\n const result: TableOfContentsHeadingWithChildren[] = [];\n const stack: TableOfContentsHeadingWithChildren[] = [];\n\n headers.forEach((header) => {\n const headingWithChildren: TableOfContentsHeadingWithChildren = {\n ...header,\n children: [],\n };\n\n while (stack.length > 0 && stack[stack.length - 1].level >= header.level) {\n stack.pop();\n }\n\n if (stack.length === 0) {\n result.push(headingWithChildren);\n } else {\n stack[stack.length - 1].children.push(headingWithChildren);\n }\n\n stack.push(headingWithChildren);\n });\n\n return result;\n}\n","import type { SerializedLexicalNode } from '@payloadcms/richtext-lexical/lexical';\nimport { getTextLexicalNode } from './getTextOfLexical.js';\n\nconst WORDS_PER_MINUTE = 210;\n\nexport function getTimeRead(node: SerializedLexicalNode | null | undefined): number {\n if (!node) return 0;\n const text = getTextLexicalNode(node);\n const wordCount = text.trim().split(/\\s+/).length;\n const minutes = Math.ceil(wordCount / WORDS_PER_MINUTE);\n return Math.max(1, minutes); // Return at least 1 minute\n}\n","/* eslint-disable no-console */\nimport type { SerializedEditorState, SerializedLexicalNode } from 'lexical';\nimport { cloneElement, Fragment, isValidElement } from '@withl5e/l5e/jsx-runtime';\n\nimport type { SerializedBlockNode, SerializedInlineBlockNode } from '@payloadcms/richtext-lexical';\nimport { hasText } from '@payloadcms/richtext-lexical/shared';\nimport type { JSXConverter, JSXConverters, SerializedLexicalNodeWithParent } from './types.js';\n\nexport { defaultJSXConverters } from './defaultConverters.js';\n\nexport { stringToLexical } from './utils/stringToLexical.js';\nexport { genFragmentIdentifier } from './utils/genFragmentIdentifier.js';\nexport {\n buildTableOfContents,\n getHeaders,\n type TableOfContentsHeading,\n type TableOfContentsHeadingWithChildren,\n} from './utils/getTableOfContents.js';\nexport { getTextLexicalNode } from './utils/getTextOfLexical.js';\nexport { getTimeRead } from './utils/getTimeRead.js';\n\nexport type ConvertLexicalToJSXArgs = {\n converters: JSXConverters;\n data: SerializedEditorState;\n disableIndent?: boolean | string[];\n disableTextAlign?: boolean | string[];\n};\n\nexport function convertLexicalToJSX({\n converters,\n data,\n disableIndent,\n disableTextAlign,\n}: ConvertLexicalToJSXArgs): JSX.Element {\n if (hasText(data)) {\n return (\n <Fragment>\n {convertLexicalNodesToJSX({\n converters,\n disableIndent,\n disableTextAlign,\n nodes: data?.root?.children,\n parent: data?.root,\n })}\n </Fragment>\n );\n }\n return <Fragment />;\n}\n\nexport function convertLexicalNodesToJSX({\n converters,\n disableIndent,\n disableTextAlign,\n nodes,\n parent,\n}: {\n converters: JSXConverters;\n disableIndent?: boolean | string[];\n disableTextAlign?: boolean | string[];\n nodes: SerializedLexicalNode[];\n parent: SerializedLexicalNodeWithParent;\n}): JSX.Element[] {\n const unknownConverter: JSXConverter<any> = converters.unknown as JSXConverter<any>;\n\n const jsxArray: JSX.Element[] = nodes.map((node, i) => {\n let converterForNode: JSXConverter<any> | undefined;\n if (node.type === 'block') {\n converterForNode = converters?.blocks?.[(node as SerializedBlockNode)?.fields?.blockType];\n if (!converterForNode && !unknownConverter) {\n console.error(\n `Lexical => JSX converter: Blocks converter: found ${(node as SerializedBlockNode)?.fields?.blockType} block, but no converter is provided`,\n );\n }\n } else if (node.type === 'inlineBlock') {\n converterForNode =\n converters?.inlineBlocks?.[(node as SerializedInlineBlockNode)?.fields?.blockType];\n if (!converterForNode && !unknownConverter) {\n console.error(\n `Lexical => JSX converter: Inline Blocks converter: found ${(node as SerializedInlineBlockNode)?.fields?.blockType} inline block, but no converter is provided`,\n );\n }\n } else {\n converterForNode = converters[node.type] as JSXConverter<any>;\n }\n\n try {\n if (!converterForNode && unknownConverter) {\n converterForNode = unknownConverter;\n }\n\n let reactNode: JSX.Element;\n if (converterForNode) {\n const converted =\n typeof converterForNode === 'function'\n ? converterForNode({\n childIndex: i,\n converters,\n node,\n nodesToJSX: (args) => {\n return convertLexicalNodesToJSX({\n converters: args.converters ?? converters,\n disableIndent: args.disableIndent ?? disableIndent,\n disableTextAlign: args.disableTextAlign ?? disableTextAlign,\n nodes: args.nodes,\n parent: args.parent ?? {\n ...node,\n parent,\n },\n });\n },\n parent,\n })\n : converterForNode;\n reactNode = converted;\n } else {\n reactNode = <span key={i}>unknown node</span>;\n }\n\n let style: string = '';\n\n // Check if disableTextAlign is not true and does not include node type\n if (\n !disableTextAlign &&\n (!Array.isArray(disableTextAlign) || !disableTextAlign?.includes(node.type))\n ) {\n if ('format' in node && node.format) {\n switch (node.format) {\n case 'center':\n style += 'text-align: center;';\n break;\n case 'end':\n style += 'text-align: right;';\n break;\n case 'justify':\n style += 'text-align: justify;';\n break;\n case 'left':\n //style.textAlign = 'left'\n // Do nothing, as left is the default\n break;\n case 'right':\n style += 'text-align: right;';\n break;\n case 'start':\n style += 'text-align: left;';\n break;\n }\n }\n }\n\n if (\n !disableIndent &&\n (!Array.isArray(disableIndent) || !disableIndent?.includes(node.type))\n ) {\n if ('indent' in node && node.indent && node.type !== 'listitem') {\n // the unit should be px. Do not change it to rem, em, or something else.\n // The quantity should be 40px. Do not change it either.\n // See rationale in\n // https://github.com/payloadcms/payload/issues/13130#issuecomment-3058348085\n style += `padding-inline-start: ${Number(node.indent) * 40}px;`;\n }\n }\n\n if (isValidElement(reactNode)) {\n // Inject style into reactNode\n if (style) {\n const existingStyle =\n typeof reactNode?.props?.style === 'string' ? reactNode.props.style : '';\n const newStyle = `${style} ${existingStyle}`.trim();\n\n return cloneElement(reactNode, {\n key: i,\n style: newStyle,\n });\n }\n return cloneElement(reactNode, {\n key: i,\n });\n }\n\n return reactNode;\n } catch (error) {\n console.error('Error converting lexical node to JSX:', error, 'node:', node);\n return null;\n }\n });\n\n return jsxArray.filter(Boolean);\n}\n"],"names":["BlockquoteJSXConverter","node","nodesToJSX","children","jsxFactory","HeadingJSXConverter","NodeTag","HorizontalRuleJSXConverter","LinebreakJSXConverter","LinkJSXConverter","internalDocToHref","rel","target","href","ListJSXConverter","parent","hasSubLists","child","uuid","uuidv4","__Fragment","ParagraphJSXConverter","TabJSXConverter","TableJSXConverter","TagName","headerStateClass","style","colSpan","rowSpan","TextJSXConverter","text","NodeFormat","UploadJSXConverter","uploadNode","uploadDoc","url","pictureJSX","size","imageSize","imageSizeURL","defaultJSXConverters","genFragmentIdentifier","getTextLexicalNode","getHeaders","headers","lexicalNode","tag","level","buildTableOfContents","result","stack","header","headingWithChildren","WORDS_PER_MINUTE","getTimeRead","wordCount","minutes","convertLexicalToJSX","converters","data","disableIndent","disableTextAlign","hasText","Fragment","convertLexicalNodesToJSX","nodes","unknownConverter","i","converterForNode","reactNode","args","isValidElement","existingStyle","newStyle","cloneElement","error"],"mappings":";;;;;AAG0E,MAAAA,IAAA;AAAA,EACxE,OAAO,CAAC,EAAE,MAAAC,GAAM,YAAAC,QAAiB;AAC/B,UAAMC,IAAWD,EAAW;AAAA,MAC1B,OAAOD,EAAK;AAAA,IAAA,CACb;AAED,WAAO,gBAAAG,EAAC,oBAAYD,CAAS;AAAA,EAC/B;AACF,GCRyEE,IAAA;AAAA,EACvE,SAAS,CAAC,EAAE,MAAAJ,GAAM,YAAAC,QAAiB;AACjC,UAAMC,IAAWD,EAAW;AAAA,MAC1B,OAAOD,EAAK;AAAA,IAAA,CACb,GAEKK,IAAUL,EAAK;AAErB,WAAO,gBAAAG,EAACE,SAASH,CAAS;AAAA,EAC5B;AACF,GCXuFI,IAAA;AAAA,EACrF,kCAAiB,MAAA,IAAG;AACtB,GCD6EC,IAAA;AAAA,EAC3E,6BAAY,MAAA,IAAG;AACjB,GCA+FC,IAAA,CAAA,EAAA,mBAAAC,SAAA;AAAA,EAC7F,UAAU,CAAC,EAAE,MAAAT,GAAM,YAAAC,QAAiB;AAClC,UAAMC,IAAWD,EAAW;AAAA,MAC1B,OAAOD,EAAK;AAAA,IAAA,CACb,GAEKU,IAA0BV,EAAK,OAAO,SAAS,wBAAwB,QACvEW,IAA6BX,EAAK,OAAO,SAAS,WAAW;AAEnE,WACE,gBAAAG,EAAC,KAAA,EAAE,MAAMH,EAAK,OAAO,KAAW,KAAAU,GAAK,QAAAC,EAAO,GACzCT,CACH;AAAA,EAEJ;AAAA,EACA,MAAM,CAAC,EAAE,MAAAF,GAAM,YAAAC,QAAiB;AAC9B,UAAMC,IAAWD,EAAW;AAAA,MAC1B,OAAOD,EAAK;AAAA,IAAA,CACb,GAEKU,IAA0BV,EAAK,OAAO,SAAS,wBAAwB,QACvEW,IAA6BX,EAAK,OAAO,SAAS,WAAW;AAEnE,QAAIY,IAAeZ,EAAK,OAAO,OAAO;AACtC,WAAIA,EAAK,OAAO,aAAa,eACvBS,IACFG,IAAOH,EAAkB,EAAE,UAAUT,EAAA,CAAM,KAE3C,QAAQ;AAAA,MACN;AAAA,IAAA,GAEFY,IAAO,OAKT,gBAAAT,EAAC,OAAE,MAAAS,GAAkB,KAAAF,GAAK,QAAAC,KACvBT,CACH;AAAA,EAEJ;AACF,ICxCaW,IAA+E;AAAA,EAC1F,MAAM,CAAC,EAAE,MAAAb,GAAM,YAAAC,QAAiB;AAC9B,UAAMC,IAAWD,EAAW;AAAA,MAC1B,OAAOD,EAAK;AAAA,IAAA,CACb,GAEKK,IAAUL,EAAK;AAErB,6BAAQK,GAAA,EAAQ,OAAO,QAAQL,GAAM,QAAQ,MAAKE,CAAS;AAAA,EAC7D;AAAA,EACA,UAAU,CAAC,EAAE,MAAAF,GAAM,YAAAC,GAAY,QAAAa,QAAa;AAC1C,UAAMC,IAAcf,EAAK,SAAS,KAAK,CAACgB,MAAUA,EAAM,SAAS,MAAM,GAEjEd,IAAWD,EAAW;AAAA,MAC1B,OAAOD,EAAK;AAAA,IAAA,CACb;AAED,QAAI,cAAcc,KAAUA,GAAQ,aAAa,SAAS;AACxD,YAAMG,IAAOC,EAAA;AAEb,aACE,gBAAAf;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,gBAAcH,EAAK,UAAU,SAAS;AAAA,UACtC,OAAO,qBAAqBA,EAAK,UAAU,gCAAgC,+BAA+B,GAAGe,IAAc,oBAAoB,EAAE;AAAA,UAEjJ,MAAK;AAAA,UACL,OAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAOf,GAAM;AAAA,QAAA;AAAA,QAEZe,IACCb,IAEA,gBAAAC,EAAAgB,GAAA,MACE,gBAAAhB,EAAC,WAAM,SAASH,EAAK,SAAS,IAAIiB,GAAM,UAAU,IAAM,MAAK,WAAA,CAAW,GACxE,gBAAAd,EAAC,SAAA,EAAM,KAAKc,KAAOf,CAAS,GAC5B,gBAAAC,EAAC,MAAA,IAAG,CACN;AAAA,MAAA;AAAA,IAIR;AACE,aACE,gBAAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAO,GAAGY,IAAc,mBAAmB,EAAE;AAAA,UAC7C,OAAOA,IAAc,2BAA2B;AAAA,UAChD,OAAOf,GAAM;AAAA,QAAA;AAAA,QAEZE;AAAA,MAAA;AAAA,EAIT;AACF,GCpD6EkB,IAAA;AAAA,EAC3E,WAAW,CAAC,EAAE,MAAApB,GAAM,YAAAC,QAAyC;AAC3D,UAAMC,IAAWD,EAAW;AAAA,MAC1B,OAAOD,EAAK;AAAA,IAAA,CACb;AAED,WAAKE,GAAU,SAQR,gBAAAC,EAAC,WAAGD,CAAS,IANhB,gBAAAC,EAAC,KAAA,MACC,gBAAAA,EAAC,MAAA,IAAG,CACN;AAAA,EAKN;AACF,GCpBiEkB,IAAA;AAAA,EAC/D,KAAK;AACP,GCIIC,IAAA;AAAA,EACF,OAAO,CAAC,EAAE,MAAAtB,GAAM,YAAAC,QAAiB;AAC/B,UAAMC,IAAWD,EAAW;AAAA,MAC1B,OAAOD,EAAK;AAAA,IAAA,CACb;AACD,WACE,gBAAAG,EAAC,OAAA,EAAI,OAAM,+CACR,SAAA,EAAM,OAAM,iBAAgB,OAAM,gCACjC,gBAAAA,EAAC,SAAA,MAAOD,CAAS,CACnB,CACF;AAAA,EAEJ;AAAA,EACA,WAAW,CAAC,EAAE,MAAAF,GAAM,YAAAC,QAAiB;AACnC,UAAMC,IAAWD,EAAW;AAAA,MAC1B,OAAOD,EAAK;AAAA,IAAA,CACb,GAEKuB,IAAUvB,EAAK,cAAc,IAAI,OAAO,MACxCwB,IAAmB,6BAA6BxB,EAAK,WAAW;AACtE,QAAIyB,IAAQ;AACZ,IAAIzB,EAAK,oBACPyB,KAAS,qBAAqBzB,EAAK,eAAe,MAGpDyB,KAAS,2BAETA,KAAS;AAGT,UAAMC,IAAU1B,EAAK,WAAWA,EAAK,UAAU,IAAIA,EAAK,UAAU,QAC5D2B,IAAU3B,EAAK,WAAWA,EAAK,UAAU,IAAIA,EAAK,UAAU;AAElE,WACE,gBAAAG;AAAA,MAACoB;AAAA,MAAA;AAAA,QACC,OAAO,sBAAsBC,CAAgB;AAAA,QAC7C,SAASE;AAAA,QACT,SAASC;AAAA,QACT,OAAAF;AAAA,MAAA;AAAA,MAECvB;AAAA,IAAA;AAAA,EAGP;AAAA,EACA,UAAU,CAAC,EAAE,MAAAF,GAAM,YAAAC,QAAiB;AAClC,UAAMC,IAAWD,EAAW;AAAA,MAC1B,OAAOD,EAAK;AAAA,IAAA,CACb;AACD,WAAO,gBAAAG,EAAC,MAAA,EAAG,OAAM,oBAAA,GAAqBD,CAAS;AAAA,EACjD;AACF,GCnDa0B,IAAsD;AAAA,EACjE,MAAM,CAAC,EAAE,MAAA5B,QAA8B;AACrC,QAAI6B,IAAoB7B,EAAK;AAE7B,WAAIA,EAAK,SAAS8B,EAAW,YAC3BD,IAAO,gBAAA1B,EAAC,gBAAQ0B,CAAK,IAEnB7B,EAAK,SAAS8B,EAAW,cAC3BD,IAAO,gBAAA1B,EAAC,YAAI0B,CAAK,IAEf7B,EAAK,SAAS8B,EAAW,qBAC3BD,IAAO,gBAAA1B,EAAC,QAAA,EAAK,OAAM,iCAAA,GAAkC0B,CAAK,IAExD7B,EAAK,SAAS8B,EAAW,iBAC3BD,IAAO,gBAAA1B,EAAC,QAAA,EAAK,OAAM,8BAAA,GAA+B0B,CAAK,IAErD7B,EAAK,SAAS8B,EAAW,YAC3BD,IAAO,gBAAA1B,EAAC,cAAM0B,CAAK,IAEjB7B,EAAK,SAAS8B,EAAW,iBAC3BD,IAAO,gBAAA1B,EAAC,aAAK0B,CAAK,IAEhB7B,EAAK,SAAS8B,EAAW,mBAC3BD,IAAO,gBAAA1B,EAAC,aAAK0B,CAAK,IAGbA;AAAA,EACT;AACF,GC/BuEE,IAAA;AAAA,EACrE,QAAQ,CAAC,EAAE,MAAA/B,QAAW;AAEpB,UAAMgC,IAAahC;AACnB,QAAI,OAAOgC,EAAW,SAAU;AAC9B,aAAO;AAGT,UAAMC,IAAYD,EAAW,OAEvBE,IAAMD,EAAU;AAKtB,QAAI,CAACA,EAAU,SAAS,WAAW,OAAO;AACxC,+BACG,KAAA,EAAE,MAAMC,GAAK,KAAI,sBAAA,GACfD,EAAU,QACb;AAOJ,QAAI,CAACA,EAAU,SAAS,CAAC,OAAO,KAAKA,EAAU,KAAK,EAAE;AACpD,aACE,gBAAA9B,EAAC,OAAA,EAAI,KAAK8B,EAAU,UAAU,QAAQA,EAAU,QAAQ,KAAKC,GAAK,OAAOD,EAAU,MAAA,CAAO;AAO9F,UAAME,IAA4B,CAAA;AAGlC,eAAWC,KAAQH,EAAU,OAAO;AAClC,YAAMI,IAAYJ,EAAU,MAAMG,CAAI;AAGtC,UACE,CAACC,KACD,CAACA,EAAU,SACX,CAACA,EAAU,UACX,CAACA,EAAU,YACX,CAACA,EAAU,YACX,CAACA,EAAU,YACX,CAACA,EAAU;AAEX;AAEF,YAAMC,IAAeD,GAAW;AAEhC,MAAAF,EAAW;AAAA,QACT,gBAAAhC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAKiC;AAAA,YACL,OAAO,eAAeC,EAAU,KAAK;AAAA,YACrC,QAAQC;AAAA,YACR,MAAMD,EAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MAClB;AAAA,IAEJ;AAGA,WAAAF,EAAW;AAAA,MACT,gBAAAhC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK8B,GAAW;AAAA,UAChB,QAAQA,GAAW;AAAA,UACnB,KAAK;AAAA,UACL,KAAKC;AAAA,UACL,OAAOD,GAAW;AAAA,QAAA;AAAA,MAAA;AAAA,IACpB,GAEK,gBAAA9B,EAAC,iBAASgC,CAAW;AAAA,EAC9B;AACF,GCnEaI,IAAwD;AAAA,EACnE,GAAGnB;AAAA,EACH,GAAGQ;AAAA,EACH,GAAGrB;AAAA,EACH,GAAGR;AAAA,EACH,GAAGuB;AAAA,EACH,GAAGlB;AAAA,EACH,GAAGE;AAAA,EACH,GAAGO;AAAA,EACH,GAAGL,EAAiB,CAAA,CAAE;AAAA,EACtB,GAAGuB;AAAA,EACH,GAAGV;AACL;AC3BO,SAASmB,EAAsBX,GAAsB;AAC1D,SAAOA,EACJ,YAAA,EACA,UAAU,KAAK,EACf,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,MAAM,GAAG,EACjB,QAAQ,4CAA4C,GAAG,EACvD,QAAQ,8BAA8B,GAAG,EACzC,QAAQ,eAAe,EAAE,EACzB,QAAQ,OAAO,GAAG,EAClB,QAAQ,UAAU,EAAE;AACzB;ACRO,SAASY,EAAmBzC,GAAwD;AACzF,SAAKA,IACDA,EAAK,SAAS,SACRA,EAA4B,QAAQ,KAE1C,EAAE,cAAcA,MAAS,CAAC,MAAM,QAAQA,EAAK,QAAQ,IAAU,KAC5DA,EAAK,SAAS,IAAI,CAACgB,MAAUyB,EAAmBzB,CAAK,CAAC,EAAE,KAAK,EAAE,IALpD;AAMpB;ACKO,SAAS0B,EACd1C,GAC0B;AAC1B,QAAM2C,IAAoC,CAAA;AAG1C,MAAI,UAAU3C,KAAQA,EAAK;AACzB,WAAO0C,EAAW1C,EAAK,IAAI;AAI7B,QAAM4C,IAAc5C;AAGpB,MAAI4C,EAAY,SAAS,WAAW;AAElC,UAAMC,IADcD,EACI,OAAO,IACzBE,IACJD,MAAQ,OACJ,IACAA,MAAQ,OACN,IACAA,MAAQ,OACN,IACAA,MAAQ,OACN,IACAA,MAAQ,OACN,IACA;AACd,QAAIC,IAAQ,GAAG;AACb,YAAMjB,IAAOY,EAAmBG,CAAW;AAC3C,MAAIf,KACFc,EAAQ,KAAK;AAAA,QACX,MAAAd;AAAA,QACA,OAAAiB;AAAA,MAAA,CACD;AAAA,IAEL;AAAA,EACF;AAGA,SAAI,cAAcF,KAAe,MAAM,QAAQA,EAAY,QAAQ,KACjEA,EAAY,SAAS,QAAQ,CAAC5B,MAAU;AACtC,IAAA2B,EAAQ,KAAK,GAAGD,EAAW1B,CAAK,CAAC;AAAA,EACnC,CAAC,GAGI2B;AACT;AAGO,SAASI,EACdJ,GACsC;AACtC,QAAMK,IAA+C,CAAA,GAC/CC,IAA8C,CAAA;AAEpD,SAAAN,EAAQ,QAAQ,CAACO,MAAW;AAC1B,UAAMC,IAA0D;AAAA,MAC9D,GAAGD;AAAA,MACH,UAAU,CAAA;AAAA,IAAC;AAGb,WAAOD,EAAM,SAAS,KAAKA,EAAMA,EAAM,SAAS,CAAC,EAAE,SAASC,EAAO;AACjE,MAAAD,EAAM,IAAA;AAGR,IAAIA,EAAM,WAAW,IACnBD,EAAO,KAAKG,CAAmB,IAE/BF,EAAMA,EAAM,SAAS,CAAC,EAAE,SAAS,KAAKE,CAAmB,GAG3DF,EAAM,KAAKE,CAAmB;AAAA,EAChC,CAAC,GAEMH;AACT;ACzFA,MAAMI,IAAmB;AAElB,SAASC,EAAYrD,GAAwD;AAClF,MAAI,CAACA,EAAM,QAAO;AAElB,QAAMsD,IADOb,EAAmBzC,CAAI,EACb,KAAA,EAAO,MAAM,KAAK,EAAE,QACrCuD,IAAU,KAAK,KAAKD,IAAYF,CAAgB;AACtD,SAAO,KAAK,IAAI,GAAGG,CAAO;AAC5B;ACiBO,SAASC,EAAoB;AAAA,EAClC,YAAAC;AAAA,EACA,MAAAC;AAAA,EACA,eAAAC;AAAA,EACA,kBAAAC;AACF,GAAyC;AACvC,SAAIC,EAAQH,CAAI,IAEZ,gBAAAvD,EAAC2D,SACEC,EAAyB;AAAA,IACxB,YAAAN;AAAA,IACA,eAAAE;AAAA,IACA,kBAAAC;AAAA,IACA,OAAOF,GAAM,MAAM;AAAA,IACnB,QAAQA,GAAM;AAAA,EAAA,CACf,CACH,sBAGII,GAAA,IAAS;AACnB;AAEO,SAASC,EAAyB;AAAA,EACvC,YAAAN;AAAA,EACA,eAAAE;AAAA,EACA,kBAAAC;AAAA,EACA,OAAAI;AAAA,EACA,QAAAlD;AACF,GAMkB;AAChB,QAAMmD,IAAsCR,EAAW;AA6HvD,SA3HgCO,EAAM,IAAI,CAAChE,GAAMkE,MAAM;AACrD,QAAIC;AACJ,IAAInE,EAAK,SAAS,WAChBmE,IAAmBV,GAAY,SAAUzD,GAA8B,QAAQ,SAAS,GACpF,CAACmE,KAAoB,CAACF,KACxB,QAAQ;AAAA,MACN,qDAAsDjE,GAA8B,QAAQ,SAAS;AAAA,IAAA,KAGhGA,EAAK,SAAS,iBACvBmE,IACEV,GAAY,eAAgBzD,GAAoC,QAAQ,SAAS,GAC/E,CAACmE,KAAoB,CAACF,KACxB,QAAQ;AAAA,MACN,4DAA6DjE,GAAoC,QAAQ,SAAS;AAAA,IAAA,KAItHmE,IAAmBV,EAAWzD,EAAK,IAAI;AAGzC,QAAI;AACF,MAAI,CAACmE,KAAoBF,MACvBE,IAAmBF;AAGrB,UAAIG;AACJ,MAAID,IAsBFC,IApBE,OAAOD,KAAqB,aACxBA,EAAiB;AAAA,QACf,YAAYD;AAAA,QACZ,YAAAT;AAAA,QACA,MAAAzD;AAAA,QACA,YAAY,CAACqE,MACJN,EAAyB;AAAA,UAC9B,YAAYM,EAAK,cAAcZ;AAAA,UAC/B,eAAeY,EAAK,iBAAiBV;AAAA,UACrC,kBAAkBU,EAAK,oBAAoBT;AAAA,UAC3C,OAAOS,EAAK;AAAA,UACZ,QAAQA,EAAK,UAAU;AAAA,YACrB,GAAGrE;AAAA,YACH,QAAAc;AAAA,UAAA;AAAA,QACF,CACD;AAAA,QAEH,QAAAA;AAAA,MAAA,CACD,IACDqD,IAGNC,IAAY,gBAAAjE,EAAC,QAAA,EAAK,KAAK+D,EAAA,GAAG,cAAY;AAGxC,UAAIzC,IAAgB;AAGpB,UACE,CAACmC,MACA,CAAC,MAAM,QAAQA,CAAgB,KAAK,CAACA,GAAkB,SAAS5D,EAAK,IAAI,MAEtE,YAAYA,KAAQA,EAAK;AAC3B,gBAAQA,EAAK,QAAA;AAAA,UACX,KAAK;AACH,YAAAyB,KAAS;AACT;AAAA,UACF,KAAK;AACH,YAAAA,KAAS;AACT;AAAA,UACF,KAAK;AACH,YAAAA,KAAS;AACT;AAAA,UACF,KAAK;AAGH;AAAA,UACF,KAAK;AACH,YAAAA,KAAS;AACT;AAAA,UACF,KAAK;AACH,YAAAA,KAAS;AACT;AAAA,QAAA;AAkBR,UAZE,CAACkC,MACA,CAAC,MAAM,QAAQA,CAAa,KAAK,CAACA,GAAe,SAAS3D,EAAK,IAAI,MAEhE,YAAYA,KAAQA,EAAK,UAAUA,EAAK,SAAS,eAKnDyB,KAAS,yBAAyB,OAAOzB,EAAK,MAAM,IAAI,EAAE,QAI1DsE,EAAeF,CAAS,GAAG;AAE7B,YAAI3C,GAAO;AACT,gBAAM8C,IACJ,OAAOH,GAAW,OAAO,SAAU,WAAWA,EAAU,MAAM,QAAQ,IAClEI,IAAW,GAAG/C,CAAK,IAAI8C,CAAa,GAAG,KAAA;AAE7C,iBAAOE,EAAaL,GAAW;AAAA,YAC7B,KAAKF;AAAA,YACL,OAAOM;AAAA,UAAA,CACR;AAAA,QACH;AACA,eAAOC,EAAaL,GAAW;AAAA,UAC7B,KAAKF;AAAA,QAAA,CACN;AAAA,MACH;AAEA,aAAOE;AAAA,IACT,SAASM,GAAO;AACd,qBAAQ,MAAM,yCAAyCA,GAAO,SAAS1E,CAAI,GACpE;AAAA,IACT;AAAA,EACF,CAAC,EAEe,OAAO,OAAO;AAChC;"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
function o(t) {
|
|
2
|
+
const e = t == null ? "" : String(t);
|
|
3
|
+
return {
|
|
4
|
+
root: {
|
|
5
|
+
type: "root",
|
|
6
|
+
format: "",
|
|
7
|
+
indent: 0,
|
|
8
|
+
version: 1,
|
|
9
|
+
direction: "ltr",
|
|
10
|
+
children: (e.length === 0 ? [""] : e.split(/\r?\n/)).map((r) => ({
|
|
11
|
+
type: "paragraph",
|
|
12
|
+
format: "",
|
|
13
|
+
indent: 0,
|
|
14
|
+
version: 1,
|
|
15
|
+
direction: "ltr",
|
|
16
|
+
textFormat: 0,
|
|
17
|
+
textStyle: "",
|
|
18
|
+
children: r.length === 0 ? [] : [
|
|
19
|
+
{
|
|
20
|
+
type: "text",
|
|
21
|
+
text: r,
|
|
22
|
+
version: 1,
|
|
23
|
+
detail: 0,
|
|
24
|
+
format: 0,
|
|
25
|
+
mode: "normal",
|
|
26
|
+
style: ""
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}))
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
o as stringToLexical
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=stringToLexical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stringToLexical.js","sources":["../src/richtext-render/utils/stringToLexical.ts"],"sourcesContent":["export type LexicalContent = {\n root: {\n type: string;\n format: '' | 'left' | 'start' | 'center' | 'right' | 'end' | 'justify';\n indent: number;\n version: number;\n direction: 'ltr' | 'rtl' | null;\n children: Array<{ type: any; version: number; [k: string]: unknown }>;\n };\n [k: string]: unknown;\n};\n\nexport function stringToLexical(text: string | null | undefined): LexicalContent {\n const raw = text == null ? '' : String(text);\n const lines = raw.length === 0 ? [''] : raw.split(/\\r?\\n/);\n\n return {\n root: {\n type: 'root',\n format: '',\n indent: 0,\n version: 1,\n direction: 'ltr',\n children: lines.map((line) => ({\n type: 'paragraph',\n format: '',\n indent: 0,\n version: 1,\n direction: 'ltr',\n textFormat: 0,\n textStyle: '',\n children:\n line.length === 0\n ? []\n : [\n {\n type: 'text',\n text: line,\n version: 1,\n detail: 0,\n format: 0,\n mode: 'normal',\n style: '',\n },\n ],\n })),\n },\n };\n}\n"],"names":["stringToLexical","text","raw","line"],"mappings":"AAYO,SAASA,EAAgBC,GAAiD;AAC/E,QAAMC,IAAMD,KAAQ,OAAO,KAAK,OAAOA,CAAI;AAG3C,SAAO;AAAA,IACL,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,WAAW;AAAA,MACX,WATUC,EAAI,WAAW,IAAI,CAAC,EAAE,IAAIA,EAAI,MAAM,OAAO,GASrC,IAAI,CAACC,OAAU;AAAA,QAC7B,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,WAAW;AAAA,QACX,UACEA,EAAK,WAAW,IACZ,CAAA,IACA;AAAA,UACE;AAAA,YACE,MAAM;AAAA,YACN,MAAMA;AAAA,YACN,SAAS;AAAA,YACT,QAAQ;AAAA,YACR,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,OAAO;AAAA,UAAA;AAAA,QACT;AAAA,MACF,EACN;AAAA,IAAA;AAAA,EACJ;AAEJ;"}
|
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './src/richtext-render';
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@withl5e/richtext-payload",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Payload Lexical rich text renderer adapter for L5E.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./src/richtext-render/index.tsx",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"src",
|
|
12
|
+
"index.ts",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./src/richtext-render/index.tsx",
|
|
19
|
+
"development": "./index.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./stringToLexical": {
|
|
23
|
+
"types": "./src/richtext-render/utils/stringToLexical.ts",
|
|
24
|
+
"development": "./src/richtext-render/utils/stringToLexical.ts",
|
|
25
|
+
"default": "./dist/stringToLexical.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"uuid": "13.0.0"
|
|
30
|
+
},
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"@withl5e/l5e": "^0.1.0-alpha.0",
|
|
33
|
+
"@payloadcms/richtext-lexical": "^3.73.0",
|
|
34
|
+
"lexical": "^0.39.0",
|
|
35
|
+
"payload": "^3.73.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@payloadcms/richtext-lexical": "3.73.0",
|
|
39
|
+
"lexical": "0.39.0",
|
|
40
|
+
"payload": "3.73.0",
|
|
41
|
+
"typescript": "^5.6.3",
|
|
42
|
+
"vite": "^7.1.5",
|
|
43
|
+
"@withl5e/l5e": "0.1.0-alpha.0"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "vite build",
|
|
50
|
+
"typecheck": "tsc --noEmit"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SerializedQuoteNode } from '@payloadcms/richtext-lexical';
|
|
2
|
+
import type { JSXConverters } from '../types.js';
|
|
3
|
+
|
|
4
|
+
export const BlockquoteJSXConverter: JSXConverters<SerializedQuoteNode> = {
|
|
5
|
+
quote: ({ node, nodesToJSX }) => {
|
|
6
|
+
const children = nodesToJSX({
|
|
7
|
+
nodes: node.children,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
return <blockquote>{children}</blockquote>;
|
|
11
|
+
},
|
|
12
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { SerializedHeadingNode } from '@payloadcms/richtext-lexical';
|
|
2
|
+
import type { JSXConverters } from '../types.js';
|
|
3
|
+
|
|
4
|
+
export const HeadingJSXConverter: JSXConverters<SerializedHeadingNode> = {
|
|
5
|
+
heading: ({ node, nodesToJSX }) => {
|
|
6
|
+
const children = nodesToJSX({
|
|
7
|
+
nodes: node.children,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const NodeTag = node.tag;
|
|
11
|
+
|
|
12
|
+
return <NodeTag>{children}</NodeTag>;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { SerializedAutoLinkNode, SerializedLinkNode } from '@payloadcms/richtext-lexical';
|
|
2
|
+
import type { JSXConverters } from '../types.js';
|
|
3
|
+
|
|
4
|
+
export const LinkJSXConverter: (args: {
|
|
5
|
+
internalDocToHref?: (args: { linkNode: SerializedLinkNode }) => string;
|
|
6
|
+
}) => JSXConverters<SerializedAutoLinkNode | SerializedLinkNode> = ({ internalDocToHref }) => ({
|
|
7
|
+
autolink: ({ node, nodesToJSX }) => {
|
|
8
|
+
const children = nodesToJSX({
|
|
9
|
+
nodes: node.children,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const rel: string | undefined = node.fields.newTab ? 'noopener noreferrer' : undefined;
|
|
13
|
+
const target: string | undefined = node.fields.newTab ? '_blank' : undefined;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<a href={node.fields.url} {...{ rel, target }}>
|
|
17
|
+
{children}
|
|
18
|
+
</a>
|
|
19
|
+
);
|
|
20
|
+
},
|
|
21
|
+
link: ({ node, nodesToJSX }) => {
|
|
22
|
+
const children = nodesToJSX({
|
|
23
|
+
nodes: node.children,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const rel: string | undefined = node.fields.newTab ? 'noopener noreferrer' : undefined;
|
|
27
|
+
const target: string | undefined = node.fields.newTab ? '_blank' : undefined;
|
|
28
|
+
|
|
29
|
+
let href: string = node.fields.url ?? '';
|
|
30
|
+
if (node.fields.linkType === 'internal') {
|
|
31
|
+
if (internalDocToHref) {
|
|
32
|
+
href = internalDocToHref({ linkNode: node });
|
|
33
|
+
} else {
|
|
34
|
+
console.error(
|
|
35
|
+
'Lexical => JSX converter: Link converter: found internal link, but internalDocToHref is not provided',
|
|
36
|
+
);
|
|
37
|
+
href = '#'; // fallback
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<a href={href} {...{ rel, target }}>
|
|
43
|
+
{children}
|
|
44
|
+
</a>
|
|
45
|
+
);
|
|
46
|
+
},
|
|
47
|
+
});
|