@pierre/diffs 1.2.12 → 1.3.0-beta.10

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 (288) hide show
  1. package/dist/components/CodeView.d.ts +91 -6
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +300 -38
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts +14 -3
  6. package/dist/components/File.d.ts.map +1 -1
  7. package/dist/components/File.js +98 -12
  8. package/dist/components/File.js.map +1 -1
  9. package/dist/components/FileDiff.d.ts +68 -19
  10. package/dist/components/FileDiff.d.ts.map +1 -1
  11. package/dist/components/FileDiff.js +363 -25
  12. package/dist/components/FileDiff.js.map +1 -1
  13. package/dist/components/FileStream.d.ts.map +1 -1
  14. package/dist/components/FileStream.js +2 -1
  15. package/dist/components/FileStream.js.map +1 -1
  16. package/dist/components/UnresolvedFile.d.ts +2 -2
  17. package/dist/components/UnresolvedFile.d.ts.map +1 -1
  18. package/dist/components/UnresolvedFile.js +2 -2
  19. package/dist/components/UnresolvedFile.js.map +1 -1
  20. package/dist/components/VirtualizedFile.d.ts +4 -2
  21. package/dist/components/VirtualizedFile.d.ts.map +1 -1
  22. package/dist/components/VirtualizedFile.js +59 -47
  23. package/dist/components/VirtualizedFile.js.map +1 -1
  24. package/dist/components/VirtualizedFileDiff.d.ts +27 -5
  25. package/dist/components/VirtualizedFileDiff.d.ts.map +1 -1
  26. package/dist/components/VirtualizedFileDiff.js +262 -56
  27. package/dist/components/VirtualizedFileDiff.js.map +1 -1
  28. package/dist/components/Virtualizer.d.ts +4 -1
  29. package/dist/components/Virtualizer.d.ts.map +1 -1
  30. package/dist/components/Virtualizer.js +21 -4
  31. package/dist/components/Virtualizer.js.map +1 -1
  32. package/dist/constants.d.ts +4 -1
  33. package/dist/constants.d.ts.map +1 -1
  34. package/dist/constants.js +4 -1
  35. package/dist/constants.js.map +1 -1
  36. package/dist/editor/command.d.ts +7 -0
  37. package/dist/editor/command.d.ts.map +1 -0
  38. package/dist/editor/command.js +54 -0
  39. package/dist/editor/command.js.map +1 -0
  40. package/dist/editor/editStack.d.ts +71 -0
  41. package/dist/editor/editStack.d.ts.map +1 -0
  42. package/dist/editor/editStack.js +218 -0
  43. package/dist/editor/editStack.js.map +1 -0
  44. package/dist/editor/editor.d.ts +105 -0
  45. package/dist/editor/editor.d.ts.map +1 -0
  46. package/dist/editor/editor.js +2545 -0
  47. package/dist/editor/editor.js.map +1 -0
  48. package/dist/editor/editor2.js +6 -0
  49. package/dist/editor/editor2.js.map +1 -0
  50. package/dist/editor/index.d.ts +5 -0
  51. package/dist/editor/index.js +3 -0
  52. package/dist/editor/languages.d.ts +26 -0
  53. package/dist/editor/languages.d.ts.map +1 -0
  54. package/dist/editor/languages.js +363 -0
  55. package/dist/editor/languages.js.map +1 -0
  56. package/dist/editor/lineAnnotations.d.ts +9 -0
  57. package/dist/editor/lineAnnotations.d.ts.map +1 -0
  58. package/dist/editor/lineAnnotations.js +212 -0
  59. package/dist/editor/lineAnnotations.js.map +1 -0
  60. package/dist/editor/marker.d.ts +38 -0
  61. package/dist/editor/marker.d.ts.map +1 -0
  62. package/dist/editor/marker.js +245 -0
  63. package/dist/editor/marker.js.map +1 -0
  64. package/dist/editor/matchBrackets.d.ts +9 -0
  65. package/dist/editor/matchBrackets.d.ts.map +1 -0
  66. package/dist/editor/matchBrackets.js +138 -0
  67. package/dist/editor/matchBrackets.js.map +1 -0
  68. package/dist/editor/pieceTable.d.ts +41 -0
  69. package/dist/editor/pieceTable.d.ts.map +1 -0
  70. package/dist/editor/pieceTable.js +671 -0
  71. package/dist/editor/pieceTable.js.map +1 -0
  72. package/dist/editor/platform.d.ts +19 -0
  73. package/dist/editor/platform.d.ts.map +1 -0
  74. package/dist/editor/platform.js +57 -0
  75. package/dist/editor/platform.js.map +1 -0
  76. package/dist/editor/popover.d.ts +65 -0
  77. package/dist/editor/popover.d.ts.map +1 -0
  78. package/dist/editor/popover.js +187 -0
  79. package/dist/editor/popover.js.map +1 -0
  80. package/dist/editor/searchPanel.d.ts +40 -0
  81. package/dist/editor/searchPanel.d.ts.map +1 -0
  82. package/dist/editor/searchPanel.js +318 -0
  83. package/dist/editor/searchPanel.js.map +1 -0
  84. package/dist/editor/selection.d.ts +211 -0
  85. package/dist/editor/selection.d.ts.map +1 -0
  86. package/dist/editor/selection.js +1626 -0
  87. package/dist/editor/selection.js.map +1 -0
  88. package/dist/editor/selectionAction.d.ts +46 -0
  89. package/dist/editor/selectionAction.d.ts.map +1 -0
  90. package/dist/editor/selectionAction.js +64 -0
  91. package/dist/editor/selectionAction.js.map +1 -0
  92. package/dist/editor/sprite.d.ts +8 -0
  93. package/dist/editor/sprite.d.ts.map +1 -0
  94. package/dist/editor/sprite.js +45 -0
  95. package/dist/editor/sprite.js.map +1 -0
  96. package/dist/editor/stateStorage.d.ts +15 -0
  97. package/dist/editor/stateStorage.d.ts.map +1 -0
  98. package/dist/editor/stateStorage.js +65 -0
  99. package/dist/editor/stateStorage.js.map +1 -0
  100. package/dist/editor/textDocument.d.ts +77 -0
  101. package/dist/editor/textDocument.d.ts.map +1 -0
  102. package/dist/editor/textDocument.js +271 -0
  103. package/dist/editor/textDocument.js.map +1 -0
  104. package/dist/editor/textMeasure.d.ts +61 -0
  105. package/dist/editor/textMeasure.d.ts.map +1 -0
  106. package/dist/editor/textMeasure.js +209 -0
  107. package/dist/editor/textMeasure.js.map +1 -0
  108. package/dist/editor/tokenizer.d.ts +41 -0
  109. package/dist/editor/tokenizer.d.ts.map +1 -0
  110. package/dist/editor/tokenizer.js +513 -0
  111. package/dist/editor/tokenizer.js.map +1 -0
  112. package/dist/editor/utils.d.ts +21 -0
  113. package/dist/editor/utils.d.ts.map +1 -0
  114. package/dist/editor/utils.js +68 -0
  115. package/dist/editor/utils.js.map +1 -0
  116. package/dist/index.d.ts +10 -8
  117. package/dist/index.js +12 -10
  118. package/dist/managers/InteractionManager.d.ts +7 -0
  119. package/dist/managers/InteractionManager.d.ts.map +1 -1
  120. package/dist/managers/InteractionManager.js +22 -1
  121. package/dist/managers/InteractionManager.js.map +1 -1
  122. package/dist/managers/ResizeManager.d.ts +10 -2
  123. package/dist/managers/ResizeManager.d.ts.map +1 -1
  124. package/dist/managers/ResizeManager.js +33 -13
  125. package/dist/managers/ResizeManager.js.map +1 -1
  126. package/dist/managers/UniversalRenderingManager.d.ts +2 -1
  127. package/dist/managers/UniversalRenderingManager.d.ts.map +1 -1
  128. package/dist/managers/UniversalRenderingManager.js +6 -1
  129. package/dist/managers/UniversalRenderingManager.js.map +1 -1
  130. package/dist/react/CodeView.d.ts +26 -1
  131. package/dist/react/CodeView.d.ts.map +1 -1
  132. package/dist/react/CodeView.js +82 -19
  133. package/dist/react/CodeView.js.map +1 -1
  134. package/dist/react/EditContext.d.ts +15 -0
  135. package/dist/react/EditContext.d.ts.map +1 -0
  136. package/dist/react/EditContext.js +23 -0
  137. package/dist/react/EditContext.js.map +1 -0
  138. package/dist/react/File.d.ts +3 -1
  139. package/dist/react/File.d.ts.map +1 -1
  140. package/dist/react/File.js +4 -2
  141. package/dist/react/File.js.map +1 -1
  142. package/dist/react/FileDiff.d.ts +4 -1
  143. package/dist/react/FileDiff.d.ts.map +1 -1
  144. package/dist/react/FileDiff.js +4 -2
  145. package/dist/react/FileDiff.js.map +1 -1
  146. package/dist/react/MultiFileDiff.d.ts +7 -5
  147. package/dist/react/MultiFileDiff.d.ts.map +1 -1
  148. package/dist/react/MultiFileDiff.js +4 -2
  149. package/dist/react/MultiFileDiff.js.map +1 -1
  150. package/dist/react/PatchDiff.d.ts +4 -1
  151. package/dist/react/PatchDiff.d.ts.map +1 -1
  152. package/dist/react/PatchDiff.js +4 -2
  153. package/dist/react/PatchDiff.js.map +1 -1
  154. package/dist/react/UnresolvedFile.d.ts +1 -0
  155. package/dist/react/UnresolvedFile.d.ts.map +1 -1
  156. package/dist/react/UnresolvedFile.js +2 -1
  157. package/dist/react/UnresolvedFile.js.map +1 -1
  158. package/dist/react/index.d.ts +3 -2
  159. package/dist/react/index.js +2 -1
  160. package/dist/react/types.d.ts +3 -0
  161. package/dist/react/types.d.ts.map +1 -1
  162. package/dist/react/utils/renderDiffChildren.d.ts +2 -0
  163. package/dist/react/utils/renderDiffChildren.d.ts.map +1 -1
  164. package/dist/react/utils/renderDiffChildren.js +16 -8
  165. package/dist/react/utils/renderDiffChildren.js.map +1 -1
  166. package/dist/react/utils/renderFileChildren.d.ts +2 -0
  167. package/dist/react/utils/renderFileChildren.d.ts.map +1 -1
  168. package/dist/react/utils/renderFileChildren.js +16 -8
  169. package/dist/react/utils/renderFileChildren.js.map +1 -1
  170. package/dist/react/utils/useFileDiffInstance.d.ts +3 -1
  171. package/dist/react/utils/useFileDiffInstance.d.ts.map +1 -1
  172. package/dist/react/utils/useFileDiffInstance.js +30 -6
  173. package/dist/react/utils/useFileDiffInstance.js.map +1 -1
  174. package/dist/react/utils/useFileInstance.d.ts +4 -1
  175. package/dist/react/utils/useFileInstance.d.ts.map +1 -1
  176. package/dist/react/utils/useFileInstance.js +30 -5
  177. package/dist/react/utils/useFileInstance.js.map +1 -1
  178. package/dist/renderers/DiffHunksRenderer.d.ts +28 -2
  179. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  180. package/dist/renderers/DiffHunksRenderer.js +244 -22
  181. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  182. package/dist/renderers/FileRenderer.d.ts +8 -1
  183. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  184. package/dist/renderers/FileRenderer.js +155 -45
  185. package/dist/renderers/FileRenderer.js.map +1 -1
  186. package/dist/ssr/index.d.ts +2 -2
  187. package/dist/ssr/preloadDiffs.d.ts +11 -10
  188. package/dist/ssr/preloadDiffs.d.ts.map +1 -1
  189. package/dist/ssr/preloadDiffs.js +15 -7
  190. package/dist/ssr/preloadDiffs.js.map +1 -1
  191. package/dist/style.js +1 -1
  192. package/dist/types.d.ts +282 -5
  193. package/dist/types.d.ts.map +1 -1
  194. package/dist/utils/applyLineTextWithNewline.d.ts +5 -0
  195. package/dist/utils/applyLineTextWithNewline.d.ts.map +1 -0
  196. package/dist/utils/applyLineTextWithNewline.js +11 -0
  197. package/dist/utils/applyLineTextWithNewline.js.map +1 -0
  198. package/dist/utils/areHunkDataEqual.js +1 -1
  199. package/dist/utils/areHunkDataEqual.js.map +1 -1
  200. package/dist/utils/areManagedSnapshotsEqual.d.ts +2 -2
  201. package/dist/utils/areManagedSnapshotsEqual.d.ts.map +1 -1
  202. package/dist/utils/areManagedSnapshotsEqual.js +5 -0
  203. package/dist/utils/areManagedSnapshotsEqual.js.map +1 -1
  204. package/dist/utils/awaitWithTimeout.d.ts +5 -0
  205. package/dist/utils/awaitWithTimeout.d.ts.map +1 -0
  206. package/dist/utils/awaitWithTimeout.js +15 -0
  207. package/dist/utils/awaitWithTimeout.js.map +1 -0
  208. package/dist/utils/cleanLastNewline.js +6 -1
  209. package/dist/utils/cleanLastNewline.js.map +1 -1
  210. package/dist/utils/cloneFileDiffMetadata.d.ts +7 -0
  211. package/dist/utils/cloneFileDiffMetadata.d.ts.map +1 -0
  212. package/dist/utils/cloneFileDiffMetadata.js +16 -0
  213. package/dist/utils/cloneFileDiffMetadata.js.map +1 -0
  214. package/dist/utils/computeEstimatedDiffHeights.d.ts +3 -1
  215. package/dist/utils/computeEstimatedDiffHeights.d.ts.map +1 -1
  216. package/dist/utils/computeEstimatedDiffHeights.js +8 -1
  217. package/dist/utils/computeEstimatedDiffHeights.js.map +1 -1
  218. package/dist/utils/computeFileOffsets.d.ts +21 -0
  219. package/dist/utils/computeFileOffsets.d.ts.map +1 -0
  220. package/dist/utils/computeFileOffsets.js +51 -0
  221. package/dist/utils/computeFileOffsets.js.map +1 -0
  222. package/dist/utils/createCodeViewHeaderFooterHostElement.d.ts +5 -0
  223. package/dist/utils/createCodeViewHeaderFooterHostElement.d.ts.map +1 -0
  224. package/dist/utils/createCodeViewHeaderFooterHostElement.js +19 -0
  225. package/dist/utils/createCodeViewHeaderFooterHostElement.js.map +1 -0
  226. package/dist/utils/createFileHeaderElement.d.ts.map +1 -1
  227. package/dist/utils/createFileHeaderElement.js +5 -1
  228. package/dist/utils/createFileHeaderElement.js.map +1 -1
  229. package/dist/utils/createTransformerWithState.js +9 -0
  230. package/dist/utils/createTransformerWithState.js.map +1 -1
  231. package/dist/utils/editSessionHunks.d.ts +84 -0
  232. package/dist/utils/editSessionHunks.d.ts.map +1 -0
  233. package/dist/utils/editSessionHunks.js +366 -0
  234. package/dist/utils/editSessionHunks.js.map +1 -0
  235. package/dist/utils/getDiffFileInput.d.ts +14 -0
  236. package/dist/utils/getDiffFileInput.d.ts.map +1 -0
  237. package/dist/utils/getDiffFileInput.js +24 -0
  238. package/dist/utils/getDiffFileInput.js.map +1 -0
  239. package/dist/utils/getDiffHunksRendererOptions.js +1 -0
  240. package/dist/utils/getDiffHunksRendererOptions.js.map +1 -1
  241. package/dist/utils/getFiletypeFromFileName.d.ts.map +1 -1
  242. package/dist/utils/getFiletypeFromFileName.js +2 -0
  243. package/dist/utils/getFiletypeFromFileName.js.map +1 -1
  244. package/dist/utils/hydratePartialDiff.d.ts +10 -0
  245. package/dist/utils/hydratePartialDiff.d.ts.map +1 -0
  246. package/dist/utils/hydratePartialDiff.js +140 -0
  247. package/dist/utils/hydratePartialDiff.js.map +1 -0
  248. package/dist/utils/iterateOverDiff.js +3 -3
  249. package/dist/utils/iterateOverDiff.js.map +1 -1
  250. package/dist/utils/parseDiffFromFile.d.ts +1 -1
  251. package/dist/utils/parseDiffFromFile.d.ts.map +1 -1
  252. package/dist/utils/parseDiffFromFile.js +26 -5
  253. package/dist/utils/parseDiffFromFile.js.map +1 -1
  254. package/dist/utils/parsePatchFiles.d.ts.map +1 -1
  255. package/dist/utils/parsePatchFiles.js +2 -0
  256. package/dist/utils/parsePatchFiles.js.map +1 -1
  257. package/dist/utils/realignChangeContent.d.ts +28 -0
  258. package/dist/utils/realignChangeContent.d.ts.map +1 -0
  259. package/dist/utils/realignChangeContent.js +142 -0
  260. package/dist/utils/realignChangeContent.js.map +1 -0
  261. package/dist/utils/renderDiffWithHighlighter.js +1 -1
  262. package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
  263. package/dist/utils/renderFileWithHighlighter.js +5 -14
  264. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  265. package/dist/utils/updateDiffHunks.d.ts +24 -0
  266. package/dist/utils/updateDiffHunks.d.ts.map +1 -0
  267. package/dist/utils/updateDiffHunks.js +235 -0
  268. package/dist/utils/updateDiffHunks.js.map +1 -0
  269. package/dist/utils/virtualDiffLayout.d.ts +40 -1
  270. package/dist/utils/virtualDiffLayout.d.ts.map +1 -1
  271. package/dist/utils/virtualDiffLayout.js +96 -1
  272. package/dist/utils/virtualDiffLayout.js.map +1 -1
  273. package/dist/worker/WorkerPoolManager.d.ts +7 -2
  274. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  275. package/dist/worker/WorkerPoolManager.js +83 -18
  276. package/dist/worker/WorkerPoolManager.js.map +1 -1
  277. package/dist/worker/index.d.ts +2 -2
  278. package/dist/worker/types.d.ts +11 -1
  279. package/dist/worker/types.d.ts.map +1 -1
  280. package/dist/worker/worker-portable.js +46 -66
  281. package/dist/worker/worker-portable.js.map +1 -1
  282. package/dist/worker/worker.js +46 -66
  283. package/dist/worker/worker.js.map +1 -1
  284. package/package.json +12 -5
  285. package/dist/utils/iterateOverFile.d.ts +0 -50
  286. package/dist/utils/iterateOverFile.d.ts.map +0 -1
  287. package/dist/utils/iterateOverFile.js +0 -49
  288. package/dist/utils/iterateOverFile.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stateStorage.js","names":["#states","#database"],"sources":["../../src/editor/stateStorage.ts"],"sourcesContent":["import type { EditorState } from '../types';\n\nexport interface IStateStorage {\n /** Read the editor state stored for a file cache key. */\n get(\n cacheKey: string\n ): EditorState | undefined | Promise<EditorState | undefined>;\n /** Store the editor state for a file cache key. */\n set(cacheKey: string, state: EditorState): void | Promise<void>;\n}\n\nexport type PersistStateStorage = 'inMemory' | 'indexedDB' | IStateStorage;\n\nexport function cloneEditorState(state: EditorState): EditorState {\n return {\n selections: state.selections?.map((selection) => ({\n start: { ...selection.start },\n end: { ...selection.end },\n direction: selection.direction,\n })),\n view: state.view === undefined ? undefined : { ...state.view },\n };\n}\n\nexport function createStateStorage(\n storage: PersistStateStorage\n): IStateStorage {\n return typeof storage === 'object'\n ? storage\n : storage === 'indexedDB'\n ? new IndexedDBStateStorage()\n : new InMemoryStateStorage();\n}\n\nclass InMemoryStateStorage implements IStateStorage {\n #states = new Map<string, EditorState>();\n\n get(cacheKey: string): EditorState | undefined {\n const state = this.#states.get(cacheKey);\n return state === undefined ? undefined : cloneEditorState(state);\n }\n\n set(cacheKey: string, state: EditorState): void {\n this.#states.set(cacheKey, cloneEditorState(state));\n }\n}\n\nconst DATABASE_NAME = 'pierre-diffs-editor-state';\nconst DATABASE_VERSION = 1;\nconst STORE_NAME = 'states';\n\nclass IndexedDBStateStorage implements IStateStorage {\n #database = openDatabase();\n\n async get(cacheKey: string): Promise<EditorState | undefined> {\n const database = await this.#database;\n if (database === undefined) {\n return undefined;\n }\n const state = await requestToPromise<EditorState | undefined>(\n database\n .transaction(STORE_NAME, 'readonly')\n .objectStore(STORE_NAME)\n .get(cacheKey)\n );\n return state === undefined ? undefined : cloneEditorState(state);\n }\n\n async set(cacheKey: string, state: EditorState): Promise<void> {\n const database = await this.#database;\n if (database === undefined) {\n return;\n }\n await requestToPromise(\n database\n .transaction(STORE_NAME, 'readwrite')\n .objectStore(STORE_NAME)\n .put(cloneEditorState(state), cacheKey)\n );\n }\n}\n\nfunction openDatabase(): Promise<IDBDatabase | undefined> {\n try {\n const factory = globalThis.indexedDB;\n if (factory === undefined) {\n return Promise.resolve(undefined);\n }\n\n const request = factory.open(DATABASE_NAME, DATABASE_VERSION);\n request.onupgradeneeded = () => {\n const database = request.result;\n if (!database.objectStoreNames.contains(STORE_NAME)) {\n database.createObjectStore(STORE_NAME);\n }\n };\n return requestToPromise(request);\n } catch {\n return Promise.resolve(undefined);\n }\n}\n\nfunction requestToPromise<T>(request: IDBRequest<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n}\n"],"mappings":";AAaA,SAAgB,iBAAiB,OAAiC;CAChE,OAAO;EACL,YAAY,MAAM,YAAY,KAAK,eAAe;GAChD,OAAO,EAAE,GAAG,UAAU,MAAM;GAC5B,KAAK,EAAE,GAAG,UAAU,IAAI;GACxB,WAAW,UAAU;EACvB,EAAE;EACF,MAAM,MAAM,SAAS,KAAA,IAAY,KAAA,IAAY,EAAE,GAAG,MAAM,KAAK;CAC/D;AACF;AAEA,SAAgB,mBACd,SACe;CACf,OAAO,OAAO,YAAY,WACtB,UACA,YAAY,cACV,IAAI,sBAAsB,IAC1B,IAAI,qBAAqB;AACjC;AAEA,IAAM,uBAAN,MAAoD;CAClD,0BAAU,IAAI,IAAyB;CAEvC,IAAI,UAA2C;EAC7C,MAAM,QAAQ,KAAKA,QAAQ,IAAI,QAAQ;EACvC,OAAO,UAAU,KAAA,IAAY,KAAA,IAAY,iBAAiB,KAAK;CACjE;CAEA,IAAI,UAAkB,OAA0B;EAC9C,KAAKA,QAAQ,IAAI,UAAU,iBAAiB,KAAK,CAAC;CACpD;AACF;AAEA,MAAM,gBAAgB;AACtB,MAAM,mBAAmB;AACzB,MAAM,aAAa;AAEnB,IAAM,wBAAN,MAAqD;CACnD,YAAY,aAAa;CAEzB,MAAM,IAAI,UAAoD;EAC5D,MAAM,WAAW,MAAM,KAAKC;EAC5B,IAAI,aAAa,KAAA,GACf;EAEF,MAAM,QAAQ,MAAM,iBAClB,SACG,YAAY,YAAY,UAAU,CAAC,CACnC,YAAY,UAAU,CAAC,CACvB,IAAI,QAAQ,CACjB;EACA,OAAO,UAAU,KAAA,IAAY,KAAA,IAAY,iBAAiB,KAAK;CACjE;CAEA,MAAM,IAAI,UAAkB,OAAmC;EAC7D,MAAM,WAAW,MAAM,KAAKA;EAC5B,IAAI,aAAa,KAAA,GACf;EAEF,MAAM,iBACJ,SACG,YAAY,YAAY,WAAW,CAAC,CACpC,YAAY,UAAU,CAAC,CACvB,IAAI,iBAAiB,KAAK,GAAG,QAAQ,CAC1C;CACF;AACF;AAEA,SAAS,eAAiD;CACxD,IAAI;EACF,MAAM,UAAU,WAAW;EAC3B,IAAI,YAAY,KAAA,GACd,OAAO,QAAQ,QAAQ,KAAA,CAAS;EAGlC,MAAM,UAAU,QAAQ,KAAK,eAAe,gBAAgB;EAC5D,QAAQ,wBAAwB;GAC9B,MAAM,WAAW,QAAQ;GACzB,IAAI,CAAC,SAAS,iBAAiB,SAAS,UAAU,GAChD,SAAS,kBAAkB,UAAU;EAEzC;EACA,OAAO,iBAAiB,OAAO;CACjC,QAAQ;EACN,OAAO,QAAQ,QAAQ,KAAA,CAAS;CAClC;AACF;AAEA,SAAS,iBAAoB,SAAoC;CAC/D,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,QAAQ,kBAAkB,QAAQ,QAAQ,MAAM;EAChD,QAAQ,gBAAgB,OAAO,QAAQ,KAAK;CAC9C,CAAC;AACH"}
@@ -0,0 +1,77 @@
1
+ import { DiffLineAnnotation, EditorSelection, Position, Range, TextEdit } from "../types.js";
2
+ import { SearchParams } from "./searchPanel.js";
3
+ import { EditStack } from "./editStack.js";
4
+
5
+ //#region src/editor/textDocument.d.ts
6
+ /** Different with `TextEdit`, the range has been resolved to offsets. */
7
+ interface ResolvedTextEdit {
8
+ /** The start offset of the text change. */
9
+ readonly start: number;
10
+ /** The end offset of the text change. */
11
+ readonly end: number;
12
+ /**
13
+ * The string to be inserted. For delete operations use an
14
+ * empty string.
15
+ */
16
+ readonly text: string;
17
+ }
18
+ interface TextDocumentChange {
19
+ /** First line whose rendered content or tokenizer state may have changed. */
20
+ readonly startLine: number;
21
+ /** Character on the first changed line where the edit began. */
22
+ readonly startCharacter: number;
23
+ /** Character on the original last changed line where the edit ended. */
24
+ readonly endCharacter: number;
25
+ /** Last line whose rendered content may have changed after the edit. */
26
+ readonly endLine: number;
27
+ /** Whether the original edit range ended at the previous document EOF. */
28
+ readonly endedAtDocumentEnd: boolean;
29
+ /** Line count before the edit was applied. */
30
+ readonly previousLineCount: number;
31
+ /** Line count after the edit was applied. */
32
+ readonly lineCount: number;
33
+ /** Difference between the old and new line counts. */
34
+ readonly lineDelta: number;
35
+ /** Exact rendered line ranges touched by each edit after the edit was applied. */
36
+ readonly changedLineRanges: readonly [startLine: number, endLine: number][];
37
+ /** Per-edit rendered line ranges before adjacent ranges are coalesced. */
38
+ readonly changedLineChanges?: readonly [startLine: number, endLine: number, lineDelta: number, startCharacter?: number, endCharacter?: number, endedAtDocumentEnd?: boolean][];
39
+ }
40
+ type TextDocumentHistoryResult<LAnnotation> = [change: TextDocumentChange, selections?: EditorSelection[], lineAnnotations?: DiffLineAnnotation<LAnnotation>[], selectionEdits?: ResolvedTextEdit[]];
41
+ /**
42
+ * A vscode-languageserver-textdocument compatible text document.
43
+ */
44
+ declare class TextDocument<LAnnotation> {
45
+ #private;
46
+ constructor(uri: string, text: string, languageId?: string, version?: number, editStack?: EditStack<LAnnotation>);
47
+ get uri(): string;
48
+ get languageId(): string;
49
+ get version(): number;
50
+ get lineCount(): number;
51
+ get eol(): string;
52
+ get canUndo(): boolean;
53
+ get canRedo(): boolean;
54
+ positionAt(offset: number): Position;
55
+ positionsAt(offsets: readonly number[]): Position[];
56
+ offsetAt(position: Position): number;
57
+ getText(range?: Range): string;
58
+ getLineText(line: number, includeLineBreak?: boolean): string;
59
+ normalizeEol(text: string): string;
60
+ getLineLength(line: number, includeLineBreak?: boolean): number;
61
+ charAt(offset: number): string;
62
+ charAt(position: Position): string;
63
+ getTextSlice(start: number, end: number): string;
64
+ findNextNonOverlappingSubstring(needle: string, occupied: readonly [start: number, end: number][]): number | undefined;
65
+ search(searchParams: SearchParams): [start: number, end: number][];
66
+ applyEdits(edits: TextEdit[], updateHistory?: boolean, selectionsBefore?: EditorSelection[], selectionsAfter?: EditorSelection[], undoBoundary?: boolean): TextDocumentChange | undefined;
67
+ resolveEdits(edits: readonly TextEdit[]): ResolvedTextEdit[];
68
+ applyResolvedEdits(edits: ResolvedTextEdit[], updateHistory?: boolean, selectionsBefore?: EditorSelection[], selectionsAfter?: EditorSelection[], undoBoundary?: boolean): TextDocumentChange | undefined;
69
+ setLastUndoSelectionsAfter(selections: EditorSelection[]): void;
70
+ setLastUndoLineAnnotations(lineAnnotationsBefore: DiffLineAnnotation<LAnnotation>[], lineAnnotationsAfter: DiffLineAnnotation<LAnnotation>[]): void;
71
+ undo(): TextDocumentHistoryResult<LAnnotation> | undefined;
72
+ redo(): TextDocumentHistoryResult<LAnnotation> | undefined;
73
+ normalizePosition(position: Position): Position;
74
+ }
75
+ //#endregion
76
+ export { type Position, type Range, ResolvedTextEdit, TextDocument, TextDocumentChange, type TextEdit };
77
+ //# sourceMappingURL=textDocument.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textDocument.d.ts","names":[],"sources":["../../src/editor/textDocument.ts"],"mappings":";;;;;;UAoBiB,gBAAA;EAAgB;EAAA,SAEtB,KAAA;EAFsB;EAAA,SAItB,GAAA;EAAA;;;AAKI;EALJ,SAKA,IAAA;AAAA;AAAA,UAGM,kBAAA;EAAkB;EAAA,SAExB,SAAA;EAEA;EAAA,SAAA,cAAA;EAIA;EAAA,SAFA,YAAA;EAMA;EAAA,SAJA,OAAA;EAQA;EAAA,SANA,kBAAA;EAQ6B;EAAA,SAN7B,iBAAA;EAQA;EAAA,SANA,SAAA;EAQP;EAAA,SANO,SAAA;EAQP;EAAA,SANO,iBAAA,YAA6B,SAAA,UAAmB,OAAA;EAQvD;EAAA,SANO,kBAAA,aACP,SAAA,UACA,OAAA,UACA,SAAA,UACA,cAAA,WACA,YAAA,WACA,kBAAA;AAAA;AAAA,KAMC,yBAAA,iBACH,MAAA,EAAQ,kBAAA,EACR,UAAA,GAAa,eAAA,IACb,eAAA,GAAkB,kBAAA,CAAmB,WAAA,KACrC,cAAA,GAAiB,gBAAA;;;;cAMN,YAAA;EAAA;EAQX,WAAA,CACE,GAAA,UACA,IAAA,UACA,UAAA,WACA,OAAA,WACA,SAAA,GAAW,SAAA,CAAU,WAAA;EAAA,IAsBnB,GAAA;EAAA,IAIA,UAAA;EAAA,IAIA,OAAA;EAAA,IAIA,SAAA;EAAA,IAIA,GAAA;EAAA,IAIA,OAAA;EAAA,IAIA,OAAA;EAIJ,UAAA,CAAW,MAAA,WAAiB,QAAA;EAI5B,WAAA,CAAY,OAAA,sBAA6B,QAAA;EAQzC,QAAA,CAAS,QAAA,EAAU,QAAA;EAInB,OAAA,CAAQ,KAAA,GAAQ,KAAA;EAgBhB,WAAA,CAAY,IAAA,UAAc,gBAAA;EAO1B,YAAA,CAAa,IAAA;EAIb,aAAA,CAAc,IAAA,UAAc,gBAAA;EAI5B,MAAA,CAAO,MAAA;EACP,MAAA,CAAO,QAAA,EAAU,QAAA;EAQjB,YAAA,CAAa,KAAA,UAAe,GAAA;EAI5B,+BAAA,CACE,MAAA,UACA,QAAA,YAAoB,KAAA,UAAe,GAAA;EAKrC,MAAA,CAAO,YAAA,EAAc,YAAA,IAAgB,KAAA,UAAe,GAAA;EAIpD,UAAA,CACE,KAAA,EAAO,QAAA,IACP,aAAA,YACA,gBAAA,GAAmB,eAAA,IACnB,eAAA,GAAkB,eAAA,IAClB,YAAA,aACC,kBAAA;EAgBH,YAAA,CAAa,KAAA,WAAgB,QAAA,KAAa,gBAAA;EAI1C,kBAAA,CACE,KAAA,EAAO,gBAAA,IACP,aAAA,YACA,gBAAA,GAAmB,eAAA,IACnB,eAAA,GAAkB,eAAA,IAClB,YAAA,aACC,kBAAA;EA2DH,0BAAA,CAA2B,UAAA,EAAY,eAAA;EAIvC,0BAAA,CACE,qBAAA,EAAuB,kBAAA,CAAmB,WAAA,KAC1C,oBAAA,EAAsB,kBAAA,CAAmB,WAAA;EAQ3C,IAAA,IAAQ,yBAAA,CAA0B,WAAA;EAqBlC,IAAA,IAAQ,yBAAA,CAA0B,WAAA;EAqBlC,iBAAA,CAAkB,QAAA,EAAU,QAAA,GAAW,QAAA;AAAA"}
@@ -0,0 +1,271 @@
1
+ import { countLineBreaks } from "../utils/computeFileOffsets.js";
2
+ import { EditStack, coalesceEditStackEntries, createEditStackEntry, shouldCoalesceEditStackEntry } from "./editStack.js";
3
+ import { PieceTable } from "./pieceTable.js";
4
+ //#region src/editor/textDocument.ts
5
+ /**
6
+ * A vscode-languageserver-textdocument compatible text document.
7
+ */
8
+ var TextDocument = class TextDocument {
9
+ #uri;
10
+ #languageId;
11
+ #version;
12
+ #pieceTable;
13
+ #editStack;
14
+ #eol;
15
+ constructor(uri, text, languageId = "text", version = 0, editStack = new EditStack()) {
16
+ this.#uri = new URL(uri, "file://").toString();
17
+ this.#languageId = languageId;
18
+ this.#version = version;
19
+ this.#pieceTable = new PieceTable(text);
20
+ this.#editStack = editStack;
21
+ const firstLineBreak = this.#pieceTable.getLineText(0, true);
22
+ if (firstLineBreak.endsWith("\r\n")) this.#eol = "\r\n";
23
+ else if (firstLineBreak.endsWith("\r")) this.#eol = "\r";
24
+ else this.#eol = "\n";
25
+ }
26
+ get uri() {
27
+ return this.#uri;
28
+ }
29
+ get languageId() {
30
+ return this.#languageId;
31
+ }
32
+ get version() {
33
+ return this.#version;
34
+ }
35
+ get lineCount() {
36
+ return this.#pieceTable.lineCount;
37
+ }
38
+ get eol() {
39
+ return this.#eol;
40
+ }
41
+ get canUndo() {
42
+ return this.#editStack.canUndo;
43
+ }
44
+ get canRedo() {
45
+ return this.#editStack.canRedo;
46
+ }
47
+ positionAt(offset) {
48
+ return this.normalizePosition(this.#pieceTable.positionAt(offset));
49
+ }
50
+ positionsAt(offsets) {
51
+ const positions = this.#pieceTable.positionsAt(offsets);
52
+ for (let i = 0; i < positions.length; i++) positions[i] = this.normalizePosition(positions[i]);
53
+ return positions;
54
+ }
55
+ offsetAt(position) {
56
+ return this.#pieceTable.offsetAt(this.normalizePosition(position));
57
+ }
58
+ getText(range) {
59
+ if (range === void 0) return this.#pieceTable.getText();
60
+ return this.#pieceTable.getText({
61
+ start: this.normalizePosition(range.start),
62
+ end: this.normalizePosition(range.end)
63
+ });
64
+ }
65
+ getLineText(line, includeLineBreak) {
66
+ return this.#pieceTable.getLineText(line, includeLineBreak);
67
+ }
68
+ normalizeEol(text) {
69
+ return text.replace(/\r\n|\r|\n/g, this.eol);
70
+ }
71
+ getLineLength(line, includeLineBreak) {
72
+ return this.#pieceTable.getLineLength(line, includeLineBreak);
73
+ }
74
+ charAt(positionOrOffset) {
75
+ if (typeof positionOrOffset === "number") return this.#pieceTable.charAt(positionOrOffset);
76
+ return this.#pieceTable.charAt(this.offsetAt(positionOrOffset));
77
+ }
78
+ getTextSlice(start, end) {
79
+ return this.#pieceTable.getTextSlice(start, end);
80
+ }
81
+ findNextNonOverlappingSubstring(needle, occupied) {
82
+ return this.#pieceTable.findNextNonOverlappingSubstring(needle, occupied);
83
+ }
84
+ search(searchParams) {
85
+ return this.#pieceTable.search(searchParams);
86
+ }
87
+ applyEdits(edits, updateHistory = true, selectionsBefore, selectionsAfter, undoBoundary = false) {
88
+ if (edits.length === 0) return;
89
+ return this.#applyResolvedEdits(this.#sortAndValidateResolvedEdits(this.resolveEdits(edits)), updateHistory, selectionsBefore, selectionsAfter, undoBoundary);
90
+ }
91
+ resolveEdits(edits) {
92
+ return edits.map((edit) => this.#resolveEdit(edit));
93
+ }
94
+ applyResolvedEdits(edits, updateHistory = true, selectionsBefore, selectionsAfter, undoBoundary = false) {
95
+ if (edits.length === 0) return;
96
+ return this.#applyResolvedEdits(this.#sortAndValidateResolvedEdits(edits.map((edit) => this.#normalizeResolvedEdit(edit))), updateHistory, selectionsBefore, selectionsAfter, undoBoundary);
97
+ }
98
+ #applyResolvedEdits(resolvedEdits, updateHistory, selectionsBefore, selectionsAfter, undoBoundary) {
99
+ const entry = createEditStackEntry(this, resolvedEdits, this.#version, this.#version + 1, updateHistory ? selectionsBefore : void 0, updateHistory ? selectionsAfter : void 0);
100
+ if (updateHistory && undoBoundary) entry.undoBoundary = true;
101
+ const previousEntry = this.#editStack.peekUndo();
102
+ const change = this.#applyResolvedEditsToBuffer(resolvedEdits);
103
+ this.#version++;
104
+ if (change.lineDelta === 0 && shouldCoalesceEditStackEntry(previousEntry, entry)) this.#editStack.replaceLastUndo(coalesceEditStackEntries(previousEntry, entry));
105
+ else this.#editStack.push(entry);
106
+ return change;
107
+ }
108
+ setLastUndoSelectionsAfter(selections) {
109
+ this.#editStack.setLastUndoSelectionsAfter(selections);
110
+ }
111
+ setLastUndoLineAnnotations(lineAnnotationsBefore, lineAnnotationsAfter) {
112
+ this.#editStack.setLastUndoLineAnnotations(lineAnnotationsBefore, lineAnnotationsAfter);
113
+ }
114
+ undo() {
115
+ const entry = this.#editStack.popUndoToRedo();
116
+ if (entry === void 0) return;
117
+ const change = this.#applyResolvedEditsToBuffer(entry.inverseEdits);
118
+ if (change === void 0) return;
119
+ this.#version = entry.versionBefore;
120
+ const selections = entry.selectionsBefore?.slice();
121
+ return [
122
+ change,
123
+ selections,
124
+ entry.lineAnnotationsBefore?.slice(),
125
+ selections === void 0 ? entry.inverseEdits.map((edit) => ({ ...edit })) : void 0
126
+ ];
127
+ }
128
+ redo() {
129
+ const entry = this.#editStack.popRedoToUndo();
130
+ if (entry === void 0) return;
131
+ const change = this.#applyResolvedEditsToBuffer(entry.forwardEdits);
132
+ if (change === void 0) return;
133
+ this.#version = entry.versionAfter;
134
+ const selections = entry.selectionsAfter?.slice();
135
+ return [
136
+ change,
137
+ selections,
138
+ entry.lineAnnotationsAfter?.slice(),
139
+ selections === void 0 ? entry.forwardEdits.map((edit) => ({ ...edit })) : void 0
140
+ ];
141
+ }
142
+ normalizePosition(position) {
143
+ const line = TextDocument.#clampIndex(position.line, this.lineCount - 1);
144
+ return {
145
+ line,
146
+ character: TextDocument.#clampIndex(position.character, this.getLineLength(line))
147
+ };
148
+ }
149
+ static #clampIndex(value, max) {
150
+ if (Number.isNaN(value)) return 0;
151
+ return Math.max(0, Math.min(Math.floor(value), max));
152
+ }
153
+ #resolveEdit(edit) {
154
+ let start = this.offsetAt(edit.range.start);
155
+ let end = this.offsetAt(edit.range.end);
156
+ if (start > end) {
157
+ const t = start;
158
+ start = end;
159
+ end = t;
160
+ }
161
+ return this.#normalizeResolvedEdit({
162
+ start,
163
+ end,
164
+ text: edit.newText
165
+ });
166
+ }
167
+ #normalizeResolvedEdit(edit) {
168
+ let { start, end } = edit;
169
+ const isInsertion = start === end;
170
+ if (this.#isInsideSurrogatePair(start)) start--;
171
+ if (isInsertion) end = start;
172
+ else if (this.#isInsideSurrogatePair(end)) end++;
173
+ return {
174
+ start,
175
+ end,
176
+ text: edit.text
177
+ };
178
+ }
179
+ #isInsideSurrogatePair(offset) {
180
+ const previous = this.#pieceTable.charAt(offset - 1).charCodeAt(0);
181
+ const next = this.#pieceTable.charAt(offset).charCodeAt(0);
182
+ return previous >= 55296 && previous <= 56319 && next >= 56320 && next <= 57343;
183
+ }
184
+ #sortAndValidateResolvedEdits(edits) {
185
+ const sortedEdits = [...edits].sort((a, b) => {
186
+ const startDelta = a.start - b.start;
187
+ return startDelta === 0 ? a.end - b.end : startDelta;
188
+ });
189
+ for (let i = 0; i < sortedEdits.length - 1; i++) if (sortedEdits[i].end > sortedEdits[i + 1].start) throw new Error("Overlapping text edits are not supported");
190
+ return sortedEdits;
191
+ }
192
+ #applyResolvedEditsToBuffer(edits) {
193
+ const previousLineCount = this.#pieceTable.lineCount;
194
+ const editPositions = this.positionsAt(edits.flatMap((edit) => [edit.start, edit.end]));
195
+ const changedLineRange = this.#computeChangedLineRange(edits, editPositions);
196
+ const startPosition = editPositions[0];
197
+ const endPosition = editPositions[editPositions.length - 1];
198
+ const endedAtDocumentEnd = endPosition.line === previousLineCount - 1 && endPosition.character === this.#pieceTable.getLineLength(endPosition.line);
199
+ this.#pieceTable.applyEdits(edits);
200
+ const lineCount = this.#pieceTable.lineCount;
201
+ return {
202
+ startLine: changedLineRange.startLine,
203
+ startCharacter: startPosition.character,
204
+ endCharacter: endPosition.character,
205
+ endLine: Math.min(changedLineRange.endLine, Math.max(0, lineCount - 1)),
206
+ endedAtDocumentEnd,
207
+ previousLineCount,
208
+ lineCount,
209
+ lineDelta: lineCount - previousLineCount,
210
+ changedLineRanges: changedLineRange.ranges,
211
+ changedLineChanges: changedLineRange.changes
212
+ };
213
+ }
214
+ #computeChangedLineRange(edits, editPositions) {
215
+ let startLine = Infinity;
216
+ let endLine = 0;
217
+ let lineDeltaBeforeEdit = 0;
218
+ const ranges = [];
219
+ const changes = [];
220
+ const previousLastLine = this.#pieceTable.lineCount - 1;
221
+ const previousLastLineLength = this.#pieceTable.getLineLength(previousLastLine);
222
+ for (let i = 0; i < edits.length; i++) {
223
+ const edit = edits[i];
224
+ const editStart = editPositions[i * 2];
225
+ const editEnd = editPositions[i * 2 + 1];
226
+ const editStartLine = editStart.line;
227
+ const editEndLine = editEnd.line;
228
+ const insertedLineSpan = countLineBreaks(edit.text);
229
+ const changedStartLine = editStartLine + lineDeltaBeforeEdit;
230
+ const changedEndLine = changedStartLine + insertedLineSpan;
231
+ const lineDelta = insertedLineSpan - (editEndLine - editStartLine);
232
+ startLine = Math.min(startLine, editStartLine);
233
+ endLine = Math.max(endLine, changedEndLine);
234
+ const lastRange = ranges[ranges.length - 1];
235
+ if (lastRange !== void 0 && changedStartLine <= lastRange[1] + 1) ranges[ranges.length - 1] = [lastRange[0], Math.max(lastRange[1], changedEndLine)];
236
+ else ranges.push([changedStartLine, changedEndLine]);
237
+ changes.push([
238
+ changedStartLine,
239
+ changedEndLine,
240
+ lineDelta,
241
+ editStart.character,
242
+ editEnd.character,
243
+ editEndLine === previousLastLine && editEnd.character === previousLastLineLength
244
+ ]);
245
+ lineDeltaBeforeEdit += lineDelta;
246
+ }
247
+ if (startLine === Infinity) return {
248
+ startLine: 0,
249
+ endLine: 0,
250
+ ranges: [[0, 0]],
251
+ changes: [[
252
+ 0,
253
+ 0,
254
+ 0,
255
+ 0,
256
+ 0,
257
+ false
258
+ ]]
259
+ };
260
+ return {
261
+ startLine,
262
+ endLine,
263
+ ranges,
264
+ changes
265
+ };
266
+ }
267
+ };
268
+ //#endregion
269
+ export { TextDocument };
270
+
271
+ //# sourceMappingURL=textDocument.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textDocument.js","names":["#uri","#languageId","#version","#pieceTable","#editStack","#eol","#applyResolvedEdits","#sortAndValidateResolvedEdits","#resolveEdit","#normalizeResolvedEdit","#applyResolvedEditsToBuffer","#clampIndex","#isInsideSurrogatePair","#computeChangedLineRange"],"sources":["../../src/editor/textDocument.ts"],"sourcesContent":["import type {\n DiffLineAnnotation,\n EditorSelection,\n Position,\n Range,\n TextEdit,\n} from '../types';\nimport { countLineBreaks } from '../utils/computeFileOffsets';\nimport {\n coalesceEditStackEntries,\n createEditStackEntry,\n EditStack,\n shouldCoalesceEditStackEntry,\n} from './editStack';\nimport { PieceTable } from './pieceTable';\nimport type { SearchParams } from './searchPanel';\n\nexport type { Position, Range, TextEdit } from '../types';\n\n/** Different with `TextEdit`, the range has been resolved to offsets. */\nexport interface ResolvedTextEdit {\n /** The start offset of the text change. */\n readonly start: number;\n /** The end offset of the text change. */\n readonly end: number;\n /**\n * The string to be inserted. For delete operations use an\n * empty string.\n */\n readonly text: string;\n}\n\nexport interface TextDocumentChange {\n /** First line whose rendered content or tokenizer state may have changed. */\n readonly startLine: number;\n /** Character on the first changed line where the edit began. */\n readonly startCharacter: number;\n /** Character on the original last changed line where the edit ended. */\n readonly endCharacter: number;\n /** Last line whose rendered content may have changed after the edit. */\n readonly endLine: number;\n /** Whether the original edit range ended at the previous document EOF. */\n readonly endedAtDocumentEnd: boolean;\n /** Line count before the edit was applied. */\n readonly previousLineCount: number;\n /** Line count after the edit was applied. */\n readonly lineCount: number;\n /** Difference between the old and new line counts. */\n readonly lineDelta: number;\n /** Exact rendered line ranges touched by each edit after the edit was applied. */\n readonly changedLineRanges: readonly [startLine: number, endLine: number][];\n /** Per-edit rendered line ranges before adjacent ranges are coalesced. */\n readonly changedLineChanges?: readonly [\n startLine: number,\n endLine: number,\n lineDelta: number,\n startCharacter?: number,\n endCharacter?: number,\n endedAtDocumentEnd?: boolean,\n ][];\n}\n\n// Metadata-less replay results include the resolved edits so Editor can remap\n// its live selections without storing a snapshot on the history entry.\ntype TextDocumentHistoryResult<LAnnotation> = [\n change: TextDocumentChange,\n selections?: EditorSelection[],\n lineAnnotations?: DiffLineAnnotation<LAnnotation>[],\n selectionEdits?: ResolvedTextEdit[],\n];\n\n/**\n * A vscode-languageserver-textdocument compatible text document.\n */\nexport class TextDocument<LAnnotation> {\n #uri: string;\n #languageId: string;\n #version: number;\n #pieceTable: PieceTable;\n #editStack: EditStack<LAnnotation>;\n #eol: string;\n\n constructor(\n uri: string,\n text: string,\n languageId = 'text',\n version = 0,\n editStack: EditStack<LAnnotation> = new EditStack()\n ) {\n this.#uri = new URL(uri, 'file://').toString();\n this.#languageId = languageId;\n this.#version = version;\n this.#pieceTable = new PieceTable(text);\n this.#editStack = editStack;\n\n // The line ending the document uses, detected once from its first line. Lets\n // inserted or pasted text match the rest of the file instead of leaving\n // mixed endings behind and keeps that convention stable as the file is\n // edited. Defaults to Unix `\\n` when the initial text has no line break.\n const firstLineBreak = this.#pieceTable.getLineText(0, true);\n if (firstLineBreak.endsWith('\\r\\n')) {\n this.#eol = '\\r\\n';\n } else if (firstLineBreak.endsWith('\\r')) {\n this.#eol = '\\r';\n } else {\n this.#eol = '\\n';\n }\n }\n\n get uri(): string {\n return this.#uri;\n }\n\n get languageId(): string {\n return this.#languageId;\n }\n\n get version(): number {\n return this.#version;\n }\n\n get lineCount(): number {\n return this.#pieceTable.lineCount;\n }\n\n get eol(): string {\n return this.#eol;\n }\n\n get canUndo(): boolean {\n return this.#editStack.canUndo;\n }\n\n get canRedo(): boolean {\n return this.#editStack.canRedo;\n }\n\n positionAt(offset: number): Position {\n return this.normalizePosition(this.#pieceTable.positionAt(offset));\n }\n\n positionsAt(offsets: readonly number[]): Position[] {\n const positions = this.#pieceTable.positionsAt(offsets);\n for (let i = 0; i < positions.length; i++) {\n positions[i] = this.normalizePosition(positions[i]);\n }\n return positions;\n }\n\n offsetAt(position: Position): number {\n return this.#pieceTable.offsetAt(this.normalizePosition(position));\n }\n\n getText(range?: Range): string {\n if (range === undefined) {\n return this.#pieceTable.getText();\n }\n // Clamp the range to visible line content before extracting text. A\n // preserved vertical-move \"goal column\" can leave a selection focus whose\n // character overshoots a shorter line; without this, the piece table clamps\n // to the line's offset span (which includes the trailing line break) and\n // copy/cut would pull in that newline. Mirrors `offsetAt`, which normalizes\n // positions the same way.\n return this.#pieceTable.getText({\n start: this.normalizePosition(range.start),\n end: this.normalizePosition(range.end),\n });\n }\n\n getLineText(line: number, includeLineBreak?: boolean): string {\n return this.#pieceTable.getLineText(line, includeLineBreak);\n }\n\n // Rewrites every line break in `text` to the document's EOL. Clipboard text\n // can carry Windows (`\\r\\n`) or classic-Mac (`\\r`) breaks; inserting it\n // verbatim would leave mixed line endings in a file that uses one style.\n normalizeEol(text: string): string {\n return text.replace(/\\r\\n|\\r|\\n/g, this.eol);\n }\n\n getLineLength(line: number, includeLineBreak?: boolean): number {\n return this.#pieceTable.getLineLength(line, includeLineBreak);\n }\n\n charAt(offset: number): string;\n charAt(position: Position): string;\n charAt(positionOrOffset: Position | number): string {\n if (typeof positionOrOffset === 'number') {\n return this.#pieceTable.charAt(positionOrOffset);\n }\n return this.#pieceTable.charAt(this.offsetAt(positionOrOffset));\n }\n\n getTextSlice(start: number, end: number): string {\n return this.#pieceTable.getTextSlice(start, end);\n }\n\n findNextNonOverlappingSubstring(\n needle: string,\n occupied: readonly [start: number, end: number][]\n ): number | undefined {\n return this.#pieceTable.findNextNonOverlappingSubstring(needle, occupied);\n }\n\n search(searchParams: SearchParams): [start: number, end: number][] {\n return this.#pieceTable.search(searchParams);\n }\n\n applyEdits(\n edits: TextEdit[],\n updateHistory = true,\n selectionsBefore?: EditorSelection[],\n selectionsAfter?: EditorSelection[],\n undoBoundary = false\n ): TextDocumentChange | undefined {\n if (edits.length === 0) {\n return;\n }\n return this.#applyResolvedEdits(\n this.#sortAndValidateResolvedEdits(this.resolveEdits(edits)),\n updateHistory,\n selectionsBefore,\n selectionsAfter,\n undoBoundary\n );\n }\n\n // Converts line/character ranges to the exact UTF-16 offsets applyEdits\n // uses, including widening invalid boundaries so they cannot split a valid\n // surrogate pair. Editor caret remapping uses the same resolved geometry.\n resolveEdits(edits: readonly TextEdit[]): ResolvedTextEdit[] {\n return edits.map((edit) => this.#resolveEdit(edit));\n }\n\n applyResolvedEdits(\n edits: ResolvedTextEdit[],\n updateHistory = true,\n selectionsBefore?: EditorSelection[],\n selectionsAfter?: EditorSelection[],\n undoBoundary = false\n ): TextDocumentChange | undefined {\n if (edits.length === 0) {\n return undefined;\n }\n return this.#applyResolvedEdits(\n this.#sortAndValidateResolvedEdits(\n edits.map((edit) => this.#normalizeResolvedEdit(edit))\n ),\n updateHistory,\n selectionsBefore,\n selectionsAfter,\n undoBoundary\n );\n }\n\n // Every edit joins the undo timeline: an edit applied with\n // `updateHistory=false` affects the edit stack exactly as the identical\n // call with `updateHistory=true` and no selections or undo boundary would.\n // The flag only controls whether the caller's interaction metadata is\n // recorded on the entry; the entry itself is always pushed (clearing any\n // pending redo) and coalesces by the normal geometry rules. This keeps a\n // mixed tracked/untracked sequence equivalent to the all-tracked sequence —\n // undo-to-exhaustion restores the original text, redo-to-exhaustion the\n // final text — instead of leaving frozen entries whose offsets go stale.\n // Only history replay (undo/redo) writes to the buffer without recording.\n #applyResolvedEdits(\n resolvedEdits: ResolvedTextEdit[],\n updateHistory: boolean,\n selectionsBefore: EditorSelection[] | undefined,\n selectionsAfter: EditorSelection[] | undefined,\n undoBoundary: boolean\n ): TextDocumentChange {\n const entry = createEditStackEntry(\n this,\n resolvedEdits,\n this.#version,\n this.#version + 1,\n updateHistory ? selectionsBefore : undefined,\n updateHistory ? selectionsAfter : undefined\n );\n if (updateHistory && undoBoundary) {\n entry.undoBoundary = true;\n }\n const previousEntry = this.#editStack.peekUndo();\n const change = this.#applyResolvedEditsToBuffer(resolvedEdits);\n this.#version++;\n if (\n change.lineDelta === 0 &&\n shouldCoalesceEditStackEntry(previousEntry, entry)\n ) {\n this.#editStack.replaceLastUndo(\n coalesceEditStackEntries(previousEntry!, entry)\n );\n } else {\n this.#editStack.push(entry);\n }\n return change;\n }\n\n setLastUndoSelectionsAfter(selections: EditorSelection[]): void {\n this.#editStack.setLastUndoSelectionsAfter(selections);\n }\n\n setLastUndoLineAnnotations(\n lineAnnotationsBefore: DiffLineAnnotation<LAnnotation>[],\n lineAnnotationsAfter: DiffLineAnnotation<LAnnotation>[]\n ): void {\n this.#editStack.setLastUndoLineAnnotations(\n lineAnnotationsBefore,\n lineAnnotationsAfter\n );\n }\n\n undo(): TextDocumentHistoryResult<LAnnotation> | undefined {\n const entry = this.#editStack.popUndoToRedo();\n if (entry === undefined) {\n return undefined;\n }\n const change = this.#applyResolvedEditsToBuffer(entry.inverseEdits);\n if (change === undefined) {\n return undefined;\n }\n this.#version = entry.versionBefore;\n const selections = entry.selectionsBefore?.slice();\n return [\n change,\n selections,\n entry.lineAnnotationsBefore?.slice(),\n selections === undefined\n ? entry.inverseEdits.map((edit) => ({ ...edit }))\n : undefined,\n ];\n }\n\n redo(): TextDocumentHistoryResult<LAnnotation> | undefined {\n const entry = this.#editStack.popRedoToUndo();\n if (entry === undefined) {\n return undefined;\n }\n const change = this.#applyResolvedEditsToBuffer(entry.forwardEdits);\n if (change === undefined) {\n return undefined;\n }\n this.#version = entry.versionAfter;\n const selections = entry.selectionsAfter?.slice();\n return [\n change,\n selections,\n entry.lineAnnotationsAfter?.slice(),\n selections === undefined\n ? entry.forwardEdits.map((edit) => ({ ...edit }))\n : undefined,\n ];\n }\n\n normalizePosition(position: Position): Position {\n const line = TextDocument.#clampIndex(position.line, this.lineCount - 1);\n return {\n line,\n character: TextDocument.#clampIndex(\n position.character,\n this.getLineLength(line)\n ),\n };\n }\n\n // Math.min/max pass NaN through, and a fractional index breaks the\n // integer-keyed line-offset lookup — either way the resolved offset becomes\n // NaN and a degenerate edit range can swallow the whole document. Malformed\n // components clamp like any other out-of-range value: NaN and -Infinity act\n // as 0, fractions floor, +Infinity clamps to the max.\n static #clampIndex(value: number, max: number): number {\n if (Number.isNaN(value)) {\n return 0;\n }\n return Math.max(0, Math.min(Math.floor(value), max));\n }\n\n #resolveEdit(edit: TextEdit): ResolvedTextEdit {\n let start = this.offsetAt(edit.range.start);\n let end = this.offsetAt(edit.range.end);\n if (start > end) {\n const t = start;\n start = end;\n end = t;\n }\n return this.#normalizeResolvedEdit({\n start,\n end,\n text: edit.newText,\n });\n }\n\n // Snaps an insertion before a pair and widens replacement boundaries\n // outward, so every edit addresses whole UTF-16 surrogate pairs.\n #normalizeResolvedEdit(edit: ResolvedTextEdit): ResolvedTextEdit {\n let { start, end } = edit;\n const isInsertion = start === end;\n if (this.#isInsideSurrogatePair(start)) {\n start--;\n }\n if (isInsertion) {\n end = start;\n } else if (this.#isInsideSurrogatePair(end)) {\n end++;\n }\n return { start, end, text: edit.text };\n }\n\n // A UTF-16 offset is invalid when it sits between the high and low units of\n // one well-formed surrogate pair. Lone surrogate units remain addressable.\n #isInsideSurrogatePair(offset: number): boolean {\n const previous = this.#pieceTable.charAt(offset - 1).charCodeAt(0);\n const next = this.#pieceTable.charAt(offset).charCodeAt(0);\n return (\n previous >= 0xd800 &&\n previous <= 0xdbff &&\n next >= 0xdc00 &&\n next <= 0xdfff\n );\n }\n\n #sortAndValidateResolvedEdits(edits: ResolvedTextEdit[]): ResolvedTextEdit[] {\n // Put zero-width edits before ranges at the same start so validation and\n // application do not depend on the caller's batch order.\n const sortedEdits = [...edits].sort((a, b) => {\n const startDelta = a.start - b.start;\n return startDelta === 0 ? a.end - b.end : startDelta;\n });\n for (let i = 0; i < sortedEdits.length - 1; i++) {\n if (sortedEdits[i].end > sortedEdits[i + 1].start) {\n throw new Error('Overlapping text edits are not supported');\n }\n }\n return sortedEdits;\n }\n\n #applyResolvedEditsToBuffer(edits: ResolvedTextEdit[]): TextDocumentChange {\n const previousLineCount = this.#pieceTable.lineCount;\n const editPositions = this.positionsAt(\n edits.flatMap((edit) => [edit.start, edit.end])\n );\n const changedLineRange = this.#computeChangedLineRange(\n edits,\n editPositions\n );\n const startPosition = editPositions[0];\n const endPosition = editPositions[editPositions.length - 1];\n const endedAtDocumentEnd =\n endPosition.line === previousLineCount - 1 &&\n endPosition.character ===\n this.#pieceTable.getLineLength(endPosition.line);\n this.#pieceTable.applyEdits(edits);\n const lineCount = this.#pieceTable.lineCount;\n const change: TextDocumentChange = {\n startLine: changedLineRange.startLine,\n startCharacter: startPosition.character,\n endCharacter: endPosition.character,\n endLine: Math.min(changedLineRange.endLine, Math.max(0, lineCount - 1)),\n endedAtDocumentEnd,\n previousLineCount,\n lineCount,\n lineDelta: lineCount - previousLineCount,\n changedLineRanges: changedLineRange.ranges,\n changedLineChanges: changedLineRange.changes,\n };\n return change;\n }\n\n #computeChangedLineRange(\n edits: ResolvedTextEdit[],\n editPositions: Position[]\n ): {\n startLine: number;\n endLine: number;\n ranges: [number, number][];\n changes: [\n startLine: number,\n endLine: number,\n lineDelta: number,\n startCharacter: number,\n endCharacter: number,\n endedAtDocumentEnd: boolean,\n ][];\n } {\n let startLine = Infinity;\n let endLine = 0;\n let lineDeltaBeforeEdit = 0;\n const ranges: [number, number][] = [];\n const changes: [\n startLine: number,\n endLine: number,\n lineDelta: number,\n startCharacter: number,\n endCharacter: number,\n endedAtDocumentEnd: boolean,\n ][] = [];\n const previousLastLine = this.#pieceTable.lineCount - 1;\n const previousLastLineLength =\n this.#pieceTable.getLineLength(previousLastLine);\n for (let i = 0; i < edits.length; i++) {\n const edit = edits[i];\n const editStart = editPositions[i * 2];\n const editEnd = editPositions[i * 2 + 1];\n const editStartLine = editStart.line;\n const editEndLine = editEnd.line;\n const insertedLineSpan = countLineBreaks(edit.text);\n const changedStartLine = editStartLine + lineDeltaBeforeEdit;\n const changedEndLine = changedStartLine + insertedLineSpan;\n const lineDelta = insertedLineSpan - (editEndLine - editStartLine);\n startLine = Math.min(startLine, editStartLine);\n endLine = Math.max(endLine, changedEndLine);\n const lastRange = ranges[ranges.length - 1];\n if (lastRange !== undefined && changedStartLine <= lastRange[1] + 1) {\n ranges[ranges.length - 1] = [\n lastRange[0],\n Math.max(lastRange[1], changedEndLine),\n ];\n } else {\n ranges.push([changedStartLine, changedEndLine]);\n }\n changes.push([\n changedStartLine,\n changedEndLine,\n lineDelta,\n editStart.character,\n editEnd.character,\n editEndLine === previousLastLine &&\n editEnd.character === previousLastLineLength,\n ]);\n lineDeltaBeforeEdit += lineDelta;\n }\n if (startLine === Infinity) {\n return {\n startLine: 0,\n endLine: 0,\n ranges: [[0, 0]],\n changes: [[0, 0, 0, 0, 0, false]],\n };\n }\n return { startLine, endLine, ranges, changes };\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ //#region src/editor/textMeasure.d.ts
2
+ declare class Metrics {
3
+ #private;
4
+ /** Width of the '0' character. */
5
+ ch: number;
6
+ /** Size of a tab(\t) character. */
7
+ tabSize: number;
8
+ /** Height of the code line. */
9
+ lineHeight: number;
10
+ /** Padding top of the root element. */
11
+ paddingTop: number;
12
+ /** initialize the metrics */
13
+ init(root: HTMLElement): void;
14
+ /**
15
+ * Re-measure the '0' character width against the font that is loaded right
16
+ * now, returning true when measurement-dependent UI should refresh.
17
+ *
18
+ * A custom web font can finish loading after the editor first renders.
19
+ * Until then canvas measureText reports the fallback font's width, and
20
+ * getComputedStyle returns the same font-family string before and after the
21
+ * file arrives, so init()'s font guard never re-measures on its own. Call
22
+ * this once fonts have settled (e.g. on document.fonts.ready) to replace a
23
+ * width measured against the fallback font with the real glyph width. Font
24
+ * completion can also change DOM-measured emoji/ZWJ widths while leaving the
25
+ * ASCII width unchanged, and the computed font string stays the same in both
26
+ * cases. The boolean return lets the caller skip re-rendering when there is no
27
+ * measured state to refresh.
28
+ */
29
+ remeasureCharacterWidth(): boolean;
30
+ /** measure the width of the text */
31
+ measureTextWidth(text: string): number;
32
+ /** measure the width of the text using the canvas measureText API */
33
+ canvasMeasureTextWidth(text: string): number;
34
+ /**
35
+ * measure the width of the text using the DOM
36
+ * this is slow because it cause a reflow, use it for non-ascii text;
37
+ * results are memoized per text so repeated measurements skip the reflow
38
+ */
39
+ domMeasureTextWidth(text: string): number;
40
+ /**
41
+ * discard memoized DOM text widths
42
+ * call this when the inherited font may have changed without re-running
43
+ * init(), e.g. on a layout reflow, so stale widths are not reused
44
+ */
45
+ clearTextWidthCache(): void;
46
+ }
47
+ /** Check if the text needs DOM text measurement. */
48
+ declare function needsDomTextMeasurement(text: string): boolean;
49
+ /** snap the text offset to the Unicode boundary */
50
+ declare function snapTextOffsetToUnicodeBoundary(text: string, offset: number): number;
51
+ /** get the offsets of the Unicode grapheme clusters in the text */
52
+ declare function getUnicodeMeasurementOffsets(text: string): number[] | undefined;
53
+ /**
54
+ * Count the rendered columns of ASCII text, advancing each tab to the next
55
+ * fixed tab stop (a multiple of tabSize) to match CSS `tab-size`. Returns -1
56
+ * for non-ASCII text, which must be measured glyph-by-glyph instead.
57
+ */
58
+ declare function getExpandedAsciiTextColumns(text: string, tabSize: number): number;
59
+ //#endregion
60
+ export { Metrics, getExpandedAsciiTextColumns, getUnicodeMeasurementOffsets, needsDomTextMeasurement, snapTextOffsetToUnicodeBoundary };
61
+ //# sourceMappingURL=textMeasure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textMeasure.d.ts","names":[],"sources":["../../src/editor/textMeasure.ts"],"mappings":";cAUa,OAAA;EAAA;EAAO;EASlB,EAAA;EASsB;EAPtB,OAAA;EAFA;EAIA,UAAA;EAAA;EAEA,UAAA;EAGA;EAAA,IAAA,CAAK,IAAA,EAAM,WAAW;EAAjB;;;;;;;;;;AAyLc;AAYrB;;;;EAtIE,uBAAA;EAuJc;EAxId,gBAAA,CAAiB,IAAA;;EA8CjB,sBAAA,CAAuB,IAAA;EA4FT;AA6ChB;;;;EA7HE,mBAAA,CAAoB,IAAA;EAyJN;;;;AAEC;EA1Gf,mBAAA;AAAA;;iBAYc,uBAAA,CAAwB,IAAY;;iBAiBpC,+BAAA,CACd,IAAA,UACA,MAAc;;iBA6CA,4BAAA,CACd,IAAY;;;;;;iBA2BE,2BAAA,CACd,IAAA,UACA,OAAe"}