@pierre/diffs 1.2.12 → 1.3.0-beta.10

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 (288) hide show
  1. package/dist/components/CodeView.d.ts +91 -6
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +300 -38
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +14 -3
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +98 -12
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +68 -19
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +363 -25
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.d.ts.map +1 -1
  14. package/dist/components/FileStream.js +2 -1
  15. package/dist/components/FileStream.js.map +1 -1
  16. package/dist/components/UnresolvedFile.d.ts +2 -2
  17. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  18. package/dist/components/UnresolvedFile.js +2 -2
  19. package/dist/components/UnresolvedFile.js.map +1 -1
  20. package/dist/components/VirtualizedFile.d.ts +4 -2
  21. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  22. package/dist/components/VirtualizedFile.js +59 -47
  23. package/dist/components/VirtualizedFile.js.map +1 -1
  24. package/dist/components/VirtualizedFileDiff.d.ts +27 -5
  25. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  26. package/dist/components/VirtualizedFileDiff.js +262 -56
  27. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  28. package/dist/components/Virtualizer.d.ts +4 -1
  29. package/dist/components/Virtualizer.d.ts.map +1 -1
  30. package/dist/components/Virtualizer.js +21 -4
  31. package/dist/components/Virtualizer.js.map +1 -1
  32. package/dist/constants.d.ts +4 -1
  33. package/dist/constants.d.ts.map +1 -1
  34. package/dist/constants.js +4 -1
  35. package/dist/constants.js.map +1 -1
  36. package/dist/editor/command.d.ts +7 -0
  37. package/dist/editor/command.d.ts.map +1 -0
  38. package/dist/editor/command.js +54 -0
  39. package/dist/editor/command.js.map +1 -0
  40. package/dist/editor/editStack.d.ts +71 -0
  41. package/dist/editor/editStack.d.ts.map +1 -0
  42. package/dist/editor/editStack.js +218 -0
  43. package/dist/editor/editStack.js.map +1 -0
  44. package/dist/editor/editor.d.ts +105 -0
  45. package/dist/editor/editor.d.ts.map +1 -0
  46. package/dist/editor/editor.js +2545 -0
  47. package/dist/editor/editor.js.map +1 -0
  48. package/dist/editor/editor2.js +6 -0
  49. package/dist/editor/editor2.js.map +1 -0
  50. package/dist/editor/index.d.ts +5 -0
  51. package/dist/editor/index.js +3 -0
  52. package/dist/editor/languages.d.ts +26 -0
  53. package/dist/editor/languages.d.ts.map +1 -0
  54. package/dist/editor/languages.js +363 -0
  55. package/dist/editor/languages.js.map +1 -0
  56. package/dist/editor/lineAnnotations.d.ts +9 -0
  57. package/dist/editor/lineAnnotations.d.ts.map +1 -0
  58. package/dist/editor/lineAnnotations.js +212 -0
  59. package/dist/editor/lineAnnotations.js.map +1 -0
  60. package/dist/editor/marker.d.ts +38 -0
  61. package/dist/editor/marker.d.ts.map +1 -0
  62. package/dist/editor/marker.js +245 -0
  63. package/dist/editor/marker.js.map +1 -0
  64. package/dist/editor/matchBrackets.d.ts +9 -0
  65. package/dist/editor/matchBrackets.d.ts.map +1 -0
  66. package/dist/editor/matchBrackets.js +138 -0
  67. package/dist/editor/matchBrackets.js.map +1 -0
  68. package/dist/editor/pieceTable.d.ts +41 -0
  69. package/dist/editor/pieceTable.d.ts.map +1 -0
  70. package/dist/editor/pieceTable.js +671 -0
  71. package/dist/editor/pieceTable.js.map +1 -0
  72. package/dist/editor/platform.d.ts +19 -0
  73. package/dist/editor/platform.d.ts.map +1 -0
  74. package/dist/editor/platform.js +57 -0
  75. package/dist/editor/platform.js.map +1 -0
  76. package/dist/editor/popover.d.ts +65 -0
  77. package/dist/editor/popover.d.ts.map +1 -0
  78. package/dist/editor/popover.js +187 -0
  79. package/dist/editor/popover.js.map +1 -0
  80. package/dist/editor/searchPanel.d.ts +40 -0
  81. package/dist/editor/searchPanel.d.ts.map +1 -0
  82. package/dist/editor/searchPanel.js +318 -0
  83. package/dist/editor/searchPanel.js.map +1 -0
  84. package/dist/editor/selection.d.ts +211 -0
  85. package/dist/editor/selection.d.ts.map +1 -0
  86. package/dist/editor/selection.js +1626 -0
  87. package/dist/editor/selection.js.map +1 -0
  88. package/dist/editor/selectionAction.d.ts +46 -0
  89. package/dist/editor/selectionAction.d.ts.map +1 -0
  90. package/dist/editor/selectionAction.js +64 -0
  91. package/dist/editor/selectionAction.js.map +1 -0
  92. package/dist/editor/sprite.d.ts +8 -0
  93. package/dist/editor/sprite.d.ts.map +1 -0
  94. package/dist/editor/sprite.js +45 -0
  95. package/dist/editor/sprite.js.map +1 -0
  96. package/dist/editor/stateStorage.d.ts +15 -0
  97. package/dist/editor/stateStorage.d.ts.map +1 -0
  98. package/dist/editor/stateStorage.js +65 -0
  99. package/dist/editor/stateStorage.js.map +1 -0
  100. package/dist/editor/textDocument.d.ts +77 -0
  101. package/dist/editor/textDocument.d.ts.map +1 -0
  102. package/dist/editor/textDocument.js +271 -0
  103. package/dist/editor/textDocument.js.map +1 -0
  104. package/dist/editor/textMeasure.d.ts +61 -0
  105. package/dist/editor/textMeasure.d.ts.map +1 -0
  106. package/dist/editor/textMeasure.js +209 -0
  107. package/dist/editor/textMeasure.js.map +1 -0
  108. package/dist/editor/tokenizer.d.ts +41 -0
  109. package/dist/editor/tokenizer.d.ts.map +1 -0
  110. package/dist/editor/tokenizer.js +513 -0
  111. package/dist/editor/tokenizer.js.map +1 -0
  112. package/dist/editor/utils.d.ts +21 -0
  113. package/dist/editor/utils.d.ts.map +1 -0
  114. package/dist/editor/utils.js +68 -0
  115. package/dist/editor/utils.js.map +1 -0
  116. package/dist/index.d.ts +10 -8
  117. package/dist/index.js +12 -10
  118. package/dist/managers/InteractionManager.d.ts +7 -0
  119. package/dist/managers/InteractionManager.d.ts.map +1 -1
  120. package/dist/managers/InteractionManager.js +22 -1
  121. package/dist/managers/InteractionManager.js.map +1 -1
  122. package/dist/managers/ResizeManager.d.ts +10 -2
  123. package/dist/managers/ResizeManager.d.ts.map +1 -1
  124. package/dist/managers/ResizeManager.js +33 -13
  125. package/dist/managers/ResizeManager.js.map +1 -1
  126. package/dist/managers/UniversalRenderingManager.d.ts +2 -1
  127. package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
  128. package/dist/managers/UniversalRenderingManager.js +6 -1
  129. package/dist/managers/UniversalRenderingManager.js.map +1 -1
  130. package/dist/react/CodeView.d.ts +26 -1
  131. package/dist/react/CodeView.d.ts.map +1 -1
  132. package/dist/react/CodeView.js +82 -19
  133. package/dist/react/CodeView.js.map +1 -1
  134. package/dist/react/EditContext.d.ts +15 -0
  135. package/dist/react/EditContext.d.ts.map +1 -0
  136. package/dist/react/EditContext.js +23 -0
  137. package/dist/react/EditContext.js.map +1 -0
  138. package/dist/react/File.d.ts +3 -1
  139. package/dist/react/File.d.ts.map +1 -1
  140. package/dist/react/File.js +4 -2
  141. package/dist/react/File.js.map +1 -1
  142. package/dist/react/FileDiff.d.ts +4 -1
  143. package/dist/react/FileDiff.d.ts.map +1 -1
  144. package/dist/react/FileDiff.js +4 -2
  145. package/dist/react/FileDiff.js.map +1 -1
  146. package/dist/react/MultiFileDiff.d.ts +7 -5
  147. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  148. package/dist/react/MultiFileDiff.js +4 -2
  149. package/dist/react/MultiFileDiff.js.map +1 -1
  150. package/dist/react/PatchDiff.d.ts +4 -1
  151. package/dist/react/PatchDiff.d.ts.map +1 -1
  152. package/dist/react/PatchDiff.js +4 -2
  153. package/dist/react/PatchDiff.js.map +1 -1
  154. package/dist/react/UnresolvedFile.d.ts +1 -0
  155. package/dist/react/UnresolvedFile.d.ts.map +1 -1
  156. package/dist/react/UnresolvedFile.js +2 -1
  157. package/dist/react/UnresolvedFile.js.map +1 -1
  158. package/dist/react/index.d.ts +3 -2
  159. package/dist/react/index.js +2 -1
  160. package/dist/react/types.d.ts +3 -0
  161. package/dist/react/types.d.ts.map +1 -1
  162. package/dist/react/utils/renderDiffChildren.d.ts +2 -0
  163. package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
  164. package/dist/react/utils/renderDiffChildren.js +16 -8
  165. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  166. package/dist/react/utils/renderFileChildren.d.ts +2 -0
  167. package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
  168. package/dist/react/utils/renderFileChildren.js +16 -8
  169. package/dist/react/utils/renderFileChildren.js.map +1 -1
  170. package/dist/react/utils/useFileDiffInstance.d.ts +3 -1
  171. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  172. package/dist/react/utils/useFileDiffInstance.js +30 -6
  173. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  174. package/dist/react/utils/useFileInstance.d.ts +4 -1
  175. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  176. package/dist/react/utils/useFileInstance.js +30 -5
  177. package/dist/react/utils/useFileInstance.js.map +1 -1
  178. package/dist/renderers/DiffHunksRenderer.d.ts +28 -2
  179. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  180. package/dist/renderers/DiffHunksRenderer.js +244 -22
  181. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  182. package/dist/renderers/FileRenderer.d.ts +8 -1
  183. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  184. package/dist/renderers/FileRenderer.js +155 -45
  185. package/dist/renderers/FileRenderer.js.map +1 -1
  186. package/dist/ssr/index.d.ts +2 -2
  187. package/dist/ssr/preloadDiffs.d.ts +11 -10
  188. package/dist/ssr/preloadDiffs.d.ts.map +1 -1
  189. package/dist/ssr/preloadDiffs.js +15 -7
  190. package/dist/ssr/preloadDiffs.js.map +1 -1
  191. package/dist/style.js +1 -1
  192. package/dist/types.d.ts +282 -5
  193. package/dist/types.d.ts.map +1 -1
  194. package/dist/utils/applyLineTextWithNewline.d.ts +5 -0
  195. package/dist/utils/applyLineTextWithNewline.d.ts.map +1 -0
  196. package/dist/utils/applyLineTextWithNewline.js +11 -0
  197. package/dist/utils/applyLineTextWithNewline.js.map +1 -0
  198. package/dist/utils/areHunkDataEqual.js +1 -1
  199. package/dist/utils/areHunkDataEqual.js.map +1 -1
  200. package/dist/utils/areManagedSnapshotsEqual.d.ts +2 -2
  201. package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
  202. package/dist/utils/areManagedSnapshotsEqual.js +5 -0
  203. package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
  204. package/dist/utils/awaitWithTimeout.d.ts +5 -0
  205. package/dist/utils/awaitWithTimeout.d.ts.map +1 -0
  206. package/dist/utils/awaitWithTimeout.js +15 -0
  207. package/dist/utils/awaitWithTimeout.js.map +1 -0
  208. package/dist/utils/cleanLastNewline.js +6 -1
  209. package/dist/utils/cleanLastNewline.js.map +1 -1
  210. package/dist/utils/cloneFileDiffMetadata.d.ts +7 -0
  211. package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -0
  212. package/dist/utils/cloneFileDiffMetadata.js +16 -0
  213. package/dist/utils/cloneFileDiffMetadata.js.map +1 -0
  214. package/dist/utils/computeEstimatedDiffHeights.d.ts +3 -1
  215. package/dist/utils/computeEstimatedDiffHeights.d.ts.map +1 -1
  216. package/dist/utils/computeEstimatedDiffHeights.js +8 -1
  217. package/dist/utils/computeEstimatedDiffHeights.js.map +1 -1
  218. package/dist/utils/computeFileOffsets.d.ts +21 -0
  219. package/dist/utils/computeFileOffsets.d.ts.map +1 -0
  220. package/dist/utils/computeFileOffsets.js +51 -0
  221. package/dist/utils/computeFileOffsets.js.map +1 -0
  222. package/dist/utils/createCodeViewHeaderFooterHostElement.d.ts +5 -0
  223. package/dist/utils/createCodeViewHeaderFooterHostElement.d.ts.map +1 -0
  224. package/dist/utils/createCodeViewHeaderFooterHostElement.js +19 -0
  225. package/dist/utils/createCodeViewHeaderFooterHostElement.js.map +1 -0
  226. package/dist/utils/createFileHeaderElement.d.ts.map +1 -1
  227. package/dist/utils/createFileHeaderElement.js +5 -1
  228. package/dist/utils/createFileHeaderElement.js.map +1 -1
  229. package/dist/utils/createTransformerWithState.js +9 -0
  230. package/dist/utils/createTransformerWithState.js.map +1 -1
  231. package/dist/utils/editSessionHunks.d.ts +84 -0
  232. package/dist/utils/editSessionHunks.d.ts.map +1 -0
  233. package/dist/utils/editSessionHunks.js +366 -0
  234. package/dist/utils/editSessionHunks.js.map +1 -0
  235. package/dist/utils/getDiffFileInput.d.ts +14 -0
  236. package/dist/utils/getDiffFileInput.d.ts.map +1 -0
  237. package/dist/utils/getDiffFileInput.js +24 -0
  238. package/dist/utils/getDiffFileInput.js.map +1 -0
  239. package/dist/utils/getDiffHunksRendererOptions.js +1 -0
  240. package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
  241. package/dist/utils/getFiletypeFromFileName.d.ts.map +1 -1
  242. package/dist/utils/getFiletypeFromFileName.js +2 -0
  243. package/dist/utils/getFiletypeFromFileName.js.map +1 -1
  244. package/dist/utils/hydratePartialDiff.d.ts +10 -0
  245. package/dist/utils/hydratePartialDiff.d.ts.map +1 -0
  246. package/dist/utils/hydratePartialDiff.js +140 -0
  247. package/dist/utils/hydratePartialDiff.js.map +1 -0
  248. package/dist/utils/iterateOverDiff.js +3 -3
  249. package/dist/utils/iterateOverDiff.js.map +1 -1
  250. package/dist/utils/parseDiffFromFile.d.ts +1 -1
  251. package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
  252. package/dist/utils/parseDiffFromFile.js +26 -5
  253. package/dist/utils/parseDiffFromFile.js.map +1 -1
  254. package/dist/utils/parsePatchFiles.d.ts.map +1 -1
  255. package/dist/utils/parsePatchFiles.js +2 -0
  256. package/dist/utils/parsePatchFiles.js.map +1 -1
  257. package/dist/utils/realignChangeContent.d.ts +28 -0
  258. package/dist/utils/realignChangeContent.d.ts.map +1 -0
  259. package/dist/utils/realignChangeContent.js +142 -0
  260. package/dist/utils/realignChangeContent.js.map +1 -0
  261. package/dist/utils/renderDiffWithHighlighter.js +1 -1
  262. package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
  263. package/dist/utils/renderFileWithHighlighter.js +5 -14
  264. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  265. package/dist/utils/updateDiffHunks.d.ts +24 -0
  266. package/dist/utils/updateDiffHunks.d.ts.map +1 -0
  267. package/dist/utils/updateDiffHunks.js +235 -0
  268. package/dist/utils/updateDiffHunks.js.map +1 -0
  269. package/dist/utils/virtualDiffLayout.d.ts +40 -1
  270. package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
  271. package/dist/utils/virtualDiffLayout.js +96 -1
  272. package/dist/utils/virtualDiffLayout.js.map +1 -1
  273. package/dist/worker/WorkerPoolManager.d.ts +7 -2
  274. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  275. package/dist/worker/WorkerPoolManager.js +83 -18
  276. package/dist/worker/WorkerPoolManager.js.map +1 -1
  277. package/dist/worker/index.d.ts +2 -2
  278. package/dist/worker/types.d.ts +11 -1
  279. package/dist/worker/types.d.ts.map +1 -1
  280. package/dist/worker/worker-portable.js +46 -66
  281. package/dist/worker/worker-portable.js.map +1 -1
  282. package/dist/worker/worker.js +46 -66
  283. package/dist/worker/worker.js.map +1 -1
  284. package/package.json +12 -5
  285. package/dist/utils/iterateOverFile.d.ts +0 -50
  286. package/dist/utils/iterateOverFile.d.ts.map +0 -1
  287. package/dist/utils/iterateOverFile.js +0 -49
  288. package/dist/utils/iterateOverFile.js.map +0 -1
@@ -0,0 +1,212 @@
1
+ import { getLineAnnotationName } from "../utils/getLineAnnotationName.js";
2
+ import { getLineNumberAttr, h } from "./utils.js";
3
+ //#region src/editor/lineAnnotations.ts
4
+ function applyDocumentChangeToLineAnnotations(change, lineAnnotations) {
5
+ const annotationChanges = getLineAnnotationChanges(change);
6
+ if (annotationChanges.length === 0) return;
7
+ const nextLineAnnotations = [];
8
+ let changed = false;
9
+ for (const annotation of lineAnnotations) {
10
+ if (annotation.side === "deletions" || annotation.lineNumber <= 0) {
11
+ nextLineAnnotations.push(annotation);
12
+ continue;
13
+ }
14
+ let line = annotation.lineNumber - 1;
15
+ let lineCount = change.previousLineCount;
16
+ let annotationChanged = false;
17
+ for (const lineChange of annotationChanges) {
18
+ const nextLineCount = Math.max(1, lineCount + lineChange.lineDelta);
19
+ const nextLine = mapLineThroughLineChange(line, lineChange, nextLineCount);
20
+ if (nextLine === void 0) {
21
+ annotationChanged = true;
22
+ line = void 0;
23
+ break;
24
+ }
25
+ if (nextLine !== line || lineChangeTouchesAnnotationLine(line, lineChange)) annotationChanged = true;
26
+ line = nextLine;
27
+ lineCount = nextLineCount;
28
+ }
29
+ if (line === void 0) {
30
+ changed = true;
31
+ continue;
32
+ }
33
+ const lineNumber = line + 1;
34
+ if (annotationChanged) {
35
+ nextLineAnnotations.push(lineNumber === annotation.lineNumber ? annotation : {
36
+ ...annotation,
37
+ lineNumber
38
+ });
39
+ changed = true;
40
+ continue;
41
+ }
42
+ nextLineAnnotations.push(annotation);
43
+ }
44
+ return changed ? nextLineAnnotations : void 0;
45
+ }
46
+ function getLineAnnotationChanges(change) {
47
+ if (change.changedLineChanges !== void 0) return change.changedLineChanges.flatMap(([startLine, changedEndLine, lineDelta, startCharacter = 0, _endCharacter = 0, endedAtDocumentEnd = false]) => {
48
+ if (lineDelta === 0) return [];
49
+ const insertedLineBreaks = Math.max(0, changedEndLine - startLine);
50
+ return [{
51
+ startLine,
52
+ startCharacter,
53
+ endLine: startLine + Math.max(0, insertedLineBreaks - lineDelta),
54
+ deletesEndLine: lineDelta < 0 && endedAtDocumentEnd,
55
+ insertedLineBreaks,
56
+ lineDelta
57
+ }];
58
+ });
59
+ if (change.lineDelta === 0) return change.changedLineRanges.flatMap(([startLine, endLine]) => {
60
+ const insertedLineBreaks = endLine - startLine;
61
+ if (insertedLineBreaks <= 0) return [];
62
+ return [{
63
+ startLine,
64
+ startCharacter: 0,
65
+ endLine: startLine,
66
+ deletesEndLine: false,
67
+ insertedLineBreaks,
68
+ lineDelta: insertedLineBreaks
69
+ }];
70
+ });
71
+ const removedLineCount = Math.max(0, -change.lineDelta);
72
+ const deletedToDocumentEnd = change.endedAtDocumentEnd && change.startLine + removedLineCount === change.previousLineCount - 1;
73
+ return [{
74
+ startLine: change.startLine,
75
+ startCharacter: change.startCharacter,
76
+ endLine: change.startLine + removedLineCount,
77
+ deletesEndLine: deletedToDocumentEnd,
78
+ insertedLineBreaks: Math.max(0, change.lineDelta),
79
+ lineDelta: change.lineDelta
80
+ }];
81
+ }
82
+ function mapLineThroughLineChange(line, lineChange, nextLineCount) {
83
+ if (line < lineChange.startLine) return line;
84
+ if (line > lineChange.endLine || lineChange.endLine > lineChange.startLine && line === lineChange.endLine && !lineChange.deletesEndLine) return line + lineChange.lineDelta;
85
+ if (lineChange.startLine === lineChange.endLine) {
86
+ if (lineChange.startCharacter === 0) return line + lineChange.insertedLineBreaks;
87
+ return line;
88
+ }
89
+ if (lineChangeDeletesAnnotationLine(line, lineChange)) return;
90
+ const replacementLineOffset = Math.min(Math.max(0, line - lineChange.startLine), lineChange.insertedLineBreaks);
91
+ return clampLine(lineChange.startLine + replacementLineOffset, nextLineCount);
92
+ }
93
+ function lineChangeDeletesAnnotationLine(line, lineChange) {
94
+ if (lineChange.lineDelta >= 0 || line < lineChange.startLine || line > lineChange.endLine) return false;
95
+ if (line === lineChange.startLine && lineChange.startCharacter > 0) return false;
96
+ if (line === lineChange.endLine && !lineChange.deletesEndLine) return false;
97
+ return true;
98
+ }
99
+ function lineChangeTouchesAnnotationLine(line, lineChange) {
100
+ if (lineChange.lineDelta === 0 || line < lineChange.startLine || line > lineChange.endLine) return false;
101
+ return !(lineChange.endLine > lineChange.startLine && line === lineChange.endLine && !lineChange.deletesEndLine);
102
+ }
103
+ function clampLine(line, lineCount) {
104
+ return Math.max(0, Math.min(line, Math.max(0, lineCount - 1)));
105
+ }
106
+ function renderLineAnnotations(lineAnnotations, contentEl, gutterEl) {
107
+ const additionAnnotations = /* @__PURE__ */ new Map();
108
+ const deletionAnnotations = /* @__PURE__ */ new Map();
109
+ for (const annotation of lineAnnotations) {
110
+ const lineNumber = annotation.lineNumber;
111
+ if (!additionAnnotations.has(lineNumber)) additionAnnotations.set(lineNumber, []);
112
+ if (!deletionAnnotations.has(lineNumber)) deletionAnnotations.set(lineNumber, []);
113
+ (annotation.side === "deletions" ? deletionAnnotations : additionAnnotations).get(lineNumber).push(getLineAnnotationName(annotation));
114
+ }
115
+ const leftCodeElement = contentEl.parentElement?.previousElementSibling;
116
+ let leftGutterElement;
117
+ let leftContentElement;
118
+ if (leftCodeElement != null && leftCodeElement instanceof HTMLElement && leftCodeElement.dataset.deletions !== void 0) for (const child of leftCodeElement.children) {
119
+ const el = child;
120
+ const { gutter, content } = el.dataset;
121
+ if (gutter !== void 0) leftGutterElement = el;
122
+ else if (content !== void 0) leftContentElement = el;
123
+ }
124
+ cleanLineAnnotationElements(contentEl, gutterEl);
125
+ if (leftContentElement !== void 0) cleanLineAnnotationElements(leftContentElement, leftGutterElement);
126
+ const additionsAnnotationElements = createLineAnnotationElements(additionAnnotations, contentEl, gutterEl);
127
+ if (leftContentElement === void 0) return;
128
+ const deletionsAnnotationElements = createLineAnnotationElements(deletionAnnotations, leftContentElement, leftGutterElement);
129
+ requestAnimationFrame(() => {
130
+ syncPairedLineAnnotationHeights(additionAnnotations, deletionAnnotations, additionsAnnotationElements, deletionsAnnotationElements);
131
+ });
132
+ }
133
+ function cleanLineAnnotationElements(contentEl, gutterEl) {
134
+ const staleElements = [];
135
+ for (let i = 1; i < contentEl.childElementCount; i++) {
136
+ const el = contentEl.children[i];
137
+ if (el.dataset.lineAnnotation !== void 0) {
138
+ staleElements.push(el);
139
+ if (gutterEl !== void 0) staleElements.push(gutterEl.children[i]);
140
+ }
141
+ }
142
+ for (const el of staleElements) el.remove();
143
+ }
144
+ function createLineAnnotationElements(lineAnnotations, contentEl, gutterEl) {
145
+ const annotationElements = /* @__PURE__ */ new Map();
146
+ for (const el of contentEl.children) {
147
+ const lineNumber = getLineNumberAttr(el);
148
+ if (lineNumber !== void 0) {
149
+ const annotations = lineAnnotations.get(lineNumber);
150
+ if (annotations !== void 0) {
151
+ const annotationElement = h("div", {
152
+ dataset: { lineAnnotation: "0," + (lineNumber - 1) },
153
+ children: [h("div", {
154
+ dataset: "annotationContent",
155
+ children: annotations.map((name) => h("slot", { name }))
156
+ })]
157
+ });
158
+ el.after(annotationElement);
159
+ annotationElements.set(lineNumber, annotationElement);
160
+ }
161
+ }
162
+ }
163
+ if (gutterEl !== void 0) for (const el of gutterEl.children) {
164
+ const lineNumber = getLineNumberAttr(el, "columnNumber");
165
+ if (lineNumber !== void 0 && lineAnnotations.has(lineNumber)) {
166
+ const bufferEl = h("div", {
167
+ dataset: {
168
+ gutterBuffer: "annotation",
169
+ bufferSize: "1"
170
+ },
171
+ style: { gridRow: "span 1" }
172
+ });
173
+ el.after(bufferEl);
174
+ }
175
+ }
176
+ return annotationElements;
177
+ }
178
+ function syncPairedLineAnnotationHeights(additionAnnotations, deletionAnnotations, additionAnnotationElements, deletionAnnotationElements) {
179
+ const offsetHeights = /* @__PURE__ */ new Map();
180
+ for (const [lineNumber, annotations] of additionAnnotations.entries()) {
181
+ const annotationElement = deletionAnnotationElements.get(lineNumber);
182
+ if (annotations.length === 0 && annotationElement !== void 0) {
183
+ const height = measureAnnotationContentHeight(annotationElement);
184
+ if (height > 0) offsetHeights.set(lineNumber, height);
185
+ }
186
+ }
187
+ for (const [lineNumber, annotations] of deletionAnnotations.entries()) {
188
+ const annotationElement = additionAnnotationElements.get(lineNumber);
189
+ if (annotations.length === 0 && annotationElement !== void 0) {
190
+ const height = measureAnnotationContentHeight(annotationElement);
191
+ if (height > 0) offsetHeights.set(lineNumber, height);
192
+ }
193
+ }
194
+ applyLineAnnotationMinHeights(additionAnnotations, additionAnnotationElements, offsetHeights);
195
+ applyLineAnnotationMinHeights(deletionAnnotations, deletionAnnotationElements, offsetHeights);
196
+ }
197
+ function measureAnnotationContentHeight(lineAnnotationEl) {
198
+ const content = lineAnnotationEl.firstElementChild;
199
+ if (!(content instanceof HTMLElement)) return 0;
200
+ return content.getBoundingClientRect().height;
201
+ }
202
+ function applyLineAnnotationMinHeights(lineAnnotations, annotationElements, offsetHeights) {
203
+ for (const [lineNumber, annotationElement] of annotationElements.entries()) {
204
+ const annotations = lineAnnotations.get(lineNumber);
205
+ const offsetHeight = offsetHeights.get(lineNumber);
206
+ if (annotations?.length === 0 && offsetHeight !== void 0) annotationElement.style.setProperty("--diffs-annotation-min-height", `${offsetHeight}px`);
207
+ }
208
+ }
209
+ //#endregion
210
+ export { applyDocumentChangeToLineAnnotations, renderLineAnnotations };
211
+
212
+ //# sourceMappingURL=lineAnnotations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lineAnnotations.js","names":[],"sources":["../../src/editor/lineAnnotations.ts"],"sourcesContent":["import type { DiffLineAnnotation } from '../types';\nimport { getLineAnnotationName } from '../utils/getLineAnnotationName';\nimport type { TextDocumentChange } from './textDocument';\nimport { getLineNumberAttr, h } from './utils';\n\ninterface LineAnnotationChange {\n readonly startLine: number;\n readonly startCharacter: number;\n readonly endLine: number;\n readonly deletesEndLine: boolean;\n readonly insertedLineBreaks: number;\n readonly lineDelta: number;\n}\n\nexport function applyDocumentChangeToLineAnnotations<T>(\n change: TextDocumentChange,\n lineAnnotations: DiffLineAnnotation<T>[]\n): DiffLineAnnotation<T>[] | undefined {\n const annotationChanges = getLineAnnotationChanges(change);\n if (annotationChanges.length === 0) {\n return undefined;\n }\n\n const nextLineAnnotations: DiffLineAnnotation<T>[] = [];\n let changed = false;\n for (const annotation of lineAnnotations) {\n if (annotation.side === 'deletions' || annotation.lineNumber <= 0) {\n nextLineAnnotations.push(annotation);\n continue;\n }\n\n let line: number | undefined = annotation.lineNumber - 1;\n let lineCount = change.previousLineCount;\n let annotationChanged = false;\n for (const lineChange of annotationChanges) {\n const nextLineCount = Math.max(1, lineCount + lineChange.lineDelta);\n const nextLine = mapLineThroughLineChange(\n line,\n lineChange,\n nextLineCount\n );\n if (nextLine === undefined) {\n annotationChanged = true;\n line = undefined;\n break;\n }\n if (\n nextLine !== line ||\n lineChangeTouchesAnnotationLine(line, lineChange)\n ) {\n annotationChanged = true;\n }\n line = nextLine;\n lineCount = nextLineCount;\n }\n\n if (line === undefined) {\n changed = true;\n continue;\n }\n\n const lineNumber = line + 1;\n if (annotationChanged) {\n nextLineAnnotations.push(\n lineNumber === annotation.lineNumber\n ? annotation\n : {\n ...annotation,\n lineNumber,\n }\n );\n changed = true;\n continue;\n }\n\n nextLineAnnotations.push(annotation);\n }\n\n return changed ? nextLineAnnotations : undefined;\n}\n\nfunction getLineAnnotationChanges(\n change: TextDocumentChange\n): readonly LineAnnotationChange[] {\n if (change.changedLineChanges !== undefined) {\n return change.changedLineChanges.flatMap(\n ([\n startLine,\n changedEndLine,\n lineDelta,\n startCharacter = 0,\n _endCharacter = 0,\n endedAtDocumentEnd = false,\n ]) => {\n if (lineDelta === 0) {\n return [];\n }\n const insertedLineBreaks = Math.max(0, changedEndLine - startLine);\n const removedLineCount = Math.max(0, insertedLineBreaks - lineDelta);\n return [\n {\n startLine,\n startCharacter,\n endLine: startLine + removedLineCount,\n deletesEndLine: lineDelta < 0 && endedAtDocumentEnd,\n insertedLineBreaks,\n lineDelta,\n },\n ];\n }\n );\n }\n\n if (change.lineDelta === 0) {\n return change.changedLineRanges.flatMap(([startLine, endLine]) => {\n const insertedLineBreaks = endLine - startLine;\n if (insertedLineBreaks <= 0) {\n return [];\n }\n return [\n {\n startLine,\n startCharacter: 0,\n endLine: startLine,\n deletesEndLine: false,\n insertedLineBreaks,\n lineDelta: insertedLineBreaks,\n },\n ];\n });\n }\n const removedLineCount = Math.max(0, -change.lineDelta);\n const deletedToDocumentEnd =\n change.endedAtDocumentEnd &&\n change.startLine + removedLineCount === change.previousLineCount - 1;\n return [\n {\n startLine: change.startLine,\n startCharacter: change.startCharacter,\n endLine: change.startLine + removedLineCount,\n deletesEndLine: deletedToDocumentEnd,\n insertedLineBreaks: Math.max(0, change.lineDelta),\n lineDelta: change.lineDelta,\n },\n ];\n}\n\nfunction mapLineThroughLineChange(\n line: number,\n lineChange: LineAnnotationChange,\n nextLineCount: number\n): number | undefined {\n if (line < lineChange.startLine) {\n return line;\n }\n\n if (\n line > lineChange.endLine ||\n (lineChange.endLine > lineChange.startLine &&\n line === lineChange.endLine &&\n !lineChange.deletesEndLine)\n ) {\n return line + lineChange.lineDelta;\n }\n\n if (lineChange.startLine === lineChange.endLine) {\n if (lineChange.startCharacter === 0) {\n return line + lineChange.insertedLineBreaks;\n }\n return line;\n }\n\n if (lineChangeDeletesAnnotationLine(line, lineChange)) {\n return undefined;\n }\n\n const replacementLineOffset = Math.min(\n Math.max(0, line - lineChange.startLine),\n lineChange.insertedLineBreaks\n );\n return clampLine(lineChange.startLine + replacementLineOffset, nextLineCount);\n}\n\nfunction lineChangeDeletesAnnotationLine(\n line: number,\n lineChange: LineAnnotationChange\n): boolean {\n if (\n lineChange.lineDelta >= 0 ||\n line < lineChange.startLine ||\n line > lineChange.endLine\n ) {\n return false;\n }\n if (line === lineChange.startLine && lineChange.startCharacter > 0) {\n return false;\n }\n if (line === lineChange.endLine && !lineChange.deletesEndLine) {\n return false;\n }\n return true;\n}\n\nfunction lineChangeTouchesAnnotationLine(\n line: number,\n lineChange: LineAnnotationChange\n): boolean {\n if (\n lineChange.lineDelta === 0 ||\n line < lineChange.startLine ||\n line > lineChange.endLine\n ) {\n return false;\n }\n return !(\n lineChange.endLine > lineChange.startLine &&\n line === lineChange.endLine &&\n !lineChange.deletesEndLine\n );\n}\n\nfunction clampLine(line: number, lineCount: number): number {\n return Math.max(0, Math.min(line, Math.max(0, lineCount - 1)));\n}\n\nexport function renderLineAnnotations<LAnnotation>(\n lineAnnotations: DiffLineAnnotation<LAnnotation>[],\n contentEl: HTMLElement,\n gutterEl?: HTMLElement\n): void {\n const additionAnnotations = new Map<number, string[]>();\n const deletionAnnotations = new Map<number, string[]>();\n for (const annotation of lineAnnotations) {\n const lineNumber = annotation.lineNumber;\n if (!additionAnnotations.has(lineNumber)) {\n additionAnnotations.set(lineNumber, []);\n }\n if (!deletionAnnotations.has(lineNumber)) {\n deletionAnnotations.set(lineNumber, []);\n }\n const map =\n annotation.side === 'deletions'\n ? deletionAnnotations\n : additionAnnotations;\n map.get(lineNumber)!.push(getLineAnnotationName(annotation));\n }\n\n const leftCodeElement = contentEl.parentElement?.previousElementSibling;\n let leftGutterElement: HTMLElement | undefined;\n let leftContentElement: HTMLElement | undefined;\n if (\n leftCodeElement != null &&\n leftCodeElement instanceof HTMLElement &&\n leftCodeElement.dataset.deletions !== undefined\n ) {\n for (const child of leftCodeElement.children) {\n const el = child as HTMLElement;\n const { gutter, content } = el.dataset;\n if (gutter !== undefined) {\n leftGutterElement = el;\n } else if (content !== undefined) {\n leftContentElement = el;\n }\n }\n }\n\n cleanLineAnnotationElements(contentEl, gutterEl);\n if (leftContentElement !== undefined) {\n cleanLineAnnotationElements(leftContentElement, leftGutterElement);\n }\n\n const additionsAnnotationElements = createLineAnnotationElements(\n additionAnnotations,\n contentEl,\n gutterEl\n );\n if (leftContentElement === undefined) {\n return;\n }\n\n const deletionsAnnotationElements = createLineAnnotationElements(\n deletionAnnotations,\n leftContentElement,\n leftGutterElement\n );\n\n requestAnimationFrame(() => {\n syncPairedLineAnnotationHeights(\n additionAnnotations,\n deletionAnnotations,\n additionsAnnotationElements,\n deletionsAnnotationElements\n );\n });\n}\n\nfunction cleanLineAnnotationElements(\n contentEl: HTMLElement,\n gutterEl?: HTMLElement\n): void {\n const staleElements: HTMLElement[] = [];\n for (let i = 1; i < contentEl.childElementCount; i++) {\n const el = contentEl.children[i] as HTMLElement;\n if (el.dataset.lineAnnotation !== undefined) {\n staleElements.push(el);\n if (gutterEl !== undefined) {\n staleElements.push(gutterEl.children[i] as HTMLElement);\n }\n }\n }\n for (const el of staleElements) {\n el.remove();\n }\n}\n\nfunction createLineAnnotationElements(\n lineAnnotations: Map<number, string[]>,\n contentEl: HTMLElement,\n gutterEl?: HTMLElement\n): Map<number, HTMLElement> {\n const annotationElements = new Map<number, HTMLElement>();\n for (const el of contentEl.children) {\n const lineNumber = getLineNumberAttr(el as HTMLElement);\n if (lineNumber !== undefined) {\n const annotations = lineAnnotations.get(lineNumber);\n if (annotations !== undefined) {\n const lineIndex = lineNumber - 1;\n const annotationElement = h('div', {\n dataset: {\n lineAnnotation: '0,' + lineIndex,\n },\n children: [\n h('div', {\n dataset: 'annotationContent',\n children: annotations.map((name) => h('slot', { name })),\n }),\n ],\n });\n el.after(annotationElement);\n annotationElements.set(lineNumber, annotationElement);\n }\n }\n }\n\n if (gutterEl !== undefined) {\n for (const el of gutterEl.children) {\n const lineNumber = getLineNumberAttr(el as HTMLElement, 'columnNumber');\n if (lineNumber !== undefined && lineAnnotations.has(lineNumber)) {\n const bufferEl = h('div', {\n dataset: {\n gutterBuffer: 'annotation',\n bufferSize: '1',\n },\n style: {\n gridRow: 'span 1',\n },\n });\n el.after(bufferEl);\n }\n }\n }\n\n return annotationElements;\n}\n\nfunction syncPairedLineAnnotationHeights(\n additionAnnotations: Map<number, string[]>,\n deletionAnnotations: Map<number, string[]>,\n additionAnnotationElements: Map<number, HTMLElement>,\n deletionAnnotationElements: Map<number, HTMLElement>\n): void {\n const offsetHeights = new Map<number, number>();\n for (const [lineNumber, annotations] of additionAnnotations.entries()) {\n const annotationElement = deletionAnnotationElements.get(lineNumber);\n if (annotations.length === 0 && annotationElement !== undefined) {\n const height = measureAnnotationContentHeight(annotationElement);\n if (height > 0) {\n offsetHeights.set(lineNumber, height);\n }\n }\n }\n for (const [lineNumber, annotations] of deletionAnnotations.entries()) {\n const annotationElement = additionAnnotationElements.get(lineNumber);\n if (annotations.length === 0 && annotationElement !== undefined) {\n const height = measureAnnotationContentHeight(annotationElement);\n if (height > 0) {\n offsetHeights.set(lineNumber, height);\n }\n }\n }\n applyLineAnnotationMinHeights(\n additionAnnotations,\n additionAnnotationElements,\n offsetHeights\n );\n applyLineAnnotationMinHeights(\n deletionAnnotations,\n deletionAnnotationElements,\n offsetHeights\n );\n}\n\nfunction measureAnnotationContentHeight(lineAnnotationEl: HTMLElement): number {\n const content = lineAnnotationEl.firstElementChild;\n if (!(content instanceof HTMLElement)) {\n return 0;\n }\n return content.getBoundingClientRect().height;\n}\n\nfunction applyLineAnnotationMinHeights(\n lineAnnotations: Map<number, string[]>,\n annotationElements: Map<number, HTMLElement>,\n offsetHeights: Map<number, number>\n): void {\n for (const [lineNumber, annotationElement] of annotationElements.entries()) {\n const annotations = lineAnnotations.get(lineNumber);\n const offsetHeight = offsetHeights.get(lineNumber);\n if (annotations?.length === 0 && offsetHeight !== undefined) {\n annotationElement.style.setProperty(\n '--diffs-annotation-min-height',\n `${offsetHeight}px`\n );\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { Range } from "../types.js";
2
+ import { TextDocument } from "./textDocument.js";
3
+ import { PopoverManager } from "./popover.js";
4
+
5
+ //#region src/editor/marker.d.ts
6
+ type MarkerSeverity = 'error' | 'warning' | 'info' | 'hint';
7
+ interface Marker extends Range {
8
+ severity: MarkerSeverity;
9
+ message: string | {
10
+ html: string;
11
+ } | HTMLElement;
12
+ source?: string;
13
+ metadata?: Record<string, unknown>;
14
+ }
15
+ interface MarkerRenderOptions {
16
+ popoverManager: PopoverManager;
17
+ getLineHeight: () => number;
18
+ getOverlayElement: () => HTMLElement | undefined;
19
+ getGutterWidth: () => number;
20
+ getCharX: (line: number, character: number) => [number, number];
21
+ getLineY: (line: number) => number;
22
+ isMouseDown: () => boolean;
23
+ }
24
+ declare class MarkerRenderer {
25
+ #private;
26
+ constructor(editor: MarkerRenderOptions);
27
+ get markers(): readonly Marker[];
28
+ isPopupVisible(): boolean;
29
+ updatePopupPosition(): void;
30
+ setMarkers<LAnnotation>(markers: Marker[], textDocument: TextDocument<LAnnotation>): void;
31
+ listenHover(contentEl: HTMLElement): void;
32
+ removePopup(): void;
33
+ cleanup(): void;
34
+ }
35
+ declare function markerSeverityDatasetKey(severity: MarkerSeverity): string;
36
+ //#endregion
37
+ export { Marker, MarkerRenderOptions, MarkerRenderer, MarkerSeverity, markerSeverityDatasetKey };
38
+ //# sourceMappingURL=marker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marker.d.ts","names":[],"sources":["../../src/editor/marker.ts"],"mappings":";;;;;KAeY,cAAA;AAAA,UAEK,MAAA,SAAe,KAAA;EAC9B,QAAA,EAAU,cAAA;EACV,OAAA;IAAoB,IAAA;EAAA,IAAiB,WAAA;EACrC,MAAA;EACA,QAAA,GAAW,MAAA;AAAA;AAAA,UAGI,mBAAA;EACf,cAAA,EAAgB,cAAA;EAChB,aAAA;EACA,iBAAA,QAAyB,WAAW;EACpC,cAAA;EACA,QAAA,GAAW,IAAA,UAAc,SAAA;EACzB,QAAA,GAAW,IAAA;EACX,WAAA;AAAA;AAAA,cAGW,cAAA;EAAA;EAcX,WAAA,CAAY,MAAA,EAAQ,mBAAA;EAAA,IAIhB,OAAA,aAAoB,MAAA;EAIxB,cAAA;EAIA,mBAAA;EAcA,UAAA,cACE,OAAA,EAAS,MAAA,IACT,YAAA,EAAc,YAAA,CAAa,WAAA;EAW7B,WAAA,CAAY,SAAA,EAAW,WAAA;EAgCvB,WAAA;EAMA,OAAA;AAAA;AAAA,iBAyQc,wBAAA,CAAyB,QAAwB,EAAd,cAAc"}
@@ -0,0 +1,245 @@
1
+ import { addEventListener, getLineNumberAttr, h } from "./utils.js";
2
+ import { setPopoverPositionStyles } from "./popover.js";
3
+ import { selectionIntersects } from "./selection.js";
4
+ //#region src/editor/marker.ts
5
+ const MARKER_POPUP_SHOW_DELAY_MS = 300;
6
+ const MARKER_POPUP_HIDE_DELAY_MS = 100;
7
+ const MARKER_POPUP_PLACEMENT_KEY = "marker-popup";
8
+ var MarkerRenderer = class {
9
+ #options;
10
+ #markers = [];
11
+ #lineCount = 0;
12
+ #markerPopupElement;
13
+ #markerPopupEventDisposes;
14
+ #markerEventDisposes;
15
+ #markerPopupShowTimeout;
16
+ #markerPopupHideTimeout;
17
+ #pendingMarkerPopupIndex;
18
+ #hoveredMarkerIndex;
19
+ #isMarkerPopupHovered = false;
20
+ constructor(editor) {
21
+ this.#options = editor;
22
+ }
23
+ get markers() {
24
+ return this.#markers;
25
+ }
26
+ isPopupVisible() {
27
+ return this.#hoveredMarkerIndex !== void 0;
28
+ }
29
+ updatePopupPosition() {
30
+ const hoveredMarkerIndex = this.#hoveredMarkerIndex;
31
+ const popup = this.#markerPopupElement;
32
+ if (hoveredMarkerIndex === void 0 || popup === void 0) return;
33
+ const marker = this.#markers[hoveredMarkerIndex];
34
+ if (marker === void 0) {
35
+ this.removePopup();
36
+ return;
37
+ }
38
+ this.#positionMarkerPopup(popup, marker.start.line, marker.start.character);
39
+ }
40
+ setMarkers(markers, textDocument) {
41
+ this.#lineCount = textDocument.lineCount;
42
+ this.#markers = markers.map((marker) => ({
43
+ ...marker,
44
+ start: textDocument.normalizePosition(marker.start),
45
+ end: textDocument.normalizePosition(marker.end)
46
+ }));
47
+ this.removePopup();
48
+ }
49
+ listenHover(contentEl) {
50
+ this.#markerEventDisposes?.forEach((dispose) => dispose());
51
+ this.#markerEventDisposes = void 0;
52
+ if (this.#markers.length === 0) return;
53
+ this.#markerEventDisposes = [addEventListener(contentEl, "mouseover", (e) => {
54
+ if (this.#options.isMouseDown()) return;
55
+ const target = e.composedPath()[0];
56
+ if (target === void 0) return;
57
+ const hoverMarkerIndex = this.#findHoveredMarkerIndex(target);
58
+ if (hoverMarkerIndex !== void 0) this.#scheduleMarkerPopup(hoverMarkerIndex);
59
+ else {
60
+ this.#cancelMarkerPopupShow();
61
+ this.#scheduleMarkerPopupHide();
62
+ }
63
+ }), addEventListener(contentEl, "mouseleave", () => {
64
+ this.#cancelMarkerPopupShow();
65
+ this.#scheduleMarkerPopupHide();
66
+ })];
67
+ }
68
+ removePopup() {
69
+ this.#cancelMarkerPopupShow();
70
+ this.#cancelMarkerPopupHide();
71
+ this.#dismissMarkerPopup();
72
+ }
73
+ cleanup() {
74
+ this.#markerEventDisposes?.forEach((dispose) => dispose());
75
+ this.#markerEventDisposes = void 0;
76
+ this.removePopup();
77
+ this.#markers = [];
78
+ }
79
+ #findHoveredMarkerIndex(target) {
80
+ const lineElement = target.closest("[data-line]");
81
+ if (lineElement == null) return;
82
+ const lineNumber = getLineNumberAttr(lineElement);
83
+ if (lineNumber === void 0) return;
84
+ let character;
85
+ if (target.tagName === "SPAN") {
86
+ const char = target.dataset.char;
87
+ if (char === void 0) return;
88
+ character = parseInt(char, 10);
89
+ if (Number.isNaN(character)) return;
90
+ } else if (target.tagName === "BR") character = 0;
91
+ else return;
92
+ const position = {
93
+ line: lineNumber - 1,
94
+ character
95
+ };
96
+ for (let i = this.#markers.length - 1; i >= 0; i--) if (selectionIntersects({
97
+ start: position,
98
+ end: position
99
+ }, this.#markers[i])) return i;
100
+ }
101
+ #cancelMarkerPopupShow() {
102
+ if (this.#markerPopupShowTimeout !== void 0) {
103
+ clearTimeout(this.#markerPopupShowTimeout);
104
+ this.#markerPopupShowTimeout = void 0;
105
+ }
106
+ this.#pendingMarkerPopupIndex = void 0;
107
+ }
108
+ #cancelMarkerPopupHide() {
109
+ if (this.#markerPopupHideTimeout !== void 0) {
110
+ clearTimeout(this.#markerPopupHideTimeout);
111
+ this.#markerPopupHideTimeout = void 0;
112
+ }
113
+ }
114
+ #scheduleMarkerPopup(markerIndex) {
115
+ if (markerIndex === this.#hoveredMarkerIndex || markerIndex === this.#pendingMarkerPopupIndex) {
116
+ this.#cancelMarkerPopupHide();
117
+ return;
118
+ }
119
+ this.#cancelMarkerPopupShow();
120
+ this.#cancelMarkerPopupHide();
121
+ if (this.#markerPopupElement !== void 0) {
122
+ this.#renderMarkerPopup(markerIndex);
123
+ return;
124
+ }
125
+ this.#pendingMarkerPopupIndex = markerIndex;
126
+ this.#markerPopupShowTimeout = setTimeout(() => {
127
+ this.#markerPopupShowTimeout = void 0;
128
+ this.#pendingMarkerPopupIndex = void 0;
129
+ this.#renderMarkerPopup(markerIndex);
130
+ }, MARKER_POPUP_SHOW_DELAY_MS);
131
+ }
132
+ #scheduleMarkerPopupHide() {
133
+ if (this.#isMarkerPopupHovered) return;
134
+ this.#cancelMarkerPopupHide();
135
+ this.#markerPopupHideTimeout = setTimeout(() => {
136
+ this.#markerPopupHideTimeout = void 0;
137
+ if (!this.#isMarkerPopupHovered) this.removePopup();
138
+ }, MARKER_POPUP_HIDE_DELAY_MS);
139
+ }
140
+ #setMarkerPopupPosition(popup, x, y, placeAbove, viewport = this.#options.popoverManager.getPlacementBounds()) {
141
+ setPopoverPositionStyles(popup, {
142
+ gutterWidth: this.#options.getGutterWidth(),
143
+ placeAbove,
144
+ viewport,
145
+ x,
146
+ y
147
+ });
148
+ }
149
+ #positionMarkerPopup(popup, line, character) {
150
+ const { getCharX, getLineY, getLineHeight, popoverManager } = this.#options;
151
+ const [left, wrapLine] = getCharX(line, character);
152
+ const lineHeight = getLineHeight();
153
+ const rowTop = getLineY(line) + wrapLine * lineHeight;
154
+ const popoverHeight = popup.offsetHeight;
155
+ const preferred = {
156
+ top: rowTop + lineHeight,
157
+ bottom: rowTop + lineHeight + popoverHeight
158
+ };
159
+ const fallback = {
160
+ top: rowTop - popoverHeight,
161
+ bottom: rowTop
162
+ };
163
+ const atDocumentEdge = line >= this.#lineCount - 3;
164
+ const viewport = popoverManager.getPlacementBounds();
165
+ const placeAbove = popoverManager.choosePlacement({
166
+ preferred,
167
+ fallback,
168
+ viewport,
169
+ popoverHeight,
170
+ atDocumentEdge,
171
+ placementKey: MARKER_POPUP_PLACEMENT_KEY
172
+ }) === "fallback";
173
+ this.#setMarkerPopupPosition(popup, left, placeAbove ? rowTop : rowTop + lineHeight, placeAbove, viewport);
174
+ }
175
+ #dismissMarkerPopup() {
176
+ this.#markerPopupEventDisposes?.forEach((dispose) => dispose());
177
+ this.#markerPopupEventDisposes = void 0;
178
+ this.#markerPopupElement?.remove();
179
+ this.#markerPopupElement = void 0;
180
+ this.#hoveredMarkerIndex = void 0;
181
+ this.#isMarkerPopupHovered = false;
182
+ this.#options.popoverManager.resetPlacement(MARKER_POPUP_PLACEMENT_KEY);
183
+ }
184
+ #renderMarkerPopup(hoveredMarkerIndex) {
185
+ if (hoveredMarkerIndex === this.#hoveredMarkerIndex) return;
186
+ const overlayElement = this.#options.getOverlayElement();
187
+ if (hoveredMarkerIndex >= this.#markers.length || overlayElement == null) return;
188
+ const { start, message, severity } = this.#markers[hoveredMarkerIndex];
189
+ const { line, character } = start;
190
+ const popup = this.#markerPopupElement;
191
+ this.#options.popoverManager.resetPlacement(MARKER_POPUP_PLACEMENT_KEY);
192
+ if (popup !== void 0) {
193
+ setMarkerPopupSeverity(popup, severity);
194
+ const content = popup.firstElementChild;
195
+ if (content?.dataset.markerMessage !== void 0) if (typeof message === "string") content.textContent = message;
196
+ else if (message instanceof HTMLElement) content.replaceChildren(message);
197
+ else content.innerHTML = message.html;
198
+ this.#positionMarkerPopup(popup, line, character);
199
+ this.#hoveredMarkerIndex = hoveredMarkerIndex;
200
+ return;
201
+ }
202
+ this.#markerPopupElement = h("div", {
203
+ dataset: {
204
+ editorWidget: "",
205
+ markerPopup: "",
206
+ [markerSeverityDatasetKey(severity)]: ""
207
+ },
208
+ children: [h("div", {
209
+ dataset: "markerMessage",
210
+ ...typeof message === "string" ? { textContent: message } : message instanceof HTMLElement ? { children: [message] } : { innerHTML: message.html }
211
+ })]
212
+ }, overlayElement);
213
+ this.#positionMarkerPopup(this.#markerPopupElement, line, character);
214
+ this.#hoveredMarkerIndex = hoveredMarkerIndex;
215
+ this.#markerPopupEventDisposes = [addEventListener(this.#markerPopupElement, "mouseenter", () => {
216
+ this.#isMarkerPopupHovered = true;
217
+ this.#cancelMarkerPopupHide();
218
+ }), addEventListener(this.#markerPopupElement, "mouseleave", () => {
219
+ this.#isMarkerPopupHovered = false;
220
+ this.#scheduleMarkerPopupHide();
221
+ })];
222
+ }
223
+ };
224
+ const MARKER_SEVERITIES = [
225
+ "error",
226
+ "warning",
227
+ "info",
228
+ "hint"
229
+ ];
230
+ function setMarkerPopupSeverity(popup, severity) {
231
+ for (const candidate of MARKER_SEVERITIES) delete popup.dataset[markerSeverityDatasetKey(candidate)];
232
+ popup.dataset[markerSeverityDatasetKey(severity)] = "";
233
+ }
234
+ function markerSeverityDatasetKey(severity) {
235
+ switch (severity) {
236
+ case "error": return "markerError";
237
+ case "warning": return "markerWarning";
238
+ case "info": return "markerInfo";
239
+ case "hint": return "markerHint";
240
+ }
241
+ }
242
+ //#endregion
243
+ export { MarkerRenderer, markerSeverityDatasetKey };
244
+
245
+ //# sourceMappingURL=marker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marker.js","names":["#options","#markers","#hoveredMarkerIndex","#markerPopupElement","#positionMarkerPopup","#lineCount","#markerEventDisposes","#findHoveredMarkerIndex","#scheduleMarkerPopup","#cancelMarkerPopupShow","#scheduleMarkerPopupHide","#cancelMarkerPopupHide","#dismissMarkerPopup","#markerPopupShowTimeout","#pendingMarkerPopupIndex","#markerPopupHideTimeout","#renderMarkerPopup","#isMarkerPopupHovered","#setMarkerPopupPosition","#markerPopupEventDisposes"],"sources":["../../src/editor/marker.ts"],"sourcesContent":["import type { Position, Range } from '../types';\nimport {\n POPOVER_BOUNDARY_LINES,\n type PopoverManager,\n type PopoverPlacementBounds,\n setPopoverPositionStyles,\n} from './popover';\nimport { selectionIntersects } from './selection';\nimport type { TextDocument } from './textDocument';\nimport { addEventListener, getLineNumberAttr, h } from './utils';\n\nconst MARKER_POPUP_SHOW_DELAY_MS = 300;\nconst MARKER_POPUP_HIDE_DELAY_MS = 100;\nconst MARKER_POPUP_PLACEMENT_KEY = 'marker-popup';\n\nexport type MarkerSeverity = 'error' | 'warning' | 'info' | 'hint';\n\nexport interface Marker extends Range {\n severity: MarkerSeverity;\n message: string | { html: string } | HTMLElement;\n source?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface MarkerRenderOptions {\n popoverManager: PopoverManager;\n getLineHeight: () => number;\n getOverlayElement: () => HTMLElement | undefined;\n getGutterWidth: () => number;\n getCharX: (line: number, character: number) => [number, number];\n getLineY: (line: number) => number;\n isMouseDown: () => boolean;\n}\n\nexport class MarkerRenderer {\n #options: MarkerRenderOptions;\n #markers: Marker[] = [];\n // Document line count, used only by the no-viewport document-edge fallback.\n #lineCount = 0;\n #markerPopupElement?: HTMLElement;\n #markerPopupEventDisposes?: (() => void)[];\n #markerEventDisposes?: (() => void)[];\n #markerPopupShowTimeout?: ReturnType<typeof setTimeout>;\n #markerPopupHideTimeout?: ReturnType<typeof setTimeout>;\n #pendingMarkerPopupIndex?: number;\n #hoveredMarkerIndex?: number;\n #isMarkerPopupHovered = false;\n\n constructor(editor: MarkerRenderOptions) {\n this.#options = editor;\n }\n\n get markers(): readonly Marker[] {\n return this.#markers;\n }\n\n isPopupVisible(): boolean {\n return this.#hoveredMarkerIndex !== undefined;\n }\n\n updatePopupPosition(): void {\n const hoveredMarkerIndex = this.#hoveredMarkerIndex;\n const popup = this.#markerPopupElement;\n if (hoveredMarkerIndex === undefined || popup === undefined) {\n return;\n }\n const marker = this.#markers[hoveredMarkerIndex];\n if (marker === undefined) {\n this.removePopup();\n return;\n }\n this.#positionMarkerPopup(popup, marker.start.line, marker.start.character);\n }\n\n setMarkers<LAnnotation>(\n markers: Marker[],\n textDocument: TextDocument<LAnnotation>\n ): void {\n this.#lineCount = textDocument.lineCount;\n this.#markers = markers.map((marker) => ({\n ...marker,\n start: textDocument.normalizePosition(marker.start),\n end: textDocument.normalizePosition(marker.end),\n }));\n this.removePopup();\n }\n\n listenHover(contentEl: HTMLElement): void {\n this.#markerEventDisposes?.forEach((dispose) => dispose());\n this.#markerEventDisposes = undefined;\n if (this.#markers.length === 0) {\n return;\n }\n\n this.#markerEventDisposes = [\n addEventListener(contentEl, 'mouseover', (e) => {\n if (this.#options.isMouseDown()) {\n return;\n }\n const target = e.composedPath()[0] as HTMLElement | undefined;\n if (target === undefined) {\n return;\n }\n\n const hoverMarkerIndex = this.#findHoveredMarkerIndex(target);\n if (hoverMarkerIndex !== undefined) {\n this.#scheduleMarkerPopup(hoverMarkerIndex);\n } else {\n this.#cancelMarkerPopupShow();\n this.#scheduleMarkerPopupHide();\n }\n }),\n addEventListener(contentEl, 'mouseleave', () => {\n this.#cancelMarkerPopupShow();\n this.#scheduleMarkerPopupHide();\n }),\n ];\n }\n\n removePopup(): void {\n this.#cancelMarkerPopupShow();\n this.#cancelMarkerPopupHide();\n this.#dismissMarkerPopup();\n }\n\n cleanup(): void {\n this.#markerEventDisposes?.forEach((dispose) => dispose());\n this.#markerEventDisposes = undefined;\n this.removePopup();\n this.#markers = [];\n }\n\n #findHoveredMarkerIndex(target: HTMLElement): number | undefined {\n const lineElement = target.closest('[data-line]');\n if (lineElement == null) {\n return;\n }\n\n const lineNumber = getLineNumberAttr(lineElement as HTMLElement);\n if (lineNumber === undefined) {\n return;\n }\n\n let character: number | undefined;\n if (target.tagName === 'SPAN') {\n const char = target.dataset.char;\n if (char === undefined) {\n return;\n }\n character = parseInt(char, 10);\n if (Number.isNaN(character)) {\n return;\n }\n } else if (target.tagName === 'BR') {\n character = 0;\n } else {\n return;\n }\n\n const position: Position = { line: lineNumber - 1, character };\n for (let i = this.#markers.length - 1; i >= 0; i--) {\n if (\n selectionIntersects(\n { start: position, end: position },\n this.#markers[i]\n )\n ) {\n return i;\n }\n }\n return undefined;\n }\n\n #cancelMarkerPopupShow(): void {\n if (this.#markerPopupShowTimeout !== undefined) {\n clearTimeout(this.#markerPopupShowTimeout);\n this.#markerPopupShowTimeout = undefined;\n }\n this.#pendingMarkerPopupIndex = undefined;\n }\n\n #cancelMarkerPopupHide(): void {\n if (this.#markerPopupHideTimeout !== undefined) {\n clearTimeout(this.#markerPopupHideTimeout);\n this.#markerPopupHideTimeout = undefined;\n }\n }\n\n #scheduleMarkerPopup(markerIndex: number): void {\n if (\n markerIndex === this.#hoveredMarkerIndex ||\n markerIndex === this.#pendingMarkerPopupIndex\n ) {\n this.#cancelMarkerPopupHide();\n return;\n }\n\n this.#cancelMarkerPopupShow();\n this.#cancelMarkerPopupHide();\n if (this.#markerPopupElement !== undefined) {\n this.#renderMarkerPopup(markerIndex);\n return;\n }\n\n this.#pendingMarkerPopupIndex = markerIndex;\n this.#markerPopupShowTimeout = setTimeout(() => {\n this.#markerPopupShowTimeout = undefined;\n this.#pendingMarkerPopupIndex = undefined;\n this.#renderMarkerPopup(markerIndex);\n }, MARKER_POPUP_SHOW_DELAY_MS);\n }\n\n #scheduleMarkerPopupHide(): void {\n if (this.#isMarkerPopupHovered) {\n return;\n }\n\n this.#cancelMarkerPopupHide();\n this.#markerPopupHideTimeout = setTimeout(() => {\n this.#markerPopupHideTimeout = undefined;\n if (!this.#isMarkerPopupHovered) {\n this.removePopup();\n }\n }, MARKER_POPUP_HIDE_DELAY_MS);\n }\n\n // Positions the popup in overlay coordinate space (see [data-marker-popup]\n // in editor.css). When `placeAbove` is true, `y` is the top edge of the\n // marker's row and the popup is shifted up by its own height.\n #setMarkerPopupPosition(\n popup: HTMLElement,\n x: number,\n y: number,\n placeAbove: boolean,\n viewport = this.#options.popoverManager.getPlacementBounds()\n ): void {\n setPopoverPositionStyles(popup, {\n gutterWidth: this.#options.getGutterWidth(),\n placeAbove,\n viewport,\n x,\n y,\n });\n }\n\n // Positions the popup for a marker at `(line, character)`: prefers below\n // (the default), flipping above when below would be clipped by the visible\n // scrollport. Must run after the popup's content is final, since it reads\n // the popup's rendered height to decide whether either side fits.\n #positionMarkerPopup(\n popup: HTMLElement,\n line: number,\n character: number\n ): void {\n const { getCharX, getLineY, getLineHeight, popoverManager } = this.#options;\n const [left, wrapLine] = getCharX(line, character);\n const lineHeight = getLineHeight();\n const rowTop = getLineY(line) + wrapLine * lineHeight;\n const popoverHeight = popup.offsetHeight;\n\n const preferred: PopoverPlacementBounds = {\n top: rowTop + lineHeight,\n bottom: rowTop + lineHeight + popoverHeight,\n };\n const fallback: PopoverPlacementBounds = {\n top: rowTop - popoverHeight,\n bottom: rowTop,\n };\n const atDocumentEdge = line >= this.#lineCount - POPOVER_BOUNDARY_LINES;\n const viewport = popoverManager.getPlacementBounds();\n const placeAbove =\n popoverManager.choosePlacement({\n preferred,\n fallback,\n viewport,\n popoverHeight,\n atDocumentEdge,\n placementKey: MARKER_POPUP_PLACEMENT_KEY,\n }) === 'fallback';\n\n this.#setMarkerPopupPosition(\n popup,\n left,\n placeAbove ? rowTop : rowTop + lineHeight,\n placeAbove,\n viewport\n );\n }\n\n #dismissMarkerPopup(): void {\n this.#markerPopupEventDisposes?.forEach((dispose) => dispose());\n this.#markerPopupEventDisposes = undefined;\n this.#markerPopupElement?.remove();\n this.#markerPopupElement = undefined;\n this.#hoveredMarkerIndex = undefined;\n this.#isMarkerPopupHovered = false;\n this.#options.popoverManager.resetPlacement(MARKER_POPUP_PLACEMENT_KEY);\n }\n\n #renderMarkerPopup(hoveredMarkerIndex: number): void {\n if (hoveredMarkerIndex === this.#hoveredMarkerIndex) {\n return;\n }\n\n const overlayElement = this.#options.getOverlayElement();\n if (hoveredMarkerIndex >= this.#markers.length || overlayElement == null) {\n return;\n }\n\n const { start, message, severity } = this.#markers[hoveredMarkerIndex];\n const { line, character } = start;\n const popup = this.#markerPopupElement;\n this.#options.popoverManager.resetPlacement(MARKER_POPUP_PLACEMENT_KEY);\n\n if (popup !== undefined) {\n setMarkerPopupSeverity(popup, severity);\n const content = popup.firstElementChild as HTMLElement | null;\n if (content?.dataset.markerMessage !== undefined) {\n if (typeof message === 'string') {\n content.textContent = message;\n } else if (message instanceof HTMLElement) {\n content.replaceChildren(message);\n } else {\n content.innerHTML = message.html;\n }\n }\n // Position after updating content: a different message size changes\n // the offsetHeight #positionMarkerPopup reads to decide placement.\n this.#positionMarkerPopup(popup, line, character);\n this.#hoveredMarkerIndex = hoveredMarkerIndex;\n return;\n }\n\n this.#markerPopupElement = h(\n 'div',\n {\n dataset: {\n editorWidget: '',\n markerPopup: '',\n [markerSeverityDatasetKey(severity)]: '',\n },\n children: [\n h('div', {\n dataset: 'markerMessage',\n ...(typeof message === 'string'\n ? { textContent: message }\n : message instanceof HTMLElement\n ? { children: [message] }\n : { innerHTML: message.html }),\n }),\n ],\n },\n overlayElement\n );\n this.#positionMarkerPopup(this.#markerPopupElement, line, character);\n this.#hoveredMarkerIndex = hoveredMarkerIndex;\n this.#markerPopupEventDisposes = [\n addEventListener(this.#markerPopupElement, 'mouseenter', () => {\n this.#isMarkerPopupHovered = true;\n this.#cancelMarkerPopupHide();\n }),\n addEventListener(this.#markerPopupElement, 'mouseleave', () => {\n this.#isMarkerPopupHovered = false;\n this.#scheduleMarkerPopupHide();\n }),\n ];\n }\n}\n\nconst MARKER_SEVERITIES: readonly MarkerSeverity[] = [\n 'error',\n 'warning',\n 'info',\n 'hint',\n];\n\n// Marks the popup with data-marker-<severity> (the same boolean attribute the\n// squiggle range element uses) so the CSS severity palette can target both with\n// a single selector. The popup element is reused across hovers, so any\n// previously applied severity attribute is cleared first.\nfunction setMarkerPopupSeverity(\n popup: HTMLElement,\n severity: MarkerSeverity\n): void {\n for (const candidate of MARKER_SEVERITIES) {\n delete popup.dataset[markerSeverityDatasetKey(candidate)];\n }\n popup.dataset[markerSeverityDatasetKey(severity)] = '';\n}\n\nexport function markerSeverityDatasetKey(severity: MarkerSeverity): string {\n switch (severity) {\n case 'error':\n return 'markerError';\n case 'warning':\n return 'markerWarning';\n case 'info':\n return 'markerInfo';\n case 'hint':\n return 'markerHint';\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { Position, Range } from "../types.js";
2
+ import { TextDocument } from "./textDocument.js";
3
+ import { EditorTokenizer } from "./tokenizer.js";
4
+
5
+ //#region src/editor/matchBrackets.d.ts
6
+ declare function findBracketMatchRanges<LAnnotation>(textDocument: TextDocument<LAnnotation>, tokenizer: EditorTokenizer, position: Position): [open: Range, close: Range] | undefined;
7
+ //#endregion
8
+ export { findBracketMatchRanges };
9
+ //# sourceMappingURL=matchBrackets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matchBrackets.d.ts","names":[],"sources":["../../src/editor/matchBrackets.ts"],"mappings":";;;;;iBAqBgB,sBAAA,cACd,YAAA,EAAc,YAAA,CAAa,WAAA,GAC3B,SAAA,EAAW,eAAA,EACX,QAAA,EAAU,QAAA,IACR,IAAA,EAAM,KAAA,EAAO,KAAA,EAAO,KAAA"}