@pierre/diffs 1.3.0-beta.4 → 1.3.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +6 -6
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +6 -6
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +1 -0
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +26 -12
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +1 -0
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +12 -11
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.js +4 -2
  14. package/dist/components/FileStream.js.map +1 -1
  15. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  16. package/dist/components/VirtualizedFile.d.ts +5 -1
  17. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  18. package/dist/components/VirtualizedFile.js +82 -21
  19. package/dist/components/VirtualizedFile.js.map +1 -1
  20. package/dist/components/VirtualizedFileDiff.d.ts +6 -1
  21. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  22. package/dist/components/VirtualizedFileDiff.js +77 -15
  23. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  24. package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
  25. package/dist/editor/command.d.ts +1 -1
  26. package/dist/editor/command.d.ts.map +1 -1
  27. package/dist/editor/command.js +3 -3
  28. package/dist/editor/command.js.map +1 -1
  29. package/dist/editor/editor.d.ts +31 -5
  30. package/dist/editor/editor.d.ts.map +1 -1
  31. package/dist/editor/editor.js +240 -178
  32. package/dist/editor/editor.js.map +1 -1
  33. package/dist/editor/editor2.js +1 -1
  34. package/dist/editor/editor2.js.map +1 -1
  35. package/dist/editor/index.d.ts +2 -2
  36. package/dist/editor/marker.d.ts +2 -2
  37. package/dist/editor/marker.d.ts.map +1 -1
  38. package/dist/editor/marker.js +2 -2
  39. package/dist/editor/marker.js.map +1 -1
  40. package/dist/editor/pieceTable.d.ts +6 -1
  41. package/dist/editor/pieceTable.d.ts.map +1 -1
  42. package/dist/editor/pieceTable.js +32 -1
  43. package/dist/editor/pieceTable.js.map +1 -1
  44. package/dist/editor/searchPanel.d.ts +12 -3
  45. package/dist/editor/searchPanel.d.ts.map +1 -1
  46. package/dist/editor/searchPanel.js +168 -54
  47. package/dist/editor/searchPanel.js.map +1 -1
  48. package/dist/editor/selection.d.ts.map +1 -1
  49. package/dist/editor/sprite.d.ts +2 -2
  50. package/dist/editor/sprite.d.ts.map +1 -1
  51. package/dist/editor/sprite.js +10 -3
  52. package/dist/editor/sprite.js.map +1 -1
  53. package/dist/editor/textMeasure.d.ts +1 -0
  54. package/dist/editor/textMeasure.d.ts.map +1 -1
  55. package/dist/editor/textMeasure.js +6 -0
  56. package/dist/editor/textMeasure.js.map +1 -1
  57. package/dist/editor/tokenzier.js +9 -6
  58. package/dist/editor/tokenzier.js.map +1 -1
  59. package/dist/managers/InteractionManager.js +1 -1
  60. package/dist/managers/InteractionManager.js.map +1 -1
  61. package/dist/managers/ResizeManager.js +1 -1
  62. package/dist/managers/ResizeManager.js.map +1 -1
  63. package/dist/react/CodeView.js +1 -1
  64. package/dist/react/jsx.d.ts.map +1 -1
  65. package/dist/renderers/DiffHunksRenderer.d.ts +3 -2
  66. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  67. package/dist/renderers/DiffHunksRenderer.js +49 -2
  68. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  69. package/dist/renderers/FileRenderer.js +12 -0
  70. package/dist/renderers/FileRenderer.js.map +1 -1
  71. package/dist/ssr/FileDiffReact.js +1 -1
  72. package/dist/types.d.ts +17 -2
  73. package/dist/types.d.ts.map +1 -1
  74. package/dist/utils/includesFileAnnotations.d.ts +17 -0
  75. package/dist/utils/includesFileAnnotations.d.ts.map +1 -0
  76. package/dist/utils/includesFileAnnotations.js +19 -0
  77. package/dist/utils/includesFileAnnotations.js.map +1 -0
  78. package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
  79. package/dist/utils/renderDiffWithHighlighter.js +4 -2
  80. package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
  81. package/dist/utils/renderFileWithHighlighter.js +4 -2
  82. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  83. package/dist/worker/{wasm-BaDzIkIn.js → wasm-qE0LgnY3.js} +2 -2
  84. package/dist/worker/{wasm-BaDzIkIn.js.map → wasm-qE0LgnY3.js.map} +1 -1
  85. package/dist/worker/worker-portable.js +289 -253
  86. package/dist/worker/worker-portable.js.map +1 -1
  87. package/dist/worker/worker.js +8 -4
  88. package/dist/worker/worker.js.map +1 -1
  89. package/package.json +4 -10
@@ -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-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}";
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]{z-index:100;flex-direction:column;justify-content:right;width:100%;height:fit-content;margin-bottom:4px;display:flex;position:sticky;top:12px;right:12px}[data-search-panel] [data-editor-widget]{z-index:100;max-width:100%;font-family:var(--diffs-header-font-fallback);align-items:flex-start;gap:8px;margin-inline:auto 12px;padding:4px;font-size:14px;display:flex;position:relative}[data-search-grid]{grid-template-columns:auto auto auto;align-items:center;gap:4px 6px;display:grid}[data-search-grid][data-mode=find] [data-replace-cell]{display:none}[data-input-box]{align-items:center;width:200px;display:flex;position:relative}[data-input-box] input{width:100%;min-width:0;color:var(--diffs-fg);background-color:var(--diffs-bg);border:1px solid color-mix(in lab, var(--diffs-fg) 12%, var(--diffs-bg));border-radius:6px;outline:none;flex-grow:1;padding-inline:6px;font-size:13px;line-height:24px}[data-input-box][data-find] input{padding-inline-end:72px}[data-input-box] input::selection{background-color:color-mix(in lab, var(--diffs-fg) 8%, var(--diffs-bg))}[data-search-toggles]{align-items:center;gap:1px;display:flex;position:absolute;top:50%;right:4px;transform:translateY(-50%)}[data-matches]{white-space:nowrap;min-width:50px;color:color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg));flex-shrink:0;font-size:12px;font-weight:500;line-height:20px}[data-matches][data-no-matches]{color:color-mix(in lab, var(--diffs-fg) 35%, var(--diffs-bg))}[data-replace-actions],[data-search-nav]{align-items:center;display:flex}[data-search-panel] svg{fill:currentColor;display:block}[data-search-panel] [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] [data-icon][data-disabled=true]{opacity:.25;pointer-events:none}[data-search-panel] [data-icon]:hover{color:var(--diffs-fg)}[data-search-panel] [data-icon][data-active=true]{color:light-dark(var(--diffs-modified-light),var(--diffs-modified-dark))}";
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-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"}
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 position: sticky;\n top: 12px;\n right: 12px;\n z-index: 100;\n display: flex;\n justify-content: right;\n flex-direction: column;\n width: 100%;\n height: fit-content;\n margin-bottom: 4px;\n}\n[data-search-panel] [data-editor-widget] {\n position: relative;\n z-index: 100;\n display: flex;\n align-items: flex-start;\n gap: 8px;\n padding: 4px;\n max-width: 100%;\n margin-inline: auto 12px;\n font-family: var(--diffs-header-font-fallback);\n font-size: 14px;\n}\n/* The two input rows form a grid: column 1 holds the find/replace inputs,\n column 2 holds the results text / replace actions, and column 3 holds the\n find navigation buttons on the first row only. DOM order auto-places items. */\n[data-search-grid] {\n display: grid;\n grid-template-columns: auto auto auto;\n align-items: center;\n gap: 4px 6px;\n}\n[data-search-grid][data-mode='find'] [data-replace-cell] {\n display: none;\n}\n[data-input-box] {\n position: relative;\n display: flex;\n align-items: center;\n width: 200px;\n}\n[data-input-box] input {\n flex-grow: 1;\n width: 100%;\n min-width: 0;\n font-size: 13px;\n line-height: 24px;\n padding-inline: 6px;\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}\n/* Reserve room on the right of the find input for the overlaid toggles. */\n[data-input-box][data-find] input {\n padding-inline-end: 72px;\n}\n[data-input-box] input::selection {\n background-color: color-mix(in lab, var(--diffs-fg) 8%, var(--diffs-bg));\n}\n[data-search-toggles] {\n position: absolute;\n top: 50%;\n right: 4px;\n transform: translateY(-50%);\n display: flex;\n align-items: center;\n gap: 1px;\n}\n[data-matches] {\n flex-shrink: 0;\n min-width: 50px;\n font-size: 12px;\n font-weight: 500;\n line-height: 20px;\n white-space: nowrap;\n color: color-mix(in lab, var(--diffs-fg) 50%, var(--diffs-bg));\n}\n[data-matches][data-no-matches] {\n color: color-mix(in lab, var(--diffs-fg) 35%, var(--diffs-bg));\n}\n[data-replace-actions],\n[data-search-nav] {\n display: flex;\n align-items: center;\n}\n[data-search-panel] svg {\n display: block;\n fill: currentColor;\n}\n[data-search-panel] [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] [data-icon][data-disabled='true'] {\n opacity: 0.25;\n pointer-events: none;\n}\n[data-search-panel] [data-icon]:hover {\n color: var(--diffs-fg);\n}\n[data-search-panel] [data-icon][data-active='true'] {\n color: light-dark(var(--diffs-modified-light), var(--diffs-modified-dark));\n}\n"],"mappings":";qBAAA"}
@@ -1,3 +1,3 @@
1
1
  import { Position, Range, ResolvedTextEdit, TextDocument, TextDocumentChange, TextEdit } from "./textDocument.js";
2
- import { Editor, EditorOptions } from "./editor.js";
3
- export { Editor, EditorOptions, Position, Range, ResolvedTextEdit, TextDocument, TextDocumentChange, TextEdit };
2
+ import { Editor, EditorOptions, EditorState } from "./editor.js";
3
+ export { Editor, EditorOptions, EditorState, Position, Range, ResolvedTextEdit, TextDocument, TextDocumentChange, TextEdit };
@@ -17,7 +17,7 @@ interface EditorStub {
17
17
  getLineY: (line: number) => number;
18
18
  isMouseDown: () => boolean;
19
19
  }
20
- declare class MarkerManager {
20
+ declare class MarkerRenderer {
21
21
  #private;
22
22
  constructor(editor: EditorStub);
23
23
  get markers(): readonly Marker[];
@@ -29,5 +29,5 @@ declare class MarkerManager {
29
29
  }
30
30
  declare function markerSeverityDatasetKey(severity: MarkerSeverity): string;
31
31
  //#endregion
32
- export { EditorStub, Marker, MarkerManager, MarkerSeverity, markerSeverityDatasetKey };
32
+ export { EditorStub, Marker, MarkerRenderer, MarkerSeverity, markerSeverityDatasetKey };
33
33
  //# sourceMappingURL=marker.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"marker.d.ts","names":["Range","TextDocument","MarkerSeverity","Marker","HTMLElement","Record","EditorStub","MarkerRenderer","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 MarkerRenderer {\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,GAAc,GAAA,MAAAC;EAEXF,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,cAAAA,CAMMH;EAAW,CAAA,OAAA;EAIdK,WAAAA,CAAAA,MAAAA,EARAH,UAQwB;0BAPpBH;;mCAESA,wBAAwBF,aAAaO;yBAC/CJ;;;;iBAIHK,wBAAAA,WAAmCP"}
@@ -4,7 +4,7 @@ import { selectionIntersects } from "./selection.js";
4
4
  //#region src/editor/marker.ts
5
5
  const MARKER_POPUP_SHOW_DELAY_MS = 300;
6
6
  const MARKER_POPUP_HIDE_DELAY_MS = 100;
7
- var MarkerManager = class {
7
+ var MarkerRenderer = class {
8
8
  #editor;
9
9
  #markers = [];
10
10
  #markerPopupElement;
@@ -181,5 +181,5 @@ function markerSeverityDatasetKey(severity) {
181
181
  }
182
182
 
183
183
  //#endregion
184
- export { MarkerManager, markerSeverityDatasetKey };
184
+ export { MarkerRenderer, markerSeverityDatasetKey };
185
185
  //# sourceMappingURL=marker.js.map
@@ -1 +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":";;;;AAIA,MAAM,6BAA6B;AACnC,MAAM,6BAA6B;AAmBnC,IAAa,gBAAb,MAA2B;CACzB;CACA,WAAqB,EAAE;CACvB;CACA;CACA;CACA;CACA;CACA;CACA;CACA,wBAAwB;CAExB,YAAY,QAAoB;AAC9B,QAAKA,SAAU;;CAGjB,IAAI,UAA6B;AAC/B,SAAO,MAAKC;;CAGd,iBAA0B;AACxB,SAAO,MAAKC,uBAAwB;;CAGtC,WACE,SACA,cACM;AACN,QAAKD,UAAW,QAAQ,KAAK,YAAY;GACvC,GAAG;GACH,OAAO,aAAa,kBAAkB,OAAO,MAAM;GACnD,KAAK,aAAa,kBAAkB,OAAO,IAAI;GAChD,EAAE;AACH,OAAK,aAAa;;CAGpB,YAAY,WAA8B;AACxC,QAAKE,qBAAsB,SAAS,YAAY,SAAS,CAAC;AAC1D,QAAKA,sBAAuB;AAC5B,MAAI,MAAKF,QAAS,WAAW,EAC3B;AAGF,QAAKE,sBAAuB,CAC1B,iBAAiB,WAAW,cAAc,MAAM;AAC9C,OAAI,MAAKH,OAAQ,aAAa,CAC5B;GAEF,MAAM,SAAS,EAAE,cAAc,CAAC;AAChC,OAAI,WAAW,OACb;GAGF,MAAM,mBAAmB,MAAKI,uBAAwB,OAAO;AAC7D,OAAI,qBAAqB,OACvB,OAAKC,oBAAqB,iBAAiB;QACtC;AACL,UAAKC,uBAAwB;AAC7B,UAAKC,yBAA0B;;IAEjC,EACF,iBAAiB,WAAW,oBAAoB;AAC9C,SAAKD,uBAAwB;AAC7B,SAAKC,yBAA0B;IAC/B,CACH;;CAGH,cAAoB;AAClB,QAAKD,uBAAwB;AAC7B,QAAKE,uBAAwB;AAC7B,QAAKC,oBAAqB;;CAG5B,UAAgB;AACd,QAAKN,qBAAsB,SAAS,YAAY,SAAS,CAAC;AAC1D,QAAKA,sBAAuB;AAC5B,OAAK,aAAa;AAClB,QAAKF,UAAW,EAAE;;CAGpB,wBAAwB,QAAyC;EAC/D,MAAM,cAAc,OAAO,QAAQ,cAAc;AACjD,MAAI,eAAe,KACjB;EAGF,MAAM,aAAa,kBAAkB,YAA2B;AAChE,MAAI,eAAe,OACjB;EAGF,IAAIS;AACJ,MAAI,OAAO,YAAY,QAAQ;GAC7B,MAAM,OAAO,OAAO,QAAQ;AAC5B,OAAI,SAAS,OACX;AAEF,eAAY,SAAS,MAAM,GAAG;AAC9B,OAAI,OAAO,MAAM,UAAU,CACzB;aAEO,OAAO,YAAY,KAC5B,aAAY;MAEZ;EAGF,MAAMC,WAAqB;GAAE,MAAM,aAAa;GAAG;GAAW;AAC9D,OAAK,IAAI,IAAI,MAAKV,QAAS,SAAS,GAAG,KAAK,GAAG,IAC7C,KACE,oBACE;GAAE,OAAO;GAAU,KAAK;GAAU,EAClC,MAAKA,QAAS,GACf,CAED,QAAO;;CAMb,yBAA+B;AAC7B,MAAI,MAAKW,2BAA4B,QAAW;AAC9C,gBAAa,MAAKA,uBAAwB;AAC1C,SAAKA,yBAA0B;;AAEjC,QAAKC,0BAA2B;;CAGlC,yBAA+B;AAC7B,MAAI,MAAKC,2BAA4B,QAAW;AAC9C,gBAAa,MAAKA,uBAAwB;AAC1C,SAAKA,yBAA0B;;;CAInC,qBAAqB,aAA2B;AAC9C,MACE,gBAAgB,MAAKZ,sBACrB,gBAAgB,MAAKW,yBACrB;AACA,SAAKL,uBAAwB;AAC7B;;AAGF,QAAKF,uBAAwB;AAC7B,QAAKE,uBAAwB;AAC7B,MAAI,MAAKO,uBAAwB,QAAW;AAC1C,SAAKC,kBAAmB,YAAY;AACpC;;AAGF,QAAKH,0BAA2B;AAChC,QAAKD,yBAA0B,iBAAiB;AAC9C,SAAKA,yBAA0B;AAC/B,SAAKC,0BAA2B;AAChC,SAAKG,kBAAmB,YAAY;KACnC,2BAA2B;;CAGhC,2BAAiC;AAC/B,MAAI,MAAKC,qBACP;AAGF,QAAKT,uBAAwB;AAC7B,QAAKM,yBAA0B,iBAAiB;AAC9C,SAAKA,yBAA0B;AAC/B,OAAI,CAAC,MAAKG,qBACR,MAAK,aAAa;KAEnB,2BAA2B;;CAGhC,sBAA4B;AAC1B,QAAKC,0BAA2B,SAAS,YAAY,SAAS,CAAC;AAC/D,QAAKA,2BAA4B;AACjC,QAAKH,oBAAqB,QAAQ;AAClC,QAAKA,qBAAsB;AAC3B,QAAKb,qBAAsB;AAC3B,QAAKe,uBAAwB;;CAG/B,mBAAmB,oBAAkC;AACnD,MAAI,uBAAuB,MAAKf,mBAC9B;EAIF,MAAM,aADgB,MAAKF,OAAQ,kBAAkB,EAEpC,YAAY,cAA2B,MAAM;EAC9D,MAAM,cAAc,YAAY,cAA2B,cAAc;AACzE,MACE,sBAAsB,MAAKC,QAAS,UACpC,cAAc,QACd,eAAe,KAEf;EAGF,MAAM,EAAE,OAAO,YAAY,MAAKA,QAAS;EACzC,MAAM,EAAE,MAAM,cAAc;EAC5B,MAAM,EAAE,UAAU,UAAU,kBAAkB,MAAKD;EACnD,MAAM,CAAC,MAAM,YAAY,SAAS,MAAM,UAAU;EAClD,MAAM,aAAa,eAAe;EAClC,MAAM,IAAI,SAAS,KAAK,GAAG,WAAW,aAAa;EACnD,MAAM,YAAY,cAAc,YAAY,aAAa,KAAK,iBAAiB,YAAY,YAAY,EAAE;EACzG,MAAM,QAAQ,MAAKe;AAEnB,MAAI,UAAU,QAAW;AACvB,SAAM,MAAM,YAAY;GACxB,MAAM,UAAU,MAAM;AACtB,OAAI,SAAS,QAAQ,kBAAkB,OACrC,KAAI,OAAO,YAAY,SACrB,SAAQ,cAAc;YACb,mBAAmB,YAC5B,SAAQ,gBAAgB,QAAQ;OAEhC,SAAQ,YAAY,QAAQ;AAGhC,SAAKb,qBAAsB;AAC3B;;AAGF,QAAKa,qBAAsB,EACzB,OACA;GACE,SAAS,CAAC,gBAAgB,cAAc;GACxC,OAAO,EAAE,WAAW;GACpB,UAAU,CACR,EAAE,OAAO;IACP,SAAS;IACT,GAAI,OAAO,YAAY,WACnB,EAAE,aAAa,SAAS,GACxB,mBAAmB,cACjB,EAAE,UAAU,CAAC,QAAQ,EAAE,GACvB,EAAE,WAAW,QAAQ,MAAM;IAClC,CAAC,CACH;GACF,EACD,WACD;AACD,QAAKb,qBAAsB;AAC3B,QAAKgB,2BAA4B,CAC/B,iBAAiB,MAAKH,oBAAqB,oBAAoB;AAC7D,SAAKE,uBAAwB;AAC7B,SAAKT,uBAAwB;IAC7B,EACF,iBAAiB,MAAKO,oBAAqB,oBAAoB;AAC7D,SAAKE,uBAAwB;AAC7B,SAAKV,yBAA0B;IAC/B,CACH;;;AAIL,SAAgB,yBAAyB,UAAkC;AACzE,SAAQ,UAAR;EACE,KAAK,QACH,QAAO;EACT,KAAK,UACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,OACH,QAAO"}
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 MarkerRenderer {\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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"}
@@ -28,6 +28,11 @@ declare class PieceTable {
28
28
  positionsAt(offsets: readonly number[]): Position[];
29
29
  offsetAt(position: Position): number;
30
30
  }
31
+ /**
32
+ * Builds the text to insert for one search match, including regex capture
33
+ * substitution when regex mode is enabled.
34
+ */
35
+ declare function buildSearchReplacementText(positionAt: (offset: number) => Position, offsetAt: (position: Position) => number, getLineText: (line: number) => string, searchParams: SearchParams, matchStart: number, matchEnd: number): string;
31
36
  //#endregion
32
- export { PieceTable };
37
+ export { PieceTable, buildSearchReplacementText };
33
38
  //# sourceMappingURL=pieceTable.d.ts.map
@@ -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, 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"}
1
+ {"version":3,"file":"pieceTable.d.ts","names":["SearchParams","Position","Range","ResolvedTextEdit","PieceTable","buildSearchReplacementText"],"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/**\n * Builds the text to insert for one search match, including regex capture\n * substitution when regex mode is enabled.\n */\nexport declare function buildSearchReplacementText(positionAt: (offset: number) => Position, offsetAt: (position: Position) => number, getLineText: (line: number) => string, searchParams: SearchParams, matchStart: number, matchEnd: number): string;\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;EAMPI,OAAAA,CAAAA,KAAAA,CAAAA,EAnBJH,KAmBIG,CAAAA,EAAAA,MAA0B;EAAiCJ,WAAAA,CAAAA,IAAAA,EAAAA,MAAAA,EAAAA,gBAAAA,CAAAA,EAAAA,OAAAA,CAAAA,EAAAA,MAAAA;EAA+BA,aAAAA,CAAAA,IAAAA,EAAAA,MAAAA,EAAAA,gBAAAA,CAAAA,EAAAA,OAAAA,CAAAA,EAAAA,MAAAA;EAA0ED,YAAAA,CAAAA,KAAAA,EAAAA,MAAAA,EAAAA,GAAAA,EAAAA,MAAAA,EAAAA,OAAAA,CAAAA,EAAAA,OAAAA,CAAAA,EAAAA,MAAAA;EAAY,MAAA,CAAA,MAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;uBAZ/KA;;;6BAGMG;8BACCF;2CACaA;qBACtBA;;;;;;iBAMCI,0BAAAA,iCAA2DJ,+BAA+BA,0EAA0ED"}
@@ -587,6 +587,37 @@ function compileSearchRegExp(source, isRegex, caseSensitive) {
587
587
  const flags = `g${caseSensitive ? "" : "i"}${isRegex ? "m" : ""}`;
588
588
  return new RegExp(body, flags);
589
589
  }
590
+ /** Expands `$&`, `$1`, `$$`, etc. in a regex replace string using a match. */
591
+ function expandReplaceString(replacement, match) {
592
+ return replacement.replace(/\$([$&]|\d+)/g, (_token, group) => {
593
+ if (group === "$") return "$";
594
+ if (group === "&") return match[0] ?? "";
595
+ return match[Number(group)] ?? "";
596
+ });
597
+ }
598
+ /**
599
+ * Builds the text to insert for one search match, including regex capture
600
+ * substitution when regex mode is enabled.
601
+ */
602
+ function buildSearchReplacementText(positionAt, offsetAt, getLineText, searchParams, matchStart, matchEnd) {
603
+ if (!searchParams.regex) return searchParams.replaceText;
604
+ const position = positionAt(matchStart);
605
+ const lineText = getLineText(position.line);
606
+ const relStart = matchStart - offsetAt({
607
+ line: position.line,
608
+ character: 0
609
+ });
610
+ const matched = lineText.slice(relStart, relStart + (matchEnd - matchStart));
611
+ let pattern;
612
+ try {
613
+ pattern = compileSearchRegExp(searchParams.text, true, searchParams.caseSensitive);
614
+ } catch {
615
+ return searchParams.replaceText;
616
+ }
617
+ const match = new RegExp(pattern.source, pattern.flags.replace("g", "")).exec(matched);
618
+ if (match === null || match[0].length !== matched.length) return searchParams.replaceText;
619
+ return expandReplaceString(searchParams.replaceText, match);
620
+ }
590
621
  function advancePastEmptyMatch(text, index) {
591
622
  if (index + 1 < text.length) {
592
623
  const first = text.charCodeAt(index);
@@ -597,5 +628,5 @@ function advancePastEmptyMatch(text, index) {
597
628
  }
598
629
 
599
630
  //#endregion
600
- export { PieceTable };
631
+ export { PieceTable, buildSearchReplacementText };
601
632
  //# sourceMappingURL=pieceTable.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"pieceTable.js","names":["source: number","offset: number","length: number","lineOffsetStart: number","lineOffsetEnd: number","text: string","piece: Piece","subtreeLength: number","subtreeLineBreakCount: number","#original","#setPieces","#createPiece","#lineCount","#textFromPieces","#lastVisitedLine","#getLineOffset","#lastVisitedLineLength","length","#length","#findPieceAtOffset","chunks: string[]","#bufferFor","start","end","#nextNode","#forEachPieceSegment","wrappedOffset: number | undefined","foundOffset: number | undefined","pattern: RegExp","#collectSearchMatchesLineByLine","out: [number, number][]","match: RegExpExecArray | null","#add","#pieces","nextPieces: Piece[]","#lineAtOffset","#lineBreakOffset","positions: Position[]","#root","#walk","#piecesCache","#buildBalancedTree","normalized: [start: number, end: number][]","merged: [start: number, end: number][]","coalescedPieces: Piece[]"],"sources":["../../src/editor/pieceTable.ts"],"sourcesContent":["import { computeLineOffsets } from '../utils/computeFileOffsets';\nimport type { SearchParams } from './searchPanel';\nimport type { Position, Range, ResolvedTextEdit } from './textDocument';\n\nconst MAX_FIND_MATCHES = 100000;\n// TODO(ije): use Intl.Segmenter instead of regex for word separators\nconst WORD_SEPARATORS = '`~!@#$%^&*()-=+[{]}\\\\|;:\\'\",.<>/?' as const;\n\n// A piece is a segment of text that is either original or added.\nclass Piece {\n static Original = 0;\n static Added = 1;\n\n constructor(\n public readonly source: number,\n public readonly offset: number,\n public readonly length: number,\n public readonly lineOffsetStart: number,\n public readonly lineOffsetEnd: number\n ) {}\n\n get lineBreakCount(): number {\n return this.lineOffsetEnd - this.lineOffsetStart;\n }\n}\n\n// A text buffer is a string with its line offsets.\nclass TextBuffer {\n lineOffsets: number[];\n\n constructor(public text: string) {\n this.lineOffsets = computeLineOffsets(text);\n }\n\n // the append operation is efficient because it only appends\n // elements to the lineOffsets array in the end\n append(text: string): number {\n const offset = this.text.length;\n const appendedLineOffsets = computeLineOffsets(text);\n for (let i = 1; i < appendedLineOffsets.length; i++) {\n this.lineOffsets.push(offset + appendedLineOffsets[i]);\n }\n this.text += text;\n return offset;\n }\n}\n\n// A node in the balanced piece tree.\nclass PieceNode {\n left: PieceNode | null = null;\n right: PieceNode | null = null;\n parent: PieceNode | null = null;\n\n constructor(\n public piece: Piece,\n public subtreeLength: number = piece.length,\n public subtreeLineBreakCount: number = piece.lineBreakCount\n ) {}\n\n updateSubtreeLength(): void {\n this.subtreeLength =\n (this.left?.subtreeLength ?? 0) +\n this.piece.length +\n (this.right?.subtreeLength ?? 0);\n this.subtreeLineBreakCount =\n (this.left?.subtreeLineBreakCount ?? 0) +\n this.piece.lineBreakCount +\n (this.right?.subtreeLineBreakCount ?? 0);\n }\n}\n\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 class PieceTable {\n #original: TextBuffer;\n #add = new TextBuffer('');\n #root: PieceNode | null = null;\n #piecesCache: Piece[] = [];\n #length = 0;\n #lineCount = 0;\n #lastVisitedLine: [number, boolean, string] | null = null;\n #lastVisitedLineLength: [number, boolean, number] | null = null;\n\n constructor(originalText: string) {\n this.#original = new TextBuffer(originalText);\n this.#setPieces([\n this.#createPiece(Piece.Original, 0, originalText.length),\n ]);\n }\n\n get lineCount(): number {\n return this.#lineCount;\n }\n\n getText(range?: Range): string {\n if (range === undefined) {\n return this.#textFromPieces();\n }\n const start = this.offsetAt(range.start);\n const end = this.offsetAt(range.end);\n return this.getTextSlice(start, end);\n }\n\n getLineText(line: number, includeLineBreak = false): string {\n if (\n this.#lastVisitedLine !== null &&\n this.#lastVisitedLine[0] === line &&\n this.#lastVisitedLine[1] === includeLineBreak\n ) {\n return this.#lastVisitedLine[2];\n }\n const offset = this.#getLineOffset(line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${line}`);\n }\n const text = this.getTextSlice(offset[0], offset[1], !includeLineBreak);\n this.#lastVisitedLine = [line, includeLineBreak, text];\n this.#lastVisitedLineLength = [line, includeLineBreak, text.length];\n return text;\n }\n\n getLineLength(line: number, includeLineBreak = false): number {\n const lastVisitedLineLength = this.#lastVisitedLineLength;\n const lastVisitedLine = this.#lastVisitedLine;\n if (\n lastVisitedLineLength !== null &&\n lastVisitedLineLength[0] === line &&\n lastVisitedLineLength[1] === includeLineBreak\n ) {\n return lastVisitedLineLength[2];\n }\n if (\n lastVisitedLine !== null &&\n lastVisitedLine[0] === line &&\n lastVisitedLine[1] === includeLineBreak\n ) {\n const length = lastVisitedLine[2].length;\n this.#lastVisitedLineLength = [line, includeLineBreak, length];\n return length;\n }\n const offset = this.#getLineOffset(line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${line}`);\n }\n const [start, end] = offset;\n let length = end - start;\n if (!includeLineBreak) {\n while (\n length > 0 &&\n isEOL(this.charAt(start + length - 1).charCodeAt(0))\n ) {\n length--;\n }\n }\n this.#lastVisitedLineLength = [line, includeLineBreak, length];\n return length;\n }\n\n getTextSlice(start: number, end: number, trimEOF = false): string {\n if (start >= end) {\n return '';\n }\n\n const sliceStart = clamp(start, 0, this.#length);\n const sliceEnd = clamp(end, sliceStart, this.#length);\n if (sliceStart >= sliceEnd) {\n return '';\n }\n\n const location = this.#findPieceAtOffset(sliceStart);\n if (location === undefined) {\n return '';\n }\n\n const chunks: string[] = [];\n let [node, offsetInPiece] = location as [PieceNode | null, number];\n let remaining = sliceEnd - sliceStart;\n while (node !== null && remaining > 0) {\n const takeLength = Math.min(node.piece.length - offsetInPiece, remaining);\n const buffer = this.#bufferFor(node.piece.source);\n const start = node.piece.offset + offsetInPiece;\n let end = start + takeLength;\n if (trimEOF) {\n while (end > start && isEOL(buffer.text.charCodeAt(end - 1))) {\n end--;\n }\n }\n chunks.push(buffer.text.slice(start, end));\n remaining -= takeLength;\n offsetInPiece = 0;\n node = this.#nextNode(node);\n }\n\n return chunks.join('');\n }\n\n charAt(offset: number): string {\n const location = this.#findPieceAtOffset(offset);\n if (location === undefined) {\n return '';\n }\n\n const [node, offsetInPiece] = location;\n const buffer = this.#bufferFor(node.piece.source);\n return buffer.text.charAt(node.piece.offset + offsetInPiece);\n }\n\n includes(needle: string): boolean {\n if (needle.length === 0) {\n return true;\n }\n\n const prefixTable = createPrefixTable(needle);\n let matched = 0;\n let found = false;\n this.#forEachPieceSegment((segment) => {\n for (let offset = segment.start; offset < segment.end; offset++) {\n const charCode = segment.text.charCodeAt(offset);\n while (matched > 0 && charCode !== needle.charCodeAt(matched)) {\n matched = prefixTable[matched - 1];\n }\n if (charCode === needle.charCodeAt(matched)) {\n matched++;\n }\n if (matched === needle.length) {\n found = true;\n return false;\n }\n }\n return true;\n });\n return found;\n }\n\n findNextNonOverlappingSubstring(\n needle: string,\n occupied: readonly [start: number, end: number][]\n ): number | undefined {\n if (needle.length === 0 || needle.length > this.#length) {\n return undefined;\n }\n\n const ranges = normalizeRanges(occupied, this.#length);\n const pivot = ranges.reduce((max, [, end]) => Math.max(max, end), 0);\n const prefixTable = createPrefixTable(needle);\n let matched = 0;\n let documentOffset = 0;\n let wrappedOffset: number | undefined;\n let foundOffset: number | undefined;\n\n this.#forEachPieceSegment((segment) => {\n for (let offset = segment.start; offset < segment.end; offset++) {\n const charCode = segment.text.charCodeAt(offset);\n while (matched > 0 && charCode !== needle.charCodeAt(matched)) {\n matched = prefixTable[matched - 1];\n }\n if (charCode === needle.charCodeAt(matched)) {\n matched++;\n }\n if (matched === needle.length) {\n const start = documentOffset - needle.length + 1;\n if (!rangeOverlaps(ranges, start, start + needle.length)) {\n if (start >= pivot) {\n foundOffset = start;\n return false;\n }\n wrappedOffset ??= start;\n }\n matched = prefixTable[matched - 1];\n }\n documentOffset++;\n }\n return true;\n });\n\n return foundOffset ?? wrappedOffset;\n }\n\n search(searchParams: SearchParams): [start: number, end: number][] {\n if (searchParams.text.length === 0 || this.#length === 0) {\n return [];\n }\n\n // Search currently operates line-by-line, so newline-spanning patterns are unsupported.\n if (\n searchParams.text.includes('\\n') ||\n searchParams.text.includes('\\r') ||\n (searchParams.regex &&\n (searchParams.text.includes('\\\\n') ||\n searchParams.text.includes('\\\\r')))\n ) {\n return [];\n }\n\n let pattern: RegExp;\n try {\n pattern = compileSearchRegExp(\n searchParams.text,\n searchParams.regex,\n searchParams.caseSensitive\n );\n } catch {\n return [];\n }\n\n return this.#collectSearchMatchesLineByLine(\n pattern,\n searchParams.wholeWord,\n MAX_FIND_MATCHES\n );\n }\n\n #collectSearchMatchesLineByLine(\n pattern: RegExp,\n wholeWord: boolean,\n limit: number\n ): [number, number][] {\n const out: [number, number][] = [];\n const docLength = this.#length;\n const charAt = (offset: number) => this.charAt(offset);\n\n for (let line = 0; line < this.#lineCount; line++) {\n const lineText = this.getLineText(line);\n const lineStart = this.offsetAt({ line, character: 0 });\n const re = new RegExp(pattern.source, pattern.flags);\n re.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = re.exec(lineText)) !== null) {\n const rel = match.index;\n const fragment = match[0];\n if (fragment.length === 0) {\n re.lastIndex = advancePastEmptyMatch(lineText, rel);\n continue;\n }\n const docStart = lineStart + rel;\n if (\n !wholeWord ||\n isWholeWordAtDocOffsets(docStart, fragment.length, docLength, charAt)\n ) {\n out.push([docStart, docStart + fragment.length]);\n if (out.length >= limit) {\n return out;\n }\n }\n if (rel === re.lastIndex) {\n re.lastIndex = advancePastEmptyMatch(lineText, rel);\n }\n }\n }\n return out;\n }\n\n insert(text: string, offset: number): void {\n if (text.length === 0) {\n return;\n }\n\n const insertOffset = clamp(offset, 0, this.#length);\n const addOffset = this.#add.append(text);\n const insertedPiece = this.#createPiece(\n Piece.Added,\n addOffset,\n text.length\n );\n const pieces = this.#pieces();\n const nextPieces: Piece[] = [];\n\n let cursor = 0;\n let inserted = false;\n\n for (const piece of pieces) {\n const pieceEnd = cursor + piece.length;\n if (!inserted && insertOffset <= pieceEnd) {\n const splitOffset = insertOffset - cursor;\n if (splitOffset > 0) {\n nextPieces.push(\n this.#createPiece(piece.source, piece.offset, splitOffset)\n );\n }\n nextPieces.push(insertedPiece);\n if (splitOffset < piece.length) {\n nextPieces.push(\n this.#createPiece(\n piece.source,\n piece.offset + splitOffset,\n piece.length - splitOffset\n )\n );\n }\n inserted = true;\n } else {\n nextPieces.push(piece);\n }\n cursor = pieceEnd;\n }\n\n if (!inserted) {\n nextPieces.push(insertedPiece);\n }\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n this.#lastVisitedLineLength = null;\n }\n\n delete(offset: number, length: number): void {\n if (length <= 0 || this.#length === 0) {\n return;\n }\n\n const start = clamp(offset, 0, this.#length);\n const end = clamp(start + length, start, this.#length);\n if (start === end) {\n return;\n }\n\n const nextPieces: Piece[] = [];\n let cursor = 0;\n for (const piece of this.#pieces()) {\n const pieceStart = cursor;\n const pieceEnd = cursor + piece.length;\n const keepBefore = clamp(start - pieceStart, 0, piece.length);\n const keepAfter = clamp(pieceEnd - end, 0, piece.length);\n\n if (keepBefore > 0) {\n nextPieces.push(\n this.#createPiece(piece.source, piece.offset, keepBefore)\n );\n }\n if (keepAfter > 0) {\n nextPieces.push(\n this.#createPiece(\n piece.source,\n piece.offset + piece.length - keepAfter,\n keepAfter\n )\n );\n }\n cursor = pieceEnd;\n }\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n this.#lastVisitedLineLength = null;\n }\n\n applyEdits(edits: readonly ResolvedTextEdit[]): void {\n if (edits.length === 0) {\n return;\n }\n\n let pieceIndex = 0;\n let pieceStart = 0;\n let copyCursor = 0;\n\n const pieces = this.#pieces();\n const insertedPieces = edits.map((edit) =>\n edit.text.length === 0\n ? undefined\n : this.#createPiece(\n Piece.Added,\n this.#add.append(edit.text),\n edit.text.length\n )\n );\n const nextPieces: Piece[] = [];\n\n const advancePiece = () => {\n const piece = pieces[pieceIndex];\n if (piece !== undefined) {\n pieceStart += piece.length;\n pieceIndex++;\n }\n };\n\n const appendRange = (start: number, end: number) => {\n let rangeStart = clamp(start, 0, this.#length);\n const rangeEnd = clamp(end, rangeStart, this.#length);\n while (\n pieceIndex < pieces.length &&\n pieceStart + pieces[pieceIndex].length <= rangeStart\n ) {\n advancePiece();\n }\n while (pieceIndex < pieces.length && rangeStart < rangeEnd) {\n const piece = pieces[pieceIndex];\n const pieceEnd = pieceStart + piece.length;\n const offsetInPiece = clamp(rangeStart - pieceStart, 0, piece.length);\n const takeEnd = Math.min(pieceEnd, rangeEnd);\n const takeLength = takeEnd - (pieceStart + offsetInPiece);\n if (takeLength > 0) {\n nextPieces.push(\n offsetInPiece === 0 && takeLength === piece.length\n ? piece\n : this.#createPiece(\n piece.source,\n piece.offset + offsetInPiece,\n takeLength\n )\n );\n }\n rangeStart = takeEnd;\n if (rangeStart >= pieceEnd) {\n advancePiece();\n }\n }\n };\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n const start = clamp(edit.start, copyCursor, this.#length);\n const end = clamp(edit.end, start, this.#length);\n appendRange(copyCursor, start);\n\n const insertedPiece = insertedPieces[i];\n if (insertedPiece !== undefined) {\n nextPieces.push(insertedPiece);\n }\n copyCursor = end;\n }\n appendRange(copyCursor, this.#length);\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n this.#lastVisitedLineLength = null;\n }\n\n positionAt(offset: number): Position {\n const clampedOffset = clamp(offset, 0, this.#length);\n if (this.#length === 0) {\n return { line: 0, character: 0 };\n }\n const line = this.#lineAtOffset(clampedOffset);\n const lineStart = line === 0 ? 0 : this.#lineBreakOffset(line - 1);\n return {\n line,\n character: clampedOffset - lineStart,\n };\n }\n\n positionsAt(offsets: readonly number[]): Position[] {\n const positions: Position[] = Array.from({ length: offsets.length });\n if (offsets.length === 0) {\n return positions;\n }\n if (this.#length === 0) {\n return positions.fill({ line: 0, character: 0 });\n }\n\n for (let i = 0; i < offsets.length; i++) {\n positions[i] = this.positionAt(offsets[i]);\n }\n\n return positions;\n }\n\n offsetAt(position: Position): number {\n if (position.line < 0 || this.#length === 0) {\n return 0;\n }\n if (position.line >= this.#lineCount) {\n throw new Error(`Line index out of range: ${position.line}`);\n }\n const offset = this.#getLineOffset(position.line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${position.line}`);\n }\n const character = clamp(position.character, 0, offset[1] - offset[0]);\n return offset[0] + character;\n }\n\n #findPieceAtOffset(\n offset: number\n ): [node: PieceNode, offsetInPiece: number] | undefined {\n if (offset < 0 || offset >= this.#length) {\n return undefined;\n }\n\n let node = this.#root;\n let remaining = offset;\n while (node !== null) {\n const leftLength = node.left?.subtreeLength ?? 0;\n if (remaining < leftLength) {\n node = node.left;\n continue;\n }\n\n remaining -= leftLength;\n if (remaining < node.piece.length) {\n return [node, remaining];\n }\n\n remaining -= node.piece.length;\n node = node.right;\n }\n\n return undefined;\n }\n\n #nextNode(node: PieceNode): PieceNode | null {\n if (node.right !== null) {\n let next = node.right;\n while (next.left !== null) {\n next = next.left;\n }\n return next;\n }\n\n let current = node;\n while (current.parent !== null && current === current.parent.right) {\n current = current.parent;\n }\n return current.parent;\n }\n\n #getLineOffset(line: number): [start: number, end: number] | undefined {\n if (line < 0) {\n throw new Error(`Line index out of range: ${line}`);\n }\n if (this.#length === 0) {\n if (line === 0) {\n return [0, 0];\n }\n throw new Error(`Line index out of range: ${line}`);\n }\n if (line >= this.#lineCount) {\n throw new Error(`Line index out of range: ${line}`);\n }\n\n const start = line === 0 ? 0 : this.#lineBreakOffset(line - 1);\n const end =\n line < this.#lineCount - 1 ? this.#lineBreakOffset(line) : this.#length;\n return [start, end];\n }\n\n #lineAtOffset(offset: number): number {\n let node = this.#root;\n let remaining = clamp(offset, 0, this.#length);\n let line = 0;\n\n while (node !== null) {\n const leftLength = node.left?.subtreeLength ?? 0;\n if (remaining < leftLength) {\n node = node.left;\n continue;\n }\n\n line += node.left?.subtreeLineBreakCount ?? 0;\n remaining -= leftLength;\n if (remaining <= node.piece.length) {\n const buffer = this.#bufferFor(node.piece.source);\n line +=\n upperBound(buffer.lineOffsets, node.piece.offset + remaining) -\n node.piece.lineOffsetStart;\n return line;\n }\n\n line += node.piece.lineBreakCount;\n remaining -= node.piece.length;\n node = node.right;\n }\n\n return this.#lineCount - 1;\n }\n\n #lineBreakOffset(lineBreakIndex: number): number {\n let node = this.#root;\n let remaining = lineBreakIndex;\n let documentOffset = 0;\n\n while (node !== null) {\n const leftLineBreakCount = node.left?.subtreeLineBreakCount ?? 0;\n if (remaining < leftLineBreakCount) {\n node = node.left;\n continue;\n }\n\n const leftLength = node.left?.subtreeLength ?? 0;\n documentOffset += leftLength;\n remaining -= leftLineBreakCount;\n\n if (remaining < node.piece.lineBreakCount) {\n const bufferLineOffset = this.#bufferFor(node.piece.source).lineOffsets[\n node.piece.lineOffsetStart + remaining\n ];\n return documentOffset + (bufferLineOffset - node.piece.offset);\n }\n\n documentOffset += node.piece.length;\n remaining -= node.piece.lineBreakCount;\n node = node.right;\n }\n\n return this.#length;\n }\n\n #textFromPieces(): string {\n const chunks: string[] = [];\n this.#forEachPieceSegment((segment) => {\n chunks.push(segment.text.slice(segment.start, segment.end));\n });\n return chunks.join('');\n }\n\n #forEachPieceSegment(\n callback: (segment: {\n readonly start: number;\n readonly end: number;\n readonly text: string;\n readonly lineOffsets: number[];\n readonly lineOffsetStart: number;\n readonly lineOffsetEnd: number;\n }) => boolean | void\n ): void {\n this.#walk(this.#root, (node) => {\n const buffer = this.#bufferFor(node.piece.source);\n return callback({\n text: buffer.text,\n lineOffsets: buffer.lineOffsets,\n lineOffsetStart: node.piece.lineOffsetStart,\n lineOffsetEnd: node.piece.lineOffsetEnd,\n start: node.piece.offset,\n end: node.piece.offset + node.piece.length,\n });\n });\n }\n\n #bufferFor(source: number): TextBuffer {\n return source === Piece.Original ? this.#original : this.#add;\n }\n\n #createPiece(source: number, offset: number, length: number): Piece {\n const buffer = this.#bufferFor(source);\n return new Piece(\n source,\n offset,\n length,\n upperBound(buffer.lineOffsets, offset),\n upperBound(buffer.lineOffsets, offset + length)\n );\n }\n\n #pieces(): Piece[] {\n return this.#piecesCache;\n }\n\n #setPieces(pieces: Piece[]): void {\n const coalescedPieces = coalescePieces(pieces);\n this.#piecesCache = coalescedPieces;\n let length = 0;\n let lineBreakCount = 0;\n for (const piece of coalescedPieces) {\n length += piece.length;\n lineBreakCount += piece.lineBreakCount;\n }\n this.#root = this.#buildBalancedTree(\n coalescedPieces,\n 0,\n coalescedPieces.length,\n null\n );\n this.#length = length;\n this.#lineCount = lineBreakCount + 1;\n }\n\n #buildBalancedTree(\n pieces: Piece[],\n start: number,\n end: number,\n parent: PieceNode | null\n ): PieceNode | null {\n if (start >= end) {\n return null;\n }\n\n const middle = start + Math.floor((end - start) / 2);\n const node = new PieceNode(pieces[middle]);\n node.parent = parent;\n node.left = this.#buildBalancedTree(pieces, start, middle, node);\n node.right = this.#buildBalancedTree(pieces, middle + 1, end, node);\n node.updateSubtreeLength();\n return node;\n }\n\n #walk(\n node: PieceNode | null,\n visit: (node: PieceNode) => boolean | void\n ): boolean {\n if (node === null) {\n return true;\n }\n if (!this.#walk(node.left, visit)) {\n return false;\n }\n if (visit(node) === false) {\n return false;\n }\n return this.#walk(node.right, visit);\n }\n}\n\nfunction isEOL(charCode: number): boolean {\n return charCode === /* \\n */ 10 || charCode === /* \\r */ 13;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction createPrefixTable(text: string): number[] {\n const table = Array.from<number>({ length: text.length }).fill(0);\n let matched = 0;\n for (let i = 1; i < text.length; i++) {\n const charCode = text.charCodeAt(i);\n while (matched > 0 && charCode !== text.charCodeAt(matched)) {\n matched = table[matched - 1];\n }\n if (charCode === text.charCodeAt(matched)) {\n matched++;\n }\n table[i] = matched;\n }\n return table;\n}\n\nfunction normalizeRanges(\n ranges: readonly [start: number, end: number][],\n length: number\n): [start: number, end: number][] {\n const normalized: [start: number, end: number][] = [];\n for (const [rawStart, rawEnd] of ranges) {\n const start = clamp(rawStart, 0, length);\n const end = clamp(rawEnd, start, length);\n if (start < end) {\n normalized.push([start, end]);\n }\n }\n normalized.sort((a, b) => a[0] - b[0]);\n\n const merged: [start: number, end: number][] = [];\n for (const range of normalized) {\n const previous = merged[merged.length - 1];\n if (previous !== undefined && range[0] <= previous[1]) {\n previous[1] = Math.max(previous[1], range[1]);\n continue;\n }\n merged.push(range);\n }\n return merged;\n}\n\nfunction rangeOverlaps(\n ranges: readonly [start: number, end: number][],\n start: number,\n end: number\n): boolean {\n let low = 0;\n let high = ranges.length;\n while (low < high) {\n const mid = low + Math.floor((high - low) / 2);\n if (ranges[mid][1] <= start) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n\n const range = ranges[low];\n return range !== undefined && range[0] < end;\n}\n\n// Keeps the table compact after repeated edits by joining neighboring pieces\n// that already point at contiguous text in the same backing buffer.\nfunction coalescePieces(pieces: Piece[]): Piece[] {\n const coalescedPieces: Piece[] = [];\n for (const piece of pieces) {\n if (piece.length === 0) {\n continue;\n }\n\n const previous = coalescedPieces[coalescedPieces.length - 1];\n if (\n previous !== undefined &&\n previous.source === piece.source &&\n previous.offset + previous.length === piece.offset\n ) {\n coalescedPieces[coalescedPieces.length - 1] = new Piece(\n previous.source,\n previous.offset,\n previous.length + piece.length,\n previous.lineOffsetStart,\n piece.lineOffsetEnd\n );\n continue;\n }\n\n coalescedPieces.push(piece);\n }\n return coalescedPieces;\n}\n\n// Returns the index of the first element in the array that is greater than the target.\nfunction upperBound(values: number[], target: number): number {\n let lo = 0;\n let hi = values.length;\n while (lo < hi) {\n const mid = lo + Math.floor((hi - lo) / 2);\n if (values[mid] <= target) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n return lo;\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction isWordSeparatorCharCode(charCode: number): boolean {\n if (charCode <= 32 || charCode === 127) {\n return true;\n }\n const ch = String.fromCharCode(charCode);\n return WORD_SEPARATORS.includes(ch);\n}\n\n// Checks if the given text is a whole word by checking if the\n// characters before and after are word separators.\nfunction isWholeWordAtDocOffsets(\n docStart: number,\n length: number,\n docLength: number,\n charAt: (offset: number) => string\n): boolean {\n const beforeOk =\n docStart <= 0 ||\n isWordSeparatorCharCode(charCodeUnitAt(charAt, docStart - 1));\n const afterOk =\n docStart + length >= docLength ||\n isWordSeparatorCharCode(charCodeUnitAt(charAt, docStart + length));\n return beforeOk && afterOk;\n}\n\nfunction charCodeUnitAt(\n charAt: (offset: number) => string,\n offset: number\n): number {\n const unit = charAt(offset);\n return unit.length === 0 ? 0 : unit.charCodeAt(0);\n}\n\nfunction compileSearchRegExp(\n source: string,\n isRegex: boolean,\n caseSensitive: boolean\n): RegExp {\n const body = isRegex ? source : escapeRegExp(source);\n const flags = `g${caseSensitive ? '' : 'i'}${isRegex ? 'm' : ''}`;\n return new RegExp(body, flags);\n}\n\nfunction advancePastEmptyMatch(text: string, index: number): number {\n if (index + 1 < text.length) {\n const first = text.charCodeAt(index);\n const second = text.charCodeAt(index + 1);\n if (\n first >= 0xd800 &&\n first <= 0xdbff &&\n second >= 0xdc00 &&\n second <= 0xdfff\n ) {\n return index + 2;\n }\n }\n return index + 1;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pieceTable.js","names":["source: number","offset: number","length: number","lineOffsetStart: number","lineOffsetEnd: number","text: string","piece: Piece","subtreeLength: number","subtreeLineBreakCount: number","#original","#setPieces","#createPiece","#lineCount","#textFromPieces","#lastVisitedLine","#getLineOffset","#lastVisitedLineLength","length","#length","#findPieceAtOffset","chunks: string[]","#bufferFor","start","end","#nextNode","#forEachPieceSegment","wrappedOffset: number | undefined","foundOffset: number | undefined","pattern: RegExp","#collectSearchMatchesLineByLine","out: [number, number][]","match: RegExpExecArray | null","#add","#pieces","nextPieces: Piece[]","#lineAtOffset","#lineBreakOffset","positions: Position[]","#root","#walk","#piecesCache","#buildBalancedTree","normalized: [start: number, end: number][]","merged: [start: number, end: number][]","coalescedPieces: Piece[]"],"sources":["../../src/editor/pieceTable.ts"],"sourcesContent":["import { computeLineOffsets } from '../utils/computeFileOffsets';\nimport type { SearchParams } from './searchPanel';\nimport type { Position, Range, ResolvedTextEdit } from './textDocument';\n\nconst MAX_FIND_MATCHES = 100000;\n// TODO(ije): use Intl.Segmenter instead of regex for word separators\nconst WORD_SEPARATORS = '`~!@#$%^&*()-=+[{]}\\\\|;:\\'\",.<>/?' as const;\n\n// A piece is a segment of text that is either original or added.\nclass Piece {\n static Original = 0;\n static Added = 1;\n\n constructor(\n public readonly source: number,\n public readonly offset: number,\n public readonly length: number,\n public readonly lineOffsetStart: number,\n public readonly lineOffsetEnd: number\n ) {}\n\n get lineBreakCount(): number {\n return this.lineOffsetEnd - this.lineOffsetStart;\n }\n}\n\n// A text buffer is a string with its line offsets.\nclass TextBuffer {\n lineOffsets: number[];\n\n constructor(public text: string) {\n this.lineOffsets = computeLineOffsets(text);\n }\n\n // the append operation is efficient because it only appends\n // elements to the lineOffsets array in the end\n append(text: string): number {\n const offset = this.text.length;\n const appendedLineOffsets = computeLineOffsets(text);\n for (let i = 1; i < appendedLineOffsets.length; i++) {\n this.lineOffsets.push(offset + appendedLineOffsets[i]);\n }\n this.text += text;\n return offset;\n }\n}\n\n// A node in the balanced piece tree.\nclass PieceNode {\n left: PieceNode | null = null;\n right: PieceNode | null = null;\n parent: PieceNode | null = null;\n\n constructor(\n public piece: Piece,\n public subtreeLength: number = piece.length,\n public subtreeLineBreakCount: number = piece.lineBreakCount\n ) {}\n\n updateSubtreeLength(): void {\n this.subtreeLength =\n (this.left?.subtreeLength ?? 0) +\n this.piece.length +\n (this.right?.subtreeLength ?? 0);\n this.subtreeLineBreakCount =\n (this.left?.subtreeLineBreakCount ?? 0) +\n this.piece.lineBreakCount +\n (this.right?.subtreeLineBreakCount ?? 0);\n }\n}\n\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 class PieceTable {\n #original: TextBuffer;\n #add = new TextBuffer('');\n #root: PieceNode | null = null;\n #piecesCache: Piece[] = [];\n #length = 0;\n #lineCount = 0;\n #lastVisitedLine: [number, boolean, string] | null = null;\n #lastVisitedLineLength: [number, boolean, number] | null = null;\n\n constructor(originalText: string) {\n this.#original = new TextBuffer(originalText);\n this.#setPieces([\n this.#createPiece(Piece.Original, 0, originalText.length),\n ]);\n }\n\n get lineCount(): number {\n return this.#lineCount;\n }\n\n getText(range?: Range): string {\n if (range === undefined) {\n return this.#textFromPieces();\n }\n const start = this.offsetAt(range.start);\n const end = this.offsetAt(range.end);\n return this.getTextSlice(start, end);\n }\n\n getLineText(line: number, includeLineBreak = false): string {\n if (\n this.#lastVisitedLine !== null &&\n this.#lastVisitedLine[0] === line &&\n this.#lastVisitedLine[1] === includeLineBreak\n ) {\n return this.#lastVisitedLine[2];\n }\n const offset = this.#getLineOffset(line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${line}`);\n }\n const text = this.getTextSlice(offset[0], offset[1], !includeLineBreak);\n this.#lastVisitedLine = [line, includeLineBreak, text];\n this.#lastVisitedLineLength = [line, includeLineBreak, text.length];\n return text;\n }\n\n getLineLength(line: number, includeLineBreak = false): number {\n const lastVisitedLineLength = this.#lastVisitedLineLength;\n const lastVisitedLine = this.#lastVisitedLine;\n if (\n lastVisitedLineLength !== null &&\n lastVisitedLineLength[0] === line &&\n lastVisitedLineLength[1] === includeLineBreak\n ) {\n return lastVisitedLineLength[2];\n }\n if (\n lastVisitedLine !== null &&\n lastVisitedLine[0] === line &&\n lastVisitedLine[1] === includeLineBreak\n ) {\n const length = lastVisitedLine[2].length;\n this.#lastVisitedLineLength = [line, includeLineBreak, length];\n return length;\n }\n const offset = this.#getLineOffset(line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${line}`);\n }\n const [start, end] = offset;\n let length = end - start;\n if (!includeLineBreak) {\n while (\n length > 0 &&\n isEOL(this.charAt(start + length - 1).charCodeAt(0))\n ) {\n length--;\n }\n }\n this.#lastVisitedLineLength = [line, includeLineBreak, length];\n return length;\n }\n\n getTextSlice(start: number, end: number, trimEOF = false): string {\n if (start >= end) {\n return '';\n }\n\n const sliceStart = clamp(start, 0, this.#length);\n const sliceEnd = clamp(end, sliceStart, this.#length);\n if (sliceStart >= sliceEnd) {\n return '';\n }\n\n const location = this.#findPieceAtOffset(sliceStart);\n if (location === undefined) {\n return '';\n }\n\n const chunks: string[] = [];\n let [node, offsetInPiece] = location as [PieceNode | null, number];\n let remaining = sliceEnd - sliceStart;\n while (node !== null && remaining > 0) {\n const takeLength = Math.min(node.piece.length - offsetInPiece, remaining);\n const buffer = this.#bufferFor(node.piece.source);\n const start = node.piece.offset + offsetInPiece;\n let end = start + takeLength;\n if (trimEOF) {\n while (end > start && isEOL(buffer.text.charCodeAt(end - 1))) {\n end--;\n }\n }\n chunks.push(buffer.text.slice(start, end));\n remaining -= takeLength;\n offsetInPiece = 0;\n node = this.#nextNode(node);\n }\n\n return chunks.join('');\n }\n\n charAt(offset: number): string {\n const location = this.#findPieceAtOffset(offset);\n if (location === undefined) {\n return '';\n }\n\n const [node, offsetInPiece] = location;\n const buffer = this.#bufferFor(node.piece.source);\n return buffer.text.charAt(node.piece.offset + offsetInPiece);\n }\n\n includes(needle: string): boolean {\n if (needle.length === 0) {\n return true;\n }\n\n const prefixTable = createPrefixTable(needle);\n let matched = 0;\n let found = false;\n this.#forEachPieceSegment((segment) => {\n for (let offset = segment.start; offset < segment.end; offset++) {\n const charCode = segment.text.charCodeAt(offset);\n while (matched > 0 && charCode !== needle.charCodeAt(matched)) {\n matched = prefixTable[matched - 1];\n }\n if (charCode === needle.charCodeAt(matched)) {\n matched++;\n }\n if (matched === needle.length) {\n found = true;\n return false;\n }\n }\n return true;\n });\n return found;\n }\n\n findNextNonOverlappingSubstring(\n needle: string,\n occupied: readonly [start: number, end: number][]\n ): number | undefined {\n if (needle.length === 0 || needle.length > this.#length) {\n return undefined;\n }\n\n const ranges = normalizeRanges(occupied, this.#length);\n const pivot = ranges.reduce((max, [, end]) => Math.max(max, end), 0);\n const prefixTable = createPrefixTable(needle);\n let matched = 0;\n let documentOffset = 0;\n let wrappedOffset: number | undefined;\n let foundOffset: number | undefined;\n\n this.#forEachPieceSegment((segment) => {\n for (let offset = segment.start; offset < segment.end; offset++) {\n const charCode = segment.text.charCodeAt(offset);\n while (matched > 0 && charCode !== needle.charCodeAt(matched)) {\n matched = prefixTable[matched - 1];\n }\n if (charCode === needle.charCodeAt(matched)) {\n matched++;\n }\n if (matched === needle.length) {\n const start = documentOffset - needle.length + 1;\n if (!rangeOverlaps(ranges, start, start + needle.length)) {\n if (start >= pivot) {\n foundOffset = start;\n return false;\n }\n wrappedOffset ??= start;\n }\n matched = prefixTable[matched - 1];\n }\n documentOffset++;\n }\n return true;\n });\n\n return foundOffset ?? wrappedOffset;\n }\n\n search(searchParams: SearchParams): [start: number, end: number][] {\n if (searchParams.text.length === 0 || this.#length === 0) {\n return [];\n }\n\n // Search currently operates line-by-line, so newline-spanning patterns are unsupported.\n if (\n searchParams.text.includes('\\n') ||\n searchParams.text.includes('\\r') ||\n (searchParams.regex &&\n (searchParams.text.includes('\\\\n') ||\n searchParams.text.includes('\\\\r')))\n ) {\n return [];\n }\n\n let pattern: RegExp;\n try {\n pattern = compileSearchRegExp(\n searchParams.text,\n searchParams.regex,\n searchParams.caseSensitive\n );\n } catch {\n return [];\n }\n\n return this.#collectSearchMatchesLineByLine(\n pattern,\n searchParams.wholeWord,\n MAX_FIND_MATCHES\n );\n }\n\n #collectSearchMatchesLineByLine(\n pattern: RegExp,\n wholeWord: boolean,\n limit: number\n ): [number, number][] {\n const out: [number, number][] = [];\n const docLength = this.#length;\n const charAt = (offset: number) => this.charAt(offset);\n\n for (let line = 0; line < this.#lineCount; line++) {\n const lineText = this.getLineText(line);\n const lineStart = this.offsetAt({ line, character: 0 });\n const re = new RegExp(pattern.source, pattern.flags);\n re.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = re.exec(lineText)) !== null) {\n const rel = match.index;\n const fragment = match[0];\n if (fragment.length === 0) {\n re.lastIndex = advancePastEmptyMatch(lineText, rel);\n continue;\n }\n const docStart = lineStart + rel;\n if (\n !wholeWord ||\n isWholeWordAtDocOffsets(docStart, fragment.length, docLength, charAt)\n ) {\n out.push([docStart, docStart + fragment.length]);\n if (out.length >= limit) {\n return out;\n }\n }\n if (rel === re.lastIndex) {\n re.lastIndex = advancePastEmptyMatch(lineText, rel);\n }\n }\n }\n return out;\n }\n\n insert(text: string, offset: number): void {\n if (text.length === 0) {\n return;\n }\n\n const insertOffset = clamp(offset, 0, this.#length);\n const addOffset = this.#add.append(text);\n const insertedPiece = this.#createPiece(\n Piece.Added,\n addOffset,\n text.length\n );\n const pieces = this.#pieces();\n const nextPieces: Piece[] = [];\n\n let cursor = 0;\n let inserted = false;\n\n for (const piece of pieces) {\n const pieceEnd = cursor + piece.length;\n if (!inserted && insertOffset <= pieceEnd) {\n const splitOffset = insertOffset - cursor;\n if (splitOffset > 0) {\n nextPieces.push(\n this.#createPiece(piece.source, piece.offset, splitOffset)\n );\n }\n nextPieces.push(insertedPiece);\n if (splitOffset < piece.length) {\n nextPieces.push(\n this.#createPiece(\n piece.source,\n piece.offset + splitOffset,\n piece.length - splitOffset\n )\n );\n }\n inserted = true;\n } else {\n nextPieces.push(piece);\n }\n cursor = pieceEnd;\n }\n\n if (!inserted) {\n nextPieces.push(insertedPiece);\n }\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n this.#lastVisitedLineLength = null;\n }\n\n delete(offset: number, length: number): void {\n if (length <= 0 || this.#length === 0) {\n return;\n }\n\n const start = clamp(offset, 0, this.#length);\n const end = clamp(start + length, start, this.#length);\n if (start === end) {\n return;\n }\n\n const nextPieces: Piece[] = [];\n let cursor = 0;\n for (const piece of this.#pieces()) {\n const pieceStart = cursor;\n const pieceEnd = cursor + piece.length;\n const keepBefore = clamp(start - pieceStart, 0, piece.length);\n const keepAfter = clamp(pieceEnd - end, 0, piece.length);\n\n if (keepBefore > 0) {\n nextPieces.push(\n this.#createPiece(piece.source, piece.offset, keepBefore)\n );\n }\n if (keepAfter > 0) {\n nextPieces.push(\n this.#createPiece(\n piece.source,\n piece.offset + piece.length - keepAfter,\n keepAfter\n )\n );\n }\n cursor = pieceEnd;\n }\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n this.#lastVisitedLineLength = null;\n }\n\n applyEdits(edits: readonly ResolvedTextEdit[]): void {\n if (edits.length === 0) {\n return;\n }\n\n let pieceIndex = 0;\n let pieceStart = 0;\n let copyCursor = 0;\n\n const pieces = this.#pieces();\n const insertedPieces = edits.map((edit) =>\n edit.text.length === 0\n ? undefined\n : this.#createPiece(\n Piece.Added,\n this.#add.append(edit.text),\n edit.text.length\n )\n );\n const nextPieces: Piece[] = [];\n\n const advancePiece = () => {\n const piece = pieces[pieceIndex];\n if (piece !== undefined) {\n pieceStart += piece.length;\n pieceIndex++;\n }\n };\n\n const appendRange = (start: number, end: number) => {\n let rangeStart = clamp(start, 0, this.#length);\n const rangeEnd = clamp(end, rangeStart, this.#length);\n while (\n pieceIndex < pieces.length &&\n pieceStart + pieces[pieceIndex].length <= rangeStart\n ) {\n advancePiece();\n }\n while (pieceIndex < pieces.length && rangeStart < rangeEnd) {\n const piece = pieces[pieceIndex];\n const pieceEnd = pieceStart + piece.length;\n const offsetInPiece = clamp(rangeStart - pieceStart, 0, piece.length);\n const takeEnd = Math.min(pieceEnd, rangeEnd);\n const takeLength = takeEnd - (pieceStart + offsetInPiece);\n if (takeLength > 0) {\n nextPieces.push(\n offsetInPiece === 0 && takeLength === piece.length\n ? piece\n : this.#createPiece(\n piece.source,\n piece.offset + offsetInPiece,\n takeLength\n )\n );\n }\n rangeStart = takeEnd;\n if (rangeStart >= pieceEnd) {\n advancePiece();\n }\n }\n };\n\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n const start = clamp(edit.start, copyCursor, this.#length);\n const end = clamp(edit.end, start, this.#length);\n appendRange(copyCursor, start);\n\n const insertedPiece = insertedPieces[i];\n if (insertedPiece !== undefined) {\n nextPieces.push(insertedPiece);\n }\n copyCursor = end;\n }\n appendRange(copyCursor, this.#length);\n\n this.#setPieces(nextPieces);\n this.#lastVisitedLine = null;\n this.#lastVisitedLineLength = null;\n }\n\n positionAt(offset: number): Position {\n const clampedOffset = clamp(offset, 0, this.#length);\n if (this.#length === 0) {\n return { line: 0, character: 0 };\n }\n const line = this.#lineAtOffset(clampedOffset);\n const lineStart = line === 0 ? 0 : this.#lineBreakOffset(line - 1);\n return {\n line,\n character: clampedOffset - lineStart,\n };\n }\n\n positionsAt(offsets: readonly number[]): Position[] {\n const positions: Position[] = Array.from({ length: offsets.length });\n if (offsets.length === 0) {\n return positions;\n }\n if (this.#length === 0) {\n return positions.fill({ line: 0, character: 0 });\n }\n\n for (let i = 0; i < offsets.length; i++) {\n positions[i] = this.positionAt(offsets[i]);\n }\n\n return positions;\n }\n\n offsetAt(position: Position): number {\n if (position.line < 0 || this.#length === 0) {\n return 0;\n }\n if (position.line >= this.#lineCount) {\n throw new Error(`Line index out of range: ${position.line}`);\n }\n const offset = this.#getLineOffset(position.line);\n if (offset === undefined) {\n throw new Error(`Line index out of range: ${position.line}`);\n }\n const character = clamp(position.character, 0, offset[1] - offset[0]);\n return offset[0] + character;\n }\n\n #findPieceAtOffset(\n offset: number\n ): [node: PieceNode, offsetInPiece: number] | undefined {\n if (offset < 0 || offset >= this.#length) {\n return undefined;\n }\n\n let node = this.#root;\n let remaining = offset;\n while (node !== null) {\n const leftLength = node.left?.subtreeLength ?? 0;\n if (remaining < leftLength) {\n node = node.left;\n continue;\n }\n\n remaining -= leftLength;\n if (remaining < node.piece.length) {\n return [node, remaining];\n }\n\n remaining -= node.piece.length;\n node = node.right;\n }\n\n return undefined;\n }\n\n #nextNode(node: PieceNode): PieceNode | null {\n if (node.right !== null) {\n let next = node.right;\n while (next.left !== null) {\n next = next.left;\n }\n return next;\n }\n\n let current = node;\n while (current.parent !== null && current === current.parent.right) {\n current = current.parent;\n }\n return current.parent;\n }\n\n #getLineOffset(line: number): [start: number, end: number] | undefined {\n if (line < 0) {\n throw new Error(`Line index out of range: ${line}`);\n }\n if (this.#length === 0) {\n if (line === 0) {\n return [0, 0];\n }\n throw new Error(`Line index out of range: ${line}`);\n }\n if (line >= this.#lineCount) {\n throw new Error(`Line index out of range: ${line}`);\n }\n\n const start = line === 0 ? 0 : this.#lineBreakOffset(line - 1);\n const end =\n line < this.#lineCount - 1 ? this.#lineBreakOffset(line) : this.#length;\n return [start, end];\n }\n\n #lineAtOffset(offset: number): number {\n let node = this.#root;\n let remaining = clamp(offset, 0, this.#length);\n let line = 0;\n\n while (node !== null) {\n const leftLength = node.left?.subtreeLength ?? 0;\n if (remaining < leftLength) {\n node = node.left;\n continue;\n }\n\n line += node.left?.subtreeLineBreakCount ?? 0;\n remaining -= leftLength;\n if (remaining <= node.piece.length) {\n const buffer = this.#bufferFor(node.piece.source);\n line +=\n upperBound(buffer.lineOffsets, node.piece.offset + remaining) -\n node.piece.lineOffsetStart;\n return line;\n }\n\n line += node.piece.lineBreakCount;\n remaining -= node.piece.length;\n node = node.right;\n }\n\n return this.#lineCount - 1;\n }\n\n #lineBreakOffset(lineBreakIndex: number): number {\n let node = this.#root;\n let remaining = lineBreakIndex;\n let documentOffset = 0;\n\n while (node !== null) {\n const leftLineBreakCount = node.left?.subtreeLineBreakCount ?? 0;\n if (remaining < leftLineBreakCount) {\n node = node.left;\n continue;\n }\n\n const leftLength = node.left?.subtreeLength ?? 0;\n documentOffset += leftLength;\n remaining -= leftLineBreakCount;\n\n if (remaining < node.piece.lineBreakCount) {\n const bufferLineOffset = this.#bufferFor(node.piece.source).lineOffsets[\n node.piece.lineOffsetStart + remaining\n ];\n return documentOffset + (bufferLineOffset - node.piece.offset);\n }\n\n documentOffset += node.piece.length;\n remaining -= node.piece.lineBreakCount;\n node = node.right;\n }\n\n return this.#length;\n }\n\n #textFromPieces(): string {\n const chunks: string[] = [];\n this.#forEachPieceSegment((segment) => {\n chunks.push(segment.text.slice(segment.start, segment.end));\n });\n return chunks.join('');\n }\n\n #forEachPieceSegment(\n callback: (segment: {\n readonly start: number;\n readonly end: number;\n readonly text: string;\n readonly lineOffsets: number[];\n readonly lineOffsetStart: number;\n readonly lineOffsetEnd: number;\n }) => boolean | void\n ): void {\n this.#walk(this.#root, (node) => {\n const buffer = this.#bufferFor(node.piece.source);\n return callback({\n text: buffer.text,\n lineOffsets: buffer.lineOffsets,\n lineOffsetStart: node.piece.lineOffsetStart,\n lineOffsetEnd: node.piece.lineOffsetEnd,\n start: node.piece.offset,\n end: node.piece.offset + node.piece.length,\n });\n });\n }\n\n #bufferFor(source: number): TextBuffer {\n return source === Piece.Original ? this.#original : this.#add;\n }\n\n #createPiece(source: number, offset: number, length: number): Piece {\n const buffer = this.#bufferFor(source);\n return new Piece(\n source,\n offset,\n length,\n upperBound(buffer.lineOffsets, offset),\n upperBound(buffer.lineOffsets, offset + length)\n );\n }\n\n #pieces(): Piece[] {\n return this.#piecesCache;\n }\n\n #setPieces(pieces: Piece[]): void {\n const coalescedPieces = coalescePieces(pieces);\n this.#piecesCache = coalescedPieces;\n let length = 0;\n let lineBreakCount = 0;\n for (const piece of coalescedPieces) {\n length += piece.length;\n lineBreakCount += piece.lineBreakCount;\n }\n this.#root = this.#buildBalancedTree(\n coalescedPieces,\n 0,\n coalescedPieces.length,\n null\n );\n this.#length = length;\n this.#lineCount = lineBreakCount + 1;\n }\n\n #buildBalancedTree(\n pieces: Piece[],\n start: number,\n end: number,\n parent: PieceNode | null\n ): PieceNode | null {\n if (start >= end) {\n return null;\n }\n\n const middle = start + Math.floor((end - start) / 2);\n const node = new PieceNode(pieces[middle]);\n node.parent = parent;\n node.left = this.#buildBalancedTree(pieces, start, middle, node);\n node.right = this.#buildBalancedTree(pieces, middle + 1, end, node);\n node.updateSubtreeLength();\n return node;\n }\n\n #walk(\n node: PieceNode | null,\n visit: (node: PieceNode) => boolean | void\n ): boolean {\n if (node === null) {\n return true;\n }\n if (!this.#walk(node.left, visit)) {\n return false;\n }\n if (visit(node) === false) {\n return false;\n }\n return this.#walk(node.right, visit);\n }\n}\n\nfunction isEOL(charCode: number): boolean {\n return charCode === /* \\n */ 10 || charCode === /* \\r */ 13;\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\nfunction createPrefixTable(text: string): number[] {\n const table = Array.from<number>({ length: text.length }).fill(0);\n let matched = 0;\n for (let i = 1; i < text.length; i++) {\n const charCode = text.charCodeAt(i);\n while (matched > 0 && charCode !== text.charCodeAt(matched)) {\n matched = table[matched - 1];\n }\n if (charCode === text.charCodeAt(matched)) {\n matched++;\n }\n table[i] = matched;\n }\n return table;\n}\n\nfunction normalizeRanges(\n ranges: readonly [start: number, end: number][],\n length: number\n): [start: number, end: number][] {\n const normalized: [start: number, end: number][] = [];\n for (const [rawStart, rawEnd] of ranges) {\n const start = clamp(rawStart, 0, length);\n const end = clamp(rawEnd, start, length);\n if (start < end) {\n normalized.push([start, end]);\n }\n }\n normalized.sort((a, b) => a[0] - b[0]);\n\n const merged: [start: number, end: number][] = [];\n for (const range of normalized) {\n const previous = merged[merged.length - 1];\n if (previous !== undefined && range[0] <= previous[1]) {\n previous[1] = Math.max(previous[1], range[1]);\n continue;\n }\n merged.push(range);\n }\n return merged;\n}\n\nfunction rangeOverlaps(\n ranges: readonly [start: number, end: number][],\n start: number,\n end: number\n): boolean {\n let low = 0;\n let high = ranges.length;\n while (low < high) {\n const mid = low + Math.floor((high - low) / 2);\n if (ranges[mid][1] <= start) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n\n const range = ranges[low];\n return range !== undefined && range[0] < end;\n}\n\n// Keeps the table compact after repeated edits by joining neighboring pieces\n// that already point at contiguous text in the same backing buffer.\nfunction coalescePieces(pieces: Piece[]): Piece[] {\n const coalescedPieces: Piece[] = [];\n for (const piece of pieces) {\n if (piece.length === 0) {\n continue;\n }\n\n const previous = coalescedPieces[coalescedPieces.length - 1];\n if (\n previous !== undefined &&\n previous.source === piece.source &&\n previous.offset + previous.length === piece.offset\n ) {\n coalescedPieces[coalescedPieces.length - 1] = new Piece(\n previous.source,\n previous.offset,\n previous.length + piece.length,\n previous.lineOffsetStart,\n piece.lineOffsetEnd\n );\n continue;\n }\n\n coalescedPieces.push(piece);\n }\n return coalescedPieces;\n}\n\n// Returns the index of the first element in the array that is greater than the target.\nfunction upperBound(values: number[], target: number): number {\n let lo = 0;\n let hi = values.length;\n while (lo < hi) {\n const mid = lo + Math.floor((hi - lo) / 2);\n if (values[mid] <= target) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n return lo;\n}\n\nfunction escapeRegExp(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction isWordSeparatorCharCode(charCode: number): boolean {\n if (charCode <= 32 || charCode === 127) {\n return true;\n }\n const ch = String.fromCharCode(charCode);\n return WORD_SEPARATORS.includes(ch);\n}\n\n// Checks if the given text is a whole word by checking if the\n// characters before and after are word separators.\nfunction isWholeWordAtDocOffsets(\n docStart: number,\n length: number,\n docLength: number,\n charAt: (offset: number) => string\n): boolean {\n const beforeOk =\n docStart <= 0 ||\n isWordSeparatorCharCode(charCodeUnitAt(charAt, docStart - 1));\n const afterOk =\n docStart + length >= docLength ||\n isWordSeparatorCharCode(charCodeUnitAt(charAt, docStart + length));\n return beforeOk && afterOk;\n}\n\nfunction charCodeUnitAt(\n charAt: (offset: number) => string,\n offset: number\n): number {\n const unit = charAt(offset);\n return unit.length === 0 ? 0 : unit.charCodeAt(0);\n}\n\nfunction compileSearchRegExp(\n source: string,\n isRegex: boolean,\n caseSensitive: boolean\n): RegExp {\n const body = isRegex ? source : escapeRegExp(source);\n const flags = `g${caseSensitive ? '' : 'i'}${isRegex ? 'm' : ''}`;\n return new RegExp(body, flags);\n}\n\n/** Expands `$&`, `$1`, `$$`, etc. in a regex replace string using a match. */\nfunction expandReplaceString(\n replacement: string,\n match: RegExpExecArray\n): string {\n return replacement.replace(/\\$([$&]|\\d+)/g, (_token, group: string) => {\n if (group === '$') {\n return '$';\n }\n if (group === '&') {\n return match[0] ?? '';\n }\n const index = Number(group);\n return match[index] ?? '';\n });\n}\n\n/**\n * Builds the text to insert for one search match, including regex capture\n * substitution when regex mode is enabled.\n */\nexport function buildSearchReplacementText(\n positionAt: (offset: number) => Position,\n offsetAt: (position: Position) => number,\n getLineText: (line: number) => string,\n searchParams: SearchParams,\n matchStart: number,\n matchEnd: number\n): string {\n if (!searchParams.regex) {\n return searchParams.replaceText;\n }\n\n const position = positionAt(matchStart);\n const lineText = getLineText(position.line);\n const lineStart = offsetAt({ line: position.line, character: 0 });\n const relStart = matchStart - lineStart;\n const matched = lineText.slice(relStart, relStart + (matchEnd - matchStart));\n\n let pattern: RegExp;\n try {\n pattern = compileSearchRegExp(\n searchParams.text,\n true,\n searchParams.caseSensitive\n );\n } catch {\n return searchParams.replaceText;\n }\n\n const re = new RegExp(pattern.source, pattern.flags.replace('g', ''));\n const match = re.exec(matched);\n if (match === null || match[0].length !== matched.length) {\n return searchParams.replaceText;\n }\n return expandReplaceString(searchParams.replaceText, match);\n}\n\nfunction advancePastEmptyMatch(text: string, index: number): number {\n if (index + 1 < text.length) {\n const first = text.charCodeAt(index);\n const second = text.charCodeAt(index + 1);\n if (\n first >= 0xd800 &&\n first <= 0xdbff &&\n second >= 0xdc00 &&\n second <= 0xdfff\n ) {\n return index + 2;\n }\n }\n return index + 1;\n}\n"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
- import { TextDocument } from "./textDocument.js";
1
+ import { ResolvedTextEdit, TextDocument } from "./textDocument.js";
2
2
 
3
3
  //#region src/editor/searchPanel.d.ts
4
4
  type MatchRange = [startOffset: number, endOffset: number];
5
+ type SearchPanelMode = 'find' | 'replace';
5
6
  interface SearchParams {
6
7
  text: string;
7
8
  replaceText: string;
@@ -13,17 +14,25 @@ interface SearchPanelOptions {
13
14
  textDocument: TextDocument<unknown>;
14
15
  containerElement: HTMLElement;
15
16
  defaultQuery: string;
17
+ mode?: SearchPanelMode;
16
18
  initialMatch?: MatchRange;
17
19
  scrollToMatch: (nextMatch: MatchRange, retainFocus: boolean) => void;
18
- onUpdate: (matches: MatchRange[]) => MatchRange | undefined;
20
+ applyReplace: (edits: ResolvedTextEdit[]) => void;
21
+ onUpdate: (matches: MatchRange[], options?: {
22
+ syncSelection?: boolean;
23
+ }) => MatchRange | undefined;
19
24
  onClose: () => void;
20
25
  }
21
26
  declare class SearchPanelWidget {
22
27
  #private;
23
28
  constructor(options: SearchPanelOptions);
24
29
  focus(): void;
30
+ updateMatches(options?: {
31
+ syncSelection?: boolean;
32
+ }): void;
33
+ setMode(mode: SearchPanelMode): void;
25
34
  cleanup(): void;
26
35
  }
27
36
  //#endregion
28
- export { MatchRange, SearchPanelOptions, SearchPanelWidget, SearchParams };
37
+ export { MatchRange, SearchPanelMode, SearchPanelOptions, SearchPanelWidget, SearchParams };
29
38
  //# sourceMappingURL=searchPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"searchPanel.d.ts","names":["TextDocument","MatchRange","SearchParams","SearchPanelOptions","HTMLElement","SearchPanelWidget"],"sources":["../../src/editor/searchPanel.d.ts"],"sourcesContent":["import type { TextDocument } from './textDocument';\nexport type MatchRange = [startOffset: number, endOffset: number];\nexport interface SearchParams {\n text: string;\n replaceText: string;\n caseSensitive: boolean;\n wholeWord: boolean;\n regex: boolean;\n}\nexport interface SearchPanelOptions {\n textDocument: TextDocument<unknown>;\n containerElement: HTMLElement;\n defaultQuery: string;\n initialMatch?: MatchRange;\n scrollToMatch: (nextMatch: MatchRange, retainFocus: boolean) => void;\n onUpdate: (matches: MatchRange[]) => MatchRange | undefined;\n onClose: () => void;\n}\nexport declare class SearchPanelWidget {\n #private;\n constructor(options: SearchPanelOptions);\n focus(): void;\n cleanup(): void;\n}\n//# sourceMappingURL=searchPanel.d.ts.map"],"mappings":";;;KACYC,UAAAA;UACKC,YAAAA;EADLD,IAAAA,EAAAA,MAAAA;EACKC,WAAAA,EAAAA,MAAY;EAOZC,aAAAA,EAAAA,OAAkB;EACjBH,SAAAA,EAAAA,OAAAA;EACII,KAAAA,EAAAA,OAAAA;;AAGSH,UALdE,kBAAAA,CAKcF;EACPA,YAAAA,EALND,YAKMC,CAAAA,OAAAA,CAAAA;EAAiBA,gBAAAA,EAJnBG,WAImBH;EAAU,YAAA,EAAA,MAAA;EAG9BI,YAAAA,CAAAA,EALFJ,UAKmB;6BAJPA;sBACPA,iBAAiBA;;;cAGpBI,iBAAAA;;uBAEIF"}
1
+ {"version":3,"file":"searchPanel.d.ts","names":["ResolvedTextEdit","TextDocument","MatchRange","SearchPanelMode","SearchParams","SearchPanelOptions","HTMLElement","SearchPanelWidget"],"sources":["../../src/editor/searchPanel.d.ts"],"sourcesContent":["import type { ResolvedTextEdit, TextDocument } from './textDocument';\nexport type MatchRange = [startOffset: number, endOffset: number];\nexport type SearchPanelMode = 'find' | 'replace';\nexport interface SearchParams {\n text: string;\n replaceText: string;\n caseSensitive: boolean;\n wholeWord: boolean;\n regex: boolean;\n}\nexport interface SearchPanelOptions {\n textDocument: TextDocument<unknown>;\n containerElement: HTMLElement;\n defaultQuery: string;\n mode?: SearchPanelMode;\n initialMatch?: MatchRange;\n scrollToMatch: (nextMatch: MatchRange, retainFocus: boolean) => void;\n applyReplace: (edits: ResolvedTextEdit[]) => void;\n onUpdate: (matches: MatchRange[], options?: {\n syncSelection?: boolean;\n }) => MatchRange | undefined;\n onClose: () => void;\n}\nexport declare class SearchPanelWidget {\n #private;\n constructor(options: SearchPanelOptions);\n focus(): void;\n updateMatches(options?: {\n syncSelection?: boolean;\n }): void;\n setMode(mode: SearchPanelMode): void;\n cleanup(): void;\n}\n//# sourceMappingURL=searchPanel.d.ts.map"],"mappings":";;;KACYE,UAAAA;KACAC,eAAAA;AADAD,UAEKE,YAAAA,CAFK;EACVD,IAAAA,EAAAA,MAAAA;EACKC,WAAAA,EAAAA,MAAY;EAOZC,aAAAA,EAAAA,OAAkB;EACjBJ,SAAAA,EAAAA,OAAAA;EACIK,KAAAA,EAAAA,OAAAA;;AAGHJ,UALFG,kBAAAA,CAKEH;EACYA,YAAAA,EALbD,YAKaC,CAAAA,OAAAA,CAAAA;EACLF,gBAAAA,EALJM,WAKIN;EACFE,YAAAA,EAAAA,MAAAA;EAEdA,IAAAA,CAAAA,EANCC,eAMDD;EAAU,YAAA,CAAA,EALDA,UAKC;EAGCK,aAAAA,EAAAA,CAAAA,SAAiB,EAPPL,UASNG,EAAAA,WAAAA,EAAAA,OAKPF,EAAAA,GAAAA,IAAAA;wBAbQH;sBACFE;;QAEdA;;;cAGWK,iBAAAA;;uBAEIF;;;;;gBAKPF"}