@webround/editor 0.0.0-stage → 0.3.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.
Files changed (227) hide show
  1. package/dist/blocks.d.ts +90 -0
  2. package/dist/blocks.js +119 -0
  3. package/dist/bridge.d.ts +96 -0
  4. package/dist/bridge.js +970 -0
  5. package/dist/check/aria.d.ts +19 -0
  6. package/dist/check/aria.js +106 -0
  7. package/dist/check/cli.d.ts +3 -0
  8. package/dist/check/cli.js +30 -0
  9. package/dist/check/css.d.ts +13 -0
  10. package/dist/check/css.js +63 -0
  11. package/dist/check/html.d.ts +8 -0
  12. package/dist/check/html.js +29 -0
  13. package/dist/check/index.d.ts +4 -0
  14. package/dist/check/index.js +5 -0
  15. package/dist/check/links.d.ts +7 -0
  16. package/dist/check/links.js +23 -0
  17. package/dist/check/orphans.d.ts +20 -0
  18. package/dist/check/orphans.js +57 -0
  19. package/dist/check/producer-code.d.ts +53 -0
  20. package/dist/check/producer-code.js +379 -0
  21. package/dist/check/producer-dom.d.ts +21 -0
  22. package/dist/check/producer-dom.js +52 -0
  23. package/dist/check/project.d.ts +20 -0
  24. package/dist/check/project.js +51 -0
  25. package/dist/check/rules.d.ts +7 -0
  26. package/dist/check/rules.js +517 -0
  27. package/dist/check/types.d.ts +160 -0
  28. package/dist/check/types.js +22 -0
  29. package/dist/components/WrAltcha.d.ts +5 -0
  30. package/dist/components/WrAltcha.js +8 -0
  31. package/dist/components/WrButton.d.ts +8 -0
  32. package/dist/components/WrButton.js +34 -0
  33. package/dist/components/WrForm.d.ts +6 -0
  34. package/dist/components/WrForm.js +29 -0
  35. package/dist/components/WrFormPrivacy.d.ts +4 -0
  36. package/dist/components/WrFormPrivacy.js +7 -0
  37. package/dist/components/WrFormSuccess.d.ts +4 -0
  38. package/dist/components/WrFormSuccess.js +12 -0
  39. package/dist/components/WrIframe.d.ts +12 -0
  40. package/dist/components/WrIframe.js +30 -0
  41. package/dist/components/WrImage.d.ts +9 -0
  42. package/dist/components/WrImage.js +28 -0
  43. package/dist/components/WrInput.d.ts +8 -0
  44. package/dist/components/WrInput.js +29 -0
  45. package/dist/components/WrLink.d.ts +10 -0
  46. package/dist/components/WrLink.js +38 -0
  47. package/dist/components/WrNav.d.ts +26 -0
  48. package/dist/components/WrNav.js +30 -0
  49. package/dist/components/WrSection.d.ts +11 -0
  50. package/dist/components/WrSection.js +5 -0
  51. package/dist/components/WrShared.d.ts +12 -0
  52. package/dist/components/WrShared.js +20 -0
  53. package/dist/components/WrText.d.ts +11 -0
  54. package/dist/components/WrText.js +41 -0
  55. package/dist/components/WrVideo.d.ts +9 -0
  56. package/dist/components/WrVideo.js +73 -0
  57. package/dist/components/text-editor/CodeThemeContext.d.ts +8 -0
  58. package/dist/components/text-editor/CodeThemeContext.js +10 -0
  59. package/dist/components/text-editor/ExampleTheme.d.ts +77 -0
  60. package/dist/components/text-editor/ExampleTheme.js +76 -0
  61. package/dist/components/text-editor/ToolbarContext.d.ts +17 -0
  62. package/dist/components/text-editor/ToolbarContext.js +32 -0
  63. package/dist/components/text-editor/WrTextEditor.d.ts +13 -0
  64. package/dist/components/text-editor/WrTextEditor.js +48 -0
  65. package/dist/components/text-editor/common/constants.d.ts +109 -0
  66. package/dist/components/text-editor/common/constants.js +58 -0
  67. package/dist/components/text-editor/common/surface.d.ts +3 -0
  68. package/dist/components/text-editor/common/surface.js +8 -0
  69. package/dist/components/text-editor/common/utils.d.ts +7 -0
  70. package/dist/components/text-editor/common/utils.js +78 -0
  71. package/dist/components/text-editor/hooks/useLexicalCommitOnBlur.d.ts +5 -0
  72. package/dist/components/text-editor/hooks/useLexicalCommitOnBlur.js +41 -0
  73. package/dist/components/text-editor/hooks/useLexicalMarkdown.d.ts +33 -0
  74. package/dist/components/text-editor/hooks/useLexicalMarkdown.js +284 -0
  75. package/dist/components/text-editor/nodes/CodeBlockNode.d.ts +23 -0
  76. package/dist/components/text-editor/nodes/CodeBlockNode.js +138 -0
  77. package/dist/components/text-editor/nodes/HorizontalRuleNode.d.ts +13 -0
  78. package/dist/components/text-editor/nodes/HorizontalRuleNode.js +22 -0
  79. package/dist/components/text-editor/plugins/CodeBlockPlugin.d.ts +2 -0
  80. package/dist/components/text-editor/plugins/CodeBlockPlugin.js +38 -0
  81. package/dist/components/text-editor/plugins/FontPlugin.d.ts +12 -0
  82. package/dist/components/text-editor/plugins/FontPlugin.js +114 -0
  83. package/dist/components/text-editor/plugins/FontSizePlugin.d.ts +7 -0
  84. package/dist/components/text-editor/plugins/FontSizePlugin.js +105 -0
  85. package/dist/components/text-editor/plugins/FontWeightPlugin.d.ts +6 -0
  86. package/dist/components/text-editor/plugins/FontWeightPlugin.js +103 -0
  87. package/dist/components/text-editor/plugins/HTMLTagPlugin.d.ts +7 -0
  88. package/dist/components/text-editor/plugins/HTMLTagPlugin.js +82 -0
  89. package/dist/components/text-editor/plugins/HorizontalRulePlugin.d.ts +2 -0
  90. package/dist/components/text-editor/plugins/HorizontalRulePlugin.js +35 -0
  91. package/dist/components/text-editor/plugins/LineSpacingPlugin.d.ts +7 -0
  92. package/dist/components/text-editor/plugins/LineSpacingPlugin.js +83 -0
  93. package/dist/components/text-editor/plugins/LinkPlugin.d.ts +8 -0
  94. package/dist/components/text-editor/plugins/LinkPlugin.js +183 -0
  95. package/dist/components/text-editor/plugins/ListToolbarPlugin.d.ts +7 -0
  96. package/dist/components/text-editor/plugins/ListToolbarPlugin.js +40 -0
  97. package/dist/components/text-editor/plugins/LoadContentPlugin.d.ts +4 -0
  98. package/dist/components/text-editor/plugins/LoadContentPlugin.js +63 -0
  99. package/dist/components/text-editor/plugins/MarkdownExportPlugin.d.ts +4 -0
  100. package/dist/components/text-editor/plugins/MarkdownExportPlugin.js +17 -0
  101. package/dist/components/text-editor/plugins/MarkdownPastePlugin.d.ts +2 -0
  102. package/dist/components/text-editor/plugins/MarkdownPastePlugin.js +45 -0
  103. package/dist/components/text-editor/plugins/SanitizePastePlugin.d.ts +3 -0
  104. package/dist/components/text-editor/plugins/SanitizePastePlugin.js +40 -0
  105. package/dist/components/text-editor/plugins/TextAlignPlugin.d.ts +7 -0
  106. package/dist/components/text-editor/plugins/TextAlignPlugin.js +65 -0
  107. package/dist/components/text-editor/plugins/TextColorPlugin.d.ts +7 -0
  108. package/dist/components/text-editor/plugins/TextColorPlugin.js +117 -0
  109. package/dist/components/text-editor/plugins/ToolbarPlugin.d.ts +10 -0
  110. package/dist/components/text-editor/plugins/ToolbarPlugin.js +73 -0
  111. package/dist/components/text-editor/theme-colors.d.ts +11 -0
  112. package/dist/components/text-editor/theme-colors.js +28 -0
  113. package/dist/context/WrAppContext.d.ts +35 -0
  114. package/dist/context/WrAppContext.js +113 -0
  115. package/dist/context/WrLayout.d.ts +15 -0
  116. package/dist/context/WrLayout.js +22 -0
  117. package/dist/context/WrPageContext.d.ts +28 -0
  118. package/dist/context/WrPageContext.js +282 -0
  119. package/dist/context/restoreValues.d.ts +2 -0
  120. package/dist/context/restoreValues.js +6 -0
  121. package/dist/contrast.d.ts +45 -0
  122. package/dist/contrast.js +122 -0
  123. package/dist/drop.d.ts +7 -0
  124. package/dist/drop.js +51 -0
  125. package/dist/gaps.d.ts +14 -0
  126. package/dist/gaps.js +50 -0
  127. package/dist/hooks/useWrMessage.d.ts +5 -0
  128. package/dist/hooks/useWrMessage.js +24 -0
  129. package/dist/hooks/useWrSave.d.ts +2 -0
  130. package/dist/hooks/useWrSave.js +11 -0
  131. package/dist/index.css +467 -0
  132. package/dist/index.d.ts +20 -0
  133. package/dist/index.js +20 -0
  134. package/dist/interactive.d.ts +8 -0
  135. package/dist/interactive.js +13 -0
  136. package/dist/measure-rules.d.ts +34 -0
  137. package/dist/measure-rules.js +54 -0
  138. package/dist/measure.d.ts +11 -0
  139. package/dist/measure.js +139 -0
  140. package/dist/messages.d.ts +860 -0
  141. package/dist/messages.js +2 -0
  142. package/dist/nav.d.ts +5 -0
  143. package/dist/nav.js +10 -0
  144. package/dist/operations/animations-store.d.ts +6 -0
  145. package/dist/operations/animations-store.js +63 -0
  146. package/dist/operations/cli.d.ts +3 -0
  147. package/dist/operations/cli.js +52 -0
  148. package/dist/operations/comments-store.d.ts +17 -0
  149. package/dist/operations/comments-store.js +62 -0
  150. package/dist/operations/context.d.ts +12 -0
  151. package/dist/operations/context.js +35 -0
  152. package/dist/operations/define.d.ts +81 -0
  153. package/dist/operations/define.js +86 -0
  154. package/dist/operations/index.d.ts +6 -0
  155. package/dist/operations/index.js +6 -0
  156. package/dist/operations/ops/check.d.ts +5 -0
  157. package/dist/operations/ops/check.js +53 -0
  158. package/dist/operations/ops/comments.d.ts +6 -0
  159. package/dist/operations/ops/comments.js +133 -0
  160. package/dist/operations/ops/content.d.ts +16 -0
  161. package/dist/operations/ops/content.js +73 -0
  162. package/dist/operations/ops/json.d.ts +4 -0
  163. package/dist/operations/ops/json.js +27 -0
  164. package/dist/operations/ops/langs.d.ts +4 -0
  165. package/dist/operations/ops/langs.js +32 -0
  166. package/dist/operations/ops/nodes.d.ts +8 -0
  167. package/dist/operations/ops/nodes.js +270 -0
  168. package/dist/operations/ops/pages.d.ts +8 -0
  169. package/dist/operations/ops/pages.js +154 -0
  170. package/dist/operations/ops/project.d.ts +36 -0
  171. package/dist/operations/ops/project.js +97 -0
  172. package/dist/operations/ops/seo.d.ts +17 -0
  173. package/dist/operations/ops/seo.js +358 -0
  174. package/dist/operations/ops/style.d.ts +76 -0
  175. package/dist/operations/ops/style.js +268 -0
  176. package/dist/operations/ops/stylesets.d.ts +9 -0
  177. package/dist/operations/ops/stylesets.js +145 -0
  178. package/dist/operations/ops/theme.d.ts +6 -0
  179. package/dist/operations/ops/theme.js +304 -0
  180. package/dist/operations/registry.d.ts +8 -0
  181. package/dist/operations/registry.js +19 -0
  182. package/dist/operations/stylesets-store.d.ts +50 -0
  183. package/dist/operations/stylesets-store.js +216 -0
  184. package/dist/registry.d.ts +5 -0
  185. package/dist/registry.js +24 -0
  186. package/dist/save.d.ts +65 -0
  187. package/dist/save.js +86 -0
  188. package/dist/schema.d.ts +69 -0
  189. package/dist/schema.js +110 -0
  190. package/dist/scope.d.ts +41 -0
  191. package/dist/scope.js +44 -0
  192. package/dist/vite-plugins/ast.d.ts +3 -0
  193. package/dist/vite-plugins/ast.js +238 -0
  194. package/dist/vite-plugins/core-swap.d.ts +3 -0
  195. package/dist/vite-plugins/core-swap.js +57 -0
  196. package/dist/vite-plugins/create-page.d.ts +4 -0
  197. package/dist/vite-plugins/create-page.js +59 -0
  198. package/dist/vite-plugins/guard.d.ts +15 -0
  199. package/dist/vite-plugins/guard.js +35 -0
  200. package/dist/vite-plugins/head.d.ts +13 -0
  201. package/dist/vite-plugins/head.js +53 -0
  202. package/dist/vite-plugins/index.d.ts +7 -0
  203. package/dist/vite-plugins/index.js +7 -0
  204. package/dist/vite-plugins/jsx-tree.d.ts +118 -0
  205. package/dist/vite-plugins/jsx-tree.js +686 -0
  206. package/dist/vite-plugins/langs.d.ts +3 -0
  207. package/dist/vite-plugins/langs.js +44 -0
  208. package/dist/vite-plugins/operations.d.ts +10 -0
  209. package/dist/vite-plugins/operations.js +66 -0
  210. package/dist/vite-plugins/pages-api.d.ts +3 -0
  211. package/dist/vite-plugins/pages-api.js +112 -0
  212. package/dist/vite-plugins/pages.d.ts +3 -0
  213. package/dist/vite-plugins/pages.js +64 -0
  214. package/dist/vite-plugins/read.d.ts +3 -0
  215. package/dist/vite-plugins/read.js +45 -0
  216. package/dist/vite-plugins/seo-files.d.ts +8 -0
  217. package/dist/vite-plugins/seo-files.js +42 -0
  218. package/dist/vite-plugins/theme.d.ts +3 -0
  219. package/dist/vite-plugins/theme.js +207 -0
  220. package/dist/vite-plugins/update.d.ts +3 -0
  221. package/dist/vite-plugins/update.js +46 -0
  222. package/dist/vite-plugins/wr-plugins.d.ts +15 -0
  223. package/dist/vite-plugins/wr-plugins.js +34 -0
  224. package/dist/vite-plugins.d.ts +11 -0
  225. package/dist/vite-plugins.js +518 -0
  226. package/package.json +96 -5
  227. package/README.md +0 -3
@@ -0,0 +1,284 @@
1
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
2
+ import { $getRoot, $createParagraphNode, $createTextNode, $isParagraphNode, $getSelection, $isRangeSelection, } from "lexical";
3
+ import { $createHeadingNode, $isHeadingNode } from "@lexical/rich-text";
4
+ import { $createLinkNode, $isLinkNode } from "@lexical/link";
5
+ import { $createListNode, $createListItemNode, $isListNode, $isListItemNode, } from "@lexical/list";
6
+ import { $createHorizontalRuleNode, $isHorizontalRuleNode } from "../nodes/HorizontalRuleNode";
7
+ import { $createCodeBlockNode, $isCodeBlockNode } from "../nodes/CodeBlockNode";
8
+ // Lexical format bitmask constants
9
+ const IS_BOLD = 1;
10
+ const IS_ITALIC = 2;
11
+ const IS_STRIKETHROUGH = 4;
12
+ const IS_UNDERLINE = 8;
13
+ const IS_CODE = 16;
14
+ // ─── Style helpers ────────────────────────────────────────────────────────────
15
+ function buildStyleVar(id) {
16
+ return [
17
+ `font-family: var(--text-style-${id}-font-family)`,
18
+ `font-size: var(--text-style-${id}-font-size)`,
19
+ `color: var(--text-style-${id}-text-color)`,
20
+ ].join("; ") + ";";
21
+ }
22
+ // ─── Inline regex ─────────────────────────────────────────────────────────────
23
+ // Order matters: ** before *, <u> before nothing
24
+ const INLINE_RE = /\*\*(.+?)\*\*|\[(.+?)\]\((.+?)\)|\*(.+?)\*|`(.+?)`|~~(.+?)~~|<u>(.+?)<\/u>/g;
25
+ export function tokenizeInline(raw) {
26
+ const tokens = [];
27
+ let last = 0;
28
+ const re = /\*\*(.+?)\*\*|\[(.+?)\]\((.+?)\)|\*(.+?)\*|`(.+?)`|~~(.+?)~~|<u>(.+?)<\/u>/g;
29
+ let m;
30
+ while ((m = re.exec(raw)) !== null) {
31
+ if (m.index > last) {
32
+ tokens.push({ kind: "text", text: raw.slice(last, m.index) });
33
+ }
34
+ if (m[1] !== undefined) {
35
+ const inner = tokenizeInline(m[1]);
36
+ inner.forEach(t => {
37
+ if (t.kind === "text")
38
+ tokens.push({ kind: "bold", text: t.text });
39
+ else
40
+ tokens.push(t);
41
+ });
42
+ }
43
+ else if (m[2] !== undefined) {
44
+ tokens.push({ kind: "link", text: m[2], url: m[3] });
45
+ }
46
+ else if (m[4] !== undefined) {
47
+ const inner = tokenizeInline(m[4]);
48
+ inner.forEach(t => {
49
+ if (t.kind === "text")
50
+ tokens.push({ kind: "italic", text: t.text });
51
+ else
52
+ tokens.push(t);
53
+ });
54
+ }
55
+ else if (m[5] !== undefined) {
56
+ tokens.push({ kind: "code", text: m[5] });
57
+ }
58
+ else if (m[6] !== undefined) {
59
+ tokens.push({ kind: "strike", text: m[6] });
60
+ }
61
+ else if (m[7] !== undefined) {
62
+ tokens.push({ kind: "under", text: m[7] });
63
+ }
64
+ last = re.lastIndex;
65
+ }
66
+ if (last < raw.length) {
67
+ tokens.push({ kind: "text", text: raw.slice(last) });
68
+ }
69
+ return tokens;
70
+ }
71
+ // ─── Lexical node builder from tokens ─────────────────────────────────────────
72
+ export function buildNodes(tokens, style) {
73
+ return tokens.map((tok) => {
74
+ if (tok.kind === "link") {
75
+ const linkNode = $createLinkNode(tok.url);
76
+ const t = $createTextNode(tok.text);
77
+ t.setStyle(style);
78
+ linkNode.append(t);
79
+ return linkNode; // ElementNode acceptable in append()
80
+ }
81
+ const t = $createTextNode(tok.text);
82
+ t.setStyle(style);
83
+ switch (tok.kind) {
84
+ case "bold":
85
+ t.setStyle(t.getStyle() + "; font-weight: 700");
86
+ break;
87
+ case "italic":
88
+ t.setFormat(IS_ITALIC);
89
+ break;
90
+ case "code":
91
+ t.setFormat(IS_CODE);
92
+ break;
93
+ case "strike":
94
+ t.setFormat(IS_STRIKETHROUGH);
95
+ break;
96
+ case "under":
97
+ t.setFormat(IS_UNDERLINE);
98
+ break;
99
+ }
100
+ return t;
101
+ });
102
+ }
103
+ // ─── Lexical → Markdown ───────────────────────────────────────────────────────
104
+ function nodeToMd(node) {
105
+ const type = node.getType();
106
+ if ($isCodeBlockNode(node)) {
107
+ return `\`\`\`${node.__language}\n${node.__code}\n\`\`\``;
108
+ }
109
+ if ($isHorizontalRuleNode(node))
110
+ return "---";
111
+ if (type === "text") {
112
+ let text = node.getTextContent();
113
+ const fmt = node.getFormat();
114
+ const style = node.getStyle() ?? "";
115
+ // bold → font-weight nello style inline, NON nel format flag
116
+ const weightMatch = style.match(/font-weight:\s*(\d+)/i);
117
+ const isBold = weightMatch ? parseInt(weightMatch[1]) >= 700 : false;
118
+ if (fmt & IS_CODE)
119
+ text = `\`${text}\``;
120
+ if (fmt & IS_STRIKETHROUGH)
121
+ text = `~~${text}~~`;
122
+ if (fmt & IS_UNDERLINE)
123
+ text = `<u>${text}</u>`;
124
+ if (fmt & IS_ITALIC)
125
+ text = `*${text}*`;
126
+ if (isBold)
127
+ text = `**${text}**`;
128
+ return text;
129
+ }
130
+ if ($isLinkNode(node)) {
131
+ const url = node.getURL();
132
+ const children = node.getChildren().map(nodeToMd).join("");
133
+ return `[${children}](${url})`;
134
+ }
135
+ if ($isHeadingNode(node)) {
136
+ const tag = node.getTag();
137
+ const hashes = "#".repeat(parseInt(tag[1]));
138
+ const children = node.getChildren().map(nodeToMd).join("");
139
+ return `${hashes} ${children}`;
140
+ }
141
+ if ($isParagraphNode(node)) {
142
+ return node.getChildren().map(nodeToMd).join("");
143
+ }
144
+ if ($isListNode(node)) {
145
+ const listType = node.getListType();
146
+ return node.getChildren().map((item, idx) => {
147
+ const prefix = listType === "number" ? `${idx + 1}. ` : "- ";
148
+ const content = $isListItemNode(item)
149
+ ? item.getChildren().map(nodeToMd).join("")
150
+ : nodeToMd(item);
151
+ return prefix + content;
152
+ }).join("\n");
153
+ }
154
+ // fallback: plain text
155
+ return node.getTextContent?.() ?? "";
156
+ }
157
+ // ─── Hook ─────────────────────────────────────────────────────────────────────
158
+ export function useLexicalMarkdown() {
159
+ const [editor] = useLexicalComposerContext();
160
+ /** Returns the CSS-var style string for a given HTML tag (h1-h6 or p/default). */
161
+ const styleForTag = (tag) => {
162
+ return "";
163
+ };
164
+ const defaultStyle = () => styleForTag("p");
165
+ // ── toMarkdown ─────────────────────────────────────────────────────────
166
+ const toMarkdown = () => {
167
+ let md = "";
168
+ editor.getEditorState().read(() => {
169
+ const root = $getRoot();
170
+ md = root.getChildren().map(nodeToMd).join("\n\n");
171
+ });
172
+ return md;
173
+ };
174
+ // ── fromMarkdown ───────────────────────────────────────────────────────
175
+ const fromMarkdown = (md) => {
176
+ editor.update(() => {
177
+ const nodes = [];
178
+ let currentList = null;
179
+ let currentListType = null;
180
+ const flushList = () => {
181
+ if (currentList) {
182
+ nodes.push(currentList);
183
+ currentList = null;
184
+ currentListType = null;
185
+ }
186
+ };
187
+ const lines = md.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
188
+ let i = 0;
189
+ while (i < lines.length) {
190
+ const line = lines[i];
191
+ if (line.trim() === "") {
192
+ flushList();
193
+ i++;
194
+ continue;
195
+ }
196
+ if (line.trim() === "---") {
197
+ flushList();
198
+ nodes.push($createHorizontalRuleNode());
199
+ i++;
200
+ continue;
201
+ }
202
+ const fenceMatch = line.match(/^```(\w*)$/);
203
+ if (fenceMatch) {
204
+ flushList();
205
+ const language = fenceMatch[1] ?? "";
206
+ const codeLines = [];
207
+ i++;
208
+ while (i < lines.length && lines[i] !== "```") {
209
+ codeLines.push(lines[i]);
210
+ i++;
211
+ }
212
+ i++;
213
+ nodes.push($createCodeBlockNode(codeLines.join("\n"), language));
214
+ continue;
215
+ }
216
+ const hMatch = line.match(/^(#{1,6}) (.+)$/);
217
+ if (hMatch) {
218
+ flushList();
219
+ const tag = `h${hMatch[1].length}`;
220
+ const style = styleForTag(tag);
221
+ const heading = $createHeadingNode(tag);
222
+ heading.setDirection("ltr");
223
+ buildNodes(tokenizeInline(hMatch[2]), style).forEach((n) => heading.append(n));
224
+ nodes.push(heading);
225
+ i++;
226
+ continue;
227
+ }
228
+ const ulMatch = line.match(/^[-*] (.+)$/);
229
+ if (ulMatch) {
230
+ if (currentListType !== "bullet") {
231
+ flushList();
232
+ currentList = $createListNode("bullet");
233
+ currentListType = "bullet";
234
+ }
235
+ const item = $createListItemNode();
236
+ buildNodes(tokenizeInline(ulMatch[1]), defaultStyle()).forEach((n) => item.append(n));
237
+ currentList.append(item);
238
+ i++;
239
+ continue;
240
+ }
241
+ const olMatch = line.match(/^\d+\. (.+)$/);
242
+ if (olMatch) {
243
+ if (currentListType !== "number") {
244
+ flushList();
245
+ currentList = $createListNode("number");
246
+ currentListType = "number";
247
+ }
248
+ const item = $createListItemNode();
249
+ buildNodes(tokenizeInline(olMatch[1]), defaultStyle()).forEach((n) => item.append(n));
250
+ currentList.append(item);
251
+ i++;
252
+ continue;
253
+ }
254
+ flushList();
255
+ const para = $createParagraphNode();
256
+ para.setDirection("ltr");
257
+ buildNodes(tokenizeInline(line), defaultStyle()).forEach((n) => para.append(n));
258
+ nodes.push(para);
259
+ i++;
260
+ }
261
+ flushList();
262
+ const selection = $getSelection();
263
+ if ($isRangeSelection(selection)) {
264
+ // prima cancella la selezione se c'è testo selezionato
265
+ if (!selection.isCollapsed()) {
266
+ selection.deleteCharacter(false);
267
+ }
268
+ const anchorNode = selection.anchor.getNode();
269
+ const topLevel = anchorNode.getTopLevelElementOrThrow();
270
+ nodes.reverse().forEach(n => topLevel.insertAfter(n));
271
+ // rimuovi il nodo corrente se è vuoto
272
+ if (topLevel.getTextContent().trim() === "") {
273
+ topLevel.remove();
274
+ }
275
+ }
276
+ else {
277
+ const root = $getRoot();
278
+ nodes.forEach(n => root.append(n));
279
+ }
280
+ });
281
+ };
282
+ return { toMarkdown, fromMarkdown };
283
+ }
284
+ //# sourceMappingURL=useLexicalMarkdown.js.map
@@ -0,0 +1,23 @@
1
+ import { DecoratorNode, LexicalNode, SerializedLexicalNode, Spread } from "lexical";
2
+ import { JSX } from "react";
3
+ type SerializedCodeBlockNode = Spread<{
4
+ code: string;
5
+ language: string;
6
+ }, SerializedLexicalNode>;
7
+ export declare class CodeBlockNode extends DecoratorNode<JSX.Element> {
8
+ __code: string;
9
+ __language: string;
10
+ static getType(): string;
11
+ static clone(node: CodeBlockNode): CodeBlockNode;
12
+ constructor(code: string, language?: string, key?: string);
13
+ createDOM(): HTMLElement;
14
+ updateDOM(): false;
15
+ isInline(): false;
16
+ decorate(): JSX.Element;
17
+ static importJSON(node: SerializedCodeBlockNode): CodeBlockNode;
18
+ exportJSON(): SerializedCodeBlockNode;
19
+ }
20
+ export declare function $createCodeBlockNode(code: string, language?: string): CodeBlockNode;
21
+ export declare function $isCodeBlockNode(node: LexicalNode | null | undefined): node is CodeBlockNode;
22
+ export {};
23
+ //# sourceMappingURL=CodeBlockNode.d.ts.map
@@ -0,0 +1,138 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { DecoratorNode, $getNodeByKey } from "lexical";
3
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
4
+ import { useEffect, useRef, useState } from "react";
5
+ import hljs from "highlight.js";
6
+ import MonacoEditor from "@monaco-editor/react";
7
+ import { useCodeTheme } from "../CodeThemeContext";
8
+ const setHljsTheme = (dark) => {
9
+ let link = document.getElementById("hljs-theme");
10
+ if (!link) {
11
+ link = document.createElement("link");
12
+ link.id = "hljs-theme";
13
+ link.rel = "stylesheet";
14
+ document.head.appendChild(link);
15
+ }
16
+ link.href = dark
17
+ ? new URL("highlight.js/styles/github-dark.css", import.meta.url).href
18
+ : new URL("highlight.js/styles/github.css", import.meta.url).href;
19
+ };
20
+ const LANGUAGE_MAP = {
21
+ ts: "typescript", tsx: "typescript",
22
+ js: "javascript", jsx: "javascript",
23
+ py: "python", rb: "ruby",
24
+ sh: "shell", bash: "shell",
25
+ yml: "yaml", md: "markdown",
26
+ };
27
+ const resolveLanguage = (lang) => LANGUAGE_MAP[lang.toLowerCase()] ?? lang.toLowerCase();
28
+ function CodeBlockComponent({ code, language, nodeKey }) {
29
+ const [editor] = useLexicalComposerContext();
30
+ const { theme, toggle } = useCodeTheme();
31
+ const isDark = theme === "vs-dark";
32
+ const [copied, setCopied] = useState(false);
33
+ const [isEditing, setIsEditing] = useState(false);
34
+ const [localCode, setLocalCode] = useState(code);
35
+ const [height, setHeight] = useState(100);
36
+ const codeRef = useRef(null);
37
+ const containerRef = useRef(null);
38
+ useEffect(() => {
39
+ setHljsTheme(isDark);
40
+ }, [isDark]);
41
+ useEffect(() => {
42
+ if (isEditing)
43
+ return;
44
+ if (!codeRef.current)
45
+ return;
46
+ codeRef.current.textContent = localCode;
47
+ hljs.highlightElement(codeRef.current);
48
+ }, [localCode, isDark, isEditing]);
49
+ const onChange = (value) => {
50
+ const next = value ?? "";
51
+ setLocalCode(next);
52
+ editor.update(() => {
53
+ const node = $getNodeByKey(nodeKey);
54
+ if ($isCodeBlockNode(node)) {
55
+ node.getWritable().__code = next;
56
+ }
57
+ });
58
+ };
59
+ const onMount = (monacoEditor) => {
60
+ const updateHeight = () => setHeight(Math.max(100, monacoEditor.getContentHeight()));
61
+ monacoEditor.onDidContentSizeChange(updateHeight);
62
+ updateHeight();
63
+ };
64
+ const handleCopy = async () => {
65
+ await navigator.clipboard.writeText(localCode);
66
+ setCopied(true);
67
+ setTimeout(() => setCopied(false), 1500);
68
+ };
69
+ useEffect(() => {
70
+ if (!isEditing)
71
+ return;
72
+ const handleClickOutside = (e) => {
73
+ if (!containerRef.current?.contains(e.target)) {
74
+ setIsEditing(false);
75
+ }
76
+ };
77
+ document.addEventListener("mousedown", handleClickOutside);
78
+ return () => document.removeEventListener("mousedown", handleClickOutside);
79
+ }, [isEditing]);
80
+ return (_jsxs("div", { ref: containerRef, className: `relative my-2 rounded-lg overflow-hidden max-w-full text-sm ${isDark ? "bg-gray-900" : "bg-gray-100"}`, onKeyDown: e => e.stopPropagation(), onKeyUp: e => e.stopPropagation(), onCopy: e => e.stopPropagation(), onCut: e => e.stopPropagation(), onPaste: e => e.stopPropagation(), children: [_jsxs("div", { className: `flex items-center justify-between text-xs ${isDark ? "bg-gray-800 text-gray-400" : "bg-gray-200 text-gray-600"}`, children: [_jsx("span", { className: "p-2", children: language || "plaintext" }), _jsxs("div", { className: "flex items-center gap-3 p-2", children: [_jsx("button", { onClick: toggle, children: isDark ? "☀️" : "🌙" }), _jsx("button", { onClick: handleCopy, className: `transition-colors ${isDark ? "hover:text-white" : "hover:text-black"}`, children: copied ? "✓" : "Copy" })] })] }), isEditing ? (_jsx(MonacoEditor, { width: "100%", height: height, language: resolveLanguage(language), value: localCode, onChange: onChange, onMount: onMount, theme: theme, options: {
81
+ minimap: { enabled: false },
82
+ scrollBeyondLastLine: false,
83
+ fontSize: 14,
84
+ lineHeight: 20,
85
+ lineNumbers: "off",
86
+ folding: false,
87
+ padding: { top: 28, bottom: 28 },
88
+ automaticLayout: true,
89
+ scrollbar: { vertical: "hidden", handleMouseWheel: false },
90
+ glyphMargin: false,
91
+ lineDecorationsWidth: 16,
92
+ lineNumbersMinChars: 0,
93
+ } })) : (_jsx("pre", { className: `m-0 pl-0 pt-4 pb-4 pr-4 overflow-x-auto cursor-text font-mono text-sm leading-5 max-w-full ${isDark ? "bg-gray-900" : "bg-gray-100"}`, onClick: () => setIsEditing(true), children: _jsx("code", { ref: codeRef, className: language ? `language-${language}` : "" }) }))] }));
94
+ }
95
+ export class CodeBlockNode extends DecoratorNode {
96
+ __code;
97
+ __language;
98
+ static getType() { return "code-block"; }
99
+ static clone(node) {
100
+ return new CodeBlockNode(node.__code, node.__language, node.__key);
101
+ }
102
+ constructor(code, language = "", key) {
103
+ super(key);
104
+ this.__code = code;
105
+ this.__language = language;
106
+ }
107
+ createDOM() {
108
+ const div = document.createElement("div");
109
+ div.contentEditable = "false";
110
+ div.style.width = "0";
111
+ div.style.minWidth = "100%";
112
+ return div;
113
+ }
114
+ updateDOM() { return false; }
115
+ isInline() { return false; }
116
+ decorate() {
117
+ return (_jsx(CodeBlockComponent, { code: this.__code, language: this.__language, nodeKey: this.__key }));
118
+ }
119
+ static importJSON(node) {
120
+ return $createCodeBlockNode(node.code, node.language);
121
+ }
122
+ exportJSON() {
123
+ return {
124
+ ...super.exportJSON(),
125
+ type: "code-block",
126
+ version: 1,
127
+ code: this.__code,
128
+ language: this.__language,
129
+ };
130
+ }
131
+ }
132
+ export function $createCodeBlockNode(code, language = "") {
133
+ return new CodeBlockNode(code, language);
134
+ }
135
+ export function $isCodeBlockNode(node) {
136
+ return node?.getType() === "code-block";
137
+ }
138
+ //# sourceMappingURL=CodeBlockNode.js.map
@@ -0,0 +1,13 @@
1
+ import { DecoratorNode, LexicalNode } from "lexical";
2
+ import { JSX } from "react";
3
+ export declare class HorizontalRuleNode extends DecoratorNode<JSX.Element> {
4
+ static getType(): string;
5
+ static clone(node: HorizontalRuleNode): HorizontalRuleNode;
6
+ createDOM(): HTMLElement;
7
+ updateDOM(): false;
8
+ decorate(): JSX.Element;
9
+ isInline(): false;
10
+ }
11
+ export declare function $createHorizontalRuleNode(): HorizontalRuleNode;
12
+ export declare function $isHorizontalRuleNode(node: LexicalNode | null | undefined): node is HorizontalRuleNode;
13
+ //# sourceMappingURL=HorizontalRuleNode.d.ts.map
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // nodes/HorizontalRuleNode.tsx
3
+ import { DecoratorNode } from "lexical";
4
+ export class HorizontalRuleNode extends DecoratorNode {
5
+ static getType() { return "horizontal-rule"; }
6
+ static clone(node) {
7
+ return new HorizontalRuleNode(node.__key);
8
+ }
9
+ createDOM() {
10
+ return document.createElement("hr");
11
+ }
12
+ updateDOM() { return false; }
13
+ decorate() { return _jsx("hr", {}); }
14
+ isInline() { return false; }
15
+ }
16
+ export function $createHorizontalRuleNode() {
17
+ return new HorizontalRuleNode();
18
+ }
19
+ export function $isHorizontalRuleNode(node) {
20
+ return node?.getType() === "horizontal-rule";
21
+ }
22
+ //# sourceMappingURL=HorizontalRuleNode.js.map
@@ -0,0 +1,2 @@
1
+ export default function CodeBlockPlugin(): null;
2
+ //# sourceMappingURL=CodeBlockPlugin.d.ts.map
@@ -0,0 +1,38 @@
1
+ import { useEffect } from "react";
2
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
3
+ import { $getSelection, $isRangeSelection, $isParagraphNode, $createParagraphNode, $createRangeSelection, $setSelection, KEY_ENTER_COMMAND, COMMAND_PRIORITY_LOW, } from "lexical";
4
+ import { $createCodeBlockNode } from "../nodes/CodeBlockNode";
5
+ export default function CodeBlockPlugin() {
6
+ const [editor] = useLexicalComposerContext();
7
+ useEffect(() => {
8
+ return editor.registerCommand(KEY_ENTER_COMMAND, (event) => {
9
+ const selection = $getSelection();
10
+ if (!$isRangeSelection(selection))
11
+ return false;
12
+ const anchor = selection.anchor.getNode();
13
+ const parent = anchor.getParent();
14
+ if (!$isParagraphNode(parent))
15
+ return false;
16
+ if (parent.getChildrenSize() !== 1)
17
+ return false;
18
+ const text = anchor.getTextContent().trim();
19
+ const match = text.match(/^```(\w*)$/);
20
+ if (!match)
21
+ return false;
22
+ event?.preventDefault();
23
+ const language = match[1] || "";
24
+ const codeBlock = $createCodeBlockNode("", language);
25
+ const para = $createParagraphNode();
26
+ parent.replace(codeBlock);
27
+ codeBlock.insertAfter(para);
28
+ const sel = $createRangeSelection();
29
+ const key = para.getKey();
30
+ sel.anchor.set(key, 0, "element");
31
+ sel.focus.set(key, 0, "element");
32
+ $setSelection(sel);
33
+ return true;
34
+ }, COMMAND_PRIORITY_LOW);
35
+ }, [editor]);
36
+ return null;
37
+ }
38
+ //# sourceMappingURL=CodeBlockPlugin.js.map
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ interface TextStyle {
3
+ fontFamily?: string;
4
+ }
5
+ interface Props {
6
+ editorPathKey?: string;
7
+ fonts?: string[];
8
+ textStyles?: TextStyle[];
9
+ }
10
+ declare function FontPlugin({ editorPathKey, fonts, textStyles, }: Props): React.JSX.Element;
11
+ export default FontPlugin;
12
+ //# sourceMappingURL=FontPlugin.d.ts.map
@@ -0,0 +1,114 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useRef, useEffect, useState, useCallback } from 'react';
3
+ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
4
+ import { $getSelection, $isRangeSelection } from 'lexical';
5
+ import { $patchStyleText } from '@lexical/selection';
6
+ import { PiTextT } from 'react-icons/pi';
7
+ import { createPortal } from 'react-dom';
8
+ import { wrGetTheme } from '../../../save';
9
+ import { WR_SURFACE_STYLE } from '../common/surface';
10
+ const DEFAULT_FONTS = [
11
+ 'Manrope'
12
+ ];
13
+ function themeFontNames(items) {
14
+ return items
15
+ .filter((i) => i.kind === 'google-font' || i.kind === 'custom-font')
16
+ .map(i => i.key);
17
+ }
18
+ function FontPlugin({ editorPathKey = '', fonts = DEFAULT_FONTS, textStyles = [], }) {
19
+ const [editor] = useLexicalComposerContext();
20
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
21
+ const [selectedFont, setSelectedFont] = useState(fonts[0]);
22
+ const [menuPosition, setMenuPosition] = useState({ top: 0, left: 0 });
23
+ const [themeFonts, setThemeFonts] = useState([]);
24
+ const buttonRef = useRef(null);
25
+ const menuRef = useRef(null);
26
+ const refreshThemeFonts = useCallback(() => {
27
+ wrGetTheme()
28
+ .then(({ items }) => setThemeFonts(themeFontNames(items)))
29
+ .catch(() => setThemeFonts([]));
30
+ }, []);
31
+ useEffect(() => { refreshThemeFonts(); }, [refreshThemeFonts]);
32
+ const allFonts = [...fonts, ...themeFonts.filter(f => !fonts.includes(f))];
33
+ const toggleMenu = (e) => {
34
+ e.stopPropagation();
35
+ setIsMenuOpen(prev => !prev);
36
+ };
37
+ const applyFont = (font) => {
38
+ editor.update(() => {
39
+ const selection = $getSelection();
40
+ if ($isRangeSelection(selection)) {
41
+ $patchStyleText(selection, { 'font-family': font });
42
+ }
43
+ });
44
+ setSelectedFont(font);
45
+ setIsMenuOpen(false);
46
+ };
47
+ const calculateMenuPosition = () => {
48
+ if (buttonRef.current && menuRef.current) {
49
+ const buttonRect = buttonRef.current.getBoundingClientRect();
50
+ const menuRect = menuRef.current.getBoundingClientRect();
51
+ let top = buttonRect.bottom;
52
+ let left = buttonRect.left;
53
+ const pageWidth = document.body.clientWidth;
54
+ if (left + menuRect.width > pageWidth)
55
+ left = pageWidth - menuRect.width - 10;
56
+ if (left < 0)
57
+ left = 10;
58
+ setMenuPosition({ top, left });
59
+ }
60
+ };
61
+ useEffect(() => {
62
+ const handleClickOutside = (e) => {
63
+ if (menuRef.current && !menuRef.current.contains(e.target) && !buttonRef.current?.contains(e.target)) {
64
+ setIsMenuOpen(false);
65
+ }
66
+ };
67
+ if (isMenuOpen) {
68
+ document.addEventListener('click', handleClickOutside);
69
+ calculateMenuPosition();
70
+ }
71
+ return () => document.removeEventListener('click', handleClickOutside);
72
+ }, [isMenuOpen]);
73
+ useEffect(() => {
74
+ return editor.registerUpdateListener(() => {
75
+ editor.getEditorState().read(() => {
76
+ const selection = $getSelection();
77
+ if (!$isRangeSelection(selection))
78
+ return;
79
+ const anchorNode = selection.anchor.getNode();
80
+ if (!anchorNode)
81
+ return;
82
+ let fontFamily = selectedFont;
83
+ const styleString = anchorNode.getStyle?.();
84
+ if (styleString && typeof styleString === 'string') {
85
+ const match = styleString.match(/font-family:\s*['"]?([^;'"]+)['"]?/i);
86
+ if (match)
87
+ fontFamily = match[1].trim();
88
+ }
89
+ if (fontFamily.startsWith('var(')) {
90
+ const match = fontFamily.match(/--text-style-(\d+)-font-family/);
91
+ if (match) {
92
+ const style = textStyles[parseInt(match[1], 10)];
93
+ if (style?.fontFamily)
94
+ fontFamily = style.fontFamily;
95
+ }
96
+ }
97
+ setSelectedFont(fontFamily);
98
+ });
99
+ });
100
+ }, [editor, textStyles]);
101
+ return (_jsxs("div", { className: `path-${editorPathKey} toolbarClass`, style: { position: 'relative', display: 'inline-block', textAlign: 'left' }, onClick: e => e.stopPropagation(), children: [_jsxs("button", { ref: buttonRef, type: "button", onClick: toggleMenu, "aria-expanded": isMenuOpen, className: "wr-toolbar-trigger", children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: 8 }, children: [_jsx(PiTextT, { style: { fontSize: 18 } }), _jsx("span", { style: { fontFamily: selectedFont }, children: selectedFont })] }), _jsx("svg", { className: `wr-toolbar-chevron ${isMenuOpen ? 'wr-toolbar-chevron--open' : ''}`, xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", children: _jsx("path", { fillRule: "evenodd", d: "M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z", clipRule: "evenodd" }) })] }), isMenuOpen && createPortal(_jsx("div", { ref: menuRef, className: `toolbarClass path-${editorPathKey} wr-toolbar-menu`, style: { ...WR_SURFACE_STYLE, top: menuPosition.top, left: menuPosition.left, width: 288 }, children: _jsx("div", { style: { padding: '4px 0' }, children: allFonts.map(font => (_jsx("div", { className: "wr-toolbar-item", style: { display: 'flex', alignItems: 'center', padding: 0 }, children: _jsx("button", { onClick: () => applyFont(font), style: {
102
+ fontFamily: font,
103
+ display: 'block',
104
+ padding: '8px 16px',
105
+ fontSize: 14,
106
+ width: '100%',
107
+ textAlign: 'left',
108
+ background: 'transparent',
109
+ border: 'none',
110
+ cursor: 'pointer',
111
+ }, children: font }) }, font))) }) }), document.body)] }));
112
+ }
113
+ export default FontPlugin;
114
+ //# sourceMappingURL=FontPlugin.js.map
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ interface Props {
3
+ editorPathKey?: string;
4
+ }
5
+ declare function FontSizePlugin({ editorPathKey }: Props): React.JSX.Element;
6
+ export default FontSizePlugin;
7
+ //# sourceMappingURL=FontSizePlugin.d.ts.map