@upstart.gg/vite-plugins 0.1.60 → 0.1.62
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/dist/page-meta.js +533 -0
- package/dist/page-meta.js.map +1 -0
- package/dist/site-meta.d.ts +28 -0
- package/dist/site-meta.d.ts.map +1 -0
- package/dist/site-meta.js +207 -0
- package/dist/site-meta.js.map +1 -0
- package/dist/upstart-editor-api.d.ts +135 -1
- package/dist/upstart-editor-api.d.ts.map +1 -1
- package/dist/upstart-editor-api.js +756 -1
- package/dist/upstart-editor-api.js.map +1 -1
- package/dist/vite-plugin-upstart-attrs.d.ts.map +1 -1
- package/dist/vite-plugin-upstart-attrs.js +130 -10
- package/dist/vite-plugin-upstart-attrs.js.map +1 -1
- package/dist/vite-plugin-upstart-editor/runtime/index.d.ts.map +1 -1
- package/dist/vite-plugin-upstart-editor/runtime/index.js +35 -0
- package/dist/vite-plugin-upstart-editor/runtime/index.js.map +1 -1
- package/dist/vite-plugin-upstart-editor/runtime/text-editor.d.ts.map +1 -1
- package/dist/vite-plugin-upstart-editor/runtime/text-editor.js +139 -14
- package/dist/vite-plugin-upstart-editor/runtime/text-editor.js.map +1 -1
- package/dist/vite-plugin-upstart-editor/runtime/types.d.ts +3 -0
- package/dist/vite-plugin-upstart-editor/runtime/types.d.ts.map +1 -1
- package/package.json +8 -3
- package/src/page-meta.ts +678 -0
- package/src/site-meta.ts +226 -0
- package/src/tests/site-meta.test.ts +158 -0
- package/src/tests/upstart-editor-api-page-meta.test.ts +635 -0
- package/src/tests/vite-plugin-upstart-attrs.test.ts +224 -13
- package/src/upstart-editor-api.ts +941 -0
- package/src/vite-plugin-upstart-attrs.ts +253 -14
- package/src/vite-plugin-upstart-editor/runtime/index.ts +38 -0
- package/src/vite-plugin-upstart-editor/runtime/text-editor.ts +141 -14
- package/src/vite-plugin-upstart-editor/runtime/types.ts +2 -0
|
@@ -49,6 +49,39 @@ const TemplateVariable = Node.create({
|
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
/**
|
|
52
|
+
* An atomic inline node holding static text that surrounds an i18n node in the
|
|
53
|
+
* source (e.g. the " *" in `<label><Trans i18nKey="…" /> *</label>`).
|
|
54
|
+
* It stays visible and non-editable, and renderText() returns "" so getText()
|
|
55
|
+
* yields only the translation — the static part never leaks into the saved value.
|
|
56
|
+
*/
|
|
57
|
+
const StaticAffix = Node.create({
|
|
58
|
+
name: "staticAffix",
|
|
59
|
+
group: "inline",
|
|
60
|
+
inline: true,
|
|
61
|
+
atom: true,
|
|
62
|
+
selectable: false,
|
|
63
|
+
addAttributes() {
|
|
64
|
+
return { text: { default: "" } };
|
|
65
|
+
},
|
|
66
|
+
parseHTML() {
|
|
67
|
+
return [{ tag: "span[data-static-affix]" }];
|
|
68
|
+
},
|
|
69
|
+
renderHTML({ node }) {
|
|
70
|
+
return [
|
|
71
|
+
"span",
|
|
72
|
+
{
|
|
73
|
+
"data-static-affix": "",
|
|
74
|
+
contenteditable: "false",
|
|
75
|
+
style: "cursor:default;user-select:none;white-space:pre;"
|
|
76
|
+
},
|
|
77
|
+
node.attrs.text
|
|
78
|
+
];
|
|
79
|
+
},
|
|
80
|
+
renderText() {
|
|
81
|
+
return "";
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
/**
|
|
52
85
|
* Remaps Enter to insert a <br> (hard break) instead of creating a new paragraph.
|
|
53
86
|
* Used in inline-rich mode where block nodes are not allowed.
|
|
54
87
|
*/
|
|
@@ -82,6 +115,84 @@ const DEFAULT_OPTIONS = {
|
|
|
82
115
|
getRawI18nTemplate: () => void 0
|
|
83
116
|
};
|
|
84
117
|
/**
|
|
118
|
+
* Parse a `data-upstart-i18n` value into its namespace and key.
|
|
119
|
+
*
|
|
120
|
+
* The build-time plugin guarantees a single "namespace:key" per element (a ternary
|
|
121
|
+
* between two translations is emitted as a runtime-resolved expression), but a stale
|
|
122
|
+
* build may still carry a comma-separated list of keys. Such a value is unresolvable —
|
|
123
|
+
* we cannot tell which translation the edited text belongs to — so it is rejected
|
|
124
|
+
* instead of being saved to a mangled key.
|
|
125
|
+
*/
|
|
126
|
+
function parseI18nAttr(value) {
|
|
127
|
+
if (!value) return null;
|
|
128
|
+
if (value.includes(",")) {
|
|
129
|
+
console.warn("[Upstart Editor] Ambiguous i18n key, refusing to save:", value);
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
const colonIdx = value.indexOf(":");
|
|
133
|
+
return colonIdx >= 0 ? {
|
|
134
|
+
namespace: value.slice(0, colonIdx),
|
|
135
|
+
key: value.slice(colonIdx + 1)
|
|
136
|
+
} : {
|
|
137
|
+
namespace: "translation",
|
|
138
|
+
key: value
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Static text emitted by the build-time plugin around a single i18n node
|
|
143
|
+
* (`data-upstart-i18n-prefix` / `data-upstart-i18n-suffix`).
|
|
144
|
+
*/
|
|
145
|
+
function getAffixes(element) {
|
|
146
|
+
return {
|
|
147
|
+
prefix: element.dataset.upstartI18nPrefix ?? "",
|
|
148
|
+
suffix: element.dataset.upstartI18nSuffix ?? ""
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
/** Remove the static affixes from a rendered text to get the translation alone. */
|
|
152
|
+
function stripAffixes(element, text) {
|
|
153
|
+
const { prefix, suffix } = getAffixes(element);
|
|
154
|
+
let out = text;
|
|
155
|
+
if (prefix && out.startsWith(prefix)) out = out.slice(prefix.length);
|
|
156
|
+
if (suffix && out.endsWith(suffix)) out = out.slice(0, out.length - suffix.length);
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
/** Re-attach the static affixes to a translation for display purposes. */
|
|
160
|
+
function applyAffixes(element, text) {
|
|
161
|
+
const { prefix, suffix } = getAffixes(element);
|
|
162
|
+
return `${prefix}${text}${suffix}`;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Wrap the editable inline nodes with non-editable StaticAffix nodes so the static
|
|
166
|
+
* parts stay visible while remaining outside of the edited (and saved) content.
|
|
167
|
+
*/
|
|
168
|
+
function buildAffixDocument(element, inlineNodes) {
|
|
169
|
+
const { prefix, suffix } = getAffixes(element);
|
|
170
|
+
const content = [...inlineNodes];
|
|
171
|
+
if (prefix) content.unshift({
|
|
172
|
+
type: "staticAffix",
|
|
173
|
+
attrs: { text: prefix }
|
|
174
|
+
});
|
|
175
|
+
if (suffix) content.push({
|
|
176
|
+
type: "staticAffix",
|
|
177
|
+
attrs: { text: suffix }
|
|
178
|
+
});
|
|
179
|
+
return {
|
|
180
|
+
type: "doc",
|
|
181
|
+
content: [{
|
|
182
|
+
type: "paragraph",
|
|
183
|
+
content
|
|
184
|
+
}]
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
/** Extract the inline nodes of a single-paragraph document produced above. */
|
|
188
|
+
function getInlineNodes(content) {
|
|
189
|
+
if (typeof content === "string") return content ? [{
|
|
190
|
+
type: "text",
|
|
191
|
+
text: content
|
|
192
|
+
}] : [];
|
|
193
|
+
return (content.content?.[0])?.content ?? [];
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
85
196
|
* Parse a raw i18n template (e.g. "Copyright {{year}}") together with the
|
|
86
197
|
* already-rendered text (e.g. "Copyright 2026") and produce a TipTap JSON
|
|
87
198
|
* document where variable tokens become TemplateVariable nodes.
|
|
@@ -248,7 +359,7 @@ function activateEditor(element, hash, options) {
|
|
|
248
359
|
});
|
|
249
360
|
}
|
|
250
361
|
function createPlainTextEditor(element, options) {
|
|
251
|
-
const renderedText = element.textContent ?? "";
|
|
362
|
+
const renderedText = stripAffixes(element, element.textContent ?? "");
|
|
252
363
|
let content = renderedText;
|
|
253
364
|
const extraExtensions = [];
|
|
254
365
|
const mixedTemplate = element.dataset.upstartMixedTemplate;
|
|
@@ -256,18 +367,20 @@ function createPlainTextEditor(element, options) {
|
|
|
256
367
|
content = buildI18nContent(mixedTemplate, renderedText);
|
|
257
368
|
extraExtensions.push(TemplateVariable);
|
|
258
369
|
} else if ((element.dataset.i18nValues?.split(",").filter(Boolean) ?? []).length > 0) {
|
|
259
|
-
const
|
|
260
|
-
if (
|
|
261
|
-
const
|
|
262
|
-
const namespace = colonIdx >= 0 ? i18nAttr.slice(0, colonIdx) : "translation";
|
|
263
|
-
const key = colonIdx >= 0 ? i18nAttr.slice(colonIdx + 1) : i18nAttr;
|
|
264
|
-
const rawTemplate = options.getRawI18nTemplate(namespace, key);
|
|
370
|
+
const parsed = parseI18nAttr(element.dataset.upstartI18n);
|
|
371
|
+
if (parsed) {
|
|
372
|
+
const rawTemplate = options.getRawI18nTemplate(parsed.namespace, parsed.key);
|
|
265
373
|
if (rawTemplate) {
|
|
266
374
|
content = buildI18nContent(rawTemplate, renderedText);
|
|
267
375
|
extraExtensions.push(TemplateVariable);
|
|
268
376
|
}
|
|
269
377
|
}
|
|
270
378
|
}
|
|
379
|
+
const { prefix, suffix } = getAffixes(element);
|
|
380
|
+
if (prefix || suffix) {
|
|
381
|
+
extraExtensions.push(StaticAffix);
|
|
382
|
+
content = buildAffixDocument(element, getInlineNodes(content));
|
|
383
|
+
}
|
|
271
384
|
element.textContent = "";
|
|
272
385
|
let hasChanged = false;
|
|
273
386
|
return new Editor({
|
|
@@ -457,11 +570,19 @@ function syncI18nSiblings(sourceElement) {
|
|
|
457
570
|
for (const sibling of siblings) {
|
|
458
571
|
if (sibling === instance.element) continue;
|
|
459
572
|
const siblingInstance = activeEditors.get(sibling);
|
|
573
|
+
const { prefix, suffix } = getAffixes(sibling);
|
|
574
|
+
const hasAffixes = Boolean(prefix || suffix);
|
|
460
575
|
if (siblingInstance) {
|
|
461
576
|
console.log(`[Upstart Editor] Updating sibling editor (hash: ${siblingInstance.hash}) with new content`, siblingInstance);
|
|
462
|
-
sibling
|
|
463
|
-
|
|
464
|
-
|
|
577
|
+
if (hasAffixes) siblingInstance.editor.commands.setContent(buildAffixDocument(sibling, plainContent ? [{
|
|
578
|
+
type: "text",
|
|
579
|
+
text: plainContent
|
|
580
|
+
}] : []));
|
|
581
|
+
else {
|
|
582
|
+
sibling.innerText = plainContent;
|
|
583
|
+
siblingInstance.editor.chain().selectAll().insertContent(plainContent).run();
|
|
584
|
+
}
|
|
585
|
+
} else sibling.textContent = applyAffixes(sibling, plainContent);
|
|
465
586
|
}
|
|
466
587
|
} finally {
|
|
467
588
|
i18nSyncInProgress = false;
|
|
@@ -480,14 +601,18 @@ function saveText(element, newText) {
|
|
|
480
601
|
}
|
|
481
602
|
});
|
|
482
603
|
else {
|
|
483
|
-
const
|
|
604
|
+
const parsed = parseI18nAttr(dataset.upstartI18n);
|
|
605
|
+
if (!parsed) {
|
|
606
|
+
console.warn("[Upstart Editor] No resolvable i18n key on element, edit not saved:", element);
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
484
609
|
sendToParent({
|
|
485
610
|
type: "text-edit",
|
|
486
611
|
payload: {
|
|
487
612
|
action: "editText",
|
|
488
613
|
content: newText,
|
|
489
|
-
namespace,
|
|
490
|
-
key,
|
|
614
|
+
namespace: parsed.namespace,
|
|
615
|
+
key: parsed.key,
|
|
491
616
|
language: document.documentElement.lang
|
|
492
617
|
}
|
|
493
618
|
});
|
|
@@ -510,7 +635,7 @@ function destroyEditor(element) {
|
|
|
510
635
|
const editorDom = instance.element.querySelector(".ProseMirror");
|
|
511
636
|
if (editorDom) editorDom.remove();
|
|
512
637
|
delete instance.element.dataset.upstartEditorActive;
|
|
513
|
-
if (isPlainMode) instance.element.textContent = finalContent;
|
|
638
|
+
if (isPlainMode) instance.element.textContent = applyAffixes(instance.element, finalContent);
|
|
514
639
|
else instance.element.innerHTML = finalContent;
|
|
515
640
|
restoreStyles(instance.element);
|
|
516
641
|
activeEditors.delete(element);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-editor.js","names":[],"sources":["../../../src/vite-plugin-upstart-editor/runtime/text-editor.ts"],"sourcesContent":["import { Editor, Extension, Node } from \"@tiptap/core\";\nimport { BubbleMenu } from \"@tiptap/extension-bubble-menu\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport { sendToParent } from \"./utils.js\";\nimport type { EditorInstance, TextEditorMode, UpstartEditorOptions } from \"./types.js\";\n\n/**\n * Custom Document node for inline elements (e.g. <a>, <span>, headings).\n * Uses `inline*` content instead of the default `block+` to prevent\n * TipTap from wrapping text in <p> tags inside inline elements.\n */\nconst InlineDocument = Node.create({\n name: \"doc\",\n topNode: true,\n content: \"inline*\",\n});\n\n/**\n * An atomic inline node that represents an i18n template variable like {{year}}.\n * It is displayed as a grayed non-editable chip showing the resolved value.\n * renderText() returns {{varName}} so getText() serialises back to the raw template.\n */\nconst TemplateVariable = Node.create({\n name: \"templateVariable\",\n group: \"inline\",\n inline: true,\n atom: true,\n\n addAttributes() {\n return {\n varName: { default: \"\" },\n value: { default: \"\" },\n };\n },\n\n parseHTML() {\n return [{ tag: \"span[data-tpl-var]\" }];\n },\n\n renderHTML({ node }) {\n return [\n \"span\",\n {\n \"data-tpl-var\": node.attrs.varName,\n contenteditable: \"false\",\n style:\n \"opacity:0.5;background:rgba(0,0,0,0.08);border-radius:3px;padding:0 3px;\" +\n \"font-family:monospace;font-size:0.875em;cursor:default;user-select:none;\",\n },\n node.attrs.value || `{{${node.attrs.varName}}}`,\n ];\n },\n\n renderText({ node }) {\n return `{{${node.attrs.varName}}}`;\n },\n});\n\n/**\n * Remaps Enter to insert a <br> (hard break) instead of creating a new paragraph.\n * Used in inline-rich mode where block nodes are not allowed.\n */\nconst EnterHardBreak = Extension.create({\n name: \"enterHardBreak\",\n addKeyboardShortcuts() {\n return {\n Enter: () => this.editor.commands.setHardBreak(),\n };\n },\n});\n\nconst DEFAULT_OPTIONS: Required<UpstartEditorOptions> = {\n richTextElements: [\"p\", \"div\", \"article\", \"section\"],\n inlineRichTextElements: [\"a\", \"span\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"],\n plainTextElements: [\"button\", \"label\"],\n bubbleMenu: true,\n placeholder: \"Start typing...\",\n autoSaveDelay: 1000,\n getRawI18nTemplate: () => undefined,\n};\n\n/**\n * Parse a raw i18n template (e.g. \"Copyright {{year}}\") together with the\n * already-rendered text (e.g. \"Copyright 2026\") and produce a TipTap JSON\n * document where variable tokens become TemplateVariable nodes.\n */\nfunction buildI18nContent(rawTemplate: string, renderedText: string): object {\n const VAR_RE = /\\{\\{(\\w+)\\}\\}/g;\n type Segment = { type: \"text\"; text: string } | { type: \"var\"; varName: string };\n const segments: Segment[] = [];\n\n let lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = VAR_RE.exec(rawTemplate)) !== null) {\n if (m.index > lastIndex) segments.push({ type: \"text\", text: rawTemplate.slice(lastIndex, m.index) });\n segments.push({ type: \"var\", varName: m[1] });\n lastIndex = m.index + m[0].length;\n }\n if (lastIndex < rawTemplate.length) segments.push({ type: \"text\", text: rawTemplate.slice(lastIndex) });\n\n // Build a regex over the rendered text to capture variable values\n const escRe = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regexParts = segments.map((s) => (s.type === \"text\" ? escRe(s.text) : \"(.+?)\"));\n const fullRegex = new RegExp(\"^\" + regexParts.join(\"\") + \"$\");\n const varSegments = segments.filter((s): s is Extract<Segment, { type: \"var\" }> => s.type === \"var\");\n\n const varValues: Record<string, string> = {};\n const match = renderedText.match(fullRegex);\n if (match) {\n varSegments.forEach((seg, i) => {\n varValues[seg.varName] = match[i + 1] ?? `{{${seg.varName}}}`;\n });\n } else {\n varSegments.forEach((seg) => {\n varValues[seg.varName] = `{{${seg.varName}}}`;\n });\n }\n\n const inlineNodes = segments\n .map((s) =>\n s.type === \"text\"\n ? { type: \"text\", text: s.text }\n : { type: \"templateVariable\", attrs: { varName: s.varName, value: varValues[s.varName] } },\n )\n .filter((n) => n.type !== \"text\" || (n as any).text !== \"\");\n\n return { type: \"doc\", content: [{ type: \"paragraph\", content: inlineNodes }] };\n}\n\n// Keyed by the host DOM element, NOT by data-upstart-hash: a component rendered\n// multiple times (e.g. a TimelineItem reused 4×) emits the same source-derived\n// hash on every instance, so keying by hash would let only the first instance\n// become editable. The element is the only per-instance unique identity.\nconst activeEditors = new Map<HTMLElement, EditorInstance>();\nlet i18nSyncInProgress = false;\nconst styleCache = new WeakMap<\n HTMLElement,\n { outline: string; outlineOffset: string; cursor: string; transition: string }\n>();\nlet resolvedOptions: Required<UpstartEditorOptions> = DEFAULT_OPTIONS;\nlet shortcutsRegistered = false;\nlet domObserver: MutationObserver | null = null;\nlet reactivateTimer: number | null = null;\n\n/**\n * Initialize TipTap text editing for elements marked as editable.\n * Activation is deferred to avoid conflicting with React hydration.\n */\nexport function initTextEditor(options: UpstartEditorOptions = {}): void {\n resolvedOptions = { ...DEFAULT_OPTIONS, ...options };\n registerKeyboardShortcuts();\n\n // Defer activation to let React finish hydrating the server-rendered HTML.\n injectEditorStyles();\n // activateAllEditors();\n startDomObserver();\n}\n\n/**\n * Inject CSS rules that visually hide original content when an editor is active.\n * This avoids moving DOM nodes (which breaks React hydration).\n *\n * - `font-size: 0` + `color: transparent` hides direct text nodes\n * - `> *:not(.ProseMirror)` hides child elements\n * - ProseMirror gets explicit inline styles to restore text rendering\n */\nfunction injectEditorStyles(): void {\n if (document.getElementById(\"upstart-editor-styles\")) return;\n\n const style = document.createElement(\"style\");\n style.id = \"upstart-editor-styles\";\n style.textContent = [\n \"[data-upstart-editor-active] {\",\n \" cursor: text;\",\n \"}\",\n // \"[data-upstart-editor-active] > *:not(.ProseMirror) {\",\n // \" display: none !important;\",\n // \"}\",\n \"[data-upstart-editor-active] .ProseMirror {\",\n \" outline: none !important;\",\n \" font-size: inherit !important;\",\n \" line-height: inherit !important;\",\n \" color: inherit !important;\",\n \" letter-spacing: inherit !important;\",\n \" font-weight: inherit !important;\",\n \" white-space: inherit !important;\",\n \"}\",\n \"[data-upstart-editor-active] .ProseMirror:focus {\",\n \" outline: none !important;\",\n \"}\",\n // Single-line editors (plain/direct, e.g. array-item pills) render their text\n // inside a ProseMirror <p>, which would otherwise pick up the browser's default\n // paragraph margin and change the element's height when edit mode activates.\n \"[data-upstart-editor-active][data-upstart-editable-text-mode='plain'] .ProseMirror p,\",\n \"[data-upstart-editor-active][data-upstart-editable-text-mode='direct'] .ProseMirror p {\",\n \" margin: 0 !important;\",\n \" padding: 0 !important;\",\n \"}\",\n ].join(\"\\n\");\n document.head.appendChild(style);\n}\n\n/**\n * Activate editors on all editable elements. Safe to call multiple times.\n */\nexport function activateAllEditors(): void {\n cleanupOrphanedEditors();\n const editables = document.querySelectorAll<HTMLElement>('[data-upstart-editable-text=\"true\"]');\n editables.forEach((element) => {\n try {\n setupEditableElement(element, resolvedOptions);\n } catch (error) {\n console.error(\"[Upstart Editor] Failed to activate element:\", element.dataset.upstartHash, error);\n }\n });\n console.log(\"[Upstart Editor] Text editors activated\");\n}\n\n/**\n * Destroy all active editors.\n */\nexport function destroyAllActiveEditors(): void {\n stopDomObserver();\n for (const element of activeEditors.keys()) {\n destroyEditor(element);\n }\n}\n\nfunction setupEditableElement(element: HTMLElement, options: Required<UpstartEditorOptions>): void {\n const hash = getEditableHash(element);\n if (!hash || activeEditors.has(element)) {\n return;\n }\n\n cacheStyles(element);\n activateEditor(element, hash, options);\n}\n\nfunction activateEditor(element: HTMLElement, hash: string, options: Required<UpstartEditorOptions>): void {\n const mode = getEditorMode(element, options);\n\n let editor: Editor;\n\n switch (mode) {\n case \"direct\":\n editor = createDirectEditor(element, options);\n break;\n case \"rich-panel\":\n editor = createRichPanelEditor(element, options);\n break;\n case \"block-rich\":\n editor = createRichTextEditor(element, options);\n break;\n case \"inline-rich\":\n editor = createInlineRichTextEditor(element, options);\n break;\n case \"plain\":\n editor = createPlainTextEditor(element, options);\n break;\n }\n\n // Mark element — triggers CSS rules that hide original content\n element.dataset.upstartEditorActive = \"true\";\n\n applyActiveStyles(element);\n activeEditors.set(element, { editor, element, hash, mode });\n}\n\nfunction createPlainTextEditor(element: HTMLElement, options: Required<UpstartEditorOptions>): Editor {\n const renderedText = element.textContent ?? \"\";\n\n let content: string | object = renderedText;\n const extraExtensions: ReturnType<typeof Node.create>[] = [];\n\n // Mixed-text: JSXText + expression chips (e.g. © {year} Some text)\n const mixedTemplate = element.dataset.upstartMixedTemplate;\n if (mixedTemplate) {\n content = buildI18nContent(mixedTemplate, renderedText);\n extraExtensions.push(TemplateVariable);\n } else {\n // Check for i18n template variables (e.g. data-i18n-values=\"year,month\")\n const i18nValueKeys = element.dataset.i18nValues?.split(\",\").filter(Boolean) ?? [];\n if (i18nValueKeys.length > 0) {\n const i18nAttr = element.dataset.upstartI18n;\n if (i18nAttr) {\n const colonIdx = i18nAttr.indexOf(\":\");\n const namespace = colonIdx >= 0 ? i18nAttr.slice(0, colonIdx) : \"translation\";\n const key = colonIdx >= 0 ? i18nAttr.slice(colonIdx + 1) : i18nAttr;\n const rawTemplate = options.getRawI18nTemplate(namespace, key);\n if (rawTemplate) {\n content = buildI18nContent(rawTemplate, renderedText);\n extraExtensions.push(TemplateVariable);\n }\n }\n }\n }\n\n element.textContent = \"\";\n let hasChanged = false;\n\n const editor = new Editor({\n element,\n extensions: [\n ...extraExtensions,\n StarterKit.configure({\n heading: false,\n bold: false,\n italic: false,\n strike: false,\n blockquote: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n codeBlock: false,\n horizontalRule: false,\n }),\n Placeholder.configure({\n placeholder: \"Click to edit...\",\n }),\n ],\n content,\n editorProps: {\n attributes: {\n class: \"upstart-editor-active\",\n },\n },\n onUpdate: () => {\n if (i18nSyncInProgress) return;\n hasChanged = true;\n syncI18nSiblings(element);\n },\n onBlur: ({ editor: e }) => {\n if (!hasChanged) return;\n hasChanged = false;\n saveText(element, e.getText());\n },\n });\n\n return editor;\n}\n\nfunction createRichTextEditor(element: HTMLElement, options: Required<UpstartEditorOptions>): Editor {\n const content = element.innerHTML;\n element.innerHTML = \"\"; // Clear the element first!\n let hasChanged = false;\n\n const bubbleMenuElement = createBubbleMenuElement();\n const extensions: Extension[] = [\n StarterKit,\n Placeholder.configure({\n placeholder: options.placeholder,\n }),\n ];\n\n if (options.bubbleMenu) {\n extensions.push(\n BubbleMenu.configure({\n element: bubbleMenuElement,\n }),\n );\n }\n\n const editor = new Editor({\n element,\n extensions,\n content,\n editorProps: {\n attributes: {\n class: \"upstart-editor-active\",\n },\n },\n onUpdate: () => {\n if (i18nSyncInProgress) return;\n hasChanged = true;\n syncI18nSiblings(element);\n },\n onBlur: ({ editor: e }) => {\n if (!hasChanged) return;\n hasChanged = false;\n saveText(element, e.getHTML());\n },\n });\n\n if (options.bubbleMenu) {\n wireBubbleMenu(bubbleMenuElement, editor);\n }\n\n return editor;\n}\n\nfunction createInlineRichTextEditor(element: HTMLElement, options: Required<UpstartEditorOptions>): Editor {\n const content = element.innerHTML;\n element.innerHTML = \"\"; // Clear the element first!\n let hasChanged = false;\n\n const bubbleMenuElement = createBubbleMenuElement(\"inline\");\n const extensions: (Extension | ReturnType<typeof Node.create>)[] = [\n InlineDocument,\n EnterHardBreak,\n StarterKit.configure({\n document: false,\n heading: false,\n blockquote: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n codeBlock: false,\n horizontalRule: false,\n }),\n Placeholder.configure({\n placeholder: \"Click to edit...\",\n }),\n ];\n\n if (options.bubbleMenu) {\n extensions.push(\n BubbleMenu.configure({\n element: bubbleMenuElement,\n }),\n );\n }\n\n const editor = new Editor({\n element,\n extensions,\n content,\n editorProps: {\n attributes: {\n class: \"upstart-editor-active\",\n },\n },\n onUpdate: () => {\n if (i18nSyncInProgress) return;\n hasChanged = true;\n syncI18nSiblings(element);\n },\n onBlur: ({ editor: e }) => {\n if (!hasChanged) return;\n hasChanged = false;\n saveText(element, e.getHTML());\n },\n });\n\n if (options.bubbleMenu) {\n wireBubbleMenu(bubbleMenuElement, editor);\n }\n\n return editor;\n}\n\nfunction createDirectEditor(element: HTMLElement, options: Required<UpstartEditorOptions>): Editor {\n const content = element.innerHTML;\n element.innerHTML = \"\";\n let hasChanged = false;\n\n const bubbleMenuElement = createBubbleMenuElement(\"inline\");\n const extensions: (Extension | ReturnType<typeof Node.create>)[] = [\n EnterHardBreak,\n StarterKit.configure({\n heading: false,\n blockquote: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n codeBlock: false,\n horizontalRule: false,\n }),\n Placeholder.configure({ placeholder: \"Click to edit...\" }),\n ];\n\n if (options.bubbleMenu) {\n extensions.push(BubbleMenu.configure({ element: bubbleMenuElement }));\n }\n\n const editor = new Editor({\n element,\n extensions,\n content,\n editorProps: { attributes: { class: \"upstart-editor-active\" } },\n onUpdate: () => {\n hasChanged = true;\n },\n onBlur: ({ editor: e }) => {\n if (!hasChanged) return;\n hasChanged = false;\n // Strip the outer <p> that TipTap adds when using default document schema\n saveText(element, e.getHTML().replace(/^<p>([\\s\\S]*)<\\/p>$/, \"$1\"));\n },\n });\n\n if (options.bubbleMenu) {\n wireBubbleMenu(bubbleMenuElement, editor);\n }\n\n return editor;\n}\n\nfunction createRichPanelEditor(element: HTMLElement, options: Required<UpstartEditorOptions>): Editor {\n const content = element.innerHTML;\n element.innerHTML = \"\";\n let hasChanged = false;\n\n const bubbleMenuElement = createBubbleMenuElement(\"inline\");\n const extensions: Extension[] = [StarterKit, Placeholder.configure({ placeholder: options.placeholder })];\n\n if (options.bubbleMenu) {\n extensions.push(BubbleMenu.configure({ element: bubbleMenuElement }));\n }\n\n const editor = new Editor({\n element,\n extensions,\n content,\n editorProps: { attributes: { class: \"upstart-editor-active\" } },\n onUpdate: () => {\n hasChanged = true;\n },\n onBlur: ({ editor: e }) => {\n if (!hasChanged) return;\n hasChanged = false;\n saveText(element, e.getHTML());\n },\n });\n\n if (options.bubbleMenu) {\n wireBubbleMenu(bubbleMenuElement, editor);\n }\n\n return editor;\n}\n\nfunction getEditorMode(element: HTMLElement, options: Required<UpstartEditorOptions>): TextEditorMode {\n const modeOverride = element.dataset.upstartEditableTextMode as TextEditorMode | undefined;\n if (\n modeOverride === \"plain\" ||\n modeOverride === \"inline-rich\" ||\n modeOverride === \"block-rich\" ||\n modeOverride === \"direct\" ||\n modeOverride === \"rich-panel\"\n ) {\n return modeOverride;\n }\n\n const tagName = element.tagName.toLowerCase();\n\n if (options.plainTextElements.includes(tagName)) {\n return \"plain\";\n }\n\n if (options.inlineRichTextElements.includes(tagName)) {\n return \"inline-rich\";\n }\n\n if (options.richTextElements.includes(tagName)) {\n return \"block-rich\";\n }\n\n return \"block-rich\";\n}\n\nfunction syncI18nSiblings(sourceElement: HTMLElement): void {\n const instance = activeEditors.get(sourceElement);\n console.log(\"[Upstart Editor] Syncing i18n siblings for\", instance?.hash);\n if (!instance) {\n console.warn(\"[Upstart Editor] No editor instance found for element:\", sourceElement);\n return;\n }\n\n const i18nKey = instance.element.dataset.upstartI18n;\n if (!i18nKey) {\n console.warn(\"[Upstart Editor] No sibling i18n key found for element:\", instance.element);\n return;\n }\n\n const siblings = document.querySelectorAll<HTMLElement>(`[data-upstart-i18n=\"${CSS.escape(i18nKey)}\"]`);\n console.log(`[Upstart Editor] Found ${siblings.length} sibling(s) with i18n key \"${i18nKey}\"`);\n\n // Always use plain text so each sibling's schema can wrap it correctly\n // (e.g. InlineDocument vs block Document have incompatible content rules).\n const plainContent = instance.editor.getText();\n\n i18nSyncInProgress = true;\n try {\n for (const sibling of siblings) {\n if (sibling === instance.element) continue;\n\n const siblingInstance = activeEditors.get(sibling);\n\n if (siblingInstance) {\n console.log(\n `[Upstart Editor] Updating sibling editor (hash: ${siblingInstance.hash}) with new content`,\n siblingInstance,\n );\n sibling.innerText = plainContent;\n siblingInstance.editor.chain().selectAll().insertContent(plainContent).run();\n } else {\n sibling.textContent = plainContent;\n }\n }\n } finally {\n i18nSyncInProgress = false;\n }\n}\n\nfunction saveText(element: HTMLElement, newText: string): void {\n try {\n const instance = activeEditors.get(element);\n const dataset = instance?.element.dataset ?? {};\n\n // direct/rich-panel always go via editTextDirect; plain goes via editTextDirect when a\n // registry id is present (mixed-text), and via editText (i18n) otherwise.\n if (instance?.mode === \"direct\" || instance?.mode === \"rich-panel\" || dataset.upstartId) {\n sendToParent({\n type: \"text-edit\",\n payload: { action: \"editTextDirect\", id: dataset.upstartId!, content: newText },\n });\n } else {\n const [namespace, key] = dataset.upstartI18n?.split(\":\") ?? [];\n sendToParent({\n type: \"text-edit\",\n payload: {\n action: \"editText\",\n content: newText,\n namespace,\n key,\n language: document.documentElement.lang,\n },\n });\n }\n\n console.log(\"[Upstart Editor] Text save message sent:\", instance?.hash);\n } catch (error) {\n console.error(\"[Upstart Editor] Failed to send save message:\", error);\n sendToParent({\n type: \"editor-error\",\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n}\n\nfunction destroyEditor(element: HTMLElement): void {\n const instance = activeEditors.get(element);\n if (!instance) {\n return;\n }\n\n const isPlainMode = instance.mode === \"plain\";\n const finalContent = isPlainMode ? instance.editor.getText() : instance.editor.getHTML();\n\n instance.editor.destroy();\n\n // Remove ProseMirror DOM\n const editorDom = instance.element.querySelector(\".ProseMirror\");\n if (editorDom) editorDom.remove();\n\n // Remove CSS-hiding marker — original content becomes visible again\n delete instance.element.dataset.upstartEditorActive;\n\n // Update element content with the final edited text\n if (isPlainMode) {\n instance.element.textContent = finalContent;\n } else {\n instance.element.innerHTML = finalContent;\n }\n\n restoreStyles(instance.element);\n activeEditors.delete(element);\n}\n\n// ---------------------------------------------------------------------------\n// MutationObserver — re-activates editors after React re-renders\n// ---------------------------------------------------------------------------\n\nfunction startDomObserver(): void {\n if (domObserver) return;\n\n domObserver = new MutationObserver((mutations) => {\n let needsReactivation = false;\n\n for (const mutation of mutations) {\n if (mutation.type !== \"childList\") continue;\n\n for (const node of mutation.addedNodes) {\n if (\n node instanceof HTMLElement &&\n (node.matches?.('[data-upstart-editable-text=\"true\"]') ||\n node.querySelector?.('[data-upstart-editable-text=\"true\"]'))\n ) {\n needsReactivation = true;\n break;\n }\n }\n\n if (!needsReactivation) {\n for (const node of mutation.removedNodes) {\n if (\n node instanceof HTMLElement &&\n (node.matches?.('[data-upstart-editable-text=\"true\"]') ||\n node.querySelector?.('[data-upstart-editable-text=\"true\"]'))\n ) {\n needsReactivation = true;\n break;\n }\n }\n }\n\n if (needsReactivation) break;\n }\n\n if (needsReactivation) {\n scheduleReactivation();\n }\n });\n\n domObserver.observe(document.body, { childList: true, subtree: true });\n}\n\nfunction stopDomObserver(): void {\n if (domObserver) {\n domObserver.disconnect();\n domObserver = null;\n }\n if (reactivateTimer) {\n clearTimeout(reactivateTimer);\n reactivateTimer = null;\n }\n}\n\nfunction scheduleReactivation(): void {\n if (reactivateTimer) clearTimeout(reactivateTimer);\n reactivateTimer = window.setTimeout(() => {\n reactivateTimer = null;\n activateAllEditors();\n }, 50);\n}\n\n/**\n * Remove editors whose host element has been detached from the document\n * (e.g. React replaced the subtree during a re-render).\n */\nfunction cleanupOrphanedEditors(): void {\n for (const [element, instance] of activeEditors) {\n if (!document.contains(instance.element)) {\n instance.editor.destroy();\n activeEditors.delete(element);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Keyboard shortcuts\n// ---------------------------------------------------------------------------\n\nfunction registerKeyboardShortcuts(): void {\n if (shortcutsRegistered) {\n return;\n }\n\n document.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Escape\") {\n blurAllEditors();\n }\n\n if ((event.metaKey || event.ctrlKey) && event.key === \"Enter\") {\n blurAllEditors();\n }\n });\n\n shortcutsRegistered = true;\n}\n\nfunction blurAllEditors(): void {\n activeEditors.forEach((instance) => {\n instance.editor.commands.blur();\n });\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getEditableHash(element: HTMLElement): string | null {\n return element.dataset.upstartHash ?? null;\n}\n\nfunction cacheStyles(element: HTMLElement): void {\n if (styleCache.has(element)) {\n return;\n }\n\n styleCache.set(element, {\n outline: element.style.outline || \"\",\n outlineOffset: element.style.outlineOffset || \"\",\n cursor: element.style.cursor || \"\",\n transition: element.style.transition || \"\",\n });\n}\n\nfunction applyActiveStyles(element: HTMLElement): void {\n cacheStyles(element);\n}\n\nfunction restoreStyles(element: HTMLElement): void {\n const cached = styleCache.get(element);\n if (!cached) {\n element.style.outline = \"\";\n element.style.outlineOffset = \"\";\n element.style.cursor = \"\";\n element.style.transition = \"\";\n return;\n }\n\n element.style.outline = cached.outline;\n element.style.outlineOffset = cached.outlineOffset;\n element.style.cursor = cached.cursor;\n element.style.transition = cached.transition;\n}\n\nconst BUBBLE_MENU_GROUPS: { command: string; icon: string; title: string }[][] = [\n [\n { command: \"bold\", icon: \"format-bold\", title: \"Bold\" },\n { command: \"italic\", icon: \"format-italic\", title: \"Italic\" },\n { command: \"strike\", icon: \"format-strikethrough\", title: \"Strikethrough\" },\n { command: \"code\", icon: \"code-tags\", title: \"Inline Code\" },\n ],\n [\n { command: \"heading\", icon: \"format-header-1\", title: \"Heading\" },\n { command: \"blockquote\", icon: \"format-quote-close\", title: \"Blockquote\" },\n ],\n [\n { command: \"bulletList\", icon: \"format-list-bulleted\", title: \"Bullet List\" },\n { command: \"orderedList\", icon: \"format-list-numbered\", title: \"Ordered List\" },\n ],\n];\n\nfunction getIconifyUrl(iconName: string): string {\n return `https://api.iconify.design/mdi/${iconName}.svg?height=none&color=%23fff`;\n}\n\nfunction createBubbleMenuElement(mode: \"block\" | \"inline\" = \"block\"): HTMLDivElement {\n const groups = mode === \"inline\" ? [BUBBLE_MENU_GROUPS[0]] : BUBBLE_MENU_GROUPS;\n const menu = document.createElement(\"div\");\n menu.className = \"upstart-editor-bubble-menu\";\n menu.style.cssText =\n \"display: flex; align-items: center; gap: 2px; padding: 4px; \" +\n \"background: #111827; color: #ffffff; border-radius: 8px; \" +\n \"font-size: 12px; box-shadow: 0 8px 24px rgba(0,0,0,0.25);\";\n\n groups.forEach((group, groupIndex) => {\n if (groupIndex > 0) {\n const separator = document.createElement(\"div\");\n separator.style.cssText =\n \"width: 1px; height: 16px; background: rgba(255,255,255,0.2); \" + \"margin: 0 4px; flex-shrink: 0;\";\n menu.appendChild(separator);\n }\n\n for (const { command, icon, title } of group) {\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.dataset.command = command;\n button.title = title;\n button.style.cssText =\n \"background: transparent; border: none; color: inherit; cursor: pointer; \" +\n \"display: flex; align-items: center; justify-content: center; \" +\n \"width: 28px; height: 28px; padding: 4px; border-radius: 4px; \" +\n \"transition: background 0.15s ease;\";\n\n const img = document.createElement(\"img\");\n img.src = getIconifyUrl(icon);\n img.alt = title;\n img.style.cssText = \"width: 18px; height: 18px; display: block; pointer-events: none;\";\n button.appendChild(img);\n\n button.addEventListener(\"mouseenter\", () => {\n if (!button.dataset.active) {\n button.style.background = \"rgba(255,255,255,0.12)\";\n }\n });\n button.addEventListener(\"mouseleave\", () => {\n button.style.background = button.dataset.active ? \"rgba(255,255,255,0.2)\" : \"transparent\";\n });\n\n menu.appendChild(button);\n }\n });\n\n return menu;\n}\n\nfunction wireBubbleMenu(menu: HTMLDivElement, editor: Editor): void {\n menu.addEventListener(\"mousedown\", (event) => {\n event.preventDefault();\n });\n\n menu.addEventListener(\n \"click\",\n (event) => {\n console.log(\"menu button cliked\");\n event.stopPropagation();\n const target = event.target as HTMLElement | null;\n const command = target?.dataset.command;\n if (!command) return;\n\n const chain = editor.chain().focus();\n\n switch (command) {\n case \"bold\":\n chain.toggleBold().run();\n break;\n case \"italic\":\n chain.toggleItalic().run();\n break;\n case \"strike\":\n chain.toggleStrike().run();\n break;\n case \"code\":\n chain.toggleCode().run();\n break;\n case \"heading\":\n chain.toggleHeading({ level: 1 }).run();\n break;\n case \"blockquote\":\n chain.toggleBlockquote().run();\n break;\n case \"bulletList\":\n chain.toggleBulletList().run();\n break;\n case \"orderedList\":\n chain.toggleOrderedList().run();\n break;\n }\n },\n { capture: true },\n );\n\n const updateActiveStates = (): void => {\n const buttons = menu.querySelectorAll<HTMLButtonElement>(\"button[data-command]\");\n for (const button of buttons) {\n const command = button.dataset.command!;\n const isActive =\n command === \"heading\" ? editor.isActive(\"heading\", { level: 1 }) : editor.isActive(command);\n\n if (isActive) {\n button.dataset.active = \"true\";\n button.style.background = \"rgba(255,255,255,0.2)\";\n } else {\n delete button.dataset.active;\n button.style.background = \"transparent\";\n }\n }\n };\n\n editor.on(\"transaction\", updateActiveStates);\n updateActiveStates();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"text-editor.js","names":[],"sources":["../../../src/vite-plugin-upstart-editor/runtime/text-editor.ts"],"sourcesContent":["import { Editor, Extension, Node } from \"@tiptap/core\";\nimport { BubbleMenu } from \"@tiptap/extension-bubble-menu\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport { sendToParent } from \"./utils.js\";\nimport type { EditorInstance, TextEditorMode, UpstartEditorOptions } from \"./types.js\";\n\n/**\n * Custom Document node for inline elements (e.g. <a>, <span>, headings).\n * Uses `inline*` content instead of the default `block+` to prevent\n * TipTap from wrapping text in <p> tags inside inline elements.\n */\nconst InlineDocument = Node.create({\n name: \"doc\",\n topNode: true,\n content: \"inline*\",\n});\n\n/**\n * An atomic inline node that represents an i18n template variable like {{year}}.\n * It is displayed as a grayed non-editable chip showing the resolved value.\n * renderText() returns {{varName}} so getText() serialises back to the raw template.\n */\nconst TemplateVariable = Node.create({\n name: \"templateVariable\",\n group: \"inline\",\n inline: true,\n atom: true,\n\n addAttributes() {\n return {\n varName: { default: \"\" },\n value: { default: \"\" },\n };\n },\n\n parseHTML() {\n return [{ tag: \"span[data-tpl-var]\" }];\n },\n\n renderHTML({ node }) {\n return [\n \"span\",\n {\n \"data-tpl-var\": node.attrs.varName,\n contenteditable: \"false\",\n style:\n \"opacity:0.5;background:rgba(0,0,0,0.08);border-radius:3px;padding:0 3px;\" +\n \"font-family:monospace;font-size:0.875em;cursor:default;user-select:none;\",\n },\n node.attrs.value || `{{${node.attrs.varName}}}`,\n ];\n },\n\n renderText({ node }) {\n return `{{${node.attrs.varName}}}`;\n },\n});\n\n/**\n * An atomic inline node holding static text that surrounds an i18n node in the\n * source (e.g. the \" *\" in `<label><Trans i18nKey=\"…\" /> *</label>`).\n * It stays visible and non-editable, and renderText() returns \"\" so getText()\n * yields only the translation — the static part never leaks into the saved value.\n */\nconst StaticAffix = Node.create({\n name: \"staticAffix\",\n group: \"inline\",\n inline: true,\n atom: true,\n selectable: false,\n\n addAttributes() {\n return {\n text: { default: \"\" },\n };\n },\n\n parseHTML() {\n return [{ tag: \"span[data-static-affix]\" }];\n },\n\n renderHTML({ node }) {\n return [\n \"span\",\n {\n \"data-static-affix\": \"\",\n contenteditable: \"false\",\n style: \"cursor:default;user-select:none;white-space:pre;\",\n },\n node.attrs.text,\n ];\n },\n\n renderText() {\n return \"\";\n },\n});\n\n/**\n * Remaps Enter to insert a <br> (hard break) instead of creating a new paragraph.\n * Used in inline-rich mode where block nodes are not allowed.\n */\nconst EnterHardBreak = Extension.create({\n name: \"enterHardBreak\",\n addKeyboardShortcuts() {\n return {\n Enter: () => this.editor.commands.setHardBreak(),\n };\n },\n});\n\nconst DEFAULT_OPTIONS: Required<UpstartEditorOptions> = {\n richTextElements: [\"p\", \"div\", \"article\", \"section\"],\n inlineRichTextElements: [\"a\", \"span\", \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\"],\n plainTextElements: [\"button\", \"label\"],\n bubbleMenu: true,\n placeholder: \"Start typing...\",\n autoSaveDelay: 1000,\n getRawI18nTemplate: () => undefined,\n};\n\n/**\n * Parse a `data-upstart-i18n` value into its namespace and key.\n *\n * The build-time plugin guarantees a single \"namespace:key\" per element (a ternary\n * between two translations is emitted as a runtime-resolved expression), but a stale\n * build may still carry a comma-separated list of keys. Such a value is unresolvable —\n * we cannot tell which translation the edited text belongs to — so it is rejected\n * instead of being saved to a mangled key.\n */\nfunction parseI18nAttr(value: string | undefined): { namespace: string; key: string } | null {\n if (!value) return null;\n if (value.includes(\",\")) {\n console.warn(\"[Upstart Editor] Ambiguous i18n key, refusing to save:\", value);\n return null;\n }\n const colonIdx = value.indexOf(\":\");\n return colonIdx >= 0\n ? { namespace: value.slice(0, colonIdx), key: value.slice(colonIdx + 1) }\n : { namespace: \"translation\", key: value };\n}\n\n/**\n * Static text emitted by the build-time plugin around a single i18n node\n * (`data-upstart-i18n-prefix` / `data-upstart-i18n-suffix`).\n */\nfunction getAffixes(element: HTMLElement): { prefix: string; suffix: string } {\n return {\n prefix: element.dataset.upstartI18nPrefix ?? \"\",\n suffix: element.dataset.upstartI18nSuffix ?? \"\",\n };\n}\n\n/** Remove the static affixes from a rendered text to get the translation alone. */\nfunction stripAffixes(element: HTMLElement, text: string): string {\n const { prefix, suffix } = getAffixes(element);\n let out = text;\n if (prefix && out.startsWith(prefix)) out = out.slice(prefix.length);\n if (suffix && out.endsWith(suffix)) out = out.slice(0, out.length - suffix.length);\n return out;\n}\n\n/** Re-attach the static affixes to a translation for display purposes. */\nfunction applyAffixes(element: HTMLElement, text: string): string {\n const { prefix, suffix } = getAffixes(element);\n return `${prefix}${text}${suffix}`;\n}\n\n/**\n * Wrap the editable inline nodes with non-editable StaticAffix nodes so the static\n * parts stay visible while remaining outside of the edited (and saved) content.\n */\nfunction buildAffixDocument(element: HTMLElement, inlineNodes: object[]): object {\n const { prefix, suffix } = getAffixes(element);\n const content: object[] = [...inlineNodes];\n if (prefix) content.unshift({ type: \"staticAffix\", attrs: { text: prefix } });\n if (suffix) content.push({ type: \"staticAffix\", attrs: { text: suffix } });\n return { type: \"doc\", content: [{ type: \"paragraph\", content }] };\n}\n\n/** Extract the inline nodes of a single-paragraph document produced above. */\nfunction getInlineNodes(content: string | object): object[] {\n if (typeof content === \"string\") {\n return content ? [{ type: \"text\", text: content }] : [];\n }\n const paragraph = (content as { content?: { content?: object[] }[] }).content?.[0];\n return paragraph?.content ?? [];\n}\n\n/**\n * Parse a raw i18n template (e.g. \"Copyright {{year}}\") together with the\n * already-rendered text (e.g. \"Copyright 2026\") and produce a TipTap JSON\n * document where variable tokens become TemplateVariable nodes.\n */\nfunction buildI18nContent(rawTemplate: string, renderedText: string): object {\n const VAR_RE = /\\{\\{(\\w+)\\}\\}/g;\n type Segment = { type: \"text\"; text: string } | { type: \"var\"; varName: string };\n const segments: Segment[] = [];\n\n let lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = VAR_RE.exec(rawTemplate)) !== null) {\n if (m.index > lastIndex) segments.push({ type: \"text\", text: rawTemplate.slice(lastIndex, m.index) });\n segments.push({ type: \"var\", varName: m[1] });\n lastIndex = m.index + m[0].length;\n }\n if (lastIndex < rawTemplate.length) segments.push({ type: \"text\", text: rawTemplate.slice(lastIndex) });\n\n // Build a regex over the rendered text to capture variable values\n const escRe = (s: string) => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const regexParts = segments.map((s) => (s.type === \"text\" ? escRe(s.text) : \"(.+?)\"));\n const fullRegex = new RegExp(\"^\" + regexParts.join(\"\") + \"$\");\n const varSegments = segments.filter((s): s is Extract<Segment, { type: \"var\" }> => s.type === \"var\");\n\n const varValues: Record<string, string> = {};\n const match = renderedText.match(fullRegex);\n if (match) {\n varSegments.forEach((seg, i) => {\n varValues[seg.varName] = match[i + 1] ?? `{{${seg.varName}}}`;\n });\n } else {\n varSegments.forEach((seg) => {\n varValues[seg.varName] = `{{${seg.varName}}}`;\n });\n }\n\n const inlineNodes = segments\n .map((s) =>\n s.type === \"text\"\n ? { type: \"text\", text: s.text }\n : { type: \"templateVariable\", attrs: { varName: s.varName, value: varValues[s.varName] } },\n )\n .filter((n) => n.type !== \"text\" || (n as any).text !== \"\");\n\n return { type: \"doc\", content: [{ type: \"paragraph\", content: inlineNodes }] };\n}\n\n// Keyed by the host DOM element, NOT by data-upstart-hash: a component rendered\n// multiple times (e.g. a TimelineItem reused 4×) emits the same source-derived\n// hash on every instance, so keying by hash would let only the first instance\n// become editable. The element is the only per-instance unique identity.\nconst activeEditors = new Map<HTMLElement, EditorInstance>();\nlet i18nSyncInProgress = false;\nconst styleCache = new WeakMap<\n HTMLElement,\n { outline: string; outlineOffset: string; cursor: string; transition: string }\n>();\nlet resolvedOptions: Required<UpstartEditorOptions> = DEFAULT_OPTIONS;\nlet shortcutsRegistered = false;\nlet domObserver: MutationObserver | null = null;\nlet reactivateTimer: number | null = null;\n\n/**\n * Initialize TipTap text editing for elements marked as editable.\n * Activation is deferred to avoid conflicting with React hydration.\n */\nexport function initTextEditor(options: UpstartEditorOptions = {}): void {\n resolvedOptions = { ...DEFAULT_OPTIONS, ...options };\n registerKeyboardShortcuts();\n\n // Defer activation to let React finish hydrating the server-rendered HTML.\n injectEditorStyles();\n // activateAllEditors();\n startDomObserver();\n}\n\n/**\n * Inject CSS rules that visually hide original content when an editor is active.\n * This avoids moving DOM nodes (which breaks React hydration).\n *\n * - `font-size: 0` + `color: transparent` hides direct text nodes\n * - `> *:not(.ProseMirror)` hides child elements\n * - ProseMirror gets explicit inline styles to restore text rendering\n */\nfunction injectEditorStyles(): void {\n if (document.getElementById(\"upstart-editor-styles\")) return;\n\n const style = document.createElement(\"style\");\n style.id = \"upstart-editor-styles\";\n style.textContent = [\n \"[data-upstart-editor-active] {\",\n \" cursor: text;\",\n \"}\",\n // \"[data-upstart-editor-active] > *:not(.ProseMirror) {\",\n // \" display: none !important;\",\n // \"}\",\n \"[data-upstart-editor-active] .ProseMirror {\",\n \" outline: none !important;\",\n \" font-size: inherit !important;\",\n \" line-height: inherit !important;\",\n \" color: inherit !important;\",\n \" letter-spacing: inherit !important;\",\n \" font-weight: inherit !important;\",\n \" white-space: inherit !important;\",\n \"}\",\n \"[data-upstart-editor-active] .ProseMirror:focus {\",\n \" outline: none !important;\",\n \"}\",\n // Single-line editors (plain/direct, e.g. array-item pills) render their text\n // inside a ProseMirror <p>, which would otherwise pick up the browser's default\n // paragraph margin and change the element's height when edit mode activates.\n \"[data-upstart-editor-active][data-upstart-editable-text-mode='plain'] .ProseMirror p,\",\n \"[data-upstart-editor-active][data-upstart-editable-text-mode='direct'] .ProseMirror p {\",\n \" margin: 0 !important;\",\n \" padding: 0 !important;\",\n \"}\",\n ].join(\"\\n\");\n document.head.appendChild(style);\n}\n\n/**\n * Activate editors on all editable elements. Safe to call multiple times.\n */\nexport function activateAllEditors(): void {\n cleanupOrphanedEditors();\n const editables = document.querySelectorAll<HTMLElement>('[data-upstart-editable-text=\"true\"]');\n editables.forEach((element) => {\n try {\n setupEditableElement(element, resolvedOptions);\n } catch (error) {\n console.error(\"[Upstart Editor] Failed to activate element:\", element.dataset.upstartHash, error);\n }\n });\n console.log(\"[Upstart Editor] Text editors activated\");\n}\n\n/**\n * Destroy all active editors.\n */\nexport function destroyAllActiveEditors(): void {\n stopDomObserver();\n for (const element of activeEditors.keys()) {\n destroyEditor(element);\n }\n}\n\nfunction setupEditableElement(element: HTMLElement, options: Required<UpstartEditorOptions>): void {\n const hash = getEditableHash(element);\n if (!hash || activeEditors.has(element)) {\n return;\n }\n\n cacheStyles(element);\n activateEditor(element, hash, options);\n}\n\nfunction activateEditor(element: HTMLElement, hash: string, options: Required<UpstartEditorOptions>): void {\n const mode = getEditorMode(element, options);\n\n let editor: Editor;\n\n switch (mode) {\n case \"direct\":\n editor = createDirectEditor(element, options);\n break;\n case \"rich-panel\":\n editor = createRichPanelEditor(element, options);\n break;\n case \"block-rich\":\n editor = createRichTextEditor(element, options);\n break;\n case \"inline-rich\":\n editor = createInlineRichTextEditor(element, options);\n break;\n case \"plain\":\n editor = createPlainTextEditor(element, options);\n break;\n }\n\n // Mark element — triggers CSS rules that hide original content\n element.dataset.upstartEditorActive = \"true\";\n\n applyActiveStyles(element);\n activeEditors.set(element, { editor, element, hash, mode });\n}\n\nfunction createPlainTextEditor(element: HTMLElement, options: Required<UpstartEditorOptions>): Editor {\n // A label like `<Trans i18nKey=\"…\" /> *` renders the static \" *\" alongside the\n // translation: strip it so only the translation becomes editable.\n const renderedText = stripAffixes(element, element.textContent ?? \"\");\n\n let content: string | object = renderedText;\n const extraExtensions: ReturnType<typeof Node.create>[] = [];\n\n // Mixed-text: JSXText + expression chips (e.g. © {year} Some text)\n const mixedTemplate = element.dataset.upstartMixedTemplate;\n if (mixedTemplate) {\n content = buildI18nContent(mixedTemplate, renderedText);\n extraExtensions.push(TemplateVariable);\n } else {\n // Check for i18n template variables (e.g. data-i18n-values=\"year,month\")\n const i18nValueKeys = element.dataset.i18nValues?.split(\",\").filter(Boolean) ?? [];\n if (i18nValueKeys.length > 0) {\n const parsed = parseI18nAttr(element.dataset.upstartI18n);\n if (parsed) {\n const rawTemplate = options.getRawI18nTemplate(parsed.namespace, parsed.key);\n if (rawTemplate) {\n content = buildI18nContent(rawTemplate, renderedText);\n extraExtensions.push(TemplateVariable);\n }\n }\n }\n }\n\n const { prefix, suffix } = getAffixes(element);\n if (prefix || suffix) {\n extraExtensions.push(StaticAffix);\n content = buildAffixDocument(element, getInlineNodes(content));\n }\n\n element.textContent = \"\";\n let hasChanged = false;\n\n const editor = new Editor({\n element,\n extensions: [\n ...extraExtensions,\n StarterKit.configure({\n heading: false,\n bold: false,\n italic: false,\n strike: false,\n blockquote: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n codeBlock: false,\n horizontalRule: false,\n }),\n Placeholder.configure({\n placeholder: \"Click to edit...\",\n }),\n ],\n content,\n editorProps: {\n attributes: {\n class: \"upstart-editor-active\",\n },\n },\n onUpdate: () => {\n if (i18nSyncInProgress) return;\n hasChanged = true;\n syncI18nSiblings(element);\n },\n onBlur: ({ editor: e }) => {\n if (!hasChanged) return;\n hasChanged = false;\n saveText(element, e.getText());\n },\n });\n\n return editor;\n}\n\nfunction createRichTextEditor(element: HTMLElement, options: Required<UpstartEditorOptions>): Editor {\n const content = element.innerHTML;\n element.innerHTML = \"\"; // Clear the element first!\n let hasChanged = false;\n\n const bubbleMenuElement = createBubbleMenuElement();\n const extensions: Extension[] = [\n StarterKit,\n Placeholder.configure({\n placeholder: options.placeholder,\n }),\n ];\n\n if (options.bubbleMenu) {\n extensions.push(\n BubbleMenu.configure({\n element: bubbleMenuElement,\n }),\n );\n }\n\n const editor = new Editor({\n element,\n extensions,\n content,\n editorProps: {\n attributes: {\n class: \"upstart-editor-active\",\n },\n },\n onUpdate: () => {\n if (i18nSyncInProgress) return;\n hasChanged = true;\n syncI18nSiblings(element);\n },\n onBlur: ({ editor: e }) => {\n if (!hasChanged) return;\n hasChanged = false;\n saveText(element, e.getHTML());\n },\n });\n\n if (options.bubbleMenu) {\n wireBubbleMenu(bubbleMenuElement, editor);\n }\n\n return editor;\n}\n\nfunction createInlineRichTextEditor(element: HTMLElement, options: Required<UpstartEditorOptions>): Editor {\n const content = element.innerHTML;\n element.innerHTML = \"\"; // Clear the element first!\n let hasChanged = false;\n\n const bubbleMenuElement = createBubbleMenuElement(\"inline\");\n const extensions: (Extension | ReturnType<typeof Node.create>)[] = [\n InlineDocument,\n EnterHardBreak,\n StarterKit.configure({\n document: false,\n heading: false,\n blockquote: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n codeBlock: false,\n horizontalRule: false,\n }),\n Placeholder.configure({\n placeholder: \"Click to edit...\",\n }),\n ];\n\n if (options.bubbleMenu) {\n extensions.push(\n BubbleMenu.configure({\n element: bubbleMenuElement,\n }),\n );\n }\n\n const editor = new Editor({\n element,\n extensions,\n content,\n editorProps: {\n attributes: {\n class: \"upstart-editor-active\",\n },\n },\n onUpdate: () => {\n if (i18nSyncInProgress) return;\n hasChanged = true;\n syncI18nSiblings(element);\n },\n onBlur: ({ editor: e }) => {\n if (!hasChanged) return;\n hasChanged = false;\n saveText(element, e.getHTML());\n },\n });\n\n if (options.bubbleMenu) {\n wireBubbleMenu(bubbleMenuElement, editor);\n }\n\n return editor;\n}\n\nfunction createDirectEditor(element: HTMLElement, options: Required<UpstartEditorOptions>): Editor {\n const content = element.innerHTML;\n element.innerHTML = \"\";\n let hasChanged = false;\n\n const bubbleMenuElement = createBubbleMenuElement(\"inline\");\n const extensions: (Extension | ReturnType<typeof Node.create>)[] = [\n EnterHardBreak,\n StarterKit.configure({\n heading: false,\n blockquote: false,\n bulletList: false,\n orderedList: false,\n listItem: false,\n codeBlock: false,\n horizontalRule: false,\n }),\n Placeholder.configure({ placeholder: \"Click to edit...\" }),\n ];\n\n if (options.bubbleMenu) {\n extensions.push(BubbleMenu.configure({ element: bubbleMenuElement }));\n }\n\n const editor = new Editor({\n element,\n extensions,\n content,\n editorProps: { attributes: { class: \"upstart-editor-active\" } },\n onUpdate: () => {\n hasChanged = true;\n },\n onBlur: ({ editor: e }) => {\n if (!hasChanged) return;\n hasChanged = false;\n // Strip the outer <p> that TipTap adds when using default document schema\n saveText(element, e.getHTML().replace(/^<p>([\\s\\S]*)<\\/p>$/, \"$1\"));\n },\n });\n\n if (options.bubbleMenu) {\n wireBubbleMenu(bubbleMenuElement, editor);\n }\n\n return editor;\n}\n\nfunction createRichPanelEditor(element: HTMLElement, options: Required<UpstartEditorOptions>): Editor {\n const content = element.innerHTML;\n element.innerHTML = \"\";\n let hasChanged = false;\n\n const bubbleMenuElement = createBubbleMenuElement(\"inline\");\n const extensions: Extension[] = [StarterKit, Placeholder.configure({ placeholder: options.placeholder })];\n\n if (options.bubbleMenu) {\n extensions.push(BubbleMenu.configure({ element: bubbleMenuElement }));\n }\n\n const editor = new Editor({\n element,\n extensions,\n content,\n editorProps: { attributes: { class: \"upstart-editor-active\" } },\n onUpdate: () => {\n hasChanged = true;\n },\n onBlur: ({ editor: e }) => {\n if (!hasChanged) return;\n hasChanged = false;\n saveText(element, e.getHTML());\n },\n });\n\n if (options.bubbleMenu) {\n wireBubbleMenu(bubbleMenuElement, editor);\n }\n\n return editor;\n}\n\nfunction getEditorMode(element: HTMLElement, options: Required<UpstartEditorOptions>): TextEditorMode {\n const modeOverride = element.dataset.upstartEditableTextMode as TextEditorMode | undefined;\n if (\n modeOverride === \"plain\" ||\n modeOverride === \"inline-rich\" ||\n modeOverride === \"block-rich\" ||\n modeOverride === \"direct\" ||\n modeOverride === \"rich-panel\"\n ) {\n return modeOverride;\n }\n\n const tagName = element.tagName.toLowerCase();\n\n if (options.plainTextElements.includes(tagName)) {\n return \"plain\";\n }\n\n if (options.inlineRichTextElements.includes(tagName)) {\n return \"inline-rich\";\n }\n\n if (options.richTextElements.includes(tagName)) {\n return \"block-rich\";\n }\n\n return \"block-rich\";\n}\n\nfunction syncI18nSiblings(sourceElement: HTMLElement): void {\n const instance = activeEditors.get(sourceElement);\n console.log(\"[Upstart Editor] Syncing i18n siblings for\", instance?.hash);\n if (!instance) {\n console.warn(\"[Upstart Editor] No editor instance found for element:\", sourceElement);\n return;\n }\n\n const i18nKey = instance.element.dataset.upstartI18n;\n if (!i18nKey) {\n console.warn(\"[Upstart Editor] No sibling i18n key found for element:\", instance.element);\n return;\n }\n\n const siblings = document.querySelectorAll<HTMLElement>(`[data-upstart-i18n=\"${CSS.escape(i18nKey)}\"]`);\n console.log(`[Upstart Editor] Found ${siblings.length} sibling(s) with i18n key \"${i18nKey}\"`);\n\n // Always use plain text so each sibling's schema can wrap it correctly\n // (e.g. InlineDocument vs block Document have incompatible content rules).\n const plainContent = instance.editor.getText();\n\n i18nSyncInProgress = true;\n try {\n for (const sibling of siblings) {\n if (sibling === instance.element) continue;\n\n const siblingInstance = activeEditors.get(sibling);\n\n const { prefix, suffix } = getAffixes(sibling);\n const hasAffixes = Boolean(prefix || suffix);\n\n if (siblingInstance) {\n console.log(\n `[Upstart Editor] Updating sibling editor (hash: ${siblingInstance.hash}) with new content`,\n siblingInstance,\n );\n if (hasAffixes) {\n // setContent rebuilds the StaticAffix nodes, which insertContent would drop\n siblingInstance.editor.commands.setContent(\n buildAffixDocument(sibling, plainContent ? [{ type: \"text\", text: plainContent }] : []),\n );\n } else {\n sibling.innerText = plainContent;\n siblingInstance.editor.chain().selectAll().insertContent(plainContent).run();\n }\n } else {\n sibling.textContent = applyAffixes(sibling, plainContent);\n }\n }\n } finally {\n i18nSyncInProgress = false;\n }\n}\n\nfunction saveText(element: HTMLElement, newText: string): void {\n try {\n const instance = activeEditors.get(element);\n const dataset = instance?.element.dataset ?? {};\n\n // direct/rich-panel always go via editTextDirect; plain goes via editTextDirect when a\n // registry id is present (mixed-text), and via editText (i18n) otherwise.\n if (instance?.mode === \"direct\" || instance?.mode === \"rich-panel\" || dataset.upstartId) {\n sendToParent({\n type: \"text-edit\",\n payload: { action: \"editTextDirect\", id: dataset.upstartId!, content: newText },\n });\n } else {\n const parsed = parseI18nAttr(dataset.upstartI18n);\n if (!parsed) {\n console.warn(\"[Upstart Editor] No resolvable i18n key on element, edit not saved:\", element);\n return;\n }\n sendToParent({\n type: \"text-edit\",\n payload: {\n action: \"editText\",\n content: newText,\n namespace: parsed.namespace,\n key: parsed.key,\n language: document.documentElement.lang,\n },\n });\n }\n\n console.log(\"[Upstart Editor] Text save message sent:\", instance?.hash);\n } catch (error) {\n console.error(\"[Upstart Editor] Failed to send save message:\", error);\n sendToParent({\n type: \"editor-error\",\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n}\n\nfunction destroyEditor(element: HTMLElement): void {\n const instance = activeEditors.get(element);\n if (!instance) {\n return;\n }\n\n const isPlainMode = instance.mode === \"plain\";\n const finalContent = isPlainMode ? instance.editor.getText() : instance.editor.getHTML();\n\n instance.editor.destroy();\n\n // Remove ProseMirror DOM\n const editorDom = instance.element.querySelector(\".ProseMirror\");\n if (editorDom) editorDom.remove();\n\n // Remove CSS-hiding marker — original content becomes visible again\n delete instance.element.dataset.upstartEditorActive;\n\n // Update element content with the final edited text\n if (isPlainMode) {\n instance.element.textContent = applyAffixes(instance.element, finalContent);\n } else {\n instance.element.innerHTML = finalContent;\n }\n\n restoreStyles(instance.element);\n activeEditors.delete(element);\n}\n\n// ---------------------------------------------------------------------------\n// MutationObserver — re-activates editors after React re-renders\n// ---------------------------------------------------------------------------\n\nfunction startDomObserver(): void {\n if (domObserver) return;\n\n domObserver = new MutationObserver((mutations) => {\n let needsReactivation = false;\n\n for (const mutation of mutations) {\n if (mutation.type !== \"childList\") continue;\n\n for (const node of mutation.addedNodes) {\n if (\n node instanceof HTMLElement &&\n (node.matches?.('[data-upstart-editable-text=\"true\"]') ||\n node.querySelector?.('[data-upstart-editable-text=\"true\"]'))\n ) {\n needsReactivation = true;\n break;\n }\n }\n\n if (!needsReactivation) {\n for (const node of mutation.removedNodes) {\n if (\n node instanceof HTMLElement &&\n (node.matches?.('[data-upstart-editable-text=\"true\"]') ||\n node.querySelector?.('[data-upstart-editable-text=\"true\"]'))\n ) {\n needsReactivation = true;\n break;\n }\n }\n }\n\n if (needsReactivation) break;\n }\n\n if (needsReactivation) {\n scheduleReactivation();\n }\n });\n\n domObserver.observe(document.body, { childList: true, subtree: true });\n}\n\nfunction stopDomObserver(): void {\n if (domObserver) {\n domObserver.disconnect();\n domObserver = null;\n }\n if (reactivateTimer) {\n clearTimeout(reactivateTimer);\n reactivateTimer = null;\n }\n}\n\nfunction scheduleReactivation(): void {\n if (reactivateTimer) clearTimeout(reactivateTimer);\n reactivateTimer = window.setTimeout(() => {\n reactivateTimer = null;\n activateAllEditors();\n }, 50);\n}\n\n/**\n * Remove editors whose host element has been detached from the document\n * (e.g. React replaced the subtree during a re-render).\n */\nfunction cleanupOrphanedEditors(): void {\n for (const [element, instance] of activeEditors) {\n if (!document.contains(instance.element)) {\n instance.editor.destroy();\n activeEditors.delete(element);\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Keyboard shortcuts\n// ---------------------------------------------------------------------------\n\nfunction registerKeyboardShortcuts(): void {\n if (shortcutsRegistered) {\n return;\n }\n\n document.addEventListener(\"keydown\", (event) => {\n if (event.key === \"Escape\") {\n blurAllEditors();\n }\n\n if ((event.metaKey || event.ctrlKey) && event.key === \"Enter\") {\n blurAllEditors();\n }\n });\n\n shortcutsRegistered = true;\n}\n\nfunction blurAllEditors(): void {\n activeEditors.forEach((instance) => {\n instance.editor.commands.blur();\n });\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction getEditableHash(element: HTMLElement): string | null {\n return element.dataset.upstartHash ?? null;\n}\n\nfunction cacheStyles(element: HTMLElement): void {\n if (styleCache.has(element)) {\n return;\n }\n\n styleCache.set(element, {\n outline: element.style.outline || \"\",\n outlineOffset: element.style.outlineOffset || \"\",\n cursor: element.style.cursor || \"\",\n transition: element.style.transition || \"\",\n });\n}\n\nfunction applyActiveStyles(element: HTMLElement): void {\n cacheStyles(element);\n}\n\nfunction restoreStyles(element: HTMLElement): void {\n const cached = styleCache.get(element);\n if (!cached) {\n element.style.outline = \"\";\n element.style.outlineOffset = \"\";\n element.style.cursor = \"\";\n element.style.transition = \"\";\n return;\n }\n\n element.style.outline = cached.outline;\n element.style.outlineOffset = cached.outlineOffset;\n element.style.cursor = cached.cursor;\n element.style.transition = cached.transition;\n}\n\nconst BUBBLE_MENU_GROUPS: { command: string; icon: string; title: string }[][] = [\n [\n { command: \"bold\", icon: \"format-bold\", title: \"Bold\" },\n { command: \"italic\", icon: \"format-italic\", title: \"Italic\" },\n { command: \"strike\", icon: \"format-strikethrough\", title: \"Strikethrough\" },\n { command: \"code\", icon: \"code-tags\", title: \"Inline Code\" },\n ],\n [\n { command: \"heading\", icon: \"format-header-1\", title: \"Heading\" },\n { command: \"blockquote\", icon: \"format-quote-close\", title: \"Blockquote\" },\n ],\n [\n { command: \"bulletList\", icon: \"format-list-bulleted\", title: \"Bullet List\" },\n { command: \"orderedList\", icon: \"format-list-numbered\", title: \"Ordered List\" },\n ],\n];\n\nfunction getIconifyUrl(iconName: string): string {\n return `https://api.iconify.design/mdi/${iconName}.svg?height=none&color=%23fff`;\n}\n\nfunction createBubbleMenuElement(mode: \"block\" | \"inline\" = \"block\"): HTMLDivElement {\n const groups = mode === \"inline\" ? [BUBBLE_MENU_GROUPS[0]] : BUBBLE_MENU_GROUPS;\n const menu = document.createElement(\"div\");\n menu.className = \"upstart-editor-bubble-menu\";\n menu.style.cssText =\n \"display: flex; align-items: center; gap: 2px; padding: 4px; \" +\n \"background: #111827; color: #ffffff; border-radius: 8px; \" +\n \"font-size: 12px; box-shadow: 0 8px 24px rgba(0,0,0,0.25);\";\n\n groups.forEach((group, groupIndex) => {\n if (groupIndex > 0) {\n const separator = document.createElement(\"div\");\n separator.style.cssText =\n \"width: 1px; height: 16px; background: rgba(255,255,255,0.2); \" + \"margin: 0 4px; flex-shrink: 0;\";\n menu.appendChild(separator);\n }\n\n for (const { command, icon, title } of group) {\n const button = document.createElement(\"button\");\n button.type = \"button\";\n button.dataset.command = command;\n button.title = title;\n button.style.cssText =\n \"background: transparent; border: none; color: inherit; cursor: pointer; \" +\n \"display: flex; align-items: center; justify-content: center; \" +\n \"width: 28px; height: 28px; padding: 4px; border-radius: 4px; \" +\n \"transition: background 0.15s ease;\";\n\n const img = document.createElement(\"img\");\n img.src = getIconifyUrl(icon);\n img.alt = title;\n img.style.cssText = \"width: 18px; height: 18px; display: block; pointer-events: none;\";\n button.appendChild(img);\n\n button.addEventListener(\"mouseenter\", () => {\n if (!button.dataset.active) {\n button.style.background = \"rgba(255,255,255,0.12)\";\n }\n });\n button.addEventListener(\"mouseleave\", () => {\n button.style.background = button.dataset.active ? \"rgba(255,255,255,0.2)\" : \"transparent\";\n });\n\n menu.appendChild(button);\n }\n });\n\n return menu;\n}\n\nfunction wireBubbleMenu(menu: HTMLDivElement, editor: Editor): void {\n menu.addEventListener(\"mousedown\", (event) => {\n event.preventDefault();\n });\n\n menu.addEventListener(\n \"click\",\n (event) => {\n console.log(\"menu button cliked\");\n event.stopPropagation();\n const target = event.target as HTMLElement | null;\n const command = target?.dataset.command;\n if (!command) return;\n\n const chain = editor.chain().focus();\n\n switch (command) {\n case \"bold\":\n chain.toggleBold().run();\n break;\n case \"italic\":\n chain.toggleItalic().run();\n break;\n case \"strike\":\n chain.toggleStrike().run();\n break;\n case \"code\":\n chain.toggleCode().run();\n break;\n case \"heading\":\n chain.toggleHeading({ level: 1 }).run();\n break;\n case \"blockquote\":\n chain.toggleBlockquote().run();\n break;\n case \"bulletList\":\n chain.toggleBulletList().run();\n break;\n case \"orderedList\":\n chain.toggleOrderedList().run();\n break;\n }\n },\n { capture: true },\n );\n\n const updateActiveStates = (): void => {\n const buttons = menu.querySelectorAll<HTMLButtonElement>(\"button[data-command]\");\n for (const button of buttons) {\n const command = button.dataset.command!;\n const isActive =\n command === \"heading\" ? editor.isActive(\"heading\", { level: 1 }) : editor.isActive(command);\n\n if (isActive) {\n button.dataset.active = \"true\";\n button.style.background = \"rgba(255,255,255,0.2)\";\n } else {\n delete button.dataset.active;\n button.style.background = \"transparent\";\n }\n }\n };\n\n editor.on(\"transaction\", updateActiveStates);\n updateActiveStates();\n}\n"],"mappings":"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"}
|
|
@@ -78,6 +78,9 @@ type EditorMessage = {
|
|
|
78
78
|
} | {
|
|
79
79
|
type: "editor-navigated";
|
|
80
80
|
path?: string;
|
|
81
|
+
} /** React-router id of the route currently rendered (e.g. "routes/_layout._index"). */ | {
|
|
82
|
+
type: "editor-route";
|
|
83
|
+
routeId: string;
|
|
81
84
|
} | {
|
|
82
85
|
type: "scroll-position";
|
|
83
86
|
x: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/vite-plugin-upstart-editor/runtime/types.ts"],"mappings":";;;;;;AAeA;;;;KAAY,UAAA;AAOZ;;;;;AAAA,UAAiB,YAAA;EACf,GAAA;EACA,IAAA;EACA,QAAA;EACA,aAAA;EACA,QAAA;EACA,IAAA;EAMS;AAWX;;;;EAXE,SAAA;AAAA;;;;;;;;;KAWU,cAAA;;;AAiBZ;UAZiB,aAAA;EACf,GAAA;EACA,IAAA;EACA,KAAA;EACA,MAAA;EACA,KAAA;EACA,MAAA;AAAA;;;;UAMe,cAAA;EACf,MAAA,EAAQ,MAAA;EACR,OAAA,EAAS,WAAA;EACT,IAAA;EACA,IAAA,EAAM,cAAA;AAAA;;;;;UAOS,gBAAA;EACf,EAAA;EACA,GAAA;EACA,GAAA;AAAA;;;;KAMU,aAAA;EAEN,IAAA;EACA,OAAA,EACI,eAAA,GACA,qBAAA,GACA,mBAAA,GACA,sBAAA,GACA,eAAA;AAAA;EAEJ,IAAA;EAAsB,IAAA;AAAA;EACtB,IAAA;EAA0B,IAAA;AAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/vite-plugin-upstart-editor/runtime/types.ts"],"mappings":";;;;;;AAeA;;;;KAAY,UAAA;AAOZ;;;;;AAAA,UAAiB,YAAA;EACf,GAAA;EACA,IAAA;EACA,QAAA;EACA,aAAA;EACA,QAAA;EACA,IAAA;EAMS;AAWX;;;;EAXE,SAAA;AAAA;;;;;;;;;KAWU,cAAA;;;AAiBZ;UAZiB,aAAA;EACf,GAAA;EACA,IAAA;EACA,KAAA;EACA,MAAA;EACA,KAAA;EACA,MAAA;AAAA;;;;UAMe,cAAA;EACf,MAAA,EAAQ,MAAA;EACR,OAAA,EAAS,WAAA;EACT,IAAA;EACA,IAAA,EAAM,cAAA;AAAA;;;;;UAOS,gBAAA;EACf,EAAA;EACA,GAAA;EACA,GAAA;AAAA;;;;KAMU,aAAA;EAEN,IAAA;EACA,OAAA,EACI,eAAA,GACA,qBAAA,GACA,mBAAA,GACA,sBAAA,GACA,eAAA;AAAA;EAEJ,IAAA;EAAsB,IAAA;AAAA;EACtB,IAAA;EAA0B,IAAA;AAAA;EAE1B,IAAA;EAAsB,OAAA;AAAA;EACtB,IAAA;EAAyB,CAAA;EAAW,CAAA;AAAA;EACpC,IAAA;EAAsB,KAAA;AAAA;EACtB,IAAA;EAA2B,SAAA,EAAW,YAAA;AAAA;EAEtC,IAAA;EACA,IAAA;EACA,aAAA;EACA,QAAA;EACA,gBAAA;EACA,WAAA;EACA,YAAA;EACA,QAAA;EACA,WAAA,GAAc,MAAA;EACd,MAAA,EAAQ,aAAA;EACR,aAAA,WALA;EAOA,MAAA,GAAS,gBAAA;AAAA;;;;KAMH,aAAA;EACN,IAAA;EAAkB,IAAA,EAAM,UAAA;AAAA;EACxB,IAAA;EAA2B,WAAA;EAAqB,SAAA;EAAmB,UAAA;AAAA;EACnE,IAAA;EAAuB,OAAA;EAAiB,GAAA;AAAA;EACxC,IAAA;AAAA;EACA,IAAA;EAAiC,CAAA;EAAW,CAAA;AAAA;EAC5C,IAAA;AAAA;EACA,IAAA;EAAkB,GAAA;AAAA;;;;UAKP,oBAAA;EACf,MAAA;EACA,IAAA,EAAM,aAAA;EAAA,CACL,GAAA;AAAA;;;;UAMc,oBAAA;EACf,MAAA;EACA,IAAA,EAAM,aAAA;EAAA,CACL,GAAA;AAAA;;;;UAMc,oBAAA;EAPf;;;;EAYA,gBAAA;EALe;;;;;EAYf,sBAAA;EAMA;;;;EAAA,iBAAA;EAyBsB;;;;EAnBtB,UAAA;EAyByC;;;;EAnBzC,WAAA;;;;;EAMA,aAAA;;;;;;EAOA,kBAAA,IAAsB,SAAA,UAAmB,GAAA;AAAA;;;;UAM1B,0BAAA;;;;;EAKf,OAAA;;;;;EAMA,UAAA;AAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upstart.gg/vite-plugins",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.62",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"oxc-parser": "0.101.0",
|
|
24
24
|
"unplugin": "^2.3.11",
|
|
25
25
|
"zimmerframe": "^1.1.4",
|
|
26
|
-
"@upstart.gg/sdk": "^0.1.
|
|
26
|
+
"@upstart.gg/sdk": "^0.1.62"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@rolldown/binding-linux-arm64-gnu": "1.0.0",
|
|
@@ -109,11 +109,16 @@
|
|
|
109
109
|
"import": "./dist/vite-plugin-upstart-theme.js",
|
|
110
110
|
"types": "./dist/vite-plugin-upstart-theme.d.ts",
|
|
111
111
|
"bun": "./src/vite-plugin-upstart-theme.ts"
|
|
112
|
+
},
|
|
113
|
+
"./site-meta": {
|
|
114
|
+
"import": "./dist/site-meta.js",
|
|
115
|
+
"types": "./dist/site-meta.d.ts",
|
|
116
|
+
"bun": "./src/site-meta.ts"
|
|
112
117
|
}
|
|
113
118
|
},
|
|
114
119
|
"peerDependencies": {
|
|
115
120
|
"zod": "4.3.6",
|
|
116
|
-
"@upstart.gg/sdk": "^0.1.
|
|
121
|
+
"@upstart.gg/sdk": "^0.1.62"
|
|
117
122
|
},
|
|
118
123
|
"author": "Upstart",
|
|
119
124
|
"publishConfig": {
|