@pierre/diffs 1.3.0-beta.3 → 1.3.0-beta.4
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.map +1 -1
- package/dist/components/File.d.ts +2 -2
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +11 -11
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +7 -4
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +56 -47
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +1 -1
- package/dist/components/VirtualizedFile.d.ts +1 -1
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +7 -3
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +2 -1
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +14 -0
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
- package/dist/editor/editStack.d.ts +1 -1
- package/dist/editor/editor.d.ts +10 -8
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +386 -339
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +1 -1
- package/dist/editor/editor2.js.map +1 -1
- package/dist/editor/lineAnnotations.d.ts +2 -1
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +111 -1
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +33 -0
- package/dist/editor/marker.d.ts.map +1 -0
- package/dist/editor/marker.js +185 -0
- package/dist/editor/marker.js.map +1 -0
- package/dist/editor/pieceTable.d.ts +2 -2
- package/dist/editor/pieceTable.d.ts.map +1 -1
- package/dist/editor/pieceTable.js +42 -11
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/searchPanel.js +2 -2
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +19 -3
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +188 -37
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/{quickEdit.d.ts → selectionAction.d.ts} +8 -8
- package/dist/editor/selectionAction.d.ts.map +1 -0
- package/dist/editor/{quickEdit.js → selectionAction.js} +18 -18
- package/dist/editor/selectionAction.js.map +1 -0
- package/dist/editor/sprite.d.ts +3 -2
- package/dist/editor/sprite.d.ts.map +1 -1
- package/dist/editor/sprite.js +9 -2
- package/dist/editor/sprite.js.map +1 -1
- package/dist/editor/textDocument.d.ts +4 -4
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +7 -7
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/tokenzier.js +11 -3
- package/dist/editor/tokenzier.js.map +1 -1
- package/dist/editor/utils.d.ts +3 -1
- package/dist/editor/utils.d.ts.map +1 -1
- package/dist/editor/utils.js +16 -1
- package/dist/editor/utils.js.map +1 -1
- package/dist/highlighter/shared_highlighter.js +3 -29
- package/dist/highlighter/shared_highlighter.js.map +1 -1
- package/dist/highlighter/themes/attachResolvedThemes.js +4 -3
- package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/cleanUpResolvedThemes.js +3 -2
- package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/constants.d.ts +1 -7
- package/dist/highlighter/themes/constants.d.ts.map +1 -1
- package/dist/highlighter/themes/constants.js +1 -4
- package/dist/highlighter/themes/constants.js.map +1 -1
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js +2 -2
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
- package/dist/highlighter/themes/getResolvedThemes.js +2 -8
- package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/hasResolvedThemes.js +2 -3
- package/dist/highlighter/themes/hasResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/registerCustomCSSVariableTheme.js +1 -1
- package/dist/highlighter/themes/registerCustomTheme.d.ts +5 -3
- package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/registerCustomTheme.js +15 -5
- package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveTheme.js +6 -27
- package/dist/highlighter/themes/resolveTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveThemes.js +5 -12
- package/dist/highlighter/themes/resolveThemes.js.map +1 -1
- package/dist/highlighter/themes/themeResolution.d.ts +8 -0
- package/dist/highlighter/themes/themeResolution.d.ts.map +1 -0
- package/dist/highlighter/themes/themeResolution.js +22 -0
- package/dist/highlighter/themes/themeResolution.js.map +1 -0
- package/dist/highlighter/themes/themeResolver.d.ts +8 -0
- package/dist/highlighter/themes/themeResolver.d.ts.map +1 -0
- package/dist/highlighter/themes/themeResolver.js +8 -0
- package/dist/highlighter/themes/themeResolver.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/react/index.d.ts +2 -2
- package/dist/react/jsx.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +1 -0
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +4 -1
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +134 -10
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +2 -2
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +5 -5
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/types.d.ts +9 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/getHighlighterThemeStyles.js +16 -12
- package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
- package/dist/utils/parsePatchFiles.js +93 -4
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/updateDiffHunks.d.ts +13 -0
- package/dist/utils/updateDiffHunks.d.ts.map +1 -0
- package/dist/utils/updateDiffHunks.js +171 -0
- package/dist/utils/updateDiffHunks.js.map +1 -0
- package/dist/utils/virtualDiffLayout.d.ts +2 -1
- package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
- package/dist/utils/virtualDiffLayout.js +9 -1
- package/dist/utils/virtualDiffLayout.js.map +1 -1
- package/dist/worker/worker-portable.js +727 -22
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +23 -15
- package/dist/worker/worker.js.map +1 -1
- package/package.json +2 -1
- package/dist/editor/quickEdit.d.ts.map +0 -1
- package/dist/editor/quickEdit.js.map +0 -1
package/dist/editor/editor2.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//#region src/editor/editor.css
|
|
2
|
-
var editor_default = "@layer base,theme,rendered,unsafe;::selection{background-color:#0000}@keyframes blinking{0%{opacity:1}50%{opacity:0}to{opacity:1}}:host,[data-code],[data-content]{position:relative}[data-content]{caret-color:var(--diffs-bg-caret);background-color:#0000;outline:none}[data-column-number]{color:var(--diffs-editor-line-number-fg)}[data-column-number][data-selected-line]
|
|
2
|
+
var editor_default = "@layer base,theme,rendered,unsafe;::selection{background-color:#0000}@keyframes blinking{0%{opacity:1}50%{opacity:0}to{opacity:1}}:host,[data-code],[data-content]{position:relative}[data-content]{caret-color:var(--diffs-bg-caret);background-color:#0000;outline:none}[data-gutter-buffer],[data-line]:not([data-selected-line]),[data-line]:not([data-selected-line]) span,[data-line-annotation]{background-color:#0000}[data-column-number]{color:var(--diffs-editor-line-number-fg)}[data-column-number][data-selected-line]{background-color:var(--diffs-editor-line-number-active-bg);color:var(--diffs-editor-line-number-active-fg)}[data-column-number][data-active]{color:var(--diffs-editor-line-number-active-fg)}[data-line]{cursor:text}[data-line][data-selected-line]{background-color:var(--diffs-editor-line-highlight-bg)}[data-line][data-line-type=change-deletion]{background-color:var(--diffs-line-bg)}[data-editor-overlay]{display:contents}[data-caret],[data-selection-range],[data-match-range],[data-marker-range]{height:1lh;line-height:var(--diffs-line-height);pointer-events:none;position:absolute;top:0;left:0}[data-caret]{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)))));visibility:hidden;width:2px;animation:1.2s .8s infinite blinking}[data-selection-range]{z-index:-10;background-color:var(--diffs-editor-selection-bg)}[data-selection-corner]{background-color:var(--diffs-bg);width:100%;height:100%}[data-match-range]{z-index:-10;background-color:var(--diffs-editor-match-bg,var(--diffs-editor-selection-bg))}[data-match-range]:not([data-focus]){background-color:var(--diffs-editor-match-highlight-bg,light-dark(#ff963288,#ff963266))}[data-marker-range]{z-index:1;mask-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2IiBoZWlnaHQ9IjMiPjxwYXRoIGQ9Im0wIDIuNSBsMiAtMS41IGwxIDAgbDIgMS41IGwxIDAiIHN0cm9rZT0iI2ZmZiIgZmlsbD0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PC9zdmc+);mask-position:0 100%;mask-size:6px 3px;mask-repeat:repeat-x}[data-marker-error]{background-color:var(--diffs-editor-error-fg,red)}[data-marker-warning]{background-color:var(--diffs-editor-warning-fg,#cca700)}[data-marker-info]{background-color:var(--diffs-editor-info-fg,#3794ff)}[data-marker-hint]{background-color:var(--diffs-editor-hint-fg,#6a6a6a)}[data-rtl]{border-top-left-radius:3px}[data-rtr]{border-top-right-radius:3px}[data-rbl]{border-bottom-left-radius:3px}[data-rbr]{border-bottom-right-radius:3px}@media (width>=480px){[data-content]{caret-color:#0000}[data-selection-action]{caret-color:currentColor}[data-content]:focus~[data-editor-overlay] [data-caret]{visibility:visible}}[data-editor-widget]{--diffs-widget-bg:color-mix(in lab, var(--diffs-fg) 4%, var(--diffs-bg));--diffs-widget-border:color-mix(in lab, var(--diffs-fg) 20%, transparent);--diffs-widget-shadow:inset 0 0 0 1px var(--diffs-bg), 0 4px 8px #00000013, 0 6px 18px #00000013;z-index:100;border:1px solid var(--diffs-widget-border);background-color:var(--diffs-widget-bg);width:fit-content;max-width:calc(100% - 24px);box-shadow:var(--diffs-widget-shadow);background-clip:padding-box;border-radius:9px;position:absolute;top:0;left:0}[data-marker-popup]{pointer-events:auto;min-width:180px;font-family:var(--diffs-header-font-fallback);padding:8px 12px;font-size:14px;line-height:1.4}[data-marker-popup] code{background-color:#0000;display:inline}[data-selection-action-icon]{z-index:10;width:1lh;height:1lh;color:color-mix(in lab, var(--diffs-fg) 40%, var(--diffs-bg));cursor:pointer;visibility:hidden;border-radius:4px;justify-content:center;align-items:center;transition:background-color .1s ease-in-out,color .1s ease-in-out;display:flex;position:absolute;top:0;left:-1lh}[data-selection-action-icon][data-visible=true]{visibility:visible}[data-selection-action-icon]:hover{background-color:color-mix(in lab, var(--diffs-fg) 8%, var(--diffs-bg));color:var(--diffs-fg)}[data-selection-action]{padding-inline-end:1ch}[data-search-panel]{margin-inline:auto 12px;gap:6px;min-width:300px;margin-bottom:4px;padding:4px;display:flex;position:sticky;top:12px}[data-search-panel-row]{width:100%;font-family:var(--diffs-header-font-fallback);justify-content:flex-start;align-items:center;gap:1px;font-size:14px;display:flex}[data-search-panel-row] input{width:120px;color:var(--diffs-fg);background-color:#0000;border:none;outline:none;padding-inline:4px;font-size:14px;line-height:24px}[data-search-panel-row] input::selection{background-color:color-mix(in lab, var(--diffs-fg) 8%, var(--diffs-bg))}[data-search-panel-row] [data-matches]{min-width:10ch;color:color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg));margin-right:auto;padding-inline:4px;font-size:12px;font-weight:500;line-height:20px}[data-search-panel-row] [data-matches][data-no-matches]{color:color-mix(in lab, var(--diffs-deletion-base) 90%, var(--diffs-bg))}[data-search-panel-row] svg{fill:currentColor;display:block}[data-search-panel-row] [data-icon]{width:24px;height:24px;color:color-mix(in lab, var(--diffs-fg) 65%, var(--diffs-bg));cursor:pointer;border-radius:4px;flex-shrink:0;justify-content:center;align-items:center;transition:background-color .1s ease-in-out,color .1s ease-in-out;display:flex}[data-search-panel-row] [data-icon=search]{color:color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg));cursor:default}[data-search-panel-row] [data-icon][data-disabled=true]{opacity:.25;pointer-events:none}[data-search-panel-row] [data-icon]:not([data-icon=search]):hover{background-color:color-mix(in lab, var(--diffs-fg) 6%, var(--diffs-bg));color:var(--diffs-fg)}[data-search-panel-row] [data-icon][data-active=true]{background-color:color-mix(in lab, var(--diffs-fg) 10%, var(--diffs-bg));color:var(--diffs-fg)}[data-search-panel-row] [data-divider]{background-color:color-mix(in lab, var(--diffs-fg) 10%, var(--diffs-bg));flex-shrink:0;align-self:center;width:1px;height:16px;margin-inline:8px}";
|
|
3
3
|
|
|
4
4
|
//#endregion
|
|
5
5
|
export { editor_default as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor2.js","names":[],"sources":["../../src/editor/editor.css"],"sourcesContent":["::selection {\n background-color: transparent;\n}\n\n@keyframes blinking {\n 0% {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n:host, /* for scroll anchor */\n[data-code], /* for editor overlay */\n[data-content] /* for wrap line measurement */ {\n position: relative;\n}\n[data-content] {\n background-color: transparent;\n caret-color: var(--diffs-bg-caret);\n outline: none;\n}\n[data-column-number] {\n color: var(--diffs-editor-line-number-fg);\n}\n[data-column-number]:is([data-selected-line])
|
|
1
|
+
{"version":3,"file":"editor2.js","names":[],"sources":["../../src/editor/editor.css"],"sourcesContent":["::selection {\n background-color: transparent;\n}\n\n@keyframes blinking {\n 0% {\n opacity: 1;\n }\n 50% {\n opacity: 0;\n }\n 100% {\n opacity: 1;\n }\n}\n\n:host, /* for scroll anchor */\n[data-code], /* for editor overlay */\n[data-content] /* for wrap line measurement */ {\n position: relative;\n}\n[data-content] {\n background-color: transparent;\n caret-color: var(--diffs-bg-caret);\n outline: none;\n}\n[data-gutter-buffer],\n[data-line]:not([data-selected-line]),\n[data-line]:not([data-selected-line]) span,\n[data-line-annotation] {\n background-color: transparent;\n}\n[data-column-number] {\n color: var(--diffs-editor-line-number-fg);\n}\n[data-column-number]:is([data-selected-line]) {\n background-color: var(--diffs-editor-line-number-active-bg);\n color: var(--diffs-editor-line-number-active-fg);\n}\n[data-column-number]:is([data-active]) {\n color: var(--diffs-editor-line-number-active-fg);\n}\n[data-line] {\n cursor: text;\n}\n[data-line]:is([data-selected-line]) {\n background-color: var(--diffs-editor-line-highlight-bg);\n}\n[data-line]:is([data-line-type='change-deletion']) {\n background-color: var(--diffs-line-bg);\n}\n\n/* Editor Overlay */\n[data-editor-overlay] {\n display: contents;\n}\n[data-caret],\n[data-selection-range],\n[data-match-range],\n[data-marker-range] {\n position: absolute;\n top: 0;\n left: 0;\n height: 1lh;\n line-height: var(--diffs-line-height);\n pointer-events: none;\n}\n[data-caret] {\n width: 2px;\n background-color: var(\n --diffs-bg-caret-override,\n var(\n --diffs-editor-cursor-fg,\n light-dark(\n color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg)),\n color-mix(in lab, var(--diffs-fg) 75%, var(--diffs-bg))\n )\n )\n );\n animation: blinking 1.2s infinite;\n animation-delay: 0.8s;\n visibility: hidden;\n}\n[data-selection-range] {\n z-index: -10;\n background-color: var(--diffs-editor-selection-bg);\n}\n[data-selection-corner] {\n width: 100%;\n height: 100%;\n background-color: var(--diffs-bg);\n}\n[data-match-range] {\n z-index: -10;\n background-color: var(\n --diffs-editor-match-bg,\n var(--diffs-editor-selection-bg)\n );\n}\n[data-match-range]:not([data-focus]) {\n background-color: var(\n --diffs-editor-match-highlight-bg,\n light-dark(#ff963288, #ff963266)\n );\n}\n[data-marker-range] {\n z-index: 1;\n /* White stroke: luminance masks treat black as transparent. */\n -webkit-mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2IiBoZWlnaHQ9IjMiPjxwYXRoIGQ9Im0wIDIuNSBsMiAtMS41IGwxIDAgbDIgMS41IGwxIDAiIHN0cm9rZT0iI2ZmZiIgZmlsbD0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PC9zdmc+');\n mask-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2IiBoZWlnaHQ9IjMiPjxwYXRoIGQ9Im0wIDIuNSBsMiAtMS41IGwxIDAgbDIgMS41IGwxIDAiIHN0cm9rZT0iI2ZmZiIgZmlsbD0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIi8+PC9zdmc+');\n -webkit-mask-position: left bottom;\n mask-position: left bottom;\n -webkit-mask-repeat: repeat-x;\n mask-repeat: repeat-x;\n -webkit-mask-size: 6px 3px;\n mask-size: 6px 3px;\n}\n[data-marker-error] {\n background-color: var(--diffs-editor-error-fg, red);\n}\n[data-marker-warning] {\n background-color: var(--diffs-editor-warning-fg, #cca700);\n}\n[data-marker-info] {\n background-color: var(--diffs-editor-info-fg, #3794ff);\n}\n[data-marker-hint] {\n background-color: var(--diffs-editor-hint-fg, #6a6a6a);\n}\n[data-rtl] {\n border-top-left-radius: 3px;\n}\n[data-rtr] {\n border-top-right-radius: 3px;\n}\n[data-rbl] {\n border-bottom-left-radius: 3px;\n}\n[data-rbr] {\n border-bottom-right-radius: 3px;\n}\n\n@media (width >= 480px) {\n [data-content] {\n caret-color: transparent;\n }\n [data-selection-action] {\n caret-color: currentColor;\n }\n [data-content]:focus ~ [data-editor-overlay] [data-caret] {\n visibility: visible;\n }\n}\n[data-editor-widget] {\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:\n inset 0 0 0 1px var(--diffs-bg), 0 4px 8px rgb(0 0 0 / 0.075),\n 0 6px 18px rgb(0 0 0 / 0.075);\n position: absolute;\n top: 0;\n left: 0;\n z-index: 100;\n width: fit-content;\n max-width: calc(100% - 24px);\n border: 1px solid var(--diffs-widget-border);\n border-radius: 9px;\n background-color: var(--diffs-widget-bg);\n background-clip: padding-box;\n box-shadow: var(--diffs-widget-shadow);\n}\n[data-marker-popup] {\n padding: 8px 12px;\n min-width: 180px;\n pointer-events: auto;\n font-family: var(--diffs-header-font-fallback);\n font-size: 14px;\n line-height: 1.4;\n}\n[data-marker-popup] code {\n display: inline;\n background-color: transparent;\n}\n\n/* Selection Action Widget */\n[data-selection-action-icon] {\n position: absolute;\n top: 0;\n left: -1lh;\n z-index: 10;\n width: 1lh;\n height: 1lh;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: color-mix(in lab, var(--diffs-fg) 40%, var(--diffs-bg));\n transition:\n background-color 0.1s ease-in-out,\n color 0.1s ease-in-out;\n cursor: pointer;\n visibility: hidden;\n}\n[data-selection-action-icon][data-visible='true'] {\n visibility: visible;\n}\n[data-selection-action-icon]:hover {\n background-color: color-mix(in lab, var(--diffs-fg) 8%, var(--diffs-bg));\n color: var(--diffs-fg);\n}\n[data-selection-action] {\n padding-inline-end: 1ch;\n}\n\n/* Search Panel Widget */\n[data-search-panel] {\n display: flex;\n gap: 6px;\n position: sticky;\n top: 12px;\n min-width: 300px;\n margin-inline: auto 12px;\n margin-bottom: 4px;\n padding: 4px;\n}\n[data-search-panel-row] {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 1px;\n width: 100%;\n font-family: var(--diffs-header-font-fallback);\n font-size: 14px;\n}\n[data-search-panel-row] input {\n font-size: 14px;\n line-height: 24px;\n width: 120px;\n padding-inline: 4px;\n border: none;\n outline: none;\n background-color: transparent;\n color: var(--diffs-fg);\n}\n[data-search-panel-row] input::selection {\n background-color: color-mix(in lab, var(--diffs-fg) 8%, var(--diffs-bg));\n}\n[data-search-panel-row] [data-matches] {\n min-width: 10ch;\n margin-right: auto;\n font-size: 12px;\n font-weight: 500;\n line-height: 20px;\n padding-inline: 4px;\n color: color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg));\n}\n[data-search-panel-row] [data-matches][data-no-matches] {\n color: color-mix(in lab, var(--diffs-deletion-base) 90%, var(--diffs-bg));\n}\n[data-search-panel-row] svg {\n display: block;\n fill: currentColor;\n}\n[data-search-panel-row] [data-icon] {\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n display: flex;\n color: color-mix(in lab, var(--diffs-fg) 65%, var(--diffs-bg));\n align-items: center;\n justify-content: center;\n border-radius: 4px;\n cursor: pointer;\n transition:\n background-color 0.1s ease-in-out,\n color 0.1s ease-in-out;\n}\n[data-search-panel-row] [data-icon='search'] {\n color: color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg));\n cursor: default;\n}\n[data-search-panel-row] [data-icon][data-disabled='true'] {\n opacity: 0.25;\n pointer-events: none;\n}\n[data-search-panel-row] [data-icon]:not([data-icon='search']):hover {\n background-color: color-mix(in lab, var(--diffs-fg) 6%, var(--diffs-bg));\n color: var(--diffs-fg);\n}\n[data-search-panel-row] [data-icon][data-active='true'] {\n background-color: color-mix(in lab, var(--diffs-fg) 10%, var(--diffs-bg));\n color: var(--diffs-fg);\n}\n[data-search-panel-row] [data-divider] {\n flex-shrink: 0;\n align-self: center;\n width: 1px;\n height: 16px;\n margin-inline: 8px;\n background-color: color-mix(in lab, var(--diffs-fg) 10%, var(--diffs-bg));\n}\n"],"mappings":";qBAAA"}
|
|
@@ -3,6 +3,7 @@ import { TextDocumentChange } from "./textDocument.js";
|
|
|
3
3
|
|
|
4
4
|
//#region src/editor/lineAnnotations.d.ts
|
|
5
5
|
declare function applyDocumentChangeToLineAnnotations<T>(change: TextDocumentChange, lineAnnotations: DiffLineAnnotation<T>[]): DiffLineAnnotation<T>[] | undefined;
|
|
6
|
+
declare function renderLineAnnotations<LAnnotation>(lineAnnotations: DiffLineAnnotation<LAnnotation>[], contentEl: HTMLElement, gutterEl?: HTMLElement): void;
|
|
6
7
|
//#endregion
|
|
7
|
-
export { applyDocumentChangeToLineAnnotations };
|
|
8
|
+
export { applyDocumentChangeToLineAnnotations, renderLineAnnotations };
|
|
8
9
|
//# sourceMappingURL=lineAnnotations.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lineAnnotations.d.ts","names":["DiffLineAnnotation","TextDocumentChange","applyDocumentChangeToLineAnnotations","T"],"sources":["../../src/editor/lineAnnotations.d.ts"],"sourcesContent":["import type { DiffLineAnnotation } from '../types';\nimport type { TextDocumentChange } from './textDocument';\nexport declare function applyDocumentChangeToLineAnnotations<T>(change: TextDocumentChange, lineAnnotations: DiffLineAnnotation<T>[]): DiffLineAnnotation<T>[] | undefined;\n//# sourceMappingURL=lineAnnotations.d.ts.map"],"mappings":";;;;iBAEwBE,gDAAgDD,qCAAqCD,mBAAmBG,OAAOH,mBAAmBG"}
|
|
1
|
+
{"version":3,"file":"lineAnnotations.d.ts","names":["DiffLineAnnotation","TextDocumentChange","applyDocumentChangeToLineAnnotations","T","renderLineAnnotations","LAnnotation","HTMLElement"],"sources":["../../src/editor/lineAnnotations.d.ts"],"sourcesContent":["import type { DiffLineAnnotation } from '../types';\nimport type { TextDocumentChange } from './textDocument';\nexport declare function applyDocumentChangeToLineAnnotations<T>(change: TextDocumentChange, lineAnnotations: DiffLineAnnotation<T>[]): DiffLineAnnotation<T>[] | undefined;\nexport declare function renderLineAnnotations<LAnnotation>(lineAnnotations: DiffLineAnnotation<LAnnotation>[], contentEl: HTMLElement, gutterEl?: HTMLElement): void;\n//# sourceMappingURL=lineAnnotations.d.ts.map"],"mappings":";;;;iBAEwBE,gDAAgDD,qCAAqCD,mBAAmBG,OAAOH,mBAAmBG;iBAClIC,oDAAoDJ,mBAAmBK,2BAA2BC,wBAAwBA"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { getLineAnnotationName } from "../utils/getLineAnnotationName.js";
|
|
2
|
+
import { getLineNumberAttr, h } from "./utils.js";
|
|
3
|
+
|
|
1
4
|
//#region src/editor/lineAnnotations.ts
|
|
2
5
|
function applyDocumentChangeToLineAnnotations(change, lineAnnotations) {
|
|
3
6
|
if (change.lineDelta === 0) return;
|
|
@@ -9,6 +12,10 @@ function applyDocumentChangeToLineAnnotations(change, lineAnnotations) {
|
|
|
9
12
|
const nextLineAnnotations = [];
|
|
10
13
|
let changed = false;
|
|
11
14
|
for (const annotation of lineAnnotations) {
|
|
15
|
+
if (annotation.side === "deletions") {
|
|
16
|
+
nextLineAnnotations.push(annotation);
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
12
19
|
const line = annotation.lineNumber - 1;
|
|
13
20
|
if (deletedStartLine !== void 0 && deletedEndLine !== void 0 && line >= deletedStartLine && line < deletedEndLine) {
|
|
14
21
|
changed = true;
|
|
@@ -26,7 +33,110 @@ function applyDocumentChangeToLineAnnotations(change, lineAnnotations) {
|
|
|
26
33
|
}
|
|
27
34
|
return changed ? nextLineAnnotations : void 0;
|
|
28
35
|
}
|
|
36
|
+
function renderLineAnnotations(lineAnnotations, contentEl, gutterEl) {
|
|
37
|
+
const additionAnnotations = /* @__PURE__ */ new Map();
|
|
38
|
+
const deletionAnnotations = /* @__PURE__ */ new Map();
|
|
39
|
+
for (const annotation of lineAnnotations) {
|
|
40
|
+
const lineNumber = annotation.lineNumber;
|
|
41
|
+
if (!additionAnnotations.has(lineNumber)) additionAnnotations.set(lineNumber, []);
|
|
42
|
+
if (!deletionAnnotations.has(lineNumber)) deletionAnnotations.set(lineNumber, []);
|
|
43
|
+
(annotation.side === "deletions" ? deletionAnnotations : additionAnnotations).get(lineNumber).push(getLineAnnotationName(annotation));
|
|
44
|
+
}
|
|
45
|
+
let leftCodeElement = contentEl.parentElement?.previousElementSibling;
|
|
46
|
+
let leftGutterElement;
|
|
47
|
+
let leftContentElement;
|
|
48
|
+
if (leftCodeElement != null && leftCodeElement instanceof HTMLElement && leftCodeElement.dataset.deletions !== void 0) for (const child of leftCodeElement.children) {
|
|
49
|
+
const el = child;
|
|
50
|
+
const { gutter, content } = el.dataset;
|
|
51
|
+
if (gutter !== void 0) leftGutterElement = el;
|
|
52
|
+
else if (content !== void 0) leftContentElement = el;
|
|
53
|
+
}
|
|
54
|
+
cleanLineAnnotationElements(contentEl, gutterEl);
|
|
55
|
+
if (leftContentElement !== void 0) cleanLineAnnotationElements(leftContentElement, leftGutterElement);
|
|
56
|
+
const additionsAnnotationElements = createLineAnnotationElements(additionAnnotations, contentEl, gutterEl);
|
|
57
|
+
if (leftContentElement === void 0) return;
|
|
58
|
+
const deletionsAnnotationElements = createLineAnnotationElements(deletionAnnotations, leftContentElement, leftGutterElement);
|
|
59
|
+
requestAnimationFrame(() => {
|
|
60
|
+
syncPairedLineAnnotationHeights(additionAnnotations, deletionAnnotations, additionsAnnotationElements, deletionsAnnotationElements);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
function cleanLineAnnotationElements(contentEl, gutterEl) {
|
|
64
|
+
const staleElements = [];
|
|
65
|
+
for (let i = 1; i < contentEl.childElementCount; i++) {
|
|
66
|
+
const el = contentEl.children[i];
|
|
67
|
+
if (el.dataset.lineAnnotation !== void 0) {
|
|
68
|
+
staleElements.push(el);
|
|
69
|
+
if (gutterEl !== void 0) staleElements.push(gutterEl.children[i]);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
for (const el of staleElements) el.remove();
|
|
73
|
+
}
|
|
74
|
+
function createLineAnnotationElements(lineAnnotations, contentEl, gutterEl) {
|
|
75
|
+
const annotationElements = /* @__PURE__ */ new Map();
|
|
76
|
+
for (const el of contentEl.children) {
|
|
77
|
+
const lineNumber = getLineNumberAttr(el);
|
|
78
|
+
if (lineNumber !== void 0) {
|
|
79
|
+
const annotations = lineAnnotations.get(lineNumber);
|
|
80
|
+
if (annotations !== void 0) {
|
|
81
|
+
const annotationElement = h("div", {
|
|
82
|
+
dataset: { lineAnnotation: "0," + (lineNumber - 1) },
|
|
83
|
+
children: [h("div", {
|
|
84
|
+
dataset: "annotationContent",
|
|
85
|
+
children: annotations.map((name) => h("slot", { name }))
|
|
86
|
+
})]
|
|
87
|
+
});
|
|
88
|
+
el.after(annotationElement);
|
|
89
|
+
annotationElements.set(lineNumber, annotationElement);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (gutterEl !== void 0) for (const el of gutterEl.children) {
|
|
94
|
+
const lineNumber = getLineNumberAttr(el, "columnNumber");
|
|
95
|
+
if (lineNumber !== void 0 && lineAnnotations.has(lineNumber)) {
|
|
96
|
+
const bufferEl = h("div", {
|
|
97
|
+
dataset: {
|
|
98
|
+
gutterBuffer: "annotation",
|
|
99
|
+
bufferSize: "1"
|
|
100
|
+
},
|
|
101
|
+
style: { gridRow: "span 1" }
|
|
102
|
+
});
|
|
103
|
+
el.after(bufferEl);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return annotationElements;
|
|
107
|
+
}
|
|
108
|
+
function syncPairedLineAnnotationHeights(additionAnnotations, deletionAnnotations, additionAnnotationElements, deletionAnnotationElements) {
|
|
109
|
+
const offsetHeights = /* @__PURE__ */ new Map();
|
|
110
|
+
for (const [lineNumber, annotations] of additionAnnotations.entries()) {
|
|
111
|
+
const annotationElement = deletionAnnotationElements.get(lineNumber);
|
|
112
|
+
if (annotations.length === 0 && annotationElement !== void 0) {
|
|
113
|
+
const height = measureAnnotationContentHeight(annotationElement);
|
|
114
|
+
if (height > 0) offsetHeights.set(lineNumber, height);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
for (const [lineNumber, annotations] of deletionAnnotations.entries()) {
|
|
118
|
+
const annotationElement = additionAnnotationElements.get(lineNumber);
|
|
119
|
+
if (annotations.length === 0 && annotationElement !== void 0) {
|
|
120
|
+
const height = measureAnnotationContentHeight(annotationElement);
|
|
121
|
+
if (height > 0) offsetHeights.set(lineNumber, height);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
applyLineAnnotationMinHeights(additionAnnotations, additionAnnotationElements, offsetHeights);
|
|
125
|
+
applyLineAnnotationMinHeights(deletionAnnotations, deletionAnnotationElements, offsetHeights);
|
|
126
|
+
}
|
|
127
|
+
function measureAnnotationContentHeight(lineAnnotationEl) {
|
|
128
|
+
const content = lineAnnotationEl.firstElementChild;
|
|
129
|
+
if (!(content instanceof HTMLElement)) return 0;
|
|
130
|
+
return content.getBoundingClientRect().height;
|
|
131
|
+
}
|
|
132
|
+
function applyLineAnnotationMinHeights(lineAnnotations, annotationElements, offsetHeights) {
|
|
133
|
+
for (const [lineNumber, annotationElement] of annotationElements.entries()) {
|
|
134
|
+
const annotations = lineAnnotations.get(lineNumber);
|
|
135
|
+
const offsetHeight = offsetHeights.get(lineNumber);
|
|
136
|
+
if (annotations?.length === 0 && offsetHeight !== void 0) annotationElement.style.setProperty("--diffs-annotation-min-height", `${offsetHeight}px`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
29
139
|
|
|
30
140
|
//#endregion
|
|
31
|
-
export { applyDocumentChangeToLineAnnotations };
|
|
141
|
+
export { applyDocumentChangeToLineAnnotations, renderLineAnnotations };
|
|
32
142
|
//# sourceMappingURL=lineAnnotations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lineAnnotations.js","names":["nextLineAnnotations: DiffLineAnnotation<T>[]"],"sources":["../../src/editor/lineAnnotations.ts"],"sourcesContent":["import type { DiffLineAnnotation } from '../types';\nimport type { TextDocumentChange } from './textDocument';\n\nexport function applyDocumentChangeToLineAnnotations<T>(\n change: TextDocumentChange,\n lineAnnotations: DiffLineAnnotation<T>[]\n): DiffLineAnnotation<T>[] | undefined {\n if (change.lineDelta === 0) {\n return undefined;\n }\n\n const startCharacter = change.startCharacter;\n const removedLineCount = Math.max(0, -change.lineDelta);\n const deletedStartLine =\n removedLineCount === 0\n ? undefined\n : change.startLine + (startCharacter === 0 ? 0 : 1);\n const deletedEndLine =\n deletedStartLine === undefined\n ? undefined\n : deletedStartLine + removedLineCount;\n const shiftFromLine =\n removedLineCount > 0\n ? change.startLine + removedLineCount\n : change.startLine + (startCharacter === 0 ? 0 : 1);\n const nextLineAnnotations: DiffLineAnnotation<T>[] = [];\n\n let changed = false;\n for (const annotation of lineAnnotations) {\n const line = annotation.lineNumber - 1;\n if (\n deletedStartLine !== undefined &&\n deletedEndLine !== undefined &&\n line >= deletedStartLine &&\n line < deletedEndLine\n ) {\n changed = true;\n continue;\n }\n\n if (line >= shiftFromLine) {\n nextLineAnnotations.push({\n ...annotation,\n lineNumber: line + change.lineDelta + 1,\n });\n changed = true;\n continue;\n }\n\n nextLineAnnotations.push(annotation);\n }\n\n return changed ? nextLineAnnotations : undefined;\n}\n"],"mappings":";AAGA,SAAgB,qCACd,QACA,iBACqC;AACrC,KAAI,OAAO,cAAc,EACvB;CAGF,MAAM,iBAAiB,OAAO;CAC9B,MAAM,mBAAmB,KAAK,IAAI,GAAG,CAAC,OAAO,UAAU;CACvD,MAAM,mBACJ,qBAAqB,IACjB,SACA,OAAO,aAAa,mBAAmB,IAAI,IAAI;CACrD,MAAM,iBACJ,qBAAqB,SACjB,SACA,mBAAmB;CACzB,MAAM,gBACJ,mBAAmB,IACf,OAAO,YAAY,mBACnB,OAAO,aAAa,mBAAmB,IAAI,IAAI;CACrD,MAAMA,sBAA+C,EAAE;CAEvD,IAAI,UAAU;AACd,MAAK,MAAM,cAAc,iBAAiB;EACxC,MAAM,OAAO,WAAW,aAAa;AACrC,MACE,qBAAqB,UACrB,mBAAmB,UACnB,QAAQ,oBACR,OAAO,gBACP;AACA,aAAU;AACV;;AAGF,MAAI,QAAQ,eAAe;AACzB,uBAAoB,KAAK;IACvB,GAAG;IACH,YAAY,OAAO,OAAO,YAAY;IACvC,CAAC;AACF,aAAU;AACV;;AAGF,sBAAoB,KAAK,WAAW;;AAGtC,QAAO,UAAU,sBAAsB"}
|
|
1
|
+
{"version":3,"file":"lineAnnotations.js","names":["nextLineAnnotations: DiffLineAnnotation<T>[]","leftGutterElement: HTMLElement | undefined","leftContentElement: HTMLElement | undefined","staleElements: HTMLElement[]"],"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\nexport function applyDocumentChangeToLineAnnotations<T>(\n change: TextDocumentChange,\n lineAnnotations: DiffLineAnnotation<T>[]\n): DiffLineAnnotation<T>[] | undefined {\n if (change.lineDelta === 0) {\n return undefined;\n }\n\n const startCharacter = change.startCharacter;\n const removedLineCount = Math.max(0, -change.lineDelta);\n const deletedStartLine =\n removedLineCount === 0\n ? undefined\n : change.startLine + (startCharacter === 0 ? 0 : 1);\n const deletedEndLine =\n deletedStartLine === undefined\n ? undefined\n : deletedStartLine + removedLineCount;\n const shiftFromLine =\n removedLineCount > 0\n ? change.startLine + removedLineCount\n : change.startLine + (startCharacter === 0 ? 0 : 1);\n const nextLineAnnotations: DiffLineAnnotation<T>[] = [];\n\n let changed = false;\n for (const annotation of lineAnnotations) {\n if (annotation.side === 'deletions') {\n nextLineAnnotations.push(annotation);\n continue;\n }\n\n const line = annotation.lineNumber - 1;\n if (\n deletedStartLine !== undefined &&\n deletedEndLine !== undefined &&\n line >= deletedStartLine &&\n line < deletedEndLine\n ) {\n changed = true;\n continue;\n }\n\n if (line >= shiftFromLine) {\n nextLineAnnotations.push({\n ...annotation,\n lineNumber: line + change.lineDelta + 1,\n });\n changed = true;\n continue;\n }\n\n nextLineAnnotations.push(annotation);\n }\n\n return changed ? nextLineAnnotations : undefined;\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 let leftCodeElement = contentEl.parentElement?.previousElementSibling;\n let leftGutterElement: HTMLElement | undefined;\n let leftContentElement: HTMLElement | undefined;\n if (\n leftCodeElement != null &&\n leftCodeElement instanceof HTMLElement &&\n leftCodeElement.dataset.deletions !== undefined\n ) {\n for (const child of leftCodeElement.children) {\n const el = child as HTMLElement;\n const { gutter, content } = el.dataset;\n if (gutter !== undefined) {\n leftGutterElement = el;\n } else if (content !== undefined) {\n leftContentElement = el;\n }\n }\n }\n\n cleanLineAnnotationElements(contentEl, gutterEl);\n if (leftContentElement !== undefined) {\n cleanLineAnnotationElements(leftContentElement, leftGutterElement);\n }\n\n const additionsAnnotationElements = createLineAnnotationElements(\n additionAnnotations,\n contentEl,\n gutterEl\n );\n if (leftContentElement === undefined) {\n return;\n }\n\n const deletionsAnnotationElements = createLineAnnotationElements(\n deletionAnnotations,\n leftContentElement,\n leftGutterElement\n );\n\n requestAnimationFrame(() => {\n syncPairedLineAnnotationHeights(\n additionAnnotations,\n deletionAnnotations,\n additionsAnnotationElements,\n deletionsAnnotationElements\n );\n });\n}\n\nfunction cleanLineAnnotationElements(\n contentEl: HTMLElement,\n gutterEl?: HTMLElement\n): void {\n const staleElements: HTMLElement[] = [];\n for (let i = 1; i < contentEl.childElementCount; i++) {\n const el = contentEl.children[i] as HTMLElement;\n if (el.dataset.lineAnnotation !== undefined) {\n staleElements.push(el);\n if (gutterEl !== undefined) {\n staleElements.push(gutterEl.children[i] as HTMLElement);\n }\n }\n }\n for (const el of staleElements) {\n el.remove();\n }\n}\n\nfunction createLineAnnotationElements(\n lineAnnotations: Map<number, string[]>,\n contentEl: HTMLElement,\n gutterEl?: HTMLElement\n): Map<number, HTMLElement> {\n const annotationElements = new Map<number, HTMLElement>();\n for (const el of contentEl.children) {\n const lineNumber = getLineNumberAttr(el as HTMLElement);\n if (lineNumber !== undefined) {\n const annotations = lineAnnotations.get(lineNumber);\n if (annotations !== undefined) {\n const lineIndex = lineNumber - 1;\n const annotationElement = h('div', {\n dataset: {\n lineAnnotation: '0,' + lineIndex,\n },\n children: [\n h('div', {\n dataset: 'annotationContent',\n children: annotations.map((name) => h('slot', { name })),\n }),\n ],\n });\n el.after(annotationElement);\n annotationElements.set(lineNumber, annotationElement);\n }\n }\n }\n\n if (gutterEl !== undefined) {\n for (const el of gutterEl.children) {\n const lineNumber = getLineNumberAttr(el as HTMLElement, 'columnNumber');\n if (lineNumber !== undefined && lineAnnotations.has(lineNumber)) {\n const bufferEl = h('div', {\n dataset: {\n gutterBuffer: 'annotation',\n bufferSize: '1',\n },\n style: {\n gridRow: 'span 1',\n },\n });\n el.after(bufferEl);\n }\n }\n }\n\n return annotationElements;\n}\n\nfunction syncPairedLineAnnotationHeights(\n additionAnnotations: Map<number, string[]>,\n deletionAnnotations: Map<number, string[]>,\n additionAnnotationElements: Map<number, HTMLElement>,\n deletionAnnotationElements: Map<number, HTMLElement>\n): void {\n const offsetHeights = new Map<number, number>();\n for (const [lineNumber, annotations] of additionAnnotations.entries()) {\n const annotationElement = deletionAnnotationElements.get(lineNumber);\n if (annotations.length === 0 && annotationElement !== undefined) {\n const height = measureAnnotationContentHeight(annotationElement);\n if (height > 0) {\n offsetHeights.set(lineNumber, height);\n }\n }\n }\n for (const [lineNumber, annotations] of deletionAnnotations.entries()) {\n const annotationElement = additionAnnotationElements.get(lineNumber);\n if (annotations.length === 0 && annotationElement !== undefined) {\n const height = measureAnnotationContentHeight(annotationElement);\n if (height > 0) {\n offsetHeights.set(lineNumber, height);\n }\n }\n }\n applyLineAnnotationMinHeights(\n additionAnnotations,\n additionAnnotationElements,\n offsetHeights\n );\n applyLineAnnotationMinHeights(\n deletionAnnotations,\n deletionAnnotationElements,\n offsetHeights\n );\n}\n\nfunction measureAnnotationContentHeight(lineAnnotationEl: HTMLElement): number {\n const content = lineAnnotationEl.firstElementChild;\n if (!(content instanceof HTMLElement)) {\n return 0;\n }\n return content.getBoundingClientRect().height;\n}\n\nfunction applyLineAnnotationMinHeights(\n lineAnnotations: Map<number, string[]>,\n annotationElements: Map<number, HTMLElement>,\n offsetHeights: Map<number, number>\n): void {\n for (const [lineNumber, annotationElement] of annotationElements.entries()) {\n const annotations = lineAnnotations.get(lineNumber);\n const offsetHeight = offsetHeights.get(lineNumber);\n if (annotations?.length === 0 && offsetHeight !== undefined) {\n annotationElement.style.setProperty(\n '--diffs-annotation-min-height',\n `${offsetHeight}px`\n );\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Range, TextDocument } from "./textDocument.js";
|
|
2
|
+
|
|
3
|
+
//#region src/editor/marker.d.ts
|
|
4
|
+
type MarkerSeverity = 'error' | 'warning' | 'info' | 'hint';
|
|
5
|
+
interface Marker extends Range {
|
|
6
|
+
severity: MarkerSeverity;
|
|
7
|
+
message: string | {
|
|
8
|
+
html: string;
|
|
9
|
+
} | HTMLElement;
|
|
10
|
+
source?: string;
|
|
11
|
+
metadata?: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
interface EditorStub {
|
|
14
|
+
getLineHeight: () => number;
|
|
15
|
+
getFileContainer: () => HTMLElement | undefined;
|
|
16
|
+
getCharX: (line: number, character: number) => [number, number];
|
|
17
|
+
getLineY: (line: number) => number;
|
|
18
|
+
isMouseDown: () => boolean;
|
|
19
|
+
}
|
|
20
|
+
declare class MarkerManager {
|
|
21
|
+
#private;
|
|
22
|
+
constructor(editor: EditorStub);
|
|
23
|
+
get markers(): readonly Marker[];
|
|
24
|
+
isPopupVisible(): boolean;
|
|
25
|
+
setMarkers<LAnnotation>(markers: Marker[], textDocument: TextDocument<LAnnotation>): void;
|
|
26
|
+
listenHover(contentEl: HTMLElement): void;
|
|
27
|
+
removePopup(): void;
|
|
28
|
+
cleanup(): void;
|
|
29
|
+
}
|
|
30
|
+
declare function markerSeverityDatasetKey(severity: MarkerSeverity): string;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { EditorStub, Marker, MarkerManager, MarkerSeverity, markerSeverityDatasetKey };
|
|
33
|
+
//# sourceMappingURL=marker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marker.d.ts","names":["Range","TextDocument","MarkerSeverity","Marker","HTMLElement","Record","EditorStub","MarkerManager","LAnnotation","markerSeverityDatasetKey"],"sources":["../../src/editor/marker.d.ts"],"sourcesContent":["import type { Range, TextDocument } from './textDocument';\nexport type MarkerSeverity = 'error' | 'warning' | 'info' | 'hint';\nexport interface Marker extends Range {\n severity: MarkerSeverity;\n message: string | {\n html: string;\n } | HTMLElement;\n source?: string;\n metadata?: Record<string, unknown>;\n}\nexport interface EditorStub {\n getLineHeight: () => number;\n getFileContainer: () => HTMLElement | undefined;\n getCharX: (line: number, character: number) => [number, number];\n getLineY: (line: number) => number;\n isMouseDown: () => boolean;\n}\nexport declare class MarkerManager {\n #private;\n constructor(editor: EditorStub);\n get markers(): readonly Marker[];\n isPopupVisible(): boolean;\n setMarkers<LAnnotation>(markers: Marker[], textDocument: TextDocument<LAnnotation>): void;\n listenHover(contentEl: HTMLElement): void;\n removePopup(): void;\n cleanup(): void;\n}\nexport declare function markerSeverityDatasetKey(severity: MarkerSeverity): string;\n//# sourceMappingURL=marker.d.ts.map"],"mappings":";;;KACYE,cAAAA;UACKC,MAAAA,SAAeH;EADpBE,QAAAA,EAEEA,cAFY;EACTC,OAAAA,EAAM,MAAA,GAAA;IACTD,IAAAA,EAAAA,MAAAA;EAGNE,CAAAA,GAAAA,WAAAA;EAEOC,MAAAA,CAAAA,EAAAA,MAAAA;EANiBL,QAAAA,CAAAA,EAMjBK,MANiBL,CAAAA,MAAAA,EAAAA,OAAAA,CAAAA;;AAQfM,UAAAA,UAAAA,CAAU;EAONC,aAAAA,EAAAA,GAAa,GAAA,MAAAC;EAEVF,gBAAAA,EAAAA,GAAAA,GAPIF,WAOJE,GAAAA,SAAAA;EACIH,QAAAA,EAAAA,CAAAA,IAAAA,EAAAA,MAAAA,EAAAA,SAAAA,EAAAA,MAAAA,EAAAA,GAAAA,CAAAA,MAAAA,EAAAA,MAAAA,CAAAA;EAESA,QAAAA,EAAAA,CAAAA,IAAAA,EAAAA,MAAAA,EAAAA,GAAAA,MAAAA;EAAqCK,WAAAA,EAAAA,GAAAA,GAAAA,OAAAA;;AAC/CJ,cANNG,aAAAA,CAMMH;EAAW,CAAA,OAAA;EAIdK,WAAAA,CAAAA,MAAAA,EARAH,UAQwB;0BAPpBH;;mCAESA,wBAAwBF,aAAaO;yBAC/CJ;;;;iBAIHK,wBAAAA,WAAmCP"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { addEventListener, getLineNumberAttr, h } from "./utils.js";
|
|
2
|
+
import { selectionIntersects } from "./selection.js";
|
|
3
|
+
|
|
4
|
+
//#region src/editor/marker.ts
|
|
5
|
+
const MARKER_POPUP_SHOW_DELAY_MS = 300;
|
|
6
|
+
const MARKER_POPUP_HIDE_DELAY_MS = 100;
|
|
7
|
+
var MarkerManager = class {
|
|
8
|
+
#editor;
|
|
9
|
+
#markers = [];
|
|
10
|
+
#markerPopupElement;
|
|
11
|
+
#markerPopupEventDisposes;
|
|
12
|
+
#markerEventDisposes;
|
|
13
|
+
#markerPopupShowTimeout;
|
|
14
|
+
#markerPopupHideTimeout;
|
|
15
|
+
#pendingMarkerPopupIndex;
|
|
16
|
+
#hoveredMarkerIndex;
|
|
17
|
+
#isMarkerPopupHovered = false;
|
|
18
|
+
constructor(editor) {
|
|
19
|
+
this.#editor = editor;
|
|
20
|
+
}
|
|
21
|
+
get markers() {
|
|
22
|
+
return this.#markers;
|
|
23
|
+
}
|
|
24
|
+
isPopupVisible() {
|
|
25
|
+
return this.#hoveredMarkerIndex !== void 0;
|
|
26
|
+
}
|
|
27
|
+
setMarkers(markers, textDocument) {
|
|
28
|
+
this.#markers = markers.map((marker) => ({
|
|
29
|
+
...marker,
|
|
30
|
+
start: textDocument.normalizePosition(marker.start),
|
|
31
|
+
end: textDocument.normalizePosition(marker.end)
|
|
32
|
+
}));
|
|
33
|
+
this.removePopup();
|
|
34
|
+
}
|
|
35
|
+
listenHover(contentEl) {
|
|
36
|
+
this.#markerEventDisposes?.forEach((dispose) => dispose());
|
|
37
|
+
this.#markerEventDisposes = void 0;
|
|
38
|
+
if (this.#markers.length === 0) return;
|
|
39
|
+
this.#markerEventDisposes = [addEventListener(contentEl, "mouseover", (e) => {
|
|
40
|
+
if (this.#editor.isMouseDown()) return;
|
|
41
|
+
const target = e.composedPath()[0];
|
|
42
|
+
if (target === void 0) return;
|
|
43
|
+
const hoverMarkerIndex = this.#findHoveredMarkerIndex(target);
|
|
44
|
+
if (hoverMarkerIndex !== void 0) this.#scheduleMarkerPopup(hoverMarkerIndex);
|
|
45
|
+
else {
|
|
46
|
+
this.#cancelMarkerPopupShow();
|
|
47
|
+
this.#scheduleMarkerPopupHide();
|
|
48
|
+
}
|
|
49
|
+
}), addEventListener(contentEl, "mouseleave", () => {
|
|
50
|
+
this.#cancelMarkerPopupShow();
|
|
51
|
+
this.#scheduleMarkerPopupHide();
|
|
52
|
+
})];
|
|
53
|
+
}
|
|
54
|
+
removePopup() {
|
|
55
|
+
this.#cancelMarkerPopupShow();
|
|
56
|
+
this.#cancelMarkerPopupHide();
|
|
57
|
+
this.#dismissMarkerPopup();
|
|
58
|
+
}
|
|
59
|
+
cleanup() {
|
|
60
|
+
this.#markerEventDisposes?.forEach((dispose) => dispose());
|
|
61
|
+
this.#markerEventDisposes = void 0;
|
|
62
|
+
this.removePopup();
|
|
63
|
+
this.#markers = [];
|
|
64
|
+
}
|
|
65
|
+
#findHoveredMarkerIndex(target) {
|
|
66
|
+
const lineElement = target.closest("[data-line]");
|
|
67
|
+
if (lineElement == null) return;
|
|
68
|
+
const lineNumber = getLineNumberAttr(lineElement);
|
|
69
|
+
if (lineNumber === void 0) return;
|
|
70
|
+
let character;
|
|
71
|
+
if (target.tagName === "SPAN") {
|
|
72
|
+
const char = target.dataset.char;
|
|
73
|
+
if (char === void 0) return;
|
|
74
|
+
character = parseInt(char, 10);
|
|
75
|
+
if (Number.isNaN(character)) return;
|
|
76
|
+
} else if (target.tagName === "BR") character = 0;
|
|
77
|
+
else return;
|
|
78
|
+
const position = {
|
|
79
|
+
line: lineNumber - 1,
|
|
80
|
+
character
|
|
81
|
+
};
|
|
82
|
+
for (let i = this.#markers.length - 1; i >= 0; i--) if (selectionIntersects({
|
|
83
|
+
start: position,
|
|
84
|
+
end: position
|
|
85
|
+
}, this.#markers[i])) return i;
|
|
86
|
+
}
|
|
87
|
+
#cancelMarkerPopupShow() {
|
|
88
|
+
if (this.#markerPopupShowTimeout !== void 0) {
|
|
89
|
+
clearTimeout(this.#markerPopupShowTimeout);
|
|
90
|
+
this.#markerPopupShowTimeout = void 0;
|
|
91
|
+
}
|
|
92
|
+
this.#pendingMarkerPopupIndex = void 0;
|
|
93
|
+
}
|
|
94
|
+
#cancelMarkerPopupHide() {
|
|
95
|
+
if (this.#markerPopupHideTimeout !== void 0) {
|
|
96
|
+
clearTimeout(this.#markerPopupHideTimeout);
|
|
97
|
+
this.#markerPopupHideTimeout = void 0;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
#scheduleMarkerPopup(markerIndex) {
|
|
101
|
+
if (markerIndex === this.#hoveredMarkerIndex || markerIndex === this.#pendingMarkerPopupIndex) {
|
|
102
|
+
this.#cancelMarkerPopupHide();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.#cancelMarkerPopupShow();
|
|
106
|
+
this.#cancelMarkerPopupHide();
|
|
107
|
+
if (this.#markerPopupElement !== void 0) {
|
|
108
|
+
this.#renderMarkerPopup(markerIndex);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
this.#pendingMarkerPopupIndex = markerIndex;
|
|
112
|
+
this.#markerPopupShowTimeout = setTimeout(() => {
|
|
113
|
+
this.#markerPopupShowTimeout = void 0;
|
|
114
|
+
this.#pendingMarkerPopupIndex = void 0;
|
|
115
|
+
this.#renderMarkerPopup(markerIndex);
|
|
116
|
+
}, MARKER_POPUP_SHOW_DELAY_MS);
|
|
117
|
+
}
|
|
118
|
+
#scheduleMarkerPopupHide() {
|
|
119
|
+
if (this.#isMarkerPopupHovered) return;
|
|
120
|
+
this.#cancelMarkerPopupHide();
|
|
121
|
+
this.#markerPopupHideTimeout = setTimeout(() => {
|
|
122
|
+
this.#markerPopupHideTimeout = void 0;
|
|
123
|
+
if (!this.#isMarkerPopupHovered) this.removePopup();
|
|
124
|
+
}, MARKER_POPUP_HIDE_DELAY_MS);
|
|
125
|
+
}
|
|
126
|
+
#dismissMarkerPopup() {
|
|
127
|
+
this.#markerPopupEventDisposes?.forEach((dispose) => dispose());
|
|
128
|
+
this.#markerPopupEventDisposes = void 0;
|
|
129
|
+
this.#markerPopupElement?.remove();
|
|
130
|
+
this.#markerPopupElement = void 0;
|
|
131
|
+
this.#hoveredMarkerIndex = void 0;
|
|
132
|
+
this.#isMarkerPopupHovered = false;
|
|
133
|
+
}
|
|
134
|
+
#renderMarkerPopup(hoveredMarkerIndex) {
|
|
135
|
+
if (hoveredMarkerIndex === this.#hoveredMarkerIndex) return;
|
|
136
|
+
const preElement = this.#editor.getFileContainer()?.shadowRoot?.querySelector("pre");
|
|
137
|
+
const codeElement = preElement?.querySelector("[data-code]");
|
|
138
|
+
if (hoveredMarkerIndex >= this.#markers.length || preElement == null || codeElement == null) return;
|
|
139
|
+
const { start, message } = this.#markers[hoveredMarkerIndex];
|
|
140
|
+
const { line, character } = start;
|
|
141
|
+
const { getCharX, getLineY, getLineHeight } = this.#editor;
|
|
142
|
+
const [left, wrapLine] = getCharX(line, character);
|
|
143
|
+
const lineHeight = getLineHeight();
|
|
144
|
+
const y = getLineY(line) + wrapLine * lineHeight + lineHeight;
|
|
145
|
+
const transform = `translateX(${codeElement.offsetLeft + left}px) translateY(${codeElement.offsetTop + y}px)`;
|
|
146
|
+
const popup = this.#markerPopupElement;
|
|
147
|
+
if (popup !== void 0) {
|
|
148
|
+
popup.style.transform = transform;
|
|
149
|
+
const content = popup.firstElementChild;
|
|
150
|
+
if (content?.dataset.markerMessage !== void 0) if (typeof message === "string") content.textContent = message;
|
|
151
|
+
else if (message instanceof HTMLElement) content.replaceChildren(message);
|
|
152
|
+
else content.innerHTML = message.html;
|
|
153
|
+
this.#hoveredMarkerIndex = hoveredMarkerIndex;
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
this.#markerPopupElement = h("div", {
|
|
157
|
+
dataset: ["editorWidget", "markerPopup"],
|
|
158
|
+
style: { transform },
|
|
159
|
+
children: [h("div", {
|
|
160
|
+
dataset: "markerMessage",
|
|
161
|
+
...typeof message === "string" ? { textContent: message } : message instanceof HTMLElement ? { children: [message] } : { innerHTML: message.html }
|
|
162
|
+
})]
|
|
163
|
+
}, preElement);
|
|
164
|
+
this.#hoveredMarkerIndex = hoveredMarkerIndex;
|
|
165
|
+
this.#markerPopupEventDisposes = [addEventListener(this.#markerPopupElement, "mouseenter", () => {
|
|
166
|
+
this.#isMarkerPopupHovered = true;
|
|
167
|
+
this.#cancelMarkerPopupHide();
|
|
168
|
+
}), addEventListener(this.#markerPopupElement, "mouseleave", () => {
|
|
169
|
+
this.#isMarkerPopupHovered = false;
|
|
170
|
+
this.#scheduleMarkerPopupHide();
|
|
171
|
+
})];
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
function markerSeverityDatasetKey(severity) {
|
|
175
|
+
switch (severity) {
|
|
176
|
+
case "error": return "markerError";
|
|
177
|
+
case "warning": return "markerWarning";
|
|
178
|
+
case "info": return "markerInfo";
|
|
179
|
+
case "hint": return "markerHint";
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
//#endregion
|
|
184
|
+
export { MarkerManager, markerSeverityDatasetKey };
|
|
185
|
+
//# sourceMappingURL=marker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marker.js","names":["#editor","#markers","#hoveredMarkerIndex","#markerEventDisposes","#findHoveredMarkerIndex","#scheduleMarkerPopup","#cancelMarkerPopupShow","#scheduleMarkerPopupHide","#cancelMarkerPopupHide","#dismissMarkerPopup","character: number | undefined","position: Position","#markerPopupShowTimeout","#pendingMarkerPopupIndex","#markerPopupHideTimeout","#markerPopupElement","#renderMarkerPopup","#isMarkerPopupHovered","#markerPopupEventDisposes"],"sources":["../../src/editor/marker.ts"],"sourcesContent":["import { selectionIntersects } from './selection';\nimport type { Position, Range, TextDocument } from './textDocument';\nimport { addEventListener, getLineNumberAttr, h } from './utils';\n\nconst MARKER_POPUP_SHOW_DELAY_MS = 300;\nconst MARKER_POPUP_HIDE_DELAY_MS = 100;\n\nexport type MarkerSeverity = 'error' | 'warning' | 'info' | 'hint';\n\nexport interface Marker extends Range {\n severity: MarkerSeverity;\n message: string | { html: string } | HTMLElement;\n source?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface EditorStub {\n getLineHeight: () => number;\n getFileContainer: () => HTMLElement | undefined;\n getCharX: (line: number, character: number) => [number, number];\n getLineY: (line: number) => number;\n isMouseDown: () => boolean;\n}\n\nexport class MarkerManager {\n #editor: EditorStub;\n #markers: Marker[] = [];\n #markerPopupElement?: HTMLElement;\n #markerPopupEventDisposes?: (() => void)[];\n #markerEventDisposes?: (() => void)[];\n #markerPopupShowTimeout?: ReturnType<typeof setTimeout>;\n #markerPopupHideTimeout?: ReturnType<typeof setTimeout>;\n #pendingMarkerPopupIndex?: number;\n #hoveredMarkerIndex?: number;\n #isMarkerPopupHovered = false;\n\n constructor(editor: EditorStub) {\n this.#editor = editor;\n }\n\n get markers(): readonly Marker[] {\n return this.#markers;\n }\n\n isPopupVisible(): boolean {\n return this.#hoveredMarkerIndex !== undefined;\n }\n\n setMarkers<LAnnotation>(\n markers: Marker[],\n textDocument: TextDocument<LAnnotation>\n ): void {\n this.#markers = markers.map((marker) => ({\n ...marker,\n start: textDocument.normalizePosition(marker.start),\n end: textDocument.normalizePosition(marker.end),\n }));\n this.removePopup();\n }\n\n listenHover(contentEl: HTMLElement): void {\n this.#markerEventDisposes?.forEach((dispose) => dispose());\n this.#markerEventDisposes = undefined;\n if (this.#markers.length === 0) {\n return;\n }\n\n this.#markerEventDisposes = [\n addEventListener(contentEl, 'mouseover', (e) => {\n if (this.#editor.isMouseDown()) {\n return;\n }\n const target = e.composedPath()[0] as HTMLElement | undefined;\n if (target === undefined) {\n return;\n }\n\n const hoverMarkerIndex = this.#findHoveredMarkerIndex(target);\n if (hoverMarkerIndex !== undefined) {\n this.#scheduleMarkerPopup(hoverMarkerIndex);\n } else {\n this.#cancelMarkerPopupShow();\n this.#scheduleMarkerPopupHide();\n }\n }),\n addEventListener(contentEl, 'mouseleave', () => {\n this.#cancelMarkerPopupShow();\n this.#scheduleMarkerPopupHide();\n }),\n ];\n }\n\n removePopup(): void {\n this.#cancelMarkerPopupShow();\n this.#cancelMarkerPopupHide();\n this.#dismissMarkerPopup();\n }\n\n cleanup(): void {\n this.#markerEventDisposes?.forEach((dispose) => dispose());\n this.#markerEventDisposes = undefined;\n this.removePopup();\n this.#markers = [];\n }\n\n #findHoveredMarkerIndex(target: HTMLElement): number | undefined {\n const lineElement = target.closest('[data-line]');\n if (lineElement == null) {\n return;\n }\n\n const lineNumber = getLineNumberAttr(lineElement as HTMLElement);\n if (lineNumber === undefined) {\n return;\n }\n\n let character: number | undefined;\n if (target.tagName === 'SPAN') {\n const char = target.dataset.char;\n if (char === undefined) {\n return;\n }\n character = parseInt(char, 10);\n if (Number.isNaN(character)) {\n return;\n }\n } else if (target.tagName === 'BR') {\n character = 0;\n } else {\n return;\n }\n\n const position: Position = { line: lineNumber - 1, character };\n for (let i = this.#markers.length - 1; i >= 0; i--) {\n if (\n selectionIntersects(\n { start: position, end: position },\n this.#markers[i]\n )\n ) {\n return i;\n }\n }\n return undefined;\n }\n\n #cancelMarkerPopupShow(): void {\n if (this.#markerPopupShowTimeout !== undefined) {\n clearTimeout(this.#markerPopupShowTimeout);\n this.#markerPopupShowTimeout = undefined;\n }\n this.#pendingMarkerPopupIndex = undefined;\n }\n\n #cancelMarkerPopupHide(): void {\n if (this.#markerPopupHideTimeout !== undefined) {\n clearTimeout(this.#markerPopupHideTimeout);\n this.#markerPopupHideTimeout = undefined;\n }\n }\n\n #scheduleMarkerPopup(markerIndex: number): void {\n if (\n markerIndex === this.#hoveredMarkerIndex ||\n markerIndex === this.#pendingMarkerPopupIndex\n ) {\n this.#cancelMarkerPopupHide();\n return;\n }\n\n this.#cancelMarkerPopupShow();\n this.#cancelMarkerPopupHide();\n if (this.#markerPopupElement !== undefined) {\n this.#renderMarkerPopup(markerIndex);\n return;\n }\n\n this.#pendingMarkerPopupIndex = markerIndex;\n this.#markerPopupShowTimeout = setTimeout(() => {\n this.#markerPopupShowTimeout = undefined;\n this.#pendingMarkerPopupIndex = undefined;\n this.#renderMarkerPopup(markerIndex);\n }, MARKER_POPUP_SHOW_DELAY_MS);\n }\n\n #scheduleMarkerPopupHide(): void {\n if (this.#isMarkerPopupHovered) {\n return;\n }\n\n this.#cancelMarkerPopupHide();\n this.#markerPopupHideTimeout = setTimeout(() => {\n this.#markerPopupHideTimeout = undefined;\n if (!this.#isMarkerPopupHovered) {\n this.removePopup();\n }\n }, MARKER_POPUP_HIDE_DELAY_MS);\n }\n\n #dismissMarkerPopup(): void {\n this.#markerPopupEventDisposes?.forEach((dispose) => dispose());\n this.#markerPopupEventDisposes = undefined;\n this.#markerPopupElement?.remove();\n this.#markerPopupElement = undefined;\n this.#hoveredMarkerIndex = undefined;\n this.#isMarkerPopupHovered = false;\n }\n\n #renderMarkerPopup(hoveredMarkerIndex: number): void {\n if (hoveredMarkerIndex === this.#hoveredMarkerIndex) {\n return;\n }\n\n const fileContainer = this.#editor.getFileContainer();\n const preElement =\n fileContainer?.shadowRoot?.querySelector<HTMLElement>('pre');\n const codeElement = preElement?.querySelector<HTMLElement>('[data-code]');\n if (\n hoveredMarkerIndex >= this.#markers.length ||\n preElement == null ||\n codeElement == null\n ) {\n return;\n }\n\n const { start, message } = this.#markers[hoveredMarkerIndex];\n const { line, character } = start;\n const { getCharX, getLineY, getLineHeight } = this.#editor;\n const [left, wrapLine] = getCharX(line, character);\n const lineHeight = getLineHeight();\n const y = getLineY(line) + wrapLine * lineHeight + lineHeight;\n const transform = `translateX(${codeElement.offsetLeft + left}px) translateY(${codeElement.offsetTop + y}px)`;\n const popup = this.#markerPopupElement;\n\n if (popup !== undefined) {\n popup.style.transform = transform;\n const content = popup.firstElementChild as HTMLElement | null;\n if (content?.dataset.markerMessage !== undefined) {\n if (typeof message === 'string') {\n content.textContent = message;\n } else if (message instanceof HTMLElement) {\n content.replaceChildren(message);\n } else {\n content.innerHTML = message.html;\n }\n }\n this.#hoveredMarkerIndex = hoveredMarkerIndex;\n return;\n }\n\n this.#markerPopupElement = h(\n 'div',\n {\n dataset: ['editorWidget', 'markerPopup'],\n style: { transform },\n children: [\n h('div', {\n dataset: 'markerMessage',\n ...(typeof message === 'string'\n ? { textContent: message }\n : message instanceof HTMLElement\n ? { children: [message] }\n : { innerHTML: message.html }),\n }),\n ],\n },\n preElement\n );\n this.#hoveredMarkerIndex = hoveredMarkerIndex;\n this.#markerPopupEventDisposes = [\n addEventListener(this.#markerPopupElement, 'mouseenter', () => {\n this.#isMarkerPopupHovered = true;\n this.#cancelMarkerPopupHide();\n }),\n addEventListener(this.#markerPopupElement, 'mouseleave', () => {\n this.#isMarkerPopupHovered = false;\n this.#scheduleMarkerPopupHide();\n }),\n ];\n }\n}\n\nexport function markerSeverityDatasetKey(severity: MarkerSeverity): string {\n switch (severity) {\n case 'error':\n return 'markerError';\n case 'warning':\n return 'markerWarning';\n case 'info':\n return 'markerInfo';\n case 'hint':\n return 'markerHint';\n }\n}\n"],"mappings":"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"}
|
|
@@ -14,7 +14,8 @@ declare class PieceTable {
|
|
|
14
14
|
constructor(originalText: string);
|
|
15
15
|
get lineCount(): number;
|
|
16
16
|
getText(range?: Range): string;
|
|
17
|
-
getLineText(line: number,
|
|
17
|
+
getLineText(line: number, includeLineBreak?: boolean): string;
|
|
18
|
+
getLineLength(line: number, includeLineBreak?: boolean): number;
|
|
18
19
|
getTextSlice(start: number, end: number, trimEOF?: boolean): string;
|
|
19
20
|
charAt(offset: number): string;
|
|
20
21
|
includes(needle: string): boolean;
|
|
@@ -26,7 +27,6 @@ declare class PieceTable {
|
|
|
26
27
|
positionAt(offset: number): Position;
|
|
27
28
|
positionsAt(offsets: readonly number[]): Position[];
|
|
28
29
|
offsetAt(position: Position): number;
|
|
29
|
-
offsetsAt(positions: readonly Position[]): number[];
|
|
30
30
|
}
|
|
31
31
|
//#endregion
|
|
32
32
|
export { PieceTable };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pieceTable.d.ts","names":["SearchParams","Position","Range","ResolvedTextEdit","PieceTable"],"sources":["../../src/editor/pieceTable.d.ts"],"sourcesContent":["import type { SearchParams } from './searchPanel';\nimport type { Position, Range, ResolvedTextEdit } from './textDocument';\n/**\n * A piece table is a data structure that allows for efficient insertion and deletion of text.\n * It is a tree of pieces, where each piece is a segment of text that is either original or added.\n * The tree is rebuilt as a balanced tree after edits to keep lookups efficient.\n * Inspired by https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation\n */\nexport declare class PieceTable {\n #private;\n constructor(originalText: string);\n get lineCount(): number;\n getText(range?: Range): string;\n getLineText(line: number,
|
|
1
|
+
{"version":3,"file":"pieceTable.d.ts","names":["SearchParams","Position","Range","ResolvedTextEdit","PieceTable"],"sources":["../../src/editor/pieceTable.d.ts"],"sourcesContent":["import type { SearchParams } from './searchPanel';\nimport type { Position, Range, ResolvedTextEdit } from './textDocument';\n/**\n * A piece table is a data structure that allows for efficient insertion and deletion of text.\n * It is a tree of pieces, where each piece is a segment of text that is either original or added.\n * The tree is rebuilt as a balanced tree after edits to keep lookups efficient.\n * Inspired by https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation\n */\nexport declare class PieceTable {\n #private;\n constructor(originalText: string);\n get lineCount(): number;\n getText(range?: Range): string;\n getLineText(line: number, includeLineBreak?: boolean): string;\n getLineLength(line: number, includeLineBreak?: boolean): number;\n getTextSlice(start: number, end: number, trimEOF?: boolean): string;\n charAt(offset: number): string;\n includes(needle: string): boolean;\n findNextNonOverlappingSubstring(needle: string, occupied: readonly [start: number, end: number][]): number | undefined;\n search(searchParams: SearchParams): [start: number, end: number][];\n insert(text: string, offset: number): void;\n delete(offset: number, length: number): void;\n applyEdits(edits: readonly ResolvedTextEdit[]): void;\n positionAt(offset: number): Position;\n positionsAt(offsets: readonly number[]): Position[];\n offsetAt(position: Position): number;\n}\n//# sourceMappingURL=pieceTable.d.ts.map"],"mappings":";;;;;;;AAQA;;;;AAegCC,cAfXG,UAAAA,CAeWH;EACaA,CAAAA,OAAAA;EACtBA,WAAAA,CAAAA,YAAAA,EAAAA,MAAAA;EAAQ,IAAA,SAAA,CAAA,CAAA,EAAA,MAAA;kBAbXC;;;;;;;uBAOKF;;;6BAGMG;8BACCF;2CACaA;qBACtBA"}
|
|
@@ -59,6 +59,7 @@ var PieceTable = class {
|
|
|
59
59
|
#length = 0;
|
|
60
60
|
#lineCount = 0;
|
|
61
61
|
#lastVisitedLine = null;
|
|
62
|
+
#lastVisitedLineLength = null;
|
|
62
63
|
constructor(originalText) {
|
|
63
64
|
this.#original = new TextBuffer(originalText);
|
|
64
65
|
this.#setPieces([this.#createPiece(Piece.Original, 0, originalText.length)]);
|
|
@@ -72,14 +73,48 @@ var PieceTable = class {
|
|
|
72
73
|
const end = this.offsetAt(range.end);
|
|
73
74
|
return this.getTextSlice(start, end);
|
|
74
75
|
}
|
|
75
|
-
getLineText(line,
|
|
76
|
-
if (this.#lastVisitedLine !== null && this.#lastVisitedLine[0] === line) return this.#lastVisitedLine[
|
|
76
|
+
getLineText(line, includeLineBreak = false) {
|
|
77
|
+
if (this.#lastVisitedLine !== null && this.#lastVisitedLine[0] === line && this.#lastVisitedLine[1] === includeLineBreak) return this.#lastVisitedLine[2];
|
|
77
78
|
const offset = this.#getLineOffset(line);
|
|
78
79
|
if (offset === void 0) throw new Error(`Line index out of range: ${line}`);
|
|
79
|
-
const text = this.getTextSlice(offset[0], offset[1],
|
|
80
|
-
this.#lastVisitedLine = [
|
|
80
|
+
const text = this.getTextSlice(offset[0], offset[1], !includeLineBreak);
|
|
81
|
+
this.#lastVisitedLine = [
|
|
82
|
+
line,
|
|
83
|
+
includeLineBreak,
|
|
84
|
+
text
|
|
85
|
+
];
|
|
86
|
+
this.#lastVisitedLineLength = [
|
|
87
|
+
line,
|
|
88
|
+
includeLineBreak,
|
|
89
|
+
text.length
|
|
90
|
+
];
|
|
81
91
|
return text;
|
|
82
92
|
}
|
|
93
|
+
getLineLength(line, includeLineBreak = false) {
|
|
94
|
+
const lastVisitedLineLength = this.#lastVisitedLineLength;
|
|
95
|
+
const lastVisitedLine = this.#lastVisitedLine;
|
|
96
|
+
if (lastVisitedLineLength !== null && lastVisitedLineLength[0] === line && lastVisitedLineLength[1] === includeLineBreak) return lastVisitedLineLength[2];
|
|
97
|
+
if (lastVisitedLine !== null && lastVisitedLine[0] === line && lastVisitedLine[1] === includeLineBreak) {
|
|
98
|
+
const length$1 = lastVisitedLine[2].length;
|
|
99
|
+
this.#lastVisitedLineLength = [
|
|
100
|
+
line,
|
|
101
|
+
includeLineBreak,
|
|
102
|
+
length$1
|
|
103
|
+
];
|
|
104
|
+
return length$1;
|
|
105
|
+
}
|
|
106
|
+
const offset = this.#getLineOffset(line);
|
|
107
|
+
if (offset === void 0) throw new Error(`Line index out of range: ${line}`);
|
|
108
|
+
const [start, end] = offset;
|
|
109
|
+
let length = end - start;
|
|
110
|
+
if (!includeLineBreak) while (length > 0 && isEOL(this.charAt(start + length - 1).charCodeAt(0))) length--;
|
|
111
|
+
this.#lastVisitedLineLength = [
|
|
112
|
+
line,
|
|
113
|
+
includeLineBreak,
|
|
114
|
+
length
|
|
115
|
+
];
|
|
116
|
+
return length;
|
|
117
|
+
}
|
|
83
118
|
getTextSlice(start, end, trimEOF = false) {
|
|
84
119
|
if (start >= end) return "";
|
|
85
120
|
const sliceStart = clamp(start, 0, this.#length);
|
|
@@ -223,6 +258,7 @@ var PieceTable = class {
|
|
|
223
258
|
if (!inserted) nextPieces.push(insertedPiece);
|
|
224
259
|
this.#setPieces(nextPieces);
|
|
225
260
|
this.#lastVisitedLine = null;
|
|
261
|
+
this.#lastVisitedLineLength = null;
|
|
226
262
|
}
|
|
227
263
|
delete(offset, length) {
|
|
228
264
|
if (length <= 0 || this.#length === 0) return;
|
|
@@ -242,6 +278,7 @@ var PieceTable = class {
|
|
|
242
278
|
}
|
|
243
279
|
this.#setPieces(nextPieces);
|
|
244
280
|
this.#lastVisitedLine = null;
|
|
281
|
+
this.#lastVisitedLineLength = null;
|
|
245
282
|
}
|
|
246
283
|
applyEdits(edits) {
|
|
247
284
|
if (edits.length === 0) return;
|
|
@@ -285,6 +322,7 @@ var PieceTable = class {
|
|
|
285
322
|
appendRange(copyCursor, this.#length);
|
|
286
323
|
this.#setPieces(nextPieces);
|
|
287
324
|
this.#lastVisitedLine = null;
|
|
325
|
+
this.#lastVisitedLineLength = null;
|
|
288
326
|
}
|
|
289
327
|
positionAt(offset) {
|
|
290
328
|
const clampedOffset = clamp(offset, 0, this.#length);
|
|
@@ -316,13 +354,6 @@ var PieceTable = class {
|
|
|
316
354
|
const character = clamp(position.character, 0, offset[1] - offset[0]);
|
|
317
355
|
return offset[0] + character;
|
|
318
356
|
}
|
|
319
|
-
offsetsAt(positions) {
|
|
320
|
-
const offsets = Array.from({ length: positions.length });
|
|
321
|
-
if (positions.length === 0) return offsets;
|
|
322
|
-
if (this.#length === 0) return offsets.fill(0);
|
|
323
|
-
for (let i = 0; i < positions.length; i++) offsets[i] = this.offsetAt(positions[i]);
|
|
324
|
-
return offsets;
|
|
325
|
-
}
|
|
326
357
|
#findPieceAtOffset(offset) {
|
|
327
358
|
if (offset < 0 || offset >= this.#length) return;
|
|
328
359
|
let node = this.#root;
|