@pierre/diffs 1.3.0-beta.5 → 1.3.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/dist/components/CodeView.d.ts +13 -11
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +53 -14
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +4 -5
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +37 -19
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +49 -36
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +173 -75
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/FileStream.d.ts +0 -1
- package/dist/components/FileStream.d.ts.map +1 -1
- package/dist/components/FileStream.js +4 -4
- package/dist/components/FileStream.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts +3 -3
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +7 -5
- package/dist/components/UnresolvedFile.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +0 -1
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +22 -25
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +12 -7
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +192 -64
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/components/Virtualizer.d.ts +1 -1
- package/dist/components/Virtualizer.d.ts.map +1 -1
- package/dist/components/Virtualizer.js +23 -24
- package/dist/components/Virtualizer.js.map +1 -1
- package/dist/components/VirtulizerDevelopment.d.ts.map +1 -1
- package/dist/components/web-components.d.ts.map +1 -1
- package/dist/components/web-components.js +2 -3
- package/dist/components/web-components.js.map +1 -1
- package/dist/constants.d.ts +3 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -2
- package/dist/constants.js.map +1 -1
- package/dist/editor/command.d.ts +2 -1
- package/dist/editor/command.d.ts.map +1 -1
- package/dist/editor/command.js +7 -3
- package/dist/editor/command.js.map +1 -1
- package/dist/editor/editStack.d.ts +7 -1
- package/dist/editor/editStack.d.ts.map +1 -1
- package/dist/editor/editStack.js +3 -3
- package/dist/editor/editStack.js.map +1 -1
- package/dist/editor/editor.d.ts +28 -4
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +669 -313
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/editor2.js +3 -3
- package/dist/editor/editor2.js.map +1 -1
- package/dist/editor/index.js +1 -2
- package/dist/editor/lineAnnotations.d.ts.map +1 -1
- package/dist/editor/lineAnnotations.js +2 -3
- package/dist/editor/lineAnnotations.js.map +1 -1
- package/dist/editor/marker.d.ts +2 -1
- package/dist/editor/marker.d.ts.map +1 -1
- package/dist/editor/marker.js +28 -11
- package/dist/editor/marker.js.map +1 -1
- package/dist/editor/pieceTable.d.ts +4 -2
- package/dist/editor/pieceTable.d.ts.map +1 -1
- package/dist/editor/pieceTable.js +138 -128
- package/dist/editor/pieceTable.js.map +1 -1
- package/dist/editor/platform.d.ts +8 -1
- package/dist/editor/platform.d.ts.map +1 -1
- package/dist/editor/platform.js +16 -5
- package/dist/editor/platform.js.map +1 -1
- package/dist/editor/searchPanel.d.ts +1 -0
- package/dist/editor/searchPanel.d.ts.map +1 -1
- package/dist/editor/searchPanel.js +75 -62
- package/dist/editor/searchPanel.js.map +1 -1
- package/dist/editor/selection.d.ts +42 -5
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +504 -114
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/selectionAction.d.ts +4 -5
- package/dist/editor/selectionAction.d.ts.map +1 -1
- package/dist/editor/selectionAction.js +14 -64
- package/dist/editor/selectionAction.js.map +1 -1
- package/dist/editor/sprite.d.ts +2 -2
- package/dist/editor/sprite.d.ts.map +1 -1
- package/dist/editor/sprite.js +7 -14
- package/dist/editor/sprite.js.map +1 -1
- package/dist/editor/textDocument.d.ts +5 -4
- package/dist/editor/textDocument.d.ts.map +1 -1
- package/dist/editor/textDocument.js +26 -15
- package/dist/editor/textDocument.js.map +1 -1
- package/dist/editor/textMeasure.d.ts +36 -3
- package/dist/editor/textMeasure.d.ts.map +1 -1
- package/dist/editor/textMeasure.js +104 -17
- package/dist/editor/textMeasure.js.map +1 -1
- package/dist/editor/tokenzier.d.ts +3 -0
- package/dist/editor/tokenzier.d.ts.map +1 -1
- package/dist/editor/tokenzier.js +27 -16
- package/dist/editor/tokenzier.js.map +1 -1
- package/dist/editor/utils.d.ts +4 -1
- package/dist/editor/utils.d.ts.map +1 -1
- package/dist/editor/utils.js +19 -3
- package/dist/editor/utils.js.map +1 -1
- package/dist/highlighter/languages/areLanguagesAttached.d.ts.map +1 -1
- package/dist/highlighter/languages/areLanguagesAttached.js +1 -2
- package/dist/highlighter/languages/areLanguagesAttached.js.map +1 -1
- package/dist/highlighter/languages/attachResolvedLanguages.d.ts +0 -2
- package/dist/highlighter/languages/attachResolvedLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/attachResolvedLanguages.js +1 -2
- package/dist/highlighter/languages/attachResolvedLanguages.js.map +1 -1
- package/dist/highlighter/languages/cleanUpResolvedLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/cleanUpResolvedLanguages.js +1 -2
- package/dist/highlighter/languages/cleanUpResolvedLanguages.js.map +1 -1
- package/dist/highlighter/languages/constants.d.ts +0 -1
- package/dist/highlighter/languages/constants.d.ts.map +1 -1
- package/dist/highlighter/languages/constants.js +1 -1
- package/dist/highlighter/languages/constants.js.map +1 -1
- package/dist/highlighter/languages/getResolvedLanguages.d.ts +0 -2
- package/dist/highlighter/languages/getResolvedLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/getResolvedLanguages.js +1 -2
- package/dist/highlighter/languages/getResolvedLanguages.js.map +1 -1
- package/dist/highlighter/languages/getResolvedOrResolveLanguage.d.ts +0 -2
- package/dist/highlighter/languages/getResolvedOrResolveLanguage.d.ts.map +1 -1
- package/dist/highlighter/languages/getResolvedOrResolveLanguage.js +1 -2
- package/dist/highlighter/languages/getResolvedOrResolveLanguage.js.map +1 -1
- package/dist/highlighter/languages/hasResolvedLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/hasResolvedLanguages.js +1 -2
- package/dist/highlighter/languages/hasResolvedLanguages.js.map +1 -1
- package/dist/highlighter/languages/registerCustomLanguage.d.ts +0 -1
- package/dist/highlighter/languages/registerCustomLanguage.d.ts.map +1 -1
- package/dist/highlighter/languages/registerCustomLanguage.js +1 -2
- package/dist/highlighter/languages/registerCustomLanguage.js.map +1 -1
- package/dist/highlighter/languages/resolveLanguage.d.ts +0 -2
- package/dist/highlighter/languages/resolveLanguage.d.ts.map +1 -1
- package/dist/highlighter/languages/resolveLanguage.js +4 -5
- package/dist/highlighter/languages/resolveLanguage.js.map +1 -1
- package/dist/highlighter/languages/resolveLanguages.d.ts +0 -2
- package/dist/highlighter/languages/resolveLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/resolveLanguages.js +1 -2
- package/dist/highlighter/languages/resolveLanguages.js.map +1 -1
- package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
- package/dist/highlighter/shared_highlighter.js +3 -4
- package/dist/highlighter/shared_highlighter.js.map +1 -1
- package/dist/highlighter/themes/areThemesAttached.d.ts.map +1 -1
- package/dist/highlighter/themes/areThemesAttached.js +1 -2
- package/dist/highlighter/themes/areThemesAttached.js.map +1 -1
- package/dist/highlighter/themes/attachResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/attachResolvedThemes.js +1 -2
- package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/cleanUpResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/cleanUpResolvedThemes.js +1 -2
- package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/constants.d.ts.map +1 -1
- package/dist/highlighter/themes/constants.js +1 -1
- package/dist/highlighter/themes/constants.js.map +1 -1
- package/dist/highlighter/themes/getResolvedOrResolveTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js +1 -2
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
- package/dist/highlighter/themes/getResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/getResolvedThemes.js +1 -2
- package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/hasResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/hasResolvedThemes.js +1 -2
- package/dist/highlighter/themes/hasResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/registerCustomCSSVariableTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/registerCustomCSSVariableTheme.js +1 -2
- package/dist/highlighter/themes/registerCustomCSSVariableTheme.js.map +1 -1
- package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/registerCustomTheme.js +1 -2
- package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/resolveTheme.js +1 -2
- package/dist/highlighter/themes/resolveTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/resolveThemes.js +1 -2
- package/dist/highlighter/themes/resolveThemes.js.map +1 -1
- package/dist/highlighter/themes/themeResolution.d.ts.map +1 -1
- package/dist/highlighter/themes/themeResolution.js +1 -2
- package/dist/highlighter/themes/themeResolution.js.map +1 -1
- package/dist/highlighter/themes/themeResolver.d.ts +2 -2
- package/dist/highlighter/themes/themeResolver.d.ts.map +1 -1
- package/dist/highlighter/themes/themeResolver.js +1 -2
- package/dist/highlighter/themes/themeResolver.js.map +1 -1
- package/dist/index.d.ts +12 -10
- package/dist/index.js +4 -3
- package/dist/managers/InteractionManager.d.ts +7 -0
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/InteractionManager.js +25 -4
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/managers/ResizeManager.d.ts.map +1 -1
- package/dist/managers/ResizeManager.js +1 -1
- package/dist/managers/ResizeManager.js.map +1 -1
- package/dist/managers/ScrollSyncManager.d.ts.map +1 -1
- package/dist/managers/ScrollSyncManager.js +1 -1
- package/dist/managers/ScrollSyncManager.js.map +1 -1
- package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
- package/dist/managers/UniversalRenderingManager.js +2 -2
- package/dist/managers/UniversalRenderingManager.js.map +1 -1
- package/dist/node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.d.ts +228 -0
- package/dist/node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.d.ts.map +1 -0
- package/dist/node_modules/.pnpm/@types_unist@3.0.3/node_modules/@types/unist/index.d.ts +84 -0
- package/dist/node_modules/.pnpm/@types_unist@3.0.3/node_modules/@types/unist/index.d.ts.map +1 -0
- package/dist/react/CodeView.d.ts +1 -1
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +17 -16
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/EditorContext.d.ts +0 -1
- package/dist/react/EditorContext.d.ts.map +1 -1
- package/dist/react/EditorContext.js +2 -5
- package/dist/react/EditorContext.js.map +1 -1
- package/dist/react/File.d.ts +1 -0
- package/dist/react/File.d.ts.map +1 -1
- package/dist/react/File.js +4 -6
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.d.ts +1 -0
- package/dist/react/FileDiff.d.ts.map +1 -1
- package/dist/react/FileDiff.js +4 -6
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.d.ts +4 -4
- package/dist/react/MultiFileDiff.d.ts.map +1 -1
- package/dist/react/MultiFileDiff.js +4 -6
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.d.ts +1 -0
- package/dist/react/PatchDiff.d.ts.map +1 -1
- package/dist/react/PatchDiff.js +4 -6
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/UnresolvedFile.d.ts +2 -1
- package/dist/react/UnresolvedFile.d.ts.map +1 -1
- package/dist/react/UnresolvedFile.js +4 -6
- package/dist/react/UnresolvedFile.js.map +1 -1
- package/dist/react/Virtualizer.d.ts.map +1 -1
- package/dist/react/Virtualizer.js +2 -5
- package/dist/react/Virtualizer.js.map +1 -1
- package/dist/react/WorkerPoolContext.d.ts +0 -1
- package/dist/react/WorkerPoolContext.d.ts.map +1 -1
- package/dist/react/WorkerPoolContext.js +2 -5
- package/dist/react/WorkerPoolContext.js.map +1 -1
- package/dist/react/constants.d.ts.map +1 -1
- package/dist/react/constants.js +1 -1
- package/dist/react/constants.js.map +1 -1
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +1 -2
- package/dist/react/jsx.d.ts +0 -2
- package/dist/react/jsx.d.ts.map +1 -1
- package/dist/react/types.d.ts +2 -0
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.d.ts +2 -0
- package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.js +18 -11
- package/dist/react/utils/renderDiffChildren.js.map +1 -1
- package/dist/react/utils/renderFileChildren.d.ts +2 -0
- package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
- package/dist/react/utils/renderFileChildren.js +18 -11
- package/dist/react/utils/renderFileChildren.js.map +1 -1
- package/dist/react/utils/templateRender.d.ts.map +1 -1
- package/dist/react/utils/templateRender.js +1 -2
- package/dist/react/utils/templateRender.js.map +1 -1
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +15 -18
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js +1 -2
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/react/utils/useStableCallback.d.ts.map +1 -1
- package/dist/react/utils/useStableCallback.js +1 -2
- package/dist/react/utils/useStableCallback.js.map +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.js +10 -11
- package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +2 -3
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +52 -33
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +1 -3
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +14 -11
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts +1 -2
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.js +1 -2
- package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
- package/dist/shiki-stream/index.js +1 -2
- package/dist/shiki-stream/stream.d.ts +0 -1
- package/dist/shiki-stream/stream.d.ts.map +1 -1
- package/dist/shiki-stream/stream.js +1 -2
- package/dist/shiki-stream/stream.js.map +1 -1
- package/dist/shiki-stream/tokenizer.d.ts.map +1 -1
- package/dist/shiki-stream/tokenizer.js +1 -1
- package/dist/shiki-stream/tokenizer.js.map +1 -1
- package/dist/shiki-stream/types.d.ts +0 -1
- package/dist/shiki-stream/types.d.ts.map +1 -1
- package/dist/sprite.d.ts.map +1 -1
- package/dist/sprite.js +1 -1
- package/dist/ssr/FileDiffReact.d.ts.map +1 -1
- package/dist/ssr/FileDiffReact.js +5 -8
- package/dist/ssr/FileDiffReact.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -2
- package/dist/ssr/index.js +1 -2
- package/dist/ssr/preloadDiffs.d.ts +12 -11
- package/dist/ssr/preloadDiffs.d.ts.map +1 -1
- package/dist/ssr/preloadDiffs.js +15 -8
- package/dist/ssr/preloadDiffs.js.map +1 -1
- package/dist/ssr/preloadFile.d.ts.map +1 -1
- package/dist/ssr/preloadFile.js +1 -2
- package/dist/ssr/preloadFile.js.map +1 -1
- package/dist/ssr/preloadPatchFile.d.ts.map +1 -1
- package/dist/ssr/preloadPatchFile.js +2 -3
- package/dist/ssr/preloadPatchFile.js.map +1 -1
- package/dist/ssr/renderHTML.d.ts +1 -1
- package/dist/ssr/renderHTML.d.ts.map +1 -1
- package/dist/ssr/renderHTML.js +1 -2
- package/dist/ssr/renderHTML.js.map +1 -1
- package/dist/string-import.d.ts +4 -0
- package/dist/string-import.d.ts.map +1 -1
- package/dist/style.js +3 -3
- package/dist/style.js.map +1 -1
- package/dist/types.d.ts +67 -7
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/areDiffLineAnnotationsEqual.d.ts.map +1 -1
- package/dist/utils/areDiffLineAnnotationsEqual.js +1 -1
- package/dist/utils/areDiffLineAnnotationsEqual.js.map +1 -1
- package/dist/utils/areDiffRenderOptionsEqual.d.ts.map +1 -1
- package/dist/utils/areDiffRenderOptionsEqual.js +1 -2
- package/dist/utils/areDiffRenderOptionsEqual.js.map +1 -1
- package/dist/utils/areDiffTargetsEqual.d.ts.map +1 -1
- package/dist/utils/areDiffTargetsEqual.js +1 -1
- package/dist/utils/areDiffTargetsEqual.js.map +1 -1
- package/dist/utils/areFileRenderOptionsEqual.d.ts.map +1 -1
- package/dist/utils/areFileRenderOptionsEqual.js +1 -2
- package/dist/utils/areFileRenderOptionsEqual.js.map +1 -1
- package/dist/utils/areFilesEqual.d.ts.map +1 -1
- package/dist/utils/areFilesEqual.js +1 -1
- package/dist/utils/areFilesEqual.js.map +1 -1
- package/dist/utils/areHunkDataEqual.d.ts.map +1 -1
- package/dist/utils/areHunkDataEqual.js +2 -2
- package/dist/utils/areHunkDataEqual.js.map +1 -1
- package/dist/utils/areLineAnnotationsEqual.d.ts.map +1 -1
- package/dist/utils/areLineAnnotationsEqual.js +1 -1
- package/dist/utils/areLineAnnotationsEqual.js.map +1 -1
- package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
- package/dist/utils/areManagedSnapshotsEqual.js +1 -1
- package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
- package/dist/utils/areMergeConflictActionsEqual.d.ts.map +1 -1
- package/dist/utils/areMergeConflictActionsEqual.js +1 -1
- package/dist/utils/areMergeConflictActionsEqual.js.map +1 -1
- package/dist/utils/areObjectsEqual.d.ts.map +1 -1
- package/dist/utils/areObjectsEqual.js +1 -1
- package/dist/utils/areObjectsEqual.js.map +1 -1
- package/dist/utils/areOptionsEqual.d.ts +0 -2
- package/dist/utils/areOptionsEqual.d.ts.map +1 -1
- package/dist/utils/areOptionsEqual.js +1 -2
- package/dist/utils/areOptionsEqual.js.map +1 -1
- package/dist/utils/arePrePropertiesEqual.d.ts.map +1 -1
- package/dist/utils/arePrePropertiesEqual.js +1 -1
- package/dist/utils/arePrePropertiesEqual.js.map +1 -1
- package/dist/utils/areRenderRangesEqual.d.ts.map +1 -1
- package/dist/utils/areRenderRangesEqual.js +1 -1
- package/dist/utils/areRenderRangesEqual.js.map +1 -1
- package/dist/utils/areSelectionPointsEqual.d.ts.map +1 -1
- package/dist/utils/areSelectionPointsEqual.js +1 -1
- package/dist/utils/areSelectionPointsEqual.js.map +1 -1
- package/dist/utils/areSelectionsEqual.d.ts.map +1 -1
- package/dist/utils/areSelectionsEqual.js +1 -1
- package/dist/utils/areSelectionsEqual.js.map +1 -1
- package/dist/utils/areThemesEqual.d.ts.map +1 -1
- package/dist/utils/areThemesEqual.js +1 -1
- package/dist/utils/areThemesEqual.js.map +1 -1
- package/dist/utils/areVirtualWindowSpecsEqual.d.ts.map +1 -1
- package/dist/utils/areVirtualWindowSpecsEqual.js +1 -1
- package/dist/utils/areVirtualWindowSpecsEqual.js.map +1 -1
- package/dist/utils/areWorkerStatsEqual.d.ts +0 -2
- package/dist/utils/areWorkerStatsEqual.d.ts.map +1 -1
- package/dist/utils/areWorkerStatsEqual.js +1 -1
- package/dist/utils/areWorkerStatsEqual.js.map +1 -1
- package/dist/utils/awaitWithTimeout.d.ts +5 -0
- package/dist/utils/awaitWithTimeout.d.ts.map +1 -0
- package/dist/utils/awaitWithTimeout.js +15 -0
- package/dist/utils/awaitWithTimeout.js.map +1 -0
- package/dist/utils/cleanLastNewline.d.ts.map +1 -1
- package/dist/utils/cleanLastNewline.js +1 -1
- package/dist/utils/cleanLastNewline.js.map +1 -1
- package/dist/utils/cloneFileDiffMetadata.d.ts +7 -0
- package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -0
- package/dist/utils/cloneFileDiffMetadata.js +16 -0
- package/dist/utils/cloneFileDiffMetadata.js.map +1 -0
- package/dist/utils/computeEstimatedDiffHeights.d.ts +3 -1
- package/dist/utils/computeEstimatedDiffHeights.d.ts.map +1 -1
- package/dist/utils/computeEstimatedDiffHeights.js +9 -3
- package/dist/utils/computeEstimatedDiffHeights.js.map +1 -1
- package/dist/utils/computeFileOffsets.d.ts +9 -1
- package/dist/utils/computeFileOffsets.d.ts.map +1 -1
- package/dist/utils/computeFileOffsets.js +20 -2
- package/dist/utils/computeFileOffsets.js.map +1 -1
- package/dist/utils/computeVirtualFileMetrics.d.ts.map +1 -1
- package/dist/utils/computeVirtualFileMetrics.js +1 -2
- package/dist/utils/computeVirtualFileMetrics.js.map +1 -1
- package/dist/utils/createAnnotationElement.d.ts +1 -1
- package/dist/utils/createAnnotationElement.d.ts.map +1 -1
- package/dist/utils/createAnnotationElement.js +1 -2
- package/dist/utils/createAnnotationElement.js.map +1 -1
- package/dist/utils/createAnnotationWrapperNode.d.ts.map +1 -1
- package/dist/utils/createAnnotationWrapperNode.js +1 -1
- package/dist/utils/createAnnotationWrapperNode.js.map +1 -1
- package/dist/utils/createContentColumn.d.ts +1 -1
- package/dist/utils/createContentColumn.d.ts.map +1 -1
- package/dist/utils/createContentColumn.js +1 -2
- package/dist/utils/createContentColumn.js.map +1 -1
- package/dist/utils/createEmptyRowBuffer.d.ts +1 -1
- package/dist/utils/createEmptyRowBuffer.d.ts.map +1 -1
- package/dist/utils/createEmptyRowBuffer.js +1 -2
- package/dist/utils/createEmptyRowBuffer.js.map +1 -1
- package/dist/utils/createFileHeaderElement.d.ts +1 -1
- package/dist/utils/createFileHeaderElement.d.ts.map +1 -1
- package/dist/utils/createFileHeaderElement.js +6 -3
- package/dist/utils/createFileHeaderElement.js.map +1 -1
- package/dist/utils/createGutterUtilityContentNode.d.ts.map +1 -1
- package/dist/utils/createGutterUtilityContentNode.js +1 -1
- package/dist/utils/createGutterUtilityContentNode.js.map +1 -1
- package/dist/utils/createGutterUtilityElement.d.ts +1 -1
- package/dist/utils/createGutterUtilityElement.d.ts.map +1 -1
- package/dist/utils/createGutterUtilityElement.js +1 -2
- package/dist/utils/createGutterUtilityElement.js.map +1 -1
- package/dist/utils/createNoNewlineElement.d.ts +1 -1
- package/dist/utils/createNoNewlineElement.d.ts.map +1 -1
- package/dist/utils/createNoNewlineElement.js +1 -2
- package/dist/utils/createNoNewlineElement.js.map +1 -1
- package/dist/utils/createPreElement.d.ts +1 -1
- package/dist/utils/createPreElement.d.ts.map +1 -1
- package/dist/utils/createPreElement.js +1 -3
- package/dist/utils/createPreElement.js.map +1 -1
- package/dist/utils/createRowNodes.d.ts.map +1 -1
- package/dist/utils/createRowNodes.js +1 -1
- package/dist/utils/createRowNodes.js.map +1 -1
- package/dist/utils/createSeparator.d.ts +1 -1
- package/dist/utils/createSeparator.d.ts.map +1 -1
- package/dist/utils/createSeparator.js +1 -2
- package/dist/utils/createSeparator.js.map +1 -1
- package/dist/utils/createSpanNodeFromToken.d.ts.map +1 -1
- package/dist/utils/createSpanNodeFromToken.js +1 -2
- package/dist/utils/createSpanNodeFromToken.js.map +1 -1
- package/dist/utils/createStyleElement.d.ts +1 -1
- package/dist/utils/createStyleElement.d.ts.map +1 -1
- package/dist/utils/createStyleElement.js +1 -2
- package/dist/utils/createStyleElement.js.map +1 -1
- package/dist/utils/createTransformerWithState.d.ts.map +1 -1
- package/dist/utils/createTransformerWithState.js +1 -2
- package/dist/utils/createTransformerWithState.js.map +1 -1
- package/dist/utils/createUnsafeCSSStyleNode.d.ts.map +1 -1
- package/dist/utils/createUnsafeCSSStyleNode.js +1 -2
- package/dist/utils/createUnsafeCSSStyleNode.js.map +1 -1
- package/dist/utils/createWindowFromScrollPosition.d.ts.map +1 -1
- package/dist/utils/createWindowFromScrollPosition.js +5 -5
- package/dist/utils/createWindowFromScrollPosition.js.map +1 -1
- package/dist/utils/cssWrappers.d.ts.map +1 -1
- package/dist/utils/cssWrappers.js +2 -3
- package/dist/utils/cssWrappers.js.map +1 -1
- package/dist/utils/detachString.d.ts.map +1 -1
- package/dist/utils/detachString.js +1 -1
- package/dist/utils/detachString.js.map +1 -1
- package/dist/utils/diffAcceptRejectHunk.d.ts.map +1 -1
- package/dist/utils/diffAcceptRejectHunk.js +1 -2
- package/dist/utils/diffAcceptRejectHunk.js.map +1 -1
- package/dist/utils/formatCSSVariablePrefix.d.ts.map +1 -1
- package/dist/utils/formatCSSVariablePrefix.js +1 -1
- package/dist/utils/formatCSSVariablePrefix.js.map +1 -1
- package/dist/utils/getDiffFileInput.d.ts +14 -0
- package/dist/utils/getDiffFileInput.d.ts.map +1 -0
- package/dist/utils/getDiffFileInput.js +24 -0
- package/dist/utils/getDiffFileInput.js.map +1 -0
- package/dist/utils/getDiffHunksRendererOptions.d.ts.map +1 -1
- package/dist/utils/getDiffHunksRendererOptions.js +2 -1
- package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
- package/dist/utils/getFileRendererOptions.d.ts.map +1 -1
- package/dist/utils/getFileRendererOptions.js +1 -1
- package/dist/utils/getFileRendererOptions.js.map +1 -1
- package/dist/utils/getFiletypeFromFileName.d.ts.map +1 -1
- package/dist/utils/getFiletypeFromFileName.js +3 -1
- package/dist/utils/getFiletypeFromFileName.js.map +1 -1
- package/dist/utils/getHighlighterOptions.d.ts.map +1 -1
- package/dist/utils/getHighlighterOptions.js +1 -2
- package/dist/utils/getHighlighterOptions.js.map +1 -1
- package/dist/utils/getHighlighterThemeStyles.d.ts.map +1 -1
- package/dist/utils/getHighlighterThemeStyles.js +1 -2
- package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
- package/dist/utils/getHunkSeparatorSlotName.d.ts.map +1 -1
- package/dist/utils/getHunkSeparatorSlotName.js +1 -1
- package/dist/utils/getHunkSeparatorSlotName.js.map +1 -1
- package/dist/utils/getIconForType.d.ts.map +1 -1
- package/dist/utils/getIconForType.js +1 -1
- package/dist/utils/getIconForType.js.map +1 -1
- package/dist/utils/getLineAnnotationName.d.ts.map +1 -1
- package/dist/utils/getLineAnnotationName.js +1 -1
- package/dist/utils/getLineAnnotationName.js.map +1 -1
- package/dist/utils/getLineEndingType.d.ts.map +1 -1
- package/dist/utils/getLineEndingType.js +1 -1
- package/dist/utils/getLineEndingType.js.map +1 -1
- package/dist/utils/getLineNodes.d.ts +1 -1
- package/dist/utils/getLineNodes.d.ts.map +1 -1
- package/dist/utils/getLineNodes.js +1 -1
- package/dist/utils/getLineNodes.js.map +1 -1
- package/dist/utils/getMergeConflictActionSlotName.d.ts.map +1 -1
- package/dist/utils/getMergeConflictActionSlotName.js +1 -1
- package/dist/utils/getMergeConflictActionSlotName.js.map +1 -1
- package/dist/utils/getMergeConflictLineTypes.d.ts.map +1 -1
- package/dist/utils/getMergeConflictLineTypes.js +1 -2
- package/dist/utils/getMergeConflictLineTypes.js.map +1 -1
- package/dist/utils/getOrCreateCodeNode.d.ts.map +1 -1
- package/dist/utils/getOrCreateCodeNode.js +1 -1
- package/dist/utils/getOrCreateCodeNode.js.map +1 -1
- package/dist/utils/getSingularPatch.d.ts.map +1 -1
- package/dist/utils/getSingularPatch.js +1 -2
- package/dist/utils/getSingularPatch.js.map +1 -1
- package/dist/utils/getThemes.d.ts.map +1 -1
- package/dist/utils/getThemes.js +1 -2
- package/dist/utils/getThemes.js.map +1 -1
- package/dist/utils/getTotalLineCountFromHunks.d.ts.map +1 -1
- package/dist/utils/getTotalLineCountFromHunks.js +1 -1
- package/dist/utils/getTotalLineCountFromHunks.js.map +1 -1
- package/dist/utils/hast_utils.d.ts +1 -1
- package/dist/utils/hast_utils.d.ts.map +1 -1
- package/dist/utils/hast_utils.js +1 -1
- package/dist/utils/hast_utils.js.map +1 -1
- package/dist/utils/hostTheme.d.ts.map +1 -1
- package/dist/utils/hostTheme.js +1 -2
- package/dist/utils/hostTheme.js.map +1 -1
- package/dist/utils/hydratePartialDiff.d.ts +10 -0
- package/dist/utils/hydratePartialDiff.d.ts.map +1 -0
- package/dist/utils/hydratePartialDiff.js +140 -0
- package/dist/utils/hydratePartialDiff.js.map +1 -0
- package/dist/utils/includesFileAnnotations.d.ts.map +1 -1
- package/dist/utils/includesFileAnnotations.js +5 -5
- package/dist/utils/includesFileAnnotations.js.map +1 -1
- package/dist/utils/isDefaultRenderRange.d.ts.map +1 -1
- package/dist/utils/isDefaultRenderRange.js +1 -1
- package/dist/utils/isDefaultRenderRange.js.map +1 -1
- package/dist/utils/isDiffPlainText.d.ts.map +1 -1
- package/dist/utils/isDiffPlainText.js +1 -2
- package/dist/utils/isDiffPlainText.js.map +1 -1
- package/dist/utils/isFilePlainText.d.ts.map +1 -1
- package/dist/utils/isFilePlainText.js +1 -2
- package/dist/utils/isFilePlainText.js.map +1 -1
- package/dist/utils/isStyleNode.d.ts.map +1 -1
- package/dist/utils/isStyleNode.js +1 -1
- package/dist/utils/isStyleNode.js.map +1 -1
- package/dist/utils/isWorkerContext.d.ts.map +1 -1
- package/dist/utils/isWorkerContext.js +1 -1
- package/dist/utils/isWorkerContext.js.map +1 -1
- package/dist/utils/iterateOverDiff.d.ts.map +1 -1
- package/dist/utils/iterateOverDiff.js +47 -48
- package/dist/utils/iterateOverDiff.js.map +1 -1
- package/dist/utils/normalizeDiffResolution.d.ts.map +1 -1
- package/dist/utils/normalizeDiffResolution.js +1 -1
- package/dist/utils/normalizeDiffResolution.js.map +1 -1
- package/dist/utils/parseDiffDecorations.d.ts.map +1 -1
- package/dist/utils/parseDiffDecorations.js +1 -2
- package/dist/utils/parseDiffDecorations.js.map +1 -1
- package/dist/utils/parseDiffFromFile.d.ts +1 -2
- package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseDiffFromFile.js +27 -7
- package/dist/utils/parseDiffFromFile.js.map +1 -1
- package/dist/utils/parseLineType.d.ts.map +1 -1
- package/dist/utils/parseLineType.js +1 -1
- package/dist/utils/parseLineType.js.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.js +5 -5
- package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
- package/dist/utils/parsePatchFiles.d.ts.map +1 -1
- package/dist/utils/parsePatchFiles.js +6 -7
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/prefersReducedMotion.d.ts.map +1 -1
- package/dist/utils/prefersReducedMotion.js +1 -1
- package/dist/utils/prefersReducedMotion.js.map +1 -1
- package/dist/utils/prerenderHTMLIfNecessary.d.ts.map +1 -1
- package/dist/utils/prerenderHTMLIfNecessary.js +1 -1
- package/dist/utils/prerenderHTMLIfNecessary.js.map +1 -1
- package/dist/utils/processLine.d.ts +1 -1
- package/dist/utils/processLine.d.ts.map +1 -1
- package/dist/utils/processLine.js +1 -2
- package/dist/utils/processLine.js.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.d.ts.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.js +4 -5
- package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
- package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
- package/dist/utils/renderFileWithHighlighter.js +1 -2
- package/dist/utils/renderFileWithHighlighter.js.map +1 -1
- package/dist/utils/resolveConflict.d.ts.map +1 -1
- package/dist/utils/resolveConflict.js +1 -2
- package/dist/utils/resolveConflict.js.map +1 -1
- package/dist/utils/resolveRegion.d.ts.map +1 -1
- package/dist/utils/resolveRegion.js +1 -1
- package/dist/utils/resolveRegion.js.map +1 -1
- package/dist/utils/roundToDevicePixel.d.ts.map +1 -1
- package/dist/utils/roundToDevicePixel.js +1 -1
- package/dist/utils/roundToDevicePixel.js.map +1 -1
- package/dist/utils/scrollbarGutter.d.ts.map +1 -1
- package/dist/utils/scrollbarGutter.js +1 -2
- package/dist/utils/scrollbarGutter.js.map +1 -1
- package/dist/utils/setLanguageOverride.d.ts.map +1 -1
- package/dist/utils/setLanguageOverride.js +1 -1
- package/dist/utils/setLanguageOverride.js.map +1 -1
- package/dist/utils/setWrapperNodeProps.d.ts.map +1 -1
- package/dist/utils/setWrapperNodeProps.js +1 -2
- package/dist/utils/setWrapperNodeProps.js.map +1 -1
- package/dist/utils/shouldUseTokenTransformer.d.ts.map +1 -1
- package/dist/utils/shouldUseTokenTransformer.js +1 -1
- package/dist/utils/shouldUseTokenTransformer.js.map +1 -1
- package/dist/utils/splitFileContents.d.ts.map +1 -1
- package/dist/utils/splitFileContents.js +1 -2
- package/dist/utils/splitFileContents.js.map +1 -1
- package/dist/utils/trimPatchContext.d.ts.map +1 -1
- package/dist/utils/trimPatchContext.js +1 -2
- package/dist/utils/trimPatchContext.js.map +1 -1
- package/dist/utils/updateDiffHunks.d.ts +6 -1
- package/dist/utils/updateDiffHunks.d.ts.map +1 -1
- package/dist/utils/updateDiffHunks.js +44 -3
- package/dist/utils/updateDiffHunks.js.map +1 -1
- package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
- package/dist/utils/virtualDiffLayout.js +1 -2
- package/dist/utils/virtualDiffLayout.js.map +1 -1
- package/dist/utils/wrapTokenFragments.d.ts +1 -1
- package/dist/utils/wrapTokenFragments.d.ts.map +1 -1
- package/dist/utils/wrapTokenFragments.js +1 -2
- package/dist/utils/wrapTokenFragments.js.map +1 -1
- package/dist/worker/WorkerPoolManager.d.ts +7 -2
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +83 -20
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/getOrCreateWorkerPoolSingleton.d.ts.map +1 -1
- package/dist/worker/getOrCreateWorkerPoolSingleton.js +1 -2
- package/dist/worker/getOrCreateWorkerPoolSingleton.js.map +1 -1
- package/dist/worker/index.d.ts +2 -2
- package/dist/worker/index.js +1 -2
- package/dist/worker/types.d.ts +7 -1
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/wasm-B9ZqxnKj.js +8 -0
- package/dist/worker/wasm-B9ZqxnKj.js.map +1 -0
- package/dist/worker/worker-portable.js +2784 -6406
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +94 -126
- package/dist/worker/worker.js.map +1 -1
- package/package.json +13 -14
- package/dist/worker/wasm-qE0LgnY3.js +0 -10
- package/dist/worker/wasm-qE0LgnY3.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Virtualizer.js","names":["DEFAULT_VIRTUALIZER_CONFIG: VirtualizerConfig","instance","top","bestAnchor: ScrollAnchor | undefined","fileOffset: number","fileTypeOffset: 'top' | 'bottom'","bestLineIndex: string | undefined","bestLineOffset: number | undefined"],"sources":["../../src/components/Virtualizer.ts"],"sourcesContent":["import { queueRender } from '../managers/UniversalRenderingManager';\nimport type { VirtualWindowSpecs } from '../types';\nimport { areVirtualWindowSpecsEqual } from '../utils/areVirtualWindowSpecsEqual';\nimport { createWindowFromScrollPosition } from '../utils/createWindowFromScrollPosition';\n\ninterface SubscribedInstance {\n onRender(dirty: boolean): boolean;\n reconcileHeights(): boolean;\n setVisibility(visible: boolean): void;\n}\n\ninterface ScrollAnchor {\n fileElement: HTMLElement;\n fileTypeOffset: 'top' | 'bottom';\n fileOffset: number;\n lineIndex: string | undefined;\n lineOffset: number | undefined;\n}\n\n// 800 seems like the healthy overscan required to\n// keep safari from blanking... if we catch it tho, maybe 900\nconst DEFAULT_OVERSCROLL_SIZE = 1000;\nconst INTERSECTION_OBSERVER_MARGIN = DEFAULT_OVERSCROLL_SIZE * 4;\nconst INTERSECTION_OBSERVER_THRESHOLD = [0, 0.000001, 0.99999, 1];\n\nexport interface VirtualizerConfig {\n /** Extra pixels rendered above and below the viewport to reduce blanking during fast scrolls. */\n overscrollSize: number;\n /** Margin used by IntersectionObserver to decide when items should be considered visible. */\n intersectionObserverMargin: number;\n /** Enables noisy resize logs to help tune metrics and investigate scroll jitter. */\n resizeDebugging: boolean;\n}\n\nconst DEFAULT_VIRTUALIZER_CONFIG: VirtualizerConfig = {\n overscrollSize: DEFAULT_OVERSCROLL_SIZE,\n intersectionObserverMargin: INTERSECTION_OBSERVER_MARGIN,\n resizeDebugging: false,\n};\n\nlet lastSize = 0;\n\nlet instance = -1;\n\nexport class Virtualizer {\n static __STOP: boolean = false;\n static __lastScrollPosition = 0;\n\n public readonly __id: string = `virtualizer-${++instance}`;\n public readonly config: VirtualizerConfig;\n public type = 'simple' as const;\n private intersectionObserver: IntersectionObserver | undefined;\n private scrollTop: number = 0;\n private height: number = 0;\n private scrollHeight: number = 0;\n private windowSpecs: VirtualWindowSpecs = { top: 0, bottom: 0 };\n private root: HTMLElement | Document | undefined;\n private contentContainer: HTMLElement | undefined;\n\n private resizeObserver: ResizeObserver | undefined;\n private observers: Map<HTMLElement, SubscribedInstance> = new Map();\n private visibleInstances: Map<HTMLElement, SubscribedInstance> = new Map();\n private visibleInstancesDirty: boolean = false;\n private instancesChanged: Set<SubscribedInstance> = new Set();\n\n private scrollDirty = true;\n private heightDirty = true;\n private scrollHeightDirty = true;\n private renderedObservers = 0;\n private connectQueue: Map<HTMLElement, SubscribedInstance> = new Map();\n\n constructor(config?: Partial<VirtualizerConfig>) {\n this.config = { ...DEFAULT_VIRTUALIZER_CONFIG, ...config };\n }\n\n setup(root: HTMLElement | Document, contentContainer?: Element): void {\n if (this.root != null) {\n return;\n }\n this.root = root;\n this.resizeObserver = new ResizeObserver(this.handleContainerResize);\n this.intersectionObserver = new IntersectionObserver(\n this.handleIntersectionChange,\n {\n root: this.root,\n threshold: INTERSECTION_OBSERVER_THRESHOLD,\n rootMargin: `${this.config.intersectionObserverMargin}px 0px ${this.config.intersectionObserverMargin}px 0px`,\n // FIXME(amadeus): Figure out the other settings we'll want in here, or\n // if we should make them configurable...\n }\n );\n if (root instanceof Document) {\n this.setupWindow();\n } else {\n this.setupElement(contentContainer);\n }\n\n // FIXME(amadeus): Remove me before release\n window.__INSTANCE = this;\n window.__TOGGLE = () => {\n if (Virtualizer.__STOP) {\n Virtualizer.__STOP = false;\n const scroller = this.getScrollContainerElement() ?? window;\n scroller.scrollTo({ top: Virtualizer.__lastScrollPosition });\n queueRender(this.computeRenderRangeAndEmit);\n } else {\n Virtualizer.__lastScrollPosition = this.getScrollTop();\n Virtualizer.__STOP = true;\n }\n };\n for (const [container, instance] of this.connectQueue.entries()) {\n this.connect(container, instance);\n }\n this.connectQueue.clear();\n this.markDOMDirty();\n queueRender(this.computeRenderRangeAndEmit);\n }\n\n instanceChanged(instance: SubscribedInstance, domDirty: boolean): void {\n this.instancesChanged.add(instance);\n if (domDirty) {\n this.markDOMDirty();\n }\n queueRender(this.computeRenderRangeAndEmit);\n }\n\n getWindowSpecs(): VirtualWindowSpecs {\n if (this.windowSpecs.top === 0 && this.windowSpecs.bottom === 0) {\n this.windowSpecs = createWindowFromScrollPosition({\n scrollTop: this.getScrollTop(),\n height: this.getHeight(),\n scrollHeight: this.getScrollHeight(),\n overscrollSize: this.config.overscrollSize,\n });\n }\n return this.windowSpecs;\n }\n\n isInstanceVisible(elementTop: number, elementHeight: number): boolean {\n const scrollTop = this.getScrollTop();\n const height = this.getHeight();\n const margin = this.config.intersectionObserverMargin;\n const top = scrollTop - margin;\n const bottom = scrollTop + height + margin;\n return !(elementTop < top - elementHeight || elementTop > bottom);\n }\n\n private handleContainerResize = (entries: ResizeObserverEntry[]) => {\n if (this.root == null) return;\n let shouldQueueUpdate = false;\n for (const entry of entries) {\n const blockSize = entry.borderBoxSize[0].blockSize;\n if (this.root instanceof Document) {\n if (blockSize !== this.scrollHeight) {\n this.scrollHeightDirty = true;\n shouldQueueUpdate = true;\n if (this.config.resizeDebugging) {\n console.log('Virtualizer: content size change', this.__id, {\n sizeChange: blockSize - lastSize,\n newSize: blockSize,\n });\n lastSize = blockSize;\n }\n }\n } else {\n if (entry.target === this.root) {\n if (blockSize !== this.height) {\n this.heightDirty = true;\n shouldQueueUpdate = true;\n }\n } else if (entry.target === this.contentContainer) {\n this.scrollHeightDirty = true;\n shouldQueueUpdate = true;\n if (this.config.resizeDebugging) {\n console.log('Virtualizer: scroller size change', this.__id, {\n sizeChange: blockSize - lastSize,\n newSize: blockSize,\n });\n lastSize = blockSize;\n }\n }\n }\n }\n\n if (shouldQueueUpdate) {\n queueRender(this.computeRenderRangeAndEmit);\n }\n };\n\n private setupWindow() {\n if (this.root == null || !(this.root instanceof Document)) {\n throw new Error('Virtualizer.setupWindow: Invalid setup method');\n }\n window.addEventListener('scroll', this.handleWindowScroll, {\n passive: true,\n });\n window.addEventListener('resize', this.handleWindowResize, {\n passive: true,\n });\n this.resizeObserver?.observe(this.root.documentElement);\n }\n\n private setupElement(contentContainer: Element | undefined) {\n if (this.root == null || this.root instanceof Document) {\n throw new Error('Virtualizer.setupElement: Invalid setup method');\n }\n this.root.addEventListener('scroll', this.handleElementScroll, {\n passive: true,\n });\n this.resizeObserver?.observe(this.root);\n contentContainer ??= this.root.firstElementChild ?? undefined;\n if (contentContainer instanceof HTMLElement) {\n this.contentContainer = contentContainer;\n this.resizeObserver?.observe(contentContainer);\n }\n }\n\n cleanUp(): void {\n this.resizeObserver?.disconnect();\n this.resizeObserver = undefined;\n this.intersectionObserver?.disconnect();\n this.intersectionObserver = undefined;\n this.root?.removeEventListener('scroll', this.handleElementScroll);\n window.removeEventListener('scroll', this.handleWindowScroll);\n window.removeEventListener('resize', this.handleWindowResize);\n this.root = undefined;\n this.contentContainer = undefined;\n this.observers.clear();\n this.visibleInstances.clear();\n this.instancesChanged.clear();\n this.connectQueue.clear();\n this.visibleInstancesDirty = false;\n this.windowSpecs = { top: 0, bottom: 0 };\n this.scrollTop = 0;\n this.height = 0;\n this.scrollHeight = 0;\n }\n\n getOffsetInScrollContainer(element: HTMLElement): number {\n return (\n this.getScrollTop() +\n getRelativeBoundingTop(element, this.getScrollContainerElement())\n );\n }\n\n connect(container: HTMLElement, instance: SubscribedInstance): () => void {\n if (this.observers.has(container)) {\n throw new Error('Virtualizer.connect: instance is already connected...');\n }\n // If we are racing against the intersectionObserver, then we should just\n // queue up the connection for when the observer does get set up\n if (this.intersectionObserver == null) {\n this.connectQueue.set(container, instance);\n } else {\n // FIXME(amadeus): Go through the connection phase a bit more closely...\n this.intersectionObserver.observe(container);\n this.observers.set(container, instance);\n this.instancesChanged.add(instance);\n this.markDOMDirty();\n queueRender(this.computeRenderRangeAndEmit);\n }\n return () => this.disconnect(container);\n }\n\n disconnect(container: HTMLElement): void {\n const instance = this.observers.get(container);\n this.connectQueue.delete(container);\n if (instance == null) {\n return;\n }\n this.intersectionObserver?.unobserve(container);\n this.observers.delete(container);\n if (this.visibleInstances.delete(container)) {\n this.visibleInstancesDirty = true;\n }\n this.markDOMDirty();\n queueRender(this.computeRenderRangeAndEmit);\n }\n\n private handleWindowResize = () => {\n if (Virtualizer.__STOP || window.innerHeight === this.height) {\n return;\n }\n this.heightDirty = true;\n queueRender(this.computeRenderRangeAndEmit);\n };\n\n private handleWindowScroll = () => {\n if (\n Virtualizer.__STOP ||\n this.root == null ||\n !(this.root instanceof Document)\n ) {\n return;\n }\n this.scrollDirty = true;\n queueRender(this.computeRenderRangeAndEmit);\n };\n\n private handleElementScroll = () => {\n if (\n Virtualizer.__STOP ||\n this.root == null ||\n this.root instanceof Document\n ) {\n return;\n }\n this.scrollDirty = true;\n queueRender(this.computeRenderRangeAndEmit);\n };\n\n private computeRenderRangeAndEmit = () => {\n if (Virtualizer.__STOP) {\n return;\n }\n const wrapperDirty = this.heightDirty || this.scrollHeightDirty;\n if (\n !this.scrollDirty &&\n !this.scrollHeightDirty &&\n !this.heightDirty &&\n this.renderedObservers === this.observers.size &&\n !this.visibleInstancesDirty &&\n this.instancesChanged.size === 0\n ) {\n // NOTE(amadeus): Is this a safe assumption/optimization?\n return;\n }\n let instancesHaveChanged = this.instancesChanged.size > 0;\n\n // If we got an emitted update from a bunch of instances, we should skip\n // the window check first and attempt to render with existing logic first\n // and then queue up a corrected render after\n if (this.instancesChanged.size === 0) {\n const windowSpecs = createWindowFromScrollPosition({\n scrollTop: this.getScrollTop(),\n height: this.getHeight(),\n scrollHeight: this.getScrollHeight(),\n overscrollSize: this.config.overscrollSize,\n });\n if (\n !wrapperDirty &&\n areVirtualWindowSpecsEqual(this.windowSpecs, windowSpecs) &&\n this.renderedObservers === this.observers.size &&\n !this.visibleInstancesDirty\n ) {\n return;\n }\n this.windowSpecs = windowSpecs;\n }\n this.visibleInstancesDirty = false;\n this.renderedObservers = this.observers.size;\n const anchor = this.getScrollAnchor(this.height);\n const updatedInstances = new Set<SubscribedInstance>();\n // NOTE(amadeus): If the wrapper is dirty, we need to force every component\n // to re-render\n for (const instance of wrapperDirty\n ? this.observers.values()\n : this.visibleInstances.values()) {\n if (instance.onRender(wrapperDirty)) {\n updatedInstances.add(instance);\n }\n }\n for (const instance of this.instancesChanged) {\n if (updatedInstances.has(instance)) continue;\n if (instance.onRender(wrapperDirty)) {\n updatedInstances.add(instance);\n }\n }\n\n this.scrollFix(anchor);\n\n for (const instance of updatedInstances) {\n instance.reconcileHeights();\n }\n instancesHaveChanged ||= this.instancesChanged.size > 0;\n\n // Reconciliation reads virtualized offsets and can consume dirty geometry\n // flags, so mark after it when an instance update needs a corrected pass.\n if (instancesHaveChanged) {\n this.markDOMDirty();\n }\n\n if (instancesHaveChanged || wrapperDirty) {\n queueRender(this.computeRenderRangeAndEmit);\n }\n updatedInstances.clear();\n this.instancesChanged.clear();\n };\n\n private scrollFix(anchor: ScrollAnchor | undefined) {\n if (anchor == null) {\n return;\n }\n const scrollContainer = this.getScrollContainerElement();\n const { lineIndex, lineOffset, fileElement, fileOffset, fileTypeOffset } =\n anchor;\n if (lineIndex != null && lineOffset != null) {\n const element = fileElement.shadowRoot?.querySelector(\n `[data-line][data-line-index=\"${lineIndex}\"]`\n );\n if (element instanceof HTMLElement) {\n const top = getRelativeBoundingTop(element, scrollContainer);\n if (top !== lineOffset) {\n const scrollOffset = top - lineOffset;\n this.applyScrollFix(scrollOffset);\n }\n return;\n }\n }\n const top = getRelativeBoundingTop(fileElement, scrollContainer);\n if (fileTypeOffset === 'top') {\n if (top !== fileOffset) {\n this.applyScrollFix(top - fileOffset);\n }\n } else {\n const bottom = top + fileElement.getBoundingClientRect().height;\n if (bottom !== fileOffset) {\n this.applyScrollFix(bottom - fileOffset);\n }\n }\n }\n\n private applyScrollFix(scrollOffset: number) {\n if (this.root == null || this.root instanceof Document) {\n window.scrollTo({\n top: window.scrollY + scrollOffset,\n behavior: 'instant',\n });\n } else {\n this.root.scrollTo({\n top: this.root.scrollTop + scrollOffset,\n behavior: 'instant',\n });\n }\n // Because we fixed our scroll positions, it means something resized or\n // moved around, so we should mark everything as dirty so the\n // reconciliation call will get the latest data when figuring calling\n // .getOffsetInScrollContainer\n this.markDOMDirty();\n }\n\n // This function tries to figure out the closest file or line to the viewport\n // top that's visible to use as a relative marker for how to fix scroll\n // position after issuing dom updates\n private getScrollAnchor(viewportHeight: number): ScrollAnchor | undefined {\n const scrollContainer = this.getScrollContainerElement();\n let bestAnchor: ScrollAnchor | undefined;\n\n for (const [fileElement] of this.visibleInstances.entries()) {\n const fileTop = getRelativeBoundingTop(fileElement, scrollContainer);\n const fileBottom = fileTop + fileElement.offsetHeight;\n\n // Determine file offset and type based on position\n // Only use bottom anchor when entire file is above viewport\n let fileOffset: number;\n let fileTypeOffset: 'top' | 'bottom';\n if (fileBottom <= 0) {\n // Entire file is above viewport - use bottom as anchor\n fileOffset = fileBottom;\n fileTypeOffset = 'bottom';\n } else {\n // File is at least partially visible or below - use top\n fileOffset = fileTop;\n fileTypeOffset = 'top';\n }\n\n // Find the best line (first fully visible) within this file\n let bestLineIndex: string | undefined;\n let bestLineOffset: number | undefined;\n\n // Only search for lines if file potentially intersects viewport\n if (fileBottom > 0 && fileTop < viewportHeight) {\n for (const line of fileElement.shadowRoot?.querySelectorAll(\n '[data-line][data-line-index]'\n ) ?? []) {\n if (!(line instanceof HTMLElement)) continue;\n const lineIndex = line.dataset.lineIndex;\n if (lineIndex == null) continue;\n\n const lineOffset = getRelativeBoundingTop(line, scrollContainer);\n\n // Ignore lines with negative offsets (above viewport top)\n if (lineOffset < 0) continue;\n\n // First visible line in DOM order is the best one because\n // querySelectorAll will grab lines in order as they appear in the\n // DOM\n bestLineIndex = lineIndex;\n bestLineOffset = lineOffset;\n break;\n }\n }\n\n // If we already have an anchor with a visible line, skip files without one\n if (bestAnchor?.lineOffset != null && bestLineOffset == null) {\n continue;\n }\n\n // Decide if this file should become the new best anchor\n let shouldReplace = false;\n // If we don't already have an anchor we should set one\n if (bestAnchor == null) {\n shouldReplace = true;\n }\n // If we found a better line anchor, we should replace the old one\n else if (\n bestLineOffset != null &&\n (bestAnchor.lineOffset == null ||\n bestLineOffset < bestAnchor.lineOffset)\n ) {\n shouldReplace = true;\n }\n // Otherwise we need to compare file only anchors\n else if (bestLineOffset == null && bestAnchor.lineOffset == null) {\n // Favor files with their tops in view\n if (\n fileOffset >= 0 &&\n (bestAnchor.fileOffset < 0 || fileOffset < bestAnchor.fileOffset)\n ) {\n shouldReplace = true;\n }\n // Or the closest file\n else if (\n fileOffset < 0 &&\n bestAnchor.fileOffset < 0 &&\n fileOffset > bestAnchor.fileOffset\n ) {\n shouldReplace = true;\n }\n }\n\n if (shouldReplace) {\n bestAnchor = {\n fileElement,\n fileTypeOffset,\n fileOffset,\n lineIndex: bestLineIndex,\n lineOffset: bestLineOffset,\n };\n }\n }\n\n return bestAnchor;\n }\n\n private handleIntersectionChange = (\n entries: IntersectionObserverEntry[]\n ): void => {\n this.scrollDirty = true;\n for (const { target, isIntersecting } of entries) {\n if (!(target instanceof HTMLElement)) {\n throw new Error(\n 'Virtualizer.handleIntersectionChange: target not an HTMLElement'\n );\n }\n const instance = this.observers.get(target);\n // IntersectionObserver delivers entries asynchronously, so an entry can\n // arrive after the target was unobserved via disconnect() or releaseElement().\n if (instance == null) {\n continue;\n }\n if (isIntersecting && !this.visibleInstances.has(target)) {\n instance.setVisibility(true);\n this.visibleInstances.set(target, instance);\n this.visibleInstancesDirty = true;\n } else if (!isIntersecting && this.visibleInstances.has(target)) {\n instance.setVisibility(false);\n this.visibleInstances.delete(target);\n this.visibleInstancesDirty = true;\n }\n }\n\n if (this.visibleInstancesDirty) {\n // Since this call is already debounced, should we just call\n // computeRenderRangeAndEmit directly?\n queueRender(this.computeRenderRangeAndEmit);\n }\n // Debug logging for visible instances\n // console.log(\n // 'handleIntersectionChange',\n // ...Array.from(this.visibleInstances.keys())\n // );\n };\n\n private getScrollTop() {\n if (!this.scrollDirty) {\n return this.scrollTop;\n }\n this.scrollDirty = false;\n let scrollTop = (() => {\n if (this.root == null) {\n return 0;\n }\n if (this.root instanceof Document) {\n return window.scrollY;\n }\n return this.root.scrollTop;\n })();\n\n // Lets always make sure to clamp scroll position cases of\n // over/bounce scroll\n scrollTop = Math.max(\n 0,\n Math.min(scrollTop, this.getScrollHeight() - this.getHeight())\n );\n this.scrollTop = scrollTop;\n return scrollTop;\n }\n\n private getScrollHeight() {\n if (!this.scrollHeightDirty) {\n return this.scrollHeight;\n }\n this.scrollHeightDirty = false;\n this.scrollHeight = (() => {\n if (this.root == null) {\n return 0;\n }\n if (this.root instanceof Document) {\n return this.root.documentElement.scrollHeight;\n }\n return this.root.scrollHeight;\n })();\n return this.scrollHeight;\n }\n\n private getHeight() {\n if (!this.heightDirty) {\n return this.height;\n }\n this.heightDirty = false;\n this.height = (() => {\n if (this.root == null) {\n return 0;\n }\n if (this.root instanceof Document) {\n return globalThis.innerHeight;\n }\n return this.root.getBoundingClientRect().height;\n })();\n return this.height;\n }\n\n markDOMDirty(): void {\n this.scrollDirty = true;\n this.scrollHeightDirty = true;\n this.heightDirty = true;\n }\n\n private getScrollContainerElement(): HTMLElement | undefined {\n return this.root == null || this.root instanceof Document\n ? undefined\n : this.root;\n }\n}\n\n// This function is like a generalized getBoundingClientRect for it's relative\n// scroll container\nfunction getRelativeBoundingTop(\n element: HTMLElement,\n scrollContainer: HTMLElement | undefined\n) {\n const rect = element.getBoundingClientRect();\n const scrollContainerTop = scrollContainer?.getBoundingClientRect().top ?? 0;\n return rect.top - scrollContainerTop;\n}\n"],"mappings":";;;;;AAqBA,MAAM,0BAA0B;AAChC,MAAM,+BAA+B,0BAA0B;AAC/D,MAAM,kCAAkC;CAAC;CAAG;CAAU;CAAS;CAAE;AAWjE,MAAMA,6BAAgD;CACpD,gBAAgB;CAChB,4BAA4B;CAC5B,iBAAiB;CAClB;AAED,IAAI,WAAW;AAEf,IAAI,WAAW;AAEf,IAAa,cAAb,MAAa,YAAY;CACvB,OAAO,SAAkB;CACzB,OAAO,uBAAuB;CAE9B,AAAgB,OAAe,eAAe,EAAE;CAChD,AAAgB;CAChB,AAAO,OAAO;CACd,AAAQ;CACR,AAAQ,YAAoB;CAC5B,AAAQ,SAAiB;CACzB,AAAQ,eAAuB;CAC/B,AAAQ,cAAkC;EAAE,KAAK;EAAG,QAAQ;EAAG;CAC/D,AAAQ;CACR,AAAQ;CAER,AAAQ;CACR,AAAQ,4BAAkD,IAAI,KAAK;CACnE,AAAQ,mCAAyD,IAAI,KAAK;CAC1E,AAAQ,wBAAiC;CACzC,AAAQ,mCAA4C,IAAI,KAAK;CAE7D,AAAQ,cAAc;CACtB,AAAQ,cAAc;CACtB,AAAQ,oBAAoB;CAC5B,AAAQ,oBAAoB;CAC5B,AAAQ,+BAAqD,IAAI,KAAK;CAEtE,YAAY,QAAqC;AAC/C,OAAK,SAAS;GAAE,GAAG;GAA4B,GAAG;GAAQ;;CAG5D,MAAM,MAA8B,kBAAkC;AACpE,MAAI,KAAK,QAAQ,KACf;AAEF,OAAK,OAAO;AACZ,OAAK,iBAAiB,IAAI,eAAe,KAAK,sBAAsB;AACpE,OAAK,uBAAuB,IAAI,qBAC9B,KAAK,0BACL;GACE,MAAM,KAAK;GACX,WAAW;GACX,YAAY,GAAG,KAAK,OAAO,2BAA2B,SAAS,KAAK,OAAO,2BAA2B;GAGvG,CACF;AACD,MAAI,gBAAgB,SAClB,MAAK,aAAa;MAElB,MAAK,aAAa,iBAAiB;AAIrC,SAAO,aAAa;AACpB,SAAO,iBAAiB;AACtB,OAAI,YAAY,QAAQ;AACtB,gBAAY,SAAS;AAErB,KADiB,KAAK,2BAA2B,IAAI,QAC5C,SAAS,EAAE,KAAK,YAAY,sBAAsB,CAAC;AAC5D,gBAAY,KAAK,0BAA0B;UACtC;AACL,gBAAY,uBAAuB,KAAK,cAAc;AACtD,gBAAY,SAAS;;;AAGzB,OAAK,MAAM,CAAC,WAAWC,eAAa,KAAK,aAAa,SAAS,CAC7D,MAAK,QAAQ,WAAWA,WAAS;AAEnC,OAAK,aAAa,OAAO;AACzB,OAAK,cAAc;AACnB,cAAY,KAAK,0BAA0B;;CAG7C,gBAAgB,YAA8B,UAAyB;AACrE,OAAK,iBAAiB,IAAIA,WAAS;AACnC,MAAI,SACF,MAAK,cAAc;AAErB,cAAY,KAAK,0BAA0B;;CAG7C,iBAAqC;AACnC,MAAI,KAAK,YAAY,QAAQ,KAAK,KAAK,YAAY,WAAW,EAC5D,MAAK,cAAc,+BAA+B;GAChD,WAAW,KAAK,cAAc;GAC9B,QAAQ,KAAK,WAAW;GACxB,cAAc,KAAK,iBAAiB;GACpC,gBAAgB,KAAK,OAAO;GAC7B,CAAC;AAEJ,SAAO,KAAK;;CAGd,kBAAkB,YAAoB,eAAgC;EACpE,MAAM,YAAY,KAAK,cAAc;EACrC,MAAM,SAAS,KAAK,WAAW;EAC/B,MAAM,SAAS,KAAK,OAAO;EAC3B,MAAM,MAAM,YAAY;EACxB,MAAM,SAAS,YAAY,SAAS;AACpC,SAAO,EAAE,aAAa,MAAM,iBAAiB,aAAa;;CAG5D,AAAQ,yBAAyB,YAAmC;AAClE,MAAI,KAAK,QAAQ,KAAM;EACvB,IAAI,oBAAoB;AACxB,OAAK,MAAM,SAAS,SAAS;GAC3B,MAAM,YAAY,MAAM,cAAc,GAAG;AACzC,OAAI,KAAK,gBAAgB,UACvB;QAAI,cAAc,KAAK,cAAc;AACnC,UAAK,oBAAoB;AACzB,yBAAoB;AACpB,SAAI,KAAK,OAAO,iBAAiB;AAC/B,cAAQ,IAAI,oCAAoC,KAAK,MAAM;OACzD,YAAY,YAAY;OACxB,SAAS;OACV,CAAC;AACF,iBAAW;;;cAIX,MAAM,WAAW,KAAK,MACxB;QAAI,cAAc,KAAK,QAAQ;AAC7B,UAAK,cAAc;AACnB,yBAAoB;;cAEb,MAAM,WAAW,KAAK,kBAAkB;AACjD,SAAK,oBAAoB;AACzB,wBAAoB;AACpB,QAAI,KAAK,OAAO,iBAAiB;AAC/B,aAAQ,IAAI,qCAAqC,KAAK,MAAM;MAC1D,YAAY,YAAY;MACxB,SAAS;MACV,CAAC;AACF,gBAAW;;;;AAMnB,MAAI,kBACF,aAAY,KAAK,0BAA0B;;CAI/C,AAAQ,cAAc;AACpB,MAAI,KAAK,QAAQ,QAAQ,EAAE,KAAK,gBAAgB,UAC9C,OAAM,IAAI,MAAM,gDAAgD;AAElE,SAAO,iBAAiB,UAAU,KAAK,oBAAoB,EACzD,SAAS,MACV,CAAC;AACF,SAAO,iBAAiB,UAAU,KAAK,oBAAoB,EACzD,SAAS,MACV,CAAC;AACF,OAAK,gBAAgB,QAAQ,KAAK,KAAK,gBAAgB;;CAGzD,AAAQ,aAAa,kBAAuC;AAC1D,MAAI,KAAK,QAAQ,QAAQ,KAAK,gBAAgB,SAC5C,OAAM,IAAI,MAAM,iDAAiD;AAEnE,OAAK,KAAK,iBAAiB,UAAU,KAAK,qBAAqB,EAC7D,SAAS,MACV,CAAC;AACF,OAAK,gBAAgB,QAAQ,KAAK,KAAK;AACvC,uBAAqB,KAAK,KAAK,qBAAqB;AACpD,MAAI,4BAA4B,aAAa;AAC3C,QAAK,mBAAmB;AACxB,QAAK,gBAAgB,QAAQ,iBAAiB;;;CAIlD,UAAgB;AACd,OAAK,gBAAgB,YAAY;AACjC,OAAK,iBAAiB;AACtB,OAAK,sBAAsB,YAAY;AACvC,OAAK,uBAAuB;AAC5B,OAAK,MAAM,oBAAoB,UAAU,KAAK,oBAAoB;AAClE,SAAO,oBAAoB,UAAU,KAAK,mBAAmB;AAC7D,SAAO,oBAAoB,UAAU,KAAK,mBAAmB;AAC7D,OAAK,OAAO;AACZ,OAAK,mBAAmB;AACxB,OAAK,UAAU,OAAO;AACtB,OAAK,iBAAiB,OAAO;AAC7B,OAAK,iBAAiB,OAAO;AAC7B,OAAK,aAAa,OAAO;AACzB,OAAK,wBAAwB;AAC7B,OAAK,cAAc;GAAE,KAAK;GAAG,QAAQ;GAAG;AACxC,OAAK,YAAY;AACjB,OAAK,SAAS;AACd,OAAK,eAAe;;CAGtB,2BAA2B,SAA8B;AACvD,SACE,KAAK,cAAc,GACnB,uBAAuB,SAAS,KAAK,2BAA2B,CAAC;;CAIrE,QAAQ,WAAwB,YAA0C;AACxE,MAAI,KAAK,UAAU,IAAI,UAAU,CAC/B,OAAM,IAAI,MAAM,wDAAwD;AAI1E,MAAI,KAAK,wBAAwB,KAC/B,MAAK,aAAa,IAAI,WAAWA,WAAS;OACrC;AAEL,QAAK,qBAAqB,QAAQ,UAAU;AAC5C,QAAK,UAAU,IAAI,WAAWA,WAAS;AACvC,QAAK,iBAAiB,IAAIA,WAAS;AACnC,QAAK,cAAc;AACnB,eAAY,KAAK,0BAA0B;;AAE7C,eAAa,KAAK,WAAW,UAAU;;CAGzC,WAAW,WAA8B;EACvC,MAAMA,aAAW,KAAK,UAAU,IAAI,UAAU;AAC9C,OAAK,aAAa,OAAO,UAAU;AACnC,MAAIA,cAAY,KACd;AAEF,OAAK,sBAAsB,UAAU,UAAU;AAC/C,OAAK,UAAU,OAAO,UAAU;AAChC,MAAI,KAAK,iBAAiB,OAAO,UAAU,CACzC,MAAK,wBAAwB;AAE/B,OAAK,cAAc;AACnB,cAAY,KAAK,0BAA0B;;CAG7C,AAAQ,2BAA2B;AACjC,MAAI,YAAY,UAAU,OAAO,gBAAgB,KAAK,OACpD;AAEF,OAAK,cAAc;AACnB,cAAY,KAAK,0BAA0B;;CAG7C,AAAQ,2BAA2B;AACjC,MACE,YAAY,UACZ,KAAK,QAAQ,QACb,EAAE,KAAK,gBAAgB,UAEvB;AAEF,OAAK,cAAc;AACnB,cAAY,KAAK,0BAA0B;;CAG7C,AAAQ,4BAA4B;AAClC,MACE,YAAY,UACZ,KAAK,QAAQ,QACb,KAAK,gBAAgB,SAErB;AAEF,OAAK,cAAc;AACnB,cAAY,KAAK,0BAA0B;;CAG7C,AAAQ,kCAAkC;AACxC,MAAI,YAAY,OACd;EAEF,MAAM,eAAe,KAAK,eAAe,KAAK;AAC9C,MACE,CAAC,KAAK,eACN,CAAC,KAAK,qBACN,CAAC,KAAK,eACN,KAAK,sBAAsB,KAAK,UAAU,QAC1C,CAAC,KAAK,yBACN,KAAK,iBAAiB,SAAS,EAG/B;EAEF,IAAI,uBAAuB,KAAK,iBAAiB,OAAO;AAKxD,MAAI,KAAK,iBAAiB,SAAS,GAAG;GACpC,MAAM,cAAc,+BAA+B;IACjD,WAAW,KAAK,cAAc;IAC9B,QAAQ,KAAK,WAAW;IACxB,cAAc,KAAK,iBAAiB;IACpC,gBAAgB,KAAK,OAAO;IAC7B,CAAC;AACF,OACE,CAAC,gBACD,2BAA2B,KAAK,aAAa,YAAY,IACzD,KAAK,sBAAsB,KAAK,UAAU,QAC1C,CAAC,KAAK,sBAEN;AAEF,QAAK,cAAc;;AAErB,OAAK,wBAAwB;AAC7B,OAAK,oBAAoB,KAAK,UAAU;EACxC,MAAM,SAAS,KAAK,gBAAgB,KAAK,OAAO;EAChD,MAAM,mCAAmB,IAAI,KAAyB;AAGtD,OAAK,MAAMA,cAAY,eACnB,KAAK,UAAU,QAAQ,GACvB,KAAK,iBAAiB,QAAQ,CAChC,KAAIA,WAAS,SAAS,aAAa,CACjC,kBAAiB,IAAIA,WAAS;AAGlC,OAAK,MAAMA,cAAY,KAAK,kBAAkB;AAC5C,OAAI,iBAAiB,IAAIA,WAAS,CAAE;AACpC,OAAIA,WAAS,SAAS,aAAa,CACjC,kBAAiB,IAAIA,WAAS;;AAIlC,OAAK,UAAU,OAAO;AAEtB,OAAK,MAAMA,cAAY,iBACrB,YAAS,kBAAkB;AAE7B,2BAAyB,KAAK,iBAAiB,OAAO;AAItD,MAAI,qBACF,MAAK,cAAc;AAGrB,MAAI,wBAAwB,aAC1B,aAAY,KAAK,0BAA0B;AAE7C,mBAAiB,OAAO;AACxB,OAAK,iBAAiB,OAAO;;CAG/B,AAAQ,UAAU,QAAkC;AAClD,MAAI,UAAU,KACZ;EAEF,MAAM,kBAAkB,KAAK,2BAA2B;EACxD,MAAM,EAAE,WAAW,YAAY,aAAa,YAAY,mBACtD;AACF,MAAI,aAAa,QAAQ,cAAc,MAAM;GAC3C,MAAM,UAAU,YAAY,YAAY,cACtC,gCAAgC,UAAU,IAC3C;AACD,OAAI,mBAAmB,aAAa;IAClC,MAAMC,QAAM,uBAAuB,SAAS,gBAAgB;AAC5D,QAAIA,UAAQ,YAAY;KACtB,MAAM,eAAeA,QAAM;AAC3B,UAAK,eAAe,aAAa;;AAEnC;;;EAGJ,MAAM,MAAM,uBAAuB,aAAa,gBAAgB;AAChE,MAAI,mBAAmB,OACrB;OAAI,QAAQ,WACV,MAAK,eAAe,MAAM,WAAW;SAElC;GACL,MAAM,SAAS,MAAM,YAAY,uBAAuB,CAAC;AACzD,OAAI,WAAW,WACb,MAAK,eAAe,SAAS,WAAW;;;CAK9C,AAAQ,eAAe,cAAsB;AAC3C,MAAI,KAAK,QAAQ,QAAQ,KAAK,gBAAgB,SAC5C,QAAO,SAAS;GACd,KAAK,OAAO,UAAU;GACtB,UAAU;GACX,CAAC;MAEF,MAAK,KAAK,SAAS;GACjB,KAAK,KAAK,KAAK,YAAY;GAC3B,UAAU;GACX,CAAC;AAMJ,OAAK,cAAc;;CAMrB,AAAQ,gBAAgB,gBAAkD;EACxE,MAAM,kBAAkB,KAAK,2BAA2B;EACxD,IAAIC;AAEJ,OAAK,MAAM,CAAC,gBAAgB,KAAK,iBAAiB,SAAS,EAAE;GAC3D,MAAM,UAAU,uBAAuB,aAAa,gBAAgB;GACpE,MAAM,aAAa,UAAU,YAAY;GAIzC,IAAIC;GACJ,IAAIC;AACJ,OAAI,cAAc,GAAG;AAEnB,iBAAa;AACb,qBAAiB;UACZ;AAEL,iBAAa;AACb,qBAAiB;;GAInB,IAAIC;GACJ,IAAIC;AAGJ,OAAI,aAAa,KAAK,UAAU,eAC9B,MAAK,MAAM,QAAQ,YAAY,YAAY,iBACzC,+BACD,IAAI,EAAE,EAAE;AACP,QAAI,EAAE,gBAAgB,aAAc;IACpC,MAAM,YAAY,KAAK,QAAQ;AAC/B,QAAI,aAAa,KAAM;IAEvB,MAAM,aAAa,uBAAuB,MAAM,gBAAgB;AAGhE,QAAI,aAAa,EAAG;AAKpB,oBAAgB;AAChB,qBAAiB;AACjB;;AAKJ,OAAI,YAAY,cAAc,QAAQ,kBAAkB,KACtD;GAIF,IAAI,gBAAgB;AAEpB,OAAI,cAAc,KAChB,iBAAgB;YAIhB,kBAAkB,SACjB,WAAW,cAAc,QACxB,iBAAiB,WAAW,YAE9B,iBAAgB;YAGT,kBAAkB,QAAQ,WAAW,cAAc,MAE1D;QACE,cAAc,MACb,WAAW,aAAa,KAAK,aAAa,WAAW,YAEtD,iBAAgB;aAIhB,aAAa,KACb,WAAW,aAAa,KACxB,aAAa,WAAW,WAExB,iBAAgB;;AAIpB,OAAI,cACF,cAAa;IACX;IACA;IACA;IACA,WAAW;IACX,YAAY;IACb;;AAIL,SAAO;;CAGT,AAAQ,4BACN,YACS;AACT,OAAK,cAAc;AACnB,OAAK,MAAM,EAAE,QAAQ,oBAAoB,SAAS;AAChD,OAAI,EAAE,kBAAkB,aACtB,OAAM,IAAI,MACR,kEACD;GAEH,MAAMN,aAAW,KAAK,UAAU,IAAI,OAAO;AAG3C,OAAIA,cAAY,KACd;AAEF,OAAI,kBAAkB,CAAC,KAAK,iBAAiB,IAAI,OAAO,EAAE;AACxD,eAAS,cAAc,KAAK;AAC5B,SAAK,iBAAiB,IAAI,QAAQA,WAAS;AAC3C,SAAK,wBAAwB;cACpB,CAAC,kBAAkB,KAAK,iBAAiB,IAAI,OAAO,EAAE;AAC/D,eAAS,cAAc,MAAM;AAC7B,SAAK,iBAAiB,OAAO,OAAO;AACpC,SAAK,wBAAwB;;;AAIjC,MAAI,KAAK,sBAGP,aAAY,KAAK,0BAA0B;;CAS/C,AAAQ,eAAe;AACrB,MAAI,CAAC,KAAK,YACR,QAAO,KAAK;AAEd,OAAK,cAAc;EACnB,IAAI,mBAAmB;AACrB,OAAI,KAAK,QAAQ,KACf,QAAO;AAET,OAAI,KAAK,gBAAgB,SACvB,QAAO,OAAO;AAEhB,UAAO,KAAK,KAAK;MACf;AAIJ,cAAY,KAAK,IACf,GACA,KAAK,IAAI,WAAW,KAAK,iBAAiB,GAAG,KAAK,WAAW,CAAC,CAC/D;AACD,OAAK,YAAY;AACjB,SAAO;;CAGT,AAAQ,kBAAkB;AACxB,MAAI,CAAC,KAAK,kBACR,QAAO,KAAK;AAEd,OAAK,oBAAoB;AACzB,OAAK,sBAAsB;AACzB,OAAI,KAAK,QAAQ,KACf,QAAO;AAET,OAAI,KAAK,gBAAgB,SACvB,QAAO,KAAK,KAAK,gBAAgB;AAEnC,UAAO,KAAK,KAAK;MACf;AACJ,SAAO,KAAK;;CAGd,AAAQ,YAAY;AAClB,MAAI,CAAC,KAAK,YACR,QAAO,KAAK;AAEd,OAAK,cAAc;AACnB,OAAK,gBAAgB;AACnB,OAAI,KAAK,QAAQ,KACf,QAAO;AAET,OAAI,KAAK,gBAAgB,SACvB,QAAO,WAAW;AAEpB,UAAO,KAAK,KAAK,uBAAuB,CAAC;MACvC;AACJ,SAAO,KAAK;;CAGd,eAAqB;AACnB,OAAK,cAAc;AACnB,OAAK,oBAAoB;AACzB,OAAK,cAAc;;CAGrB,AAAQ,4BAAqD;AAC3D,SAAO,KAAK,QAAQ,QAAQ,KAAK,gBAAgB,WAC7C,SACA,KAAK;;;AAMb,SAAS,uBACP,SACA,iBACA;CACA,MAAM,OAAO,QAAQ,uBAAuB;CAC5C,MAAM,qBAAqB,iBAAiB,uBAAuB,CAAC,OAAO;AAC3E,QAAO,KAAK,MAAM"}
|
|
1
|
+
{"version":3,"file":"Virtualizer.js","names":[],"sources":["../../src/components/Virtualizer.ts"],"sourcesContent":["import { queueRender } from '../managers/UniversalRenderingManager';\nimport type { VirtualWindowSpecs } from '../types';\nimport { areVirtualWindowSpecsEqual } from '../utils/areVirtualWindowSpecsEqual';\nimport { createWindowFromScrollPosition } from '../utils/createWindowFromScrollPosition';\n\ninterface SubscribedInstance {\n onRender(dirty: boolean): boolean;\n reconcileHeights(): boolean;\n setVisibility(visible: boolean): void;\n}\n\ninterface ScrollAnchor {\n fileElement: HTMLElement;\n fileTypeOffset: 'top' | 'bottom';\n fileOffset: number;\n lineIndex: string | undefined;\n lineOffset: number | undefined;\n}\n\n// 800 seems like the healthy overscan required to\n// keep safari from blanking... if we catch it tho, maybe 900\nconst DEFAULT_OVERSCROLL_SIZE = 1000;\nconst INTERSECTION_OBSERVER_MARGIN = DEFAULT_OVERSCROLL_SIZE * 4;\nconst INTERSECTION_OBSERVER_THRESHOLD = [0, 0.000001, 0.99999, 1];\n\nexport interface VirtualizerConfig {\n /** Extra pixels rendered above and below the viewport to reduce blanking during fast scrolls. */\n overscrollSize: number;\n /** Margin used by IntersectionObserver to decide when items should be considered visible. */\n intersectionObserverMargin: number;\n /** Enables noisy resize logs to help tune metrics and investigate scroll jitter. */\n resizeDebugging: boolean;\n}\n\nconst DEFAULT_VIRTUALIZER_CONFIG: VirtualizerConfig = {\n overscrollSize: DEFAULT_OVERSCROLL_SIZE,\n intersectionObserverMargin: INTERSECTION_OBSERVER_MARGIN,\n resizeDebugging: false,\n};\n\nlet lastSize = 0;\n\nlet instance = -1;\n\nexport class Virtualizer {\n static __STOP: boolean = false;\n static __lastScrollPosition = 0;\n\n public readonly __id: string = `virtualizer-${++instance}`;\n public readonly config: VirtualizerConfig;\n public type = 'simple' as const;\n private intersectionObserver: IntersectionObserver | undefined;\n private scrollTop: number = 0;\n private height: number = 0;\n private scrollHeight: number = 0;\n private windowSpecs: VirtualWindowSpecs = { top: 0, bottom: 0 };\n private root: HTMLElement | Document | undefined;\n private contentContainer: HTMLElement | undefined;\n\n private resizeObserver: ResizeObserver | undefined;\n private observers: Map<HTMLElement, SubscribedInstance> = new Map();\n private visibleInstances: Map<HTMLElement, SubscribedInstance> = new Map();\n private visibleInstancesDirty: boolean = false;\n private instancesChanged: Set<SubscribedInstance> = new Set();\n\n private scrollDirty = true;\n private heightDirty = true;\n private scrollHeightDirty = true;\n private renderedObservers = 0;\n private connectQueue: Map<HTMLElement, SubscribedInstance> = new Map();\n\n constructor(config?: Partial<VirtualizerConfig>) {\n this.config = { ...DEFAULT_VIRTUALIZER_CONFIG, ...config };\n }\n\n setup(root: HTMLElement | Document, contentContainer?: Element): void {\n if (this.root != null) {\n return;\n }\n this.root = root;\n this.resizeObserver = new ResizeObserver(this.handleContainerResize);\n this.intersectionObserver = new IntersectionObserver(\n this.handleIntersectionChange,\n {\n root: this.root,\n threshold: INTERSECTION_OBSERVER_THRESHOLD,\n rootMargin: `${this.config.intersectionObserverMargin}px 0px ${this.config.intersectionObserverMargin}px 0px`,\n // FIXME(amadeus): Figure out the other settings we'll want in here, or\n // if we should make them configurable...\n }\n );\n if (root instanceof Document) {\n this.setupWindow();\n } else {\n this.setupElement(contentContainer);\n }\n\n // FIXME(amadeus): Remove me before release\n window.__INSTANCE = this;\n window.__TOGGLE = () => {\n if (Virtualizer.__STOP) {\n Virtualizer.__STOP = false;\n const scroller = this.getScrollContainerElement() ?? window;\n scroller.scrollTo({ top: Virtualizer.__lastScrollPosition });\n queueRender(this.computeRenderRangeAndEmit);\n } else {\n Virtualizer.__lastScrollPosition = this.getScrollTop();\n Virtualizer.__STOP = true;\n }\n };\n for (const [container, instance] of this.connectQueue.entries()) {\n this.connect(container, instance);\n }\n this.connectQueue.clear();\n this.markDOMDirty();\n queueRender(this.computeRenderRangeAndEmit);\n }\n\n instanceChanged(instance: SubscribedInstance, domDirty: boolean): void {\n this.instancesChanged.add(instance);\n if (domDirty) {\n this.markDOMDirty();\n }\n queueRender(this.computeRenderRangeAndEmit);\n }\n\n getWindowSpecs(): VirtualWindowSpecs {\n if (this.windowSpecs.top === 0 && this.windowSpecs.bottom === 0) {\n this.windowSpecs = createWindowFromScrollPosition({\n scrollTop: this.getScrollTop(),\n height: this.getHeight(),\n scrollHeight: this.getScrollHeight(),\n overscrollSize: this.config.overscrollSize,\n });\n }\n return this.windowSpecs;\n }\n\n isInstanceVisible(elementTop: number, elementHeight: number): boolean {\n const scrollTop = this.getScrollTop();\n const height = this.getHeight();\n const margin = this.config.intersectionObserverMargin;\n const top = scrollTop - margin;\n const bottom = scrollTop + height + margin;\n return !(elementTop < top - elementHeight || elementTop > bottom);\n }\n\n private handleContainerResize = (entries: ResizeObserverEntry[]) => {\n if (this.root == null) return;\n let shouldQueueUpdate = false;\n for (const entry of entries) {\n const blockSize = entry.borderBoxSize[0].blockSize;\n if (this.root instanceof Document) {\n if (blockSize !== this.scrollHeight) {\n this.scrollHeightDirty = true;\n shouldQueueUpdate = true;\n if (this.config.resizeDebugging) {\n console.log('Virtualizer: content size change', this.__id, {\n sizeChange: blockSize - lastSize,\n newSize: blockSize,\n });\n lastSize = blockSize;\n }\n }\n } else {\n if (entry.target === this.root) {\n if (blockSize !== this.height) {\n this.heightDirty = true;\n shouldQueueUpdate = true;\n }\n } else if (entry.target === this.contentContainer) {\n this.scrollHeightDirty = true;\n shouldQueueUpdate = true;\n if (this.config.resizeDebugging) {\n console.log('Virtualizer: scroller size change', this.__id, {\n sizeChange: blockSize - lastSize,\n newSize: blockSize,\n });\n lastSize = blockSize;\n }\n }\n }\n }\n\n if (shouldQueueUpdate) {\n queueRender(this.computeRenderRangeAndEmit);\n }\n };\n\n private setupWindow() {\n if (this.root == null || !(this.root instanceof Document)) {\n throw new Error('Virtualizer.setupWindow: Invalid setup method');\n }\n window.addEventListener('scroll', this.handleWindowScroll, {\n passive: true,\n });\n window.addEventListener('resize', this.handleWindowResize, {\n passive: true,\n });\n this.resizeObserver?.observe(this.root.documentElement);\n }\n\n private setupElement(contentContainer: Element | undefined) {\n if (this.root == null || this.root instanceof Document) {\n throw new Error('Virtualizer.setupElement: Invalid setup method');\n }\n this.root.addEventListener('scroll', this.handleElementScroll, {\n passive: true,\n });\n this.resizeObserver?.observe(this.root);\n contentContainer ??= this.root.firstElementChild ?? undefined;\n if (contentContainer instanceof HTMLElement) {\n this.contentContainer = contentContainer;\n this.resizeObserver?.observe(contentContainer);\n }\n }\n\n cleanUp(): void {\n this.resizeObserver?.disconnect();\n this.resizeObserver = undefined;\n this.intersectionObserver?.disconnect();\n this.intersectionObserver = undefined;\n this.root?.removeEventListener('scroll', this.handleElementScroll);\n window.removeEventListener('scroll', this.handleWindowScroll);\n window.removeEventListener('resize', this.handleWindowResize);\n this.root = undefined;\n this.contentContainer = undefined;\n this.observers.clear();\n this.visibleInstances.clear();\n this.instancesChanged.clear();\n this.connectQueue.clear();\n this.visibleInstancesDirty = false;\n this.windowSpecs = { top: 0, bottom: 0 };\n this.scrollTop = 0;\n this.height = 0;\n this.scrollHeight = 0;\n }\n\n getOffsetInScrollContainer(element: HTMLElement): number {\n return (\n this.getScrollTop() +\n getRelativeBoundingTop(element, this.getScrollContainerElement())\n );\n }\n\n connect(container: HTMLElement, instance: SubscribedInstance): () => void {\n if (this.observers.has(container)) {\n throw new Error('Virtualizer.connect: instance is already connected...');\n }\n // If we are racing against the intersectionObserver, then we should just\n // queue up the connection for when the observer does get set up\n if (this.intersectionObserver == null) {\n this.connectQueue.set(container, instance);\n } else {\n // FIXME(amadeus): Go through the connection phase a bit more closely...\n this.intersectionObserver.observe(container);\n this.observers.set(container, instance);\n this.instancesChanged.add(instance);\n this.markDOMDirty();\n queueRender(this.computeRenderRangeAndEmit);\n }\n return () => this.disconnect(container);\n }\n\n disconnect(container: HTMLElement): void {\n const instance = this.observers.get(container);\n this.connectQueue.delete(container);\n if (instance == null) {\n return;\n }\n this.intersectionObserver?.unobserve(container);\n this.observers.delete(container);\n if (this.visibleInstances.delete(container)) {\n this.visibleInstancesDirty = true;\n }\n this.markDOMDirty();\n queueRender(this.computeRenderRangeAndEmit);\n }\n\n private handleWindowResize = () => {\n if (Virtualizer.__STOP || window.innerHeight === this.height) {\n return;\n }\n this.heightDirty = true;\n queueRender(this.computeRenderRangeAndEmit);\n };\n\n private handleWindowScroll = () => {\n if (\n Virtualizer.__STOP ||\n this.root == null ||\n !(this.root instanceof Document)\n ) {\n return;\n }\n this.scrollDirty = true;\n queueRender(this.computeRenderRangeAndEmit);\n };\n\n private handleElementScroll = () => {\n if (\n Virtualizer.__STOP ||\n this.root == null ||\n this.root instanceof Document\n ) {\n return;\n }\n this.scrollDirty = true;\n queueRender(this.computeRenderRangeAndEmit);\n };\n\n private computeRenderRangeAndEmit = () => {\n if (Virtualizer.__STOP) {\n return;\n }\n const wrapperDirty = this.heightDirty || this.scrollHeightDirty;\n if (\n !this.scrollDirty &&\n !this.scrollHeightDirty &&\n !this.heightDirty &&\n this.renderedObservers === this.observers.size &&\n !this.visibleInstancesDirty &&\n this.instancesChanged.size === 0\n ) {\n // NOTE(amadeus): Is this a safe assumption/optimization?\n return;\n }\n let instancesHaveChanged = this.instancesChanged.size > 0;\n\n // If we got an emitted update from a bunch of instances, we should skip\n // the window check first and attempt to render with existing logic first\n // and then queue up a corrected render after\n if (this.instancesChanged.size === 0) {\n const windowSpecs = createWindowFromScrollPosition({\n scrollTop: this.getScrollTop(),\n height: this.getHeight(),\n scrollHeight: this.getScrollHeight(),\n overscrollSize: this.config.overscrollSize,\n });\n if (\n !wrapperDirty &&\n areVirtualWindowSpecsEqual(this.windowSpecs, windowSpecs) &&\n this.renderedObservers === this.observers.size &&\n !this.visibleInstancesDirty\n ) {\n return;\n }\n this.windowSpecs = windowSpecs;\n }\n this.visibleInstancesDirty = false;\n this.renderedObservers = this.observers.size;\n const anchor = this.getScrollAnchor(this.height);\n const updatedInstances = new Set<SubscribedInstance>();\n // NOTE(amadeus): If the wrapper is dirty, we need to force every component\n // to re-render\n for (const instance of wrapperDirty\n ? this.observers.values()\n : this.visibleInstances.values()) {\n if (instance.onRender(wrapperDirty)) {\n updatedInstances.add(instance);\n }\n }\n for (const instance of this.instancesChanged) {\n if (updatedInstances.has(instance)) continue;\n if (instance.onRender(wrapperDirty)) {\n updatedInstances.add(instance);\n }\n }\n\n this.scrollFix(anchor);\n\n for (const instance of updatedInstances) {\n instance.reconcileHeights();\n }\n instancesHaveChanged ||= this.instancesChanged.size > 0;\n\n // Reconciliation reads virtualized offsets and can consume dirty geometry\n // flags, so mark after it when an instance update needs a corrected pass.\n if (instancesHaveChanged) {\n this.markDOMDirty();\n }\n\n if (instancesHaveChanged || wrapperDirty) {\n queueRender(this.computeRenderRangeAndEmit);\n }\n updatedInstances.clear();\n this.instancesChanged.clear();\n };\n\n private scrollFix(anchor: ScrollAnchor | undefined) {\n if (anchor == null) {\n return;\n }\n const scrollContainer = this.getScrollContainerElement();\n const { lineIndex, lineOffset, fileElement, fileOffset, fileTypeOffset } =\n anchor;\n if (lineIndex != null && lineOffset != null) {\n const element = fileElement.shadowRoot?.querySelector(\n `[data-line][data-line-index=\"${lineIndex}\"]`\n );\n if (element instanceof HTMLElement) {\n const top = getRelativeBoundingTop(element, scrollContainer);\n if (top !== lineOffset) {\n const scrollOffset = top - lineOffset;\n this.applyScrollFix(scrollOffset);\n }\n return;\n }\n }\n const top = getRelativeBoundingTop(fileElement, scrollContainer);\n if (fileTypeOffset === 'top') {\n if (top !== fileOffset) {\n this.applyScrollFix(top - fileOffset);\n }\n } else {\n const bottom = top + fileElement.getBoundingClientRect().height;\n if (bottom !== fileOffset) {\n this.applyScrollFix(bottom - fileOffset);\n }\n }\n }\n\n private applyScrollFix(scrollOffset: number) {\n if (this.root == null || this.root instanceof Document) {\n window.scrollTo({\n top: window.scrollY + scrollOffset,\n behavior: 'instant',\n });\n } else {\n this.root.scrollTo({\n top: this.root.scrollTop + scrollOffset,\n behavior: 'instant',\n });\n }\n // Because we fixed our scroll positions, it means something resized or\n // moved around, so we should mark everything as dirty so the\n // reconciliation call will get the latest data when figuring calling\n // .getOffsetInScrollContainer\n this.markDOMDirty();\n }\n\n // This function tries to figure out the closest file or line to the viewport\n // top that's visible to use as a relative marker for how to fix scroll\n // position after issuing dom updates\n private getScrollAnchor(viewportHeight: number): ScrollAnchor | undefined {\n const scrollContainer = this.getScrollContainerElement();\n let bestAnchor: ScrollAnchor | undefined;\n\n for (const [fileElement] of this.visibleInstances.entries()) {\n const fileTop = getRelativeBoundingTop(fileElement, scrollContainer);\n const fileBottom = fileTop + fileElement.offsetHeight;\n\n // Determine file offset and type based on position\n // Only use bottom anchor when entire file is above viewport\n let fileOffset: number;\n let fileTypeOffset: 'top' | 'bottom';\n if (fileBottom <= 0) {\n // Entire file is above viewport - use bottom as anchor\n fileOffset = fileBottom;\n fileTypeOffset = 'bottom';\n } else {\n // File is at least partially visible or below - use top\n fileOffset = fileTop;\n fileTypeOffset = 'top';\n }\n\n // Find the best line (first fully visible) within this file\n let bestLineIndex: string | undefined;\n let bestLineOffset: number | undefined;\n\n // Only search for lines if file potentially intersects viewport\n if (fileBottom > 0 && fileTop < viewportHeight) {\n for (const line of fileElement.shadowRoot?.querySelectorAll(\n '[data-line][data-line-index]'\n ) ?? []) {\n if (!(line instanceof HTMLElement)) continue;\n const lineIndex = line.dataset.lineIndex;\n if (lineIndex == null) continue;\n\n const lineOffset = getRelativeBoundingTop(line, scrollContainer);\n\n // Ignore lines with negative offsets (above viewport top)\n if (lineOffset < 0) continue;\n\n // First visible line in DOM order is the best one because\n // querySelectorAll will grab lines in order as they appear in the\n // DOM\n bestLineIndex = lineIndex;\n bestLineOffset = lineOffset;\n break;\n }\n }\n\n // If we already have an anchor with a visible line, skip files without one\n if (bestAnchor?.lineOffset != null && bestLineOffset == null) {\n continue;\n }\n\n // Decide if this file should become the new best anchor\n let shouldReplace = false;\n // If we don't already have an anchor we should set one\n if (bestAnchor == null) {\n shouldReplace = true;\n }\n // If we found a better line anchor, we should replace the old one\n else if (\n bestLineOffset != null &&\n (bestAnchor.lineOffset == null ||\n bestLineOffset < bestAnchor.lineOffset)\n ) {\n shouldReplace = true;\n }\n // Otherwise we need to compare file only anchors\n else if (bestLineOffset == null && bestAnchor.lineOffset == null) {\n // Favor files with their tops in view\n if (\n fileOffset >= 0 &&\n (bestAnchor.fileOffset < 0 || fileOffset < bestAnchor.fileOffset)\n ) {\n shouldReplace = true;\n }\n // Or the closest file\n else if (\n fileOffset < 0 &&\n bestAnchor.fileOffset < 0 &&\n fileOffset > bestAnchor.fileOffset\n ) {\n shouldReplace = true;\n }\n }\n\n if (shouldReplace) {\n bestAnchor = {\n fileElement,\n fileTypeOffset,\n fileOffset,\n lineIndex: bestLineIndex,\n lineOffset: bestLineOffset,\n };\n }\n }\n\n return bestAnchor;\n }\n\n private handleIntersectionChange = (\n entries: IntersectionObserverEntry[]\n ): void => {\n this.scrollDirty = true;\n for (const { target, isIntersecting } of entries) {\n if (!(target instanceof HTMLElement)) {\n throw new Error(\n 'Virtualizer.handleIntersectionChange: target not an HTMLElement'\n );\n }\n const instance = this.observers.get(target);\n // IntersectionObserver delivers entries asynchronously, so an entry can\n // arrive after the target was unobserved via disconnect() or releaseElement().\n if (instance == null) {\n continue;\n }\n if (isIntersecting && !this.visibleInstances.has(target)) {\n instance.setVisibility(true);\n this.visibleInstances.set(target, instance);\n this.visibleInstancesDirty = true;\n } else if (!isIntersecting && this.visibleInstances.has(target)) {\n instance.setVisibility(false);\n this.visibleInstances.delete(target);\n this.visibleInstancesDirty = true;\n }\n }\n\n if (this.visibleInstancesDirty) {\n // Since this call is already debounced, should we just call\n // computeRenderRangeAndEmit directly?\n queueRender(this.computeRenderRangeAndEmit);\n }\n // Debug logging for visible instances\n // console.log(\n // 'handleIntersectionChange',\n // ...Array.from(this.visibleInstances.keys())\n // );\n };\n\n private getScrollTop() {\n if (!this.scrollDirty) {\n return this.scrollTop;\n }\n this.scrollDirty = false;\n let scrollTop = (() => {\n if (this.root == null) {\n return 0;\n }\n if (this.root instanceof Document) {\n return window.scrollY;\n }\n return this.root.scrollTop;\n })();\n\n // Lets always make sure to clamp scroll position cases of\n // over/bounce scroll\n scrollTop = Math.max(\n 0,\n Math.min(scrollTop, this.getScrollHeight() - this.getHeight())\n );\n this.scrollTop = scrollTop;\n return scrollTop;\n }\n\n private getScrollHeight() {\n if (!this.scrollHeightDirty) {\n return this.scrollHeight;\n }\n this.scrollHeightDirty = false;\n this.scrollHeight = (() => {\n if (this.root == null) {\n return 0;\n }\n if (this.root instanceof Document) {\n return this.root.documentElement.scrollHeight;\n }\n return this.root.scrollHeight;\n })();\n return this.scrollHeight;\n }\n\n private getHeight() {\n if (!this.heightDirty) {\n return this.height;\n }\n this.heightDirty = false;\n this.height = (() => {\n if (this.root == null) {\n return 0;\n }\n if (this.root instanceof Document) {\n return globalThis.innerHeight;\n }\n return this.root.getBoundingClientRect().height;\n })();\n return this.height;\n }\n\n markDOMDirty(): void {\n this.scrollDirty = true;\n this.scrollHeightDirty = true;\n this.heightDirty = true;\n }\n\n private getScrollContainerElement(): HTMLElement | undefined {\n return this.root == null || this.root instanceof Document\n ? undefined\n : this.root;\n }\n}\n\n// This function is like a generalized getBoundingClientRect for it's relative\n// scroll container\nfunction getRelativeBoundingTop(\n element: HTMLElement,\n scrollContainer: HTMLElement | undefined\n) {\n const rect = element.getBoundingClientRect();\n const scrollContainerTop = scrollContainer?.getBoundingClientRect().top ?? 0;\n return rect.top - scrollContainerTop;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtulizerDevelopment.d.ts","names":["CodeView","Virtualizer","
|
|
1
|
+
{"version":3,"file":"VirtulizerDevelopment.d.ts","names":["global","Window","__INSTANCE","CodeView","Virtualizer","__TOGGLE","__LOG"],"sources":["../../src/components/VirtulizerDevelopment.d.ts"],"mappings":";;;;;QAIQA,MAAAA;EAAAA,UACIC,MAAAA;IAAAA;IAERC,UAAAA,GAAa,QAAA,QAAgB,WAAW;IACxCG,QAAAA;IACAC,KAAAA;EAAAA;AAAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-components.d.ts","names":[
|
|
1
|
+
{"version":3,"file":"web-components.d.ts","names":[],"sources":["../../src/components/web-components.ts"],"mappings":";cAqCa,oBAAA"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { DIFFS_TAG_NAME } from "../constants.js";
|
|
2
2
|
import style_default from "../style.js";
|
|
3
3
|
import { getMeasuredScrollbarGutter } from "../utils/scrollbarGutter.js";
|
|
4
|
-
|
|
5
4
|
//#region src/components/web-components.ts
|
|
6
|
-
if (typeof HTMLElement !== "undefined" && customElements.get(
|
|
5
|
+
if (typeof HTMLElement !== "undefined" && customElements.get("diffs-container") == null) {
|
|
7
6
|
let sheet;
|
|
8
7
|
class FileDiffContainer extends HTMLElement {
|
|
9
8
|
constructor() {
|
|
@@ -23,7 +22,7 @@ if (typeof HTMLElement !== "undefined" && customElements.get(DIFFS_TAG_NAME) ==
|
|
|
23
22
|
customElements.define(DIFFS_TAG_NAME, FileDiffContainer);
|
|
24
23
|
}
|
|
25
24
|
const DiffsContainerLoaded = true;
|
|
26
|
-
|
|
27
25
|
//#endregion
|
|
28
26
|
export { DiffsContainerLoaded };
|
|
27
|
+
|
|
29
28
|
//# sourceMappingURL=web-components.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-components.js","names":["
|
|
1
|
+
{"version":3,"file":"web-components.js","names":["styles"],"sources":["../../src/components/web-components.ts"],"sourcesContent":["import { DIFFS_TAG_NAME } from '../constants';\nimport styles from '../style.css?inline';\nimport { getMeasuredScrollbarGutter } from '../utils/scrollbarGutter';\n\n// If HTMLElement is undefined it usually means we are in a server environment\n// so best to just not do anything\nif (\n typeof HTMLElement !== 'undefined' &&\n customElements.get(DIFFS_TAG_NAME) == null\n) {\n let sheet: CSSStyleSheet | undefined;\n\n class FileDiffContainer extends HTMLElement {\n constructor() {\n super();\n // If shadow root is already open, we can sorta assume the\n // CSS is already in place\n if (this.shadowRoot != null) {\n return;\n }\n const shadowRoot = this.attachShadow({ mode: 'open' });\n if (sheet == null) {\n sheet = new CSSStyleSheet();\n sheet.replaceSync(styles);\n }\n shadowRoot.adoptedStyleSheets = [sheet];\n }\n\n connectedCallback() {\n const shadowRoot = this.shadowRoot ?? this.attachShadow({ mode: 'open' });\n getMeasuredScrollbarGutter(shadowRoot);\n }\n }\n\n customElements.define(DIFFS_TAG_NAME, FileDiffContainer);\n}\n\nexport const DiffsContainerLoaded = true;\n"],"mappings":";;;;AAMA,IACE,OAAO,gBAAgB,eACvB,eAAe,IAAA,iBAAkB,KAAK,MACtC;CACA,IAAI;CAEJ,MAAM,0BAA0B,YAAY;EAC1C,cAAc;GACZ,MAAM;GAGN,IAAI,KAAK,cAAc,MACrB;GAEF,MAAM,aAAa,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;GACrD,IAAI,SAAS,MAAM;IACjB,QAAQ,IAAI,cAAc;IAC1B,MAAM,YAAYA,aAAM;GAC1B;GACA,WAAW,qBAAqB,CAAC,KAAK;EACxC;EAEA,oBAAoB;GAElB,2BADmB,KAAK,cAAc,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC,CACnC;EACvC;CACF;CAEA,eAAe,OAAO,gBAAgB,iBAAiB;AACzD;AAEA,MAAa,uBAAuB"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CodeViewLayout, HunkExpansionRegion, RenderRange, SmoothScrollSettings, ThemesType, VirtualFileMetrics } from "./types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/constants.d.ts
|
|
4
|
-
declare const DIFFS_TAG_NAME:
|
|
4
|
+
declare const DIFFS_TAG_NAME: 'diffs-container';
|
|
5
5
|
declare const DIFFS_DEVELOPMENT_BUILD: boolean;
|
|
6
6
|
declare const COMMIT_METADATA_SPLIT: RegExp;
|
|
7
7
|
declare const GIT_DIFF_FILE_BREAK_REGEX: RegExp;
|
|
@@ -18,6 +18,7 @@ declare const MERGE_CONFLICT_BASE_MARKER_REGEX: RegExp;
|
|
|
18
18
|
declare const MERGE_CONFLICT_SEPARATOR_MARKER_REGEX: RegExp;
|
|
19
19
|
declare const MERGE_CONFLICT_END_MARKER_REGEX: RegExp;
|
|
20
20
|
declare const HEADER_PREFIX_SLOT_ID = "header-prefix";
|
|
21
|
+
declare const HEADER_FILENAME_SUFFIX_SLOT_ID = "header-filename-suffix";
|
|
21
22
|
declare const HEADER_METADATA_SLOT_ID = "header-metadata";
|
|
22
23
|
declare const CUSTOM_HEADER_SLOT_ID = "header-custom";
|
|
23
24
|
declare const DEFAULT_THEMES: ThemesType;
|
|
@@ -36,5 +37,5 @@ declare const DEFAULT_EXPANDED_REGION: HunkExpansionRegion;
|
|
|
36
37
|
declare const DEFAULT_RENDER_RANGE: RenderRange;
|
|
37
38
|
declare const EMPTY_RENDER_RANGE: RenderRange;
|
|
38
39
|
//#endregion
|
|
39
|
-
export { ALTERNATE_FILE_NAMES_GIT, COMMIT_METADATA_SPLIT, CORE_CSS_ATTRIBUTE, CUSTOM_HEADER_SLOT_ID, DEFAULT_CODE_VIEW_FILE_METRICS, DEFAULT_CODE_VIEW_LAYOUT, DEFAULT_COLLAPSED_CONTEXT_THRESHOLD, DEFAULT_EXPANDED_REGION, DEFAULT_RENDER_RANGE, DEFAULT_SMOOTH_SCROLL_SETTINGS, DEFAULT_THEMES, DEFAULT_TOKENIZE_MAX_LENGTH, DEFAULT_VIRTUAL_FILE_METRICS, DIFFS_DEVELOPMENT_BUILD, DIFFS_SCROLLBAR_GUTTER_MEASURED_PROPERTY, DIFFS_SCROLLBAR_MEASURE_ATTRIBUTE, DIFFS_TAG_NAME, EMPTY_RENDER_RANGE, FILENAME_HEADER_REGEX, FILENAME_HEADER_REGEX_GIT, FILE_CONTEXT_BLOB, GIT_DIFF_FILE_BREAK_REGEX, HEADER_METADATA_SLOT_ID, HEADER_PREFIX_SLOT_ID, HUNK_HEADER, INDEX_LINE_METADATA, MERGE_CONFLICT_BASE_MARKER_REGEX, MERGE_CONFLICT_END_MARKER_REGEX, MERGE_CONFLICT_SEPARATOR_MARKER_REGEX, MERGE_CONFLICT_START_MARKER_REGEX, SPLIT_WITH_NEWLINES, THEME_CSS_ATTRIBUTE, UNIFIED_DIFF_FILE_BREAK_REGEX, UNSAFE_CSS_ATTRIBUTE };
|
|
40
|
+
export { ALTERNATE_FILE_NAMES_GIT, COMMIT_METADATA_SPLIT, CORE_CSS_ATTRIBUTE, CUSTOM_HEADER_SLOT_ID, DEFAULT_CODE_VIEW_FILE_METRICS, DEFAULT_CODE_VIEW_LAYOUT, DEFAULT_COLLAPSED_CONTEXT_THRESHOLD, DEFAULT_EXPANDED_REGION, DEFAULT_RENDER_RANGE, DEFAULT_SMOOTH_SCROLL_SETTINGS, DEFAULT_THEMES, DEFAULT_TOKENIZE_MAX_LENGTH, DEFAULT_VIRTUAL_FILE_METRICS, DIFFS_DEVELOPMENT_BUILD, DIFFS_SCROLLBAR_GUTTER_MEASURED_PROPERTY, DIFFS_SCROLLBAR_MEASURE_ATTRIBUTE, DIFFS_TAG_NAME, EMPTY_RENDER_RANGE, FILENAME_HEADER_REGEX, FILENAME_HEADER_REGEX_GIT, FILE_CONTEXT_BLOB, GIT_DIFF_FILE_BREAK_REGEX, HEADER_FILENAME_SUFFIX_SLOT_ID, HEADER_METADATA_SLOT_ID, HEADER_PREFIX_SLOT_ID, HUNK_HEADER, INDEX_LINE_METADATA, MERGE_CONFLICT_BASE_MARKER_REGEX, MERGE_CONFLICT_END_MARKER_REGEX, MERGE_CONFLICT_SEPARATOR_MARKER_REGEX, MERGE_CONFLICT_START_MARKER_REGEX, SPLIT_WITH_NEWLINES, THEME_CSS_ATTRIBUTE, UNIFIED_DIFF_FILE_BREAK_REGEX, UNSAFE_CSS_ATTRIBUTE };
|
|
40
41
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","names":[
|
|
1
|
+
{"version":3,"file":"constants.d.ts","names":[],"sources":["../src/constants.ts"],"mappings":";;;cASa,cAAA;AAAA,cAIA,uBAAA;AAAA,cASA,qBAAA,EAAuB,MAAmC;AAAA,cAC1D,yBAAA,EAA2B,MAA4B;AAAA,cACvD,6BAAA,EAA+B,MAA0B;AAAA,cACzD,iBAAA,EAAmB,MAAqB;AAAA,cACxC,WAAA,EAAa,MACgC;AAAA,cAC7C,mBAAA,EAAqB,MAAkB;AAAA,cACvC,qBAAA,EAAuB,MAAuC;AAAA,cAC9D,yBAAA,EAA2B,MACF;AAAA,cACzB,wBAAA,EAA0B,MACyB;AAAA,cACnD,mBAAA,EAAqB,MACgB;AAAA,cAErC,iCAAA,EAAmC,MAA2B;AAAA,cAC9D,gCAAA,EAAkC,MAA4B;AAAA,cAC9D,qCAAA,EAAuC,MAAkB;AAAA,cACzD,+BAAA,EAAiC,MAA2B;AAAA,cAE5D,qBAAA;AAAA,cACA,8BAAA;AAAA,cACA,uBAAA;AAAA,cACA,qBAAA;AAAA,cAEA,cAAA,EAAgB,UAG5B;AAAA,cAEY,mBAAA;AAAA,cACA,oBAAA;AAAA,cACA,kBAAA;AAAA,cACA,iCAAA;AAAA,cACA,wCAAA;AAAA,cAGA,mCAAA;AAAA,cACA,2BAAA;AAAA,cACA,4BAAA,EAA8B,kBAK1C;AAAA,cAEY,8BAAA,EAAgC,kBAG5C;AAAA,cAEY,wBAAA,EAA0B,cAItC;AAAA,cAEY,8BAAA,EAAgC,oBAI5C;AAAA,cAEY,uBAAA,EAAyB,mBAGpC;AAAA,cAEW,oBAAA,EAAsB,WAKlC;AAAA,cAEY,kBAAA,EAAoB,WAKhC"}
|
package/dist/constants.js
CHANGED
|
@@ -22,6 +22,7 @@ const MERGE_CONFLICT_BASE_MARKER_REGEX = /^\|{7,}(?:\s.*)?$/;
|
|
|
22
22
|
const MERGE_CONFLICT_SEPARATOR_MARKER_REGEX = /^={7,}$/;
|
|
23
23
|
const MERGE_CONFLICT_END_MARKER_REGEX = /^>{7,}(?:\s.*)?$/;
|
|
24
24
|
const HEADER_PREFIX_SLOT_ID = "header-prefix";
|
|
25
|
+
const HEADER_FILENAME_SUFFIX_SLOT_ID = "header-filename-suffix";
|
|
25
26
|
const HEADER_METADATA_SLOT_ID = "header-metadata";
|
|
26
27
|
const CUSTOM_HEADER_SLOT_ID = "header-custom";
|
|
27
28
|
const DEFAULT_THEMES = {
|
|
@@ -71,7 +72,7 @@ const EMPTY_RENDER_RANGE = {
|
|
|
71
72
|
bufferBefore: 0,
|
|
72
73
|
bufferAfter: 0
|
|
73
74
|
};
|
|
74
|
-
|
|
75
75
|
//#endregion
|
|
76
|
-
export { ALTERNATE_FILE_NAMES_GIT, COMMIT_METADATA_SPLIT, CORE_CSS_ATTRIBUTE, CUSTOM_HEADER_SLOT_ID, DEFAULT_CODE_VIEW_FILE_METRICS, DEFAULT_CODE_VIEW_LAYOUT, DEFAULT_COLLAPSED_CONTEXT_THRESHOLD, DEFAULT_EXPANDED_REGION, DEFAULT_RENDER_RANGE, DEFAULT_SMOOTH_SCROLL_SETTINGS, DEFAULT_THEMES, DEFAULT_TOKENIZE_MAX_LENGTH, DEFAULT_VIRTUAL_FILE_METRICS, DIFFS_DEVELOPMENT_BUILD, DIFFS_SCROLLBAR_GUTTER_MEASURED_PROPERTY, DIFFS_SCROLLBAR_MEASURE_ATTRIBUTE, DIFFS_TAG_NAME, EMPTY_RENDER_RANGE, FILENAME_HEADER_REGEX, FILENAME_HEADER_REGEX_GIT, FILE_CONTEXT_BLOB, GIT_DIFF_FILE_BREAK_REGEX, HEADER_METADATA_SLOT_ID, HEADER_PREFIX_SLOT_ID, HUNK_HEADER, INDEX_LINE_METADATA, MERGE_CONFLICT_BASE_MARKER_REGEX, MERGE_CONFLICT_END_MARKER_REGEX, MERGE_CONFLICT_SEPARATOR_MARKER_REGEX, MERGE_CONFLICT_START_MARKER_REGEX, SPLIT_WITH_NEWLINES, THEME_CSS_ATTRIBUTE, UNIFIED_DIFF_FILE_BREAK_REGEX, UNSAFE_CSS_ATTRIBUTE };
|
|
76
|
+
export { ALTERNATE_FILE_NAMES_GIT, COMMIT_METADATA_SPLIT, CORE_CSS_ATTRIBUTE, CUSTOM_HEADER_SLOT_ID, DEFAULT_CODE_VIEW_FILE_METRICS, DEFAULT_CODE_VIEW_LAYOUT, DEFAULT_COLLAPSED_CONTEXT_THRESHOLD, DEFAULT_EXPANDED_REGION, DEFAULT_RENDER_RANGE, DEFAULT_SMOOTH_SCROLL_SETTINGS, DEFAULT_THEMES, DEFAULT_TOKENIZE_MAX_LENGTH, DEFAULT_VIRTUAL_FILE_METRICS, DIFFS_DEVELOPMENT_BUILD, DIFFS_SCROLLBAR_GUTTER_MEASURED_PROPERTY, DIFFS_SCROLLBAR_MEASURE_ATTRIBUTE, DIFFS_TAG_NAME, EMPTY_RENDER_RANGE, FILENAME_HEADER_REGEX, FILENAME_HEADER_REGEX_GIT, FILE_CONTEXT_BLOB, GIT_DIFF_FILE_BREAK_REGEX, HEADER_FILENAME_SUFFIX_SLOT_ID, HEADER_METADATA_SLOT_ID, HEADER_PREFIX_SLOT_ID, HUNK_HEADER, INDEX_LINE_METADATA, MERGE_CONFLICT_BASE_MARKER_REGEX, MERGE_CONFLICT_END_MARKER_REGEX, MERGE_CONFLICT_SEPARATOR_MARKER_REGEX, MERGE_CONFLICT_START_MARKER_REGEX, SPLIT_WITH_NEWLINES, THEME_CSS_ATTRIBUTE, UNIFIED_DIFF_FILE_BREAK_REGEX, UNSAFE_CSS_ATTRIBUTE };
|
|
77
|
+
|
|
77
78
|
//# sourceMappingURL=constants.js.map
|
package/dist/constants.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","names":[
|
|
1
|
+
{"version":3,"file":"constants.js","names":[],"sources":["../src/constants.ts"],"sourcesContent":["import type {\n CodeViewLayout,\n HunkExpansionRegion,\n RenderRange,\n SmoothScrollSettings,\n ThemesType,\n VirtualFileMetrics,\n} from './types';\n\nexport const DIFFS_TAG_NAME = 'diffs-container' as const;\n\n// Keep this as a NODE_ENV read so app builds can hard-disable development-only\n// checks unless they are explicitly built for development.\nexport const DIFFS_DEVELOPMENT_BUILD: boolean = (() => {\n try {\n return process.env.NODE_ENV === 'development';\n } catch {\n return false;\n }\n})();\n\n// Misc patch/content parsing regexes\nexport const COMMIT_METADATA_SPLIT: RegExp = /(?=^From [a-f0-9]+ .+$)/m;\nexport const GIT_DIFF_FILE_BREAK_REGEX: RegExp = /(?=^diff --git)/gm;\nexport const UNIFIED_DIFF_FILE_BREAK_REGEX: RegExp = /(?=^---\\s+\\S)/gm;\nexport const FILE_CONTEXT_BLOB: RegExp = /(?=^@@ )/gm;\nexport const HUNK_HEADER: RegExp =\n /^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@(?: (.*))?/m;\nexport const SPLIT_WITH_NEWLINES: RegExp = /(?<=\\n)/;\nexport const FILENAME_HEADER_REGEX: RegExp = /^(---|\\+\\+\\+)\\s+([^\\t\\r\\n]+)/;\nexport const FILENAME_HEADER_REGEX_GIT: RegExp =\n /^(---|\\+\\+\\+)\\s+[ab]\\/([^\\t\\r\\n]+)/;\nexport const ALTERNATE_FILE_NAMES_GIT: RegExp =\n /^diff --git (?:\"a\\/(.+?)\"|a\\/(.+?)) (?:\"b\\/(.+?)\"|b\\/(.+?))$/;\nexport const INDEX_LINE_METADATA: RegExp =\n /^index ([0-9a-f]+)\\.\\.([0-9a-f]+)(?: (\\d+))?$/i;\n\nexport const MERGE_CONFLICT_START_MARKER_REGEX: RegExp = /^<{7,}(?:\\s.*)?$/;\nexport const MERGE_CONFLICT_BASE_MARKER_REGEX: RegExp = /^\\|{7,}(?:\\s.*)?$/;\nexport const MERGE_CONFLICT_SEPARATOR_MARKER_REGEX: RegExp = /^={7,}$/;\nexport const MERGE_CONFLICT_END_MARKER_REGEX: RegExp = /^>{7,}(?:\\s.*)?$/;\n\nexport const HEADER_PREFIX_SLOT_ID = 'header-prefix';\nexport const HEADER_FILENAME_SUFFIX_SLOT_ID = 'header-filename-suffix';\nexport const HEADER_METADATA_SLOT_ID = 'header-metadata';\nexport const CUSTOM_HEADER_SLOT_ID = 'header-custom';\n\nexport const DEFAULT_THEMES: ThemesType = {\n dark: 'pierre-dark',\n light: 'pierre-light',\n};\n\nexport const THEME_CSS_ATTRIBUTE = 'data-theme-css';\nexport const UNSAFE_CSS_ATTRIBUTE = 'data-unsafe-css';\nexport const CORE_CSS_ATTRIBUTE = 'data-core-css';\nexport const DIFFS_SCROLLBAR_MEASURE_ATTRIBUTE = 'data-diffs-scrollbar-measure';\nexport const DIFFS_SCROLLBAR_GUTTER_MEASURED_PROPERTY =\n '--diffs-scrollbar-gutter-measured';\n\nexport const DEFAULT_COLLAPSED_CONTEXT_THRESHOLD = 1;\nexport const DEFAULT_TOKENIZE_MAX_LENGTH = 100_000;\nexport const DEFAULT_VIRTUAL_FILE_METRICS: VirtualFileMetrics = {\n hunkLineCount: 50,\n lineHeight: 20,\n diffHeaderHeight: 44,\n spacing: 8,\n};\n\nexport const DEFAULT_CODE_VIEW_FILE_METRICS: VirtualFileMetrics = {\n ...DEFAULT_VIRTUAL_FILE_METRICS,\n hunkLineCount: 1,\n};\n\nexport const DEFAULT_CODE_VIEW_LAYOUT: CodeViewLayout = {\n paddingTop: 8,\n paddingBottom: 8,\n gap: 8,\n};\n\nexport const DEFAULT_SMOOTH_SCROLL_SETTINGS: SmoothScrollSettings = {\n omega: 0.015,\n positionEpsilon: 0.5,\n velocityEpsilon: 0.05,\n};\n\nexport const DEFAULT_EXPANDED_REGION: HunkExpansionRegion = Object.freeze({\n fromStart: 0,\n fromEnd: 0,\n});\n\nexport const DEFAULT_RENDER_RANGE: RenderRange = {\n startingLine: 0,\n totalLines: Infinity,\n bufferBefore: 0,\n bufferAfter: 0,\n};\n\nexport const EMPTY_RENDER_RANGE: RenderRange = {\n startingLine: 0,\n totalLines: 0,\n bufferBefore: 0,\n bufferAfter: 0,\n};\n"],"mappings":";AASA,MAAa,iBAAiB;AAI9B,MAAa,iCAA0C;CACrD,IAAI;EACF,OAAO,QAAQ,IAAI,aAAa;CAClC,QAAQ;EACN,OAAO;CACT;AACF,EAAA,CAAG;AAGH,MAAa,wBAAgC;AAC7C,MAAa,4BAAoC;AACjD,MAAa,gCAAwC;AACrD,MAAa,oBAA4B;AACzC,MAAa,cACX;AACF,MAAa,sBAA8B;AAC3C,MAAa,wBAAgC;AAC7C,MAAa,4BACX;AACF,MAAa,2BACX;AACF,MAAa,sBACX;AAEF,MAAa,oCAA4C;AACzD,MAAa,mCAA2C;AACxD,MAAa,wCAAgD;AAC7D,MAAa,kCAA0C;AAEvD,MAAa,wBAAwB;AACrC,MAAa,iCAAiC;AAC9C,MAAa,0BAA0B;AACvC,MAAa,wBAAwB;AAErC,MAAa,iBAA6B;CACxC,MAAM;CACN,OAAO;AACT;AAEA,MAAa,sBAAsB;AACnC,MAAa,uBAAuB;AACpC,MAAa,qBAAqB;AAClC,MAAa,oCAAoC;AACjD,MAAa,2CACX;AAEF,MAAa,sCAAsC;AACnD,MAAa,8BAA8B;AAC3C,MAAa,+BAAmD;CAC9D,eAAe;CACf,YAAY;CACZ,kBAAkB;CAClB,SAAS;AACX;AAEA,MAAa,iCAAqD;CAChE,GAAG;CACH,eAAe;AACjB;AAEA,MAAa,2BAA2C;CACtD,YAAY;CACZ,eAAe;CACf,KAAK;AACP;AAEA,MAAa,iCAAuD;CAClE,OAAO;CACP,iBAAiB;CACjB,iBAAiB;AACnB;AAEA,MAAa,0BAA+C,OAAO,OAAO;CACxE,WAAW;CACX,SAAS;AACX,CAAC;AAED,MAAa,uBAAoC;CAC/C,cAAc;CACd,YAAY;CACZ,cAAc;CACd,aAAa;AACf;AAEA,MAAa,qBAAkC;CAC7C,cAAc;CACd,YAAY;CACZ,cAAc;CACd,aAAa;AACf"}
|
package/dist/editor/command.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//#region src/editor/command.d.ts
|
|
2
2
|
type EditorCommand = 'indent' | 'outdent' | 'undo' | 'redo' | 'selectAll' | 'findNextMatch' | 'openSearchPanel' | 'openSearchReplacePanel' | 'moveCursorToDocStart' | 'moveCursorToDocEnd' | 'expandSelectionDocStart' | 'expandSelectionDocEnd';
|
|
3
3
|
declare function resolveEditorCommandFromKeyboardEvent(event: KeyboardEvent, isMac?: boolean): EditorCommand | undefined;
|
|
4
|
+
declare function resolveFindAgainShortcut(event: KeyboardEvent, isMac?: boolean): 'next' | 'previous' | undefined;
|
|
4
5
|
//#endregion
|
|
5
|
-
export { EditorCommand, resolveEditorCommandFromKeyboardEvent };
|
|
6
|
+
export { EditorCommand, resolveEditorCommandFromKeyboardEvent, resolveFindAgainShortcut };
|
|
6
7
|
//# sourceMappingURL=command.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","names":[
|
|
1
|
+
{"version":3,"file":"command.d.ts","names":[],"sources":["../../src/editor/command.ts"],"mappings":";KAEY,aAAA;AAAA,iBAmBI,qCAAA,CACd,KAAA,EAAO,aAAA,EACP,KAAA,aACC,aAAa;AAAA,iBAsDA,wBAAA,CACd,KAAA,EAAO,aAAa,EACpB,KAAA"}
|
package/dist/editor/command.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { isMacLike, isPrimaryModifier } from "./platform.js";
|
|
2
|
-
|
|
3
2
|
//#region src/editor/command.ts
|
|
4
3
|
const SHORTCUTS = {
|
|
5
4
|
a: "selectAll",
|
|
@@ -25,7 +24,12 @@ function resolveEditorCommandFromKeyboardEvent(event, isMac = isMacLike()) {
|
|
|
25
24
|
}
|
|
26
25
|
return SHORTCUTS[normalizedKey];
|
|
27
26
|
}
|
|
28
|
-
|
|
27
|
+
function resolveFindAgainShortcut(event, isMac = isMacLike()) {
|
|
28
|
+
if (event.altKey) return;
|
|
29
|
+
if (!isPrimaryModifier(event, isMac)) return;
|
|
30
|
+
if ((event.key.length === 1 ? event.key.toLowerCase() : event.key) === "g" || event.code === "KeyG") return event.shiftKey ? "previous" : "next";
|
|
31
|
+
}
|
|
29
32
|
//#endregion
|
|
30
|
-
export { resolveEditorCommandFromKeyboardEvent };
|
|
33
|
+
export { resolveEditorCommandFromKeyboardEvent, resolveFindAgainShortcut };
|
|
34
|
+
|
|
31
35
|
//# sourceMappingURL=command.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.js","names":[
|
|
1
|
+
{"version":3,"file":"command.js","names":[],"sources":["../../src/editor/command.ts"],"sourcesContent":["import { isMacLike, isPrimaryModifier } from './platform';\n\nexport type EditorCommand =\n | 'indent'\n | 'outdent'\n | 'undo'\n | 'redo'\n | 'selectAll'\n | 'findNextMatch'\n | 'openSearchPanel'\n | 'openSearchReplacePanel'\n | 'moveCursorToDocStart'\n | 'moveCursorToDocEnd'\n | 'expandSelectionDocStart'\n | 'expandSelectionDocEnd';\n\nconst SHORTCUTS: Partial<Record<string, EditorCommand>> = {\n a: 'selectAll',\n d: 'findNextMatch',\n};\n\nexport function resolveEditorCommandFromKeyboardEvent(\n event: KeyboardEvent,\n isMac: boolean = isMacLike()\n): EditorCommand | undefined {\n const hasPrimaryModifier = isPrimaryModifier(event, isMac);\n const { shiftKey, altKey, key } = event;\n\n const normalizedKey = key.length === 1 ? key.toLowerCase() : key;\n\n // cmd/ctrl+f opens the search panel in find mode; adding alt opens it in\n // find/replace mode. macOS emits a dead key for Option+F (key === 'ƒ'), so\n // fall back to event.code to detect the physical F key.\n if (hasPrimaryModifier && (normalizedKey === 'f' || event.code === 'KeyF')) {\n return altKey ? 'openSearchReplacePanel' : 'openSearchPanel';\n }\n\n if (altKey) {\n return undefined;\n }\n\n if (!hasPrimaryModifier && normalizedKey === 'Tab') {\n return shiftKey ? 'outdent' : 'indent';\n }\n\n if (!hasPrimaryModifier) {\n return undefined;\n }\n\n if (normalizedKey === 'z') {\n return shiftKey ? 'redo' : 'undo';\n }\n\n if (!isMac && normalizedKey === 'y') {\n return 'redo';\n }\n\n if (normalizedKey === 'Home' || (isMac && normalizedKey === 'ArrowUp')) {\n if (shiftKey) {\n return 'expandSelectionDocStart';\n }\n return 'moveCursorToDocStart';\n }\n\n if (normalizedKey === 'End' || (isMac && normalizedKey === 'ArrowDown')) {\n if (shiftKey) {\n return 'expandSelectionDocEnd';\n }\n return 'moveCursorToDocEnd';\n }\n\n return SHORTCUTS[normalizedKey];\n}\n\n// Detects the native \"find again\" shortcut (cmd/ctrl+g for next, adding shift\n// for previous) so the find/replace panel can override the browser default and\n// step through matches. macOS can emit a dead key for the physical G, so fall\n// back to event.code like the cmd+f handling above.\nexport function resolveFindAgainShortcut(\n event: KeyboardEvent,\n isMac: boolean = isMacLike()\n): 'next' | 'previous' | undefined {\n if (event.altKey) {\n return undefined;\n }\n if (!isPrimaryModifier(event, isMac)) {\n return undefined;\n }\n const normalizedKey =\n event.key.length === 1 ? event.key.toLowerCase() : event.key;\n if (normalizedKey === 'g' || event.code === 'KeyG') {\n return event.shiftKey ? 'previous' : 'next';\n }\n return undefined;\n}\n"],"mappings":";;AAgBA,MAAM,YAAoD;CACxD,GAAG;CACH,GAAG;AACL;AAEA,SAAgB,sCACd,OACA,QAAiB,UAAU,GACA;CAC3B,MAAM,qBAAqB,kBAAkB,OAAO,KAAK;CACzD,MAAM,EAAE,UAAU,QAAQ,QAAQ;CAElC,MAAM,gBAAgB,IAAI,WAAW,IAAI,IAAI,YAAY,IAAI;CAK7D,IAAI,uBAAuB,kBAAkB,OAAO,MAAM,SAAS,SACjE,OAAO,SAAS,2BAA2B;CAG7C,IAAI,QACF;CAGF,IAAI,CAAC,sBAAsB,kBAAkB,OAC3C,OAAO,WAAW,YAAY;CAGhC,IAAI,CAAC,oBACH;CAGF,IAAI,kBAAkB,KACpB,OAAO,WAAW,SAAS;CAG7B,IAAI,CAAC,SAAS,kBAAkB,KAC9B,OAAO;CAGT,IAAI,kBAAkB,UAAW,SAAS,kBAAkB,WAAY;EACtE,IAAI,UACF,OAAO;EAET,OAAO;CACT;CAEA,IAAI,kBAAkB,SAAU,SAAS,kBAAkB,aAAc;EACvE,IAAI,UACF,OAAO;EAET,OAAO;CACT;CAEA,OAAO,UAAU;AACnB;AAMA,SAAgB,yBACd,OACA,QAAiB,UAAU,GACM;CACjC,IAAI,MAAM,QACR;CAEF,IAAI,CAAC,kBAAkB,OAAO,KAAK,GACjC;CAIF,KADE,MAAM,IAAI,WAAW,IAAI,MAAM,IAAI,YAAY,IAAI,MAAM,SACrC,OAAO,MAAM,SAAS,QAC1C,OAAO,MAAM,WAAW,aAAa;AAGzC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DiffLineAnnotation } from "../types.js";
|
|
2
|
-
import { EditorSelection } from "./selection.js";
|
|
3
2
|
import { ResolvedTextEdit, TextDocument } from "./textDocument.js";
|
|
3
|
+
import { EditorSelection } from "./selection.js";
|
|
4
4
|
|
|
5
5
|
//#region src/editor/editStack.d.ts
|
|
6
6
|
/** An entry in the edit stack. */
|
|
@@ -21,6 +21,12 @@ interface EditStackEntry<LAnnotation> {
|
|
|
21
21
|
lineAnnotationsBefore?: DiffLineAnnotation<LAnnotation>[];
|
|
22
22
|
/** Line annotations after the transaction. */
|
|
23
23
|
lineAnnotationsAfter?: DiffLineAnnotation<LAnnotation>[];
|
|
24
|
+
/**
|
|
25
|
+
* When `true`, this entry is its own undo step and never merges with the
|
|
26
|
+
* entry before or after it. Set for paste and cut, which otherwise look like
|
|
27
|
+
* typing and would merge into the previous keystroke.
|
|
28
|
+
*/
|
|
29
|
+
undoBoundary?: boolean;
|
|
24
30
|
}
|
|
25
31
|
/** Options for the edit stack. */
|
|
26
32
|
interface EditStackOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editStack.d.ts","names":[
|
|
1
|
+
{"version":3,"file":"editStack.d.ts","names":[],"sources":["../../src/editor/editStack.ts"],"mappings":";;;;;;UAQiB,cAAA;EAAA;EAEf,YAAA,EAAc,gBAAA;EAFe;EAI7B,YAAA,EAAc,gBAAA;EAAA;EAEd,aAAA;EAMkB;EAJlB,YAAA;EAMwB;EAJxB,gBAAA,GAAmB,eAAA;EAMI;EAJvB,eAAA,GAAkB,eAAA;EAIuB;EAFzC,qBAAA,GAAwB,kBAAA,CAAmB,WAAA;EAZ3C;EAcA,oBAAA,GAAuB,kBAAA,CAAmB,WAAA;EAZ1C;;;;;EAkBA,YAAA;AAAA;;UAIe,gBAAA;EAZS;EAcxB,UAAU;AAAA;;cAIC,SAAA;EAAA;EAKX,WAAA,CAAY,OAAA,GAAU,gBAAA;EAAA,IAOlB,OAAA;EAAA,IAIA,OAAA;EAtB2B;EA2B/B,KAAA;EAzBU;EA+BV,SAAA;EA3BW;EAgCX,IAAA,CAAK,KAAA,EAAO,cAAA,CAAe,WAAA;EAhCP;EAyCpB,0BAAA,CAA2B,UAAA,EAAY,eAAA;EATZ;EAmB3B,0BAAA,CACE,qBAAA,EAAuB,kBAAA,CAAmB,WAAA,KAC1C,oBAAA,EAAsB,kBAAA,CAAmB,WAAA;EAZJ;EAsBvC,QAAA,IAAY,cAAA,CAAe,WAAA;EAXF;EAgBzB,eAAA,CAAgB,KAAA,EAAO,cAAA,CAAe,WAAA;EAfd;EAyBxB,aAAA,IAAiB,cAAA,CAAe,WAAA;EAfpB;EAwBZ,aAAA,IAAiB,cAAA,CAAe,WAAA;AAAA;AAAA,iBASlB,oBAAA,cACd,YAAA,EAAc,YAAA,CAAa,WAAA,GAC3B,aAAA,EAAe,gBAAA,IACf,aAAA,UACA,YAAA,UACA,gBAAA,GAAmB,eAAA,IACnB,eAAA,GAAkB,eAAA,IAClB,qBAAA,GAAwB,kBAAA,CAAmB,WAAA,KAC3C,oBAAA,GAAuB,kBAAA,CAAmB,WAAA,MACzC,cAAA,CAAe,WAAA;;;;;;iBAiCF,4BAAA,cACd,aAAA,EAAe,cAAA,CAAe,WAAA,eAC9B,SAAA,EAAW,cAAA,CAAe,WAAA;;iBAgFZ,wBAAA,cACd,aAAA,EAAe,cAAA,CAAe,WAAA,GAC9B,SAAA,EAAW,cAAA,CAAe,WAAA,IACzB,cAAA,CAAe,WAAA"}
|
package/dist/editor/editStack.js
CHANGED
|
@@ -104,7 +104,7 @@ function createEditStackEntry(textDocument, resolvedEdits, versionBefore, versio
|
|
|
104
104
|
* - 'delete': forward delete
|
|
105
105
|
*/
|
|
106
106
|
function shouldCoalesceEditStackEntry(previousEntry, nextEntry) {
|
|
107
|
-
if (previousEntry === void 0 || previousEntry.forwardEdits.length === 0 || previousEntry.forwardEdits.length !== previousEntry.inverseEdits.length || previousEntry.forwardEdits.length !== nextEntry.forwardEdits.length || nextEntry.forwardEdits.length !== nextEntry.inverseEdits.length) return false;
|
|
107
|
+
if (previousEntry === void 0 || previousEntry.undoBoundary === true || nextEntry.undoBoundary === true || previousEntry.forwardEdits.length === 0 || previousEntry.forwardEdits.length !== previousEntry.inverseEdits.length || previousEntry.forwardEdits.length !== nextEntry.forwardEdits.length || nextEntry.forwardEdits.length !== nextEntry.inverseEdits.length) return false;
|
|
108
108
|
let mode;
|
|
109
109
|
for (let i = 0; i < previousEntry.forwardEdits.length; i++) {
|
|
110
110
|
const previousForward = previousEntry.forwardEdits[i];
|
|
@@ -113,7 +113,7 @@ function shouldCoalesceEditStackEntry(previousEntry, nextEntry) {
|
|
|
113
113
|
const nextInverse = nextEntry.inverseEdits[i];
|
|
114
114
|
const mappedNextStart = mapOffsetAfterForwardBatchToBefore(nextForward.start, previousEntry.forwardEdits);
|
|
115
115
|
const previousWasInsert = previousForward.start <= previousForward.end && previousForward.text.length > 0 && !previousForward.text.includes("\n") && !previousInverse.text.includes("\n");
|
|
116
|
-
const nextIsInsert = nextForward.start === nextForward.end && nextForward.text.length > 0 && nextInverse.text.length === 0;
|
|
116
|
+
const nextIsInsert = nextForward.start === nextForward.end && nextForward.text.length > 0 && !nextForward.text.includes("\n") && nextInverse.text.length === 0;
|
|
117
117
|
if (previousWasInsert && nextIsInsert) {
|
|
118
118
|
if (mappedNextStart !== previousForward.end) return false;
|
|
119
119
|
mode ??= "insert";
|
|
@@ -212,7 +212,7 @@ function mapOffsetAfterForwardBatchToBefore(offsetAfter, forwardEdits) {
|
|
|
212
212
|
}
|
|
213
213
|
return offset;
|
|
214
214
|
}
|
|
215
|
-
|
|
216
215
|
//#endregion
|
|
217
216
|
export { EditStack, coalesceEditStackEntries, createEditStackEntry, shouldCoalesceEditStackEntry };
|
|
217
|
+
|
|
218
218
|
//# sourceMappingURL=editStack.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editStack.js","names":["#maxEntries","#undoStack","#redoStack","inverseEdits: ResolvedTextEdit[]","mode: 'insert' | 'backspace' | 'delete' | undefined","forwardEdits: ResolvedTextEdit[]","replacedTexts: string[]"],"sources":["../../src/editor/editStack.ts"],"sourcesContent":["import type { DiffLineAnnotation } from '../types';\nimport type { EditorSelection } from './selection';\nimport type { ResolvedTextEdit, TextDocument } from './textDocument';\n\n/** Largest number of undo or redo entries kept; oldest entries drop first once exceeded. */\nconst DEFAULT_EDIT_STACK_MAX_ENTRIES = 100;\n\n/** An entry in the edit stack. */\nexport interface EditStackEntry<LAnnotation> {\n /** Forward offset edits from the entry's base text to its final text. */\n forwardEdits: ResolvedTextEdit[];\n /** Inverse offset edits from the entry's final text back to its base text. */\n inverseEdits: ResolvedTextEdit[];\n /** Document version before the entry is applied. */\n versionBefore: number;\n /** Document version after the entry is applied. */\n versionAfter: number;\n /** Selection before the transaction. */\n selectionsBefore?: EditorSelection[];\n /** Selection after the transaction. */\n selectionsAfter?: EditorSelection[];\n /** Line annotations before the transaction. */\n lineAnnotationsBefore?: DiffLineAnnotation<LAnnotation>[];\n /** Line annotations after the transaction. */\n lineAnnotationsAfter?: DiffLineAnnotation<LAnnotation>[];\n}\n\n/** Options for the edit stack. */\nexport interface EditStackOptions {\n /** The maximum number of entries to keep in the undo stack. */\n maxEntries?: number;\n}\n\n/** A stack of edit entries. */\nexport class EditStack<LAnnotation> {\n #undoStack: EditStackEntry<LAnnotation>[] = [];\n #redoStack: EditStackEntry<LAnnotation>[] = [];\n #maxEntries: number;\n\n constructor(options?: EditStackOptions) {\n this.#maxEntries = Math.max(\n 1,\n options?.maxEntries ?? DEFAULT_EDIT_STACK_MAX_ENTRIES\n );\n }\n\n get canUndo(): boolean {\n return this.#undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.#redoStack.length > 0;\n }\n\n /** Clears both the undo and redo stacks. */\n clear(): void {\n this.#undoStack.length = 0;\n this.#redoStack.length = 0;\n }\n\n /** Clears the redo stack. */\n clearRedo(): void {\n this.#redoStack.length = 0;\n }\n\n /** Pushes a new entry onto the undo stack. */\n push(entry: EditStackEntry<LAnnotation>): void {\n this.#undoStack.push(entry);\n this.clearRedo();\n if (this.#undoStack.length > this.#maxEntries) {\n this.#undoStack.shift();\n }\n }\n\n /** Sets the selections after the last undo entry. */\n setLastUndoSelectionsAfter(selections: EditorSelection[]): void {\n const lastEntry = this.#undoStack[this.#undoStack.length - 1];\n if (lastEntry !== undefined) {\n lastEntry.selectionsAfter = selections.map((selection) => ({\n ...selection,\n }));\n }\n }\n\n /** Sets the line annotations after the last undo entry. */\n setLastUndoLineAnnotations(\n lineAnnotationsBefore: DiffLineAnnotation<LAnnotation>[],\n lineAnnotationsAfter: DiffLineAnnotation<LAnnotation>[]\n ): void {\n const lastEntry = this.#undoStack[this.#undoStack.length - 1];\n if (lastEntry !== undefined) {\n lastEntry.lineAnnotationsBefore = lineAnnotationsBefore.slice();\n lastEntry.lineAnnotationsAfter = lineAnnotationsAfter.slice();\n }\n }\n\n /** Returns the last undo entry, or `undefined` if empty. */\n peekUndo(): EditStackEntry<LAnnotation> | undefined {\n return this.#undoStack[this.#undoStack.length - 1];\n }\n\n /** Replaces the last undo entry with the given entry. */\n replaceLastUndo(entry: EditStackEntry<LAnnotation>): void {\n if (this.#undoStack.length === 0) {\n this.push(entry);\n return;\n }\n this.#undoStack[this.#undoStack.length - 1] = entry;\n this.clearRedo();\n }\n\n /** Moves the latest undo entry to the redo stack and returns it, or `undefined` if empty. */\n popUndoToRedo(): EditStackEntry<LAnnotation> | void {\n const entry = this.#undoStack.pop();\n if (entry !== undefined) {\n this.#redoStack.push(entry);\n return entry;\n }\n }\n\n /** Moves the latest redo entry back to the undo stack and returns it, or `undefined` if empty. */\n popRedoToUndo(): EditStackEntry<LAnnotation> | void {\n const entry = this.#redoStack.pop();\n if (entry !== undefined) {\n this.#undoStack.push(entry);\n return entry;\n }\n }\n}\n\nexport function createEditStackEntry<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n resolvedEdits: ResolvedTextEdit[],\n versionBefore: number,\n versionAfter: number,\n selectionsBefore?: EditorSelection[],\n selectionsAfter?: EditorSelection[],\n lineAnnotationsBefore?: DiffLineAnnotation<LAnnotation>[],\n lineAnnotationsAfter?: DiffLineAnnotation<LAnnotation>[]\n): EditStackEntry<LAnnotation> {\n const forwardEdits = [...resolvedEdits].sort((a, b) => a.start - b.start);\n const inverseEdits: ResolvedTextEdit[] = [];\n for (let i = 0, offsetDelta = 0; i < forwardEdits.length; i++) {\n const edit = forwardEdits[i];\n const replacedText = textDocument.getTextSlice(edit.start, edit.end);\n const startAfterEdit = edit.start + offsetDelta;\n inverseEdits.push({\n start: startAfterEdit,\n end: startAfterEdit + edit.text.length,\n text: replacedText,\n });\n offsetDelta += edit.text.length - (edit.end - edit.start);\n }\n return {\n forwardEdits: forwardEdits.map((edit) => ({ ...edit })),\n inverseEdits: inverseEdits,\n versionBefore,\n versionAfter,\n selectionsBefore: selectionsBefore?.map((selection) => ({\n ...selection,\n })),\n selectionsAfter: selectionsAfter?.map((selection) => ({ ...selection })),\n lineAnnotationsBefore: lineAnnotationsBefore?.slice(),\n lineAnnotationsAfter: lineAnnotationsAfter?.slice(),\n };\n}\n\n/** Determines if the change matches following modes:\n * - 'insert': simple typing\n * - 'backspace': backward delete\n * - 'delete': forward delete\n */\nexport function shouldCoalesceEditStackEntry<LAnnotation>(\n previousEntry: EditStackEntry<LAnnotation> | undefined,\n nextEntry: EditStackEntry<LAnnotation>\n): boolean {\n if (\n previousEntry === undefined ||\n previousEntry.forwardEdits.length === 0 ||\n previousEntry.forwardEdits.length !== previousEntry.inverseEdits.length ||\n previousEntry.forwardEdits.length !== nextEntry.forwardEdits.length ||\n nextEntry.forwardEdits.length !== nextEntry.inverseEdits.length\n ) {\n return false;\n }\n let mode: 'insert' | 'backspace' | 'delete' | undefined;\n for (let i = 0; i < previousEntry.forwardEdits.length; i++) {\n const previousForward = previousEntry.forwardEdits[i];\n const previousInverse = previousEntry.inverseEdits[i];\n const nextForward = nextEntry.forwardEdits[i];\n const nextInverse = nextEntry.inverseEdits[i];\n const mappedNextStart = mapOffsetAfterForwardBatchToBefore(\n nextForward.start,\n previousEntry.forwardEdits\n );\n const previousWasInsert =\n previousForward.start <= previousForward.end &&\n previousForward.text.length > 0 &&\n !previousForward.text.includes('\\n') &&\n !previousInverse.text.includes('\\n');\n const nextIsInsert =\n nextForward.start === nextForward.end &&\n nextForward.text.length > 0 &&\n nextInverse.text.length === 0;\n if (previousWasInsert && nextIsInsert) {\n const expectedMappedNextStart = previousForward.end;\n // Allow continuing typing after replacing a selection (e.g. \"hello\" -> \"w\")\n // while still requiring that the cursor extension maps inside the same base range.\n if (mappedNextStart !== expectedMappedNextStart) {\n return false;\n }\n mode ??= 'insert';\n if (mode !== 'insert') {\n return false;\n }\n continue;\n }\n const previousWasDelete =\n previousForward.text.length === 0 &&\n previousForward.end > previousForward.start &&\n previousInverse.text.length > 0;\n const nextIsDelete =\n nextForward.text.length === 0 &&\n nextForward.end > nextForward.start &&\n nextInverse.text.length > 0;\n if (previousWasDelete && nextIsDelete) {\n if (mappedNextStart === previousForward.end) {\n mode ??= 'delete';\n if (mode !== 'delete') {\n return false;\n }\n continue;\n }\n if (\n mappedNextStart + (nextForward.end - nextForward.start) !==\n previousForward.start\n ) {\n return false;\n }\n mode ??= 'backspace';\n if (mode !== 'backspace') {\n return false;\n }\n continue;\n }\n return false;\n }\n return mode !== undefined;\n}\n\n/** Coalesce edit stack entries for simple typing and single-character deletes. */\nexport function coalesceEditStackEntries<LAnnotation>(\n previousEntry: EditStackEntry<LAnnotation>,\n nextEntry: EditStackEntry<LAnnotation>\n): EditStackEntry<LAnnotation> {\n const forwardEdits: ResolvedTextEdit[] = [];\n const replacedTexts: string[] = [];\n for (let i = 0; i < previousEntry.forwardEdits.length; i++) {\n const previousForward = previousEntry.forwardEdits[i];\n const previousInverse = previousEntry.inverseEdits[i];\n const nextForward = nextEntry.forwardEdits[i];\n const nextInverse = nextEntry.inverseEdits[i];\n const mappedNextStart = mapOffsetAfterForwardBatchToBefore(\n nextForward.start,\n previousEntry.forwardEdits\n );\n\n if (previousForward.text.length > 0) {\n forwardEdits.push({\n start: previousForward.start,\n end: previousForward.end,\n text: previousForward.text + nextForward.text,\n });\n replacedTexts.push(previousInverse.text);\n continue;\n }\n\n if (mappedNextStart === previousForward.end) {\n forwardEdits.push({\n start: previousForward.start,\n end: mappedNextStart + (nextForward.end - nextForward.start),\n text: '',\n });\n replacedTexts.push(previousInverse.text + nextInverse.text);\n continue;\n }\n\n forwardEdits.push({\n start: Math.min(previousForward.start, mappedNextStart),\n end: previousForward.end,\n text: '',\n });\n replacedTexts.push(nextInverse.text + previousInverse.text);\n }\n\n return {\n forwardEdits,\n inverseEdits: buildInverseEditsFromReplacedTexts(\n forwardEdits,\n replacedTexts\n ),\n versionBefore: previousEntry.versionBefore,\n versionAfter: nextEntry.versionAfter,\n selectionsBefore: previousEntry.selectionsBefore?.slice(),\n selectionsAfter: nextEntry.selectionsAfter?.slice(),\n lineAnnotationsBefore: previousEntry.lineAnnotationsBefore?.slice(),\n lineAnnotationsAfter: nextEntry.lineAnnotationsAfter?.slice(),\n };\n}\n\nfunction buildInverseEditsFromReplacedTexts(\n forwardEdits: readonly ResolvedTextEdit[],\n replacedTexts: readonly string[]\n): ResolvedTextEdit[] {\n const inverseEdits: ResolvedTextEdit[] = [];\n for (let i = 0, offsetDelta = 0; i < forwardEdits.length; i++) {\n const edit = forwardEdits[i];\n const startAfterEdit = edit.start + offsetDelta;\n inverseEdits.push({\n start: startAfterEdit,\n end: startAfterEdit + edit.text.length,\n text: replacedTexts[i],\n });\n offsetDelta += edit.text.length - (edit.end - edit.start);\n }\n return inverseEdits;\n}\n\nfunction mapOffsetAfterForwardBatchToBefore(\n offsetAfter: number,\n forwardEdits: readonly ResolvedTextEdit[]\n): number {\n let offset = offsetAfter;\n for (const edit of forwardEdits) {\n const oldLength = edit.end - edit.start;\n const newLength = edit.text.length;\n const delta = newLength - oldLength;\n if (offset < edit.start) {\n continue;\n }\n if (offset >= edit.start + newLength) {\n offset -= delta;\n continue;\n }\n offset = edit.start + Math.min(offset - edit.start, oldLength);\n }\n return offset;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"editStack.js","names":["#maxEntries","#undoStack","#redoStack"],"sources":["../../src/editor/editStack.ts"],"sourcesContent":["import type { DiffLineAnnotation } from '../types';\nimport type { EditorSelection } from './selection';\nimport type { ResolvedTextEdit, TextDocument } from './textDocument';\n\n/** Largest number of undo or redo entries kept; oldest entries drop first once exceeded. */\nconst DEFAULT_EDIT_STACK_MAX_ENTRIES = 100;\n\n/** An entry in the edit stack. */\nexport interface EditStackEntry<LAnnotation> {\n /** Forward offset edits from the entry's base text to its final text. */\n forwardEdits: ResolvedTextEdit[];\n /** Inverse offset edits from the entry's final text back to its base text. */\n inverseEdits: ResolvedTextEdit[];\n /** Document version before the entry is applied. */\n versionBefore: number;\n /** Document version after the entry is applied. */\n versionAfter: number;\n /** Selection before the transaction. */\n selectionsBefore?: EditorSelection[];\n /** Selection after the transaction. */\n selectionsAfter?: EditorSelection[];\n /** Line annotations before the transaction. */\n lineAnnotationsBefore?: DiffLineAnnotation<LAnnotation>[];\n /** Line annotations after the transaction. */\n lineAnnotationsAfter?: DiffLineAnnotation<LAnnotation>[];\n /**\n * When `true`, this entry is its own undo step and never merges with the\n * entry before or after it. Set for paste and cut, which otherwise look like\n * typing and would merge into the previous keystroke.\n */\n undoBoundary?: boolean;\n}\n\n/** Options for the edit stack. */\nexport interface EditStackOptions {\n /** The maximum number of entries to keep in the undo stack. */\n maxEntries?: number;\n}\n\n/** A stack of edit entries. */\nexport class EditStack<LAnnotation> {\n #undoStack: EditStackEntry<LAnnotation>[] = [];\n #redoStack: EditStackEntry<LAnnotation>[] = [];\n #maxEntries: number;\n\n constructor(options?: EditStackOptions) {\n this.#maxEntries = Math.max(\n 1,\n options?.maxEntries ?? DEFAULT_EDIT_STACK_MAX_ENTRIES\n );\n }\n\n get canUndo(): boolean {\n return this.#undoStack.length > 0;\n }\n\n get canRedo(): boolean {\n return this.#redoStack.length > 0;\n }\n\n /** Clears both the undo and redo stacks. */\n clear(): void {\n this.#undoStack.length = 0;\n this.#redoStack.length = 0;\n }\n\n /** Clears the redo stack. */\n clearRedo(): void {\n this.#redoStack.length = 0;\n }\n\n /** Pushes a new entry onto the undo stack. */\n push(entry: EditStackEntry<LAnnotation>): void {\n this.#undoStack.push(entry);\n this.clearRedo();\n if (this.#undoStack.length > this.#maxEntries) {\n this.#undoStack.shift();\n }\n }\n\n /** Sets the selections after the last undo entry. */\n setLastUndoSelectionsAfter(selections: EditorSelection[]): void {\n const lastEntry = this.#undoStack[this.#undoStack.length - 1];\n if (lastEntry !== undefined) {\n lastEntry.selectionsAfter = selections.map((selection) => ({\n ...selection,\n }));\n }\n }\n\n /** Sets the line annotations after the last undo entry. */\n setLastUndoLineAnnotations(\n lineAnnotationsBefore: DiffLineAnnotation<LAnnotation>[],\n lineAnnotationsAfter: DiffLineAnnotation<LAnnotation>[]\n ): void {\n const lastEntry = this.#undoStack[this.#undoStack.length - 1];\n if (lastEntry !== undefined) {\n lastEntry.lineAnnotationsBefore = lineAnnotationsBefore.slice();\n lastEntry.lineAnnotationsAfter = lineAnnotationsAfter.slice();\n }\n }\n\n /** Returns the last undo entry, or `undefined` if empty. */\n peekUndo(): EditStackEntry<LAnnotation> | undefined {\n return this.#undoStack[this.#undoStack.length - 1];\n }\n\n /** Replaces the last undo entry with the given entry. */\n replaceLastUndo(entry: EditStackEntry<LAnnotation>): void {\n if (this.#undoStack.length === 0) {\n this.push(entry);\n return;\n }\n this.#undoStack[this.#undoStack.length - 1] = entry;\n this.clearRedo();\n }\n\n /** Moves the latest undo entry to the redo stack and returns it, or `undefined` if empty. */\n popUndoToRedo(): EditStackEntry<LAnnotation> | void {\n const entry = this.#undoStack.pop();\n if (entry !== undefined) {\n this.#redoStack.push(entry);\n return entry;\n }\n }\n\n /** Moves the latest redo entry back to the undo stack and returns it, or `undefined` if empty. */\n popRedoToUndo(): EditStackEntry<LAnnotation> | void {\n const entry = this.#redoStack.pop();\n if (entry !== undefined) {\n this.#undoStack.push(entry);\n return entry;\n }\n }\n}\n\nexport function createEditStackEntry<LAnnotation>(\n textDocument: TextDocument<LAnnotation>,\n resolvedEdits: ResolvedTextEdit[],\n versionBefore: number,\n versionAfter: number,\n selectionsBefore?: EditorSelection[],\n selectionsAfter?: EditorSelection[],\n lineAnnotationsBefore?: DiffLineAnnotation<LAnnotation>[],\n lineAnnotationsAfter?: DiffLineAnnotation<LAnnotation>[]\n): EditStackEntry<LAnnotation> {\n const forwardEdits = [...resolvedEdits].sort((a, b) => a.start - b.start);\n const inverseEdits: ResolvedTextEdit[] = [];\n for (let i = 0, offsetDelta = 0; i < forwardEdits.length; i++) {\n const edit = forwardEdits[i];\n const replacedText = textDocument.getTextSlice(edit.start, edit.end);\n const startAfterEdit = edit.start + offsetDelta;\n inverseEdits.push({\n start: startAfterEdit,\n end: startAfterEdit + edit.text.length,\n text: replacedText,\n });\n offsetDelta += edit.text.length - (edit.end - edit.start);\n }\n return {\n forwardEdits: forwardEdits.map((edit) => ({ ...edit })),\n inverseEdits: inverseEdits,\n versionBefore,\n versionAfter,\n selectionsBefore: selectionsBefore?.map((selection) => ({\n ...selection,\n })),\n selectionsAfter: selectionsAfter?.map((selection) => ({ ...selection })),\n lineAnnotationsBefore: lineAnnotationsBefore?.slice(),\n lineAnnotationsAfter: lineAnnotationsAfter?.slice(),\n };\n}\n\n/** Determines if the change matches following modes:\n * - 'insert': simple typing\n * - 'backspace': backward delete\n * - 'delete': forward delete\n */\nexport function shouldCoalesceEditStackEntry<LAnnotation>(\n previousEntry: EditStackEntry<LAnnotation> | undefined,\n nextEntry: EditStackEntry<LAnnotation>\n): boolean {\n if (\n previousEntry === undefined ||\n previousEntry.undoBoundary === true ||\n nextEntry.undoBoundary === true ||\n previousEntry.forwardEdits.length === 0 ||\n previousEntry.forwardEdits.length !== previousEntry.inverseEdits.length ||\n previousEntry.forwardEdits.length !== nextEntry.forwardEdits.length ||\n nextEntry.forwardEdits.length !== nextEntry.inverseEdits.length\n ) {\n return false;\n }\n let mode: 'insert' | 'backspace' | 'delete' | undefined;\n for (let i = 0; i < previousEntry.forwardEdits.length; i++) {\n const previousForward = previousEntry.forwardEdits[i];\n const previousInverse = previousEntry.inverseEdits[i];\n const nextForward = nextEntry.forwardEdits[i];\n const nextInverse = nextEntry.inverseEdits[i];\n const mappedNextStart = mapOffsetAfterForwardBatchToBefore(\n nextForward.start,\n previousEntry.forwardEdits\n );\n const previousWasInsert =\n previousForward.start <= previousForward.end &&\n previousForward.text.length > 0 &&\n !previousForward.text.includes('\\n') &&\n !previousInverse.text.includes('\\n');\n const nextIsInsert =\n nextForward.start === nextForward.end &&\n nextForward.text.length > 0 &&\n !nextForward.text.includes('\\n') &&\n nextInverse.text.length === 0;\n if (previousWasInsert && nextIsInsert) {\n const expectedMappedNextStart = previousForward.end;\n // Allow continuing typing after replacing a selection (e.g. \"hello\" -> \"w\")\n // while still requiring that the cursor extension maps inside the same base range.\n if (mappedNextStart !== expectedMappedNextStart) {\n return false;\n }\n mode ??= 'insert';\n if (mode !== 'insert') {\n return false;\n }\n continue;\n }\n const previousWasDelete =\n previousForward.text.length === 0 &&\n previousForward.end > previousForward.start &&\n previousInverse.text.length > 0;\n const nextIsDelete =\n nextForward.text.length === 0 &&\n nextForward.end > nextForward.start &&\n nextInverse.text.length > 0;\n if (previousWasDelete && nextIsDelete) {\n if (mappedNextStart === previousForward.end) {\n mode ??= 'delete';\n if (mode !== 'delete') {\n return false;\n }\n continue;\n }\n if (\n mappedNextStart + (nextForward.end - nextForward.start) !==\n previousForward.start\n ) {\n return false;\n }\n mode ??= 'backspace';\n if (mode !== 'backspace') {\n return false;\n }\n continue;\n }\n return false;\n }\n return mode !== undefined;\n}\n\n/** Coalesce edit stack entries for simple typing and single-character deletes. */\nexport function coalesceEditStackEntries<LAnnotation>(\n previousEntry: EditStackEntry<LAnnotation>,\n nextEntry: EditStackEntry<LAnnotation>\n): EditStackEntry<LAnnotation> {\n const forwardEdits: ResolvedTextEdit[] = [];\n const replacedTexts: string[] = [];\n for (let i = 0; i < previousEntry.forwardEdits.length; i++) {\n const previousForward = previousEntry.forwardEdits[i];\n const previousInverse = previousEntry.inverseEdits[i];\n const nextForward = nextEntry.forwardEdits[i];\n const nextInverse = nextEntry.inverseEdits[i];\n const mappedNextStart = mapOffsetAfterForwardBatchToBefore(\n nextForward.start,\n previousEntry.forwardEdits\n );\n\n if (previousForward.text.length > 0) {\n forwardEdits.push({\n start: previousForward.start,\n end: previousForward.end,\n text: previousForward.text + nextForward.text,\n });\n replacedTexts.push(previousInverse.text);\n continue;\n }\n\n if (mappedNextStart === previousForward.end) {\n forwardEdits.push({\n start: previousForward.start,\n end: mappedNextStart + (nextForward.end - nextForward.start),\n text: '',\n });\n replacedTexts.push(previousInverse.text + nextInverse.text);\n continue;\n }\n\n forwardEdits.push({\n start: Math.min(previousForward.start, mappedNextStart),\n end: previousForward.end,\n text: '',\n });\n replacedTexts.push(nextInverse.text + previousInverse.text);\n }\n\n return {\n forwardEdits,\n inverseEdits: buildInverseEditsFromReplacedTexts(\n forwardEdits,\n replacedTexts\n ),\n versionBefore: previousEntry.versionBefore,\n versionAfter: nextEntry.versionAfter,\n selectionsBefore: previousEntry.selectionsBefore?.slice(),\n selectionsAfter: nextEntry.selectionsAfter?.slice(),\n lineAnnotationsBefore: previousEntry.lineAnnotationsBefore?.slice(),\n lineAnnotationsAfter: nextEntry.lineAnnotationsAfter?.slice(),\n };\n}\n\nfunction buildInverseEditsFromReplacedTexts(\n forwardEdits: readonly ResolvedTextEdit[],\n replacedTexts: readonly string[]\n): ResolvedTextEdit[] {\n const inverseEdits: ResolvedTextEdit[] = [];\n for (let i = 0, offsetDelta = 0; i < forwardEdits.length; i++) {\n const edit = forwardEdits[i];\n const startAfterEdit = edit.start + offsetDelta;\n inverseEdits.push({\n start: startAfterEdit,\n end: startAfterEdit + edit.text.length,\n text: replacedTexts[i],\n });\n offsetDelta += edit.text.length - (edit.end - edit.start);\n }\n return inverseEdits;\n}\n\nfunction mapOffsetAfterForwardBatchToBefore(\n offsetAfter: number,\n forwardEdits: readonly ResolvedTextEdit[]\n): number {\n let offset = offsetAfter;\n for (const edit of forwardEdits) {\n const oldLength = edit.end - edit.start;\n const newLength = edit.text.length;\n const delta = newLength - oldLength;\n if (offset < edit.start) {\n continue;\n }\n if (offset >= edit.start + newLength) {\n offset -= delta;\n continue;\n }\n offset = edit.start + Math.min(offset - edit.start, oldLength);\n }\n return offset;\n}\n"],"mappings":"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"}
|
package/dist/editor/editor.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DiffLineAnnotation, DiffsEditableComponent, DiffsEditor, DiffsEditorSelection, FileContents, RenderRange } from "../types.js";
|
|
2
|
-
import { EditorSelection } from "./selection.js";
|
|
3
2
|
import { TextEdit } from "./textDocument.js";
|
|
3
|
+
import { AutoSurround, EditorSelection } from "./selection.js";
|
|
4
4
|
import { Marker } from "./marker.js";
|
|
5
5
|
import { SelectionActionContext } from "./selectionAction.js";
|
|
6
6
|
|
|
@@ -10,8 +10,24 @@ interface EditorOptions<LAnnotation> {
|
|
|
10
10
|
historyMaxEntries?: number;
|
|
11
11
|
/** Render rounded corners for selection ranges, default is true. */
|
|
12
12
|
roundedSelection?: boolean;
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Controls auto-surround when typing quotes or brackets over a selection.
|
|
15
|
+
* Default is `"default"` (both quotes and brackets).
|
|
16
|
+
*/
|
|
17
|
+
autoSurround?: AutoSurround;
|
|
18
|
+
/**
|
|
19
|
+
* Show a floating selection action popover anchored to the active selection,
|
|
20
|
+
* default is disabled.
|
|
21
|
+
*/
|
|
14
22
|
enabledSelectionAction?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Custom clipboard provider.
|
|
25
|
+
* Highly recommended to use native clipboard API if you are building an electron app.
|
|
26
|
+
* see https://www.electronjs.org/docs/latest/api/clipboard
|
|
27
|
+
*/
|
|
28
|
+
clipboard?: {
|
|
29
|
+
readText: () => Promise<string> | string;
|
|
30
|
+
};
|
|
15
31
|
/** Render the selection action widget element. */
|
|
16
32
|
renderSelectionAction?: (context: SelectionActionContext<LAnnotation>) => HTMLElement;
|
|
17
33
|
/** Callback when the editor is attached to a file. */
|
|
@@ -29,11 +45,19 @@ interface EditorState<LAnnotation> {
|
|
|
29
45
|
declare class Editor<LAnnotation> implements DiffsEditor<LAnnotation> {
|
|
30
46
|
#private;
|
|
31
47
|
constructor(options?: EditorOptions<LAnnotation>);
|
|
32
|
-
edit(
|
|
48
|
+
edit(fileInstance: DiffsEditableComponent<LAnnotation>): () => void;
|
|
33
49
|
/**
|
|
34
50
|
* Apply edits to current attached file.
|
|
35
51
|
*/
|
|
36
52
|
applyEdits(edits: TextEdit[], updateHistory?: boolean): void;
|
|
53
|
+
/** Whether there is an edit to undo. */
|
|
54
|
+
get canUndo(): boolean;
|
|
55
|
+
/** Whether there is an undone edit to redo. */
|
|
56
|
+
get canRedo(): boolean;
|
|
57
|
+
/** Undo the last edit. Does nothing when there is nothing to undo. */
|
|
58
|
+
undo(): void;
|
|
59
|
+
/** Redo the last undone edit. Does nothing when there is nothing to redo. */
|
|
60
|
+
redo(): void;
|
|
37
61
|
getState(): EditorState<LAnnotation>;
|
|
38
62
|
setState({
|
|
39
63
|
file,
|
|
@@ -47,7 +71,7 @@ declare class Editor<LAnnotation> implements DiffsEditor<LAnnotation> {
|
|
|
47
71
|
blur(): void;
|
|
48
72
|
cleanUp(): void;
|
|
49
73
|
/** @internal */
|
|
50
|
-
|
|
74
|
+
__postponeBgTokenizeToNextFrame(): void;
|
|
51
75
|
/** @internal */
|
|
52
76
|
__syncRenderView: DiffsEditor<LAnnotation>['__syncRenderView'];
|
|
53
77
|
}
|