@moraya/core 0.1.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 (58) hide show
  1. package/CHANGELOG.md +344 -0
  2. package/LICENSE +85 -0
  3. package/README.md +82 -0
  4. package/dist/adapters/browser-media-resolver.d.ts +21 -0
  5. package/dist/adapters/browser-media-resolver.js +24 -0
  6. package/dist/adapters/browser-media-resolver.js.map +1 -0
  7. package/dist/commands.d.ts +35 -0
  8. package/dist/commands.js +976 -0
  9. package/dist/commands.js.map +1 -0
  10. package/dist/doc-cache.d.ts +29 -0
  11. package/dist/doc-cache.js +50 -0
  12. package/dist/doc-cache.js.map +1 -0
  13. package/dist/index.d.ts +10 -0
  14. package/dist/index.js +4534 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/markdown.d.ts +46 -0
  17. package/dist/markdown.js +1553 -0
  18. package/dist/markdown.js.map +1 -0
  19. package/dist/plugins/code-block-view.d.ts +52 -0
  20. package/dist/plugins/code-block-view.js +686 -0
  21. package/dist/plugins/code-block-view.js.map +1 -0
  22. package/dist/plugins/cursor-syntax.d.ts +27 -0
  23. package/dist/plugins/cursor-syntax.js +122 -0
  24. package/dist/plugins/cursor-syntax.js.map +1 -0
  25. package/dist/plugins/definition-list.d.ts +23 -0
  26. package/dist/plugins/definition-list.js +12 -0
  27. package/dist/plugins/definition-list.js.map +1 -0
  28. package/dist/plugins/editor-props-plugin.d.ts +36 -0
  29. package/dist/plugins/editor-props-plugin.js +1963 -0
  30. package/dist/plugins/editor-props-plugin.js.map +1 -0
  31. package/dist/plugins/emoji.d.ts +21 -0
  32. package/dist/plugins/emoji.js +42 -0
  33. package/dist/plugins/emoji.js.map +1 -0
  34. package/dist/plugins/enter-handler.d.ts +26 -0
  35. package/dist/plugins/enter-handler.js +193 -0
  36. package/dist/plugins/enter-handler.js.map +1 -0
  37. package/dist/plugins/highlight.d.ts +39 -0
  38. package/dist/plugins/highlight.js +283 -0
  39. package/dist/plugins/highlight.js.map +1 -0
  40. package/dist/plugins/inline-code-convert.d.ts +32 -0
  41. package/dist/plugins/inline-code-convert.js +173 -0
  42. package/dist/plugins/inline-code-convert.js.map +1 -0
  43. package/dist/plugins/link-text-plugin.d.ts +22 -0
  44. package/dist/plugins/link-text-plugin.js +194 -0
  45. package/dist/plugins/link-text-plugin.js.map +1 -0
  46. package/dist/plugins/mermaid-renderer.d.ts +24 -0
  47. package/dist/plugins/mermaid-renderer.js +80 -0
  48. package/dist/plugins/mermaid-renderer.js.map +1 -0
  49. package/dist/schema.d.ts +48 -0
  50. package/dist/schema.js +847 -0
  51. package/dist/schema.js.map +1 -0
  52. package/dist/setup.d.ts +104 -0
  53. package/dist/setup.js +4393 -0
  54. package/dist/setup.js.map +1 -0
  55. package/dist/types.d.ts +107 -0
  56. package/dist/types.js +10 -0
  57. package/dist/types.js.map +1 -0
  58. package/package.json +121 -0
@@ -0,0 +1,686 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res) => function __init() {
4
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
+ };
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+
11
+ // src/plugins/mermaid-renderer.ts
12
+ var mermaid_renderer_exports = {};
13
+ __export(mermaid_renderer_exports, {
14
+ ensureMermaidLoaded: () => ensureMermaidLoaded,
15
+ renderMermaid: () => renderMermaid,
16
+ updateMermaidTheme: () => updateMermaidTheme
17
+ });
18
+ function isDark() {
19
+ if (typeof document === "undefined") return false;
20
+ const dt = document.documentElement.getAttribute("data-theme");
21
+ if (dt === "dark") return true;
22
+ if (dt === "light") return false;
23
+ if (typeof window === "undefined" || !window.matchMedia) return false;
24
+ return window.matchMedia("(prefers-color-scheme: dark)").matches;
25
+ }
26
+ function resolveThemeColors() {
27
+ if (typeof document === "undefined" || typeof getComputedStyle === "undefined") {
28
+ return {
29
+ primaryColor: "#4a90d9",
30
+ primaryTextColor: "#333",
31
+ primaryBorderColor: "#ccc",
32
+ lineColor: "#666",
33
+ secondaryColor: "#f5f5f5",
34
+ tertiaryColor: "#eee"
35
+ };
36
+ }
37
+ const s = getComputedStyle(document.documentElement);
38
+ return {
39
+ primaryColor: s.getPropertyValue("--accent-color").trim() || "#4a90d9",
40
+ primaryTextColor: s.getPropertyValue("--text-primary").trim() || "#333",
41
+ primaryBorderColor: s.getPropertyValue("--border-color").trim() || "#ccc",
42
+ lineColor: s.getPropertyValue("--text-secondary").trim() || "#666",
43
+ secondaryColor: s.getPropertyValue("--bg-secondary").trim() || "#f5f5f5",
44
+ tertiaryColor: s.getPropertyValue("--bg-hover").trim() || "#eee"
45
+ };
46
+ }
47
+ async function ensureMermaidLoaded() {
48
+ if (mermaidModule) return;
49
+ if (loadingPromise) return loadingPromise;
50
+ loadingPromise = (async () => {
51
+ const mod = await import(
52
+ /* @vite-ignore */
53
+ "mermaid"
54
+ );
55
+ mermaidModule = mod.default;
56
+ mermaidModule.initialize({
57
+ startOnLoad: false,
58
+ theme: isDark() ? "dark" : "default",
59
+ themeVariables: resolveThemeColors()
60
+ });
61
+ })();
62
+ return loadingPromise;
63
+ }
64
+ async function renderMermaid(code) {
65
+ await ensureMermaidLoaded();
66
+ const result = new Promise((resolve) => {
67
+ renderQueue = renderQueue.then(async () => {
68
+ const id = `mermaid-${++renderCounter}`;
69
+ try {
70
+ const { svg } = await mermaidModule.render(id, code);
71
+ resolve({ svg });
72
+ } catch (e) {
73
+ resolve({ error: e instanceof Error ? e.message : "Render failed" });
74
+ }
75
+ });
76
+ });
77
+ return result;
78
+ }
79
+ function updateMermaidTheme() {
80
+ if (!mermaidModule) return;
81
+ mermaidModule.initialize({
82
+ startOnLoad: false,
83
+ theme: isDark() ? "dark" : "default",
84
+ themeVariables: resolveThemeColors()
85
+ });
86
+ }
87
+ var mermaidModule, loadingPromise, renderCounter, renderQueue;
88
+ var init_mermaid_renderer = __esm({
89
+ "src/plugins/mermaid-renderer.ts"() {
90
+ "use strict";
91
+ mermaidModule = null;
92
+ loadingPromise = null;
93
+ renderCounter = 0;
94
+ renderQueue = Promise.resolve();
95
+ }
96
+ });
97
+
98
+ // src/plugins/code-block-view.ts
99
+ var mermaidApi = null;
100
+ var mermaidLoading = null;
101
+ function loadMermaidApi() {
102
+ if (mermaidApi) return Promise.resolve(mermaidApi);
103
+ if (mermaidLoading) return mermaidLoading;
104
+ mermaidLoading = Promise.resolve().then(() => (init_mermaid_renderer(), mermaid_renderer_exports)).then((mod) => {
105
+ mermaidApi = mod;
106
+ return mermaidApi;
107
+ });
108
+ return mermaidLoading;
109
+ }
110
+ var themeObserverInstalled = false;
111
+ var mermaidReRenderCallbacks = /* @__PURE__ */ new Set();
112
+ function installThemeObserver() {
113
+ if (themeObserverInstalled) return;
114
+ themeObserverInstalled = true;
115
+ if (typeof document === "undefined" || typeof MutationObserver === "undefined") return;
116
+ const observer = new MutationObserver(() => {
117
+ if (mermaidApi) mermaidApi.updateMermaidTheme();
118
+ for (const cb of mermaidReRenderCallbacks) cb();
119
+ });
120
+ observer.observe(document.documentElement, {
121
+ attributes: true,
122
+ attributeFilter: ["data-theme"]
123
+ });
124
+ }
125
+ var POPULAR_LANGUAGES = [
126
+ { id: "javascript", label: "JavaScript", aliases: ["js"] },
127
+ { id: "typescript", label: "TypeScript", aliases: ["ts"] },
128
+ { id: "python", label: "Python", aliases: ["py"] },
129
+ { id: "java", label: "Java", aliases: [] },
130
+ { id: "go", label: "Go", aliases: ["golang"] },
131
+ { id: "rust", label: "Rust", aliases: ["rs"] },
132
+ { id: "c", label: "C", aliases: [] },
133
+ { id: "cpp", label: "C++", aliases: ["c++"] },
134
+ { id: "ruby", label: "Ruby", aliases: ["rb"] },
135
+ { id: "php", label: "PHP", aliases: [] },
136
+ { id: "swift", label: "Swift", aliases: [] },
137
+ { id: "kotlin", label: "Kotlin", aliases: ["kt"] },
138
+ { id: "sql", label: "SQL", aliases: [] },
139
+ { id: "bash", label: "Bash", aliases: ["sh", "shell"] },
140
+ { id: "json", label: "JSON", aliases: [] },
141
+ { id: "yaml", label: "YAML", aliases: ["yml"] },
142
+ { id: "html", label: "HTML", aliases: ["xml"] },
143
+ { id: "css", label: "CSS", aliases: [] },
144
+ { id: "csharp", label: "C#", aliases: ["cs"] },
145
+ { id: "dart", label: "Dart", aliases: [] },
146
+ { id: "r", label: "R", aliases: [] },
147
+ { id: "dockerfile", label: "Dockerfile", aliases: ["docker"] },
148
+ { id: "graphql", label: "GraphQL", aliases: ["gql"] },
149
+ { id: "markdown", label: "Markdown", aliases: ["md"] },
150
+ { id: "text", label: "Plain Text", aliases: ["plaintext", "txt"] },
151
+ { id: "prompt", label: "Prompt", aliases: ["image-prompts", "image-prompt"] },
152
+ { id: "system", label: "System Prompt", aliases: ["system-prompt"] }
153
+ ];
154
+ var BASE_OTHER_LANGUAGES = [
155
+ { id: "scss", label: "SCSS", aliases: [] },
156
+ { id: "lua", label: "Lua", aliases: [] },
157
+ { id: "diff", label: "Diff", aliases: [] },
158
+ { id: "perl", label: "Perl", aliases: ["pl"] },
159
+ { id: "scala", label: "Scala", aliases: [] },
160
+ { id: "objectivec", label: "Objective-C", aliases: ["objc"] },
161
+ { id: "ini", label: "TOML / INI", aliases: ["toml"] },
162
+ { id: "powershell", label: "PowerShell", aliases: ["ps", "ps1"] },
163
+ { id: "makefile", label: "Makefile", aliases: ["make"] },
164
+ { id: "groovy", label: "Groovy", aliases: [] },
165
+ { id: "elixir", label: "Elixir", aliases: ["ex"] },
166
+ { id: "haskell", label: "Haskell", aliases: ["hs"] },
167
+ { id: "protobuf", label: "Protobuf", aliases: ["proto"] },
168
+ { id: "latex", label: "LaTeX", aliases: ["tex"] },
169
+ { id: "nginx", label: "Nginx", aliases: ["nginxconf"] },
170
+ { id: "shell", label: "Shell Session", aliases: [] },
171
+ { id: "mermaid", label: "Mermaid", aliases: [] }
172
+ ];
173
+ var POPULAR_IDS = new Set(POPULAR_LANGUAGES.map((l) => l.id));
174
+ function buildLanguageLists(registry) {
175
+ const rendererLangIds = registry ? new Set(Object.keys(registry.versions)) : /* @__PURE__ */ new Set();
176
+ const rendererPlugins = registry ? Object.keys(registry.versions).sort().map((id) => ({
177
+ id,
178
+ label: id.charAt(0).toUpperCase() + id.slice(1),
179
+ aliases: []
180
+ })) : [];
181
+ const all = [
182
+ ...POPULAR_LANGUAGES,
183
+ ...BASE_OTHER_LANGUAGES,
184
+ ...rendererPlugins
185
+ ].sort((a, b) => a.label.localeCompare(b.label));
186
+ return { popular: POPULAR_LANGUAGES, rendererPlugins, all, rendererLangIds };
187
+ }
188
+ function findLanguageLabel(langId, all) {
189
+ if (!langId) return "text";
190
+ const entry = all.find(
191
+ (l) => l.id === langId || l.aliases.includes(langId)
192
+ );
193
+ return entry ? entry.label : langId;
194
+ }
195
+ var hljsAutoDetect = null;
196
+ async function getAutoDetect() {
197
+ if (hljsAutoDetect) return hljsAutoDetect;
198
+ try {
199
+ const hljs = (await import("highlight.js/lib/core")).default;
200
+ hljsAutoDetect = (code) => {
201
+ if (!code.trim() || code.length < 10) return null;
202
+ try {
203
+ const result = hljs.highlightAuto(code);
204
+ if (result.language && result.relevance > 5) {
205
+ return result.language;
206
+ }
207
+ } catch {
208
+ }
209
+ return null;
210
+ };
211
+ } catch {
212
+ hljsAutoDetect = () => null;
213
+ }
214
+ return hljsAutoDetect;
215
+ }
216
+ function createLanguagePicker(container, anchor, currentLang, codeContent, langLists, onSelect, onDismiss) {
217
+ const { popular, rendererPlugins, all } = langLists;
218
+ const picker = document.createElement("div");
219
+ picker.className = "code-lang-picker";
220
+ picker.setAttribute("contenteditable", "false");
221
+ picker.addEventListener("mousedown", (e) => {
222
+ e.stopPropagation();
223
+ });
224
+ picker.addEventListener("click", (e) => {
225
+ e.stopPropagation();
226
+ });
227
+ const searchWrap = document.createElement("div");
228
+ searchWrap.className = "code-lang-search";
229
+ const searchInput = document.createElement("input");
230
+ searchInput.type = "text";
231
+ searchInput.className = "code-lang-search-input";
232
+ searchInput.placeholder = "Search language...";
233
+ searchInput.autocomplete = "off";
234
+ searchInput.setAttribute("autocorrect", "off");
235
+ searchInput.setAttribute("autocapitalize", "off");
236
+ searchInput.spellcheck = false;
237
+ searchWrap.appendChild(searchInput);
238
+ picker.appendChild(searchWrap);
239
+ const listEl = document.createElement("div");
240
+ listEl.className = "code-lang-list";
241
+ picker.appendChild(listEl);
242
+ let detectedLang = null;
243
+ function renderList(filter) {
244
+ listEl.innerHTML = "";
245
+ const lowerFilter = filter.toLowerCase();
246
+ const matchesFilter = (entry) => {
247
+ if (!lowerFilter) return true;
248
+ return entry.id.includes(lowerFilter) || entry.label.toLowerCase().includes(lowerFilter) || entry.aliases.some((a) => a.includes(lowerFilter));
249
+ };
250
+ if (detectedLang && !lowerFilter && detectedLang !== currentLang) {
251
+ const label = findLanguageLabel(detectedLang, all);
252
+ const suggestEl = document.createElement("div");
253
+ suggestEl.className = "code-lang-suggestion";
254
+ suggestEl.innerHTML = `<span class="suggestion-icon">\u2726</span> ${label} <span class="suggestion-hint">detected</span>`;
255
+ suggestEl.addEventListener("mousedown", (e) => {
256
+ e.preventDefault();
257
+ e.stopPropagation();
258
+ onSelect(detectedLang);
259
+ destroy();
260
+ });
261
+ listEl.appendChild(suggestEl);
262
+ const divider = document.createElement("div");
263
+ divider.className = "code-lang-divider";
264
+ listEl.appendChild(divider);
265
+ }
266
+ const popularMatches = popular.filter(matchesFilter);
267
+ if (popularMatches.length > 0 && !lowerFilter) {
268
+ const groupLabel = document.createElement("div");
269
+ groupLabel.className = "code-lang-group-label";
270
+ groupLabel.textContent = "Popular";
271
+ listEl.appendChild(groupLabel);
272
+ for (const lang of popularMatches) {
273
+ listEl.appendChild(createOption(lang));
274
+ }
275
+ const rendererIds = new Set(rendererPlugins.map((l) => l.id));
276
+ const others = all.filter(
277
+ (l) => !POPULAR_IDS.has(l.id) && !rendererIds.has(l.id) && matchesFilter(l)
278
+ );
279
+ if (others.length > 0) {
280
+ const divider = document.createElement("div");
281
+ divider.className = "code-lang-divider";
282
+ listEl.appendChild(divider);
283
+ const allLabel = document.createElement("div");
284
+ allLabel.className = "code-lang-group-label";
285
+ allLabel.textContent = "All";
286
+ listEl.appendChild(allLabel);
287
+ for (const lang of others) {
288
+ listEl.appendChild(createOption(lang));
289
+ }
290
+ }
291
+ const rendererMatches = rendererPlugins.filter(matchesFilter);
292
+ if (rendererMatches.length > 0) {
293
+ const divider2 = document.createElement("div");
294
+ divider2.className = "code-lang-divider";
295
+ listEl.appendChild(divider2);
296
+ const rendererLabel = document.createElement("div");
297
+ rendererLabel.className = "code-lang-group-label";
298
+ rendererLabel.textContent = "Renderer Plugins";
299
+ listEl.appendChild(rendererLabel);
300
+ for (const lang of rendererMatches) {
301
+ listEl.appendChild(createOption(lang));
302
+ }
303
+ }
304
+ } else {
305
+ const matches = all.filter(matchesFilter);
306
+ for (const lang of matches) {
307
+ listEl.appendChild(createOption(lang));
308
+ }
309
+ if (matches.length === 0) {
310
+ const empty = document.createElement("div");
311
+ empty.className = "code-lang-empty";
312
+ empty.textContent = "No matches";
313
+ listEl.appendChild(empty);
314
+ }
315
+ }
316
+ }
317
+ function createOption(lang) {
318
+ const option = document.createElement("div");
319
+ option.className = "code-lang-option";
320
+ if (lang.id === currentLang) option.classList.add("selected");
321
+ option.textContent = lang.label;
322
+ option.addEventListener("mousedown", (e) => {
323
+ e.preventDefault();
324
+ e.stopPropagation();
325
+ onSelect(lang.id);
326
+ destroy();
327
+ });
328
+ return option;
329
+ }
330
+ renderList("");
331
+ searchInput.addEventListener("input", () => {
332
+ renderList(searchInput.value);
333
+ });
334
+ searchInput.addEventListener("keydown", (e) => {
335
+ e.stopPropagation();
336
+ if (e.key === "Escape") {
337
+ destroy();
338
+ }
339
+ });
340
+ const pickerHost = container.closest(".editor-wrapper") ?? document.body;
341
+ pickerHost.appendChild(picker);
342
+ (function positionPicker() {
343
+ const rect = anchor.getBoundingClientRect();
344
+ picker.style.position = "fixed";
345
+ picker.style.top = `${rect.bottom + 2}px`;
346
+ picker.style.left = `${rect.left}px`;
347
+ })();
348
+ requestAnimationFrame(() => searchInput.focus());
349
+ getAutoDetect().then((detect) => {
350
+ detectedLang = detect(codeContent);
351
+ if (detectedLang && !searchInput.value) {
352
+ renderList("");
353
+ }
354
+ });
355
+ function handleOutsideClick(e) {
356
+ if (!picker.contains(e.target) && !anchor.contains(e.target)) {
357
+ destroy();
358
+ }
359
+ }
360
+ function handleKeydown(e) {
361
+ if (e.key === "Escape") {
362
+ destroy();
363
+ }
364
+ }
365
+ setTimeout(() => {
366
+ document.addEventListener("mousedown", handleOutsideClick);
367
+ document.addEventListener("keydown", handleKeydown, true);
368
+ }, 0);
369
+ function destroy() {
370
+ document.removeEventListener("mousedown", handleOutsideClick);
371
+ document.removeEventListener("keydown", handleKeydown, true);
372
+ picker.remove();
373
+ onDismiss?.();
374
+ }
375
+ return { destroy };
376
+ }
377
+ function escapeText(str) {
378
+ const d = document.createElement("div");
379
+ d.textContent = str;
380
+ return d.innerHTML;
381
+ }
382
+ function handleCopy(btn, codeEl) {
383
+ const text = codeEl.textContent || "";
384
+ navigator.clipboard.writeText(text).then(() => {
385
+ btn.classList.add("copied");
386
+ btn.title = "Copied!";
387
+ setTimeout(() => {
388
+ btn.classList.remove("copied");
389
+ btn.title = "Copy";
390
+ }, 1500);
391
+ });
392
+ }
393
+ function createCodeBlockNodeViewFactory(opts = {}) {
394
+ const { rendererRegistry } = opts;
395
+ const langLists = buildLanguageLists(rendererRegistry);
396
+ const { rendererLangIds, all: allLanguages } = langLists;
397
+ return function createCodeBlockNodeView(nodeArg, view, getPos) {
398
+ let node = nodeArg;
399
+ const wrapper = document.createElement("div");
400
+ wrapper.className = "code-block-wrapper";
401
+ const toolbar = document.createElement("div");
402
+ toolbar.className = "code-block-toolbar";
403
+ toolbar.setAttribute("contenteditable", "false");
404
+ const langLabel = document.createElement("span");
405
+ langLabel.className = "code-lang-label";
406
+ langLabel.textContent = findLanguageLabel(node.attrs.language || "", allLanguages);
407
+ langLabel.title = "Change language";
408
+ const toggleBtn = document.createElement("button");
409
+ toggleBtn.className = "mermaid-toggle-btn";
410
+ toggleBtn.type = "button";
411
+ const copyBtn = document.createElement("button");
412
+ copyBtn.className = "code-copy-btn";
413
+ copyBtn.title = "Copy";
414
+ copyBtn.type = "button";
415
+ copyBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg><svg class="check-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6L9 17l-5-5"/></svg>';
416
+ const toolbarRight = document.createElement("div");
417
+ toolbarRight.className = "code-toolbar-right";
418
+ toolbarRight.appendChild(toggleBtn);
419
+ toolbarRight.appendChild(copyBtn);
420
+ toolbar.appendChild(langLabel);
421
+ toolbar.appendChild(toolbarRight);
422
+ const pre = document.createElement("pre");
423
+ pre.className = "code-block-pre";
424
+ const code = document.createElement("code");
425
+ code.className = "code-block-code";
426
+ pre.appendChild(code);
427
+ const mermaidPreview = document.createElement("div");
428
+ mermaidPreview.className = "mermaid-preview";
429
+ mermaidPreview.setAttribute("contenteditable", "false");
430
+ mermaidPreview.style.display = "none";
431
+ const rendererPreview = document.createElement("div");
432
+ rendererPreview.className = "renderer-preview";
433
+ rendererPreview.setAttribute("contenteditable", "false");
434
+ rendererPreview.style.display = "none";
435
+ wrapper.appendChild(toolbar);
436
+ wrapper.appendChild(pre);
437
+ wrapper.appendChild(mermaidPreview);
438
+ wrapper.appendChild(rendererPreview);
439
+ let isEditing = false;
440
+ let isMermaid = node.attrs.language === "mermaid";
441
+ let lastRenderedCode = "";
442
+ let renderTimer = null;
443
+ let isRenderer = rendererLangIds.has(node.attrs.language || "");
444
+ let rendererEditing = false;
445
+ let lastRendererCode = "";
446
+ let rendererTimer = null;
447
+ let currentRendererModule = null;
448
+ function syncMermaidMode() {
449
+ const showPreview = isMermaid && !isEditing;
450
+ pre.style.display = showPreview || isRenderer && !rendererEditing ? "none" : "";
451
+ mermaidPreview.style.display = showPreview ? "flex" : "none";
452
+ toggleBtn.style.display = isMermaid || isRenderer ? "inline-flex" : "none";
453
+ wrapper.classList.toggle("mermaid-preview-mode", showPreview);
454
+ if (isMermaid) {
455
+ toggleBtn.textContent = isEditing ? "\u{1F441} Preview" : "\u270F\uFE0F Edit";
456
+ if (showPreview) triggerMermaidRender();
457
+ }
458
+ }
459
+ function triggerMermaidRender() {
460
+ const codeText = code.textContent || "";
461
+ if (!codeText.trim()) {
462
+ mermaidPreview.innerHTML = '<div class="mermaid-empty">Empty diagram</div>';
463
+ lastRenderedCode = "";
464
+ return;
465
+ }
466
+ if (codeText === lastRenderedCode) return;
467
+ lastRenderedCode = codeText;
468
+ if (renderTimer) clearTimeout(renderTimer);
469
+ renderTimer = setTimeout(async () => {
470
+ mermaidPreview.innerHTML = '<div class="mermaid-loading"><div class="mermaid-spinner"></div>Loading diagram...</div>';
471
+ try {
472
+ const api = await loadMermaidApi();
473
+ if (!api) return;
474
+ const result = await api.renderMermaid(codeText);
475
+ if (code.textContent !== codeText) return;
476
+ if ("svg" in result) {
477
+ mermaidPreview.innerHTML = result.svg;
478
+ } else {
479
+ mermaidPreview.innerHTML = `<div class="mermaid-error">${escapeText(result.error)}</div>`;
480
+ }
481
+ } catch {
482
+ mermaidPreview.innerHTML = '<div class="mermaid-error">Render failed</div>';
483
+ }
484
+ }, 150);
485
+ }
486
+ function syncRendererMode() {
487
+ const showPreview = isRenderer && !rendererEditing;
488
+ pre.style.display = showPreview || isMermaid && !isEditing ? "none" : "";
489
+ rendererPreview.style.display = showPreview ? "block" : "none";
490
+ toggleBtn.style.display = isMermaid || isRenderer ? "inline-flex" : "none";
491
+ wrapper.classList.toggle("renderer-preview-mode", showPreview);
492
+ if (isRenderer) {
493
+ toggleBtn.textContent = rendererEditing ? "\u{1F441} Preview" : "\u270F\uFE0F Edit";
494
+ if (showPreview) triggerRendererRender();
495
+ }
496
+ }
497
+ function triggerRendererRender() {
498
+ const source = code.textContent || "";
499
+ const lang = node.attrs.language || "";
500
+ if (!rendererRegistry || !rendererRegistry.has(lang)) return;
501
+ if (!source.trim()) {
502
+ rendererPreview.innerHTML = '<div class="renderer-empty">Empty block</div>';
503
+ lastRendererCode = "";
504
+ return;
505
+ }
506
+ if (source === lastRendererCode) return;
507
+ lastRendererCode = source;
508
+ if (rendererTimer) clearTimeout(rendererTimer);
509
+ rendererTimer = setTimeout(async () => {
510
+ rendererPreview.innerHTML = '<div class="renderer-loading"><div class="renderer-spinner"></div>Rendering...</div>';
511
+ try {
512
+ const module = await rendererRegistry.load(lang);
513
+ if (code.textContent !== source) return;
514
+ if (currentRendererModule?.destroy) {
515
+ try {
516
+ currentRendererModule.destroy(rendererPreview);
517
+ } catch {
518
+ }
519
+ }
520
+ currentRendererModule = module;
521
+ rendererPreview.innerHTML = "";
522
+ try {
523
+ await module.render(source, rendererPreview);
524
+ } catch (e) {
525
+ rendererPreview.innerHTML = `<div class="renderer-error" data-language="${escapeText(lang)}" data-error="${escapeText(String(e))}">[Renderer ${escapeText(lang)} failed]</div>`;
526
+ }
527
+ } catch (e) {
528
+ rendererPreview.innerHTML = `<div class="renderer-error" data-language="${escapeText(lang)}" data-error="${escapeText(String(e))}">[Renderer ${escapeText(lang)} failed]</div>`;
529
+ }
530
+ }, 150);
531
+ }
532
+ function onThemeChange() {
533
+ if (isMermaid && !isEditing) {
534
+ lastRenderedCode = "";
535
+ triggerMermaidRender();
536
+ }
537
+ }
538
+ if (isMermaid) {
539
+ installThemeObserver();
540
+ mermaidReRenderCallbacks.add(onThemeChange);
541
+ requestAnimationFrame(() => syncMermaidMode());
542
+ } else if (isRenderer) {
543
+ syncRendererMode();
544
+ requestAnimationFrame(() => syncRendererMode());
545
+ } else {
546
+ syncMermaidMode();
547
+ }
548
+ let activePicker = null;
549
+ langLabel.addEventListener("mousedown", (e) => {
550
+ e.preventDefault();
551
+ e.stopPropagation();
552
+ if (activePicker) {
553
+ activePicker.destroy();
554
+ activePicker = null;
555
+ wrapper.classList.remove("picker-open");
556
+ return;
557
+ }
558
+ const currentLang = node.attrs.language || "";
559
+ const codeContent = code.textContent || "";
560
+ wrapper.classList.add("picker-open");
561
+ activePicker = createLanguagePicker(
562
+ wrapper,
563
+ langLabel,
564
+ currentLang,
565
+ codeContent,
566
+ langLists,
567
+ (newLang) => {
568
+ activePicker = null;
569
+ wrapper.classList.remove("picker-open");
570
+ const pos = getPos();
571
+ if (pos === void 0) return;
572
+ view.dispatch(
573
+ view.state.tr.setNodeMarkup(pos, void 0, {
574
+ ...node.attrs,
575
+ language: newLang
576
+ })
577
+ );
578
+ view.focus();
579
+ },
580
+ () => {
581
+ activePicker = null;
582
+ wrapper.classList.remove("picker-open");
583
+ }
584
+ );
585
+ });
586
+ toggleBtn.addEventListener("mousedown", (e) => {
587
+ e.preventDefault();
588
+ e.stopPropagation();
589
+ if (isMermaid) {
590
+ isEditing = !isEditing;
591
+ syncMermaidMode();
592
+ } else if (isRenderer) {
593
+ rendererEditing = !rendererEditing;
594
+ syncRendererMode();
595
+ }
596
+ if (isEditing || rendererEditing) view.focus();
597
+ });
598
+ mermaidPreview.addEventListener("mousedown", (e) => {
599
+ e.preventDefault();
600
+ e.stopPropagation();
601
+ isEditing = true;
602
+ syncMermaidMode();
603
+ view.focus();
604
+ });
605
+ copyBtn.addEventListener("mousedown", (e) => {
606
+ e.preventDefault();
607
+ e.stopPropagation();
608
+ handleCopy(copyBtn, code);
609
+ });
610
+ return {
611
+ dom: wrapper,
612
+ contentDOM: code,
613
+ stopEvent(event) {
614
+ const target = event.target;
615
+ return !code.contains(target) && wrapper.contains(target) && target !== code;
616
+ },
617
+ ignoreMutation(mutation) {
618
+ return !code.contains(mutation.target);
619
+ },
620
+ update(updatedNode) {
621
+ if (updatedNode.type.name !== "code_block") return false;
622
+ node = updatedNode;
623
+ langLabel.textContent = findLanguageLabel(updatedNode.attrs.language || "", allLanguages);
624
+ const wasMermaid = isMermaid;
625
+ isMermaid = updatedNode.attrs.language === "mermaid";
626
+ if (isMermaid !== wasMermaid) {
627
+ isEditing = false;
628
+ if (isMermaid) {
629
+ installThemeObserver();
630
+ mermaidReRenderCallbacks.add(onThemeChange);
631
+ } else {
632
+ mermaidReRenderCallbacks.delete(onThemeChange);
633
+ }
634
+ }
635
+ const wasRenderer = isRenderer;
636
+ isRenderer = rendererLangIds.has(updatedNode.attrs.language || "");
637
+ if (isRenderer !== wasRenderer) {
638
+ rendererEditing = false;
639
+ lastRendererCode = "";
640
+ rendererPreview.innerHTML = "";
641
+ if (!isRenderer && currentRendererModule?.destroy) {
642
+ try {
643
+ currentRendererModule.destroy(rendererPreview);
644
+ } catch {
645
+ }
646
+ currentRendererModule = null;
647
+ }
648
+ }
649
+ if (isRenderer) {
650
+ syncRendererMode();
651
+ } else {
652
+ rendererPreview.style.display = "none";
653
+ wrapper.classList.remove("renderer-preview-mode");
654
+ syncMermaidMode();
655
+ }
656
+ return true;
657
+ },
658
+ selectNode() {
659
+ wrapper.classList.add("ProseMirror-selectednode");
660
+ },
661
+ deselectNode() {
662
+ wrapper.classList.remove("ProseMirror-selectednode");
663
+ },
664
+ destroy() {
665
+ if (activePicker) {
666
+ activePicker.destroy();
667
+ activePicker = null;
668
+ }
669
+ if (renderTimer) clearTimeout(renderTimer);
670
+ if (rendererTimer) clearTimeout(rendererTimer);
671
+ if (currentRendererModule?.destroy) {
672
+ try {
673
+ currentRendererModule.destroy(rendererPreview);
674
+ } catch {
675
+ }
676
+ }
677
+ currentRendererModule = null;
678
+ mermaidReRenderCallbacks.delete(onThemeChange);
679
+ }
680
+ };
681
+ };
682
+ }
683
+ export {
684
+ createCodeBlockNodeViewFactory
685
+ };
686
+ //# sourceMappingURL=code-block-view.js.map