@pierre/diffs 1.3.0-beta.8 → 1.3.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/CodeView.d.ts +12 -12
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +51 -43
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +7 -2
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +36 -8
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +34 -6
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +198 -17
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/FileStream.d.ts.map +1 -1
- package/dist/components/FileStream.js +2 -1
- package/dist/components/FileStream.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +2 -1
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +9 -5
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +14 -0
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +61 -3
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/Virtualizer.d.ts +14 -2
- package/dist/components/Virtualizer.d.ts.map +1 -1
- package/dist/components/Virtualizer.js +29 -3
- package/dist/components/Virtualizer.js.map +1 -1
- package/dist/edit/index.d.ts +5 -0
- package/dist/edit/index.js +3 -0
- package/dist/editor/command.d.ts +1 -1
- package/dist/editor/command.d.ts.map +1 -1
- package/dist/editor/command.js +11 -0
- package/dist/editor/command.js.map +1 -1
- package/dist/editor/editStack.d.ts +6 -2
- package/dist/editor/editStack.d.ts.map +1 -1
- package/dist/editor/editStack.js +54 -13
- package/dist/editor/editStack.js.map +1 -1
- package/dist/editor/editor.d.ts +51 -23
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +995 -242
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +1 -1
- package/dist/editor/languages.d.ts +26 -0
- package/dist/editor/languages.d.ts.map +1 -0
- package/dist/editor/languages.js +363 -0
- package/dist/editor/languages.js.map +1 -0
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +25 -26
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +5 -3
- package/dist/editor/marker.d.ts.map +1 -1
- package/dist/editor/marker.js +111 -91
- package/dist/editor/marker.js.map +1 -1
- package/dist/editor/matchBrackets.d.ts +3 -2
- package/dist/editor/matchBrackets.d.ts.map +1 -1
- package/dist/editor/matchBrackets.js +2 -10
- package/dist/editor/matchBrackets.js.map +1 -1
- package/dist/editor/pieceTable.d.ts +2 -1
- package/dist/editor/pieceTable.d.ts.map +1 -1
- package/dist/editor/pieceTable.js +103 -39
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/platform.js +2 -0
- package/dist/editor/platform.js.map +1 -1
- package/dist/editor/popover.d.ts +25 -5
- package/dist/editor/popover.d.ts.map +1 -1
- package/dist/editor/popover.js +60 -14
- package/dist/editor/popover.js.map +1 -1
- package/dist/editor/searchPanel.d.ts +1 -0
- package/dist/editor/searchPanel.d.ts.map +1 -1
- package/dist/editor/searchPanel.js +15 -8
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +31 -11
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +198 -70
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/selectionAction.d.ts +4 -3
- package/dist/editor/selectionAction.d.ts.map +1 -1
- package/dist/editor/selectionAction.js +9 -5
- package/dist/editor/selectionAction.js.map +1 -1
- package/dist/editor/stateStorage.d.ts +15 -0
- package/dist/editor/stateStorage.d.ts.map +1 -0
- package/dist/editor/stateStorage.js +65 -0
- package/dist/editor/stateStorage.js.map +1 -0
- package/dist/editor/textDocument.d.ts +12 -77
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +76 -34
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/textMeasure.d.ts +7 -12
- package/dist/editor/textMeasure.d.ts.map +1 -1
- package/dist/editor/textMeasure.js +40 -32
- package/dist/editor/textMeasure.js.map +1 -1
- package/dist/editor/{tokenzier.d.ts → tokenizer.d.ts} +3 -3
- package/dist/editor/tokenizer.d.ts.map +1 -0
- package/dist/editor/{tokenzier.js → tokenizer.js} +91 -26
- package/dist/editor/tokenizer.js.map +1 -0
- package/dist/editor/utils.js +1 -1
- package/dist/editor/utils.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +7 -6
- package/dist/managers/InteractionManager.d.ts +18 -7
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/InteractionManager.js +154 -99
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/managers/UniversalRenderingManager.d.ts +2 -1
- package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
- package/dist/managers/UniversalRenderingManager.js +7 -3
- package/dist/managers/UniversalRenderingManager.js.map +1 -1
- package/dist/react/CodeView.d.ts +13 -13
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +38 -29
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/EditContext.d.ts +20 -0
- package/dist/react/EditContext.d.ts.map +1 -0
- package/dist/react/EditContext.js +20 -0
- package/dist/react/EditContext.js.map +1 -0
- package/dist/react/File.d.ts +2 -1
- package/dist/react/File.d.ts.map +1 -1
- package/dist/react/File.js +3 -2
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.d.ts +2 -2
- package/dist/react/FileDiff.d.ts.map +1 -1
- package/dist/react/FileDiff.js +3 -2
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.d.ts +2 -2
- package/dist/react/MultiFileDiff.d.ts.map +1 -1
- package/dist/react/MultiFileDiff.js +3 -2
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.d.ts +2 -2
- package/dist/react/PatchDiff.d.ts.map +1 -1
- package/dist/react/PatchDiff.js +3 -2
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/UnresolvedFile.d.ts +1 -1
- package/dist/react/UnresolvedFile.js.map +1 -1
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +3 -3
- package/dist/react/types.d.ts +9 -1
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.d.ts +5 -3
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +28 -27
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts +5 -3
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js +29 -25
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.js +3 -3
- package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +33 -1
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +134 -21
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +2 -0
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +33 -11
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/ssr/FileDiffReact.js +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/preloadDiffs.js +1 -1
- package/dist/style.js +1 -1
- package/dist/types.d.ts +185 -42
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/annotationHelpers.d.ts +20 -0
- package/dist/utils/annotationHelpers.d.ts.map +1 -0
- package/dist/utils/annotationHelpers.js +29 -0
- package/dist/utils/annotationHelpers.js.map +1 -0
- package/dist/utils/computeFileOffsets.d.ts.map +1 -1
- package/dist/utils/computeFileOffsets.js +34 -5
- package/dist/utils/computeFileOffsets.js.map +1 -1
- package/dist/utils/editSessionHunks.d.ts +66 -0
- package/dist/utils/editSessionHunks.d.ts.map +1 -0
- package/dist/utils/editSessionHunks.js +437 -0
- package/dist/utils/editSessionHunks.js.map +1 -0
- package/dist/utils/getHunkSideBoundaries.d.ts +7 -0
- package/dist/utils/getHunkSideBoundaries.d.ts.map +1 -0
- package/dist/utils/getHunkSideBoundaries.js +12 -0
- package/dist/utils/getHunkSideBoundaries.js.map +1 -0
- package/dist/utils/getTotalLineCountFromHunks.d.ts.map +1 -1
- package/dist/utils/getTotalLineCountFromHunks.js +2 -1
- package/dist/utils/getTotalLineCountFromHunks.js.map +1 -1
- package/dist/utils/hydratePartialDiff.d.ts.map +1 -1
- package/dist/utils/hydratePartialDiff.js +4 -3
- package/dist/utils/hydratePartialDiff.js.map +1 -1
- package/dist/utils/isGutterUtilityPath.d.ts +5 -0
- package/dist/utils/isGutterUtilityPath.d.ts.map +1 -0
- package/dist/utils/isGutterUtilityPath.js +12 -0
- package/dist/utils/isGutterUtilityPath.js.map +1 -0
- package/dist/utils/iterateOverDiff.d.ts.map +1 -1
- package/dist/utils/iterateOverDiff.js +17 -12
- package/dist/utils/iterateOverDiff.js.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.js +9 -6
- package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
- package/dist/utils/parsePatchFiles.d.ts.map +1 -1
- package/dist/utils/parsePatchFiles.js +6 -3
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/realignChangeContent.d.ts +33 -0
- package/dist/utils/realignChangeContent.d.ts.map +1 -0
- package/dist/utils/realignChangeContent.js +148 -0
- package/dist/utils/realignChangeContent.js.map +1 -0
- package/dist/utils/renderDiffWithHighlighter.js +1 -1
- package/dist/utils/resolveRegion.d.ts.map +1 -1
- package/dist/utils/resolveRegion.js +18 -2
- package/dist/utils/resolveRegion.js.map +1 -1
- package/dist/utils/updateDiffHunks.d.ts +8 -2
- package/dist/utils/updateDiffHunks.d.ts.map +1 -1
- package/dist/utils/updateDiffHunks.js +9 -7
- package/dist/utils/updateDiffHunks.js.map +1 -1
- package/dist/utils/virtualDiffLayout.d.ts +42 -2
- package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
- package/dist/utils/virtualDiffLayout.js +101 -7
- package/dist/utils/virtualDiffLayout.js.map +1 -1
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +4 -2
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/types.d.ts +4 -0
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/worker-portable.js +60 -20
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +61 -19
- package/dist/worker/worker.js.map +1 -1
- package/package.json +13 -8
- package/dist/editor/index.d.ts +0 -3
- package/dist/editor/index.js +0 -3
- package/dist/editor/tokenzier.d.ts.map +0 -1
- package/dist/editor/tokenzier.js.map +0 -1
- package/dist/react/EditorContext.d.ts +0 -15
- package/dist/react/EditorContext.d.ts.map +0 -1
- package/dist/react/EditorContext.js +0 -23
- package/dist/react/EditorContext.js.map +0 -1
package/dist/editor/editor2.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/editor/editor.css?inline
|
|
2
|
-
var editor_default = "::selection {\n background-color: #0000;\n}\n\n[data-deleted-text-selection] [data-deletions] ::selection, [data-deleted-text-selection] [data-line-type=\"change-deletion\"] ::selection {\n background-color: var(--diffs-editor-selection-bg);\n}\n\n@keyframes blinking {\n 0% {\n opacity: 1;\n }\n\n 50% {\n opacity: 0;\n }\n\n 100% {\n opacity: 1;\n }\n}\n\n:host, [data-code], [data-content], [data-diff-type=\"split\"][data-overflow=\"wrap\"] {\n position: relative;\n}\n\n[data-code] {\n container-type: inline-size;\n}\n\n[data-content] {\n cursor: text;\n caret-color: var(--diffs-bg-caret);\n background-color: #0000;\n outline: none;\n}\n\n[data-line] {\n cursor: text;\n background-color: #0000;\n}\n\n[data-line]:after {\n content: \"\";\n z-index: -20;\n background-color: var(--diffs-line-bg);\n pointer-events: none;\n position: absolute;\n inset: 0;\n}\n\n[data-line][data-selected-line]:after {\n background-color: var(--diffs-computed-diff-line-bg, var(--diffs-bg));\n background-image: linear-gradient(var(--diffs-editor-line-highlight-bg),\n var(--diffs-editor-line-highlight-bg));\n}\n\n[data-editor-overlay] {\n display: contents;\n}\n\n[data-caret], [data-selection-range], [data-match-range], [data-bracket-match-range], [data-marker-range] {\n height: 1lh;\n line-height: var(--diffs-line-height);\n pointer-events: none;\n position: absolute;\n top: 0;\n left: 0;\n}\n\n[data-caret] {\n background-color: var(--diffs-bg-caret-override, var(--diffs-editor-cursor-fg, light-dark(color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg)), color-mix(in lab, var(--diffs-fg) 75%, var(--diffs-bg)))));\n visibility: hidden;\n width: 2px;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n [data-caret] {\n animation: 1.2s .8s infinite blinking;\n }\n}\n\n[data-selection-range] {\n z-index: -10;\n background-color: var(--diffs-editor-selection-bg);\n}\n\n[data-selection-corner] {\n background-color: var(--diffs-selection-corner-bg, var(--diffs-bg));\n width: 100%;\n height: 100%;\n}\n\n[data-match-range] {\n z-index: -10;\n background-color: var(--diffs-editor-match-bg, var(--diffs-editor-selection-bg));\n}\n\n[data-match-range]:not([data-focus]) {\n background-color: var(--diffs-editor-match-highlight-bg, light-dark(#ff963288, #ff963266));\n}\n\n[data-bracket-match-range] {\n z-index: -9;\n box-sizing: border-box;\n border-bottom: 1px solid\n var(--diffs-editor-bracket-match-border, color-mix(in lab, var(--diffs-fg) 60%, transparent));\n background-color: var(--diffs-editor-bracket-match-bg, color-mix(in lab, var(--diffs-fg) 5%, transparent));\n}\n\n[data-rtl] {\n border-top-left-radius: 3px;\n}\n\n[data-rtr] {\n border-top-right-radius: 3px;\n}\n\n[data-rbl] {\n border-bottom-left-radius: 3px;\n}\n\n[data-rbr] {\n border-bottom-right-radius: 3px;\n}\n\n[data-marker-range] {\n z-index: 1;\n background-color: var(--diffs-marker-bg);\n mask-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2IiBoZWlnaHQ9IjMiPjxwYXRoIGQ9Im0wIDIuNSBsMiAtMS41IGwxIDAgbDIgMS41IGwxIDAiIHN0cm9rZT0iI2ZmZiIgZmlsbD0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PC9zdmc+\");\n mask-position: 0 100%;\n mask-size: 6px 3px;\n mask-repeat: repeat-x;\n}\n\n[data-marker-error] {\n --diffs-marker-contrast: #fff;\n --diffs-marker-bg: var(--diffs-editor-error-fg, var(--diffs-deletion-base));\n}\n\n[data-marker-warning] {\n --diffs-marker-contrast: #000;\n --diffs-marker-bg: var(--diffs-editor-warning-fg, light-dark(var(--diffs-warning-light), var(--diffs-warning-dark)));\n}\n\n[data-marker-info] {\n --diffs-marker-contrast: #fff;\n --diffs-marker-bg: var(--diffs-editor-info-fg, var(--diffs-modified-base));\n}\n\n[data-marker-hint] {\n --diffs-marker-contrast: light-dark(#fff, #000);\n --diffs-marker-bg: var(--diffs-editor-hint-fg, var(--diffs-fg-number));\n}\n\n@media (width >= 480px) {\n [data-content] {\n caret-color: #0000;\n }\n\n [data-content]:focus ~ [data-editor-overlay] [data-caret] {\n visibility: visible;\n }\n}\n\n[data-editor-widget] {\n --diffs-widget-fg: var(--diffs-fg);\n --diffs-widget-bg: color-mix(in lab, var(--diffs-fg) 4%, var(--diffs-bg));\n --diffs-widget-border: color-mix(in lab, var(--diffs-fg) 20%, transparent);\n --diffs-widget-shadow: inset 0 0 0 1px var(--diffs-bg), 0 4px 8px #00000013,\n 0 6px 18px #00000013;\n z-index: 100;\n width: fit-content;\n max-width: calc(100% - 24px);\n font: 14px/20px var(--diffs-header-font-fallback);\n border: 1px solid var(--diffs-widget-border);\n background-color: var(--diffs-widget-bg);\n box-shadow: var(--diffs-widget-shadow);\n background-clip: padding-box;\n border-radius: 9px;\n position: absolute;\n top: 0;\n left: 0;\n}\n\n[data-marker-popup], [data-selection-action-popover] {\n --popover-min-left: calc(var(--gutter-width, 0px) + 8px);\n --popover-available-width: calc(100cqw - var(--gutter-width, 0px) - 16px);\n max-width: min(640px, var(--popover-available-width));\n translate: clamp(var(--popover-min-left),\n var(--popover-x, var(--popover-min-left)),\n calc(100cqw - 8px - 100%))\n calc(var(--popover-y, 0px) + var(--popover-y-shift, 0px));\n}\n\n[data-marker-popup] {\n --diffs-widget-bg: var(--diffs-marker-bg);\n --diffs-widget-shadow: 0 4px 8px #00000026, 0 6px 18px #00000026;\n overflow-wrap: anywhere;\n min-width: min(180px, 100cqw - 24px);\n color: var(--diffs-marker-contrast, contrast-color(#fff, #000));\n white-space: normal;\n pointer-events: auto;\n border: 0;\n padding: 8px 12px;\n\n & [data-marker-message] {\n white-space: normal;\n overflow-wrap: anywhere;\n\n & code {\n white-space: normal;\n color: inherit;\n background-color: #0000;\n display: inline;\n }\n }\n}\n\n[data-selection-action-popover] {\n pointer-events: auto;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n width: max-content;\n padding: 4px;\n display: flex;\n}\n\n[data-search-panel] {\n z-index: 100;\n flex-direction: column;\n justify-content: right;\n width: 100%;\n height: 0;\n display: flex;\n position: sticky;\n top: 16px;\n right: 16px;\n container: search-panel / inline-size;\n\n & [data-editor-widget] {\n z-index: 100;\n flex-shrink: 0;\n align-items: stretch;\n gap: 8px;\n min-width: 260px;\n max-width: 100%;\n margin-inline: auto 16px;\n padding: 4px;\n display: flex;\n position: relative;\n }\n\n & svg {\n fill: currentColor;\n width: 12px;\n height: 12px;\n display: block;\n }\n}\n\n[data-search-grid] {\n grid-template-columns: auto auto auto;\n grid-template-areas: \"find matches nav\"\n \"replace actions .\";\n align-items: center;\n gap: 4px 6px;\n width: 100%;\n display: grid;\n}\n\n[data-input-box][data-find] {\n grid-area: find;\n}\n\n[data-search-nav] {\n grid-area: nav;\n}\n\n[data-input-box][data-replace] {\n grid-area: replace;\n}\n\n[data-replace-actions] {\n grid-area: actions;\n}\n\n[data-search-grid][data-mode=\"find\"] {\n grid-template-areas: \"find matches nav\";\n}\n\n[data-search-grid][data-mode=\"find\"] [data-replace-cell] {\n display: none;\n}\n\n@container search-panel (width < 400px) {\n [data-search-panel] [data-editor-widget] {\n padding: 10px;\n }\n\n [data-search-grid][data-mode=\"replace\"] {\n grid-template-columns: auto 1fr auto;\n grid-template-areas: \"find find find\"\n \"replace replace replace\"\n \"nav matches actions\";\n }\n\n [data-search-grid][data-mode=\"find\"] {\n grid-template-columns: auto 1fr auto;\n grid-template-areas: \"find find find\"\n \"nav matches matches\";\n }\n\n [data-replace-actions] {\n justify-self: end;\n }\n\n [data-search-grid] [data-input-box] {\n width: auto;\n }\n}\n\n[data-input-box] {\n align-items: center;\n width: 200px;\n display: flex;\n position: relative;\n\n & input {\n width: 100%;\n min-width: 0;\n color: var(--diffs-fg);\n background-color: var(--diffs-bg);\n border: 1px solid color-mix(in lab, var(--diffs-fg) 12%, var(--diffs-bg));\n border-radius: 6px;\n outline: none;\n flex-grow: 1;\n padding-inline: 6px;\n font-size: 13px;\n line-height: 24px;\n\n &::selection {\n background-color: color-mix(in lab, var(--diffs-fg) 8%, var(--diffs-bg));\n }\n\n &:focus-visible {\n outline: 1px solid var(--diffs-modified-base);\n }\n }\n\n &[data-find] input {\n padding-inline-end: 72px;\n }\n\n & [data-search-icon] {\n --diffs-search-icon-size: 20px;\n }\n}\n\n[data-search-toggles] {\n align-items: center;\n gap: 1px;\n display: flex;\n position: absolute;\n top: 50%;\n right: 4px;\n transform: translateY(-50%);\n}\n\n[data-matches] {\n white-space: nowrap;\n min-width: 50px;\n color: color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg));\n flex-shrink: 0;\n grid-area: matches;\n font-size: 12px;\n font-weight: 500;\n line-height: 20px;\n\n &[data-no-matches] {\n color: color-mix(in lab, var(--diffs-fg) 35%, var(--diffs-bg));\n }\n}\n\n[data-replace-actions], [data-search-nav] {\n align-items: center;\n display: flex;\n}\n\n[data-search-icon] {\n appearance: none;\n width: var(--diffs-search-icon-size, 24px);\n height: var(--diffs-search-icon-size, 24px);\n color: color-mix(in lab, var(--diffs-fg) 65%, var(--diffs-bg));\n border-radius: var(--diffs-search-icon-radius, 4px);\n cursor: pointer;\n background: none;\n border: 0;\n flex-shrink: 0;\n justify-content: center;\n align-items: center;\n margin: 0;\n padding: 0;\n transition: background-color .1s ease-in-out, color .1s ease-in-out;\n display: flex;\n\n &:disabled {\n opacity: .25;\n cursor: default;\n }\n\n &:not(:disabled):hover {\n color: var(--diffs-fg);\n }\n\n &:focus-visible {\n outline: 1px solid var(--diffs-modified-base);\n }\n\n &[aria-pressed=\"true\"] {\n color: var(--diffs-modified-base);\n }\n}\n\n[data-search-close] {\n --diffs-search-icon-size: 20px;\n --diffs-search-icon-radius: 50%;\n color: var(--diffs-widget-bg);\n background-color: color-mix(in lab,\n var(--diffs-widget-fg) 50%,\n var(--diffs-bg));\n position: absolute;\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n\n &:not(:disabled):hover {\n opacity: 1;\n color: var(--diffs-widget-bg);\n background-color: var(--diffs-widget-fg);\n }\n}\n";
|
|
2
|
+
var editor_default = "::selection {\n background-color: #0000;\n}\n\n[data-deleted-text-selection] [data-deletions] ::selection, [data-deleted-text-selection] [data-line-type=\"change-deletion\"] ::selection {\n background-color: var(--diffs-editor-selection-bg);\n}\n\n@keyframes blinking {\n 0% {\n opacity: 1;\n }\n\n 50% {\n opacity: 0;\n }\n\n 100% {\n opacity: 1;\n }\n}\n\n:host, [data-code], [data-content], [data-diff-type=\"split\"][data-overflow=\"wrap\"] {\n position: relative;\n}\n\n[data-code] {\n container-type: inline-size;\n}\n\n[data-content] {\n cursor: text;\n caret-color: var(--diffs-bg-caret);\n background-color: #0000;\n outline: none;\n}\n\n[data-line] {\n cursor: text;\n background-color: #0000;\n}\n\n[data-line]:after {\n content: \"\";\n z-index: -20;\n background-color: var(--diffs-line-bg);\n pointer-events: none;\n position: absolute;\n inset: 0;\n}\n\n[data-line][data-editor-active-line]:after {\n box-shadow: inset 0 0 0 1px var(--diffs-editor-line-highlight-border);\n}\n\n[data-editor-overlay] {\n display: contents;\n}\n\n[data-caret], [data-selection-range], [data-match-range], [data-bracket-match-range], [data-marker-range] {\n height: 1lh;\n line-height: var(--diffs-line-height);\n pointer-events: none;\n position: absolute;\n top: 0;\n left: 0;\n}\n\n[data-caret] {\n background-color: var(--diffs-bg-caret-override, var(--diffs-editor-cursor-fg, light-dark(color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg)), color-mix(in lab, var(--diffs-fg) 75%, var(--diffs-bg)))));\n visibility: hidden;\n width: 2px;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n [data-caret] {\n animation: 1.2s .8s infinite blinking;\n }\n}\n\n[data-selection-range] {\n z-index: -10;\n background-color: var(--diffs-editor-selection-bg);\n}\n\n[data-selection-corner] {\n background-color: var(--diffs-selection-corner-bg, var(--diffs-bg));\n width: 100%;\n height: 100%;\n}\n\n[data-match-range] {\n z-index: -10;\n background-color: var(--diffs-editor-match-bg, var(--diffs-editor-selection-bg));\n}\n\n[data-match-range]:not([data-focus]) {\n background-color: var(--diffs-editor-match-highlight-bg, light-dark(#ff963288, #ff963266));\n}\n\n[data-bracket-match-range] {\n z-index: -9;\n box-sizing: border-box;\n border-bottom: 1px solid\n var(--diffs-editor-bracket-match-border, color-mix(in lab, var(--diffs-fg) 60%, transparent));\n background-color: var(--diffs-editor-bracket-match-bg, color-mix(in lab, var(--diffs-fg) 5%, transparent));\n}\n\n[data-rtl] {\n border-top-left-radius: 3px;\n}\n\n[data-rtr] {\n border-top-right-radius: 3px;\n}\n\n[data-rbl] {\n border-bottom-left-radius: 3px;\n}\n\n[data-rbr] {\n border-bottom-right-radius: 3px;\n}\n\n[data-marker-range] {\n z-index: 1;\n background-color: var(--diffs-marker-bg);\n mask-image: url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2IiBoZWlnaHQ9IjMiPjxwYXRoIGQ9Im0wIDIuNSBsMiAtMS41IGwxIDAgbDIgMS41IGwxIDAiIHN0cm9rZT0iI2ZmZiIgZmlsbD0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PC9zdmc+\");\n mask-position: 0 100%;\n mask-size: 6px 3px;\n mask-repeat: repeat-x;\n}\n\n[data-marker-error] {\n --diffs-marker-contrast: light-dark(#fff, #000);\n --diffs-marker-bg: var(--diffs-editor-error-fg, var(--diffs-deletion-base));\n}\n\n[data-marker-warning] {\n --diffs-marker-contrast: #000;\n --diffs-marker-bg: var(--diffs-editor-warning-fg, light-dark(var(--diffs-warning-light), var(--diffs-warning-dark)));\n}\n\n[data-marker-info] {\n --diffs-marker-contrast: #000;\n --diffs-marker-bg: var(--diffs-editor-info-fg, var(--diffs-modified-base));\n}\n\n[data-marker-hint] {\n --diffs-marker-contrast: light-dark(#fff, #000);\n --diffs-marker-bg: var(--diffs-editor-hint-fg, var(--diffs-fg-number));\n}\n\n@media (width >= 480px) {\n [data-content] {\n caret-color: #0000;\n }\n\n [data-content]:focus ~ [data-editor-overlay] [data-caret] {\n visibility: visible;\n }\n}\n\n[data-editor-widget] {\n --diffs-widget-fg: var(--diffs-fg);\n --diffs-widget-bg: color-mix(in lab, var(--diffs-fg) 4%, var(--diffs-bg));\n --diffs-widget-border: color-mix(in lab, var(--diffs-fg) 20%, transparent);\n --diffs-widget-shadow: inset 0 0 0 1px var(--diffs-bg), 0 4px 8px #00000013,\n 0 6px 18px #00000013;\n z-index: 100;\n width: fit-content;\n max-width: calc(100% - 24px);\n font: 14px/20px var(--diffs-header-font-fallback);\n border: 1px solid var(--diffs-widget-border);\n background-color: var(--diffs-widget-bg);\n box-shadow: var(--diffs-widget-shadow);\n background-clip: padding-box;\n border-radius: 9px;\n position: absolute;\n top: 0;\n left: 0;\n}\n\n[data-marker-popover], [data-selection-action-popover] {\n --popover-gap: var(--diffs-popover-gap, var(--diffs-gap-fallback, 8px));\n --popover-viewport-left: 0px;\n --popover-viewport-right: 100cqw;\n --popover-viewport-top: -99999px;\n --popover-viewport-bottom: 99999px;\n --popover-min-left: calc(var(--popover-viewport-left) + var(--gutter-width, 0px) + var(--popover-gap));\n --popover-available-width: max(0px,\n calc(var(--popover-viewport-right) - var(--popover-min-left) -\n var(--popover-gap)));\n max-width: min(640px, var(--popover-available-width));\n translate: clamp(var(--popover-min-left),\n var(--popover-x, var(--popover-min-left)),\n calc(var(--popover-viewport-right) - var(--popover-gap) - 100%))\n /* Clamp into the scrollport so a popover with no fitting side stays in view. */\n clamp(var(--popover-viewport-top),\n calc(var(--popover-y, 0px) + var(--popover-y-shift, 0px)),\n calc(var(--popover-viewport-bottom) - var(--popover-gap) - 100%));\n}\n\n[data-marker-popover] {\n --diffs-widget-bg: var(--diffs-marker-bg);\n --diffs-widget-shadow: 0 4px 8px #00000026, 0 6px 18px #00000026;\n min-width: min(180px, var(--popover-available-width));\n overflow-wrap: anywhere;\n color: var(--diffs-marker-contrast);\n white-space: normal;\n pointer-events: auto;\n border: 0;\n padding: 8px 12px;\n\n @supports (color: contrast-color(red)) {\n color: contrast-color(var(--diffs-marker-bg), var(--diffs-bg));\n }\n\n & [data-marker-message] {\n white-space: normal;\n overflow-wrap: anywhere;\n\n & code {\n white-space: normal;\n color: inherit;\n background-color: #0000;\n display: inline;\n }\n }\n}\n\n[data-selection-action-popover] {\n pointer-events: auto;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n width: max-content;\n padding: 4px;\n display: flex;\n}\n\n[data-search-panel] {\n z-index: 100;\n flex-direction: column;\n justify-content: right;\n width: 100%;\n height: 0;\n display: flex;\n position: sticky;\n top: 16px;\n right: 16px;\n container: search-panel / inline-size;\n\n & [data-editor-widget] {\n z-index: 100;\n flex-shrink: 0;\n align-items: stretch;\n gap: 8px;\n min-width: 260px;\n max-width: 100%;\n margin-inline: auto 16px;\n padding: 4px;\n display: flex;\n position: relative;\n }\n\n & svg {\n fill: currentColor;\n width: 12px;\n height: 12px;\n display: block;\n }\n}\n\n[data-search-grid] {\n grid-template-columns: auto auto auto;\n grid-template-areas: \"find matches nav\"\n \"replace actions .\";\n align-items: center;\n gap: 4px 6px;\n width: 100%;\n display: grid;\n}\n\n[data-input-box][data-find] {\n grid-area: find;\n}\n\n[data-search-nav] {\n grid-area: nav;\n}\n\n[data-input-box][data-replace] {\n grid-area: replace;\n}\n\n[data-replace-actions] {\n grid-area: actions;\n}\n\n[data-search-grid][data-mode=\"find\"] {\n grid-template-areas: \"find matches nav\";\n}\n\n[data-search-grid][data-mode=\"find\"] [data-replace-cell] {\n display: none;\n}\n\n@container search-panel (width < 400px) {\n [data-search-panel] [data-editor-widget] {\n padding: 10px;\n }\n\n [data-search-grid][data-mode=\"replace\"] {\n grid-template-columns: auto 1fr auto;\n grid-template-areas: \"find find find\"\n \"replace replace replace\"\n \"nav matches actions\";\n }\n\n [data-search-grid][data-mode=\"find\"] {\n grid-template-columns: auto 1fr auto;\n grid-template-areas: \"find find find\"\n \"nav matches matches\";\n }\n\n [data-replace-actions] {\n justify-self: end;\n }\n\n [data-search-grid] [data-input-box] {\n width: auto;\n }\n}\n\n[data-input-box] {\n align-items: center;\n width: 200px;\n display: flex;\n position: relative;\n\n & input {\n width: 100%;\n min-width: 0;\n color: var(--diffs-fg);\n background-color: var(--diffs-bg);\n border: 1px solid color-mix(in lab, var(--diffs-fg) 12%, var(--diffs-bg));\n border-radius: 6px;\n outline: none;\n flex-grow: 1;\n padding-inline: 6px;\n font-size: 13px;\n line-height: 24px;\n\n &::selection {\n background-color: color-mix(in lab, var(--diffs-fg) 8%, var(--diffs-bg));\n }\n\n &:focus-visible {\n outline: 1px solid var(--diffs-modified-base);\n }\n }\n\n &[data-find] input {\n padding-inline-end: 72px;\n }\n\n & [data-search-icon] {\n --diffs-search-icon-size: 20px;\n }\n}\n\n[data-search-toggles] {\n align-items: center;\n gap: 1px;\n display: flex;\n position: absolute;\n top: 50%;\n right: 4px;\n transform: translateY(-50%);\n}\n\n[data-matches] {\n white-space: nowrap;\n min-width: 50px;\n color: color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg));\n flex-shrink: 0;\n grid-area: matches;\n font-size: 12px;\n font-weight: 500;\n line-height: 20px;\n\n &[data-no-matches] {\n color: color-mix(in lab, var(--diffs-fg) 35%, var(--diffs-bg));\n }\n}\n\n[data-replace-actions], [data-search-nav] {\n align-items: center;\n display: flex;\n}\n\n[data-search-icon] {\n appearance: none;\n width: var(--diffs-search-icon-size, 24px);\n height: var(--diffs-search-icon-size, 24px);\n color: color-mix(in lab, var(--diffs-fg) 65%, var(--diffs-bg));\n border-radius: var(--diffs-search-icon-radius, 4px);\n cursor: pointer;\n background: none;\n border: 0;\n flex-shrink: 0;\n justify-content: center;\n align-items: center;\n margin: 0;\n padding: 0;\n transition: background-color .1s ease-in-out, color .1s ease-in-out;\n display: flex;\n\n &:disabled {\n opacity: .25;\n cursor: default;\n }\n\n &:not(:disabled):hover {\n color: var(--diffs-fg);\n }\n\n &:focus-visible {\n outline: 1px solid var(--diffs-modified-base);\n }\n\n &[aria-pressed=\"true\"] {\n color: var(--diffs-modified-base);\n }\n}\n\n[data-search-close] {\n --diffs-search-icon-size: 20px;\n --diffs-search-icon-radius: 50%;\n color: var(--diffs-widget-bg);\n background-color: color-mix(in lab,\n var(--diffs-widget-fg) 50%,\n var(--diffs-bg));\n position: absolute;\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n\n &:not(:disabled):hover {\n opacity: 1;\n color: var(--diffs-widget-bg);\n background-color: var(--diffs-widget-fg);\n }\n}\n";
|
|
3
3
|
//#endregion
|
|
4
4
|
export { editor_default as default };
|
|
5
5
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { EditorSelection, TextEdit } from "../types.js";
|
|
2
|
+
import { TextDocument } from "./textDocument.js";
|
|
3
|
+
|
|
4
|
+
//#region src/editor/languages.d.ts
|
|
5
|
+
interface LanguageConfig {
|
|
6
|
+
lineComment?: string | null;
|
|
7
|
+
blockComment?: readonly [open: string, close: string];
|
|
8
|
+
}
|
|
9
|
+
type LanguageConfigMap = Readonly<Record<string, LanguageConfig>>;
|
|
10
|
+
interface ResolvedLanguageConfig {
|
|
11
|
+
lineComment: string | null;
|
|
12
|
+
blockComment: readonly [open: string, close: string];
|
|
13
|
+
}
|
|
14
|
+
/** Resolves language-specific comment tokens over the editor defaults. */
|
|
15
|
+
declare function resolveCommentConfig(languageId: string, overrides?: LanguageConfigMap): ResolvedLanguageConfig;
|
|
16
|
+
/** Builds one aligned batch of line-comment edits for all selected lines. */
|
|
17
|
+
declare function resolveLineCommentEdits(textDocument: TextDocument<unknown>, selections: readonly EditorSelection[], token: string): TextEdit[];
|
|
18
|
+
interface BlockCommentEditResult {
|
|
19
|
+
edits: TextEdit[];
|
|
20
|
+
nextSelectionOffsets: Array<readonly [start: number, end: number, direction: EditorSelection['direction']]>;
|
|
21
|
+
}
|
|
22
|
+
/** Builds block-comment edits and content-preserving post-edit selections. */
|
|
23
|
+
declare function resolveBlockCommentEdits(textDocument: TextDocument<unknown>, selections: readonly EditorSelection[], [open, close]: readonly [string, string], linewise?: boolean): BlockCommentEditResult | undefined;
|
|
24
|
+
//#endregion
|
|
25
|
+
export { BlockCommentEditResult, LanguageConfig, LanguageConfigMap, resolveBlockCommentEdits, resolveCommentConfig, resolveLineCommentEdits };
|
|
26
|
+
//# sourceMappingURL=languages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"languages.d.ts","names":[],"sources":["../../src/editor/languages.ts"],"mappings":";;;;UAMiB,cAAA;EACf,WAAA;EACA,YAAA,aAAyB,IAAA,UAAc,KAAA;AAAA;AAAA,KAG7B,iBAAA,GAAoB,QAAA,CAAS,MAAA,SAAe,cAAA;AAAA,UAE9C,sBAAA;EACR,WAAA;EACA,YAAA,YAAwB,IAAA,UAAc,KAAA;AAAA;;iBAwCxB,oBAAA,CACd,UAAA,UACA,SAAA,GAAY,iBAAA,GACX,sBAAsB;AAlDqB;AAAA,iBAyE9B,uBAAA,CACd,YAAA,EAAc,YAAA,WACd,UAAA,WAAqB,eAAA,IACrB,KAAA,WACC,QAAA;AAAA,UA+Fc,sBAAA;EACf,KAAA,EAAO,QAAA;EACP,oBAAA,EAAsB,KAAA,WAElB,KAAA,UACA,GAAA,UACA,SAAA,EAAW,eAAA;AAAA;;iBA+HD,wBAAA,CACd,YAAA,EAAc,YAAA,WACd,UAAA,WAAqB,eAAA,KACpB,IAAA,EAAM,KAAA,8BACP,QAAA,aACC,sBAAA"}
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
//#region src/editor/languages.ts
|
|
2
|
+
const DEFAULT_LINE_COMMENT = "//";
|
|
3
|
+
const DEFAULT_BLOCK_COMMENT = ["/*", "*/"];
|
|
4
|
+
const LANGUAGE_COMMENT_CONFIGS = {
|
|
5
|
+
sql: { lineComment: "--" },
|
|
6
|
+
ruby: {
|
|
7
|
+
lineComment: "#",
|
|
8
|
+
blockComment: ["=begin", "=end"]
|
|
9
|
+
},
|
|
10
|
+
rst: { lineComment: ".." },
|
|
11
|
+
coffeescript: {
|
|
12
|
+
lineComment: "#",
|
|
13
|
+
blockComment: ["###", "###"]
|
|
14
|
+
},
|
|
15
|
+
cmd: { lineComment: "@REM" },
|
|
16
|
+
julia: {
|
|
17
|
+
lineComment: "#",
|
|
18
|
+
blockComment: ["#=", "=#"]
|
|
19
|
+
},
|
|
20
|
+
yaml: { lineComment: "#" },
|
|
21
|
+
yml: { lineComment: "#" },
|
|
22
|
+
markdown: {
|
|
23
|
+
lineComment: null,
|
|
24
|
+
blockComment: ["<!--", "-->"]
|
|
25
|
+
},
|
|
26
|
+
zsh: { lineComment: "#" },
|
|
27
|
+
makefile: { lineComment: "#" },
|
|
28
|
+
handlebars: {
|
|
29
|
+
lineComment: null,
|
|
30
|
+
blockComment: ["{{!--", "--}}"]
|
|
31
|
+
},
|
|
32
|
+
ini: {
|
|
33
|
+
lineComment: ";",
|
|
34
|
+
blockComment: [";", " "]
|
|
35
|
+
},
|
|
36
|
+
powershell: {
|
|
37
|
+
lineComment: "#",
|
|
38
|
+
blockComment: ["<#", "#>"]
|
|
39
|
+
},
|
|
40
|
+
vb: { lineComment: "'" },
|
|
41
|
+
xml: {
|
|
42
|
+
lineComment: null,
|
|
43
|
+
blockComment: ["<!--", "-->"]
|
|
44
|
+
},
|
|
45
|
+
lua: {
|
|
46
|
+
lineComment: "--",
|
|
47
|
+
blockComment: ["--[[", "]]"]
|
|
48
|
+
},
|
|
49
|
+
html: {
|
|
50
|
+
lineComment: null,
|
|
51
|
+
blockComment: ["<!--", "-->"]
|
|
52
|
+
},
|
|
53
|
+
diff: {
|
|
54
|
+
lineComment: "#",
|
|
55
|
+
blockComment: ["#", " "]
|
|
56
|
+
},
|
|
57
|
+
r: { lineComment: "#" },
|
|
58
|
+
fsharp: { blockComment: ["(*", "*)"] },
|
|
59
|
+
pug: { lineComment: "//-" },
|
|
60
|
+
perl: { lineComment: "#" },
|
|
61
|
+
tex: { lineComment: "%" },
|
|
62
|
+
clojure: { lineComment: ";;" },
|
|
63
|
+
css: { lineComment: null },
|
|
64
|
+
python: {
|
|
65
|
+
lineComment: "#",
|
|
66
|
+
blockComment: ["\"\"\"", "\"\"\""]
|
|
67
|
+
},
|
|
68
|
+
dotenv: { lineComment: "#" },
|
|
69
|
+
dockerfile: { lineComment: "#" },
|
|
70
|
+
razor: {
|
|
71
|
+
lineComment: null,
|
|
72
|
+
blockComment: ["<!--", "-->"]
|
|
73
|
+
},
|
|
74
|
+
prompt: {
|
|
75
|
+
lineComment: null,
|
|
76
|
+
blockComment: ["<!--", "-->"]
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
/** Resolves language-specific comment tokens over the editor defaults. */
|
|
80
|
+
function resolveCommentConfig(languageId, overrides) {
|
|
81
|
+
const config = {
|
|
82
|
+
...LANGUAGE_COMMENT_CONFIGS[languageId],
|
|
83
|
+
...overrides?.[languageId]
|
|
84
|
+
};
|
|
85
|
+
return {
|
|
86
|
+
lineComment: config.lineComment === void 0 ? DEFAULT_LINE_COMMENT : config.lineComment,
|
|
87
|
+
blockComment: config.blockComment ?? DEFAULT_BLOCK_COMMENT
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/** Builds one aligned batch of line-comment edits for all selected lines. */
|
|
91
|
+
function resolveLineCommentEdits(textDocument, selections, token) {
|
|
92
|
+
const lines = [];
|
|
93
|
+
const seenLines = /* @__PURE__ */ new Set();
|
|
94
|
+
for (const selection of selections) {
|
|
95
|
+
let endLine = selection.end.line;
|
|
96
|
+
if (selection.start.line < endLine && selection.end.character === 0) endLine--;
|
|
97
|
+
const startIndex = lines.length;
|
|
98
|
+
let minIndent = Infinity;
|
|
99
|
+
for (let line = selection.start.line; line <= endLine; line++) {
|
|
100
|
+
if (seenLines.has(line)) continue;
|
|
101
|
+
seenLines.add(line);
|
|
102
|
+
const text = textDocument.getLineText(line);
|
|
103
|
+
const indent = text.length - text.trimStart().length;
|
|
104
|
+
const empty = indent === text.length;
|
|
105
|
+
if (!empty) minIndent = Math.min(minIndent, indent);
|
|
106
|
+
lines.push({
|
|
107
|
+
line,
|
|
108
|
+
comment: text.slice(indent, indent + token.length) === token ? indent : -1,
|
|
109
|
+
empty,
|
|
110
|
+
indent,
|
|
111
|
+
single: false
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (minIndent !== Infinity) {
|
|
115
|
+
for (let index = startIndex; index < lines.length; index++) if (!lines[index].empty) lines[index].indent = minIndent;
|
|
116
|
+
}
|
|
117
|
+
if (lines.length === startIndex + 1) lines[startIndex].single = true;
|
|
118
|
+
}
|
|
119
|
+
const shouldComment = lines.some((line) => line.comment < 0 && (!line.empty || line.single));
|
|
120
|
+
const edits = [];
|
|
121
|
+
if (shouldComment) {
|
|
122
|
+
for (const line of lines) {
|
|
123
|
+
if (line.empty && !line.single) continue;
|
|
124
|
+
const position = {
|
|
125
|
+
line: line.line,
|
|
126
|
+
character: line.indent
|
|
127
|
+
};
|
|
128
|
+
edits.push({
|
|
129
|
+
range: {
|
|
130
|
+
start: position,
|
|
131
|
+
end: position
|
|
132
|
+
},
|
|
133
|
+
newText: token + " "
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return edits;
|
|
137
|
+
}
|
|
138
|
+
for (const line of lines) {
|
|
139
|
+
if (line.comment < 0) continue;
|
|
140
|
+
const text = textDocument.getLineText(line.line);
|
|
141
|
+
const start = line.comment;
|
|
142
|
+
const end = start + token.length + (text[start + token.length] === " " ? 1 : 0);
|
|
143
|
+
edits.push({
|
|
144
|
+
range: {
|
|
145
|
+
start: {
|
|
146
|
+
line: line.line,
|
|
147
|
+
character: start
|
|
148
|
+
},
|
|
149
|
+
end: {
|
|
150
|
+
line: line.line,
|
|
151
|
+
character: end
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
newText: ""
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
return edits;
|
|
158
|
+
}
|
|
159
|
+
const BLOCK_COMMENT_SEARCH_MARGIN = 50;
|
|
160
|
+
function findBlockComment(textDocument, open, close, from, to) {
|
|
161
|
+
const beforeStart = Math.max(0, from - BLOCK_COMMENT_SEARCH_MARGIN);
|
|
162
|
+
const textBefore = textDocument.getTextSlice(beforeStart, from);
|
|
163
|
+
const textAfter = textDocument.getTextSlice(to, to + BLOCK_COMMENT_SEARCH_MARGIN);
|
|
164
|
+
const spaceBefore = textBefore.length - textBefore.trimEnd().length;
|
|
165
|
+
const spaceAfter = textAfter.length - textAfter.trimStart().length;
|
|
166
|
+
const beforeOffset = textBefore.length - spaceBefore;
|
|
167
|
+
if (textBefore.slice(beforeOffset - open.length, beforeOffset) === open && textAfter.slice(spaceAfter, spaceAfter + close.length) === close) return {
|
|
168
|
+
open: {
|
|
169
|
+
start: from - spaceBefore - open.length,
|
|
170
|
+
end: from - spaceBefore + (spaceBefore > 0 ? 1 : 0),
|
|
171
|
+
text: ""
|
|
172
|
+
},
|
|
173
|
+
close: {
|
|
174
|
+
start: to + spaceAfter - (spaceAfter > 0 ? 1 : 0),
|
|
175
|
+
end: to + spaceAfter + close.length,
|
|
176
|
+
text: ""
|
|
177
|
+
},
|
|
178
|
+
contentStart: from,
|
|
179
|
+
contentEnd: to
|
|
180
|
+
};
|
|
181
|
+
const shortText = to - from <= BLOCK_COMMENT_SEARCH_MARGIN * 2 ? textDocument.getTextSlice(from, to) : void 0;
|
|
182
|
+
const startText = shortText ?? textDocument.getTextSlice(from, from + BLOCK_COMMENT_SEARCH_MARGIN);
|
|
183
|
+
const endText = shortText ?? textDocument.getTextSlice(to - BLOCK_COMMENT_SEARCH_MARGIN, to);
|
|
184
|
+
const startSpace = startText.length - startText.trimStart().length;
|
|
185
|
+
const closeStart = to - (endText.length - endText.trimEnd().length) - close.length;
|
|
186
|
+
if (startText.slice(startSpace, startSpace + open.length) !== open || textDocument.getTextSlice(closeStart, closeStart + close.length) !== close) return;
|
|
187
|
+
const openStart = from + startSpace;
|
|
188
|
+
const openEnd = openStart + open.length + (/\s/.test(startText[open.length + startSpace] ?? "") ? 1 : 0);
|
|
189
|
+
const closeDeleteStart = closeStart - (/\s/.test(textDocument.getTextSlice(closeStart - 1, closeStart)) ? 1 : 0);
|
|
190
|
+
return {
|
|
191
|
+
open: {
|
|
192
|
+
start: openStart,
|
|
193
|
+
end: openEnd,
|
|
194
|
+
text: ""
|
|
195
|
+
},
|
|
196
|
+
close: {
|
|
197
|
+
start: closeDeleteStart,
|
|
198
|
+
end: closeStart + close.length,
|
|
199
|
+
text: ""
|
|
200
|
+
},
|
|
201
|
+
contentStart: openEnd,
|
|
202
|
+
contentEnd: closeDeleteStart
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
function mapOffset(offset, edits, cumulativeDeltas, association) {
|
|
206
|
+
let low = 0;
|
|
207
|
+
let high = edits.length;
|
|
208
|
+
while (low < high) {
|
|
209
|
+
const middle = low + high >>> 1;
|
|
210
|
+
if (edits[middle].end < offset) low = middle + 1;
|
|
211
|
+
else high = middle;
|
|
212
|
+
}
|
|
213
|
+
let delta = cumulativeDeltas[low];
|
|
214
|
+
for (let index = low; index < edits.length; index++) {
|
|
215
|
+
const edit = edits[index];
|
|
216
|
+
if (offset < edit.start) break;
|
|
217
|
+
if (edit.start === edit.end && offset === edit.start) {
|
|
218
|
+
if (association < 0) break;
|
|
219
|
+
delta += edit.text.length;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (offset > edit.end) {
|
|
223
|
+
delta += edit.text.length - (edit.end - edit.start);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (offset === edit.end) return edit.start + delta + edit.text.length;
|
|
227
|
+
return edit.start + delta + (association > 0 ? edit.text.length : 0);
|
|
228
|
+
}
|
|
229
|
+
return offset + delta;
|
|
230
|
+
}
|
|
231
|
+
/** Builds block-comment edits and content-preserving post-edit selections. */
|
|
232
|
+
function resolveBlockCommentEdits(textDocument, selections, [open, close], linewise = false) {
|
|
233
|
+
const ranges = selections.map((selection) => {
|
|
234
|
+
let { start, end } = selection;
|
|
235
|
+
if (linewise) {
|
|
236
|
+
let endLine = end.line;
|
|
237
|
+
if (start.line < endLine && end.character === 0) endLine--;
|
|
238
|
+
const firstLine = textDocument.getLineText(start.line);
|
|
239
|
+
const indent = firstLine.length - firstLine.trimStart().length;
|
|
240
|
+
start = {
|
|
241
|
+
line: start.line,
|
|
242
|
+
character: indent
|
|
243
|
+
};
|
|
244
|
+
end = {
|
|
245
|
+
line: endLine,
|
|
246
|
+
character: textDocument.getLineLength(endLine)
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
from: textDocument.offsetAt(start),
|
|
251
|
+
to: textDocument.offsetAt(end),
|
|
252
|
+
direction: selection.direction,
|
|
253
|
+
comment: void 0
|
|
254
|
+
};
|
|
255
|
+
});
|
|
256
|
+
if (linewise && ranges.length > 1) {
|
|
257
|
+
ranges.sort((a, b) => {
|
|
258
|
+
const startOrder = a.from - b.from;
|
|
259
|
+
return startOrder !== 0 ? startOrder : a.to - b.to;
|
|
260
|
+
});
|
|
261
|
+
let lastRangeIndex = 0;
|
|
262
|
+
for (let index = 1; index < ranges.length; index++) {
|
|
263
|
+
const previous = ranges[lastRangeIndex];
|
|
264
|
+
const current = ranges[index];
|
|
265
|
+
if (current.from <= previous.to) previous.to = Math.max(previous.to, current.to);
|
|
266
|
+
else ranges[++lastRangeIndex] = current;
|
|
267
|
+
}
|
|
268
|
+
ranges.length = lastRangeIndex + 1;
|
|
269
|
+
}
|
|
270
|
+
for (const range of ranges) range.comment = findBlockComment(textDocument, open, close, range.from, range.to);
|
|
271
|
+
const shouldUncomment = ranges.every((range) => range.comment !== void 0);
|
|
272
|
+
const offsetEdits = [];
|
|
273
|
+
for (const range of ranges) {
|
|
274
|
+
const comment = range.comment;
|
|
275
|
+
if (shouldUncomment && comment !== void 0) {
|
|
276
|
+
offsetEdits.push(comment.open, comment.close);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (comment !== void 0) continue;
|
|
280
|
+
if (range.from === range.to) {
|
|
281
|
+
offsetEdits.push({
|
|
282
|
+
start: range.from,
|
|
283
|
+
end: range.to,
|
|
284
|
+
text: open + " " + close
|
|
285
|
+
});
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
offsetEdits.push({
|
|
289
|
+
start: range.from,
|
|
290
|
+
end: range.from,
|
|
291
|
+
text: open + " "
|
|
292
|
+
}, {
|
|
293
|
+
start: range.to,
|
|
294
|
+
end: range.to,
|
|
295
|
+
text: " " + close
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
if (offsetEdits.length === 0) return;
|
|
299
|
+
offsetEdits.sort((a, b) => {
|
|
300
|
+
const startOrder = a.start - b.start;
|
|
301
|
+
return startOrder !== 0 ? startOrder : a.end - b.end;
|
|
302
|
+
});
|
|
303
|
+
const edits = offsetEdits.map((edit) => ({
|
|
304
|
+
range: {
|
|
305
|
+
start: textDocument.positionAt(edit.start),
|
|
306
|
+
end: textDocument.positionAt(edit.end)
|
|
307
|
+
},
|
|
308
|
+
newText: edit.text
|
|
309
|
+
}));
|
|
310
|
+
if (linewise) return {
|
|
311
|
+
edits,
|
|
312
|
+
nextSelectionOffsets: []
|
|
313
|
+
};
|
|
314
|
+
const logicalRanges = ranges.map((range) => {
|
|
315
|
+
const comment = range.comment;
|
|
316
|
+
if (shouldUncomment && comment !== void 0) return {
|
|
317
|
+
start: comment.contentStart,
|
|
318
|
+
end: comment.contentEnd,
|
|
319
|
+
startAssociation: 1,
|
|
320
|
+
endAssociation: -1
|
|
321
|
+
};
|
|
322
|
+
if (comment !== void 0) return {
|
|
323
|
+
start: range.from,
|
|
324
|
+
end: range.to,
|
|
325
|
+
startAssociation: 1,
|
|
326
|
+
endAssociation: 1
|
|
327
|
+
};
|
|
328
|
+
if (range.from === range.to) return {
|
|
329
|
+
start: range.from,
|
|
330
|
+
end: range.to,
|
|
331
|
+
startAssociation: -1,
|
|
332
|
+
endAssociation: -1,
|
|
333
|
+
collapsedInset: open.length + 1
|
|
334
|
+
};
|
|
335
|
+
return {
|
|
336
|
+
start: range.from,
|
|
337
|
+
end: range.to,
|
|
338
|
+
startAssociation: 1,
|
|
339
|
+
endAssociation: -1
|
|
340
|
+
};
|
|
341
|
+
});
|
|
342
|
+
const cumulativeDeltas = new Array(offsetEdits.length + 1);
|
|
343
|
+
cumulativeDeltas[0] = 0;
|
|
344
|
+
for (let index = 0; index < offsetEdits.length; index++) {
|
|
345
|
+
const edit = offsetEdits[index];
|
|
346
|
+
cumulativeDeltas[index + 1] = cumulativeDeltas[index] + edit.text.length - (edit.end - edit.start);
|
|
347
|
+
}
|
|
348
|
+
return {
|
|
349
|
+
edits,
|
|
350
|
+
nextSelectionOffsets: logicalRanges.map((range, index) => {
|
|
351
|
+
const start = mapOffset(range.start, offsetEdits, cumulativeDeltas, range.startAssociation) + (range.collapsedInset ?? 0);
|
|
352
|
+
return [
|
|
353
|
+
start,
|
|
354
|
+
range.collapsedInset === void 0 ? mapOffset(range.end, offsetEdits, cumulativeDeltas, range.endAssociation) : start,
|
|
355
|
+
ranges[index].direction
|
|
356
|
+
];
|
|
357
|
+
})
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
//#endregion
|
|
361
|
+
export { resolveBlockCommentEdits, resolveCommentConfig, resolveLineCommentEdits };
|
|
362
|
+
|
|
363
|
+
//# sourceMappingURL=languages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"languages.js","names":[],"sources":["../../src/editor/languages.ts"],"sourcesContent":["import type { EditorSelection, TextEdit } from '../types';\nimport type { TextDocument } from './textDocument';\n\nconst DEFAULT_LINE_COMMENT = '//';\nconst DEFAULT_BLOCK_COMMENT = ['/*', '*/'] as const;\n\nexport interface LanguageConfig {\n lineComment?: string | null;\n blockComment?: readonly [open: string, close: string];\n}\n\nexport type LanguageConfigMap = Readonly<Record<string, LanguageConfig>>;\n\ninterface ResolvedLanguageConfig {\n lineComment: string | null;\n blockComment: readonly [open: string, close: string];\n}\n\n// Language comment configurations\n// Languages matching DEFAULT_LINE_COMMENT and DEFAULT_BLOCK_COMMENT are omitted.\nconst LANGUAGE_COMMENT_CONFIGS: LanguageConfigMap = {\n sql: { lineComment: '--' },\n ruby: { lineComment: '#', blockComment: ['=begin', '=end'] },\n rst: { lineComment: '..' },\n coffeescript: { lineComment: '#', blockComment: ['###', '###'] },\n cmd: { lineComment: '@REM' },\n julia: { lineComment: '#', blockComment: ['#=', '=#'] },\n yaml: { lineComment: '#' },\n yml: { lineComment: '#' },\n markdown: { lineComment: null, blockComment: ['<!--', '-->'] },\n zsh: { lineComment: '#' },\n makefile: { lineComment: '#' },\n handlebars: { lineComment: null, blockComment: ['{{!--', '--}}'] },\n ini: { lineComment: ';', blockComment: [';', ' '] },\n powershell: { lineComment: '#', blockComment: ['<#', '#>'] },\n vb: { lineComment: \"'\" },\n xml: { lineComment: null, blockComment: ['<!--', '-->'] },\n lua: { lineComment: '--', blockComment: ['--[[', ']]'] },\n html: { lineComment: null, blockComment: ['<!--', '-->'] },\n diff: { lineComment: '#', blockComment: ['#', ' '] },\n r: { lineComment: '#' },\n fsharp: { blockComment: ['(*', '*)'] },\n pug: { lineComment: '//-' },\n perl: { lineComment: '#' },\n tex: { lineComment: '%' },\n clojure: { lineComment: ';;' },\n css: { lineComment: null },\n python: { lineComment: '#', blockComment: ['\"\"\"', '\"\"\"'] },\n dotenv: { lineComment: '#' },\n dockerfile: { lineComment: '#' },\n razor: { lineComment: null, blockComment: ['<!--', '-->'] },\n prompt: { lineComment: null, blockComment: ['<!--', '-->'] },\n};\n\n/** Resolves language-specific comment tokens over the editor defaults. */\nexport function resolveCommentConfig(\n languageId: string,\n overrides?: LanguageConfigMap\n): ResolvedLanguageConfig {\n const config = {\n ...LANGUAGE_COMMENT_CONFIGS[languageId],\n ...overrides?.[languageId],\n };\n return {\n lineComment:\n config.lineComment === undefined\n ? DEFAULT_LINE_COMMENT\n : config.lineComment,\n blockComment: config.blockComment ?? DEFAULT_BLOCK_COMMENT,\n };\n}\n\ninterface LineCommentInfo {\n line: number;\n comment: number;\n empty: boolean;\n indent: number;\n single: boolean;\n}\n\n/** Builds one aligned batch of line-comment edits for all selected lines. */\nexport function resolveLineCommentEdits(\n textDocument: TextDocument<unknown>,\n selections: readonly EditorSelection[],\n token: string\n): TextEdit[] {\n const lines: LineCommentInfo[] = [];\n const seenLines = new Set<number>();\n\n for (const selection of selections) {\n let endLine = selection.end.line;\n if (selection.start.line < endLine && selection.end.character === 0) {\n endLine--;\n }\n\n const startIndex = lines.length;\n let minIndent = Infinity;\n for (let line = selection.start.line; line <= endLine; line++) {\n if (seenLines.has(line)) {\n continue;\n }\n seenLines.add(line);\n const text = textDocument.getLineText(line);\n const indent = text.length - text.trimStart().length;\n const empty = indent === text.length;\n if (!empty) {\n minIndent = Math.min(minIndent, indent);\n }\n lines.push({\n line,\n comment:\n text.slice(indent, indent + token.length) === token ? indent : -1,\n empty,\n indent,\n single: false,\n });\n }\n\n if (minIndent !== Infinity) {\n for (let index = startIndex; index < lines.length; index++) {\n if (!lines[index].empty) {\n lines[index].indent = minIndent;\n }\n }\n }\n if (lines.length === startIndex + 1) {\n lines[startIndex].single = true;\n }\n }\n\n const shouldComment = lines.some(\n (line) => line.comment < 0 && (!line.empty || line.single)\n );\n const edits: TextEdit[] = [];\n if (shouldComment) {\n for (const line of lines) {\n if (line.empty && !line.single) {\n continue;\n }\n const position = { line: line.line, character: line.indent };\n edits.push({\n range: { start: position, end: position },\n newText: token + ' ',\n });\n }\n return edits;\n }\n\n for (const line of lines) {\n if (line.comment < 0) {\n continue;\n }\n const text = textDocument.getLineText(line.line);\n const start = line.comment;\n const end =\n start + token.length + (text[start + token.length] === ' ' ? 1 : 0);\n edits.push({\n range: {\n start: { line: line.line, character: start },\n end: { line: line.line, character: end },\n },\n newText: '',\n });\n }\n return edits;\n}\n\ninterface OffsetEdit {\n start: number;\n end: number;\n text: string;\n}\n\ninterface BlockCommentMatch {\n open: OffsetEdit;\n close: OffsetEdit;\n contentStart: number;\n contentEnd: number;\n}\n\nexport interface BlockCommentEditResult {\n edits: TextEdit[];\n nextSelectionOffsets: Array<\n readonly [\n start: number,\n end: number,\n direction: EditorSelection['direction'],\n ]\n >;\n}\n\nconst BLOCK_COMMENT_SEARCH_MARGIN = 50;\n\nfunction findBlockComment(\n textDocument: TextDocument<unknown>,\n open: string,\n close: string,\n from: number,\n to: number\n): BlockCommentMatch | undefined {\n const beforeStart = Math.max(0, from - BLOCK_COMMENT_SEARCH_MARGIN);\n const textBefore = textDocument.getTextSlice(beforeStart, from);\n const textAfter = textDocument.getTextSlice(\n to,\n to + BLOCK_COMMENT_SEARCH_MARGIN\n );\n const spaceBefore = textBefore.length - textBefore.trimEnd().length;\n const spaceAfter = textAfter.length - textAfter.trimStart().length;\n const beforeOffset = textBefore.length - spaceBefore;\n if (\n textBefore.slice(beforeOffset - open.length, beforeOffset) === open &&\n textAfter.slice(spaceAfter, spaceAfter + close.length) === close\n ) {\n return {\n open: {\n start: from - spaceBefore - open.length,\n end: from - spaceBefore + (spaceBefore > 0 ? 1 : 0),\n text: '',\n },\n close: {\n start: to + spaceAfter - (spaceAfter > 0 ? 1 : 0),\n end: to + spaceAfter + close.length,\n text: '',\n },\n contentStart: from,\n contentEnd: to,\n };\n }\n\n const length = to - from;\n const shortText =\n length <= BLOCK_COMMENT_SEARCH_MARGIN * 2\n ? textDocument.getTextSlice(from, to)\n : undefined;\n const startText =\n shortText ??\n textDocument.getTextSlice(from, from + BLOCK_COMMENT_SEARCH_MARGIN);\n const endText =\n shortText ??\n textDocument.getTextSlice(to - BLOCK_COMMENT_SEARCH_MARGIN, to);\n const startSpace = startText.length - startText.trimStart().length;\n const endSpace = endText.length - endText.trimEnd().length;\n const closeStart = to - endSpace - close.length;\n if (\n startText.slice(startSpace, startSpace + open.length) !== open ||\n textDocument.getTextSlice(closeStart, closeStart + close.length) !== close\n ) {\n return undefined;\n }\n\n const openStart = from + startSpace;\n const openEnd =\n openStart +\n open.length +\n (/\\s/.test(startText[open.length + startSpace] ?? '') ? 1 : 0);\n const closeDeleteStart =\n closeStart -\n (/\\s/.test(textDocument.getTextSlice(closeStart - 1, closeStart)) ? 1 : 0);\n return {\n open: { start: openStart, end: openEnd, text: '' },\n close: {\n start: closeDeleteStart,\n end: closeStart + close.length,\n text: '',\n },\n contentStart: openEnd,\n contentEnd: closeDeleteStart,\n };\n}\n\nfunction mapOffset(\n offset: number,\n edits: readonly OffsetEdit[],\n cumulativeDeltas: readonly number[],\n association: -1 | 1\n): number {\n let low = 0;\n let high = edits.length;\n while (low < high) {\n const middle = (low + high) >>> 1;\n if (edits[middle].end < offset) {\n low = middle + 1;\n } else {\n high = middle;\n }\n }\n\n let delta = cumulativeDeltas[low];\n for (let index = low; index < edits.length; index++) {\n const edit = edits[index];\n if (offset < edit.start) {\n break;\n }\n if (edit.start === edit.end && offset === edit.start) {\n if (association < 0) {\n break;\n }\n delta += edit.text.length;\n continue;\n }\n if (offset > edit.end) {\n delta += edit.text.length - (edit.end - edit.start);\n continue;\n }\n if (offset === edit.end) {\n return edit.start + delta + edit.text.length;\n }\n return edit.start + delta + (association > 0 ? edit.text.length : 0);\n }\n return offset + delta;\n}\n\n/** Builds block-comment edits and content-preserving post-edit selections. */\nexport function resolveBlockCommentEdits(\n textDocument: TextDocument<unknown>,\n selections: readonly EditorSelection[],\n [open, close]: readonly [string, string],\n linewise = false\n): BlockCommentEditResult | undefined {\n const ranges = selections.map((selection) => {\n let { start, end } = selection;\n if (linewise) {\n let endLine = end.line;\n if (start.line < endLine && end.character === 0) {\n endLine--;\n }\n const firstLine = textDocument.getLineText(start.line);\n const indent = firstLine.length - firstLine.trimStart().length;\n start = { line: start.line, character: indent };\n end = {\n line: endLine,\n character: textDocument.getLineLength(endLine),\n };\n }\n return {\n from: textDocument.offsetAt(start),\n to: textDocument.offsetAt(end),\n direction: selection.direction,\n comment: undefined as BlockCommentMatch | undefined,\n };\n });\n if (linewise && ranges.length > 1) {\n ranges.sort((a, b) => {\n const startOrder = a.from - b.from;\n return startOrder !== 0 ? startOrder : a.to - b.to;\n });\n let lastRangeIndex = 0;\n for (let index = 1; index < ranges.length; index++) {\n const previous = ranges[lastRangeIndex];\n const current = ranges[index];\n if (current.from <= previous.to) {\n previous.to = Math.max(previous.to, current.to);\n } else {\n ranges[++lastRangeIndex] = current;\n }\n }\n ranges.length = lastRangeIndex + 1;\n }\n for (const range of ranges) {\n range.comment = findBlockComment(\n textDocument,\n open,\n close,\n range.from,\n range.to\n );\n }\n\n const shouldUncomment = ranges.every((range) => range.comment !== undefined);\n const offsetEdits: OffsetEdit[] = [];\n for (const range of ranges) {\n const comment = range.comment;\n if (shouldUncomment && comment !== undefined) {\n offsetEdits.push(comment.open, comment.close);\n continue;\n }\n if (comment !== undefined) {\n continue;\n }\n if (range.from === range.to) {\n offsetEdits.push({\n start: range.from,\n end: range.to,\n text: open + ' ' + close,\n });\n continue;\n }\n offsetEdits.push(\n { start: range.from, end: range.from, text: open + ' ' },\n { start: range.to, end: range.to, text: ' ' + close }\n );\n }\n\n if (offsetEdits.length === 0) {\n return undefined;\n }\n offsetEdits.sort((a, b) => {\n const startOrder = a.start - b.start;\n return startOrder !== 0 ? startOrder : a.end - b.end;\n });\n const edits = offsetEdits.map((edit) => ({\n range: {\n start: textDocument.positionAt(edit.start),\n end: textDocument.positionAt(edit.end),\n },\n newText: edit.text,\n }));\n if (linewise) {\n return { edits, nextSelectionOffsets: [] };\n }\n\n const logicalRanges: Array<{\n start: number;\n end: number;\n startAssociation: -1 | 1;\n endAssociation: -1 | 1;\n collapsedInset?: number;\n }> = ranges.map((range) => {\n const comment = range.comment;\n if (shouldUncomment && comment !== undefined) {\n return {\n start: comment.contentStart,\n end: comment.contentEnd,\n startAssociation: 1,\n endAssociation: -1,\n };\n }\n if (comment !== undefined) {\n return {\n start: range.from,\n end: range.to,\n startAssociation: 1,\n endAssociation: 1,\n };\n }\n if (range.from === range.to) {\n return {\n start: range.from,\n end: range.to,\n startAssociation: -1,\n endAssociation: -1,\n collapsedInset: open.length + 1,\n };\n }\n return {\n start: range.from,\n end: range.to,\n startAssociation: 1,\n endAssociation: -1,\n };\n });\n const cumulativeDeltas = new Array<number>(offsetEdits.length + 1);\n cumulativeDeltas[0] = 0;\n for (let index = 0; index < offsetEdits.length; index++) {\n const edit = offsetEdits[index];\n cumulativeDeltas[index + 1] =\n cumulativeDeltas[index] + edit.text.length - (edit.end - edit.start);\n }\n const nextSelectionOffsets = logicalRanges.map((range, index) => {\n const start =\n mapOffset(\n range.start,\n offsetEdits,\n cumulativeDeltas,\n range.startAssociation\n ) + (range.collapsedInset ?? 0);\n const end =\n range.collapsedInset === undefined\n ? mapOffset(\n range.end,\n offsetEdits,\n cumulativeDeltas,\n range.endAssociation\n )\n : start;\n return [start, end, ranges[index].direction] as const;\n });\n\n return {\n edits,\n nextSelectionOffsets,\n };\n}\n"],"mappings":";AAGA,MAAM,uBAAuB;AAC7B,MAAM,wBAAwB,CAAC,MAAM,IAAI;AAgBzC,MAAM,2BAA8C;CAClD,KAAK,EAAE,aAAa,KAAK;CACzB,MAAM;EAAE,aAAa;EAAK,cAAc,CAAC,UAAU,MAAM;CAAE;CAC3D,KAAK,EAAE,aAAa,KAAK;CACzB,cAAc;EAAE,aAAa;EAAK,cAAc,CAAC,OAAO,KAAK;CAAE;CAC/D,KAAK,EAAE,aAAa,OAAO;CAC3B,OAAO;EAAE,aAAa;EAAK,cAAc,CAAC,MAAM,IAAI;CAAE;CACtD,MAAM,EAAE,aAAa,IAAI;CACzB,KAAK,EAAE,aAAa,IAAI;CACxB,UAAU;EAAE,aAAa;EAAM,cAAc,CAAC,QAAQ,KAAK;CAAE;CAC7D,KAAK,EAAE,aAAa,IAAI;CACxB,UAAU,EAAE,aAAa,IAAI;CAC7B,YAAY;EAAE,aAAa;EAAM,cAAc,CAAC,SAAS,MAAM;CAAE;CACjE,KAAK;EAAE,aAAa;EAAK,cAAc,CAAC,KAAK,GAAG;CAAE;CAClD,YAAY;EAAE,aAAa;EAAK,cAAc,CAAC,MAAM,IAAI;CAAE;CAC3D,IAAI,EAAE,aAAa,IAAI;CACvB,KAAK;EAAE,aAAa;EAAM,cAAc,CAAC,QAAQ,KAAK;CAAE;CACxD,KAAK;EAAE,aAAa;EAAM,cAAc,CAAC,QAAQ,IAAI;CAAE;CACvD,MAAM;EAAE,aAAa;EAAM,cAAc,CAAC,QAAQ,KAAK;CAAE;CACzD,MAAM;EAAE,aAAa;EAAK,cAAc,CAAC,KAAK,GAAG;CAAE;CACnD,GAAG,EAAE,aAAa,IAAI;CACtB,QAAQ,EAAE,cAAc,CAAC,MAAM,IAAI,EAAE;CACrC,KAAK,EAAE,aAAa,MAAM;CAC1B,MAAM,EAAE,aAAa,IAAI;CACzB,KAAK,EAAE,aAAa,IAAI;CACxB,SAAS,EAAE,aAAa,KAAK;CAC7B,KAAK,EAAE,aAAa,KAAK;CACzB,QAAQ;EAAE,aAAa;EAAK,cAAc,CAAC,UAAO,QAAK;CAAE;CACzD,QAAQ,EAAE,aAAa,IAAI;CAC3B,YAAY,EAAE,aAAa,IAAI;CAC/B,OAAO;EAAE,aAAa;EAAM,cAAc,CAAC,QAAQ,KAAK;CAAE;CAC1D,QAAQ;EAAE,aAAa;EAAM,cAAc,CAAC,QAAQ,KAAK;CAAE;AAC7D;;AAGA,SAAgB,qBACd,YACA,WACwB;CACxB,MAAM,SAAS;EACb,GAAG,yBAAyB;EAC5B,GAAG,YAAY;CACjB;CACA,OAAO;EACL,aACE,OAAO,gBAAgB,KAAA,IACnB,uBACA,OAAO;EACb,cAAc,OAAO,gBAAgB;CACvC;AACF;;AAWA,SAAgB,wBACd,cACA,YACA,OACY;CACZ,MAAM,QAA2B,CAAC;CAClC,MAAM,4BAAY,IAAI,IAAY;CAElC,KAAK,MAAM,aAAa,YAAY;EAClC,IAAI,UAAU,UAAU,IAAI;EAC5B,IAAI,UAAU,MAAM,OAAO,WAAW,UAAU,IAAI,cAAc,GAChE;EAGF,MAAM,aAAa,MAAM;EACzB,IAAI,YAAY;EAChB,KAAK,IAAI,OAAO,UAAU,MAAM,MAAM,QAAQ,SAAS,QAAQ;GAC7D,IAAI,UAAU,IAAI,IAAI,GACpB;GAEF,UAAU,IAAI,IAAI;GAClB,MAAM,OAAO,aAAa,YAAY,IAAI;GAC1C,MAAM,SAAS,KAAK,SAAS,KAAK,UAAU,CAAC,CAAC;GAC9C,MAAM,QAAQ,WAAW,KAAK;GAC9B,IAAI,CAAC,OACH,YAAY,KAAK,IAAI,WAAW,MAAM;GAExC,MAAM,KAAK;IACT;IACA,SACE,KAAK,MAAM,QAAQ,SAAS,MAAM,MAAM,MAAM,QAAQ,SAAS;IACjE;IACA;IACA,QAAQ;GACV,CAAC;EACH;EAEA,IAAI,cAAc;QACX,IAAI,QAAQ,YAAY,QAAQ,MAAM,QAAQ,SACjD,IAAI,CAAC,MAAM,MAAM,CAAC,OAChB,MAAM,MAAM,CAAC,SAAS;EAAA;EAI5B,IAAI,MAAM,WAAW,aAAa,GAChC,MAAM,WAAW,CAAC,SAAS;CAE/B;CAEA,MAAM,gBAAgB,MAAM,MACzB,SAAS,KAAK,UAAU,MAAM,CAAC,KAAK,SAAS,KAAK,OACrD;CACA,MAAM,QAAoB,CAAC;CAC3B,IAAI,eAAe;EACjB,KAAK,MAAM,QAAQ,OAAO;GACxB,IAAI,KAAK,SAAS,CAAC,KAAK,QACtB;GAEF,MAAM,WAAW;IAAE,MAAM,KAAK;IAAM,WAAW,KAAK;GAAO;GAC3D,MAAM,KAAK;IACT,OAAO;KAAE,OAAO;KAAU,KAAK;IAAS;IACxC,SAAS,QAAQ;GACnB,CAAC;EACH;EACA,OAAO;CACT;CAEA,KAAK,MAAM,QAAQ,OAAO;EACxB,IAAI,KAAK,UAAU,GACjB;EAEF,MAAM,OAAO,aAAa,YAAY,KAAK,IAAI;EAC/C,MAAM,QAAQ,KAAK;EACnB,MAAM,MACJ,QAAQ,MAAM,UAAU,KAAK,QAAQ,MAAM,YAAY,MAAM,IAAI;EACnE,MAAM,KAAK;GACT,OAAO;IACL,OAAO;KAAE,MAAM,KAAK;KAAM,WAAW;IAAM;IAC3C,KAAK;KAAE,MAAM,KAAK;KAAM,WAAW;IAAI;GACzC;GACA,SAAS;EACX,CAAC;CACH;CACA,OAAO;AACT;AA0BA,MAAM,8BAA8B;AAEpC,SAAS,iBACP,cACA,MACA,OACA,MACA,IAC+B;CAC/B,MAAM,cAAc,KAAK,IAAI,GAAG,OAAO,2BAA2B;CAClE,MAAM,aAAa,aAAa,aAAa,aAAa,IAAI;CAC9D,MAAM,YAAY,aAAa,aAC7B,IACA,KAAK,2BACP;CACA,MAAM,cAAc,WAAW,SAAS,WAAW,QAAQ,CAAC,CAAC;CAC7D,MAAM,aAAa,UAAU,SAAS,UAAU,UAAU,CAAC,CAAC;CAC5D,MAAM,eAAe,WAAW,SAAS;CACzC,IACE,WAAW,MAAM,eAAe,KAAK,QAAQ,YAAY,MAAM,QAC/D,UAAU,MAAM,YAAY,aAAa,MAAM,MAAM,MAAM,OAE3D,OAAO;EACL,MAAM;GACJ,OAAO,OAAO,cAAc,KAAK;GACjC,KAAK,OAAO,eAAe,cAAc,IAAI,IAAI;GACjD,MAAM;EACR;EACA,OAAO;GACL,OAAO,KAAK,cAAc,aAAa,IAAI,IAAI;GAC/C,KAAK,KAAK,aAAa,MAAM;GAC7B,MAAM;EACR;EACA,cAAc;EACd,YAAY;CACd;CAIF,MAAM,YADS,KAAK,QAER,8BAA8B,IACpC,aAAa,aAAa,MAAM,EAAE,IAClC,KAAA;CACN,MAAM,YACJ,aACA,aAAa,aAAa,MAAM,OAAO,2BAA2B;CACpE,MAAM,UACJ,aACA,aAAa,aAAa,KAAK,6BAA6B,EAAE;CAChE,MAAM,aAAa,UAAU,SAAS,UAAU,UAAU,CAAC,CAAC;CAE5D,MAAM,aAAa,MADF,QAAQ,SAAS,QAAQ,QAAQ,CAAC,CAAC,UACjB,MAAM;CACzC,IACE,UAAU,MAAM,YAAY,aAAa,KAAK,MAAM,MAAM,QAC1D,aAAa,aAAa,YAAY,aAAa,MAAM,MAAM,MAAM,OAErE;CAGF,MAAM,YAAY,OAAO;CACzB,MAAM,UACJ,YACA,KAAK,UACJ,KAAK,KAAK,UAAU,KAAK,SAAS,eAAe,EAAE,IAAI,IAAI;CAC9D,MAAM,mBACJ,cACC,KAAK,KAAK,aAAa,aAAa,aAAa,GAAG,UAAU,CAAC,IAAI,IAAI;CAC1E,OAAO;EACL,MAAM;GAAE,OAAO;GAAW,KAAK;GAAS,MAAM;EAAG;EACjD,OAAO;GACL,OAAO;GACP,KAAK,aAAa,MAAM;GACxB,MAAM;EACR;EACA,cAAc;EACd,YAAY;CACd;AACF;AAEA,SAAS,UACP,QACA,OACA,kBACA,aACQ;CACR,IAAI,MAAM;CACV,IAAI,OAAO,MAAM;CACjB,OAAO,MAAM,MAAM;EACjB,MAAM,SAAU,MAAM,SAAU;EAChC,IAAI,MAAM,OAAO,CAAC,MAAM,QACtB,MAAM,SAAS;OAEf,OAAO;CAEX;CAEA,IAAI,QAAQ,iBAAiB;CAC7B,KAAK,IAAI,QAAQ,KAAK,QAAQ,MAAM,QAAQ,SAAS;EACnD,MAAM,OAAO,MAAM;EACnB,IAAI,SAAS,KAAK,OAChB;EAEF,IAAI,KAAK,UAAU,KAAK,OAAO,WAAW,KAAK,OAAO;GACpD,IAAI,cAAc,GAChB;GAEF,SAAS,KAAK,KAAK;GACnB;EACF;EACA,IAAI,SAAS,KAAK,KAAK;GACrB,SAAS,KAAK,KAAK,UAAU,KAAK,MAAM,KAAK;GAC7C;EACF;EACA,IAAI,WAAW,KAAK,KAClB,OAAO,KAAK,QAAQ,QAAQ,KAAK,KAAK;EAExC,OAAO,KAAK,QAAQ,SAAS,cAAc,IAAI,KAAK,KAAK,SAAS;CACpE;CACA,OAAO,SAAS;AAClB;;AAGA,SAAgB,yBACd,cACA,YACA,CAAC,MAAM,QACP,WAAW,OACyB;CACpC,MAAM,SAAS,WAAW,KAAK,cAAc;EAC3C,IAAI,EAAE,OAAO,QAAQ;EACrB,IAAI,UAAU;GACZ,IAAI,UAAU,IAAI;GAClB,IAAI,MAAM,OAAO,WAAW,IAAI,cAAc,GAC5C;GAEF,MAAM,YAAY,aAAa,YAAY,MAAM,IAAI;GACrD,MAAM,SAAS,UAAU,SAAS,UAAU,UAAU,CAAC,CAAC;GACxD,QAAQ;IAAE,MAAM,MAAM;IAAM,WAAW;GAAO;GAC9C,MAAM;IACJ,MAAM;IACN,WAAW,aAAa,cAAc,OAAO;GAC/C;EACF;EACA,OAAO;GACL,MAAM,aAAa,SAAS,KAAK;GACjC,IAAI,aAAa,SAAS,GAAG;GAC7B,WAAW,UAAU;GACrB,SAAS,KAAA;EACX;CACF,CAAC;CACD,IAAI,YAAY,OAAO,SAAS,GAAG;EACjC,OAAO,MAAM,GAAG,MAAM;GACpB,MAAM,aAAa,EAAE,OAAO,EAAE;GAC9B,OAAO,eAAe,IAAI,aAAa,EAAE,KAAK,EAAE;EAClD,CAAC;EACD,IAAI,iBAAiB;EACrB,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS;GAClD,MAAM,WAAW,OAAO;GACxB,MAAM,UAAU,OAAO;GACvB,IAAI,QAAQ,QAAQ,SAAS,IAC3B,SAAS,KAAK,KAAK,IAAI,SAAS,IAAI,QAAQ,EAAE;QAE9C,OAAO,EAAE,kBAAkB;EAE/B;EACA,OAAO,SAAS,iBAAiB;CACnC;CACA,KAAK,MAAM,SAAS,QAClB,MAAM,UAAU,iBACd,cACA,MACA,OACA,MAAM,MACN,MAAM,EACR;CAGF,MAAM,kBAAkB,OAAO,OAAO,UAAU,MAAM,YAAY,KAAA,CAAS;CAC3E,MAAM,cAA4B,CAAC;CACnC,KAAK,MAAM,SAAS,QAAQ;EAC1B,MAAM,UAAU,MAAM;EACtB,IAAI,mBAAmB,YAAY,KAAA,GAAW;GAC5C,YAAY,KAAK,QAAQ,MAAM,QAAQ,KAAK;GAC5C;EACF;EACA,IAAI,YAAY,KAAA,GACd;EAEF,IAAI,MAAM,SAAS,MAAM,IAAI;GAC3B,YAAY,KAAK;IACf,OAAO,MAAM;IACb,KAAK,MAAM;IACX,MAAM,OAAO,OAAO;GACtB,CAAC;GACD;EACF;EACA,YAAY,KACV;GAAE,OAAO,MAAM;GAAM,KAAK,MAAM;GAAM,MAAM,OAAO;EAAI,GACvD;GAAE,OAAO,MAAM;GAAI,KAAK,MAAM;GAAI,MAAM,MAAM;EAAM,CACtD;CACF;CAEA,IAAI,YAAY,WAAW,GACzB;CAEF,YAAY,MAAM,GAAG,MAAM;EACzB,MAAM,aAAa,EAAE,QAAQ,EAAE;EAC/B,OAAO,eAAe,IAAI,aAAa,EAAE,MAAM,EAAE;CACnD,CAAC;CACD,MAAM,QAAQ,YAAY,KAAK,UAAU;EACvC,OAAO;GACL,OAAO,aAAa,WAAW,KAAK,KAAK;GACzC,KAAK,aAAa,WAAW,KAAK,GAAG;EACvC;EACA,SAAS,KAAK;CAChB,EAAE;CACF,IAAI,UACF,OAAO;EAAE;EAAO,sBAAsB,CAAC;CAAE;CAG3C,MAAM,gBAMD,OAAO,KAAK,UAAU;EACzB,MAAM,UAAU,MAAM;EACtB,IAAI,mBAAmB,YAAY,KAAA,GACjC,OAAO;GACL,OAAO,QAAQ;GACf,KAAK,QAAQ;GACb,kBAAkB;GAClB,gBAAgB;EAClB;EAEF,IAAI,YAAY,KAAA,GACd,OAAO;GACL,OAAO,MAAM;GACb,KAAK,MAAM;GACX,kBAAkB;GAClB,gBAAgB;EAClB;EAEF,IAAI,MAAM,SAAS,MAAM,IACvB,OAAO;GACL,OAAO,MAAM;GACb,KAAK,MAAM;GACX,kBAAkB;GAClB,gBAAgB;GAChB,gBAAgB,KAAK,SAAS;EAChC;EAEF,OAAO;GACL,OAAO,MAAM;GACb,KAAK,MAAM;GACX,kBAAkB;GAClB,gBAAgB;EAClB;CACF,CAAC;CACD,MAAM,mBAAmB,IAAI,MAAc,YAAY,SAAS,CAAC;CACjE,iBAAiB,KAAK;CACtB,KAAK,IAAI,QAAQ,GAAG,QAAQ,YAAY,QAAQ,SAAS;EACvD,MAAM,OAAO,YAAY;EACzB,iBAAiB,QAAQ,KACvB,iBAAiB,SAAS,KAAK,KAAK,UAAU,KAAK,MAAM,KAAK;CAClE;CAqBA,OAAO;EACL;EACA,sBAtB2B,cAAc,KAAK,OAAO,UAAU;GAC/D,MAAM,QACJ,UACE,MAAM,OACN,aACA,kBACA,MAAM,gBACR,KAAK,MAAM,kBAAkB;GAU/B,OAAO;IAAC;IARN,MAAM,mBAAmB,KAAA,IACrB,UACE,MAAM,KACN,aACA,kBACA,MAAM,cACR,IACA;IACc,OAAO,MAAM,CAAC;GAAS;EAC7C,CAIqB;CACrB;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lineAnnotations.d.ts","names":[],"sources":["../../src/editor/lineAnnotations.ts"],"mappings":";;;;iBAcgB,oCAAA,IACd,MAAA,EAAQ,kBAAA,EACR,eAAA,EAAiB,kBAAA,CAAmB,CAAA,MACnC,kBAAA,CAAmB,CAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"lineAnnotations.d.ts","names":[],"sources":["../../src/editor/lineAnnotations.ts"],"mappings":";;;;iBAcgB,oCAAA,IACd,MAAA,EAAQ,kBAAA,EACR,eAAA,EAAiB,kBAAA,CAAmB,CAAA,MACnC,kBAAA,CAAmB,CAAA;AAAA,iBAgNN,qBAAA,cACd,eAAA,EAAiB,kBAAA,CAAmB,WAAA,KACpC,SAAA,EAAW,WAAA,EACX,QAAA,GAAW,WAAA"}
|
|
@@ -44,33 +44,32 @@ function applyDocumentChangeToLineAnnotations(change, lineAnnotations) {
|
|
|
44
44
|
return changed ? nextLineAnnotations : void 0;
|
|
45
45
|
}
|
|
46
46
|
function getLineAnnotationChanges(change) {
|
|
47
|
-
if (change.lineDelta
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
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
|
+
});
|
|
72
71
|
const removedLineCount = Math.max(0, -change.lineDelta);
|
|
73
|
-
const deletedToDocumentEnd = change.
|
|
72
|
+
const deletedToDocumentEnd = change.endedAtDocumentEnd && change.startLine + removedLineCount === change.previousLineCount - 1;
|
|
74
73
|
return [{
|
|
75
74
|
startLine: change.startLine,
|
|
76
75
|
startCharacter: change.startCharacter,
|
|
@@ -1 +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.lineDelta === 0) {\n if (change.changedLineChanges !== undefined) {\n return change.changedLineChanges.flatMap(\n ([startLine, _endLine, lineDelta]) => {\n if (lineDelta === 0) {\n return [];\n }\n const removedLineCount = Math.max(0, -lineDelta);\n return [\n {\n startLine,\n startCharacter: 0,\n endLine: startLine + removedLineCount,\n deletesEndLine: false,\n insertedLineBreaks: Math.max(0, lineDelta),\n lineDelta,\n },\n ];\n }\n );\n }\n\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.startLine === 0 &&\n change.startCharacter === 0 &&\n change.lineCount === 1 &&\n change.lineDelta === 1 - change.previousLineCount;\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":";;;AAcA,SAAgB,qCACd,QACA,iBACqC;CACrC,MAAM,oBAAoB,yBAAyB,MAAM;CACzD,IAAI,kBAAkB,WAAW,GAC/B;CAGF,MAAM,sBAA+C,CAAC;CACtD,IAAI,UAAU;CACd,KAAK,MAAM,cAAc,iBAAiB;EACxC,IAAI,WAAW,SAAS,eAAe,WAAW,cAAc,GAAG;GACjE,oBAAoB,KAAK,UAAU;GACnC;EACF;EAEA,IAAI,OAA2B,WAAW,aAAa;EACvD,IAAI,YAAY,OAAO;EACvB,IAAI,oBAAoB;EACxB,KAAK,MAAM,cAAc,mBAAmB;GAC1C,MAAM,gBAAgB,KAAK,IAAI,GAAG,YAAY,WAAW,SAAS;GAClE,MAAM,WAAW,yBACf,MACA,YACA,aACF;GACA,IAAI,aAAa,KAAA,GAAW;IAC1B,oBAAoB;IACpB,OAAO,KAAA;IACP;GACF;GACA,IACE,aAAa,QACb,gCAAgC,MAAM,UAAU,GAEhD,oBAAoB;GAEtB,OAAO;GACP,YAAY;EACd;EAEA,IAAI,SAAS,KAAA,GAAW;GACtB,UAAU;GACV;EACF;EAEA,MAAM,aAAa,OAAO;EAC1B,IAAI,mBAAmB;GACrB,oBAAoB,KAClB,eAAe,WAAW,aACtB,aACA;IACE,GAAG;IACH;GACF,CACN;GACA,UAAU;GACV;EACF;EAEA,oBAAoB,KAAK,UAAU;CACrC;CAEA,OAAO,UAAU,sBAAsB,KAAA;AACzC;AAEA,SAAS,yBACP,QACiC;CACjC,IAAI,OAAO,cAAc,GAAG;EAC1B,IAAI,OAAO,uBAAuB,KAAA,GAChC,OAAO,OAAO,mBAAmB,SAC9B,CAAC,WAAW,UAAU,eAAe;GACpC,IAAI,cAAc,GAChB,OAAO,CAAC;GAGV,OAAO,CACL;IACE;IACA,gBAAgB;IAChB,SAAS,YALY,KAAK,IAAI,GAAG,CAAC,SAKE;IACpC,gBAAgB;IAChB,oBAAoB,KAAK,IAAI,GAAG,SAAS;IACzC;GACF,CACF;EACF,CACF;EAGF,OAAO,OAAO,kBAAkB,SAAS,CAAC,WAAW,aAAa;GAChE,MAAM,qBAAqB,UAAU;GACrC,IAAI,sBAAsB,GACxB,OAAO,CAAC;GAEV,OAAO,CACL;IACE;IACA,gBAAgB;IAChB,SAAS;IACT,gBAAgB;IAChB;IACA,WAAW;GACb,CACF;EACF,CAAC;CACH;CACA,MAAM,mBAAmB,KAAK,IAAI,GAAG,CAAC,OAAO,SAAS;CACtD,MAAM,uBACJ,OAAO,cAAc,KACrB,OAAO,mBAAmB,KAC1B,OAAO,cAAc,KACrB,OAAO,cAAc,IAAI,OAAO;CAClC,OAAO,CACL;EACE,WAAW,OAAO;EAClB,gBAAgB,OAAO;EACvB,SAAS,OAAO,YAAY;EAC5B,gBAAgB;EAChB,oBAAoB,KAAK,IAAI,GAAG,OAAO,SAAS;EAChD,WAAW,OAAO;CACpB,CACF;AACF;AAEA,SAAS,yBACP,MACA,YACA,eACoB;CACpB,IAAI,OAAO,WAAW,WACpB,OAAO;CAGT,IACE,OAAO,WAAW,WACjB,WAAW,UAAU,WAAW,aAC/B,SAAS,WAAW,WACpB,CAAC,WAAW,gBAEd,OAAO,OAAO,WAAW;CAG3B,IAAI,WAAW,cAAc,WAAW,SAAS;EAC/C,IAAI,WAAW,mBAAmB,GAChC,OAAO,OAAO,WAAW;EAE3B,OAAO;CACT;CAEA,IAAI,gCAAgC,MAAM,UAAU,GAClD;CAGF,MAAM,wBAAwB,KAAK,IACjC,KAAK,IAAI,GAAG,OAAO,WAAW,SAAS,GACvC,WAAW,kBACb;CACA,OAAO,UAAU,WAAW,YAAY,uBAAuB,aAAa;AAC9E;AAEA,SAAS,gCACP,MACA,YACS;CACT,IACE,WAAW,aAAa,KACxB,OAAO,WAAW,aAClB,OAAO,WAAW,SAElB,OAAO;CAET,IAAI,SAAS,WAAW,aAAa,WAAW,iBAAiB,GAC/D,OAAO;CAET,IAAI,SAAS,WAAW,WAAW,CAAC,WAAW,gBAC7C,OAAO;CAET,OAAO;AACT;AAEA,SAAS,gCACP,MACA,YACS;CACT,IACE,WAAW,cAAc,KACzB,OAAO,WAAW,aAClB,OAAO,WAAW,SAElB,OAAO;CAET,OAAO,EACL,WAAW,UAAU,WAAW,aAChC,SAAS,WAAW,WACpB,CAAC,WAAW;AAEhB;AAEA,SAAS,UAAU,MAAc,WAA2B;CAC1D,OAAO,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,KAAK,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC;AAC/D;AAEA,SAAgB,sBACd,iBACA,WACA,UACM;CACN,MAAM,sCAAsB,IAAI,IAAsB;CACtD,MAAM,sCAAsB,IAAI,IAAsB;CACtD,KAAK,MAAM,cAAc,iBAAiB;EACxC,MAAM,aAAa,WAAW;EAC9B,IAAI,CAAC,oBAAoB,IAAI,UAAU,GACrC,oBAAoB,IAAI,YAAY,CAAC,CAAC;EAExC,IAAI,CAAC,oBAAoB,IAAI,UAAU,GACrC,oBAAoB,IAAI,YAAY,CAAC,CAAC;EAMxC,CAHE,WAAW,SAAS,cAChB,sBACA,oBAAA,CACF,IAAI,UAAU,CAAC,CAAE,KAAK,sBAAsB,UAAU,CAAC;CAC7D;CAEA,MAAM,kBAAkB,UAAU,eAAe;CACjD,IAAI;CACJ,IAAI;CACJ,IACE,mBAAmB,QACnB,2BAA2B,eAC3B,gBAAgB,QAAQ,cAAc,KAAA,GAEtC,KAAK,MAAM,SAAS,gBAAgB,UAAU;EAC5C,MAAM,KAAK;EACX,MAAM,EAAE,QAAQ,YAAY,GAAG;EAC/B,IAAI,WAAW,KAAA,GACb,oBAAoB;OACf,IAAI,YAAY,KAAA,GACrB,qBAAqB;CAEzB;CAGF,4BAA4B,WAAW,QAAQ;CAC/C,IAAI,uBAAuB,KAAA,GACzB,4BAA4B,oBAAoB,iBAAiB;CAGnE,MAAM,8BAA8B,6BAClC,qBACA,WACA,QACF;CACA,IAAI,uBAAuB,KAAA,GACzB;CAGF,MAAM,8BAA8B,6BAClC,qBACA,oBACA,iBACF;CAEA,4BAA4B;EAC1B,gCACE,qBACA,qBACA,6BACA,2BACF;CACF,CAAC;AACH;AAEA,SAAS,4BACP,WACA,UACM;CACN,MAAM,gBAA+B,CAAC;CACtC,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,mBAAmB,KAAK;EACpD,MAAM,KAAK,UAAU,SAAS;EAC9B,IAAI,GAAG,QAAQ,mBAAmB,KAAA,GAAW;GAC3C,cAAc,KAAK,EAAE;GACrB,IAAI,aAAa,KAAA,GACf,cAAc,KAAK,SAAS,SAAS,EAAiB;EAE1D;CACF;CACA,KAAK,MAAM,MAAM,eACf,GAAG,OAAO;AAEd;AAEA,SAAS,6BACP,iBACA,WACA,UAC0B;CAC1B,MAAM,qCAAqB,IAAI,IAAyB;CACxD,KAAK,MAAM,MAAM,UAAU,UAAU;EACnC,MAAM,aAAa,kBAAkB,EAAiB;EACtD,IAAI,eAAe,KAAA,GAAW;GAC5B,MAAM,cAAc,gBAAgB,IAAI,UAAU;GAClD,IAAI,gBAAgB,KAAA,GAAW;IAE7B,MAAM,oBAAoB,EAAE,OAAO;KACjC,SAAS,EACP,gBAAgB,QAHF,aAAa,GAI7B;KACA,UAAU,CACR,EAAE,OAAO;MACP,SAAS;MACT,UAAU,YAAY,KAAK,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;KACzD,CAAC,CACH;IACF,CAAC;IACD,GAAG,MAAM,iBAAiB;IAC1B,mBAAmB,IAAI,YAAY,iBAAiB;GACtD;EACF;CACF;CAEA,IAAI,aAAa,KAAA,GACf,KAAK,MAAM,MAAM,SAAS,UAAU;EAClC,MAAM,aAAa,kBAAkB,IAAmB,cAAc;EACtE,IAAI,eAAe,KAAA,KAAa,gBAAgB,IAAI,UAAU,GAAG;GAC/D,MAAM,WAAW,EAAE,OAAO;IACxB,SAAS;KACP,cAAc;KACd,YAAY;IACd;IACA,OAAO,EACL,SAAS,SACX;GACF,CAAC;GACD,GAAG,MAAM,QAAQ;EACnB;CACF;CAGF,OAAO;AACT;AAEA,SAAS,gCACP,qBACA,qBACA,4BACA,4BACM;CACN,MAAM,gCAAgB,IAAI,IAAoB;CAC9C,KAAK,MAAM,CAAC,YAAY,gBAAgB,oBAAoB,QAAQ,GAAG;EACrE,MAAM,oBAAoB,2BAA2B,IAAI,UAAU;EACnE,IAAI,YAAY,WAAW,KAAK,sBAAsB,KAAA,GAAW;GAC/D,MAAM,SAAS,+BAA+B,iBAAiB;GAC/D,IAAI,SAAS,GACX,cAAc,IAAI,YAAY,MAAM;EAExC;CACF;CACA,KAAK,MAAM,CAAC,YAAY,gBAAgB,oBAAoB,QAAQ,GAAG;EACrE,MAAM,oBAAoB,2BAA2B,IAAI,UAAU;EACnE,IAAI,YAAY,WAAW,KAAK,sBAAsB,KAAA,GAAW;GAC/D,MAAM,SAAS,+BAA+B,iBAAiB;GAC/D,IAAI,SAAS,GACX,cAAc,IAAI,YAAY,MAAM;EAExC;CACF;CACA,8BACE,qBACA,4BACA,aACF;CACA,8BACE,qBACA,4BACA,aACF;AACF;AAEA,SAAS,+BAA+B,kBAAuC;CAC7E,MAAM,UAAU,iBAAiB;CACjC,IAAI,EAAE,mBAAmB,cACvB,OAAO;CAET,OAAO,QAAQ,sBAAsB,CAAC,CAAC;AACzC;AAEA,SAAS,8BACP,iBACA,oBACA,eACM;CACN,KAAK,MAAM,CAAC,YAAY,sBAAsB,mBAAmB,QAAQ,GAAG;EAC1E,MAAM,cAAc,gBAAgB,IAAI,UAAU;EAClD,MAAM,eAAe,cAAc,IAAI,UAAU;EACjD,IAAI,aAAa,WAAW,KAAK,iBAAiB,KAAA,GAChD,kBAAkB,MAAM,YACtB,iCACA,GAAG,aAAa,GAClB;CAEJ;AACF"}
|
|
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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"}
|