collabmd 0.1.45 → 0.1.46

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 (190) hide show
  1. package/README.md +39 -19
  2. package/bin/collabmd.js +27 -1
  3. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-CYM5nxUi.js +1 -0
  4. package/dist/client/assets/browser-utils--H_DkyEF.js +1 -0
  5. package/dist/client/assets/chunk-ERSWUTIN-hHdvnhaY.js +41 -0
  6. package/dist/client/assets/comment-thread-store-CdcwrObc.js +1 -0
  7. package/dist/client/assets/comment-threads-9J6Em-_y.js +4 -0
  8. package/dist/client/assets/comment-ui-shared-BC4pt4w8.js +7 -0
  9. package/dist/client/assets/dist-B5HTH2BO.js +1 -0
  10. package/dist/client/assets/{dist-DhLvC8DS.js → dist-B5Jf1SLZ.js} +2 -2
  11. package/dist/client/assets/{dist-CnL7Y2sM.js → dist-BDt3rz7l.js} +1 -1
  12. package/dist/client/assets/dist-BEwK4csK.js +1 -0
  13. package/dist/client/assets/dist-BKW4PALF.js +1 -0
  14. package/dist/client/assets/dist-BWcHHOx-.js +1 -0
  15. package/dist/client/assets/{dist-CYZmbokb.js → dist-BalScOwZ.js} +9 -9
  16. package/dist/client/assets/dist-Bf8f4HmM.js +6 -0
  17. package/dist/client/assets/dist-BjHJDtyU.js +1 -0
  18. package/dist/client/assets/dist-Bm6pf9Bl.js +1 -0
  19. package/dist/client/assets/dist-BoVBdSjk.js +1 -0
  20. package/dist/client/assets/dist-CC5IrQMG.js +1 -0
  21. package/dist/client/assets/{dist-C11hHqv_.js → dist-CCP_AKPG.js} +12 -12
  22. package/dist/client/assets/dist-CZgOmxK6.js +1 -0
  23. package/dist/client/assets/{dist-D2AQ-76g.js → dist-Cqhv5LAk.js} +1 -1
  24. package/dist/client/assets/{dist-MvcV4190.js → dist-D-Z6FLem.js} +1 -1
  25. package/dist/client/assets/dist-DLMiIsNC.js +11 -0
  26. package/dist/client/assets/{dist-3bgCp7iY.js → dist-DZKu9Cs8.js} +1 -1
  27. package/dist/client/assets/dist-DaYdhcVs.js +1 -0
  28. package/dist/client/assets/dist-FWJsgGYI.js +1 -0
  29. package/dist/client/assets/dist-Kh2COra_.js +1 -0
  30. package/dist/client/assets/{dist-JYEDRrPT.js → dist-PDZ3bSqm.js} +1 -1
  31. package/dist/client/assets/{dist-Drp8uu5J.js → dist-TjMh8n1u.js} +1 -1
  32. package/dist/client/assets/{dist-DGb27Dl6.js → dist-dtAdgL39.js} +1 -1
  33. package/dist/client/assets/dist-jv4WdPnK.js +9 -0
  34. package/dist/client/assets/{dist-DK5Gs2wa.js → dist-rGBmqxC7.js} +1 -1
  35. package/dist/client/assets/{dist-DCzuX1AF.js → dist-shrl6K_0.js} +1 -1
  36. package/dist/client/assets/dist-tOaegDYS2.js +1 -0
  37. package/dist/client/assets/dist-ule2n6ak.js +1 -0
  38. package/dist/client/assets/dist-xElaxbia.js +1 -0
  39. package/dist/client/assets/{drawio-editor-ClE8jpoG.js → drawio-editor-FzY1cVw8.js} +1 -1
  40. package/dist/client/assets/drawioEditor-BjiKJqlc.js +2 -0
  41. package/dist/client/assets/editor-session-Cm9ekeNo.js +54 -0
  42. package/dist/client/assets/embedded-editor-base-CwTkk911.css +1 -0
  43. package/dist/client/assets/{preview-render-profile-BZzGSg6K.js → es-DXGV3RHd.js} +13 -13
  44. package/dist/client/assets/excalidraw-editor-B46zsTFI.js +9 -0
  45. package/dist/client/assets/{excalidraw-editor-CyGwOhLz.css → excalidraw-editor-Bt7gMSoh.css} +1 -1
  46. package/dist/client/assets/excalidraw-scene-BOben2gr.js +1 -0
  47. package/dist/client/assets/excalidrawEditor-CT2pHq7e.js +2 -0
  48. package/dist/client/assets/{export-page-CUfws2T-.js → export-page-A7NHawJY.js} +3 -3
  49. package/dist/client/assets/exportDocument-B2L8fe34.css +1 -0
  50. package/dist/client/assets/exportDocument-BaqcOAAW.js +2 -0
  51. package/dist/client/assets/file-icon-svg-CQAjlWjK.js +1 -0
  52. package/dist/client/assets/file-kind-BbqgGzpc.js +1 -0
  53. package/dist/client/assets/image-QXRYHUNP-SWEV8H0J.js +1 -0
  54. package/dist/client/assets/index-ClbjMBVt.js +2 -0
  55. package/dist/client/assets/index-Pum8ET-5.css +1 -0
  56. package/dist/client/assets/main-B3uPyqic.js +893 -0
  57. package/dist/client/assets/pdf-BL9Pr2D5.js +54 -0
  58. package/dist/client/assets/pdf.worker-CLesOks4.mjs +64857 -0
  59. package/dist/client/assets/pdf_viewer-FVkkThnz.js +551 -0
  60. package/dist/client/assets/{preview-render-compiler-BSaQO_p3.js → preview-render-compiler-BD-XhkS2.js} +2 -2
  61. package/dist/client/assets/preview-render-compiler-BKedaMxx.js +1 -0
  62. package/dist/client/assets/preview-render-profile-CE-5rVTC.js +1 -0
  63. package/dist/client/assets/{preview-render-worker-B42LWvrD.js → preview-render-worker-CiPqc9n6.js} +20 -20
  64. package/dist/client/assets/prod-Dy20X7eT.js +1 -0
  65. package/dist/client/assets/prod-hnwh7wRM.js +177 -0
  66. package/dist/client/assets/quick-switcher-controller-fqOYR7qR.js +12 -0
  67. package/dist/client/assets/runtime-config-BLrEKVO1.js +1 -0
  68. package/dist/client/assets/vault-api-client-_LpV1aIn.js +6 -0
  69. package/dist/client/drawio-editor.html +1 -1
  70. package/dist/client/excalidraw-editor.html +1 -1
  71. package/dist/client/export-document.html +2 -2
  72. package/dist/client/index.html +15 -3
  73. package/docker-compose.yml +42 -0
  74. package/package.json +17 -4
  75. package/scripts/local-structurizr-compose.mjs +101 -0
  76. package/src/client/app/index.html +13 -1
  77. package/src/client/application/app-shell/comments-feature.js +19 -10
  78. package/src/client/application/app-shell/git-feature.js +12 -0
  79. package/src/client/application/app-shell/presence-feature.js +2 -1
  80. package/src/client/application/app-shell/ui-feature-shell.js +45 -2
  81. package/src/client/application/app-shell/ui-feature-toolbar.js +2 -52
  82. package/src/client/application/app-shell/workspace-feature.js +5 -1
  83. package/src/client/application/app-shell-elements.js +2 -0
  84. package/src/client/application/pdf-preview-controller.js +992 -0
  85. package/src/client/application/structurizr-preview-controller.js +395 -0
  86. package/src/client/application/workspace-coordinator.js +25 -3
  87. package/src/client/application/workspace-preview-controller.js +91 -2
  88. package/src/client/bootstrap/collabmd-app-shell.js +31 -5
  89. package/src/client/browser-utils.js +44 -0
  90. package/src/client/domain/runtime-paths.js +26 -5
  91. package/src/client/domain/structurizr-language.js +99 -0
  92. package/src/client/domain/vault-paths.js +48 -0
  93. package/src/client/excalidraw-editor.js +833 -51
  94. package/src/client/infrastructure/browser-preferences-port.js +10 -0
  95. package/src/client/infrastructure/comment-thread-store.js +34 -13
  96. package/src/client/infrastructure/editor-session.js +10 -0
  97. package/src/client/infrastructure/editor-view-adapter.js +46 -2
  98. package/src/client/infrastructure/excalidraw-room-client.js +103 -14
  99. package/src/client/infrastructure/git-api-client.js +5 -0
  100. package/src/client/infrastructure/vault-api-client.js +26 -0
  101. package/src/client/presentation/comment-ui/comment-ui-shared.js +4 -0
  102. package/src/client/presentation/drawio-embed-controller.js +9 -102
  103. package/src/client/presentation/drawio-viewer.js +118 -0
  104. package/src/client/presentation/excalidraw-embed-controller.js +74 -8
  105. package/src/client/presentation/file-action-controller.js +102 -0
  106. package/src/client/presentation/file-explorer-view.js +10 -29
  107. package/src/client/presentation/file-icon-svg.js +40 -0
  108. package/src/client/presentation/file-tree-state.js +2 -0
  109. package/src/client/presentation/git-diff-view-controller.js +731 -3
  110. package/src/client/presentation/outline-controller.js +86 -0
  111. package/src/client/presentation/quick-switcher-controller.js +25 -13
  112. package/src/client/presentation/quick-switcher-text-search.js +1 -1
  113. package/src/client/styles/components/navigation.css +11 -1
  114. package/src/client/styles/features/diagram-preview.css +76 -0
  115. package/src/client/styles/features/diff-special.css +309 -0
  116. package/src/client/styles/foundation/themes.css +6 -0
  117. package/src/client/styles/layout/shell.css +358 -1
  118. package/src/client/styles/layout/view-modes.css +1 -0
  119. package/src/client/styles/style.css +1 -0
  120. package/src/client/styles/surfaces/excalidraw-editor.css +294 -0
  121. package/src/domain/comment-threads.js +63 -5
  122. package/src/domain/excalidraw-room-codec.js +6 -4
  123. package/src/domain/file-kind.js +35 -3
  124. package/src/server/config/env.js +79 -0
  125. package/src/server/create-app-server.js +12 -0
  126. package/src/server/domain/bases/base-definition.js +1 -1
  127. package/src/server/domain/bases/base-expression-runtime.js +1 -4
  128. package/src/server/domain/bases/base-index-snapshot-store.js +1 -4
  129. package/src/server/domain/bases/base-transform.js +1 -4
  130. package/src/server/domain/collaboration/collaboration-room.js +55 -21
  131. package/src/server/domain/comment-overview.js +15 -5
  132. package/src/server/domain/ripgrep-search-service.js +4 -0
  133. package/src/server/infrastructure/git/diff-service.js +5 -0
  134. package/src/server/infrastructure/git/git-service.js +21 -0
  135. package/src/server/infrastructure/git/history-service.js +54 -0
  136. package/src/server/infrastructure/git/image-mime.js +14 -0
  137. package/src/server/infrastructure/git/untracked-files.js +28 -1
  138. package/src/server/infrastructure/http/create-git-api-query-handler.js +31 -1
  139. package/src/server/infrastructure/http/create-request-handler.js +16 -23
  140. package/src/server/infrastructure/http/create-static-handler.js +5 -2
  141. package/src/server/infrastructure/http/create-structurizr-api-handler.js +145 -0
  142. package/src/server/infrastructure/http/create-vault-api-command-handler.js +66 -4
  143. package/src/server/infrastructure/http/create-vault-api-query-handler.js +51 -3
  144. package/src/server/infrastructure/http/http-request-helpers.js +22 -0
  145. package/src/server/infrastructure/persistence/path-utils.js +1 -1
  146. package/src/server/infrastructure/persistence/vault-file-store.js +3 -0
  147. package/src/server/infrastructure/structurizr/structurizr-embed.css +43 -0
  148. package/src/server/infrastructure/structurizr/structurizr-workspace-service.js +374 -0
  149. package/src/server/infrastructure/websocket/attach-collaboration-gateway.js +4 -22
  150. package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-CbSISC1w.js +0 -1
  151. package/dist/client/assets/browser-utils-CKtI_rZl.js +0 -1
  152. package/dist/client/assets/chunk-ERSWUTIN-ME9RVNel.js +0 -41
  153. package/dist/client/assets/comment-threads-DDegmaFO.js +0 -4
  154. package/dist/client/assets/dist-BH87JoHx.js +0 -11
  155. package/dist/client/assets/dist-BIkPRZO7.js +0 -6
  156. package/dist/client/assets/dist-BqCsFpx4.js +0 -1
  157. package/dist/client/assets/dist-C2JHCt8U.js +0 -1
  158. package/dist/client/assets/dist-CZjTtmTu.js +0 -1
  159. package/dist/client/assets/dist-Cig4Ov_X.js +0 -1
  160. package/dist/client/assets/dist-CqQEC8gR.js +0 -1
  161. package/dist/client/assets/dist-D4Rzqod1.js +0 -1
  162. package/dist/client/assets/dist-D5sn-mwk.js +0 -9
  163. package/dist/client/assets/dist-D7G-n87v.js +0 -1
  164. package/dist/client/assets/dist-DRqOrNgN.js +0 -1
  165. package/dist/client/assets/dist-DetkMS_4.js +0 -1
  166. package/dist/client/assets/dist-Dp6FVkQ1.js +0 -1
  167. package/dist/client/assets/dist-DtbjNB28.js +0 -1
  168. package/dist/client/assets/dist-DyrYcvpo2.js +0 -1
  169. package/dist/client/assets/dist-GrygD2zE.js +0 -1
  170. package/dist/client/assets/dist-HmEpWUow.js +0 -1
  171. package/dist/client/assets/dist-RTa81Km7.js +0 -1
  172. package/dist/client/assets/drawioEditor-CXaTM9Ds.js +0 -2
  173. package/dist/client/assets/editor-session-GTwZS6Df.js +0 -16
  174. package/dist/client/assets/embedded-editor-base-CiNEc8vy.css +0 -1
  175. package/dist/client/assets/excalidraw-editor-BZVM81BO.js +0 -9
  176. package/dist/client/assets/excalidraw-scene-C8n9CHsK.js +0 -176
  177. package/dist/client/assets/excalidrawEditor-DxJanCze.js +0 -2
  178. package/dist/client/assets/exportDocument-BCuxqXDY.js +0 -2
  179. package/dist/client/assets/exportDocument-DV-OX74E.css +0 -1
  180. package/dist/client/assets/file-kind-BKPOIRPE.js +0 -1
  181. package/dist/client/assets/image-QXRYHUNP-lfTHE3bb.js +0 -1
  182. package/dist/client/assets/index-C3YnUgMD.css +0 -1
  183. package/dist/client/assets/index-D2wXraJ1.js +0 -2
  184. package/dist/client/assets/main-DtiGz7uI.js +0 -795
  185. package/dist/client/assets/preview-render-compiler-csGM5ZFz.js +0 -1
  186. package/dist/client/assets/quick-switcher-controller-shW_6vPY.js +0 -12
  187. package/dist/client/assets/room-CQLoqtMo.js +0 -1
  188. package/dist/client/assets/runtime-config-DSGmGE9V.js +0 -1
  189. package/dist/client/assets/vault-api-client-C6bcGwy-.js +0 -5
  190. package/src/server/domain/collaboration/room-persistence-controller.js +0 -80
@@ -9,6 +9,8 @@ export class OutlineController {
9
9
  this.activeHeadingId = null;
10
10
  this.headings = [];
11
11
  this.pinnedHeadingId = null;
12
+ this.pdfOutline = null;
13
+ this.onNavigateToPdfOutline = null;
12
14
  this.onNavigateToHeading = onNavigateToHeading;
13
15
  this.onWillOpen = onWillOpen;
14
16
  this.panel = document.getElementById('outlinePanel');
@@ -81,6 +83,11 @@ export class OutlineController {
81
83
  return;
82
84
  }
83
85
 
86
+ if (this.pdfOutline) {
87
+ this.renderPdfOutline();
88
+ return;
89
+ }
90
+
84
91
  const previewContent = document.getElementById('previewContent');
85
92
  const headings = previewContent?.querySelectorAll('h1, h2, h3, h4, h5, h6') ?? [];
86
93
 
@@ -124,6 +131,85 @@ export class OutlineController {
124
131
  this.observeHeadings(Array.from(headings));
125
132
  }
126
133
 
134
+ setPdfOutline(outline, onNavigate) {
135
+ this.cleanup();
136
+ this.pdfOutline = Array.isArray(outline) && outline.length > 0 ? outline : null;
137
+ this.onNavigateToPdfOutline = this.pdfOutline ? onNavigate : null;
138
+ this.activeHeadingId = null;
139
+ this.toggleButton?.classList.toggle('hidden', !this.pdfOutline);
140
+
141
+ if (!this.pdfOutline) {
142
+ this.navigation?.replaceChildren();
143
+ this.close();
144
+ return;
145
+ }
146
+
147
+ if (this.outlineOpen) {
148
+ this.renderPdfOutline();
149
+ }
150
+ }
151
+
152
+ clearPdfOutline() {
153
+ this.pdfOutline = null;
154
+ this.onNavigateToPdfOutline = null;
155
+ this.activeHeadingId = null;
156
+ this.pinnedHeadingId = null;
157
+ this.navigation?.replaceChildren();
158
+ this.toggleButton?.classList.add('hidden');
159
+ this.close();
160
+ }
161
+
162
+ renderPdfOutline() {
163
+ if (!this.navigation || !this.pdfOutline) {
164
+ return;
165
+ }
166
+
167
+ this.cleanup();
168
+ this.navigation.replaceChildren();
169
+ const fragment = document.createDocumentFragment();
170
+ let itemIndex = 0;
171
+ const appendItems = (items, level = 1) => {
172
+ items.forEach((item) => {
173
+ if (!item || typeof item !== 'object') {
174
+ return;
175
+ }
176
+
177
+ const title = String(item.title ?? '').trim();
178
+ if (title) {
179
+ const id = `pdf-outline-${itemIndex}`;
180
+ const button = document.createElement('button');
181
+ button.type = 'button';
182
+ button.className = 'outline-item';
183
+ button.dataset.level = String(Math.min(level, 6));
184
+ button.dataset.target = id;
185
+ button.title = title;
186
+ button.textContent = title;
187
+ button.addEventListener('click', () => {
188
+ this.setActiveItem(id, { behavior: 'auto' });
189
+ this.onNavigateToPdfOutline?.(item);
190
+ if (this.mobileBreakpointQuery.matches) {
191
+ this.close();
192
+ }
193
+ });
194
+ fragment.appendChild(button);
195
+ itemIndex += 1;
196
+ }
197
+
198
+ if (Array.isArray(item.items)) {
199
+ appendItems(item.items, Math.min(level + 1, 6));
200
+ }
201
+ });
202
+ };
203
+
204
+ appendItems(this.pdfOutline);
205
+ if (fragment.childNodes.length === 0) {
206
+ this.navigation.innerHTML = '<div class="outline-empty">No outline found</div>';
207
+ return;
208
+ }
209
+
210
+ this.navigation.appendChild(fragment);
211
+ }
212
+
127
213
  cleanup({ preservePinnedHeading = false } = {}) {
128
214
  if (this.activeHeadingFrame) {
129
215
  cancelAnimationFrame(this.activeHeadingFrame);
@@ -1,5 +1,6 @@
1
1
  import { stripVaultFileExtension } from '../../domain/file-kind.js';
2
2
  import { escapeHtml } from '../domain/vault-utils.js';
3
+ import { getVaultFileIconSvg } from './file-icon-svg.js';
3
4
  import {
4
5
  DEFAULT_SEARCH_DEBOUNCE_MS,
5
6
  QuickSwitcherTextSearchRunner,
@@ -19,6 +20,7 @@ function getRawFileName(filePath) {
19
20
  function createCorpusEntry(filePath) {
20
21
  const displayName = stripVaultFileExtension(filePath);
21
22
  const fileName = displayName.split('/').pop() || displayName;
23
+ const rawFileName = getRawFileName(filePath);
22
24
 
23
25
  return {
24
26
  displayName,
@@ -27,6 +29,7 @@ function createCorpusEntry(filePath) {
27
29
  lowerDisplayName: displayName.toLowerCase(),
28
30
  lowerFileName: fileName.toLowerCase(),
29
31
  lowerPath: String(filePath).toLowerCase(),
32
+ lowerRawFileName: rawFileName.toLowerCase(),
30
33
  };
31
34
  }
32
35
 
@@ -94,6 +97,25 @@ function findCorpusMatch(entry, query) {
94
97
  };
95
98
  }
96
99
 
100
+ const rawFileIndex = entry.lowerRawFileName.indexOf(query);
101
+ if (rawFileIndex >= 0) {
102
+ return {
103
+ indices: createRangeIndices(
104
+ rawFileIndex + (entry.displayName.length - entry.fileName.length),
105
+ query.length,
106
+ ),
107
+ score: 40 + (1 / entry.lowerRawFileName.length),
108
+ };
109
+ }
110
+
111
+ const rawPathIndex = entry.lowerPath.indexOf(query);
112
+ if (rawPathIndex >= 0) {
113
+ return {
114
+ indices: createRangeIndices(rawPathIndex, query.length),
115
+ score: 25 + (1 / entry.lowerPath.length),
116
+ };
117
+ }
118
+
97
119
  return findFuzzyMatch(entry.lowerDisplayName, query);
98
120
  }
99
121
 
@@ -174,7 +196,6 @@ export class QuickSwitcherController {
174
196
 
175
197
  this.filteredFiles = [];
176
198
  this.fileMatches = new Map();
177
- this.fileNameCounts = new Map();
178
199
  this.fileMatchCount = 0;
179
200
  this.fileResultsTruncated = false;
180
201
  this.fileCorpus = [];
@@ -370,11 +391,6 @@ export class QuickSwitcherController {
370
391
  if (allFiles !== this.lastFileListRef) {
371
392
  this.lastFileListRef = allFiles;
372
393
  this.fileCorpus = allFiles.map((filePath) => createCorpusEntry(filePath));
373
- this.fileNameCounts = new Map();
374
- this.fileCorpus.forEach((entry) => {
375
- const count = this.fileNameCounts.get(entry.lowerFileName) ?? 0;
376
- this.fileNameCounts.set(entry.lowerFileName, count + 1);
377
- });
378
394
  }
379
395
 
380
396
  this.fileMatches.clear();
@@ -495,19 +511,15 @@ export class QuickSwitcherController {
495
511
  item.setAttribute('aria-selected', index === this.selectedIndex ? 'true' : 'false');
496
512
  item.dataset.index = String(index);
497
513
 
498
- const fileName = getFileName(filePath);
499
- const rawFileName = getRawFileName(filePath);
514
+ const fileName = getRawFileName(filePath);
500
515
  const dirPath = getDirPath(filePath);
501
516
  const match = this.fileMatches.get(filePath);
502
517
  const corpusEntry = this.fileCorpus.find((entry) => entry.filePath === filePath);
503
518
  const matchIndices = corpusEntry ? splitMatchIndices(corpusEntry, match?.indices) : { dirPath: [], fileName: [] };
504
- const displayFileName = (this.fileNameCounts.get(fileName.toLowerCase()) ?? 0) > 1
505
- ? rawFileName
506
- : fileName;
507
519
 
508
520
  item.innerHTML = `
509
- <svg class="qs-result-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
510
- <span class="qs-result-name">${highlightText(displayFileName, matchIndices.fileName)}</span>
521
+ ${getVaultFileIconSvg(filePath, { className: 'qs-result-icon' })}
522
+ <span class="qs-result-name">${highlightText(fileName, matchIndices.fileName)}</span>
511
523
  ${dirPath ? `<span class="qs-result-path">${highlightText(dirPath, matchIndices.dirPath)}</span>` : ''}
512
524
  `;
513
525
 
@@ -1,4 +1,4 @@
1
- export const DEFAULT_SEARCH_DEBOUNCE_MS = 220;
1
+ export const DEFAULT_SEARCH_DEBOUNCE_MS = 300;
2
2
  const TEXT_RESULT_LIMIT = 50;
3
3
 
4
4
  export function formatMatchCount(count = 0, { truncated = false } = {}) {
@@ -25,13 +25,23 @@
25
25
  white-space: nowrap;
26
26
  }
27
27
 
28
- .toolbar-theme-icon {
28
+ .toolbar-theme-icon,
29
+ .toolbar-vim-icon {
29
30
  display: inline-flex;
30
31
  align-items: center;
31
32
  justify-content: center;
32
33
  flex-shrink: 0;
33
34
  }
34
35
 
36
+ .toolbar-vim-button .toolbar-vim-state {
37
+ margin-left: auto;
38
+ }
39
+
40
+ .toolbar-vim-button[aria-pressed='true'] .toolbar-vim-state {
41
+ background: var(--color-primary-highlight);
42
+ color: var(--color-primary);
43
+ }
44
+
35
45
  .toolbar-theme-button {
36
46
  width: 32px;
37
47
  min-width: 32px;
@@ -524,6 +524,82 @@ body.excalidraw-maximized-open .resizer {
524
524
  color: var(--color-primary);
525
525
  }
526
526
 
527
+ .file-tree-file.is-pdf .file-tree-icon {
528
+ color: var(--color-danger);
529
+ }
530
+
527
531
  .file-tree-file.is-mermaid .file-tree-icon {
528
532
  color: oklch(from var(--color-primary) calc(l * 0.96) calc(c * 0.86) 215);
529
533
  }
534
+
535
+ .file-tree-file.is-structurizr .file-tree-icon {
536
+ color: var(--color-primary);
537
+ }
538
+
539
+ .structurizr-preview-shell {
540
+ display: flex;
541
+ flex-direction: column;
542
+ width: 100%;
543
+ height: 100%;
544
+ min-height: 0;
545
+ margin: 0;
546
+ overflow: hidden;
547
+ }
548
+
549
+ .structurizr-preview-header {
550
+ flex-shrink: 0;
551
+ }
552
+
553
+ .structurizr-preview-label {
554
+ flex: 1;
555
+ min-width: 0;
556
+ overflow: hidden;
557
+ text-overflow: ellipsis;
558
+ white-space: nowrap;
559
+ font-weight: 500;
560
+ }
561
+
562
+ .structurizr-preview-status {
563
+ padding: var(--space-4);
564
+ border-bottom: 1px solid var(--color-divider);
565
+ color: var(--color-text-muted);
566
+ font-size: var(--text-sm);
567
+ }
568
+
569
+ .structurizr-preview-status.is-error {
570
+ background: var(--color-error-highlight);
571
+ color: var(--color-error);
572
+ }
573
+
574
+ .structurizr-preview-stage {
575
+ position: relative;
576
+ flex: 1;
577
+ min-width: 0;
578
+ min-height: 0;
579
+ overflow: hidden;
580
+ }
581
+
582
+ .structurizr-preview-iframe {
583
+ display: block;
584
+ position: absolute;
585
+ inset: 0;
586
+ width: 100%;
587
+ height: 100%;
588
+ min-height: 0;
589
+ border: 0;
590
+ background: var(--color-surface);
591
+ }
592
+
593
+ .structurizr-preview-shell.is-maximized {
594
+ position: fixed;
595
+ inset: var(--space-4);
596
+ z-index: 172;
597
+ width: auto !important;
598
+ height: auto !important;
599
+ max-width: none;
600
+ box-shadow: 0 0 0 9999px var(--surface-scrim), var(--shadow-media-modal);
601
+ }
602
+
603
+ body.structurizr-maximized-open {
604
+ overflow: hidden;
605
+ }
@@ -0,0 +1,309 @@
1
+ /* ===== DIFF / SPECIAL FILES ===== */
2
+
3
+ .diff-special {
4
+ padding: var(--space-4);
5
+ border-top: 1px solid var(--color-divider);
6
+ background: var(--color-surface);
7
+ }
8
+
9
+ .diff-special-header {
10
+ display: flex;
11
+ align-items: flex-start;
12
+ justify-content: space-between;
13
+ gap: var(--space-3);
14
+ margin-bottom: var(--space-3);
15
+ }
16
+
17
+ .diff-special-eyebrow {
18
+ display: block;
19
+ margin-bottom: 3px;
20
+ color: var(--color-primary);
21
+ font-size: var(--text-meta);
22
+ font-weight: 700;
23
+ letter-spacing: 0.08em;
24
+ text-transform: uppercase;
25
+ }
26
+
27
+ .diff-special-title {
28
+ margin: 0;
29
+ color: var(--color-text);
30
+ font-size: var(--text-ui-sm);
31
+ font-weight: 700;
32
+ }
33
+
34
+ .diff-special-note,
35
+ .diff-special-footnote {
36
+ color: var(--color-text-faint);
37
+ font-size: var(--text-meta);
38
+ }
39
+
40
+ .diff-special-note {
41
+ flex-shrink: 0;
42
+ font-family: var(--font-mono);
43
+ }
44
+
45
+ .diff-special-footnote {
46
+ margin: var(--space-3) 0 0;
47
+ }
48
+
49
+ .diff-media-grid,
50
+ .diff-excalidraw-grid,
51
+ .diff-drawio-grid {
52
+ display: grid;
53
+ grid-template-columns: repeat(2, minmax(0, 1fr));
54
+ gap: var(--space-3);
55
+ }
56
+
57
+ .diff-media-pane,
58
+ .diff-excalidraw-pane,
59
+ .diff-drawio-pane {
60
+ min-width: 0;
61
+ overflow: hidden;
62
+ border: 1px solid var(--color-divider);
63
+ border-radius: var(--radius-md);
64
+ background: var(--color-surface-offset);
65
+ }
66
+
67
+ .diff-media-pane-header,
68
+ .diff-excalidraw-pane-header,
69
+ .diff-drawio-pane-header {
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: space-between;
73
+ gap: var(--space-2);
74
+ min-height: 34px;
75
+ padding: 0 var(--space-3);
76
+ border-bottom: 1px solid var(--color-divider);
77
+ }
78
+
79
+ .diff-media-pane-label {
80
+ color: var(--color-text);
81
+ font-size: var(--text-label);
82
+ font-weight: 700;
83
+ }
84
+
85
+ .diff-media-pane-meta {
86
+ overflow: hidden;
87
+ color: var(--color-text-faint);
88
+ font-family: var(--font-mono);
89
+ font-size: var(--text-meta);
90
+ text-overflow: ellipsis;
91
+ white-space: nowrap;
92
+ }
93
+
94
+ .diff-media-canvas {
95
+ display: flex;
96
+ align-items: center;
97
+ justify-content: center;
98
+ min-height: 280px;
99
+ padding: var(--space-4);
100
+ background-color: var(--color-surface);
101
+ background-image: linear-gradient(45deg, color-mix(in oklab, var(--color-text) 5%, transparent) 25%, transparent 25%, transparent 75%, color-mix(in oklab, var(--color-text) 5%, transparent) 75%), linear-gradient(45deg, color-mix(in oklab, var(--color-text) 5%, transparent) 25%, transparent 25%, transparent 75%, color-mix(in oklab, var(--color-text) 5%, transparent) 75%);
102
+ background-position: 0 0, 8px 8px;
103
+ background-size: 16px 16px;
104
+ }
105
+
106
+ .diff-media-image {
107
+ display: block;
108
+ width: auto;
109
+ max-width: 100%;
110
+ max-height: 380px;
111
+ object-fit: contain;
112
+ border-radius: var(--radius-sm);
113
+ box-shadow: var(--shadow-md);
114
+ }
115
+
116
+ .diff-media-empty {
117
+ display: flex;
118
+ flex-direction: column;
119
+ align-items: center;
120
+ gap: var(--space-2);
121
+ color: var(--color-text-faint);
122
+ font-size: var(--text-meta);
123
+ text-align: center;
124
+ }
125
+
126
+ .diff-media-empty-icon {
127
+ display: grid;
128
+ width: 30px;
129
+ height: 30px;
130
+ place-items: center;
131
+ border: 1px solid var(--color-divider);
132
+ border-radius: 50%;
133
+ color: var(--color-text-muted);
134
+ font-size: var(--text-title-md);
135
+ }
136
+
137
+ .diff-file-header-kind {
138
+ margin-left: auto;
139
+ color: var(--color-text-muted);
140
+ font-family: var(--font-mono);
141
+ font-size: var(--text-meta);
142
+ }
143
+
144
+ .diff-scene-summary {
145
+ display: flex;
146
+ flex-wrap: wrap;
147
+ gap: var(--space-2);
148
+ margin-bottom: var(--space-3);
149
+ }
150
+
151
+ .diff-scene-stat {
152
+ display: inline-flex;
153
+ align-items: baseline;
154
+ gap: 5px;
155
+ padding: 5px 8px;
156
+ border-radius: var(--radius-sm);
157
+ background: var(--color-surface-offset);
158
+ font-family: var(--font-mono);
159
+ font-size: var(--text-meta);
160
+ }
161
+
162
+ .diff-scene-stat strong {
163
+ font-size: var(--text-ui-sm);
164
+ }
165
+
166
+ .diff-scene-stat--add strong {
167
+ color: var(--diff-add-text);
168
+ }
169
+
170
+ .diff-scene-stat--update strong {
171
+ color: var(--color-primary);
172
+ }
173
+
174
+ .diff-scene-stat--remove strong {
175
+ color: var(--diff-del-text);
176
+ }
177
+
178
+ .diff-excalidraw-preview {
179
+ display: flex;
180
+ align-items: center;
181
+ justify-content: center;
182
+ min-height: 220px;
183
+ padding: var(--space-3);
184
+ background: var(--surface-embed-canvas);
185
+ }
186
+
187
+ .diff-excalidraw-preview svg {
188
+ display: block;
189
+ width: 100%;
190
+ height: 220px;
191
+ }
192
+
193
+ .diff-excalidraw-preview-loading,
194
+ .diff-excalidraw-preview--empty,
195
+ .diff-excalidraw-preview.is-error {
196
+ color: var(--color-text-faint);
197
+ font-size: var(--text-meta);
198
+ }
199
+
200
+ .diff-excalidraw-preview.is-error {
201
+ background: var(--color-surface-offset);
202
+ }
203
+
204
+ .diff-excalidraw-source {
205
+ border-top: 1px solid var(--color-divider);
206
+ }
207
+
208
+ .diff-excalidraw-source summary {
209
+ padding: 8px var(--space-3);
210
+ color: var(--color-text-muted);
211
+ cursor: pointer;
212
+ font-size: var(--text-meta);
213
+ font-weight: 600;
214
+ }
215
+
216
+ .diff-excalidraw-source summary:hover {
217
+ color: var(--color-text);
218
+ }
219
+
220
+ .diff-excalidraw-source pre {
221
+ max-height: 300px;
222
+ margin: 0;
223
+ padding: var(--space-3);
224
+ overflow: auto;
225
+ border-top: 1px solid var(--color-divider);
226
+ color: var(--color-text-muted);
227
+ font-family: var(--font-mono);
228
+ font-size: var(--text-meta);
229
+ line-height: 1.55;
230
+ white-space: pre;
231
+ }
232
+
233
+ .diff-excalidraw-diff .diff-load-full-btn {
234
+ margin-top: var(--space-3);
235
+ }
236
+
237
+ .diff-drawio-preview {
238
+ display: flex;
239
+ align-items: stretch;
240
+ justify-content: center;
241
+ min-height: 280px;
242
+ overflow: hidden;
243
+ background: var(--surface-embed-canvas);
244
+ }
245
+
246
+ .diff-drawio-preview .drawio-viewer-frame {
247
+ min-height: 280px;
248
+ cursor: default;
249
+ }
250
+
251
+ .diff-drawio-preview-loading,
252
+ .diff-drawio-preview--empty,
253
+ .diff-drawio-preview.is-error {
254
+ align-items: center;
255
+ justify-content: center;
256
+ width: 100%;
257
+ color: var(--color-text-faint);
258
+ font-size: var(--text-meta);
259
+ }
260
+
261
+ .diff-drawio-preview.is-error {
262
+ background: var(--color-surface-offset);
263
+ }
264
+
265
+ .diff-drawio-source {
266
+ border-top: 1px solid var(--color-divider);
267
+ }
268
+
269
+ .diff-drawio-source summary {
270
+ padding: 8px var(--space-3);
271
+ color: var(--color-text-muted);
272
+ cursor: pointer;
273
+ font-size: var(--text-meta);
274
+ font-weight: 600;
275
+ }
276
+
277
+ .diff-drawio-source summary:hover {
278
+ color: var(--color-text);
279
+ }
280
+
281
+ .diff-drawio-source pre {
282
+ max-height: 300px;
283
+ margin: 0;
284
+ padding: var(--space-3);
285
+ overflow: auto;
286
+ border-top: 1px solid var(--color-divider);
287
+ color: var(--color-text-muted);
288
+ font-family: var(--font-mono);
289
+ font-size: var(--text-meta);
290
+ line-height: 1.55;
291
+ white-space: pre;
292
+ }
293
+
294
+ @media (max-width: 768px) {
295
+ .diff-media-grid,
296
+ .diff-excalidraw-grid,
297
+ .diff-drawio-grid {
298
+ grid-template-columns: 1fr;
299
+ }
300
+
301
+ .diff-special-header {
302
+ flex-direction: column;
303
+ gap: var(--space-1);
304
+ }
305
+
306
+ .diff-media-canvas {
307
+ min-height: 220px;
308
+ }
309
+ }
@@ -1,5 +1,11 @@
1
1
  /* ===== FOUNDATION / THEMES ===== */
2
2
 
3
+ :root {
4
+ --pdf-highlight-bg: rgb(180 0 170 / 25%);
5
+ --pdf-highlight-selected-bg: rgb(0 100 0 / 25%);
6
+ --pdf-selection-bg: rgb(0 90 255 / 25%);
7
+ }
8
+
3
9
  :root,
4
10
  [data-theme="light"] {
5
11
  --color-bg: #f6f8fa;