@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.
Files changed (359) hide show
  1. package/README.md +4 -3
  2. package/dist/components/CodeView.d.ts +3 -2
  3. package/dist/components/CodeView.d.ts.map +1 -1
  4. package/dist/components/CodeView.js +24 -19
  5. package/dist/components/CodeView.js.map +1 -1
  6. package/dist/components/File.d.ts +31 -9
  7. package/dist/components/File.d.ts.map +1 -1
  8. package/dist/components/File.js +176 -90
  9. package/dist/components/File.js.map +1 -1
  10. package/dist/components/FileDiff.d.ts +32 -9
  11. package/dist/components/FileDiff.d.ts.map +1 -1
  12. package/dist/components/FileDiff.js +225 -131
  13. package/dist/components/FileDiff.js.map +1 -1
  14. package/dist/components/FileStream.d.ts +6 -4
  15. package/dist/components/FileStream.d.ts.map +1 -1
  16. package/dist/components/FileStream.js +49 -36
  17. package/dist/components/FileStream.js.map +1 -1
  18. package/dist/components/UnresolvedFile.d.ts +14 -4
  19. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  20. package/dist/components/UnresolvedFile.js +35 -16
  21. package/dist/components/UnresolvedFile.js.map +1 -1
  22. package/dist/components/VirtualizedFile.d.ts +3 -2
  23. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  24. package/dist/components/VirtualizedFile.js +28 -20
  25. package/dist/components/VirtualizedFile.js.map +1 -1
  26. package/dist/components/VirtualizedFileDiff.d.ts +3 -2
  27. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  28. package/dist/components/VirtualizedFileDiff.js +31 -24
  29. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  30. package/dist/constants.d.ts +4 -2
  31. package/dist/constants.d.ts.map +1 -1
  32. package/dist/constants.js +3 -1
  33. package/dist/constants.js.map +1 -1
  34. package/dist/editor/editor.d.ts +2 -1
  35. package/dist/editor/editor.d.ts.map +1 -1
  36. package/dist/editor/editor.js +5 -1
  37. package/dist/editor/editor.js.map +1 -1
  38. package/dist/editor/platform.d.ts +1 -1
  39. package/dist/editor/platform.js +5 -4
  40. package/dist/editor/platform.js.map +1 -1
  41. package/dist/editor/selection.d.ts +2 -2
  42. package/dist/editor/selection.d.ts.map +1 -1
  43. package/dist/editor/selection.js +31 -6
  44. package/dist/editor/selection.js.map +1 -1
  45. package/dist/editor/tokenizer.d.ts +6 -4
  46. package/dist/editor/tokenizer.d.ts.map +1 -1
  47. package/dist/editor/tokenizer.js +25 -470
  48. package/dist/editor/tokenizer.js.map +1 -1
  49. package/dist/highlighter/DiffsEditorTokenizer.d.ts +16 -0
  50. package/dist/highlighter/DiffsEditorTokenizer.d.ts.map +1 -0
  51. package/dist/highlighter/DiffsEditorTokenizer.js +0 -0
  52. package/dist/highlighter/DiffsHighlighter.d.ts +41 -0
  53. package/dist/highlighter/DiffsHighlighter.d.ts.map +1 -0
  54. package/dist/highlighter/DiffsHighlighter.js +39 -0
  55. package/dist/highlighter/DiffsHighlighter.js.map +1 -0
  56. package/dist/highlighter/backends/highlights.d.ts +26 -0
  57. package/dist/highlighter/backends/highlights.d.ts.map +1 -0
  58. package/dist/highlighter/backends/highlights.js +71 -0
  59. package/dist/highlighter/backends/highlights.js.map +1 -0
  60. package/dist/highlighter/backends/shiki.d.ts +27 -0
  61. package/dist/highlighter/backends/shiki.d.ts.map +1 -0
  62. package/dist/highlighter/backends/shiki.js +107 -0
  63. package/dist/highlighter/backends/shiki.js.map +1 -0
  64. package/dist/highlighter/highlighterType.d.ts +13 -0
  65. package/dist/highlighter/highlighterType.d.ts.map +1 -0
  66. package/dist/highlighter/highlighterType.js +32 -0
  67. package/dist/highlighter/highlighterType.js.map +1 -0
  68. package/dist/highlighter/highlights-editor.d.ts +24 -0
  69. package/dist/highlighter/highlights-editor.d.ts.map +1 -0
  70. package/dist/highlighter/highlights-editor.js +166 -0
  71. package/dist/highlighter/highlights-editor.js.map +1 -0
  72. package/dist/highlighter/highlights-stream.d.ts +20 -0
  73. package/dist/highlighter/highlights-stream.d.ts.map +1 -0
  74. package/dist/highlighter/highlights-stream.js +93 -0
  75. package/dist/highlighter/highlights-stream.js.map +1 -0
  76. package/dist/highlighter/languages/areLanguagesAttached.d.ts +2 -1
  77. package/dist/highlighter/languages/areLanguagesAttached.d.ts.map +1 -1
  78. package/dist/highlighter/languages/areLanguagesAttached.js +4 -6
  79. package/dist/highlighter/languages/areLanguagesAttached.js.map +1 -1
  80. package/dist/highlighter/languages/attachResolvedLanguages.d.ts +6 -1
  81. package/dist/highlighter/languages/attachResolvedLanguages.d.ts.map +1 -1
  82. package/dist/highlighter/languages/attachResolvedLanguages.js +6 -11
  83. package/dist/highlighter/languages/attachResolvedLanguages.js.map +1 -1
  84. package/dist/highlighter/languages/constants.d.ts +1 -1
  85. package/dist/highlighter/languages/getResolvedLanguages.d.ts +1 -1
  86. package/dist/highlighter/languages/getResolvedOrResolveLanguage.d.ts +1 -1
  87. package/dist/highlighter/languages/resolveLanguage.d.ts +1 -1
  88. package/dist/highlighter/languages/resolveLanguage.d.ts.map +1 -1
  89. package/dist/highlighter/languages/resolveLanguage.js +19 -16
  90. package/dist/highlighter/languages/resolveLanguage.js.map +1 -1
  91. package/dist/highlighter/languages/resolveLanguages.d.ts +1 -1
  92. package/dist/highlighter/shared_highlighter.d.ts +24 -9
  93. package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
  94. package/dist/highlighter/shared_highlighter.js +59 -47
  95. package/dist/highlighter/shared_highlighter.js.map +1 -1
  96. package/dist/highlighter/shiki-editor.d.ts +25 -0
  97. package/dist/highlighter/shiki-editor.d.ts.map +1 -0
  98. package/dist/highlighter/shiki-editor.js +483 -0
  99. package/dist/highlighter/shiki-editor.js.map +1 -0
  100. package/dist/highlighter/shiki-stream.d.ts +20 -0
  101. package/dist/highlighter/shiki-stream.d.ts.map +1 -0
  102. package/dist/highlighter/shiki-stream.js +60 -0
  103. package/dist/highlighter/shiki-stream.js.map +1 -0
  104. package/dist/highlighter/stream-tokenizer.d.ts +40 -0
  105. package/dist/highlighter/stream-tokenizer.d.ts.map +1 -0
  106. package/dist/highlighter/stream-tokenizer.js +70 -0
  107. package/dist/highlighter/stream-tokenizer.js.map +1 -0
  108. package/dist/highlighter/themes/areThemesAttached.d.ts +3 -2
  109. package/dist/highlighter/themes/areThemesAttached.d.ts.map +1 -1
  110. package/dist/highlighter/themes/areThemesAttached.js +5 -4
  111. package/dist/highlighter/themes/areThemesAttached.js.map +1 -1
  112. package/dist/highlighter/themes/attachResolvedThemes.d.ts +5 -2
  113. package/dist/highlighter/themes/attachResolvedThemes.d.ts.map +1 -1
  114. package/dist/highlighter/themes/attachResolvedThemes.js +4 -16
  115. package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
  116. package/dist/highlighter/themes/cleanUpResolvedThemes.d.ts +3 -1
  117. package/dist/highlighter/themes/cleanUpResolvedThemes.d.ts.map +1 -1
  118. package/dist/highlighter/themes/cleanUpResolvedThemes.js +8 -5
  119. package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
  120. package/dist/highlighter/themes/createCSSVariablesTheme.d.ts +7 -0
  121. package/dist/highlighter/themes/createCSSVariablesTheme.d.ts.map +1 -0
  122. package/dist/highlighter/themes/createCSSVariablesTheme.js +89 -0
  123. package/dist/highlighter/themes/createCSSVariablesTheme.js.map +1 -0
  124. package/dist/highlighter/themes/createCachedLoader.d.ts +5 -0
  125. package/dist/highlighter/themes/createCachedLoader.d.ts.map +1 -0
  126. package/dist/highlighter/themes/createCachedLoader.js +15 -0
  127. package/dist/highlighter/themes/createCachedLoader.js.map +1 -0
  128. package/dist/highlighter/themes/getResolvedOrResolveTheme.d.ts +3 -2
  129. package/dist/highlighter/themes/getResolvedOrResolveTheme.d.ts.map +1 -1
  130. package/dist/highlighter/themes/getResolvedOrResolveTheme.js +4 -4
  131. package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
  132. package/dist/highlighter/themes/getResolvedThemes.d.ts +3 -2
  133. package/dist/highlighter/themes/getResolvedThemes.d.ts.map +1 -1
  134. package/dist/highlighter/themes/getResolvedThemes.js +4 -3
  135. package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
  136. package/dist/highlighter/themes/hasResolvedThemes.d.ts +2 -2
  137. package/dist/highlighter/themes/hasResolvedThemes.d.ts.map +1 -1
  138. package/dist/highlighter/themes/hasResolvedThemes.js +4 -3
  139. package/dist/highlighter/themes/hasResolvedThemes.js.map +1 -1
  140. package/dist/highlighter/themes/registerCustomCSSVariableTheme.d.ts.map +1 -1
  141. package/dist/highlighter/themes/registerCustomCSSVariableTheme.js +3 -3
  142. package/dist/highlighter/themes/registerCustomCSSVariableTheme.js.map +1 -1
  143. package/dist/highlighter/themes/registerCustomTheme.d.ts +9 -4
  144. package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
  145. package/dist/highlighter/themes/registerCustomTheme.js +8 -16
  146. package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
  147. package/dist/highlighter/themes/resolveTheme.d.ts +3 -2
  148. package/dist/highlighter/themes/resolveTheme.d.ts.map +1 -1
  149. package/dist/highlighter/themes/resolveTheme.js +4 -7
  150. package/dist/highlighter/themes/resolveTheme.js.map +1 -1
  151. package/dist/highlighter/themes/resolveThemes.d.ts +3 -2
  152. package/dist/highlighter/themes/resolveThemes.d.ts.map +1 -1
  153. package/dist/highlighter/themes/resolveThemes.js +4 -7
  154. package/dist/highlighter/themes/resolveThemes.js.map +1 -1
  155. package/dist/highlighter/themes/themeResolver.d.ts +10 -4
  156. package/dist/highlighter/themes/themeResolver.d.ts.map +1 -1
  157. package/dist/highlighter/themes/themeResolver.js +141 -2
  158. package/dist/highlighter/themes/themeResolver.js.map +1 -1
  159. package/dist/highlighter/themes/types.d.ts +23 -0
  160. package/dist/highlighter/themes/types.d.ts.map +1 -0
  161. package/dist/highlighter/themes/types.js +0 -0
  162. package/dist/highlighter/tokenizer-types.d.ts +35 -0
  163. package/dist/highlighter/tokenizer-types.d.ts.map +1 -0
  164. package/dist/highlighter/tokenizer-types.js +0 -0
  165. package/dist/highlighter/types.d.ts +55 -0
  166. package/dist/highlighter/types.d.ts.map +1 -0
  167. package/dist/highlighter/types.js +0 -0
  168. package/dist/index.d.ts +22 -13
  169. package/dist/index.js +21 -18
  170. package/dist/managers/InteractionManager.d.ts.map +1 -1
  171. package/dist/managers/InteractionManager.js +2 -2
  172. package/dist/managers/InteractionManager.js.map +1 -1
  173. package/dist/node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.d.ts +9 -1
  174. package/dist/node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.d.ts.map +1 -1
  175. package/dist/react/CodeView.d.ts +4 -3
  176. package/dist/react/CodeView.d.ts.map +1 -1
  177. package/dist/react/CodeView.js +47 -38
  178. package/dist/react/CodeView.js.map +1 -1
  179. package/dist/react/File.js +3 -3
  180. package/dist/react/File.js.map +1 -1
  181. package/dist/react/FileDiff.js +3 -3
  182. package/dist/react/FileDiff.js.map +1 -1
  183. package/dist/react/MultiFileDiff.js +2 -2
  184. package/dist/react/MultiFileDiff.js.map +1 -1
  185. package/dist/react/PatchDiff.js +3 -3
  186. package/dist/react/PatchDiff.js.map +1 -1
  187. package/dist/react/UnresolvedFile.js +2 -2
  188. package/dist/react/UnresolvedFile.js.map +1 -1
  189. package/dist/react/index.d.ts +9 -4
  190. package/dist/react/types.d.ts +4 -2
  191. package/dist/react/types.d.ts.map +1 -1
  192. package/dist/react/utils/renderDiffChildren.js +1 -1
  193. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  194. package/dist/react/utils/renderFileChildren.js +1 -1
  195. package/dist/react/utils/renderFileChildren.js.map +1 -1
  196. package/dist/react/utils/useFileDiffInstance.d.ts +1 -0
  197. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  198. package/dist/react/utils/useFileDiffInstance.js +29 -24
  199. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  200. package/dist/react/utils/useFileInstance.d.ts +2 -0
  201. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  202. package/dist/react/utils/useFileInstance.js +38 -28
  203. package/dist/react/utils/useFileInstance.js.map +1 -1
  204. package/dist/react/utils/useForceUpdate.d.ts +5 -0
  205. package/dist/react/utils/useForceUpdate.d.ts.map +1 -0
  206. package/dist/react/utils/useForceUpdate.js +27 -0
  207. package/dist/react/utils/useForceUpdate.js.map +1 -0
  208. package/dist/react/utils/useNextRenderData.d.ts +9 -0
  209. package/dist/react/utils/useNextRenderData.d.ts.map +1 -0
  210. package/dist/react/utils/useNextRenderData.js +9 -0
  211. package/dist/react/utils/useNextRenderData.js.map +1 -0
  212. package/dist/react/utils/useUnresolvedFileInstance.d.ts +1 -0
  213. package/dist/react/utils/useUnresolvedFileInstance.d.ts.map +1 -1
  214. package/dist/react/utils/useUnresolvedFileInstance.js +26 -11
  215. package/dist/react/utils/useUnresolvedFileInstance.js.map +1 -1
  216. package/dist/renderers/DiffHunksRenderer.d.ts +4 -2
  217. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  218. package/dist/renderers/DiffHunksRenderer.js +82 -43
  219. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  220. package/dist/renderers/FileRenderer.d.ts +6 -2
  221. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  222. package/dist/renderers/FileRenderer.js +77 -43
  223. package/dist/renderers/FileRenderer.js.map +1 -1
  224. package/dist/renderers/UnresolvedFileHunksRenderer.d.ts.map +1 -1
  225. package/dist/renderers/UnresolvedFileHunksRenderer.js +1 -1
  226. package/dist/renderers/UnresolvedFileHunksRenderer.js.map +1 -1
  227. package/dist/shiki-stream/index.d.ts +3 -3
  228. package/dist/shiki-stream/index.js +1 -2
  229. package/dist/shiki-stream/stream.d.ts +4 -4
  230. package/dist/shiki-stream/stream.d.ts.map +1 -1
  231. package/dist/shiki-stream/stream.js +20 -9
  232. package/dist/shiki-stream/stream.js.map +1 -1
  233. package/dist/shiki-stream/types.d.ts +7 -38
  234. package/dist/shiki-stream/types.d.ts.map +1 -1
  235. package/dist/ssr/index.d.ts +7 -2
  236. package/dist/ssr/renderHTML.js +2 -2
  237. package/dist/ssr/renderHTML.js.map +1 -1
  238. package/dist/style.js +1 -1
  239. package/dist/style.js.map +1 -1
  240. package/dist/types.d.ts +20 -11
  241. package/dist/types.d.ts.map +1 -1
  242. package/dist/utils/canUseWASM.d.ts +13 -0
  243. package/dist/utils/canUseWASM.d.ts.map +1 -0
  244. package/dist/utils/canUseWASM.js +59 -0
  245. package/dist/utils/canUseWASM.js.map +1 -0
  246. package/dist/utils/createSpanNodeFromToken.d.ts +3 -2
  247. package/dist/utils/createSpanNodeFromToken.d.ts.map +1 -1
  248. package/dist/utils/createSpanNodeFromToken.js +4 -5
  249. package/dist/utils/createSpanNodeFromToken.js.map +1 -1
  250. package/dist/utils/cssWrappers.d.ts.map +1 -1
  251. package/dist/utils/cssWrappers.js +12 -0
  252. package/dist/utils/cssWrappers.js.map +1 -1
  253. package/dist/utils/getCodeViewItemRenderData.d.ts +10 -0
  254. package/dist/utils/getCodeViewItemRenderData.d.ts.map +1 -0
  255. package/dist/utils/getCodeViewItemRenderData.js +19 -0
  256. package/dist/utils/getCodeViewItemRenderData.js.map +1 -0
  257. package/dist/utils/getHighlighterOptions.d.ts.map +1 -1
  258. package/dist/utils/getHighlighterOptions.js +3 -2
  259. package/dist/utils/getHighlighterOptions.js.map +1 -1
  260. package/dist/utils/getHighlighterThemeStyles.d.ts +2 -1
  261. package/dist/utils/getHighlighterThemeStyles.d.ts.map +1 -1
  262. package/dist/utils/getHighlighterThemeStyles.js +13 -3
  263. package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
  264. package/dist/utils/getTokenOptions.d.ts +7 -0
  265. package/dist/utils/getTokenOptions.d.ts.map +1 -0
  266. package/dist/utils/getTokenOptions.js +16 -0
  267. package/dist/utils/getTokenOptions.js.map +1 -0
  268. package/dist/utils/hastToHtml.d.ts +10 -0
  269. package/dist/utils/hastToHtml.d.ts.map +1 -0
  270. package/dist/utils/hastToHtml.js +125 -0
  271. package/dist/utils/hastToHtml.js.map +1 -0
  272. package/dist/utils/hydratePartialDiff.js +4 -0
  273. package/dist/utils/hydratePartialDiff.js.map +1 -1
  274. package/dist/utils/parseDiffDecorations.d.ts +2 -1
  275. package/dist/utils/parseDiffDecorations.d.ts.map +1 -1
  276. package/dist/utils/parseMergeConflictDiffFromFile.d.ts.map +1 -1
  277. package/dist/utils/parseMergeConflictDiffFromFile.js +2 -0
  278. package/dist/utils/parseMergeConflictDiffFromFile.js.map +1 -1
  279. package/dist/utils/parsePatchFiles.d.ts.map +1 -1
  280. package/dist/utils/parsePatchFiles.js +24 -4
  281. package/dist/utils/parsePatchFiles.js.map +1 -1
  282. package/dist/utils/renderDiffWithHighlighter.d.ts +3 -2
  283. package/dist/utils/renderDiffWithHighlighter.d.ts.map +1 -1
  284. package/dist/utils/renderDiffWithHighlighter.js +33 -48
  285. package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
  286. package/dist/utils/renderFileWithHighlighter.d.ts +3 -2
  287. package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
  288. package/dist/utils/renderFileWithHighlighter.js +10 -26
  289. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  290. package/dist/utils/renderTokenLines.d.ts +22 -0
  291. package/dist/utils/renderTokenLines.d.ts.map +1 -0
  292. package/dist/utils/renderTokenLines.js +250 -0
  293. package/dist/utils/renderTokenLines.js.map +1 -0
  294. package/dist/utils/resolvePreferredHighlighter.d.ts +13 -0
  295. package/dist/utils/resolvePreferredHighlighter.d.ts.map +1 -0
  296. package/dist/utils/resolvePreferredHighlighter.js +11 -0
  297. package/dist/utils/resolvePreferredHighlighter.js.map +1 -0
  298. package/dist/utils/resolveRegion.js +20 -10
  299. package/dist/utils/resolveRegion.js.map +1 -1
  300. package/dist/utils/setDeferredArrayItem.d.ts +5 -0
  301. package/dist/utils/setDeferredArrayItem.d.ts.map +1 -0
  302. package/dist/utils/setDeferredArrayItem.js +39 -0
  303. package/dist/utils/setDeferredArrayItem.js.map +1 -0
  304. package/dist/utils/tokenStyle.d.ts +11 -0
  305. package/dist/utils/tokenStyle.d.ts.map +1 -0
  306. package/dist/utils/tokenStyle.js +32 -0
  307. package/dist/utils/tokenStyle.js.map +1 -0
  308. package/dist/utils/tokensToHtml.d.ts +11 -0
  309. package/dist/utils/tokensToHtml.d.ts.map +1 -0
  310. package/dist/utils/tokensToHtml.js +48 -0
  311. package/dist/utils/tokensToHtml.js.map +1 -0
  312. package/dist/utils/updateDiffHunks.d.ts +2 -2
  313. package/dist/utils/updateDiffHunks.d.ts.map +1 -1
  314. package/dist/utils/updateDiffHunks.js +7 -3
  315. package/dist/utils/updateDiffHunks.js.map +1 -1
  316. package/dist/utils/wrapTokenFragments.js.map +1 -1
  317. package/dist/worker/WorkerPoolManager.d.ts +14 -2
  318. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  319. package/dist/worker/WorkerPoolManager.js +155 -67
  320. package/dist/worker/WorkerPoolManager.js.map +1 -1
  321. package/dist/worker/hastLinesTransport.d.ts +14 -0
  322. package/dist/worker/hastLinesTransport.d.ts.map +1 -0
  323. package/dist/worker/hastLinesTransport.js +156 -0
  324. package/dist/worker/hastLinesTransport.js.map +1 -0
  325. package/dist/worker/highlights-CpZm9DAR.js +317 -0
  326. package/dist/worker/highlights-CpZm9DAR.js.map +1 -0
  327. package/dist/worker/index.d.ts +1 -1
  328. package/dist/worker/shiki-Ci4cdHsM.js +697 -0
  329. package/dist/worker/shiki-Ci4cdHsM.js.map +1 -0
  330. package/dist/worker/stream-tokenizer-DK9xp5M5.js +427 -0
  331. package/dist/worker/stream-tokenizer-DK9xp5M5.js.map +1 -0
  332. package/dist/worker/types.d.ts +16 -3
  333. package/dist/worker/types.d.ts.map +1 -1
  334. package/dist/worker/worker-portable.js +41 -13337
  335. package/dist/worker/worker-portable.js.map +1 -1
  336. package/dist/worker/worker.js +681 -349
  337. package/dist/worker/worker.js.map +1 -1
  338. package/dist/worker/workerMessage.d.ts +24 -0
  339. package/dist/worker/workerMessage.d.ts.map +1 -0
  340. package/dist/worker/workerMessage.js +0 -0
  341. package/package.json +5 -3
  342. package/dist/highlighter/themes/constants.d.ts +0 -5
  343. package/dist/highlighter/themes/constants.d.ts.map +0 -1
  344. package/dist/highlighter/themes/constants.js +0 -6
  345. package/dist/highlighter/themes/constants.js.map +0 -1
  346. package/dist/highlighter/themes/themeResolution.d.ts +0 -7
  347. package/dist/highlighter/themes/themeResolution.d.ts.map +0 -1
  348. package/dist/highlighter/themes/themeResolution.js +0 -21
  349. package/dist/highlighter/themes/themeResolution.js.map +0 -1
  350. package/dist/shiki-stream/tokenizer.d.ts +0 -23
  351. package/dist/shiki-stream/tokenizer.d.ts.map +0 -1
  352. package/dist/shiki-stream/tokenizer.js +0 -72
  353. package/dist/shiki-stream/tokenizer.js.map +0 -1
  354. package/dist/utils/createTransformerWithState.d.ts +0 -12
  355. package/dist/utils/createTransformerWithState.d.ts.map +0 -1
  356. package/dist/utils/createTransformerWithState.js +0 -89
  357. package/dist/utils/createTransformerWithState.js.map +0 -1
  358. package/dist/worker/wasm-B9ZqxnKj.js +0 -8
  359. package/dist/worker/wasm-B9ZqxnKj.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderTokenLines.js","names":[],"sources":["../../src/utils/renderTokenLines.ts"],"sourcesContent":["import type { Element, ElementContent, Properties } from 'hast';\n\nimport type { DecorationItem, SharedRenderState, ThemedToken } from '../types';\nimport { processLine } from './processLine';\nimport { setDeferredArrayItem } from './setDeferredArrayItem';\nimport { tokenStyle } from './tokenStyle';\nimport { wrapTokenFragments } from './wrapTokenFragments';\n\nexport interface RenderTokenLinesOptions {\n lazyLineAST?: boolean;\n cacheHtmlStyles?: boolean;\n state?: SharedRenderState;\n useTokenTransformer?: boolean;\n mergeWhitespaces?: 'never' | 'always';\n decorations?: DecorationItem[];\n /** UTF-16 line start offsets, required for numeric decoration positions. */\n lineOffsets?: number[];\n}\n\ninterface LineDecoration extends Omit<DecorationItem, 'start' | 'end'> {\n start: { line: number; character: number };\n end: { line: number; character: number };\n}\n\n// from/to are columns within this line; order preserves outer-to-inner nesting.\ninterface LineDecorationRange {\n decoration: LineDecoration;\n order: number;\n from: number;\n to: number;\n}\n\ninterface DecorationBoundary {\n position: number;\n range: LineDecorationRange;\n start: boolean;\n}\n\n/**\n * Converts highlighted tokens to one HAST element per line for custom renderers.\n * Callers provide any line separators and enclosing pre/code elements.\n */\nexport function renderTokenLines(\n lines: ThemedToken[][],\n {\n state,\n lazyLineAST = false,\n cacheHtmlStyles = false,\n useTokenTransformer = false,\n mergeWhitespaces = 'always',\n decorations = [],\n lineOffsets = [],\n }: RenderTokenLinesOptions\n): ElementContent[] {\n let decorationsByLine: Map<number, LineDecoration[]> | undefined;\n for (const decoration of decorations) {\n const byLine = (decorationsByLine ??= new Map());\n const normalized: LineDecoration = {\n ...decoration,\n start: getDecorationPosition(decoration.start, lineOffsets),\n end: getDecorationPosition(decoration.end, lineOffsets),\n };\n const lastLine = Math.min(normalized.end.line, lines.length - 1);\n for (let line = normalized.start.line; line <= lastLine; line++) {\n let spans = byLine.get(line);\n if (spans == null) byLine.set(line, (spans = []));\n spans.push(normalized);\n }\n }\n const renderLine = (tokens: ThemedToken[], lineIndex: number) => {\n let normalized: ThemedToken[] | undefined;\n if (useTokenTransformer || mergeWhitespaces !== 'never') {\n let pendingWhitespace = '';\n let whitespaceOffset = 0;\n for (let i = 0; i < tokens.length; i++) {\n let token = tokens[i];\n if (useTokenTransformer) {\n const content = token.content.trim();\n if (content !== '' && content !== token.content) {\n normalized ??= tokens.slice(0, i);\n const start = token.content.indexOf(content);\n if (start > 0)\n normalized.push({\n content: token.content.slice(0, start),\n offset: token.offset,\n });\n normalized.push({\n ...token,\n content,\n offset: token.offset + start,\n });\n const end = start + content.length;\n if (end < token.content.length)\n normalized.push({\n content: token.content.slice(end),\n offset: token.offset + end,\n });\n continue;\n }\n } else {\n const decoratedWhitespace = ((token.fontStyle ?? 0) & 12) !== 0;\n if (\n !decoratedWhitespace &&\n /^\\s+$/.test(token.content) &&\n i < tokens.length - 1\n ) {\n normalized ??= tokens.slice(0, i);\n if (pendingWhitespace === '') whitespaceOffset = token.offset;\n pendingWhitespace += token.content;\n continue;\n }\n if (pendingWhitespace !== '' && normalized != null) {\n if (decoratedWhitespace)\n normalized.push({\n content: pendingWhitespace,\n offset: whitespaceOffset,\n });\n else\n token = {\n ...token,\n content: pendingWhitespace + token.content,\n offset: whitespaceOffset,\n };\n pendingWhitespace = '';\n }\n }\n normalized?.push(token);\n }\n }\n normalized ??= tokens;\n const line: Element = {\n type: 'element',\n tagName: state == null ? 'span' : 'div',\n properties: state == null ? { class: 'line' } : {},\n children: [],\n };\n const spans = decorationsByLine?.get(lineIndex);\n const column =\n spans == null\n ? appendTokens(line, normalized, useTokenTransformer, cacheHtmlStyles)\n : appendDecoratedTokens(\n line,\n normalized,\n spans,\n lineIndex,\n useTokenTransformer,\n cacheHtmlStyles\n );\n if (useTokenTransformer && column === 0) {\n line.children.push({\n type: 'element',\n tagName: 'br',\n properties: {},\n children: [],\n });\n }\n // Undecorated tokens already have one span per editor position.\n if (useTokenTransformer && spans != null) wrapTokenFragments(line);\n return state == null ? line : processLine(line, lineIndex + 1, state);\n };\n if (!lazyLineAST) return lines.map(renderLine);\n const rows: ElementContent[] = new Array(lines.length);\n for (let index = 0; index < lines.length; index++) {\n // Warning: capture one line, not `lines`; unbuilt rows would keep every\n // line's tokens alive.\n const tokens = lines[index];\n setDeferredArrayItem(rows, index, () => renderLine(tokens, index));\n }\n return rows;\n}\n\n// Returns the line length in UTF-16 code units.\nfunction appendTokens(\n line: Element,\n tokens: ThemedToken[],\n useTokenTransformer: boolean,\n cacheHtmlStyles: boolean\n): number {\n let column = 0;\n for (const token of tokens) {\n if (token.content === '') continue;\n line.children.push(\n createTokenSpan(\n token,\n tokenStyle(token, cacheHtmlStyles),\n token.content,\n column,\n useTokenTransformer\n )\n );\n column += token.content.length;\n }\n return column;\n}\n\n// Visit sorted boundaries once to avoid scanning every decoration per token.\n// Emit empty ranges before text at the same position.\nfunction appendDecoratedTokens(\n line: Element,\n tokens: ThemedToken[],\n spans: LineDecoration[],\n lineIndex: number,\n useTokenTransformer: boolean,\n cacheHtmlStyles: boolean\n): number {\n // Open outer ranges first, regardless of their order in the input.\n if (spans.length > 1)\n spans.sort((a, b) => {\n if (a.start.line !== b.start.line) return a.start.line - b.start.line;\n if (a.start.character !== b.start.character)\n return a.start.character - b.start.character;\n if (a.end.line !== b.end.line) return b.end.line - a.end.line;\n return b.end.character - a.end.character;\n });\n const lineLength = tokens.reduce(\n (length, token) => length + token.content.length,\n 0\n );\n const boundaries: DecorationBoundary[] = [];\n for (let order = 0; order < spans.length; order++) {\n const decoration = spans[order];\n const range: LineDecorationRange = {\n decoration,\n order,\n from:\n decoration.start.line === lineIndex ? decoration.start.character : 0,\n to:\n decoration.end.line === lineIndex\n ? decoration.end.character\n : lineLength,\n };\n boundaries.push(\n {\n position: Math.max(0, Math.min(range.from, lineLength)),\n range,\n start: true,\n },\n {\n position: Math.max(0, Math.min(range.to, lineLength)),\n range,\n start: false,\n }\n );\n }\n boundaries.sort((a, b) => a.position - b.position);\n const active: LineDecorationRange[] = [];\n const decorationStack: { range: LineDecorationRange; node: Element }[] = [];\n let boundaryIndex = 0;\n\n // Keep the same outer-to-inner order even when decorations cross each other.\n const updateActive = (range: LineDecorationRange, add: boolean): void => {\n let low = 0;\n let high = active.length;\n while (low < high) {\n const middle = (low + high) >>> 1;\n if (active[middle].order < range.order) low = middle + 1;\n else high = middle;\n }\n if (add) active.splice(low, 0, range);\n else if (active[low] === range) active.splice(low, 1);\n };\n\n // Reuse wrappers across tokens so a continuous range stays in one element.\n const getParent = (): Element => {\n let parent = line;\n let depth = 0;\n for (const range of active) {\n if (decorationStack[depth]?.range !== range) {\n decorationStack.length = depth;\n const wrapper: Element = {\n type: 'element',\n tagName: 'span',\n properties: { ...range.decoration.properties },\n children: [],\n };\n parent.children.push(wrapper);\n decorationStack.push({ range, node: wrapper });\n }\n parent = decorationStack[depth++].node;\n }\n decorationStack.length = depth;\n return parent;\n };\n\n let parent = line;\n\n // Markers belong inside ranges starting here, except at the line end,\n // where they belong inside ranges ending here.\n const advanceBoundary = (position: number): void => {\n const first = boundaryIndex;\n while (boundaries[boundaryIndex]?.position === position) boundaryIndex++;\n let hasMarker = false;\n for (let i = first; i < boundaryIndex; i++) {\n const { range, start } = boundaries[i];\n if (!start && range.from !== range.to && position < lineLength)\n updateActive(range, false);\n }\n for (let i = first; i < boundaryIndex; i++) {\n const { range, start } = boundaries[i];\n if (\n start &&\n range.from <= position &&\n range.to >= position &&\n (range.to > position ||\n range.from === position ||\n position === lineLength)\n ) {\n updateActive(range, true);\n if (range.from === range.to) hasMarker = true;\n }\n }\n if (hasMarker) {\n getParent();\n for (let i = first; i < boundaryIndex; i++) {\n const { range, start } = boundaries[i];\n if (start && range.from === range.to) updateActive(range, false);\n }\n }\n if (position < lineLength) parent = getParent();\n };\n\n let column = 0;\n for (const token of tokens) {\n if (token.content === '') continue;\n const start = column;\n const end = start + token.content.length;\n const style = tokenStyle(token, cacheHtmlStyles);\n while (column < end) {\n if (boundaries[boundaryIndex]?.position === column)\n advanceBoundary(column);\n const to = Math.min(end, boundaries[boundaryIndex]?.position ?? end);\n parent.children.push(\n createTokenSpan(\n token,\n style,\n column === start && to === end\n ? token.content\n : token.content.slice(column - start, to - start),\n start,\n useTokenTransformer\n )\n );\n column = to;\n }\n }\n if (boundaries[boundaryIndex]?.position === column) advanceBoundary(column);\n return column;\n}\n\n// data-char must retain the original token column when decorations split it.\nfunction createTokenSpan(\n token: ThemedToken,\n style: string,\n text: string,\n start: number,\n useTokenTransformer: boolean\n): Element {\n const properties: Properties =\n token.htmlAttrs != null ? { ...token.htmlAttrs } : {};\n if (style !== '') properties.style = style;\n if (useTokenTransformer) properties['data-char'] = start;\n return {\n type: 'element',\n tagName: 'span',\n properties,\n children: [{ type: 'text', value: text }],\n };\n}\n\n// Convert absolute UTF-16 offsets to the line coordinates used by decorations.\nfunction getDecorationPosition(\n position: DecorationItem['start'],\n lineOffsets: number[]\n): { line: number; character: number } {\n if (typeof position !== 'number') return position;\n let low = 0;\n let high = lineOffsets.length;\n while (low + 1 < high) {\n const middle = (low + high) >>> 1;\n if (lineOffsets[middle] <= position) low = middle;\n else high = middle;\n }\n return { line: low, character: position - (lineOffsets[low] ?? 0) };\n}\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { HighlighterTypes } from "../types.js";
2
+ //#region src/utils/resolvePreferredHighlighter.d.ts
3
+ /**
4
+ * Undefined lets the caller use the active type or the default.
5
+ */
6
+ declare function resolvePreferredHighlighter(workerManager: {
7
+ getPreferredHighlighter(): HighlighterTypes;
8
+ } | undefined, options: {
9
+ preferredHighlighter?: HighlighterTypes | undefined;
10
+ }): HighlighterTypes | undefined;
11
+ //#endregion
12
+ export { resolvePreferredHighlighter };
13
+ //# sourceMappingURL=resolvePreferredHighlighter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolvePreferredHighlighter.d.ts","names":[],"sources":["../../src/utils/resolvePreferredHighlighter.ts"],"mappings":";;;;;iBAKgB,4BACd;EAAiB,2BAA2B;eAC5C;EAAW,uBAAuB;IACjC"}
@@ -0,0 +1,11 @@
1
+ //#region src/utils/resolvePreferredHighlighter.ts
2
+ /**
3
+ * Undefined lets the caller use the active type or the default.
4
+ */
5
+ function resolvePreferredHighlighter(workerManager, options) {
6
+ return workerManager?.getPreferredHighlighter() ?? options.preferredHighlighter;
7
+ }
8
+ //#endregion
9
+ export { resolvePreferredHighlighter };
10
+
11
+ //# sourceMappingURL=resolvePreferredHighlighter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolvePreferredHighlighter.js","names":[],"sources":["../../src/utils/resolvePreferredHighlighter.ts"],"sourcesContent":["import type { HighlighterTypes } from '../types';\n\n/**\n * Undefined lets the caller use the active type or the default.\n */\nexport function resolvePreferredHighlighter(\n workerManager: { getPreferredHighlighter(): HighlighterTypes } | undefined,\n options: { preferredHighlighter?: HighlighterTypes | undefined }\n): HighlighterTypes | undefined {\n return (\n workerManager?.getPreferredHighlighter() ?? options.preferredHighlighter\n );\n}\n"],"mappings":";;;;AAKA,SAAgB,4BACd,eACA,SAC8B;CAC9B,OACE,eAAe,wBAAwB,KAAK,QAAQ;AAExD"}
@@ -17,6 +17,8 @@ function resolveRegion(diff, target) {
17
17
  hunks: [],
18
18
  deletionLines: [],
19
19
  additionLines: [],
20
+ deletionCharacterCount: 0,
21
+ additionCharacterCount: 0,
20
22
  splitLineCount: 0,
21
23
  unifiedLineCount: 0,
22
24
  cacheKey: diff.cacheKey != null ? `${diff.cacheKey}:${resolution[0]}-${hunkIndex}:${startContentIndex}-${endContentIndex}` : void 0
@@ -117,8 +119,8 @@ function pushCollapsedContextLines(diff, deletionLines, additionLines, deletionL
117
119
  const deletionLine = deletionLines[deletionLineIndex + index];
118
120
  const additionLine = additionLines[additionLineIndex + index];
119
121
  if (deletionLine == null || additionLine == null) throw new Error("pushCollapsedContextLines: missing collapsed context line");
120
- diff.deletionLines.push(deletionLine);
121
- diff.additionLines.push(additionLine);
122
+ pushDeletionLine(diff, deletionLine);
123
+ pushAdditionLine(diff, additionLine);
122
124
  }
123
125
  }
124
126
  function processCollapsedContext(sourceDiff, resolvedDiff, cursor, deletionLineIndex, additionLineIndex, lineCount, shouldProcessContent) {
@@ -144,8 +146,8 @@ function pushContentLinesToDiff(content, diff, deletionLines, additionLines) {
144
146
  });
145
147
  throw new Error("pushContentLinesToDiff: Context line does not exist");
146
148
  }
147
- diff.deletionLines.push(line);
148
- diff.additionLines.push(line);
149
+ pushDeletionLine(diff, line);
150
+ pushAdditionLine(diff, line);
149
151
  }
150
152
  else {
151
153
  const len = Math.max(content.deletions, content.additions);
@@ -160,7 +162,7 @@ function pushContentLinesToDiff(content, diff, deletionLines, additionLines) {
160
162
  });
161
163
  throw new Error("pushContentLinesToDiff: Deletion line does not exist");
162
164
  }
163
- diff.deletionLines.push(line);
165
+ pushDeletionLine(diff, line);
164
166
  }
165
167
  if (i < content.additions) {
166
168
  const line = additionLines[content.additionLineIndex + i];
@@ -172,7 +174,7 @@ function pushContentLinesToDiff(content, diff, deletionLines, additionLines) {
172
174
  });
173
175
  throw new Error("pushContentLinesToDiff: Addition line does not exist");
174
176
  }
175
- diff.additionLines.push(line);
177
+ pushAdditionLine(diff, line);
176
178
  }
177
179
  }
178
180
  }
@@ -188,8 +190,8 @@ function pushResolveLinesToDiff(resolution, content, diff, deletionLines, additi
188
190
  });
189
191
  throw new Error("pushResolveLinesToDiff: Deletion line does not exist");
190
192
  }
191
- diff.deletionLines.push(line);
192
- diff.additionLines.push(line);
193
+ pushDeletionLine(diff, line);
194
+ pushAdditionLine(diff, line);
193
195
  }
194
196
  if (resolution === "additions" || resolution === "both") for (let i = 0; i < content.additions; i++) {
195
197
  const line = additionLines[content.additionLineIndex + i];
@@ -201,8 +203,8 @@ function pushResolveLinesToDiff(resolution, content, diff, deletionLines, additi
201
203
  });
202
204
  throw new Error("pushResolveLinesToDiff: Addition line does not exist");
203
205
  }
204
- diff.deletionLines.push(line);
205
- diff.additionLines.push(line);
206
+ pushDeletionLine(diff, line);
207
+ pushAdditionLine(diff, line);
206
208
  }
207
209
  }
208
210
  function advanceCursor(content, cursor, hunk) {
@@ -232,6 +234,14 @@ function advanceCursor(content, cursor, hunk) {
232
234
  hunk.unifiedLineCount += content.deletions + content.additions;
233
235
  }
234
236
  }
237
+ function pushDeletionLine(diff, line) {
238
+ diff.deletionLines.push(line);
239
+ diff.deletionCharacterCount += line.length;
240
+ }
241
+ function pushAdditionLine(diff, line) {
242
+ diff.additionLines.push(line);
243
+ diff.additionCharacterCount += line.length;
244
+ }
235
245
  //#endregion
236
246
  export { resolveRegion };
237
247
 
@@ -1 +1 @@
1
- {"version":3,"file":"resolveRegion.js","names":[],"sources":["../../src/utils/resolveRegion.ts"],"sourcesContent":["import type {\n ChangeContent,\n ContextContent,\n FileDiffMetadata,\n Hunk,\n} from '../types';\nimport {\n getHunkSideEndBoundary,\n getHunkSideStartBoundary,\n} from './getHunkSideBoundaries';\n\ninterface RegionResolutionTarget {\n hunkIndex: number;\n startContentIndex: number;\n endContentIndex: number;\n resolution: 'deletions' | 'additions' | 'both';\n indexesToDelete?: Set<number>;\n}\n\ninterface CursorState {\n nextAdditionLineIndex: number;\n nextDeletionLineIndex: number;\n nextAdditionStart: number;\n nextDeletionStart: number;\n splitLineCount: number;\n unifiedLineCount: number;\n}\n\nexport function resolveRegion(\n diff: FileDiffMetadata,\n target: RegionResolutionTarget\n): FileDiffMetadata {\n const {\n resolution,\n hunkIndex,\n startContentIndex,\n endContentIndex,\n indexesToDelete = new Set(),\n } = target;\n const currentHunk = diff.hunks[hunkIndex];\n if (currentHunk == null) {\n console.error({ diff, hunkIndex });\n throw new Error(`resolveRegion: Invalid hunk index: ${hunkIndex}`);\n }\n\n if (\n startContentIndex < 0 ||\n endContentIndex >= currentHunk.hunkContent.length ||\n startContentIndex > endContentIndex\n ) {\n throw new Error(\n `resolveRegion: Invalid content range, ${startContentIndex}, ${endContentIndex}`\n );\n }\n\n const { hunks, additionLines, deletionLines } = diff;\n const resolvedDiff: FileDiffMetadata = {\n ...diff,\n hunks: [],\n deletionLines: [],\n additionLines: [],\n splitLineCount: 0,\n unifiedLineCount: 0,\n cacheKey:\n diff.cacheKey != null\n ? `${diff.cacheKey}:${resolution[0]}-${hunkIndex}:${startContentIndex}-${endContentIndex}`\n : undefined,\n };\n\n const cursor: CursorState = {\n nextAdditionLineIndex: 0,\n nextDeletionLineIndex: 0,\n nextAdditionStart: 1,\n nextDeletionStart: 1,\n splitLineCount: 0,\n unifiedLineCount: 0,\n };\n const updatesEOFState =\n hunkIndex === hunks.length - 1 &&\n endContentIndex === currentHunk.hunkContent.length - 1;\n const shouldProcessCollapsedContext = !diff.isPartial;\n\n for (const [index, hunk] of hunks.entries()) {\n processCollapsedContext(\n diff,\n resolvedDiff,\n cursor,\n getHunkSideStartBoundary(hunk.deletionStart, hunk.deletionCount) -\n hunk.collapsedBefore,\n getHunkSideStartBoundary(hunk.additionStart, hunk.additionCount) -\n hunk.collapsedBefore,\n hunk.collapsedBefore,\n shouldProcessCollapsedContext\n );\n\n const newHunk: Hunk = {\n ...hunk,\n hunkContent: [],\n additionStart: cursor.nextAdditionStart,\n deletionStart: cursor.nextDeletionStart,\n additionLineIndex: cursor.nextAdditionLineIndex,\n deletionLineIndex: cursor.nextDeletionLineIndex,\n additionCount: 0,\n deletionCount: 0,\n deletionLines: 0,\n additionLines: 0,\n splitLineStart: cursor.splitLineCount,\n unifiedLineStart: cursor.unifiedLineCount,\n splitLineCount: 0,\n unifiedLineCount: 0,\n };\n\n for (const [contentIndex, content] of hunk.hunkContent.entries()) {\n // If we are outside of the targeted hunk or content region\n if (\n index !== hunkIndex ||\n contentIndex < startContentIndex ||\n contentIndex > endContentIndex\n ) {\n pushContentLinesToDiff(\n content,\n resolvedDiff,\n deletionLines,\n additionLines\n );\n const newContent = {\n ...content,\n additionLineIndex: cursor.nextAdditionLineIndex,\n deletionLineIndex: cursor.nextDeletionLineIndex,\n };\n newHunk.hunkContent.push(newContent);\n advanceCursor(newContent, cursor, newHunk);\n }\n // If we are at an index to delete, replace with an empty context node\n else if (indexesToDelete.has(contentIndex)) {\n newHunk.hunkContent.push({\n type: 'context',\n lines: 0,\n deletionLineIndex: cursor.nextDeletionLineIndex,\n additionLineIndex: cursor.nextAdditionLineIndex,\n });\n }\n // There's nothing to `resolve` with context nodes, so just push them as\n // they are\n else if (content.type === 'context') {\n pushContentLinesToDiff(\n content,\n resolvedDiff,\n deletionLines,\n additionLines\n );\n const newContent: ContextContent = {\n ...content,\n deletionLineIndex: cursor.nextDeletionLineIndex,\n additionLineIndex: cursor.nextAdditionLineIndex,\n };\n newHunk.hunkContent.push(newContent);\n advanceCursor(newContent, cursor, newHunk);\n }\n // Looks like we have a change to resolve and push\n else {\n pushResolveLinesToDiff(\n resolution,\n content,\n resolvedDiff,\n deletionLines,\n additionLines\n );\n const newContent: ContextContent = {\n type: 'context',\n lines:\n resolution === 'deletions'\n ? content.deletions\n : resolution === 'additions'\n ? content.additions\n : content.deletions + content.additions,\n deletionLineIndex: cursor.nextDeletionLineIndex,\n additionLineIndex: cursor.nextAdditionLineIndex,\n };\n newHunk.hunkContent.push(newContent);\n advanceCursor(newContent, cursor, newHunk);\n }\n }\n\n if (index === hunkIndex && updatesEOFState) {\n const noEOFCR =\n resolution === 'deletions'\n ? hunk.noEOFCRDeletions\n : hunk.noEOFCRAdditions;\n newHunk.noEOFCRAdditions = noEOFCR;\n newHunk.noEOFCRDeletions = noEOFCR;\n }\n\n if (newHunk.additionCount === 0) {\n newHunk.additionStart--;\n if (!diff.isPartial) {\n newHunk.additionLineIndex--;\n }\n }\n if (newHunk.deletionCount === 0) {\n newHunk.deletionStart--;\n if (!diff.isPartial) {\n newHunk.deletionLineIndex--;\n }\n }\n\n resolvedDiff.hunks.push(newHunk);\n }\n\n const finalHunk = hunks.at(-1);\n if (finalHunk != null && !diff.isPartial) {\n const finalDeletionEnd = getHunkSideEndBoundary(\n finalHunk.deletionStart,\n finalHunk.deletionCount\n );\n const finalAdditionEnd = getHunkSideEndBoundary(\n finalHunk.additionStart,\n finalHunk.additionCount\n );\n const trailingContext = Math.min(\n deletionLines.length - finalDeletionEnd,\n additionLines.length - finalAdditionEnd\n );\n pushCollapsedContextLines(\n resolvedDiff,\n deletionLines,\n additionLines,\n finalDeletionEnd,\n finalAdditionEnd,\n trailingContext\n );\n cursor.splitLineCount += trailingContext;\n cursor.unifiedLineCount += trailingContext;\n }\n\n resolvedDiff.splitLineCount = cursor.splitLineCount;\n resolvedDiff.unifiedLineCount = cursor.unifiedLineCount;\n\n return resolvedDiff;\n}\n\nfunction pushCollapsedContextLines(\n diff: FileDiffMetadata,\n deletionLines: string[],\n additionLines: string[],\n deletionLineIndex: number,\n additionLineIndex: number,\n lineCount: number\n) {\n for (let index = 0; index < lineCount; index++) {\n const deletionLine = deletionLines[deletionLineIndex + index];\n const additionLine = additionLines[additionLineIndex + index];\n if (deletionLine == null || additionLine == null) {\n throw new Error(\n 'pushCollapsedContextLines: missing collapsed context line'\n );\n }\n diff.deletionLines.push(deletionLine);\n diff.additionLines.push(additionLine);\n }\n}\n\n// Partial patches track omitted context in `collapsedBefore`, but those lines do\n// not exist in the diff's line arrays. Keep the virtual row counts and file\n// positions in sync without inventing hidden lines.\nfunction processCollapsedContext(\n sourceDiff: FileDiffMetadata,\n resolvedDiff: FileDiffMetadata,\n cursor: CursorState,\n deletionLineIndex: number,\n additionLineIndex: number,\n lineCount: number,\n shouldProcessContent: boolean\n) {\n if (lineCount <= 0) {\n return;\n }\n\n if (shouldProcessContent) {\n pushCollapsedContextLines(\n resolvedDiff,\n sourceDiff.deletionLines,\n sourceDiff.additionLines,\n deletionLineIndex,\n additionLineIndex,\n lineCount\n );\n cursor.nextAdditionLineIndex += lineCount;\n cursor.nextDeletionLineIndex += lineCount;\n }\n\n cursor.nextAdditionStart += lineCount;\n cursor.nextDeletionStart += lineCount;\n cursor.splitLineCount += lineCount;\n cursor.unifiedLineCount += lineCount;\n}\n\nfunction pushContentLinesToDiff(\n content: ContextContent | ChangeContent,\n diff: FileDiffMetadata,\n deletionLines: string[],\n additionLines: string[]\n) {\n if (content.type === 'context') {\n for (let i = 0; i < content.lines; i++) {\n const line = additionLines[content.additionLineIndex + i];\n if (line == null) {\n console.error({ additionLines, content, i });\n throw new Error('pushContentLinesToDiff: Context line does not exist');\n }\n diff.deletionLines.push(line);\n diff.additionLines.push(line);\n }\n } else {\n const len = Math.max(content.deletions, content.additions);\n for (let i = 0; i < len; i++) {\n if (i < content.deletions) {\n const line = deletionLines[content.deletionLineIndex + i];\n if (line == null) {\n console.error({ deletionLines, content, i });\n throw new Error(\n 'pushContentLinesToDiff: Deletion line does not exist'\n );\n }\n diff.deletionLines.push(line);\n }\n if (i < content.additions) {\n const line = additionLines[content.additionLineIndex + i];\n if (line == null) {\n console.error({ additionLines, content, i });\n throw new Error(\n 'pushContentLinesToDiff: Addition line does not exist'\n );\n }\n diff.additionLines.push(line);\n }\n }\n }\n}\n\nfunction pushResolveLinesToDiff(\n resolution: 'deletions' | 'additions' | 'both',\n content: ChangeContent,\n diff: FileDiffMetadata,\n deletionLines: string[],\n additionLines: string[]\n) {\n if (resolution === 'deletions' || resolution === 'both') {\n for (let i = 0; i < content.deletions; i++) {\n const line = deletionLines[content.deletionLineIndex + i];\n if (line == null) {\n console.error({ deletionLines, content, i });\n throw new Error('pushResolveLinesToDiff: Deletion line does not exist');\n }\n diff.deletionLines.push(line);\n diff.additionLines.push(line);\n }\n }\n if (resolution === 'additions' || resolution === 'both') {\n for (let i = 0; i < content.additions; i++) {\n const line = additionLines[content.additionLineIndex + i];\n if (line == null) {\n console.error({ additionLines, content, i });\n throw new Error('pushResolveLinesToDiff: Addition line does not exist');\n }\n diff.deletionLines.push(line);\n diff.additionLines.push(line);\n }\n }\n}\n\nfunction advanceCursor(\n content: ChangeContent | ContextContent,\n cursor: CursorState,\n hunk: Hunk\n) {\n if (content.type === 'context') {\n cursor.nextAdditionLineIndex += content.lines;\n cursor.nextDeletionLineIndex += content.lines;\n cursor.nextAdditionStart += content.lines;\n cursor.nextDeletionStart += content.lines;\n cursor.splitLineCount += content.lines;\n cursor.unifiedLineCount += content.lines;\n\n hunk.additionCount += content.lines;\n hunk.deletionCount += content.lines;\n hunk.splitLineCount += content.lines;\n hunk.unifiedLineCount += content.lines;\n } else {\n cursor.nextAdditionLineIndex += content.additions;\n cursor.nextDeletionLineIndex += content.deletions;\n cursor.nextAdditionStart += content.additions;\n cursor.nextDeletionStart += content.deletions;\n cursor.splitLineCount += Math.max(content.deletions, content.additions);\n cursor.unifiedLineCount += content.deletions + content.additions;\n\n hunk.deletionCount += content.deletions;\n hunk.deletionLines += content.deletions;\n hunk.additionCount += content.additions;\n hunk.additionLines += content.additions;\n hunk.splitLineCount += Math.max(content.deletions, content.additions);\n hunk.unifiedLineCount += content.deletions + content.additions;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"resolveRegion.js","names":[],"sources":["../../src/utils/resolveRegion.ts"],"sourcesContent":["import type {\n ChangeContent,\n ContextContent,\n FileDiffMetadata,\n Hunk,\n} from '../types';\nimport {\n getHunkSideEndBoundary,\n getHunkSideStartBoundary,\n} from './getHunkSideBoundaries';\n\ninterface RegionResolutionTarget {\n hunkIndex: number;\n startContentIndex: number;\n endContentIndex: number;\n resolution: 'deletions' | 'additions' | 'both';\n indexesToDelete?: Set<number>;\n}\n\ninterface CursorState {\n nextAdditionLineIndex: number;\n nextDeletionLineIndex: number;\n nextAdditionStart: number;\n nextDeletionStart: number;\n splitLineCount: number;\n unifiedLineCount: number;\n}\n\nexport function resolveRegion(\n diff: FileDiffMetadata,\n target: RegionResolutionTarget\n): FileDiffMetadata {\n const {\n resolution,\n hunkIndex,\n startContentIndex,\n endContentIndex,\n indexesToDelete = new Set(),\n } = target;\n const currentHunk = diff.hunks[hunkIndex];\n if (currentHunk == null) {\n console.error({ diff, hunkIndex });\n throw new Error(`resolveRegion: Invalid hunk index: ${hunkIndex}`);\n }\n\n if (\n startContentIndex < 0 ||\n endContentIndex >= currentHunk.hunkContent.length ||\n startContentIndex > endContentIndex\n ) {\n throw new Error(\n `resolveRegion: Invalid content range, ${startContentIndex}, ${endContentIndex}`\n );\n }\n\n const { hunks, additionLines, deletionLines } = diff;\n const resolvedDiff: FileDiffMetadata = {\n ...diff,\n hunks: [],\n deletionLines: [],\n additionLines: [],\n deletionCharacterCount: 0,\n additionCharacterCount: 0,\n splitLineCount: 0,\n unifiedLineCount: 0,\n cacheKey:\n diff.cacheKey != null\n ? `${diff.cacheKey}:${resolution[0]}-${hunkIndex}:${startContentIndex}-${endContentIndex}`\n : undefined,\n };\n\n const cursor: CursorState = {\n nextAdditionLineIndex: 0,\n nextDeletionLineIndex: 0,\n nextAdditionStart: 1,\n nextDeletionStart: 1,\n splitLineCount: 0,\n unifiedLineCount: 0,\n };\n const updatesEOFState =\n hunkIndex === hunks.length - 1 &&\n endContentIndex === currentHunk.hunkContent.length - 1;\n const shouldProcessCollapsedContext = !diff.isPartial;\n\n for (const [index, hunk] of hunks.entries()) {\n processCollapsedContext(\n diff,\n resolvedDiff,\n cursor,\n getHunkSideStartBoundary(hunk.deletionStart, hunk.deletionCount) -\n hunk.collapsedBefore,\n getHunkSideStartBoundary(hunk.additionStart, hunk.additionCount) -\n hunk.collapsedBefore,\n hunk.collapsedBefore,\n shouldProcessCollapsedContext\n );\n\n const newHunk: Hunk = {\n ...hunk,\n hunkContent: [],\n additionStart: cursor.nextAdditionStart,\n deletionStart: cursor.nextDeletionStart,\n additionLineIndex: cursor.nextAdditionLineIndex,\n deletionLineIndex: cursor.nextDeletionLineIndex,\n additionCount: 0,\n deletionCount: 0,\n deletionLines: 0,\n additionLines: 0,\n splitLineStart: cursor.splitLineCount,\n unifiedLineStart: cursor.unifiedLineCount,\n splitLineCount: 0,\n unifiedLineCount: 0,\n };\n\n for (const [contentIndex, content] of hunk.hunkContent.entries()) {\n // If we are outside of the targeted hunk or content region\n if (\n index !== hunkIndex ||\n contentIndex < startContentIndex ||\n contentIndex > endContentIndex\n ) {\n pushContentLinesToDiff(\n content,\n resolvedDiff,\n deletionLines,\n additionLines\n );\n const newContent = {\n ...content,\n additionLineIndex: cursor.nextAdditionLineIndex,\n deletionLineIndex: cursor.nextDeletionLineIndex,\n };\n newHunk.hunkContent.push(newContent);\n advanceCursor(newContent, cursor, newHunk);\n }\n // If we are at an index to delete, replace with an empty context node\n else if (indexesToDelete.has(contentIndex)) {\n newHunk.hunkContent.push({\n type: 'context',\n lines: 0,\n deletionLineIndex: cursor.nextDeletionLineIndex,\n additionLineIndex: cursor.nextAdditionLineIndex,\n });\n }\n // There's nothing to `resolve` with context nodes, so just push them as\n // they are\n else if (content.type === 'context') {\n pushContentLinesToDiff(\n content,\n resolvedDiff,\n deletionLines,\n additionLines\n );\n const newContent: ContextContent = {\n ...content,\n deletionLineIndex: cursor.nextDeletionLineIndex,\n additionLineIndex: cursor.nextAdditionLineIndex,\n };\n newHunk.hunkContent.push(newContent);\n advanceCursor(newContent, cursor, newHunk);\n }\n // Looks like we have a change to resolve and push\n else {\n pushResolveLinesToDiff(\n resolution,\n content,\n resolvedDiff,\n deletionLines,\n additionLines\n );\n const newContent: ContextContent = {\n type: 'context',\n lines:\n resolution === 'deletions'\n ? content.deletions\n : resolution === 'additions'\n ? content.additions\n : content.deletions + content.additions,\n deletionLineIndex: cursor.nextDeletionLineIndex,\n additionLineIndex: cursor.nextAdditionLineIndex,\n };\n newHunk.hunkContent.push(newContent);\n advanceCursor(newContent, cursor, newHunk);\n }\n }\n\n if (index === hunkIndex && updatesEOFState) {\n const noEOFCR =\n resolution === 'deletions'\n ? hunk.noEOFCRDeletions\n : hunk.noEOFCRAdditions;\n newHunk.noEOFCRAdditions = noEOFCR;\n newHunk.noEOFCRDeletions = noEOFCR;\n }\n\n if (newHunk.additionCount === 0) {\n newHunk.additionStart--;\n if (!diff.isPartial) {\n newHunk.additionLineIndex--;\n }\n }\n if (newHunk.deletionCount === 0) {\n newHunk.deletionStart--;\n if (!diff.isPartial) {\n newHunk.deletionLineIndex--;\n }\n }\n\n resolvedDiff.hunks.push(newHunk);\n }\n\n const finalHunk = hunks.at(-1);\n if (finalHunk != null && !diff.isPartial) {\n const finalDeletionEnd = getHunkSideEndBoundary(\n finalHunk.deletionStart,\n finalHunk.deletionCount\n );\n const finalAdditionEnd = getHunkSideEndBoundary(\n finalHunk.additionStart,\n finalHunk.additionCount\n );\n const trailingContext = Math.min(\n deletionLines.length - finalDeletionEnd,\n additionLines.length - finalAdditionEnd\n );\n pushCollapsedContextLines(\n resolvedDiff,\n deletionLines,\n additionLines,\n finalDeletionEnd,\n finalAdditionEnd,\n trailingContext\n );\n cursor.splitLineCount += trailingContext;\n cursor.unifiedLineCount += trailingContext;\n }\n\n resolvedDiff.splitLineCount = cursor.splitLineCount;\n resolvedDiff.unifiedLineCount = cursor.unifiedLineCount;\n\n return resolvedDiff;\n}\n\nfunction pushCollapsedContextLines(\n diff: FileDiffMetadata,\n deletionLines: string[],\n additionLines: string[],\n deletionLineIndex: number,\n additionLineIndex: number,\n lineCount: number\n) {\n for (let index = 0; index < lineCount; index++) {\n const deletionLine = deletionLines[deletionLineIndex + index];\n const additionLine = additionLines[additionLineIndex + index];\n if (deletionLine == null || additionLine == null) {\n throw new Error(\n 'pushCollapsedContextLines: missing collapsed context line'\n );\n }\n pushDeletionLine(diff, deletionLine);\n pushAdditionLine(diff, additionLine);\n }\n}\n\n// Partial patches track omitted context in `collapsedBefore`, but those lines do\n// not exist in the diff's line arrays. Keep the virtual row counts and file\n// positions in sync without inventing hidden lines.\nfunction processCollapsedContext(\n sourceDiff: FileDiffMetadata,\n resolvedDiff: FileDiffMetadata,\n cursor: CursorState,\n deletionLineIndex: number,\n additionLineIndex: number,\n lineCount: number,\n shouldProcessContent: boolean\n) {\n if (lineCount <= 0) {\n return;\n }\n\n if (shouldProcessContent) {\n pushCollapsedContextLines(\n resolvedDiff,\n sourceDiff.deletionLines,\n sourceDiff.additionLines,\n deletionLineIndex,\n additionLineIndex,\n lineCount\n );\n cursor.nextAdditionLineIndex += lineCount;\n cursor.nextDeletionLineIndex += lineCount;\n }\n\n cursor.nextAdditionStart += lineCount;\n cursor.nextDeletionStart += lineCount;\n cursor.splitLineCount += lineCount;\n cursor.unifiedLineCount += lineCount;\n}\n\nfunction pushContentLinesToDiff(\n content: ContextContent | ChangeContent,\n diff: FileDiffMetadata,\n deletionLines: string[],\n additionLines: string[]\n) {\n if (content.type === 'context') {\n for (let i = 0; i < content.lines; i++) {\n const line = additionLines[content.additionLineIndex + i];\n if (line == null) {\n console.error({ additionLines, content, i });\n throw new Error('pushContentLinesToDiff: Context line does not exist');\n }\n pushDeletionLine(diff, line);\n pushAdditionLine(diff, line);\n }\n } else {\n const len = Math.max(content.deletions, content.additions);\n for (let i = 0; i < len; i++) {\n if (i < content.deletions) {\n const line = deletionLines[content.deletionLineIndex + i];\n if (line == null) {\n console.error({ deletionLines, content, i });\n throw new Error(\n 'pushContentLinesToDiff: Deletion line does not exist'\n );\n }\n pushDeletionLine(diff, line);\n }\n if (i < content.additions) {\n const line = additionLines[content.additionLineIndex + i];\n if (line == null) {\n console.error({ additionLines, content, i });\n throw new Error(\n 'pushContentLinesToDiff: Addition line does not exist'\n );\n }\n pushAdditionLine(diff, line);\n }\n }\n }\n}\n\nfunction pushResolveLinesToDiff(\n resolution: 'deletions' | 'additions' | 'both',\n content: ChangeContent,\n diff: FileDiffMetadata,\n deletionLines: string[],\n additionLines: string[]\n) {\n if (resolution === 'deletions' || resolution === 'both') {\n for (let i = 0; i < content.deletions; i++) {\n const line = deletionLines[content.deletionLineIndex + i];\n if (line == null) {\n console.error({ deletionLines, content, i });\n throw new Error('pushResolveLinesToDiff: Deletion line does not exist');\n }\n pushDeletionLine(diff, line);\n pushAdditionLine(diff, line);\n }\n }\n if (resolution === 'additions' || resolution === 'both') {\n for (let i = 0; i < content.additions; i++) {\n const line = additionLines[content.additionLineIndex + i];\n if (line == null) {\n console.error({ additionLines, content, i });\n throw new Error('pushResolveLinesToDiff: Addition line does not exist');\n }\n pushDeletionLine(diff, line);\n pushAdditionLine(diff, line);\n }\n }\n}\n\nfunction advanceCursor(\n content: ChangeContent | ContextContent,\n cursor: CursorState,\n hunk: Hunk\n) {\n if (content.type === 'context') {\n cursor.nextAdditionLineIndex += content.lines;\n cursor.nextDeletionLineIndex += content.lines;\n cursor.nextAdditionStart += content.lines;\n cursor.nextDeletionStart += content.lines;\n cursor.splitLineCount += content.lines;\n cursor.unifiedLineCount += content.lines;\n\n hunk.additionCount += content.lines;\n hunk.deletionCount += content.lines;\n hunk.splitLineCount += content.lines;\n hunk.unifiedLineCount += content.lines;\n } else {\n cursor.nextAdditionLineIndex += content.additions;\n cursor.nextDeletionLineIndex += content.deletions;\n cursor.nextAdditionStart += content.additions;\n cursor.nextDeletionStart += content.deletions;\n cursor.splitLineCount += Math.max(content.deletions, content.additions);\n cursor.unifiedLineCount += content.deletions + content.additions;\n\n hunk.deletionCount += content.deletions;\n hunk.deletionLines += content.deletions;\n hunk.additionCount += content.additions;\n hunk.additionLines += content.additions;\n hunk.splitLineCount += Math.max(content.deletions, content.additions);\n hunk.unifiedLineCount += content.deletions + content.additions;\n }\n}\n\n// Appends a line to one side of the resolved diff and keeps that side's\n// character count in sync with its line array.\nfunction pushDeletionLine(diff: FileDiffMetadata, line: string) {\n diff.deletionLines.push(line);\n diff.deletionCharacterCount += line.length;\n}\n\nfunction pushAdditionLine(diff: FileDiffMetadata, line: string) {\n diff.additionLines.push(line);\n diff.additionCharacterCount += line.length;\n}\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ //#region src/utils/setDeferredArrayItem.d.ts
2
+ declare function setDeferredArrayItem<T>(array: T[], index: number, create: () => T): void;
3
+ //#endregion
4
+ export { setDeferredArrayItem };
5
+ //# sourceMappingURL=setDeferredArrayItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setDeferredArrayItem.d.ts","names":[],"sources":["../../src/utils/setDeferredArrayItem.ts"],"mappings":";iBAAgB,qBAAqB,GACnC,OAAO,KACP,eACA,cAAc"}
@@ -0,0 +1,39 @@
1
+ //#region src/utils/setDeferredArrayItem.ts
2
+ function setDeferredArrayItem(array, index, create) {
3
+ let initialized = false;
4
+ let cached;
5
+ Object.defineProperty(array, index, {
6
+ configurable: true,
7
+ enumerable: true,
8
+ get() {
9
+ if (!initialized) {
10
+ cached = create();
11
+ initialized = true;
12
+ }
13
+ if (Object.getOwnPropertyDescriptor(array, index)?.configurable === true) Object.defineProperty(array, index, {
14
+ configurable: true,
15
+ enumerable: true,
16
+ writable: true,
17
+ value: cached
18
+ });
19
+ return cached;
20
+ },
21
+ set(value) {
22
+ if (Object.getOwnPropertyDescriptor(array, index)?.configurable === true) Object.defineProperty(array, index, {
23
+ configurable: true,
24
+ enumerable: true,
25
+ writable: true,
26
+ value
27
+ });
28
+ else if (Object.isFrozen(array)) throw new TypeError(`Cannot assign to read only array index '${index}'`);
29
+ else {
30
+ cached = value;
31
+ initialized = true;
32
+ }
33
+ }
34
+ });
35
+ }
36
+ //#endregion
37
+ export { setDeferredArrayItem };
38
+
39
+ //# sourceMappingURL=setDeferredArrayItem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setDeferredArrayItem.js","names":[],"sources":["../../src/utils/setDeferredArrayItem.ts"],"sourcesContent":["export function setDeferredArrayItem<T>(\n array: T[],\n index: number,\n create: () => T\n): void {\n let initialized = false;\n let cached: T;\n Object.defineProperty(array, index, {\n configurable: true,\n enumerable: true,\n get() {\n if (!initialized) {\n cached = create();\n initialized = true;\n }\n if (\n Object.getOwnPropertyDescriptor(array, index)?.configurable === true\n ) {\n Object.defineProperty(array, index, {\n configurable: true,\n enumerable: true,\n writable: true,\n value: cached,\n });\n }\n return cached;\n },\n set(value: T) {\n if (\n Object.getOwnPropertyDescriptor(array, index)?.configurable === true\n ) {\n Object.defineProperty(array, index, {\n configurable: true,\n enumerable: true,\n writable: true,\n value,\n });\n } else if (Object.isFrozen(array)) {\n throw new TypeError(\n `Cannot assign to read only array index '${index}'`\n );\n } else {\n cached = value;\n initialized = true;\n }\n },\n });\n}\n"],"mappings":";AAAA,SAAgB,qBACd,OACA,OACA,QACM;CACN,IAAI,cAAc;CAClB,IAAI;CACJ,OAAO,eAAe,OAAO,OAAO;EAClC,cAAc;EACd,YAAY;EACZ,MAAM;GACJ,IAAI,CAAC,aAAa;IAChB,SAAS,OAAO;IAChB,cAAc;GAChB;GACA,IACE,OAAO,yBAAyB,OAAO,KAAK,CAAC,EAAE,iBAAiB,MAEhE,OAAO,eAAe,OAAO,OAAO;IAClC,cAAc;IACd,YAAY;IACZ,UAAU;IACV,OAAO;GACT,CAAC;GAEH,OAAO;EACT;EACA,IAAI,OAAU;GACZ,IACE,OAAO,yBAAyB,OAAO,KAAK,CAAC,EAAE,iBAAiB,MAEhE,OAAO,eAAe,OAAO,OAAO;IAClC,cAAc;IACd,YAAY;IACZ,UAAU;IACV;GACF,CAAC;QACI,IAAI,OAAO,SAAS,KAAK,GAC9B,MAAM,IAAI,UACR,2CAA2C,MAAM,EACnD;QACK;IACL,SAAS;IACT,cAAc;GAChB;EACF;CACF,CAAC;AACH"}
@@ -0,0 +1,11 @@
1
+ import { ThemedToken } from "../highlighter/types.js";
2
+ import "../types.js";
3
+ //#region src/utils/tokenStyle.d.ts
4
+ /**
5
+ * Returns CSS declarations for a highlighted token. Enable caching only when
6
+ * htmlStyle objects are immutable and reused across tokens.
7
+ */
8
+ declare function tokenStyle(token: ThemedToken, cacheHtmlStyle?: boolean): string;
9
+ //#endregion
10
+ export { tokenStyle };
11
+ //# sourceMappingURL=tokenStyle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenStyle.d.ts","names":[],"sources":["../../src/utils/tokenStyle.ts"],"mappings":";;;;;;;iBAUgB,WACd,OAAO,aACP"}
@@ -0,0 +1,32 @@
1
+ //#region src/utils/tokenStyle.ts
2
+ const htmlStyleCache = /* @__PURE__ */ new WeakMap();
3
+ /**
4
+ * Returns CSS declarations for a highlighted token. Enable caching only when
5
+ * htmlStyle objects are immutable and reused across tokens.
6
+ */
7
+ function tokenStyle(token, cacheHtmlStyle = false) {
8
+ const { htmlStyle } = token;
9
+ if (htmlStyle != null) {
10
+ let style = cacheHtmlStyle ? htmlStyleCache.get(htmlStyle) : void 0;
11
+ if (style == null) {
12
+ style = "";
13
+ for (const name in htmlStyle) style += `${style === "" ? "" : ";"}${name}:${htmlStyle[name]}`;
14
+ if (cacheHtmlStyle) htmlStyleCache.set(htmlStyle, style);
15
+ }
16
+ return style;
17
+ }
18
+ let style = token.color != null ? `color:${token.color}` : "";
19
+ if (token.bgColor != null) style += `;background-color:${token.bgColor}`;
20
+ if (token.fontStyle != null) {
21
+ if ((token.fontStyle & 1) !== 0) style += ";font-style:italic";
22
+ if ((token.fontStyle & 2) !== 0) style += ";font-weight:bold";
23
+ const underline = (token.fontStyle & 4) !== 0;
24
+ const strikethrough = (token.fontStyle & 8) !== 0;
25
+ if (underline || strikethrough) style += `;text-decoration:${underline ? "underline" : ""}${underline && strikethrough ? " " : ""}${strikethrough ? "line-through" : ""}`;
26
+ }
27
+ return style.replace(/^;/, "");
28
+ }
29
+ //#endregion
30
+ export { tokenStyle };
31
+
32
+ //# sourceMappingURL=tokenStyle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenStyle.js","names":[],"sources":["../../src/utils/tokenStyle.ts"],"sourcesContent":["import type { ThemedToken } from '../types';\n\n// Warning: cache only tokens from Highlights, which reuses htmlStyle objects.\n// Shiki creates one per token, so caching them adds a WeakMap entry per token.\nconst htmlStyleCache = new WeakMap<Record<string, string>, string>();\n\n/**\n * Returns CSS declarations for a highlighted token. Enable caching only when\n * htmlStyle objects are immutable and reused across tokens.\n */\nexport function tokenStyle(\n token: ThemedToken,\n cacheHtmlStyle: boolean = false\n): string {\n const { htmlStyle } = token;\n if (htmlStyle != null) {\n let style = cacheHtmlStyle ? htmlStyleCache.get(htmlStyle) : undefined;\n if (style == null) {\n style = '';\n for (const name in htmlStyle) {\n style += `${style === '' ? '' : ';'}${name}:${htmlStyle[name]}`;\n }\n if (cacheHtmlStyle) htmlStyleCache.set(htmlStyle, style);\n }\n return style;\n }\n let style = token.color != null ? `color:${token.color}` : '';\n if (token.bgColor != null) style += `;background-color:${token.bgColor}`;\n if (token.fontStyle != null) {\n if ((token.fontStyle & 1) !== 0) style += ';font-style:italic';\n if ((token.fontStyle & 2) !== 0) style += ';font-weight:bold';\n const underline = (token.fontStyle & 4) !== 0;\n const strikethrough = (token.fontStyle & 8) !== 0;\n if (underline || strikethrough)\n style += `;text-decoration:${underline ? 'underline' : ''}${underline && strikethrough ? ' ' : ''}${strikethrough ? 'line-through' : ''}`;\n }\n return style.replace(/^;/, '');\n}\n"],"mappings":";AAIA,MAAM,iCAAiB,IAAI,QAAwC;;;;;AAMnE,SAAgB,WACd,OACA,iBAA0B,OAClB;CACR,MAAM,EAAE,cAAc;CACtB,IAAI,aAAa,MAAM;EACrB,IAAI,QAAQ,iBAAiB,eAAe,IAAI,SAAS,IAAI,KAAA;EAC7D,IAAI,SAAS,MAAM;GACjB,QAAQ;GACR,KAAK,MAAM,QAAQ,WACjB,SAAS,GAAG,UAAU,KAAK,KAAK,MAAM,KAAK,GAAG,UAAU;GAE1D,IAAI,gBAAgB,eAAe,IAAI,WAAW,KAAK;EACzD;EACA,OAAO;CACT;CACA,IAAI,QAAQ,MAAM,SAAS,OAAO,SAAS,MAAM,UAAU;CAC3D,IAAI,MAAM,WAAW,MAAM,SAAS,qBAAqB,MAAM;CAC/D,IAAI,MAAM,aAAa,MAAM;EAC3B,KAAK,MAAM,YAAY,OAAO,GAAG,SAAS;EAC1C,KAAK,MAAM,YAAY,OAAO,GAAG,SAAS;EAC1C,MAAM,aAAa,MAAM,YAAY,OAAO;EAC5C,MAAM,iBAAiB,MAAM,YAAY,OAAO;EAChD,IAAI,aAAa,eACf,SAAS,oBAAoB,YAAY,cAAc,KAAK,aAAa,gBAAgB,MAAM,KAAK,gBAAgB,iBAAiB;CACzI;CACA,OAAO,MAAM,QAAQ,MAAM,EAAE;AAC/B"}
@@ -0,0 +1,11 @@
1
+ import { CodeToHtmlOptions, TokensResult } from "../highlighter/types.js";
2
+ import "../types.js";
3
+ //#region src/utils/tokensToHtml.d.ts
4
+ /**
5
+ * Renders existing tokens as a pre/code HTML block without highlighting again.
6
+ * Pass the original source to resolve numeric decoration offsets.
7
+ */
8
+ declare function tokensToHtml(source: string, result: TokensResult, options: CodeToHtmlOptions, cacheHtmlStyles?: boolean): string;
9
+ //#endregion
10
+ export { tokensToHtml };
11
+ //# sourceMappingURL=tokensToHtml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokensToHtml.d.ts","names":[],"sources":["../../src/utils/tokensToHtml.ts"],"mappings":";;;;;;;iBAUgB,aACd,gBACA,QAAQ,cACR,SAAS,mBACT"}
@@ -0,0 +1,48 @@
1
+ import { hastToHtml } from "./hastToHtml.js";
2
+ import { renderTokenLines } from "./renderTokenLines.js";
3
+ //#region src/utils/tokensToHtml.ts
4
+ /**
5
+ * Renders existing tokens as a pre/code HTML block without highlighting again.
6
+ * Pass the original source to resolve numeric decoration offsets.
7
+ */
8
+ function tokensToHtml(source, result, options, cacheHtmlStyles = false) {
9
+ const lineOffsets = [0];
10
+ if (options.decorations?.some((item) => typeof item.start === "number" || typeof item.end === "number") === true) for (let index = source.indexOf("\n"); index !== -1; index = source.indexOf("\n", index + 1)) lineOffsets.push(index + 1);
11
+ const code = {
12
+ type: "element",
13
+ tagName: "code",
14
+ properties: {},
15
+ children: []
16
+ };
17
+ const lines = renderTokenLines(result.tokens, {
18
+ decorations: options.decorations,
19
+ mergeWhitespaces: options.mergeWhitespaces,
20
+ lineOffsets,
21
+ cacheHtmlStyles
22
+ });
23
+ for (let i = 0; i < lines.length; i++) {
24
+ if (i > 0) code.children.push({
25
+ type: "text",
26
+ value: "\n"
27
+ });
28
+ code.children.push(lines[i]);
29
+ }
30
+ const root = {
31
+ type: "root",
32
+ children: [{
33
+ type: "element",
34
+ tagName: "pre",
35
+ properties: {
36
+ class: "diffs",
37
+ style: result.rootStyle === false ? void 0 : result.rootStyle ?? [result.fg != null ? `color:${result.fg}` : "", result.bg != null ? `background-color:${result.bg}` : ""].filter(Boolean).join(";"),
38
+ tabIndex: 0
39
+ },
40
+ children: [code]
41
+ }]
42
+ };
43
+ return hastToHtml(root);
44
+ }
45
+ //#endregion
46
+ export { tokensToHtml };
47
+
48
+ //# sourceMappingURL=tokensToHtml.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokensToHtml.js","names":[],"sources":["../../src/utils/tokensToHtml.ts"],"sourcesContent":["import type { Element, Root } from 'hast';\n\nimport type { CodeToHtmlOptions, TokensResult } from '../types';\nimport { hastToHtml } from './hastToHtml';\nimport { renderTokenLines } from './renderTokenLines';\n\n/**\n * Renders existing tokens as a pre/code HTML block without highlighting again.\n * Pass the original source to resolve numeric decoration offsets.\n */\nexport function tokensToHtml(\n source: string,\n result: TokensResult,\n options: CodeToHtmlOptions,\n cacheHtmlStyles: boolean = false\n): string {\n const lineOffsets = [0];\n if (\n options.decorations?.some(\n (item) => typeof item.start === 'number' || typeof item.end === 'number'\n ) === true\n ) {\n for (\n let index = source.indexOf('\\n');\n index !== -1;\n index = source.indexOf('\\n', index + 1)\n )\n lineOffsets.push(index + 1);\n }\n const code: Element = {\n type: 'element',\n tagName: 'code',\n properties: {},\n children: [],\n };\n const lines = renderTokenLines(result.tokens, {\n decorations: options.decorations,\n mergeWhitespaces: options.mergeWhitespaces,\n lineOffsets,\n cacheHtmlStyles,\n });\n for (let i = 0; i < lines.length; i++) {\n if (i > 0) code.children.push({ type: 'text', value: '\\n' });\n code.children.push(lines[i]);\n }\n const root: Root = {\n type: 'root',\n children: [\n {\n type: 'element',\n tagName: 'pre',\n properties: {\n class: 'diffs',\n style:\n result.rootStyle === false\n ? undefined\n : (result.rootStyle ??\n [\n result.fg != null ? `color:${result.fg}` : '',\n result.bg != null ? `background-color:${result.bg}` : '',\n ]\n .filter(Boolean)\n .join(';')),\n tabIndex: 0,\n },\n children: [code],\n },\n ],\n };\n return hastToHtml(root);\n}\n"],"mappings":";;;;;;;AAUA,SAAgB,aACd,QACA,QACA,SACA,kBAA2B,OACnB;CACR,MAAM,cAAc,CAAC,CAAC;CACtB,IACE,QAAQ,aAAa,MAClB,SAAS,OAAO,KAAK,UAAU,YAAY,OAAO,KAAK,QAAQ,QAClE,MAAM,MAEN,KACE,IAAI,QAAQ,OAAO,QAAQ,IAAI,GAC/B,UAAU,IACV,QAAQ,OAAO,QAAQ,MAAM,QAAQ,CAAC,GAEtC,YAAY,KAAK,QAAQ,CAAC;CAE9B,MAAM,OAAgB;EACpB,MAAM;EACN,SAAS;EACT,YAAY,CAAC;EACb,UAAU,CAAC;CACb;CACA,MAAM,QAAQ,iBAAiB,OAAO,QAAQ;EAC5C,aAAa,QAAQ;EACrB,kBAAkB,QAAQ;EAC1B;EACA;CACF,CAAC;CACD,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACrC,IAAI,IAAI,GAAG,KAAK,SAAS,KAAK;GAAE,MAAM;GAAQ,OAAO;EAAK,CAAC;EAC3D,KAAK,SAAS,KAAK,MAAM,EAAE;CAC7B;CACA,MAAM,OAAa;EACjB,MAAM;EACN,UAAU,CACR;GACE,MAAM;GACN,SAAS;GACT,YAAY;IACV,OAAO;IACP,OACE,OAAO,cAAc,QACjB,KAAA,IACC,OAAO,aACR,CACE,OAAO,MAAM,OAAO,SAAS,OAAO,OAAO,IAC3C,OAAO,MAAM,OAAO,oBAAoB,OAAO,OAAO,EACxD,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;IACjB,UAAU;GACZ;GACA,UAAU,CAAC,IAAI;EACjB,CACF;CACF;CACA,OAAO,WAAW,IAAI;AACxB"}
@@ -3,11 +3,11 @@ import { CreatePatchOptionsNonabortable } from "diff";
3
3
  //#region src/utils/updateDiffHunks.d.ts
4
4
  type HunkContent = ContextContent | ChangeContent;
5
5
  type HunkMetadataUpdate = Pick<FileDiffMetadata, 'hunks' | 'splitLineCount' | 'unifiedLineCount' | 'type'>;
6
- type FullDiffHunkUpdate = HunkMetadataUpdate & Pick<FileDiffMetadata, 'additionLines' | 'deletionLines'>;
6
+ type FullDiffHunkUpdate = HunkMetadataUpdate & Pick<FileDiffMetadata, 'additionLines' | 'deletionLines' | 'additionCharacterCount' | 'deletionCharacterCount'>;
7
7
  /** Rebuilds all hunk metadata from the current deletion/addition line arrays. */
8
8
  declare function recomputeDiffHunks(diff: FileDiffMetadata, parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;
9
9
  declare function shouldTopAlignAdditionRecompute(diff: FileDiffMetadata, additionLines: string[]): boolean;
10
- declare function recomputeTopAlignedAdditionDiff(diff: FileDiffMetadata, additionLines: string[], parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;
10
+ declare function recomputeTopAlignedAdditionDiff(diff: FileDiffMetadata, additionLines: string[], additionCharacterCount: number, parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;
11
11
  declare function recomputeEmptyDocumentDiff(diff: FileDiffMetadata, parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;
12
12
  /** Rebuilds diff hunks after an edit, top-aligning sparse addition sides when needed. */
13
13
  declare function recomputeDiffHunksForEdit(diff: FileDiffMetadata, parseDiffOptions?: CreatePatchOptionsNonabortable): FullDiffHunkUpdate;
@@ -1 +1 @@
1
- {"version":3,"file":"updateDiffHunks.d.ts","names":[],"sources":["../../src/utils/updateDiffHunks.ts"],"mappings":";;;KAgBK,cAAc,iBAAiB;KAE/B,qBAAqB,KACxB;KAIG,qBAAqB,qBACxB,KAAK;;iBAGS,mBACd,MAAM,kBACN,mBAAmB,iCAClB;iBAwDa,gCACd,MAAM,kBACN;iBAYc,gCACd,MAAM,kBACN,yBACA,mBAAmB,iCAClB;iBAkCa,2BACd,MAAM,kBACN,mBAAmB,iCAClB;;iBAKa,0BACd,MAAM,kBACN,mBAAmB,iCAClB;iBAwBa,gCACd,YAAY,KACV,wFAGF;;iBAyCc,gBACd,MAAM,kBACN,4BAA4B,kBAC5B,mBAAmB,iCAClB;iBA2Ja,4BACd,MAAM,kBACN;iBAiDc,kBACd,SAAS,aACT,wBACA,yBACC;iBAQa,8BAA8B,MAAM;iBAkBpC,8BACd,MAAM,KACJ"}
1
+ {"version":3,"file":"updateDiffHunks.d.ts","names":[],"sources":["../../src/utils/updateDiffHunks.ts"],"mappings":";;;KAgBK,cAAc,iBAAiB;KAE/B,qBAAqB,KACxB;KAIG,qBAAqB,qBACxB,KACE;;iBAQY,mBACd,MAAM,kBACN,mBAAmB,iCAClB;iBA0Da,gCACd,MAAM,kBACN;iBAYc,gCACd,MAAM,kBACN,yBACA,gCACA,mBAAmB,iCAClB;iBAoCa,2BACd,MAAM,kBACN,mBAAmB,iCAClB;;iBAKa,0BACd,MAAM,kBACN,mBAAmB,iCAClB;iBAyBa,gCACd,YAAY,KACV,wFAGF;;iBAyCc,gBACd,MAAM,kBACN,4BAA4B,kBAC5B,mBAAmB,iCAClB;iBA2Ja,4BACd,MAAM,kBACN;iBAiDc,kBACd,SAAS,aACT,wBACA,yBACC;iBAQa,8BAA8B,MAAM;iBAkBpC,8BACd,MAAM,KACJ"}
@@ -19,6 +19,8 @@ function recomputeDiffHunks(diff, parseDiffOptions) {
19
19
  unifiedLineCount: recomputed.unifiedLineCount,
20
20
  additionLines: recomputed.additionLines,
21
21
  deletionLines: recomputed.deletionLines,
22
+ additionCharacterCount: recomputed.additionCharacterCount,
23
+ deletionCharacterCount: recomputed.deletionCharacterCount,
22
24
  type: recomputed.type
23
25
  };
24
26
  }
@@ -35,7 +37,7 @@ function hasOnlyBlankAdditionContents(additionLines) {
35
37
  function shouldTopAlignAdditionRecompute(diff, additionLines) {
36
38
  return additionLines.length > 0 && additionLines.length < diff.deletionLines.length && hasOnlyBlankAdditionContents(additionLines);
37
39
  }
38
- function recomputeTopAlignedAdditionDiff(diff, additionLines, parseDiffOptions) {
40
+ function recomputeTopAlignedAdditionDiff(diff, additionLines, additionCharacterCount, parseDiffOptions) {
39
41
  const deletionContents = diff.deletionLines.join("");
40
42
  const additionSentinel = buildTopAlignedAdditionSentinel(additionLines.length, deletionContents);
41
43
  const recomputed = parseDiffFromFile({
@@ -52,16 +54,18 @@ function recomputeTopAlignedAdditionDiff(diff, additionLines, parseDiffOptions)
52
54
  unifiedLineCount: recomputed.unifiedLineCount,
53
55
  additionLines,
54
56
  deletionLines: recomputed.deletionLines,
57
+ additionCharacterCount,
58
+ deletionCharacterCount: recomputed.deletionCharacterCount,
55
59
  type: recomputed.type
56
60
  };
57
61
  }
58
62
  function recomputeEmptyDocumentDiff(diff, parseDiffOptions) {
59
- return recomputeTopAlignedAdditionDiff(diff, [""], parseDiffOptions);
63
+ return recomputeTopAlignedAdditionDiff(diff, [""], 0, parseDiffOptions);
60
64
  }
61
65
  /** Rebuilds diff hunks after an edit, top-aligning sparse addition sides when needed. */
62
66
  function recomputeDiffHunksForEdit(diff, parseDiffOptions) {
63
67
  if (diff.additionLines.length === 0) return recomputeEmptyDocumentDiff(diff, parseDiffOptions);
64
- if (shouldTopAlignAdditionRecompute(diff, diff.additionLines)) return recomputeTopAlignedAdditionDiff(diff, diff.additionLines, parseDiffOptions);
68
+ if (shouldTopAlignAdditionRecompute(diff, diff.additionLines)) return recomputeTopAlignedAdditionDiff(diff, diff.additionLines, diff.additionCharacterCount, parseDiffOptions);
65
69
  const additionLines = diff.additionLines;
66
70
  const recomputed = recomputeDiffHunks(diff, parseDiffOptions);
67
71
  preserveTrailingEditorBlankLine(recomputed, additionLines);
@@ -1 +1 @@
1
- {"version":3,"file":"updateDiffHunks.js","names":[],"sources":["../../src/utils/updateDiffHunks.ts"],"sourcesContent":["import type { CreatePatchOptionsNonabortable } from 'diff';\n\nimport type {\n ChangeContent,\n ContextContent,\n FileDiffMetadata,\n Hunk,\n} from '../types';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport {\n getHunkSideEndBoundary,\n getHunkSideStartBoundary,\n} from './getHunkSideBoundaries';\nimport { parseDiffFromFile } from './parseDiffFromFile';\nimport { hasTrailingContextMismatch } from './virtualDiffLayout';\n\ntype HunkContent = ContextContent | ChangeContent;\n\ntype HunkMetadataUpdate = Pick<\n FileDiffMetadata,\n 'hunks' | 'splitLineCount' | 'unifiedLineCount' | 'type'\n>;\n\ntype FullDiffHunkUpdate = HunkMetadataUpdate &\n Pick<FileDiffMetadata, 'additionLines' | 'deletionLines'>;\n\n/** Rebuilds all hunk metadata from the current deletion/addition line arrays. */\nexport function recomputeDiffHunks(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n const recomputed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: diff.deletionLines.join(''),\n },\n {\n name: diff.name,\n contents: diff.additionLines.join(''),\n lang: diff.lang,\n },\n parseDiffOptions\n );\n return {\n hunks: recomputed.hunks,\n splitLineCount: recomputed.splitLineCount,\n unifiedLineCount: recomputed.unifiedLineCount,\n additionLines: recomputed.additionLines,\n deletionLines: recomputed.deletionLines,\n type: recomputed.type,\n };\n}\n\n// Builds placeholder addition contents that diff as one top-aligned change row per\n// line. Bare `\\\\n` sentinels align as context against the first deletion lines,\n// which pushes the real addition rows down in split view.\nfunction buildTopAlignedAdditionSentinel(\n lineCount: number,\n deletionContents: string\n): string {\n const count = Math.max(lineCount, 1);\n let sentinel = Array.from(\n { length: count },\n (_, index) => `${' '.repeat(index + 1)}\\n`\n ).join('');\n if (sentinel === deletionContents) {\n sentinel = Array.from(\n { length: count },\n (_, index) => `\\u0000${' '.repeat(index)}\\n`\n ).join('');\n }\n return sentinel;\n}\n\nfunction hasOnlyBlankAdditionContents(additionLines: string[]): boolean {\n for (const line of additionLines) {\n if (line.trim().length > 0) {\n return false;\n }\n }\n return true;\n}\n\n// After delete-all the editable side is blank and much shorter than the deletion\n// side. A normal recompute can still treat newline-only additions as context and\n// render the first editable row deep in split view instead of at the top.\nexport function shouldTopAlignAdditionRecompute(\n diff: FileDiffMetadata,\n additionLines: string[]\n): boolean {\n return (\n additionLines.length > 0 &&\n additionLines.length < diff.deletionLines.length &&\n hasOnlyBlankAdditionContents(additionLines)\n );\n}\n\n// Rebuilds hunk metadata while keeping the editable addition rows top-aligned in\n// split view. The sentinel only shapes hunks; the caller's addition lines are\n// preserved so the editor document stays the source of truth.\nexport function recomputeTopAlignedAdditionDiff(\n diff: FileDiffMetadata,\n additionLines: string[],\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n const deletionContents = diff.deletionLines.join('');\n const additionSentinel = buildTopAlignedAdditionSentinel(\n additionLines.length,\n deletionContents\n );\n const recomputed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: deletionContents,\n },\n {\n name: diff.name,\n contents: additionSentinel,\n lang: diff.lang,\n },\n parseDiffOptions\n );\n return {\n hunks: recomputed.hunks,\n splitLineCount: recomputed.splitLineCount,\n unifiedLineCount: recomputed.unifiedLineCount,\n additionLines,\n deletionLines: recomputed.deletionLines,\n type: recomputed.type,\n };\n}\n\n// Rebuilds hunk metadata when the editable side has been emptied of all text.\n//\n// The editor always keeps one (empty) line for an empty document, but an empty\n// string splits into zero addition lines, so a normal recompute produces a diff\n// with no addition rows at all. Rendering that leaves the attached editor with\n// no line element to host its caret.\nexport function recomputeEmptyDocumentDiff(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n return recomputeTopAlignedAdditionDiff(diff, [''], parseDiffOptions);\n}\n\n/** Rebuilds diff hunks after an edit, top-aligning sparse addition sides when needed. */\nexport function recomputeDiffHunksForEdit(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n if (diff.additionLines.length === 0) {\n return recomputeEmptyDocumentDiff(diff, parseDiffOptions);\n }\n if (shouldTopAlignAdditionRecompute(diff, diff.additionLines)) {\n return recomputeTopAlignedAdditionDiff(\n diff,\n diff.additionLines,\n parseDiffOptions\n );\n }\n const additionLines = diff.additionLines;\n const recomputed = recomputeDiffHunks(diff, parseDiffOptions);\n preserveTrailingEditorBlankLine(recomputed, additionLines);\n return recomputed;\n}\n\nfunction hasTrailingEditorBlankLine(additionLines: string[]): boolean {\n return additionLines.length > 1 && additionLines.at(-1) === '';\n}\n\n// Re-adds the editor's phantom trailing empty line (a document ending in a\n// newline exposes one extra empty line) as an addition row when the last\n// hunk's final change block can absorb it, so the caret keeps a rendered row.\nexport function preserveTrailingEditorBlankLine(\n recomputed: Pick<\n FullDiffHunkUpdate,\n 'hunks' | 'additionLines' | 'splitLineCount' | 'unifiedLineCount'\n >,\n additionLines: string[]\n): void {\n if (!hasTrailingEditorBlankLine(additionLines)) {\n return;\n }\n const extraLineCount = additionLines.length - recomputed.additionLines.length;\n if (extraLineCount <= 0) {\n return;\n }\n const extraAdditionLineIndex = recomputed.additionLines.length;\n\n const lastHunk = recomputed.hunks.at(-1);\n if (lastHunk == null) {\n return;\n }\n\n const lastHunkAdditionEnd = getHunkSideEndBoundary(\n lastHunk.additionStart,\n lastHunk.additionCount\n );\n if (lastHunkAdditionEnd !== extraAdditionLineIndex) {\n return;\n }\n\n for (const content of lastHunk.hunkContent) {\n if (\n content.type === 'change' &&\n content.additions < content.deletions &&\n content.additionLineIndex + content.additions === extraAdditionLineIndex\n ) {\n recomputed.additionLines = additionLines;\n content.additions += extraLineCount;\n lastHunk.additionCount += extraLineCount;\n lastHunk.additionLines += extraLineCount;\n recomputeDiffRenderLineCounts(recomputed);\n return;\n }\n }\n}\n\n/** Updates hunk metadata after addition lines change; re-parses affected hunks only. */\nexport function updateDiffHunks(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): HunkMetadataUpdate {\n if (diff.isPartial) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n if (diff.deletionLines.length !== diff.additionLines.length) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n const changedLines = Array.from(changedAdditionLineIndexes);\n if (changedLines.length === 0) {\n return applyHunkUpdateResult(diff, {\n hunks: diff.hunks,\n splitLineCount: diff.splitLineCount,\n unifiedLineCount: diff.unifiedLineCount,\n type: diff.type,\n });\n }\n for (const line of changedLines) {\n const additionLine = diff.additionLines[line];\n const deletionLine = diff.deletionLines[line];\n if (additionLine == null || deletionLine == null) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n // Restoring a line to the old side can merge/split hunks across context windows.\n if (cleanLastNewline(additionLine) === cleanLastNewline(deletionLine)) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n }\n\n const affectedHunkIndexes = getAffectedHunkIndexes(diff, changedLines);\n if (affectedHunkIndexes.size === 0) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n for (const hunkIndex of affectedHunkIndexes) {\n const updated = reparseHunkRegion(diff, hunkIndex, parseDiffOptions);\n if (!updated) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n }\n\n recomputeDiffRenderLineCounts(diff);\n\n if (hasTrailingContextMismatch(diff)) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n return applyHunkUpdateResult(diff, {\n hunks: diff.hunks,\n splitLineCount: diff.splitLineCount,\n unifiedLineCount: diff.unifiedLineCount,\n type: diff.type,\n });\n}\n\nfunction applyHunkUpdateResult<T extends HunkMetadataUpdate>(\n diff: FileDiffMetadata,\n result: T\n): T {\n Object.assign(diff, result);\n return result;\n}\n\nfunction getAffectedHunkIndexes(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>\n): Set<number> {\n const indexes = new Set<number>();\n for (const line of changedAdditionLineIndexes) {\n const hunkIndex = findHunkIndexForAdditionLine(diff, line);\n if (hunkIndex == null) {\n return new Set();\n }\n indexes.add(hunkIndex);\n }\n return indexes;\n}\n\nfunction findHunkIndexForAdditionLine(\n diff: FileDiffMetadata,\n line: number\n): number | undefined {\n for (const [hunkIndex, hunk] of diff.hunks.entries()) {\n const end = hunk.additionLineIndex + hunk.additionCount;\n if (line >= hunk.additionLineIndex && line < end) {\n return hunkIndex;\n }\n }\n return undefined;\n}\n\nfunction reparseHunkRegion(\n diff: FileDiffMetadata,\n hunkIndex: number,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): boolean {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n return false;\n }\n\n const deletionSlice = diff.deletionLines.slice(\n hunk.deletionLineIndex,\n hunk.deletionLineIndex + hunk.deletionCount\n );\n const additionSlice = diff.additionLines.slice(\n hunk.additionLineIndex,\n hunk.additionLineIndex + hunk.additionCount\n );\n\n const reparsed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: deletionSlice.join(''),\n },\n {\n name: diff.name,\n contents: additionSlice.join(''),\n lang: diff.lang,\n },\n { ...parseDiffOptions, context: 0 }\n );\n\n const reparsedHunk = reparsed.hunks[0];\n if (reparsedHunk == null || reparsed.hunks.length !== 1) {\n return false;\n }\n\n applyReparsedHunk(hunk, reparsedHunk);\n syncHunkNoEOFCRFromFullFile(diff, hunkIndex);\n return true;\n}\n\nexport function syncHunkNoEOFCRFromFullFile(\n diff: FileDiffMetadata,\n hunkIndex: number\n): void {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n return;\n }\n\n const isLastHunk = hunkIndex === diff.hunks.length - 1;\n if (!isLastHunk) {\n hunk.noEOFCRAdditions = false;\n hunk.noEOFCRDeletions = false;\n return;\n }\n\n const lastAdditionLine = diff.additionLines.at(-1);\n const lastDeletionLine = diff.deletionLines.at(-1);\n hunk.noEOFCRAdditions =\n lastAdditionLine != null &&\n lastAdditionLine !== '' &&\n !lastAdditionLine.endsWith('\\n');\n hunk.noEOFCRDeletions =\n lastDeletionLine != null &&\n lastDeletionLine !== '' &&\n !lastDeletionLine.endsWith('\\n');\n}\n\nfunction applyReparsedHunk(target: Hunk, parsed: Hunk): void {\n const additionOffset = target.additionLineIndex;\n const deletionOffset = target.deletionLineIndex;\n\n target.hunkContent = parsed.hunkContent.map((content) =>\n offsetHunkContent(content, additionOffset, deletionOffset)\n );\n target.additionLineIndex = additionOffset + parsed.additionLineIndex;\n target.additionStart = target.additionStart + parsed.additionLineIndex;\n target.additionCount = parsed.additionCount;\n target.additionLines = parsed.additionLines;\n if (parsed.deletionLineIndex >= 0) {\n target.deletionLineIndex = deletionOffset + parsed.deletionLineIndex;\n target.deletionStart = target.deletionStart + parsed.deletionLineIndex;\n }\n target.deletionCount = parsed.deletionCount;\n target.deletionLines = parsed.deletionLines;\n target.noEOFCRAdditions = parsed.noEOFCRAdditions;\n target.noEOFCRDeletions = parsed.noEOFCRDeletions;\n\n recomputeHunkRenderLineCounts(target);\n}\n\nexport function offsetHunkContent(\n content: HunkContent,\n additionOffset: number,\n deletionOffset: number\n): HunkContent {\n return {\n ...content,\n additionLineIndex: content.additionLineIndex + additionOffset,\n deletionLineIndex: content.deletionLineIndex + deletionOffset,\n };\n}\n\nexport function recomputeHunkRenderLineCounts(hunk: Hunk): void {\n let splitLineCount = 0;\n let unifiedLineCount = 0;\n\n for (const content of hunk.hunkContent) {\n if (content.type === 'context') {\n splitLineCount += content.lines;\n unifiedLineCount += content.lines;\n } else {\n splitLineCount += Math.max(content.additions, content.deletions);\n unifiedLineCount += content.additions + content.deletions;\n }\n }\n\n hunk.splitLineCount = splitLineCount;\n hunk.unifiedLineCount = unifiedLineCount;\n}\n\nexport function recomputeDiffRenderLineCounts(\n diff: Pick<\n FileDiffMetadata,\n 'hunks' | 'splitLineCount' | 'unifiedLineCount' | 'additionLines'\n >\n): void {\n let splitTotal = 0;\n let unifiedTotal = 0;\n let lastHunkAdditionEnd = 0;\n\n for (const hunk of diff.hunks) {\n hunk.collapsedBefore = Math.max(\n getHunkSideStartBoundary(hunk.additionStart, hunk.additionCount) -\n lastHunkAdditionEnd,\n 0\n );\n hunk.splitLineStart = splitTotal + hunk.collapsedBefore;\n hunk.unifiedLineStart = unifiedTotal + hunk.collapsedBefore;\n\n recomputeHunkRenderLineCounts(hunk);\n\n splitTotal += hunk.collapsedBefore + hunk.splitLineCount;\n unifiedTotal += hunk.collapsedBefore + hunk.unifiedLineCount;\n lastHunkAdditionEnd = getHunkSideEndBoundary(\n hunk.additionStart,\n hunk.additionCount\n );\n }\n\n if (diff.hunks.length > 0) {\n const lastHunk = diff.hunks[diff.hunks.length - 1];\n const collapsedAfter = Math.max(\n diff.additionLines.length -\n getHunkSideEndBoundary(lastHunk.additionStart, lastHunk.additionCount),\n 0\n );\n splitTotal += collapsedAfter;\n unifiedTotal += collapsedAfter;\n }\n\n diff.splitLineCount = splitTotal;\n diff.unifiedLineCount = unifiedTotal;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"updateDiffHunks.js","names":[],"sources":["../../src/utils/updateDiffHunks.ts"],"sourcesContent":["import type { CreatePatchOptionsNonabortable } from 'diff';\n\nimport type {\n ChangeContent,\n ContextContent,\n FileDiffMetadata,\n Hunk,\n} from '../types';\nimport { cleanLastNewline } from './cleanLastNewline';\nimport {\n getHunkSideEndBoundary,\n getHunkSideStartBoundary,\n} from './getHunkSideBoundaries';\nimport { parseDiffFromFile } from './parseDiffFromFile';\nimport { hasTrailingContextMismatch } from './virtualDiffLayout';\n\ntype HunkContent = ContextContent | ChangeContent;\n\ntype HunkMetadataUpdate = Pick<\n FileDiffMetadata,\n 'hunks' | 'splitLineCount' | 'unifiedLineCount' | 'type'\n>;\n\ntype FullDiffHunkUpdate = HunkMetadataUpdate &\n Pick<\n FileDiffMetadata,\n | 'additionLines'\n | 'deletionLines'\n | 'additionCharacterCount'\n | 'deletionCharacterCount'\n >;\n\n/** Rebuilds all hunk metadata from the current deletion/addition line arrays. */\nexport function recomputeDiffHunks(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n const recomputed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: diff.deletionLines.join(''),\n },\n {\n name: diff.name,\n contents: diff.additionLines.join(''),\n lang: diff.lang,\n },\n parseDiffOptions\n );\n return {\n hunks: recomputed.hunks,\n splitLineCount: recomputed.splitLineCount,\n unifiedLineCount: recomputed.unifiedLineCount,\n additionLines: recomputed.additionLines,\n deletionLines: recomputed.deletionLines,\n additionCharacterCount: recomputed.additionCharacterCount,\n deletionCharacterCount: recomputed.deletionCharacterCount,\n type: recomputed.type,\n };\n}\n\n// Builds placeholder addition contents that diff as one top-aligned change row per\n// line. Bare `\\\\n` sentinels align as context against the first deletion lines,\n// which pushes the real addition rows down in split view.\nfunction buildTopAlignedAdditionSentinel(\n lineCount: number,\n deletionContents: string\n): string {\n const count = Math.max(lineCount, 1);\n let sentinel = Array.from(\n { length: count },\n (_, index) => `${' '.repeat(index + 1)}\\n`\n ).join('');\n if (sentinel === deletionContents) {\n sentinel = Array.from(\n { length: count },\n (_, index) => `\\u0000${' '.repeat(index)}\\n`\n ).join('');\n }\n return sentinel;\n}\n\nfunction hasOnlyBlankAdditionContents(additionLines: string[]): boolean {\n for (const line of additionLines) {\n if (line.trim().length > 0) {\n return false;\n }\n }\n return true;\n}\n\n// After delete-all the editable side is blank and much shorter than the deletion\n// side. A normal recompute can still treat newline-only additions as context and\n// render the first editable row deep in split view instead of at the top.\nexport function shouldTopAlignAdditionRecompute(\n diff: FileDiffMetadata,\n additionLines: string[]\n): boolean {\n return (\n additionLines.length > 0 &&\n additionLines.length < diff.deletionLines.length &&\n hasOnlyBlankAdditionContents(additionLines)\n );\n}\n\n// Rebuilds hunk metadata while keeping the editable addition rows top-aligned in\n// split view. The sentinel only shapes hunks; the caller's addition lines are\n// preserved so the editor document stays the source of truth.\nexport function recomputeTopAlignedAdditionDiff(\n diff: FileDiffMetadata,\n additionLines: string[],\n additionCharacterCount: number,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n const deletionContents = diff.deletionLines.join('');\n const additionSentinel = buildTopAlignedAdditionSentinel(\n additionLines.length,\n deletionContents\n );\n const recomputed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: deletionContents,\n },\n {\n name: diff.name,\n contents: additionSentinel,\n lang: diff.lang,\n },\n parseDiffOptions\n );\n return {\n hunks: recomputed.hunks,\n splitLineCount: recomputed.splitLineCount,\n unifiedLineCount: recomputed.unifiedLineCount,\n additionLines,\n deletionLines: recomputed.deletionLines,\n additionCharacterCount,\n deletionCharacterCount: recomputed.deletionCharacterCount,\n type: recomputed.type,\n };\n}\n\n// Rebuilds hunk metadata when the editable side has been emptied of all text.\n//\n// The editor always keeps one (empty) line for an empty document, but an empty\n// string splits into zero addition lines, so a normal recompute produces a diff\n// with no addition rows at all. Rendering that leaves the attached editor with\n// no line element to host its caret.\nexport function recomputeEmptyDocumentDiff(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n return recomputeTopAlignedAdditionDiff(diff, [''], 0, parseDiffOptions);\n}\n\n/** Rebuilds diff hunks after an edit, top-aligning sparse addition sides when needed. */\nexport function recomputeDiffHunksForEdit(\n diff: FileDiffMetadata,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): FullDiffHunkUpdate {\n if (diff.additionLines.length === 0) {\n return recomputeEmptyDocumentDiff(diff, parseDiffOptions);\n }\n if (shouldTopAlignAdditionRecompute(diff, diff.additionLines)) {\n return recomputeTopAlignedAdditionDiff(\n diff,\n diff.additionLines,\n diff.additionCharacterCount,\n parseDiffOptions\n );\n }\n const additionLines = diff.additionLines;\n const recomputed = recomputeDiffHunks(diff, parseDiffOptions);\n preserveTrailingEditorBlankLine(recomputed, additionLines);\n return recomputed;\n}\n\nfunction hasTrailingEditorBlankLine(additionLines: string[]): boolean {\n return additionLines.length > 1 && additionLines.at(-1) === '';\n}\n\n// Re-adds the editor's phantom trailing empty line (a document ending in a\n// newline exposes one extra empty line) as an addition row when the last\n// hunk's final change block can absorb it, so the caret keeps a rendered row.\nexport function preserveTrailingEditorBlankLine(\n recomputed: Pick<\n FullDiffHunkUpdate,\n 'hunks' | 'additionLines' | 'splitLineCount' | 'unifiedLineCount'\n >,\n additionLines: string[]\n): void {\n if (!hasTrailingEditorBlankLine(additionLines)) {\n return;\n }\n const extraLineCount = additionLines.length - recomputed.additionLines.length;\n if (extraLineCount <= 0) {\n return;\n }\n const extraAdditionLineIndex = recomputed.additionLines.length;\n\n const lastHunk = recomputed.hunks.at(-1);\n if (lastHunk == null) {\n return;\n }\n\n const lastHunkAdditionEnd = getHunkSideEndBoundary(\n lastHunk.additionStart,\n lastHunk.additionCount\n );\n if (lastHunkAdditionEnd !== extraAdditionLineIndex) {\n return;\n }\n\n for (const content of lastHunk.hunkContent) {\n if (\n content.type === 'change' &&\n content.additions < content.deletions &&\n content.additionLineIndex + content.additions === extraAdditionLineIndex\n ) {\n recomputed.additionLines = additionLines;\n content.additions += extraLineCount;\n lastHunk.additionCount += extraLineCount;\n lastHunk.additionLines += extraLineCount;\n recomputeDiffRenderLineCounts(recomputed);\n return;\n }\n }\n}\n\n/** Updates hunk metadata after addition lines change; re-parses affected hunks only. */\nexport function updateDiffHunks(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): HunkMetadataUpdate {\n if (diff.isPartial) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n if (diff.deletionLines.length !== diff.additionLines.length) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n const changedLines = Array.from(changedAdditionLineIndexes);\n if (changedLines.length === 0) {\n return applyHunkUpdateResult(diff, {\n hunks: diff.hunks,\n splitLineCount: diff.splitLineCount,\n unifiedLineCount: diff.unifiedLineCount,\n type: diff.type,\n });\n }\n for (const line of changedLines) {\n const additionLine = diff.additionLines[line];\n const deletionLine = diff.deletionLines[line];\n if (additionLine == null || deletionLine == null) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n // Restoring a line to the old side can merge/split hunks across context windows.\n if (cleanLastNewline(additionLine) === cleanLastNewline(deletionLine)) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n }\n\n const affectedHunkIndexes = getAffectedHunkIndexes(diff, changedLines);\n if (affectedHunkIndexes.size === 0) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n for (const hunkIndex of affectedHunkIndexes) {\n const updated = reparseHunkRegion(diff, hunkIndex, parseDiffOptions);\n if (!updated) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n }\n\n recomputeDiffRenderLineCounts(diff);\n\n if (hasTrailingContextMismatch(diff)) {\n return applyHunkUpdateResult(\n diff,\n recomputeDiffHunks(diff, parseDiffOptions)\n );\n }\n\n return applyHunkUpdateResult(diff, {\n hunks: diff.hunks,\n splitLineCount: diff.splitLineCount,\n unifiedLineCount: diff.unifiedLineCount,\n type: diff.type,\n });\n}\n\nfunction applyHunkUpdateResult<T extends HunkMetadataUpdate>(\n diff: FileDiffMetadata,\n result: T\n): T {\n Object.assign(diff, result);\n return result;\n}\n\nfunction getAffectedHunkIndexes(\n diff: FileDiffMetadata,\n changedAdditionLineIndexes: Iterable<number>\n): Set<number> {\n const indexes = new Set<number>();\n for (const line of changedAdditionLineIndexes) {\n const hunkIndex = findHunkIndexForAdditionLine(diff, line);\n if (hunkIndex == null) {\n return new Set();\n }\n indexes.add(hunkIndex);\n }\n return indexes;\n}\n\nfunction findHunkIndexForAdditionLine(\n diff: FileDiffMetadata,\n line: number\n): number | undefined {\n for (const [hunkIndex, hunk] of diff.hunks.entries()) {\n const end = hunk.additionLineIndex + hunk.additionCount;\n if (line >= hunk.additionLineIndex && line < end) {\n return hunkIndex;\n }\n }\n return undefined;\n}\n\nfunction reparseHunkRegion(\n diff: FileDiffMetadata,\n hunkIndex: number,\n parseDiffOptions?: CreatePatchOptionsNonabortable\n): boolean {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n return false;\n }\n\n const deletionSlice = diff.deletionLines.slice(\n hunk.deletionLineIndex,\n hunk.deletionLineIndex + hunk.deletionCount\n );\n const additionSlice = diff.additionLines.slice(\n hunk.additionLineIndex,\n hunk.additionLineIndex + hunk.additionCount\n );\n\n const reparsed = parseDiffFromFile(\n {\n name: diff.prevName ?? diff.name,\n contents: deletionSlice.join(''),\n },\n {\n name: diff.name,\n contents: additionSlice.join(''),\n lang: diff.lang,\n },\n { ...parseDiffOptions, context: 0 }\n );\n\n const reparsedHunk = reparsed.hunks[0];\n if (reparsedHunk == null || reparsed.hunks.length !== 1) {\n return false;\n }\n\n applyReparsedHunk(hunk, reparsedHunk);\n syncHunkNoEOFCRFromFullFile(diff, hunkIndex);\n return true;\n}\n\nexport function syncHunkNoEOFCRFromFullFile(\n diff: FileDiffMetadata,\n hunkIndex: number\n): void {\n const hunk = diff.hunks[hunkIndex];\n if (hunk == null) {\n return;\n }\n\n const isLastHunk = hunkIndex === diff.hunks.length - 1;\n if (!isLastHunk) {\n hunk.noEOFCRAdditions = false;\n hunk.noEOFCRDeletions = false;\n return;\n }\n\n const lastAdditionLine = diff.additionLines.at(-1);\n const lastDeletionLine = diff.deletionLines.at(-1);\n hunk.noEOFCRAdditions =\n lastAdditionLine != null &&\n lastAdditionLine !== '' &&\n !lastAdditionLine.endsWith('\\n');\n hunk.noEOFCRDeletions =\n lastDeletionLine != null &&\n lastDeletionLine !== '' &&\n !lastDeletionLine.endsWith('\\n');\n}\n\nfunction applyReparsedHunk(target: Hunk, parsed: Hunk): void {\n const additionOffset = target.additionLineIndex;\n const deletionOffset = target.deletionLineIndex;\n\n target.hunkContent = parsed.hunkContent.map((content) =>\n offsetHunkContent(content, additionOffset, deletionOffset)\n );\n target.additionLineIndex = additionOffset + parsed.additionLineIndex;\n target.additionStart = target.additionStart + parsed.additionLineIndex;\n target.additionCount = parsed.additionCount;\n target.additionLines = parsed.additionLines;\n if (parsed.deletionLineIndex >= 0) {\n target.deletionLineIndex = deletionOffset + parsed.deletionLineIndex;\n target.deletionStart = target.deletionStart + parsed.deletionLineIndex;\n }\n target.deletionCount = parsed.deletionCount;\n target.deletionLines = parsed.deletionLines;\n target.noEOFCRAdditions = parsed.noEOFCRAdditions;\n target.noEOFCRDeletions = parsed.noEOFCRDeletions;\n\n recomputeHunkRenderLineCounts(target);\n}\n\nexport function offsetHunkContent(\n content: HunkContent,\n additionOffset: number,\n deletionOffset: number\n): HunkContent {\n return {\n ...content,\n additionLineIndex: content.additionLineIndex + additionOffset,\n deletionLineIndex: content.deletionLineIndex + deletionOffset,\n };\n}\n\nexport function recomputeHunkRenderLineCounts(hunk: Hunk): void {\n let splitLineCount = 0;\n let unifiedLineCount = 0;\n\n for (const content of hunk.hunkContent) {\n if (content.type === 'context') {\n splitLineCount += content.lines;\n unifiedLineCount += content.lines;\n } else {\n splitLineCount += Math.max(content.additions, content.deletions);\n unifiedLineCount += content.additions + content.deletions;\n }\n }\n\n hunk.splitLineCount = splitLineCount;\n hunk.unifiedLineCount = unifiedLineCount;\n}\n\nexport function recomputeDiffRenderLineCounts(\n diff: Pick<\n FileDiffMetadata,\n 'hunks' | 'splitLineCount' | 'unifiedLineCount' | 'additionLines'\n >\n): void {\n let splitTotal = 0;\n let unifiedTotal = 0;\n let lastHunkAdditionEnd = 0;\n\n for (const hunk of diff.hunks) {\n hunk.collapsedBefore = Math.max(\n getHunkSideStartBoundary(hunk.additionStart, hunk.additionCount) -\n lastHunkAdditionEnd,\n 0\n );\n hunk.splitLineStart = splitTotal + hunk.collapsedBefore;\n hunk.unifiedLineStart = unifiedTotal + hunk.collapsedBefore;\n\n recomputeHunkRenderLineCounts(hunk);\n\n splitTotal += hunk.collapsedBefore + hunk.splitLineCount;\n unifiedTotal += hunk.collapsedBefore + hunk.unifiedLineCount;\n lastHunkAdditionEnd = getHunkSideEndBoundary(\n hunk.additionStart,\n hunk.additionCount\n );\n }\n\n if (diff.hunks.length > 0) {\n const lastHunk = diff.hunks[diff.hunks.length - 1];\n const collapsedAfter = Math.max(\n diff.additionLines.length -\n getHunkSideEndBoundary(lastHunk.additionStart, lastHunk.additionCount),\n 0\n );\n splitTotal += collapsedAfter;\n unifiedTotal += collapsedAfter;\n }\n\n diff.splitLineCount = splitTotal;\n diff.unifiedLineCount = unifiedTotal;\n}\n"],"mappings":"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"}