@filipc77/cowrite 0.6.20 → 0.6.21

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.
@@ -1197,7 +1197,7 @@ function createPreviewServer(store, projectDir, port, initialFile) {
1197
1197
  // bin/cowrite.ts
1198
1198
  import updateNotifier from "update-notifier";
1199
1199
  import "module";
1200
- var version = true ? "0.6.19" : createRequire(import.meta.url)("../package.json").version;
1200
+ var version = true ? "0.6.20" : createRequire(import.meta.url)("../package.json").version;
1201
1201
  var USAGE = `
1202
1202
  cowrite \u2014 Live commenting plugin for coding agent sessions
1203
1203
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@filipc77/cowrite",
3
- "version": "0.6.20",
3
+ "version": "0.6.21",
4
4
  "description": "Live commenting and inline editing plugin for coding agent sessions",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,38 +24,85 @@ function cancelDebouncedSubmit() {
24
24
  }
25
25
 
26
26
  /**
27
- * Render mermaid diagrams in the plain-text container (non-markdown files).
28
- * NEVER modifies ProseMirror DOM injecting elements there corrupts the
29
- * doc model and produces "mermaidCopy" artifacts in the serialized markdown.
27
+ * Render mermaid diagrams.
28
+ * - Plain-text container: modifies DOM directly (safe, not tracked by ProseMirror).
29
+ * - ProseMirror (markdown): renders into an overlay container OUTSIDE the editor
30
+ * to avoid corrupting the doc model. Original code blocks are hidden via CSS.
30
31
  */
31
32
  async function renderMermaidDiagrams() {
32
33
  if (!window.__mermaid) return;
33
34
  const fileContentEl = $('#fileContent');
34
- // Only process plain-text container — never touch ProseMirror DOM
35
- const container = fileContentEl.querySelector('.plain-text-container');
36
- if (!container) return;
37
- const blocks = container.querySelectorAll('pre code.language-mermaid');
38
- if (blocks.length === 0) return;
39
35
 
40
- const containers = [];
41
- for (const code of blocks) {
36
+ // --- Plain-text container (non-markdown files) ---
37
+ const plainContainer = fileContentEl.querySelector('.plain-text-container');
38
+ if (plainContainer) {
39
+ const blocks = plainContainer.querySelectorAll('pre code.language-mermaid');
40
+ const containers = [];
41
+ for (const code of blocks) {
42
+ const pre = code.parentElement;
43
+ if (!pre) continue;
44
+ if (!pre.parentElement?.classList.contains('mermaid-container')) {
45
+ const wrapper = document.createElement('div');
46
+ wrapper.className = 'mermaid-container';
47
+ pre.parentElement.insertBefore(wrapper, pre);
48
+ wrapper.appendChild(pre);
49
+ }
50
+ pre.classList.add('mermaid');
51
+ containers.push(pre);
52
+ }
53
+ if (containers.length > 0) {
54
+ try { await window.__mermaid.run({ nodes: containers }); }
55
+ catch (err) { console.error('Mermaid rendering failed:', err); }
56
+ }
57
+ return;
58
+ }
59
+
60
+ // --- ProseMirror (markdown files) ---
61
+ // Render into an overlay container OUTSIDE ProseMirror to avoid DOM corruption.
62
+ const proseMirror = fileContentEl.querySelector('.ProseMirror');
63
+ if (!proseMirror) return;
64
+
65
+ // Remove old overlay
66
+ const oldOverlay = fileContentEl.querySelector('.mermaid-overlay');
67
+ if (oldOverlay) oldOverlay.remove();
68
+
69
+ const codeBlocks = proseMirror.querySelectorAll('pre code.language-mermaid');
70
+ if (codeBlocks.length === 0) {
71
+ fileContentEl.classList.remove('has-mermaid-overlays');
72
+ return;
73
+ }
74
+
75
+ // Create overlay container as sibling of ProseMirror (not inside it)
76
+ const overlay = document.createElement('div');
77
+ overlay.className = 'mermaid-overlay';
78
+ fileContentEl.appendChild(overlay);
79
+ fileContentEl.classList.add('has-mermaid-overlays');
80
+
81
+ const renderTargets = [];
82
+ for (const code of codeBlocks) {
42
83
  const pre = code.parentElement;
43
84
  if (!pre) continue;
44
- if (!pre.parentElement?.classList.contains('mermaid-container')) {
45
- const wrapper = document.createElement('div');
46
- wrapper.className = 'mermaid-container';
47
- pre.parentElement.insertBefore(wrapper, pre);
48
- wrapper.appendChild(pre);
49
- }
50
- pre.classList.add('mermaid');
51
- containers.push(pre);
85
+
86
+ // Get position of the code block relative to fileContent
87
+ const preRect = pre.getBoundingClientRect();
88
+ const parentRect = fileContentEl.getBoundingClientRect();
89
+ const top = preRect.top - parentRect.top + fileContentEl.scrollTop;
90
+ const left = preRect.left - parentRect.left;
91
+
92
+ const renderDiv = document.createElement('div');
93
+ renderDiv.className = 'mermaid mermaid-overlay-item';
94
+ renderDiv.textContent = code.textContent;
95
+ renderDiv.style.position = 'absolute';
96
+ renderDiv.style.top = `${top}px`;
97
+ renderDiv.style.left = `${left}px`;
98
+ renderDiv.style.width = `${preRect.width}px`;
99
+ overlay.appendChild(renderDiv);
100
+ renderTargets.push(renderDiv);
52
101
  }
53
- if (containers.length === 0) return;
54
102
 
55
- try {
56
- await window.__mermaid.run({ nodes: containers });
57
- } catch (err) {
58
- console.error('Mermaid rendering failed:', err);
103
+ if (renderTargets.length > 0) {
104
+ try { await window.__mermaid.run({ nodes: renderTargets }); }
105
+ catch (err) { console.error('Mermaid rendering failed:', err); }
59
106
  }
60
107
  }
61
108
 
package/ui/styles.css CHANGED
@@ -1160,6 +1160,36 @@ body.sidebar-resizing {
1160
1160
  height: auto;
1161
1161
  }
1162
1162
 
1163
+ /* Mermaid overlay for ProseMirror (renders outside editor to avoid DOM corruption) */
1164
+ .mermaid-overlay {
1165
+ position: absolute;
1166
+ top: 0;
1167
+ left: 0;
1168
+ right: 0;
1169
+ pointer-events: none;
1170
+ z-index: 2;
1171
+ }
1172
+
1173
+ .mermaid-overlay-item {
1174
+ pointer-events: auto;
1175
+ background: var(--surface);
1176
+ border: 1px solid var(--border);
1177
+ border-radius: var(--radius-md);
1178
+ padding: 20px;
1179
+ display: flex;
1180
+ justify-content: center;
1181
+ }
1182
+
1183
+ .mermaid-overlay-item svg {
1184
+ max-width: 100%;
1185
+ height: auto;
1186
+ }
1187
+
1188
+ /* Hide original mermaid code blocks when overlays are rendered */
1189
+ .has-mermaid-overlays .ProseMirror pre:has(code.language-mermaid) {
1190
+ visibility: hidden;
1191
+ }
1192
+
1163
1193
  /* ---- Highlight popover ---- */
1164
1194
  .highlight-popover {
1165
1195
  position: fixed;