@pierre/diffs 1.5.2 → 1.6.0
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 +4 -3
- package/dist/components/CodeView.d.ts +3 -2
- package/dist/components/CodeView.d.ts.map +1 -1
- package/dist/components/CodeView.js +24 -19
- package/dist/components/CodeView.js.map +1 -1
- package/dist/components/File.d.ts +31 -9
- package/dist/components/File.d.ts.map +1 -1
- package/dist/components/File.js +176 -90
- package/dist/components/File.js.map +1 -1
- package/dist/components/FileDiff.d.ts +32 -9
- package/dist/components/FileDiff.d.ts.map +1 -1
- package/dist/components/FileDiff.js +225 -131
- package/dist/components/FileDiff.js.map +1 -1
- package/dist/components/FileStream.d.ts +6 -4
- package/dist/components/FileStream.d.ts.map +1 -1
- package/dist/components/FileStream.js +49 -36
- package/dist/components/FileStream.js.map +1 -1
- package/dist/components/UnresolvedFile.d.ts +14 -4
- package/dist/components/UnresolvedFile.d.ts.map +1 -1
- package/dist/components/UnresolvedFile.js +35 -16
- package/dist/components/UnresolvedFile.js.map +1 -1
- package/dist/components/VirtualizedFile.d.ts +3 -2
- package/dist/components/VirtualizedFile.d.ts.map +1 -1
- package/dist/components/VirtualizedFile.js +28 -20
- package/dist/components/VirtualizedFile.js.map +1 -1
- package/dist/components/VirtualizedFileDiff.d.ts +3 -2
- package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
- package/dist/components/VirtualizedFileDiff.js +31 -24
- package/dist/components/VirtualizedFileDiff.js.map +1 -1
- package/dist/constants.d.ts +4 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -1
- package/dist/constants.js.map +1 -1
- package/dist/editor/editor.d.ts +2 -1
- package/dist/editor/editor.d.ts.map +1 -1
- package/dist/editor/editor.js +5 -1
- package/dist/editor/editor.js.map +1 -1
- package/dist/editor/platform.d.ts +1 -1
- package/dist/editor/platform.js +5 -4
- package/dist/editor/platform.js.map +1 -1
- package/dist/editor/selection.d.ts +2 -2
- package/dist/editor/selection.d.ts.map +1 -1
- package/dist/editor/selection.js +31 -6
- package/dist/editor/selection.js.map +1 -1
- package/dist/editor/tokenizer.d.ts +6 -4
- package/dist/editor/tokenizer.d.ts.map +1 -1
- package/dist/editor/tokenizer.js +25 -470
- package/dist/editor/tokenizer.js.map +1 -1
- package/dist/highlighter/DiffsEditorTokenizer.d.ts +16 -0
- package/dist/highlighter/DiffsEditorTokenizer.d.ts.map +1 -0
- package/dist/highlighter/DiffsEditorTokenizer.js +0 -0
- package/dist/highlighter/DiffsHighlighter.d.ts +41 -0
- package/dist/highlighter/DiffsHighlighter.d.ts.map +1 -0
- package/dist/highlighter/DiffsHighlighter.js +39 -0
- package/dist/highlighter/DiffsHighlighter.js.map +1 -0
- package/dist/highlighter/backends/highlights.d.ts +26 -0
- package/dist/highlighter/backends/highlights.d.ts.map +1 -0
- package/dist/highlighter/backends/highlights.js +71 -0
- package/dist/highlighter/backends/highlights.js.map +1 -0
- package/dist/highlighter/backends/shiki.d.ts +27 -0
- package/dist/highlighter/backends/shiki.d.ts.map +1 -0
- package/dist/highlighter/backends/shiki.js +107 -0
- package/dist/highlighter/backends/shiki.js.map +1 -0
- package/dist/highlighter/highlighterType.d.ts +13 -0
- package/dist/highlighter/highlighterType.d.ts.map +1 -0
- package/dist/highlighter/highlighterType.js +32 -0
- package/dist/highlighter/highlighterType.js.map +1 -0
- package/dist/highlighter/highlights-editor.d.ts +24 -0
- package/dist/highlighter/highlights-editor.d.ts.map +1 -0
- package/dist/highlighter/highlights-editor.js +166 -0
- package/dist/highlighter/highlights-editor.js.map +1 -0
- package/dist/highlighter/highlights-stream.d.ts +20 -0
- package/dist/highlighter/highlights-stream.d.ts.map +1 -0
- package/dist/highlighter/highlights-stream.js +93 -0
- package/dist/highlighter/highlights-stream.js.map +1 -0
- package/dist/highlighter/languages/areLanguagesAttached.d.ts +2 -1
- package/dist/highlighter/languages/areLanguagesAttached.d.ts.map +1 -1
- package/dist/highlighter/languages/areLanguagesAttached.js +4 -6
- package/dist/highlighter/languages/areLanguagesAttached.js.map +1 -1
- package/dist/highlighter/languages/attachResolvedLanguages.d.ts +6 -1
- package/dist/highlighter/languages/attachResolvedLanguages.d.ts.map +1 -1
- package/dist/highlighter/languages/attachResolvedLanguages.js +6 -11
- package/dist/highlighter/languages/attachResolvedLanguages.js.map +1 -1
- package/dist/highlighter/languages/constants.d.ts +1 -1
- package/dist/highlighter/languages/getResolvedLanguages.d.ts +1 -1
- package/dist/highlighter/languages/getResolvedOrResolveLanguage.d.ts +1 -1
- package/dist/highlighter/languages/resolveLanguage.d.ts +1 -1
- package/dist/highlighter/languages/resolveLanguage.d.ts.map +1 -1
- package/dist/highlighter/languages/resolveLanguage.js +19 -16
- package/dist/highlighter/languages/resolveLanguage.js.map +1 -1
- package/dist/highlighter/languages/resolveLanguages.d.ts +1 -1
- package/dist/highlighter/shared_highlighter.d.ts +24 -9
- package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
- package/dist/highlighter/shared_highlighter.js +59 -47
- package/dist/highlighter/shared_highlighter.js.map +1 -1
- package/dist/highlighter/shiki-editor.d.ts +25 -0
- package/dist/highlighter/shiki-editor.d.ts.map +1 -0
- package/dist/highlighter/shiki-editor.js +483 -0
- package/dist/highlighter/shiki-editor.js.map +1 -0
- package/dist/highlighter/shiki-stream.d.ts +20 -0
- package/dist/highlighter/shiki-stream.d.ts.map +1 -0
- package/dist/highlighter/shiki-stream.js +60 -0
- package/dist/highlighter/shiki-stream.js.map +1 -0
- package/dist/highlighter/stream-tokenizer.d.ts +40 -0
- package/dist/highlighter/stream-tokenizer.d.ts.map +1 -0
- package/dist/highlighter/stream-tokenizer.js +70 -0
- package/dist/highlighter/stream-tokenizer.js.map +1 -0
- package/dist/highlighter/themes/areThemesAttached.d.ts +3 -2
- package/dist/highlighter/themes/areThemesAttached.d.ts.map +1 -1
- package/dist/highlighter/themes/areThemesAttached.js +5 -4
- package/dist/highlighter/themes/areThemesAttached.js.map +1 -1
- package/dist/highlighter/themes/attachResolvedThemes.d.ts +5 -2
- package/dist/highlighter/themes/attachResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/attachResolvedThemes.js +4 -16
- package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/cleanUpResolvedThemes.d.ts +3 -1
- package/dist/highlighter/themes/cleanUpResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/cleanUpResolvedThemes.js +8 -5
- package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/createCSSVariablesTheme.d.ts +7 -0
- package/dist/highlighter/themes/createCSSVariablesTheme.d.ts.map +1 -0
- package/dist/highlighter/themes/createCSSVariablesTheme.js +89 -0
- package/dist/highlighter/themes/createCSSVariablesTheme.js.map +1 -0
- package/dist/highlighter/themes/createCachedLoader.d.ts +5 -0
- package/dist/highlighter/themes/createCachedLoader.d.ts.map +1 -0
- package/dist/highlighter/themes/createCachedLoader.js +15 -0
- package/dist/highlighter/themes/createCachedLoader.js.map +1 -0
- package/dist/highlighter/themes/getResolvedOrResolveTheme.d.ts +3 -2
- package/dist/highlighter/themes/getResolvedOrResolveTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js +4 -4
- package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
- package/dist/highlighter/themes/getResolvedThemes.d.ts +3 -2
- package/dist/highlighter/themes/getResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/getResolvedThemes.js +4 -3
- package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
- package/dist/highlighter/themes/hasResolvedThemes.d.ts +2 -2
- package/dist/highlighter/themes/hasResolvedThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/hasResolvedThemes.js +4 -3
- 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 +3 -3
- package/dist/highlighter/themes/registerCustomCSSVariableTheme.js.map +1 -1
- package/dist/highlighter/themes/registerCustomTheme.d.ts +9 -4
- package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/registerCustomTheme.js +8 -16
- package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveTheme.d.ts +3 -2
- package/dist/highlighter/themes/resolveTheme.d.ts.map +1 -1
- package/dist/highlighter/themes/resolveTheme.js +4 -7
- package/dist/highlighter/themes/resolveTheme.js.map +1 -1
- package/dist/highlighter/themes/resolveThemes.d.ts +3 -2
- package/dist/highlighter/themes/resolveThemes.d.ts.map +1 -1
- package/dist/highlighter/themes/resolveThemes.js +4 -7
- package/dist/highlighter/themes/resolveThemes.js.map +1 -1
- package/dist/highlighter/themes/themeResolver.d.ts +10 -4
- package/dist/highlighter/themes/themeResolver.d.ts.map +1 -1
- package/dist/highlighter/themes/themeResolver.js +141 -2
- package/dist/highlighter/themes/themeResolver.js.map +1 -1
- package/dist/highlighter/themes/types.d.ts +23 -0
- package/dist/highlighter/themes/types.d.ts.map +1 -0
- package/dist/highlighter/themes/types.js +0 -0
- package/dist/highlighter/tokenizer-types.d.ts +35 -0
- package/dist/highlighter/tokenizer-types.d.ts.map +1 -0
- package/dist/highlighter/tokenizer-types.js +0 -0
- package/dist/highlighter/types.d.ts +55 -0
- package/dist/highlighter/types.d.ts.map +1 -0
- package/dist/highlighter/types.js +0 -0
- package/dist/index.d.ts +22 -13
- package/dist/index.js +21 -18
- package/dist/managers/InteractionManager.d.ts.map +1 -1
- package/dist/managers/InteractionManager.js +2 -2
- package/dist/managers/InteractionManager.js.map +1 -1
- package/dist/node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.d.ts +9 -1
- package/dist/node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.d.ts.map +1 -1
- package/dist/react/CodeView.d.ts +4 -3
- package/dist/react/CodeView.d.ts.map +1 -1
- package/dist/react/CodeView.js +47 -38
- package/dist/react/CodeView.js.map +1 -1
- package/dist/react/File.js +3 -3
- package/dist/react/File.js.map +1 -1
- package/dist/react/FileDiff.js +3 -3
- package/dist/react/FileDiff.js.map +1 -1
- package/dist/react/MultiFileDiff.js +2 -2
- package/dist/react/MultiFileDiff.js.map +1 -1
- package/dist/react/PatchDiff.js +3 -3
- package/dist/react/PatchDiff.js.map +1 -1
- package/dist/react/UnresolvedFile.js +2 -2
- package/dist/react/UnresolvedFile.js.map +1 -1
- package/dist/react/index.d.ts +9 -4
- package/dist/react/types.d.ts +4 -2
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/utils/renderDiffChildren.js +1 -1
- package/dist/react/utils/renderDiffChildren.js.map +1 -1
- package/dist/react/utils/renderFileChildren.js +1 -1
- package/dist/react/utils/renderFileChildren.js.map +1 -1
- package/dist/react/utils/useFileDiffInstance.d.ts +1 -0
- package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileDiffInstance.js +29 -24
- package/dist/react/utils/useFileDiffInstance.js.map +1 -1
- package/dist/react/utils/useFileInstance.d.ts +2 -0
- package/dist/react/utils/useFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useFileInstance.js +38 -28
- package/dist/react/utils/useFileInstance.js.map +1 -1
- package/dist/react/utils/useForceUpdate.d.ts +5 -0
- package/dist/react/utils/useForceUpdate.d.ts.map +1 -0
- package/dist/react/utils/useForceUpdate.js +27 -0
- package/dist/react/utils/useForceUpdate.js.map +1 -0
- package/dist/react/utils/useNextRenderData.d.ts +9 -0
- package/dist/react/utils/useNextRenderData.d.ts.map +1 -0
- package/dist/react/utils/useNextRenderData.js +9 -0
- package/dist/react/utils/useNextRenderData.js.map +1 -0
- package/dist/react/utils/useUnresolvedFileInstance.d.ts +1 -0
- package/dist/react/utils/useUnresolvedFileInstance.d.ts.map +1 -1
- package/dist/react/utils/useUnresolvedFileInstance.js +26 -11
- package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
- package/dist/renderers/DiffHunksRenderer.d.ts +4 -2
- package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/DiffHunksRenderer.js +82 -43
- package/dist/renderers/DiffHunksRenderer.js.map +1 -1
- package/dist/renderers/FileRenderer.d.ts +6 -2
- package/dist/renderers/FileRenderer.d.ts.map +1 -1
- package/dist/renderers/FileRenderer.js +77 -43
- package/dist/renderers/FileRenderer.js.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.js +1 -1
- package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
- package/dist/shiki-stream/index.d.ts +3 -3
- package/dist/shiki-stream/index.js +1 -2
- package/dist/shiki-stream/stream.d.ts +4 -4
- package/dist/shiki-stream/stream.d.ts.map +1 -1
- package/dist/shiki-stream/stream.js +20 -9
- package/dist/shiki-stream/stream.js.map +1 -1
- package/dist/shiki-stream/types.d.ts +7 -38
- package/dist/shiki-stream/types.d.ts.map +1 -1
- package/dist/ssr/index.d.ts +7 -2
- package/dist/ssr/renderHTML.js +2 -2
- package/dist/ssr/renderHTML.js.map +1 -1
- package/dist/style.js +1 -1
- package/dist/style.js.map +1 -1
- package/dist/types.d.ts +20 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/canUseWASM.d.ts +13 -0
- package/dist/utils/canUseWASM.d.ts.map +1 -0
- package/dist/utils/canUseWASM.js +59 -0
- package/dist/utils/canUseWASM.js.map +1 -0
- package/dist/utils/createSpanNodeFromToken.d.ts +3 -2
- package/dist/utils/createSpanNodeFromToken.d.ts.map +1 -1
- package/dist/utils/createSpanNodeFromToken.js +4 -5
- package/dist/utils/createSpanNodeFromToken.js.map +1 -1
- package/dist/utils/cssWrappers.d.ts.map +1 -1
- package/dist/utils/cssWrappers.js +12 -0
- package/dist/utils/cssWrappers.js.map +1 -1
- package/dist/utils/getCodeViewItemRenderData.d.ts +10 -0
- package/dist/utils/getCodeViewItemRenderData.d.ts.map +1 -0
- package/dist/utils/getCodeViewItemRenderData.js +19 -0
- package/dist/utils/getCodeViewItemRenderData.js.map +1 -0
- package/dist/utils/getHighlighterOptions.d.ts.map +1 -1
- package/dist/utils/getHighlighterOptions.js +3 -2
- package/dist/utils/getHighlighterOptions.js.map +1 -1
- package/dist/utils/getHighlighterThemeStyles.d.ts +2 -1
- package/dist/utils/getHighlighterThemeStyles.d.ts.map +1 -1
- package/dist/utils/getHighlighterThemeStyles.js +13 -3
- package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
- package/dist/utils/getTokenOptions.d.ts +7 -0
- package/dist/utils/getTokenOptions.d.ts.map +1 -0
- package/dist/utils/getTokenOptions.js +16 -0
- package/dist/utils/getTokenOptions.js.map +1 -0
- package/dist/utils/hastToHtml.d.ts +10 -0
- package/dist/utils/hastToHtml.d.ts.map +1 -0
- package/dist/utils/hastToHtml.js +125 -0
- package/dist/utils/hastToHtml.js.map +1 -0
- package/dist/utils/hydratePartialDiff.js +4 -0
- package/dist/utils/hydratePartialDiff.js.map +1 -1
- package/dist/utils/parseDiffDecorations.d.ts +2 -1
- package/dist/utils/parseDiffDecorations.d.ts.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
- package/dist/utils/parseMergeConflictDiffFromFile.js +2 -0
- package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
- package/dist/utils/parsePatchFiles.d.ts.map +1 -1
- package/dist/utils/parsePatchFiles.js +24 -4
- package/dist/utils/parsePatchFiles.js.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.d.ts +3 -2
- package/dist/utils/renderDiffWithHighlighter.d.ts.map +1 -1
- package/dist/utils/renderDiffWithHighlighter.js +33 -48
- package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
- package/dist/utils/renderFileWithHighlighter.d.ts +3 -2
- package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
- package/dist/utils/renderFileWithHighlighter.js +10 -26
- package/dist/utils/renderFileWithHighlighter.js.map +1 -1
- package/dist/utils/renderTokenLines.d.ts +22 -0
- package/dist/utils/renderTokenLines.d.ts.map +1 -0
- package/dist/utils/renderTokenLines.js +250 -0
- package/dist/utils/renderTokenLines.js.map +1 -0
- package/dist/utils/resolvePreferredHighlighter.d.ts +13 -0
- package/dist/utils/resolvePreferredHighlighter.d.ts.map +1 -0
- package/dist/utils/resolvePreferredHighlighter.js +11 -0
- package/dist/utils/resolvePreferredHighlighter.js.map +1 -0
- package/dist/utils/resolveRegion.js +20 -10
- package/dist/utils/resolveRegion.js.map +1 -1
- package/dist/utils/setDeferredArrayItem.d.ts +5 -0
- package/dist/utils/setDeferredArrayItem.d.ts.map +1 -0
- package/dist/utils/setDeferredArrayItem.js +39 -0
- package/dist/utils/setDeferredArrayItem.js.map +1 -0
- package/dist/utils/tokenStyle.d.ts +11 -0
- package/dist/utils/tokenStyle.d.ts.map +1 -0
- package/dist/utils/tokenStyle.js +32 -0
- package/dist/utils/tokenStyle.js.map +1 -0
- package/dist/utils/tokensToHtml.d.ts +11 -0
- package/dist/utils/tokensToHtml.d.ts.map +1 -0
- package/dist/utils/tokensToHtml.js +48 -0
- package/dist/utils/tokensToHtml.js.map +1 -0
- package/dist/utils/updateDiffHunks.d.ts +2 -2
- package/dist/utils/updateDiffHunks.d.ts.map +1 -1
- package/dist/utils/updateDiffHunks.js +7 -3
- package/dist/utils/updateDiffHunks.js.map +1 -1
- package/dist/utils/wrapTokenFragments.js.map +1 -1
- package/dist/worker/WorkerPoolManager.d.ts +14 -2
- package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
- package/dist/worker/WorkerPoolManager.js +155 -67
- package/dist/worker/WorkerPoolManager.js.map +1 -1
- package/dist/worker/hastLinesTransport.d.ts +14 -0
- package/dist/worker/hastLinesTransport.d.ts.map +1 -0
- package/dist/worker/hastLinesTransport.js +156 -0
- package/dist/worker/hastLinesTransport.js.map +1 -0
- package/dist/worker/highlights-CpZm9DAR.js +317 -0
- package/dist/worker/highlights-CpZm9DAR.js.map +1 -0
- package/dist/worker/index.d.ts +1 -1
- package/dist/worker/shiki-Ci4cdHsM.js +697 -0
- package/dist/worker/shiki-Ci4cdHsM.js.map +1 -0
- package/dist/worker/stream-tokenizer-DK9xp5M5.js +427 -0
- package/dist/worker/stream-tokenizer-DK9xp5M5.js.map +1 -0
- package/dist/worker/types.d.ts +16 -3
- package/dist/worker/types.d.ts.map +1 -1
- package/dist/worker/worker-portable.js +41 -13337
- package/dist/worker/worker-portable.js.map +1 -1
- package/dist/worker/worker.js +681 -349
- package/dist/worker/worker.js.map +1 -1
- package/dist/worker/workerMessage.d.ts +24 -0
- package/dist/worker/workerMessage.d.ts.map +1 -0
- package/dist/worker/workerMessage.js +0 -0
- package/package.json +5 -3
- package/dist/highlighter/themes/constants.d.ts +0 -5
- package/dist/highlighter/themes/constants.d.ts.map +0 -1
- package/dist/highlighter/themes/constants.js +0 -6
- package/dist/highlighter/themes/constants.js.map +0 -1
- package/dist/highlighter/themes/themeResolution.d.ts +0 -7
- package/dist/highlighter/themes/themeResolution.d.ts.map +0 -1
- package/dist/highlighter/themes/themeResolution.js +0 -21
- package/dist/highlighter/themes/themeResolution.js.map +0 -1
- package/dist/shiki-stream/tokenizer.d.ts +0 -23
- package/dist/shiki-stream/tokenizer.d.ts.map +0 -1
- package/dist/shiki-stream/tokenizer.js +0 -72
- package/dist/shiki-stream/tokenizer.js.map +0 -1
- package/dist/utils/createTransformerWithState.d.ts +0 -12
- package/dist/utils/createTransformerWithState.d.ts.map +0 -1
- package/dist/utils/createTransformerWithState.js +0 -89
- package/dist/utils/createTransformerWithState.js.map +0 -1
- package/dist/worker/wasm-B9ZqxnKj.js +0 -8
- package/dist/worker/wasm-B9ZqxnKj.js.map +0 -1
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import "../constants.js";
|
|
2
2
|
import { getFiletypeFromFileName } from "./getFiletypeFromFileName.js";
|
|
3
3
|
import { appendItems } from "./appendItems.js";
|
|
4
|
-
import { createTransformerWithState } from "./createTransformerWithState.js";
|
|
5
|
-
import { formatCSSVariablePrefix } from "./formatCSSVariablePrefix.js";
|
|
6
4
|
import { getHighlighterThemeStyles } from "./getHighlighterThemeStyles.js";
|
|
7
|
-
import {
|
|
5
|
+
import { getTokenOptions } from "./getTokenOptions.js";
|
|
6
|
+
import { setDeferredArrayItem } from "./setDeferredArrayItem.js";
|
|
7
|
+
import { renderTokenLines } from "./renderTokenLines.js";
|
|
8
8
|
import { iterateOverDiff } from "./iterateOverDiff.js";
|
|
9
9
|
import { cleanLastNewline } from "./cleanLastNewline.js";
|
|
10
10
|
import { createDiffSpanDecoration, pushOrJoinSpan } from "./parseDiffDecorations.js";
|
|
11
11
|
import { diffChars, diffWordsWithSpace } from "diff";
|
|
12
12
|
//#region src/utils/renderDiffWithHighlighter.ts
|
|
13
13
|
const DEFAULT_PLAIN_TEXT_OPTIONS = { forcePlainText: false };
|
|
14
|
-
function renderDiffWithHighlighter(diff, highlighter, options, { forcePlainText, startingLine, totalLines, expandedHunks, collapsedContextThreshold = 1 } = DEFAULT_PLAIN_TEXT_OPTIONS) {
|
|
14
|
+
function renderDiffWithHighlighter(diff, highlighter, options, { forcePlainText, lazyLineAST = false, startingLine, totalLines, expandedHunks, collapsedContextThreshold = 1 } = DEFAULT_PLAIN_TEXT_OPTIONS) {
|
|
15
15
|
if (forcePlainText) {
|
|
16
16
|
startingLine ??= 0;
|
|
17
17
|
totalLines ??= Infinity;
|
|
@@ -20,6 +20,7 @@ function renderDiffWithHighlighter(diff, highlighter, options, { forcePlainText,
|
|
|
20
20
|
totalLines = Infinity;
|
|
21
21
|
}
|
|
22
22
|
const isWindowedHighlight = startingLine > 0 || totalLines < Infinity;
|
|
23
|
+
lazyLineAST &&= !forcePlainText && !options.useTokenTransformer;
|
|
23
24
|
const baseThemeType = typeof options.theme === "string" ? highlighter.getTheme(options.theme).type : void 0;
|
|
24
25
|
const themeStyles = getHighlighterThemeStyles({
|
|
25
26
|
theme: options.theme,
|
|
@@ -114,17 +115,27 @@ function renderDiffWithHighlighter(diff, highlighter, options, { forcePlainText,
|
|
|
114
115
|
additionDecorations: bucket.additionDecorations,
|
|
115
116
|
highlighter,
|
|
116
117
|
options,
|
|
117
|
-
languageOverride: forcePlainText ? "text" : diff.lang
|
|
118
|
+
languageOverride: forcePlainText ? "text" : diff.lang,
|
|
119
|
+
lazyLineAST
|
|
118
120
|
});
|
|
119
121
|
if (shouldGroupAll) {
|
|
120
122
|
code.deletionLines = deletionLines;
|
|
121
123
|
code.additionLines = additionLines;
|
|
122
124
|
continue;
|
|
123
125
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
for (const [target, lines, segments] of [[
|
|
127
|
+
code.deletionLines,
|
|
128
|
+
deletionLines,
|
|
129
|
+
bucket.deletionSegments
|
|
130
|
+
], [
|
|
131
|
+
code.additionLines,
|
|
132
|
+
additionLines,
|
|
133
|
+
bucket.additionSegments
|
|
134
|
+
]]) if (segments.length > 0) for (const segment of segments) for (let index = 0; index < segment.count; index++) target[segment.targetIndex + index] = lines[segment.originalOffset + index];
|
|
135
|
+
else if (lazyLineAST) {
|
|
136
|
+
const offset = target.length;
|
|
137
|
+
for (let index = 0; index < lines.length; index++) setDeferredArrayItem(target, offset + index, () => lines[index]);
|
|
138
|
+
} else appendItems(target, lines);
|
|
128
139
|
}
|
|
129
140
|
return {
|
|
130
141
|
code,
|
|
@@ -256,46 +267,20 @@ function createBucket() {
|
|
|
256
267
|
additionSegments: []
|
|
257
268
|
};
|
|
258
269
|
}
|
|
259
|
-
function renderTwoFiles({ deletionFile, additionFile, deletionInfo, additionInfo, highlighter, deletionDecorations, additionDecorations, languageOverride, options: { theme
|
|
260
|
-
const
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
defaultColor: false,
|
|
271
|
-
cssVariablePrefix: formatCSSVariablePrefix("token"),
|
|
272
|
-
tokenizeTimeLimit: 0
|
|
273
|
-
} : {
|
|
274
|
-
...options,
|
|
275
|
-
lang: "text",
|
|
276
|
-
themes: themeOrThemes,
|
|
277
|
-
transformers,
|
|
278
|
-
decorations: void 0,
|
|
279
|
-
defaultColor: false,
|
|
280
|
-
cssVariablePrefix: formatCSSVariablePrefix("token"),
|
|
281
|
-
tokenizeTimeLimit: 0
|
|
282
|
-
};
|
|
283
|
-
})();
|
|
270
|
+
function renderTwoFiles({ lazyLineAST, deletionFile, additionFile, deletionInfo, additionInfo, highlighter, deletionDecorations, additionDecorations, languageOverride, options: { theme, useTokenTransformer, tokenizeMaxLineLength } }) {
|
|
271
|
+
const renderFile = (file, lineInfo, decorations) => {
|
|
272
|
+
if (file.contents === "") return [];
|
|
273
|
+
return renderTokenLines(highlighter.codeToTokens(cleanLastNewline(file.contents), getTokenOptions(languageOverride ?? getFiletypeFromFileName(file.name), theme, tokenizeMaxLineLength)).tokens, {
|
|
274
|
+
state: { lineInfo },
|
|
275
|
+
useTokenTransformer,
|
|
276
|
+
decorations,
|
|
277
|
+
lazyLineAST,
|
|
278
|
+
cacheHtmlStyles: highlighter.name === "highlights"
|
|
279
|
+
});
|
|
280
|
+
};
|
|
284
281
|
return {
|
|
285
|
-
deletionLines: (
|
|
286
|
-
|
|
287
|
-
hastConfig.lang = deletionLang;
|
|
288
|
-
state.lineInfo = deletionInfo;
|
|
289
|
-
hastConfig.decorations = deletionDecorations;
|
|
290
|
-
return getLineNodes(highlighter.codeToHast(cleanLastNewline(deletionFile.contents), hastConfig));
|
|
291
|
-
})(),
|
|
292
|
-
additionLines: (() => {
|
|
293
|
-
if (additionFile.contents === "") return [];
|
|
294
|
-
hastConfig.lang = additionLang;
|
|
295
|
-
hastConfig.decorations = additionDecorations;
|
|
296
|
-
state.lineInfo = additionInfo;
|
|
297
|
-
return getLineNodes(highlighter.codeToHast(cleanLastNewline(additionFile.contents), hastConfig));
|
|
298
|
-
})()
|
|
282
|
+
deletionLines: renderFile(deletionFile, deletionInfo, deletionDecorations),
|
|
283
|
+
additionLines: renderFile(additionFile, additionInfo, additionDecorations)
|
|
299
284
|
};
|
|
300
285
|
}
|
|
301
286
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderDiffWithHighlighter.js","names":[],"sources":["../../src/utils/renderDiffWithHighlighter.ts"],"sourcesContent":["import { type ChangeObject, diffChars, diffWordsWithSpace } from 'diff';\n\nimport { DEFAULT_COLLAPSED_CONTEXT_THRESHOLD } from '../constants';\nimport type {\n CodeToHastOptions,\n DecorationItem,\n DiffsHighlighter,\n DiffsThemeNames,\n FileContents,\n FileDiffMetadata,\n ForceDiffPlainTextOptions,\n LineDiffTypes,\n LineInfo,\n RenderDiffFilesResult,\n RenderDiffOptions,\n SupportedLanguages,\n ThemedDiffResult,\n} from '../types';\nimport { appendItems } from './appendItems';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport { createTransformerWithState } from './createTransformerWithState';\nimport { formatCSSVariablePrefix } from './formatCSSVariablePrefix';\nimport { getFiletypeFromFileName } from './getFiletypeFromFileName';\nimport { getHighlighterThemeStyles } from './getHighlighterThemeStyles';\nimport { getLineNodes } from './getLineNodes';\nimport { iterateOverDiff } from './iterateOverDiff';\nimport {\n createDiffSpanDecoration,\n pushOrJoinSpan,\n} from './parseDiffDecorations';\n\nconst DEFAULT_PLAIN_TEXT_OPTIONS: ForceDiffPlainTextOptions = {\n forcePlainText: false,\n};\n\nexport function renderDiffWithHighlighter(\n diff: FileDiffMetadata,\n highlighter: DiffsHighlighter,\n options: RenderDiffOptions,\n {\n forcePlainText,\n startingLine,\n totalLines,\n expandedHunks,\n collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD,\n }: ForceDiffPlainTextOptions = DEFAULT_PLAIN_TEXT_OPTIONS\n): ThemedDiffResult {\n if (forcePlainText) {\n startingLine ??= 0;\n totalLines ??= Infinity;\n } else {\n // If we aren't forcing plain text, then we intentionally do not support\n // ranges for highlighting as that could break the syntax highlighting, we\n // we override any values that may have been passed in. Maybe one day we\n // warn about this?\n startingLine = 0;\n totalLines = Infinity;\n }\n const isWindowedHighlight = startingLine > 0 || totalLines < Infinity;\n const baseThemeType =\n typeof options.theme === 'string'\n ? highlighter.getTheme(options.theme).type\n : undefined;\n const themeStyles = getHighlighterThemeStyles({\n theme: options.theme,\n highlighter,\n });\n\n // If we have a large file and we are rendering the WHOLE plain diff ast,\n // then we should remove the lineDiffType to make sure things render quickly.\n // For highlighted ASTs or windowed highlights, we should just inherit the\n // setting\n const lineDiffType =\n forcePlainText &&\n !isWindowedHighlight &&\n (diff.unifiedLineCount > 1000 || diff.splitLineCount > 1000)\n ? 'none'\n : options.lineDiffType;\n\n const code: RenderDiffFilesResult = {\n deletionLines: [],\n additionLines: [],\n };\n\n const { maxLineDiffLength } = options;\n const shouldGroupAll = !forcePlainText && !diff.isPartial;\n const expandedHunksForIteration = forcePlainText ? expandedHunks : undefined;\n const buckets = new Map<number, RenderBucket>();\n function getBucketForHunk(hunkIndex: number) {\n const index = shouldGroupAll ? 0 : hunkIndex;\n const bucket = buckets.get(index) ?? createBucket();\n buckets.set(index, bucket);\n return bucket;\n }\n\n function appendContent(\n lineContent: string,\n lineIndex: number,\n segments: HighlightSegment[],\n contentWrapper: FakeArrayType\n ) {\n if (isWindowedHighlight) {\n let segment = segments.at(-1);\n if (\n segment == null ||\n segment.targetIndex + segment.count !== lineIndex\n ) {\n segment = {\n targetIndex: lineIndex,\n originalOffset: contentWrapper.length,\n count: 0,\n };\n segments.push(segment);\n }\n segment.count++;\n }\n contentWrapper.push(lineContent);\n }\n\n iterateOverDiff({\n diff,\n diffStyle: 'both',\n startingLine,\n totalLines,\n expandedHunks: isWindowedHighlight ? expandedHunksForIteration : true,\n collapsedContextThreshold,\n callback: ({ hunkIndex, additionLine, deletionLine, type }) => {\n const bucket = getBucketForHunk(hunkIndex);\n const splitLineIndex =\n additionLine != null\n ? additionLine.splitLineIndex\n : deletionLine.splitLineIndex;\n\n if (type === 'change' && additionLine != null && deletionLine != null) {\n computeLineDiffDecorations({\n additionLine: diff.additionLines[additionLine.lineIndex],\n deletionLine: diff.deletionLines[deletionLine.lineIndex],\n deletionLineIndex: bucket.deletionContent.length,\n additionLineIndex: bucket.additionContent.length,\n deletionDecorations: bucket.deletionDecorations,\n additionDecorations: bucket.additionDecorations,\n lineDiffType,\n maxLineDiffLength,\n });\n }\n\n if (deletionLine != null) {\n appendContent(\n diff.deletionLines[deletionLine.lineIndex],\n deletionLine.lineIndex,\n bucket.deletionSegments,\n bucket.deletionContent\n );\n bucket.deletionInfo.push({\n type: type === 'change' ? 'change-deletion' : type,\n lineNumber: deletionLine.lineNumber,\n altLineNumber:\n type === 'change'\n ? undefined\n : (additionLine.lineNumber ?? undefined),\n lineIndex: `${deletionLine.unifiedLineIndex},${splitLineIndex}`,\n });\n }\n\n if (additionLine != null) {\n appendContent(\n diff.additionLines[additionLine.lineIndex],\n additionLine.lineIndex,\n bucket.additionSegments,\n bucket.additionContent\n );\n bucket.additionInfo.push({\n type: type === 'change' ? 'change-addition' : type,\n lineNumber: additionLine.lineNumber,\n altLineNumber:\n type === 'change'\n ? undefined\n : (deletionLine.lineNumber ?? undefined),\n lineIndex: `${additionLine.unifiedLineIndex},${splitLineIndex}`,\n });\n }\n },\n });\n\n for (const bucket of buckets.values()) {\n if (\n bucket.deletionContent.length === 0 &&\n bucket.additionContent.length === 0\n ) {\n continue;\n }\n\n const deletionFile = {\n name: diff.prevName ?? diff.name,\n contents: bucket.deletionContent.value,\n };\n const additionFile = {\n name: diff.name,\n contents: bucket.additionContent.value,\n };\n const { deletionLines, additionLines } = renderTwoFiles({\n deletionFile,\n deletionInfo: bucket.deletionInfo,\n deletionDecorations: bucket.deletionDecorations,\n\n additionFile,\n additionInfo: bucket.additionInfo,\n additionDecorations: bucket.additionDecorations,\n\n highlighter,\n options,\n languageOverride: forcePlainText ? 'text' : diff.lang,\n });\n\n if (shouldGroupAll) {\n code.deletionLines = deletionLines;\n code.additionLines = additionLines;\n continue;\n }\n\n if (bucket.deletionSegments.length > 0) {\n for (const seg of bucket.deletionSegments) {\n for (let i = 0; i < seg.count; i++) {\n code.deletionLines[seg.targetIndex + i] =\n deletionLines[seg.originalOffset + i];\n }\n }\n } else {\n appendItems(code.deletionLines, deletionLines);\n }\n if (bucket.additionSegments.length > 0) {\n for (const seg of bucket.additionSegments) {\n for (let i = 0; i < seg.count; i++) {\n code.additionLines[seg.targetIndex + i] =\n additionLines[seg.originalOffset + i];\n }\n }\n } else {\n appendItems(code.additionLines, additionLines);\n }\n }\n\n return { code, themeStyles, baseThemeType };\n}\n\n// The line indexes and decoration arrays a line diff writes its highlights to\ninterface LineDiffDecorationTargets {\n deletionLineIndex: number;\n additionLineIndex: number;\n deletionDecorations: DecorationItem[];\n additionDecorations: DecorationItem[];\n}\n\ninterface ProcessLineDiffProps extends LineDiffDecorationTargets {\n deletionLine: string | undefined;\n additionLine: string | undefined;\n lineDiffType: LineDiffTypes;\n maxLineDiffLength: number;\n}\n\n// Push one decoration per side covering the first through last changed\n// token, so each line only has one highlight. Offsets come straight from the\n// diff items, skipping the span arrays the other word modes build.\nfunction pushWordLineDecorations(\n lineDiff: ChangeObject<string>[],\n {\n deletionLineIndex,\n additionLineIndex,\n deletionDecorations,\n additionDecorations,\n }: LineDiffDecorationTargets\n): void {\n let deletionOffset = 0;\n let additionOffset = 0;\n let deletionStart = -1;\n let deletionEnd = 0;\n let additionStart = -1;\n let additionEnd = 0;\n for (const { value, added, removed } of lineDiff) {\n if (removed) {\n if (deletionStart === -1) deletionStart = deletionOffset;\n deletionOffset += value.length;\n deletionEnd = deletionOffset;\n } else if (added) {\n if (additionStart === -1) additionStart = additionOffset;\n additionOffset += value.length;\n additionEnd = additionOffset;\n } else {\n deletionOffset += value.length;\n additionOffset += value.length;\n }\n }\n if (deletionStart !== -1) {\n deletionDecorations.push(\n createDiffSpanDecoration({\n line: deletionLineIndex,\n spanStart: deletionStart,\n spanLength: deletionEnd - deletionStart,\n })\n );\n }\n if (additionStart !== -1) {\n additionDecorations.push(\n createDiffSpanDecoration({\n line: additionLineIndex,\n spanStart: additionStart,\n spanLength: additionEnd - additionStart,\n })\n );\n }\n}\n\nfunction computeLineDiffDecorations({\n deletionLine,\n additionLine,\n deletionLineIndex,\n additionLineIndex,\n deletionDecorations,\n additionDecorations,\n lineDiffType,\n maxLineDiffLength,\n}: ProcessLineDiffProps) {\n if (deletionLine == null || additionLine == null || lineDiffType === 'none') {\n return;\n }\n deletionLine = cleanLastNewline(deletionLine);\n additionLine = cleanLastNewline(additionLine);\n // If we have really long lines, we probably shouldn't compute diffs on them.\n if (\n deletionLine.length > maxLineDiffLength ||\n additionLine.length > maxLineDiffLength\n ) {\n return;\n }\n // NOTE(amadeus): Because we visually trim trailing newlines when rendering,\n // we also gotta make sure the diff parsing doesn't include the newline\n // character that could be there...\n const lineDiff =\n lineDiffType === 'char'\n ? diffChars(deletionLine, additionLine)\n : diffWordsWithSpace(deletionLine, additionLine);\n if (lineDiffType === 'word-line') {\n pushWordLineDecorations(lineDiff, {\n deletionLineIndex,\n additionLineIndex,\n deletionDecorations,\n additionDecorations,\n });\n return;\n }\n const deletionSpans: [0 | 1, string][] = [];\n const additionSpans: [0 | 1, string][] = [];\n const enableJoin = lineDiffType === 'word-alt';\n const lastItem = lineDiff.at(-1);\n for (const item of lineDiff) {\n const isLastItem = item === lastItem;\n if (!item.added && !item.removed) {\n pushOrJoinSpan({\n item,\n arr: deletionSpans,\n enableJoin,\n isNeutral: true,\n isLastItem,\n });\n pushOrJoinSpan({\n item,\n arr: additionSpans,\n enableJoin,\n isNeutral: true,\n isLastItem,\n });\n } else if (item.removed) {\n pushOrJoinSpan({ item, arr: deletionSpans, enableJoin, isLastItem });\n } else {\n pushOrJoinSpan({ item, arr: additionSpans, enableJoin, isLastItem });\n }\n }\n let spanIndex = 0;\n for (const span of deletionSpans) {\n if (span[0] === 1) {\n deletionDecorations.push(\n createDiffSpanDecoration({\n line: deletionLineIndex,\n spanStart: spanIndex,\n spanLength: span[1].length,\n })\n );\n }\n spanIndex += span[1].length;\n }\n spanIndex = 0;\n for (const span of additionSpans) {\n if (span[0] === 1) {\n additionDecorations.push(\n createDiffSpanDecoration({\n line: additionLineIndex,\n spanStart: spanIndex,\n spanLength: span[1].length,\n })\n );\n }\n spanIndex += span[1].length;\n }\n}\n\ninterface HighlightSegment {\n // The where the highlighted region starts\n originalOffset: number;\n // Where to place the highlighted line in RenderDiffFilesResult\n targetIndex: number;\n // Number of highlighted lines\n count: number;\n}\n\ninterface FakeArrayType {\n push(value: string): void;\n value: string;\n length: number;\n}\n\ninterface RenderBucket {\n deletionContent: FakeArrayType;\n additionContent: FakeArrayType;\n deletionInfo: (LineInfo | undefined)[];\n additionInfo: (LineInfo | undefined)[];\n deletionDecorations: DecorationItem[];\n additionDecorations: DecorationItem[];\n deletionSegments: HighlightSegment[];\n additionSegments: HighlightSegment[];\n}\n\nfunction createBucket(): RenderBucket {\n return {\n deletionContent: {\n push(value: string) {\n this.value += value;\n this.length++;\n },\n value: '',\n length: 0,\n },\n additionContent: {\n push(value: string) {\n this.value += value;\n this.length++;\n },\n value: '',\n length: 0,\n },\n deletionInfo: [],\n additionInfo: [],\n deletionDecorations: [],\n additionDecorations: [],\n deletionSegments: [],\n additionSegments: [],\n };\n}\n\ninterface RenderTwoFilesProps {\n deletionFile: FileContents;\n additionFile: FileContents;\n deletionInfo: (LineInfo | undefined)[];\n additionInfo: (LineInfo | undefined)[];\n deletionDecorations: DecorationItem[];\n additionDecorations: DecorationItem[];\n options: RenderDiffOptions;\n highlighter: DiffsHighlighter;\n languageOverride: SupportedLanguages | undefined;\n}\n\nfunction renderTwoFiles({\n deletionFile,\n additionFile,\n deletionInfo,\n additionInfo,\n highlighter,\n deletionDecorations,\n additionDecorations,\n languageOverride,\n options: { theme: themeOrThemes, ...options },\n}: RenderTwoFilesProps): RenderDiffFilesResult {\n const deletionLang =\n languageOverride ?? getFiletypeFromFileName(deletionFile.name);\n const additionLang =\n languageOverride ?? getFiletypeFromFileName(additionFile.name);\n const { state, transformers } = createTransformerWithState(\n options.useTokenTransformer\n );\n // tokenizeTimeLimit: 0 — never trade silently-wrong token colors for\n // latency; see renderFileWithHighlighter for the full rationale.\n const hastConfig: CodeToHastOptions<DiffsThemeNames> = (() => {\n return typeof themeOrThemes === 'string'\n ? {\n ...options,\n // language will be overwritten for each highlight\n lang: 'text',\n theme: themeOrThemes,\n transformers,\n decorations: undefined,\n defaultColor: false,\n cssVariablePrefix: formatCSSVariablePrefix('token'),\n tokenizeTimeLimit: 0,\n }\n : {\n ...options,\n // language will be overwritten for each highlight\n lang: 'text',\n themes: themeOrThemes,\n transformers,\n decorations: undefined,\n defaultColor: false,\n cssVariablePrefix: formatCSSVariablePrefix('token'),\n tokenizeTimeLimit: 0,\n };\n })();\n\n const deletionLines = (() => {\n if (deletionFile.contents === '') {\n return [];\n }\n hastConfig.lang = deletionLang;\n state.lineInfo = deletionInfo;\n hastConfig.decorations = deletionDecorations;\n return getLineNodes(\n highlighter.codeToHast(\n cleanLastNewline(deletionFile.contents),\n hastConfig\n )\n );\n })();\n const additionLines = (() => {\n if (additionFile.contents === '') {\n return [];\n }\n hastConfig.lang = additionLang;\n hastConfig.decorations = additionDecorations;\n state.lineInfo = additionInfo;\n return getLineNodes(\n highlighter.codeToHast(\n cleanLastNewline(additionFile.contents),\n hastConfig\n )\n );\n })();\n\n return { deletionLines, additionLines };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"renderDiffWithHighlighter.js","names":[],"sources":["../../src/utils/renderDiffWithHighlighter.ts"],"sourcesContent":["import { type ChangeObject, diffChars, diffWordsWithSpace } from 'diff';\n\nimport { DEFAULT_COLLAPSED_CONTEXT_THRESHOLD } from '../constants';\nimport type {\n DecorationItem,\n DiffsHighlighter,\n FileContents,\n FileDiffMetadata,\n ForceDiffPlainTextOptions,\n LineDiffTypes,\n LineInfo,\n RenderDiffFilesResult,\n RenderDiffOptions,\n SupportedLanguages,\n ThemedDiffResult,\n} from '../types';\nimport { appendItems } from './appendItems';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport { getFiletypeFromFileName } from './getFiletypeFromFileName';\nimport { getHighlighterThemeStyles } from './getHighlighterThemeStyles';\nimport { getTokenOptions } from './getTokenOptions';\nimport { iterateOverDiff } from './iterateOverDiff';\nimport {\n createDiffSpanDecoration,\n pushOrJoinSpan,\n} from './parseDiffDecorations';\nimport { renderTokenLines } from './renderTokenLines';\nimport { setDeferredArrayItem } from './setDeferredArrayItem';\n\nconst DEFAULT_PLAIN_TEXT_OPTIONS: ForceDiffPlainTextOptions = {\n forcePlainText: false,\n};\n\nexport function renderDiffWithHighlighter(\n diff: FileDiffMetadata,\n highlighter: DiffsHighlighter,\n options: RenderDiffOptions,\n {\n forcePlainText,\n lazyLineAST = false,\n startingLine,\n totalLines,\n expandedHunks,\n collapsedContextThreshold = DEFAULT_COLLAPSED_CONTEXT_THRESHOLD,\n }: ForceDiffPlainTextOptions = DEFAULT_PLAIN_TEXT_OPTIONS\n): ThemedDiffResult {\n if (forcePlainText) {\n startingLine ??= 0;\n totalLines ??= Infinity;\n } else {\n // Tokenization must include preceding lines to preserve lexical state.\n startingLine = 0;\n totalLines = Infinity;\n }\n const isWindowedHighlight = startingLine > 0 || totalLines < Infinity;\n lazyLineAST &&= !forcePlainText && !options.useTokenTransformer;\n const baseThemeType =\n typeof options.theme === 'string'\n ? highlighter.getTheme(options.theme).type\n : undefined;\n const themeStyles = getHighlighterThemeStyles({\n theme: options.theme,\n highlighter,\n });\n\n // If we have a large file and we are rendering the WHOLE plain diff ast,\n // then we should remove the lineDiffType to make sure things render quickly.\n // For highlighted ASTs or windowed highlights, we should just inherit the\n // setting\n const lineDiffType =\n forcePlainText &&\n !isWindowedHighlight &&\n (diff.unifiedLineCount > 1000 || diff.splitLineCount > 1000)\n ? 'none'\n : options.lineDiffType;\n\n const code: RenderDiffFilesResult = {\n deletionLines: [],\n additionLines: [],\n };\n\n const { maxLineDiffLength } = options;\n const shouldGroupAll = !forcePlainText && !diff.isPartial;\n const expandedHunksForIteration = forcePlainText ? expandedHunks : undefined;\n const buckets = new Map<number, RenderBucket>();\n function getBucketForHunk(hunkIndex: number) {\n const index = shouldGroupAll ? 0 : hunkIndex;\n const bucket = buckets.get(index) ?? createBucket();\n buckets.set(index, bucket);\n return bucket;\n }\n\n function appendContent(\n lineContent: string,\n lineIndex: number,\n segments: HighlightSegment[],\n contentWrapper: FakeArrayType\n ) {\n if (isWindowedHighlight) {\n let segment = segments.at(-1);\n if (\n segment == null ||\n segment.targetIndex + segment.count !== lineIndex\n ) {\n segment = {\n targetIndex: lineIndex,\n originalOffset: contentWrapper.length,\n count: 0,\n };\n segments.push(segment);\n }\n segment.count++;\n }\n contentWrapper.push(lineContent);\n }\n\n iterateOverDiff({\n diff,\n diffStyle: 'both',\n startingLine,\n totalLines,\n expandedHunks: isWindowedHighlight ? expandedHunksForIteration : true,\n collapsedContextThreshold,\n callback: ({ hunkIndex, additionLine, deletionLine, type }) => {\n const bucket = getBucketForHunk(hunkIndex);\n const splitLineIndex =\n additionLine != null\n ? additionLine.splitLineIndex\n : deletionLine.splitLineIndex;\n\n if (type === 'change' && additionLine != null && deletionLine != null) {\n computeLineDiffDecorations({\n additionLine: diff.additionLines[additionLine.lineIndex],\n deletionLine: diff.deletionLines[deletionLine.lineIndex],\n deletionLineIndex: bucket.deletionContent.length,\n additionLineIndex: bucket.additionContent.length,\n deletionDecorations: bucket.deletionDecorations,\n additionDecorations: bucket.additionDecorations,\n lineDiffType,\n maxLineDiffLength,\n });\n }\n\n if (deletionLine != null) {\n appendContent(\n diff.deletionLines[deletionLine.lineIndex],\n deletionLine.lineIndex,\n bucket.deletionSegments,\n bucket.deletionContent\n );\n bucket.deletionInfo.push({\n type: type === 'change' ? 'change-deletion' : type,\n lineNumber: deletionLine.lineNumber,\n altLineNumber:\n type === 'change'\n ? undefined\n : (additionLine.lineNumber ?? undefined),\n lineIndex: `${deletionLine.unifiedLineIndex},${splitLineIndex}`,\n });\n }\n\n if (additionLine != null) {\n appendContent(\n diff.additionLines[additionLine.lineIndex],\n additionLine.lineIndex,\n bucket.additionSegments,\n bucket.additionContent\n );\n bucket.additionInfo.push({\n type: type === 'change' ? 'change-addition' : type,\n lineNumber: additionLine.lineNumber,\n altLineNumber:\n type === 'change'\n ? undefined\n : (deletionLine.lineNumber ?? undefined),\n lineIndex: `${additionLine.unifiedLineIndex},${splitLineIndex}`,\n });\n }\n },\n });\n\n for (const bucket of buckets.values()) {\n if (\n bucket.deletionContent.length === 0 &&\n bucket.additionContent.length === 0\n ) {\n continue;\n }\n\n const deletionFile = {\n name: diff.prevName ?? diff.name,\n contents: bucket.deletionContent.value,\n };\n const additionFile = {\n name: diff.name,\n contents: bucket.additionContent.value,\n };\n const { deletionLines, additionLines } = renderTwoFiles({\n deletionFile,\n deletionInfo: bucket.deletionInfo,\n deletionDecorations: bucket.deletionDecorations,\n\n additionFile,\n additionInfo: bucket.additionInfo,\n additionDecorations: bucket.additionDecorations,\n\n highlighter,\n options,\n languageOverride: forcePlainText ? 'text' : diff.lang,\n lazyLineAST,\n });\n\n if (shouldGroupAll) {\n code.deletionLines = deletionLines;\n code.additionLines = additionLines;\n continue;\n }\n\n for (const [target, lines, segments] of [\n [code.deletionLines, deletionLines, bucket.deletionSegments],\n [code.additionLines, additionLines, bucket.additionSegments],\n ] as const) {\n if (segments.length > 0) {\n for (const segment of segments) {\n for (let index = 0; index < segment.count; index++) {\n target[segment.targetIndex + index] =\n lines[segment.originalOffset + index];\n }\n }\n } else if (lazyLineAST) {\n const offset = target.length;\n for (let index = 0; index < lines.length; index++) {\n setDeferredArrayItem(target, offset + index, () => lines[index]);\n }\n } else {\n appendItems(target, lines);\n }\n }\n }\n\n return { code, themeStyles, baseThemeType };\n}\n\n// The line indexes and decoration arrays a line diff writes its highlights to\ninterface LineDiffDecorationTargets {\n deletionLineIndex: number;\n additionLineIndex: number;\n deletionDecorations: DecorationItem[];\n additionDecorations: DecorationItem[];\n}\n\ninterface ProcessLineDiffProps extends LineDiffDecorationTargets {\n deletionLine: string | undefined;\n additionLine: string | undefined;\n lineDiffType: LineDiffTypes;\n maxLineDiffLength: number;\n}\n\n// Push one decoration per side covering the first through last changed\n// token, so each line only has one highlight. Offsets come straight from the\n// diff items, skipping the span arrays the other word modes build.\nfunction pushWordLineDecorations(\n lineDiff: ChangeObject<string>[],\n {\n deletionLineIndex,\n additionLineIndex,\n deletionDecorations,\n additionDecorations,\n }: LineDiffDecorationTargets\n): void {\n let deletionOffset = 0;\n let additionOffset = 0;\n let deletionStart = -1;\n let deletionEnd = 0;\n let additionStart = -1;\n let additionEnd = 0;\n for (const { value, added, removed } of lineDiff) {\n if (removed) {\n if (deletionStart === -1) deletionStart = deletionOffset;\n deletionOffset += value.length;\n deletionEnd = deletionOffset;\n } else if (added) {\n if (additionStart === -1) additionStart = additionOffset;\n additionOffset += value.length;\n additionEnd = additionOffset;\n } else {\n deletionOffset += value.length;\n additionOffset += value.length;\n }\n }\n if (deletionStart !== -1) {\n deletionDecorations.push(\n createDiffSpanDecoration({\n line: deletionLineIndex,\n spanStart: deletionStart,\n spanLength: deletionEnd - deletionStart,\n })\n );\n }\n if (additionStart !== -1) {\n additionDecorations.push(\n createDiffSpanDecoration({\n line: additionLineIndex,\n spanStart: additionStart,\n spanLength: additionEnd - additionStart,\n })\n );\n }\n}\n\nfunction computeLineDiffDecorations({\n deletionLine,\n additionLine,\n deletionLineIndex,\n additionLineIndex,\n deletionDecorations,\n additionDecorations,\n lineDiffType,\n maxLineDiffLength,\n}: ProcessLineDiffProps) {\n if (deletionLine == null || additionLine == null || lineDiffType === 'none') {\n return;\n }\n deletionLine = cleanLastNewline(deletionLine);\n additionLine = cleanLastNewline(additionLine);\n // If we have really long lines, we probably shouldn't compute diffs on them.\n if (\n deletionLine.length > maxLineDiffLength ||\n additionLine.length > maxLineDiffLength\n ) {\n return;\n }\n // NOTE(amadeus): Because we visually trim trailing newlines when rendering,\n // we also gotta make sure the diff parsing doesn't include the newline\n // character that could be there...\n const lineDiff =\n lineDiffType === 'char'\n ? diffChars(deletionLine, additionLine)\n : diffWordsWithSpace(deletionLine, additionLine);\n if (lineDiffType === 'word-line') {\n pushWordLineDecorations(lineDiff, {\n deletionLineIndex,\n additionLineIndex,\n deletionDecorations,\n additionDecorations,\n });\n return;\n }\n const deletionSpans: [0 | 1, string][] = [];\n const additionSpans: [0 | 1, string][] = [];\n const enableJoin = lineDiffType === 'word-alt';\n const lastItem = lineDiff.at(-1);\n for (const item of lineDiff) {\n const isLastItem = item === lastItem;\n if (!item.added && !item.removed) {\n pushOrJoinSpan({\n item,\n arr: deletionSpans,\n enableJoin,\n isNeutral: true,\n isLastItem,\n });\n pushOrJoinSpan({\n item,\n arr: additionSpans,\n enableJoin,\n isNeutral: true,\n isLastItem,\n });\n } else if (item.removed) {\n pushOrJoinSpan({ item, arr: deletionSpans, enableJoin, isLastItem });\n } else {\n pushOrJoinSpan({ item, arr: additionSpans, enableJoin, isLastItem });\n }\n }\n let spanIndex = 0;\n for (const span of deletionSpans) {\n if (span[0] === 1) {\n deletionDecorations.push(\n createDiffSpanDecoration({\n line: deletionLineIndex,\n spanStart: spanIndex,\n spanLength: span[1].length,\n })\n );\n }\n spanIndex += span[1].length;\n }\n spanIndex = 0;\n for (const span of additionSpans) {\n if (span[0] === 1) {\n additionDecorations.push(\n createDiffSpanDecoration({\n line: additionLineIndex,\n spanStart: spanIndex,\n spanLength: span[1].length,\n })\n );\n }\n spanIndex += span[1].length;\n }\n}\n\ninterface HighlightSegment {\n // The where the highlighted region starts\n originalOffset: number;\n // Where to place the highlighted line in RenderDiffFilesResult\n targetIndex: number;\n // Number of highlighted lines\n count: number;\n}\n\ninterface FakeArrayType {\n push(value: string): void;\n value: string;\n length: number;\n}\n\ninterface RenderBucket {\n deletionContent: FakeArrayType;\n additionContent: FakeArrayType;\n deletionInfo: (LineInfo | undefined)[];\n additionInfo: (LineInfo | undefined)[];\n deletionDecorations: DecorationItem[];\n additionDecorations: DecorationItem[];\n deletionSegments: HighlightSegment[];\n additionSegments: HighlightSegment[];\n}\n\nfunction createBucket(): RenderBucket {\n return {\n deletionContent: {\n push(value: string) {\n this.value += value;\n this.length++;\n },\n value: '',\n length: 0,\n },\n additionContent: {\n push(value: string) {\n this.value += value;\n this.length++;\n },\n value: '',\n length: 0,\n },\n deletionInfo: [],\n additionInfo: [],\n deletionDecorations: [],\n additionDecorations: [],\n deletionSegments: [],\n additionSegments: [],\n };\n}\n\ninterface RenderTwoFilesProps {\n lazyLineAST: boolean;\n deletionFile: FileContents;\n additionFile: FileContents;\n deletionInfo: (LineInfo | undefined)[];\n additionInfo: (LineInfo | undefined)[];\n deletionDecorations: DecorationItem[];\n additionDecorations: DecorationItem[];\n options: RenderDiffOptions;\n highlighter: DiffsHighlighter;\n languageOverride: SupportedLanguages | undefined;\n}\n\nfunction renderTwoFiles({\n lazyLineAST,\n deletionFile,\n additionFile,\n deletionInfo,\n additionInfo,\n highlighter,\n deletionDecorations,\n additionDecorations,\n languageOverride,\n options: { theme, useTokenTransformer, tokenizeMaxLineLength },\n}: RenderTwoFilesProps): RenderDiffFilesResult {\n const renderFile = (\n file: FileContents,\n lineInfo: (LineInfo | undefined)[],\n decorations: DecorationItem[]\n ): RenderDiffFilesResult['additionLines'] => {\n if (file.contents === '') return [];\n return renderTokenLines(\n highlighter.codeToTokens(\n cleanLastNewline(file.contents),\n getTokenOptions(\n languageOverride ?? getFiletypeFromFileName(file.name),\n theme,\n tokenizeMaxLineLength\n )\n ).tokens,\n {\n state: { lineInfo },\n useTokenTransformer,\n decorations,\n lazyLineAST,\n cacheHtmlStyles: highlighter.name === 'highlights',\n }\n );\n };\n\n return {\n deletionLines: renderFile(deletionFile, deletionInfo, deletionDecorations),\n additionLines: renderFile(additionFile, additionInfo, additionDecorations),\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { DiffsHighlighter
|
|
1
|
+
import { DiffsHighlighter } from "../highlighter/DiffsHighlighter.js";
|
|
2
|
+
import { FileContents, ForceFilePlainTextOptions, RenderFileOptions, ThemedFileResult } from "../types.js";
|
|
2
3
|
//#region src/utils/renderFileWithHighlighter.d.ts
|
|
3
|
-
declare function renderFileWithHighlighter(file: FileContents, highlighter: DiffsHighlighter, { theme, tokenizeMaxLineLength, useTokenTransformer }: RenderFileOptions, { forcePlainText, startingLine, totalLines, lines }?: ForceFilePlainTextOptions): ThemedFileResult;
|
|
4
|
+
declare function renderFileWithHighlighter(file: FileContents, highlighter: DiffsHighlighter, { theme, tokenizeMaxLineLength, useTokenTransformer }: RenderFileOptions, { forcePlainText, lazyLineAST, startingLine, totalLines, lines }?: ForceFilePlainTextOptions): ThemedFileResult;
|
|
4
5
|
//#endregion
|
|
5
6
|
export { renderFileWithHighlighter };
|
|
6
7
|
//# sourceMappingURL=renderFileWithHighlighter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderFileWithHighlighter.d.ts","names":[],"sources":["../../src/utils/renderFileWithHighlighter.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"renderFileWithHighlighter.d.ts","names":[],"sources":["../../src/utils/renderFileWithHighlighter.ts"],"mappings":";;;iBAmBgB,0BACd,MAAM,cACN,aAAa,oBACX,OAAO,uBAAuB,uBAAuB,qBAErD,gBACA,aACA,cACA,YACA,UACC,4BACF"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { linesFromFileContents } from "./computeFileOffsets.js";
|
|
2
2
|
import { getFiletypeFromFileName } from "./getFiletypeFromFileName.js";
|
|
3
3
|
import { appendItems } from "./appendItems.js";
|
|
4
|
-
import { createTransformerWithState } from "./createTransformerWithState.js";
|
|
5
|
-
import { formatCSSVariablePrefix } from "./formatCSSVariablePrefix.js";
|
|
6
4
|
import { getHighlighterThemeStyles } from "./getHighlighterThemeStyles.js";
|
|
7
|
-
import {
|
|
5
|
+
import { getTokenOptions } from "./getTokenOptions.js";
|
|
6
|
+
import { renderTokenLines } from "./renderTokenLines.js";
|
|
8
7
|
//#region src/utils/renderFileWithHighlighter.ts
|
|
9
8
|
const DEFAULT_PLAIN_TEXT_OPTIONS = { forcePlainText: false };
|
|
10
|
-
function renderFileWithHighlighter(file, highlighter, { theme, tokenizeMaxLineLength, useTokenTransformer }, { forcePlainText, startingLine, totalLines, lines } = DEFAULT_PLAIN_TEXT_OPTIONS) {
|
|
9
|
+
function renderFileWithHighlighter(file, highlighter, { theme, tokenizeMaxLineLength, useTokenTransformer }, { forcePlainText, lazyLineAST = false, startingLine, totalLines, lines } = DEFAULT_PLAIN_TEXT_OPTIONS) {
|
|
11
10
|
if (forcePlainText) {
|
|
12
11
|
startingLine ??= 0;
|
|
13
12
|
totalLines ??= Infinity;
|
|
@@ -16,7 +15,7 @@ function renderFileWithHighlighter(file, highlighter, { theme, tokenizeMaxLineLe
|
|
|
16
15
|
totalLines = Infinity;
|
|
17
16
|
}
|
|
18
17
|
const isWindowedHighlight = startingLine > 0 || totalLines < Infinity;
|
|
19
|
-
const {
|
|
18
|
+
const state = { lineInfo: [] };
|
|
20
19
|
const lang = forcePlainText ? "text" : file.lang ?? getFiletypeFromFileName(file.name);
|
|
21
20
|
const baseThemeType = typeof theme === "string" ? highlighter.getTheme(theme).type : void 0;
|
|
22
21
|
const themeStyles = getHighlighterThemeStyles({
|
|
@@ -28,27 +27,12 @@ function renderFileWithHighlighter(file, highlighter, { theme, tokenizeMaxLineLe
|
|
|
28
27
|
lineIndex: shikiLineNumber - 1 + startingLine,
|
|
29
28
|
lineNumber: shikiLineNumber + startingLine
|
|
30
29
|
});
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
cssVariablePrefix: formatCSSVariablePrefix("token"),
|
|
38
|
-
tokenizeMaxLineLength,
|
|
39
|
-
tokenizeTimeLimit: 0
|
|
40
|
-
};
|
|
41
|
-
return {
|
|
42
|
-
lang,
|
|
43
|
-
themes: theme,
|
|
44
|
-
transformers,
|
|
45
|
-
defaultColor: false,
|
|
46
|
-
cssVariablePrefix: formatCSSVariablePrefix("token"),
|
|
47
|
-
tokenizeMaxLineLength,
|
|
48
|
-
tokenizeTimeLimit: 0
|
|
49
|
-
};
|
|
50
|
-
})();
|
|
51
|
-
const highlightedLines = getLineNodes(highlighter.codeToHast(normalizeHighlightLineEndings(isWindowedHighlight ? extractWindowedFileContent(lines ?? linesFromFileContents(file.contents), startingLine, totalLines) : file.contents), hastConfig));
|
|
30
|
+
const highlightedLines = renderTokenLines(highlighter.codeToTokens(normalizeHighlightLineEndings(isWindowedHighlight ? extractWindowedFileContent(lines ?? linesFromFileContents(file.contents), startingLine, totalLines) : file.contents), getTokenOptions(lang, theme, tokenizeMaxLineLength)).tokens, {
|
|
31
|
+
state,
|
|
32
|
+
useTokenTransformer,
|
|
33
|
+
lazyLineAST: lazyLineAST && !forcePlainText && !useTokenTransformer,
|
|
34
|
+
cacheHtmlStyles: highlighter.name === "highlights"
|
|
35
|
+
});
|
|
52
36
|
const code = isWindowedHighlight ? new Array(startingLine) : highlightedLines;
|
|
53
37
|
if (isWindowedHighlight) appendItems(code, highlightedLines);
|
|
54
38
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderFileWithHighlighter.js","names":[],"sources":["../../src/utils/renderFileWithHighlighter.ts"],"sourcesContent":["import type {\n
|
|
1
|
+
{"version":3,"file":"renderFileWithHighlighter.js","names":[],"sources":["../../src/utils/renderFileWithHighlighter.ts"],"sourcesContent":["import type {\n DiffsHighlighter,\n FileContents,\n ForceFilePlainTextOptions,\n RenderFileOptions,\n SharedRenderState,\n ThemedFileResult,\n} from '../types';\nimport { appendItems } from './appendItems';\nimport { linesFromFileContents } from './computeFileOffsets';\nimport { getFiletypeFromFileName } from './getFiletypeFromFileName';\nimport { getHighlighterThemeStyles } from './getHighlighterThemeStyles';\nimport { getTokenOptions } from './getTokenOptions';\nimport { renderTokenLines } from './renderTokenLines';\n\nconst DEFAULT_PLAIN_TEXT_OPTIONS: ForceFilePlainTextOptions = {\n forcePlainText: false,\n};\n\nexport function renderFileWithHighlighter(\n file: FileContents,\n highlighter: DiffsHighlighter,\n { theme, tokenizeMaxLineLength, useTokenTransformer }: RenderFileOptions,\n {\n forcePlainText,\n lazyLineAST = false,\n startingLine,\n totalLines,\n lines,\n }: ForceFilePlainTextOptions = DEFAULT_PLAIN_TEXT_OPTIONS\n): ThemedFileResult {\n if (forcePlainText) {\n startingLine ??= 0;\n totalLines ??= Infinity;\n } else {\n // Tokenization must include preceding lines to preserve lexical state.\n startingLine = 0;\n totalLines = Infinity;\n }\n const isWindowedHighlight = startingLine > 0 || totalLines < Infinity;\n const state: SharedRenderState = { lineInfo: [] };\n const lang = forcePlainText\n ? 'text'\n : (file.lang ?? getFiletypeFromFileName(file.name));\n const baseThemeType =\n typeof theme === 'string' ? highlighter.getTheme(theme).type : undefined;\n const themeStyles = getHighlighterThemeStyles({\n theme,\n highlighter,\n });\n state.lineInfo = (shikiLineNumber: number) => ({\n type: 'context',\n lineIndex: shikiLineNumber - 1 + startingLine,\n lineNumber: shikiLineNumber + startingLine,\n });\n const highlightedLines = renderTokenLines(\n highlighter.codeToTokens(\n normalizeHighlightLineEndings(\n isWindowedHighlight\n ? extractWindowedFileContent(\n lines ?? linesFromFileContents(file.contents),\n startingLine,\n totalLines\n )\n : file.contents\n ),\n getTokenOptions(lang, theme, tokenizeMaxLineLength)\n ).tokens,\n {\n state,\n useTokenTransformer,\n lazyLineAST: lazyLineAST && !forcePlainText && !useTokenTransformer,\n cacheHtmlStyles: highlighter.name === 'highlights',\n }\n );\n\n // Create sparse array for windowed rendering\n const code = isWindowedHighlight ? new Array(startingLine) : highlightedLines;\n if (isWindowedHighlight) {\n appendItems(code, highlightedLines);\n }\n\n return { code, themeStyles, baseThemeType };\n}\n\n// Shiki does not treat a lone carriage return as a line break. Normalize only\n// the text sent to the highlighter so its output stays aligned with the file\n// model while the original document retains its line endings.\nfunction normalizeHighlightLineEndings(contents: string): string {\n return contents.replace(/\\r(?!\\n)/g, '\\n');\n}\n\nfunction extractWindowedFileContent(\n lines: string[],\n startingLine: number,\n totalLines: number\n): string {\n if (lines.length === 0) {\n return '';\n }\n const endLine = Math.min(startingLine + totalLines, lines.length);\n return lines.slice(startingLine, endLine).join('');\n}\n"],"mappings":";;;;;;;AAeA,MAAM,6BAAwD,EAC5D,gBAAgB,MAClB;AAEA,SAAgB,0BACd,MACA,aACA,EAAE,OAAO,uBAAuB,uBAChC,EACE,gBACA,cAAc,OACd,cACA,YACA,UAC6B,4BACb;CAClB,IAAI,gBAAgB;EAClB,iBAAiB;EACjB,eAAe;CACjB,OAAO;EAEL,eAAe;EACf,aAAa;CACf;CACA,MAAM,sBAAsB,eAAe,KAAK,aAAa;CAC7D,MAAM,QAA2B,EAAE,UAAU,CAAC,EAAE;CAChD,MAAM,OAAO,iBACT,SACC,KAAK,QAAQ,wBAAwB,KAAK,IAAI;CACnD,MAAM,gBACJ,OAAO,UAAU,WAAW,YAAY,SAAS,KAAK,CAAC,CAAC,OAAO,KAAA;CACjE,MAAM,cAAc,0BAA0B;EAC5C;EACA;CACF,CAAC;CACD,MAAM,YAAY,qBAA6B;EAC7C,MAAM;EACN,WAAW,kBAAkB,IAAI;EACjC,YAAY,kBAAkB;CAChC;CACA,MAAM,mBAAmB,iBACvB,YAAY,aACV,8BACE,sBACI,2BACE,SAAS,sBAAsB,KAAK,QAAQ,GAC5C,cACA,UACF,IACA,KAAK,QACX,GACA,gBAAgB,MAAM,OAAO,qBAAqB,CACpD,CAAC,CAAC,QACF;EACE;EACA;EACA,aAAa,eAAe,CAAC,kBAAkB,CAAC;EAChD,iBAAiB,YAAY,SAAS;CACxC,CACF;CAGA,MAAM,OAAO,sBAAsB,IAAI,MAAM,YAAY,IAAI;CAC7D,IAAI,qBACF,YAAY,MAAM,gBAAgB;CAGpC,OAAO;EAAE;EAAM;EAAa;CAAc;AAC5C;AAKA,SAAS,8BAA8B,UAA0B;CAC/D,OAAO,SAAS,QAAQ,aAAa,IAAI;AAC3C;AAEA,SAAS,2BACP,OACA,cACA,YACQ;CACR,IAAI,MAAM,WAAW,GACnB,OAAO;CAET,MAAM,UAAU,KAAK,IAAI,eAAe,YAAY,MAAM,MAAM;CAChE,OAAO,MAAM,MAAM,cAAc,OAAO,CAAC,CAAC,KAAK,EAAE;AACnD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ElementContent } from "../node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.js";
|
|
2
|
+
import { DecorationItem, ThemedToken } from "../highlighter/types.js";
|
|
3
|
+
import { SharedRenderState } from "../types.js";
|
|
4
|
+
//#region src/utils/renderTokenLines.d.ts
|
|
5
|
+
interface RenderTokenLinesOptions {
|
|
6
|
+
lazyLineAST?: boolean;
|
|
7
|
+
cacheHtmlStyles?: boolean;
|
|
8
|
+
state?: SharedRenderState;
|
|
9
|
+
useTokenTransformer?: boolean;
|
|
10
|
+
mergeWhitespaces?: 'never' | 'always';
|
|
11
|
+
decorations?: DecorationItem[];
|
|
12
|
+
/** UTF-16 line start offsets, required for numeric decoration positions. */
|
|
13
|
+
lineOffsets?: number[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Converts highlighted tokens to one HAST element per line for custom renderers.
|
|
17
|
+
* Callers provide any line separators and enclosing pre/code elements.
|
|
18
|
+
*/
|
|
19
|
+
declare function renderTokenLines(lines: ThemedToken[][], { state, lazyLineAST, cacheHtmlStyles, useTokenTransformer, mergeWhitespaces, decorations, lineOffsets }: RenderTokenLinesOptions): ElementContent[];
|
|
20
|
+
//#endregion
|
|
21
|
+
export { RenderTokenLinesOptions, renderTokenLines };
|
|
22
|
+
//# sourceMappingURL=renderTokenLines.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderTokenLines.d.ts","names":[],"sources":["../../src/utils/renderTokenLines.ts"],"mappings":";;;;UAQiB;EACf;EACA;EACA,QAAQ;EACR;EACA;EACA,cAAc;;EAEd;;;;;;iBA0Bc,iBACd,OAAO,mBAEL,OACA,aACA,iBACA,qBACA,kBACA,aACA,eACC,0BACF"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { processLine } from "./processLine.js";
|
|
2
|
+
import { setDeferredArrayItem } from "./setDeferredArrayItem.js";
|
|
3
|
+
import { tokenStyle } from "./tokenStyle.js";
|
|
4
|
+
import { wrapTokenFragments } from "./wrapTokenFragments.js";
|
|
5
|
+
//#region src/utils/renderTokenLines.ts
|
|
6
|
+
/**
|
|
7
|
+
* Converts highlighted tokens to one HAST element per line for custom renderers.
|
|
8
|
+
* Callers provide any line separators and enclosing pre/code elements.
|
|
9
|
+
*/
|
|
10
|
+
function renderTokenLines(lines, { state, lazyLineAST = false, cacheHtmlStyles = false, useTokenTransformer = false, mergeWhitespaces = "always", decorations = [], lineOffsets = [] }) {
|
|
11
|
+
let decorationsByLine;
|
|
12
|
+
for (const decoration of decorations) {
|
|
13
|
+
const byLine = decorationsByLine ??= /* @__PURE__ */ new Map();
|
|
14
|
+
const normalized = {
|
|
15
|
+
...decoration,
|
|
16
|
+
start: getDecorationPosition(decoration.start, lineOffsets),
|
|
17
|
+
end: getDecorationPosition(decoration.end, lineOffsets)
|
|
18
|
+
};
|
|
19
|
+
const lastLine = Math.min(normalized.end.line, lines.length - 1);
|
|
20
|
+
for (let line = normalized.start.line; line <= lastLine; line++) {
|
|
21
|
+
let spans = byLine.get(line);
|
|
22
|
+
if (spans == null) byLine.set(line, spans = []);
|
|
23
|
+
spans.push(normalized);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const renderLine = (tokens, lineIndex) => {
|
|
27
|
+
let normalized;
|
|
28
|
+
if (useTokenTransformer || mergeWhitespaces !== "never") {
|
|
29
|
+
let pendingWhitespace = "";
|
|
30
|
+
let whitespaceOffset = 0;
|
|
31
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
32
|
+
let token = tokens[i];
|
|
33
|
+
if (useTokenTransformer) {
|
|
34
|
+
const content = token.content.trim();
|
|
35
|
+
if (content !== "" && content !== token.content) {
|
|
36
|
+
normalized ??= tokens.slice(0, i);
|
|
37
|
+
const start = token.content.indexOf(content);
|
|
38
|
+
if (start > 0) normalized.push({
|
|
39
|
+
content: token.content.slice(0, start),
|
|
40
|
+
offset: token.offset
|
|
41
|
+
});
|
|
42
|
+
normalized.push({
|
|
43
|
+
...token,
|
|
44
|
+
content,
|
|
45
|
+
offset: token.offset + start
|
|
46
|
+
});
|
|
47
|
+
const end = start + content.length;
|
|
48
|
+
if (end < token.content.length) normalized.push({
|
|
49
|
+
content: token.content.slice(end),
|
|
50
|
+
offset: token.offset + end
|
|
51
|
+
});
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
const decoratedWhitespace = ((token.fontStyle ?? 0) & 12) !== 0;
|
|
56
|
+
if (!decoratedWhitespace && /^\s+$/.test(token.content) && i < tokens.length - 1) {
|
|
57
|
+
normalized ??= tokens.slice(0, i);
|
|
58
|
+
if (pendingWhitespace === "") whitespaceOffset = token.offset;
|
|
59
|
+
pendingWhitespace += token.content;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (pendingWhitespace !== "" && normalized != null) {
|
|
63
|
+
if (decoratedWhitespace) normalized.push({
|
|
64
|
+
content: pendingWhitespace,
|
|
65
|
+
offset: whitespaceOffset
|
|
66
|
+
});
|
|
67
|
+
else token = {
|
|
68
|
+
...token,
|
|
69
|
+
content: pendingWhitespace + token.content,
|
|
70
|
+
offset: whitespaceOffset
|
|
71
|
+
};
|
|
72
|
+
pendingWhitespace = "";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
normalized?.push(token);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
normalized ??= tokens;
|
|
79
|
+
const line = {
|
|
80
|
+
type: "element",
|
|
81
|
+
tagName: state == null ? "span" : "div",
|
|
82
|
+
properties: state == null ? { class: "line" } : {},
|
|
83
|
+
children: []
|
|
84
|
+
};
|
|
85
|
+
const spans = decorationsByLine?.get(lineIndex);
|
|
86
|
+
const column = spans == null ? appendTokens(line, normalized, useTokenTransformer, cacheHtmlStyles) : appendDecoratedTokens(line, normalized, spans, lineIndex, useTokenTransformer, cacheHtmlStyles);
|
|
87
|
+
if (useTokenTransformer && column === 0) line.children.push({
|
|
88
|
+
type: "element",
|
|
89
|
+
tagName: "br",
|
|
90
|
+
properties: {},
|
|
91
|
+
children: []
|
|
92
|
+
});
|
|
93
|
+
if (useTokenTransformer && spans != null) wrapTokenFragments(line);
|
|
94
|
+
return state == null ? line : processLine(line, lineIndex + 1, state);
|
|
95
|
+
};
|
|
96
|
+
if (!lazyLineAST) return lines.map(renderLine);
|
|
97
|
+
const rows = new Array(lines.length);
|
|
98
|
+
for (let index = 0; index < lines.length; index++) {
|
|
99
|
+
const tokens = lines[index];
|
|
100
|
+
setDeferredArrayItem(rows, index, () => renderLine(tokens, index));
|
|
101
|
+
}
|
|
102
|
+
return rows;
|
|
103
|
+
}
|
|
104
|
+
function appendTokens(line, tokens, useTokenTransformer, cacheHtmlStyles) {
|
|
105
|
+
let column = 0;
|
|
106
|
+
for (const token of tokens) {
|
|
107
|
+
if (token.content === "") continue;
|
|
108
|
+
line.children.push(createTokenSpan(token, tokenStyle(token, cacheHtmlStyles), token.content, column, useTokenTransformer));
|
|
109
|
+
column += token.content.length;
|
|
110
|
+
}
|
|
111
|
+
return column;
|
|
112
|
+
}
|
|
113
|
+
function appendDecoratedTokens(line, tokens, spans, lineIndex, useTokenTransformer, cacheHtmlStyles) {
|
|
114
|
+
if (spans.length > 1) spans.sort((a, b) => {
|
|
115
|
+
if (a.start.line !== b.start.line) return a.start.line - b.start.line;
|
|
116
|
+
if (a.start.character !== b.start.character) return a.start.character - b.start.character;
|
|
117
|
+
if (a.end.line !== b.end.line) return b.end.line - a.end.line;
|
|
118
|
+
return b.end.character - a.end.character;
|
|
119
|
+
});
|
|
120
|
+
const lineLength = tokens.reduce((length, token) => length + token.content.length, 0);
|
|
121
|
+
const boundaries = [];
|
|
122
|
+
for (let order = 0; order < spans.length; order++) {
|
|
123
|
+
const decoration = spans[order];
|
|
124
|
+
const range = {
|
|
125
|
+
decoration,
|
|
126
|
+
order,
|
|
127
|
+
from: decoration.start.line === lineIndex ? decoration.start.character : 0,
|
|
128
|
+
to: decoration.end.line === lineIndex ? decoration.end.character : lineLength
|
|
129
|
+
};
|
|
130
|
+
boundaries.push({
|
|
131
|
+
position: Math.max(0, Math.min(range.from, lineLength)),
|
|
132
|
+
range,
|
|
133
|
+
start: true
|
|
134
|
+
}, {
|
|
135
|
+
position: Math.max(0, Math.min(range.to, lineLength)),
|
|
136
|
+
range,
|
|
137
|
+
start: false
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
boundaries.sort((a, b) => a.position - b.position);
|
|
141
|
+
const active = [];
|
|
142
|
+
const decorationStack = [];
|
|
143
|
+
let boundaryIndex = 0;
|
|
144
|
+
const updateActive = (range, add) => {
|
|
145
|
+
let low = 0;
|
|
146
|
+
let high = active.length;
|
|
147
|
+
while (low < high) {
|
|
148
|
+
const middle = low + high >>> 1;
|
|
149
|
+
if (active[middle].order < range.order) low = middle + 1;
|
|
150
|
+
else high = middle;
|
|
151
|
+
}
|
|
152
|
+
if (add) active.splice(low, 0, range);
|
|
153
|
+
else if (active[low] === range) active.splice(low, 1);
|
|
154
|
+
};
|
|
155
|
+
const getParent = () => {
|
|
156
|
+
let parent = line;
|
|
157
|
+
let depth = 0;
|
|
158
|
+
for (const range of active) {
|
|
159
|
+
if (decorationStack[depth]?.range !== range) {
|
|
160
|
+
decorationStack.length = depth;
|
|
161
|
+
const wrapper = {
|
|
162
|
+
type: "element",
|
|
163
|
+
tagName: "span",
|
|
164
|
+
properties: { ...range.decoration.properties },
|
|
165
|
+
children: []
|
|
166
|
+
};
|
|
167
|
+
parent.children.push(wrapper);
|
|
168
|
+
decorationStack.push({
|
|
169
|
+
range,
|
|
170
|
+
node: wrapper
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
parent = decorationStack[depth++].node;
|
|
174
|
+
}
|
|
175
|
+
decorationStack.length = depth;
|
|
176
|
+
return parent;
|
|
177
|
+
};
|
|
178
|
+
let parent = line;
|
|
179
|
+
const advanceBoundary = (position) => {
|
|
180
|
+
const first = boundaryIndex;
|
|
181
|
+
while (boundaries[boundaryIndex]?.position === position) boundaryIndex++;
|
|
182
|
+
let hasMarker = false;
|
|
183
|
+
for (let i = first; i < boundaryIndex; i++) {
|
|
184
|
+
const { range, start } = boundaries[i];
|
|
185
|
+
if (!start && range.from !== range.to && position < lineLength) updateActive(range, false);
|
|
186
|
+
}
|
|
187
|
+
for (let i = first; i < boundaryIndex; i++) {
|
|
188
|
+
const { range, start } = boundaries[i];
|
|
189
|
+
if (start && range.from <= position && range.to >= position && (range.to > position || range.from === position || position === lineLength)) {
|
|
190
|
+
updateActive(range, true);
|
|
191
|
+
if (range.from === range.to) hasMarker = true;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (hasMarker) {
|
|
195
|
+
getParent();
|
|
196
|
+
for (let i = first; i < boundaryIndex; i++) {
|
|
197
|
+
const { range, start } = boundaries[i];
|
|
198
|
+
if (start && range.from === range.to) updateActive(range, false);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (position < lineLength) parent = getParent();
|
|
202
|
+
};
|
|
203
|
+
let column = 0;
|
|
204
|
+
for (const token of tokens) {
|
|
205
|
+
if (token.content === "") continue;
|
|
206
|
+
const start = column;
|
|
207
|
+
const end = start + token.content.length;
|
|
208
|
+
const style = tokenStyle(token, cacheHtmlStyles);
|
|
209
|
+
while (column < end) {
|
|
210
|
+
if (boundaries[boundaryIndex]?.position === column) advanceBoundary(column);
|
|
211
|
+
const to = Math.min(end, boundaries[boundaryIndex]?.position ?? end);
|
|
212
|
+
parent.children.push(createTokenSpan(token, style, column === start && to === end ? token.content : token.content.slice(column - start, to - start), start, useTokenTransformer));
|
|
213
|
+
column = to;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (boundaries[boundaryIndex]?.position === column) advanceBoundary(column);
|
|
217
|
+
return column;
|
|
218
|
+
}
|
|
219
|
+
function createTokenSpan(token, style, text, start, useTokenTransformer) {
|
|
220
|
+
const properties = token.htmlAttrs != null ? { ...token.htmlAttrs } : {};
|
|
221
|
+
if (style !== "") properties.style = style;
|
|
222
|
+
if (useTokenTransformer) properties["data-char"] = start;
|
|
223
|
+
return {
|
|
224
|
+
type: "element",
|
|
225
|
+
tagName: "span",
|
|
226
|
+
properties,
|
|
227
|
+
children: [{
|
|
228
|
+
type: "text",
|
|
229
|
+
value: text
|
|
230
|
+
}]
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function getDecorationPosition(position, lineOffsets) {
|
|
234
|
+
if (typeof position !== "number") return position;
|
|
235
|
+
let low = 0;
|
|
236
|
+
let high = lineOffsets.length;
|
|
237
|
+
while (low + 1 < high) {
|
|
238
|
+
const middle = low + high >>> 1;
|
|
239
|
+
if (lineOffsets[middle] <= position) low = middle;
|
|
240
|
+
else high = middle;
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
line: low,
|
|
244
|
+
character: position - (lineOffsets[low] ?? 0)
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
//#endregion
|
|
248
|
+
export { renderTokenLines };
|
|
249
|
+
|
|
250
|
+
//# sourceMappingURL=renderTokenLines.js.map
|