@pierre/diffs 1.5.2 → 1.6.0-beta.1

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 (274) hide show
  1. package/README.md +4 -3
  2. package/dist/components/CodeView.d.ts.map +1 -1
  3. package/dist/components/CodeView.js +6 -5
  4. package/dist/components/CodeView.js.map +1 -1
  5. package/dist/components/File.d.ts.map +1 -1
  6. package/dist/components/File.js +11 -6
  7. package/dist/components/File.js.map +1 -1
  8. package/dist/components/FileDiff.d.ts.map +1 -1
  9. package/dist/components/FileDiff.js +12 -7
  10. package/dist/components/FileDiff.js.map +1 -1
  11. package/dist/components/FileStream.d.ts +6 -4
  12. package/dist/components/FileStream.d.ts.map +1 -1
  13. package/dist/components/FileStream.js +49 -36
  14. package/dist/components/FileStream.js.map +1 -1
  15. package/dist/constants.d.ts +3 -2
  16. package/dist/constants.d.ts.map +1 -1
  17. package/dist/constants.js +2 -1
  18. package/dist/constants.js.map +1 -1
  19. package/dist/editor/editor.d.ts +2 -1
  20. package/dist/editor/editor.d.ts.map +1 -1
  21. package/dist/editor/editor.js +5 -1
  22. package/dist/editor/editor.js.map +1 -1
  23. package/dist/editor/tokenizer.d.ts +6 -4
  24. package/dist/editor/tokenizer.d.ts.map +1 -1
  25. package/dist/editor/tokenizer.js +25 -470
  26. package/dist/editor/tokenizer.js.map +1 -1
  27. package/dist/highlighter/DiffsEditorTokenizer.d.ts +16 -0
  28. package/dist/highlighter/DiffsEditorTokenizer.d.ts.map +1 -0
  29. package/dist/highlighter/DiffsEditorTokenizer.js +0 -0
  30. package/dist/highlighter/DiffsHighlighter.d.ts +41 -0
  31. package/dist/highlighter/DiffsHighlighter.d.ts.map +1 -0
  32. package/dist/highlighter/DiffsHighlighter.js +39 -0
  33. package/dist/highlighter/DiffsHighlighter.js.map +1 -0
  34. package/dist/highlighter/backends/highlights.d.ts +26 -0
  35. package/dist/highlighter/backends/highlights.d.ts.map +1 -0
  36. package/dist/highlighter/backends/highlights.js +71 -0
  37. package/dist/highlighter/backends/highlights.js.map +1 -0
  38. package/dist/highlighter/backends/shiki.d.ts +27 -0
  39. package/dist/highlighter/backends/shiki.d.ts.map +1 -0
  40. package/dist/highlighter/backends/shiki.js +107 -0
  41. package/dist/highlighter/backends/shiki.js.map +1 -0
  42. package/dist/highlighter/highlighterType.d.ts +13 -0
  43. package/dist/highlighter/highlighterType.d.ts.map +1 -0
  44. package/dist/highlighter/highlighterType.js +32 -0
  45. package/dist/highlighter/highlighterType.js.map +1 -0
  46. package/dist/highlighter/highlights-editor.d.ts +24 -0
  47. package/dist/highlighter/highlights-editor.d.ts.map +1 -0
  48. package/dist/highlighter/highlights-editor.js +166 -0
  49. package/dist/highlighter/highlights-editor.js.map +1 -0
  50. package/dist/highlighter/highlights-stream.d.ts +20 -0
  51. package/dist/highlighter/highlights-stream.d.ts.map +1 -0
  52. package/dist/highlighter/highlights-stream.js +93 -0
  53. package/dist/highlighter/highlights-stream.js.map +1 -0
  54. package/dist/highlighter/languages/areLanguagesAttached.d.ts +2 -1
  55. package/dist/highlighter/languages/areLanguagesAttached.d.ts.map +1 -1
  56. package/dist/highlighter/languages/areLanguagesAttached.js +4 -6
  57. package/dist/highlighter/languages/areLanguagesAttached.js.map +1 -1
  58. package/dist/highlighter/languages/attachResolvedLanguages.d.ts +6 -1
  59. package/dist/highlighter/languages/attachResolvedLanguages.d.ts.map +1 -1
  60. package/dist/highlighter/languages/attachResolvedLanguages.js +6 -11
  61. package/dist/highlighter/languages/attachResolvedLanguages.js.map +1 -1
  62. package/dist/highlighter/languages/constants.d.ts +1 -1
  63. package/dist/highlighter/languages/getResolvedLanguages.d.ts +1 -1
  64. package/dist/highlighter/languages/getResolvedOrResolveLanguage.d.ts +1 -1
  65. package/dist/highlighter/languages/resolveLanguage.d.ts +1 -1
  66. package/dist/highlighter/languages/resolveLanguage.d.ts.map +1 -1
  67. package/dist/highlighter/languages/resolveLanguage.js +19 -16
  68. package/dist/highlighter/languages/resolveLanguage.js.map +1 -1
  69. package/dist/highlighter/languages/resolveLanguages.d.ts +1 -1
  70. package/dist/highlighter/shared_highlighter.d.ts +23 -9
  71. package/dist/highlighter/shared_highlighter.d.ts.map +1 -1
  72. package/dist/highlighter/shared_highlighter.js +59 -47
  73. package/dist/highlighter/shared_highlighter.js.map +1 -1
  74. package/dist/highlighter/shiki-editor.d.ts +25 -0
  75. package/dist/highlighter/shiki-editor.d.ts.map +1 -0
  76. package/dist/highlighter/shiki-editor.js +483 -0
  77. package/dist/highlighter/shiki-editor.js.map +1 -0
  78. package/dist/highlighter/shiki-stream.d.ts +20 -0
  79. package/dist/highlighter/shiki-stream.d.ts.map +1 -0
  80. package/dist/highlighter/shiki-stream.js +60 -0
  81. package/dist/highlighter/shiki-stream.js.map +1 -0
  82. package/dist/highlighter/stream-tokenizer.d.ts +40 -0
  83. package/dist/highlighter/stream-tokenizer.d.ts.map +1 -0
  84. package/dist/highlighter/stream-tokenizer.js +70 -0
  85. package/dist/highlighter/stream-tokenizer.js.map +1 -0
  86. package/dist/highlighter/themes/areThemesAttached.d.ts +3 -2
  87. package/dist/highlighter/themes/areThemesAttached.d.ts.map +1 -1
  88. package/dist/highlighter/themes/areThemesAttached.js +5 -4
  89. package/dist/highlighter/themes/areThemesAttached.js.map +1 -1
  90. package/dist/highlighter/themes/attachResolvedThemes.d.ts +5 -2
  91. package/dist/highlighter/themes/attachResolvedThemes.d.ts.map +1 -1
  92. package/dist/highlighter/themes/attachResolvedThemes.js +4 -16
  93. package/dist/highlighter/themes/attachResolvedThemes.js.map +1 -1
  94. package/dist/highlighter/themes/cleanUpResolvedThemes.d.ts +3 -1
  95. package/dist/highlighter/themes/cleanUpResolvedThemes.d.ts.map +1 -1
  96. package/dist/highlighter/themes/cleanUpResolvedThemes.js +8 -5
  97. package/dist/highlighter/themes/cleanUpResolvedThemes.js.map +1 -1
  98. package/dist/highlighter/themes/createCSSVariablesTheme.d.ts +7 -0
  99. package/dist/highlighter/themes/createCSSVariablesTheme.d.ts.map +1 -0
  100. package/dist/highlighter/themes/createCSSVariablesTheme.js +89 -0
  101. package/dist/highlighter/themes/createCSSVariablesTheme.js.map +1 -0
  102. package/dist/highlighter/themes/createCachedLoader.d.ts +5 -0
  103. package/dist/highlighter/themes/createCachedLoader.d.ts.map +1 -0
  104. package/dist/highlighter/themes/createCachedLoader.js +15 -0
  105. package/dist/highlighter/themes/createCachedLoader.js.map +1 -0
  106. package/dist/highlighter/themes/getResolvedOrResolveTheme.d.ts +3 -2
  107. package/dist/highlighter/themes/getResolvedOrResolveTheme.d.ts.map +1 -1
  108. package/dist/highlighter/themes/getResolvedOrResolveTheme.js +4 -4
  109. package/dist/highlighter/themes/getResolvedOrResolveTheme.js.map +1 -1
  110. package/dist/highlighter/themes/getResolvedThemes.d.ts +3 -2
  111. package/dist/highlighter/themes/getResolvedThemes.d.ts.map +1 -1
  112. package/dist/highlighter/themes/getResolvedThemes.js +4 -3
  113. package/dist/highlighter/themes/getResolvedThemes.js.map +1 -1
  114. package/dist/highlighter/themes/hasResolvedThemes.d.ts +2 -2
  115. package/dist/highlighter/themes/hasResolvedThemes.d.ts.map +1 -1
  116. package/dist/highlighter/themes/hasResolvedThemes.js +4 -3
  117. package/dist/highlighter/themes/hasResolvedThemes.js.map +1 -1
  118. package/dist/highlighter/themes/registerCustomCSSVariableTheme.d.ts.map +1 -1
  119. package/dist/highlighter/themes/registerCustomCSSVariableTheme.js +3 -3
  120. package/dist/highlighter/themes/registerCustomCSSVariableTheme.js.map +1 -1
  121. package/dist/highlighter/themes/registerCustomTheme.d.ts +9 -4
  122. package/dist/highlighter/themes/registerCustomTheme.d.ts.map +1 -1
  123. package/dist/highlighter/themes/registerCustomTheme.js +8 -16
  124. package/dist/highlighter/themes/registerCustomTheme.js.map +1 -1
  125. package/dist/highlighter/themes/resolveTheme.d.ts +3 -2
  126. package/dist/highlighter/themes/resolveTheme.d.ts.map +1 -1
  127. package/dist/highlighter/themes/resolveTheme.js +4 -7
  128. package/dist/highlighter/themes/resolveTheme.js.map +1 -1
  129. package/dist/highlighter/themes/resolveThemes.d.ts +3 -2
  130. package/dist/highlighter/themes/resolveThemes.d.ts.map +1 -1
  131. package/dist/highlighter/themes/resolveThemes.js +4 -7
  132. package/dist/highlighter/themes/resolveThemes.js.map +1 -1
  133. package/dist/highlighter/themes/themeResolver.d.ts +10 -4
  134. package/dist/highlighter/themes/themeResolver.d.ts.map +1 -1
  135. package/dist/highlighter/themes/themeResolver.js +141 -2
  136. package/dist/highlighter/themes/themeResolver.js.map +1 -1
  137. package/dist/highlighter/themes/types.d.ts +23 -0
  138. package/dist/highlighter/themes/types.d.ts.map +1 -0
  139. package/dist/highlighter/themes/types.js +0 -0
  140. package/dist/highlighter/tokenizer-types.d.ts +35 -0
  141. package/dist/highlighter/tokenizer-types.d.ts.map +1 -0
  142. package/dist/highlighter/tokenizer-types.js +0 -0
  143. package/dist/highlighter/types.d.ts +55 -0
  144. package/dist/highlighter/types.d.ts.map +1 -0
  145. package/dist/highlighter/types.js +0 -0
  146. package/dist/index.d.ts +14 -10
  147. package/dist/index.js +16 -18
  148. package/dist/managers/InteractionManager.d.ts.map +1 -1
  149. package/dist/managers/InteractionManager.js +2 -2
  150. package/dist/managers/InteractionManager.js.map +1 -1
  151. package/dist/node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.d.ts +9 -1
  152. package/dist/node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.d.ts.map +1 -1
  153. package/dist/react/CodeView.js +1 -1
  154. package/dist/react/index.d.ts +8 -3
  155. package/dist/renderers/DiffHunksRenderer.d.ts +2 -1
  156. package/dist/renderers/DiffHunksRenderer.d.ts.map +1 -1
  157. package/dist/renderers/DiffHunksRenderer.js +31 -22
  158. package/dist/renderers/DiffHunksRenderer.js.map +1 -1
  159. package/dist/renderers/FileRenderer.d.ts +2 -1
  160. package/dist/renderers/FileRenderer.d.ts.map +1 -1
  161. package/dist/renderers/FileRenderer.js +33 -24
  162. package/dist/renderers/FileRenderer.js.map +1 -1
  163. package/dist/shiki-stream/index.d.ts +3 -3
  164. package/dist/shiki-stream/index.js +1 -2
  165. package/dist/shiki-stream/stream.d.ts +4 -4
  166. package/dist/shiki-stream/stream.d.ts.map +1 -1
  167. package/dist/shiki-stream/stream.js +20 -9
  168. package/dist/shiki-stream/stream.js.map +1 -1
  169. package/dist/shiki-stream/types.d.ts +7 -38
  170. package/dist/shiki-stream/types.d.ts.map +1 -1
  171. package/dist/ssr/FileDiffReact.js +1 -1
  172. package/dist/ssr/index.d.ts +7 -2
  173. package/dist/ssr/renderHTML.js +2 -2
  174. package/dist/ssr/renderHTML.js.map +1 -1
  175. package/dist/style.js +1 -1
  176. package/dist/style.js.map +1 -1
  177. package/dist/types.d.ts +10 -11
  178. package/dist/types.d.ts.map +1 -1
  179. package/dist/utils/createSpanNodeFromToken.d.ts +3 -2
  180. package/dist/utils/createSpanNodeFromToken.d.ts.map +1 -1
  181. package/dist/utils/createSpanNodeFromToken.js +4 -5
  182. package/dist/utils/createSpanNodeFromToken.js.map +1 -1
  183. package/dist/utils/cssWrappers.d.ts.map +1 -1
  184. package/dist/utils/cssWrappers.js +12 -0
  185. package/dist/utils/cssWrappers.js.map +1 -1
  186. package/dist/utils/getHighlighterOptions.d.ts.map +1 -1
  187. package/dist/utils/getHighlighterOptions.js +3 -2
  188. package/dist/utils/getHighlighterOptions.js.map +1 -1
  189. package/dist/utils/getHighlighterThemeStyles.d.ts +2 -1
  190. package/dist/utils/getHighlighterThemeStyles.d.ts.map +1 -1
  191. package/dist/utils/getHighlighterThemeStyles.js +13 -3
  192. package/dist/utils/getHighlighterThemeStyles.js.map +1 -1
  193. package/dist/utils/getTokenOptions.d.ts +7 -0
  194. package/dist/utils/getTokenOptions.d.ts.map +1 -0
  195. package/dist/utils/getTokenOptions.js +16 -0
  196. package/dist/utils/getTokenOptions.js.map +1 -0
  197. package/dist/utils/hastToHtml.d.ts +10 -0
  198. package/dist/utils/hastToHtml.d.ts.map +1 -0
  199. package/dist/utils/hastToHtml.js +125 -0
  200. package/dist/utils/hastToHtml.js.map +1 -0
  201. package/dist/utils/parseDiffDecorations.d.ts +2 -1
  202. package/dist/utils/parseDiffDecorations.d.ts.map +1 -1
  203. package/dist/utils/renderDiffWithHighlighter.d.ts +3 -2
  204. package/dist/utils/renderDiffWithHighlighter.d.ts.map +1 -1
  205. package/dist/utils/renderDiffWithHighlighter.js +33 -48
  206. package/dist/utils/renderDiffWithHighlighter.js.map +1 -1
  207. package/dist/utils/renderFileWithHighlighter.d.ts +3 -2
  208. package/dist/utils/renderFileWithHighlighter.d.ts.map +1 -1
  209. package/dist/utils/renderFileWithHighlighter.js +10 -26
  210. package/dist/utils/renderFileWithHighlighter.js.map +1 -1
  211. package/dist/utils/renderTokenLines.d.ts +17 -0
  212. package/dist/utils/renderTokenLines.d.ts.map +1 -0
  213. package/dist/utils/renderTokenLines.js +246 -0
  214. package/dist/utils/renderTokenLines.js.map +1 -0
  215. package/dist/utils/resolvePreferredHighlighter.d.ts +13 -0
  216. package/dist/utils/resolvePreferredHighlighter.d.ts.map +1 -0
  217. package/dist/utils/resolvePreferredHighlighter.js +11 -0
  218. package/dist/utils/resolvePreferredHighlighter.js.map +1 -0
  219. package/dist/utils/setDeferredArrayItem.d.ts +5 -0
  220. package/dist/utils/setDeferredArrayItem.d.ts.map +1 -0
  221. package/dist/utils/setDeferredArrayItem.js +39 -0
  222. package/dist/utils/setDeferredArrayItem.js.map +1 -0
  223. package/dist/utils/tokenStyle.d.ts +7 -0
  224. package/dist/utils/tokenStyle.d.ts.map +1 -0
  225. package/dist/utils/tokenStyle.js +28 -0
  226. package/dist/utils/tokenStyle.js.map +1 -0
  227. package/dist/utils/tokensToHtml.d.ts +8 -0
  228. package/dist/utils/tokensToHtml.d.ts.map +1 -0
  229. package/dist/utils/tokensToHtml.js +45 -0
  230. package/dist/utils/tokensToHtml.js.map +1 -0
  231. package/dist/utils/wrapTokenFragments.js.map +1 -1
  232. package/dist/worker/WorkerPoolManager.d.ts +2 -2
  233. package/dist/worker/WorkerPoolManager.d.ts.map +1 -1
  234. package/dist/worker/WorkerPoolManager.js +56 -46
  235. package/dist/worker/WorkerPoolManager.js.map +1 -1
  236. package/dist/worker/hastLinesTransport.d.ts +14 -0
  237. package/dist/worker/hastLinesTransport.d.ts.map +1 -0
  238. package/dist/worker/hastLinesTransport.js +156 -0
  239. package/dist/worker/hastLinesTransport.js.map +1 -0
  240. package/dist/worker/highlights-sAHlxqlf.js +317 -0
  241. package/dist/worker/highlights-sAHlxqlf.js.map +1 -0
  242. package/dist/worker/index.d.ts +1 -1
  243. package/dist/worker/shiki-Bx2JpdqZ.js +697 -0
  244. package/dist/worker/shiki-Bx2JpdqZ.js.map +1 -0
  245. package/dist/worker/stream-tokenizer-YZ6M1qSx.js +424 -0
  246. package/dist/worker/stream-tokenizer-YZ6M1qSx.js.map +1 -0
  247. package/dist/worker/types.d.ts +5 -3
  248. package/dist/worker/types.d.ts.map +1 -1
  249. package/dist/worker/worker-portable.js +41 -13337
  250. package/dist/worker/worker-portable.js.map +1 -1
  251. package/dist/worker/worker.js +672 -349
  252. package/dist/worker/worker.js.map +1 -1
  253. package/dist/worker/workerMessage.d.ts +24 -0
  254. package/dist/worker/workerMessage.d.ts.map +1 -0
  255. package/dist/worker/workerMessage.js +0 -0
  256. package/package.json +33 -29
  257. package/dist/highlighter/themes/constants.d.ts +0 -5
  258. package/dist/highlighter/themes/constants.d.ts.map +0 -1
  259. package/dist/highlighter/themes/constants.js +0 -6
  260. package/dist/highlighter/themes/constants.js.map +0 -1
  261. package/dist/highlighter/themes/themeResolution.d.ts +0 -7
  262. package/dist/highlighter/themes/themeResolution.d.ts.map +0 -1
  263. package/dist/highlighter/themes/themeResolution.js +0 -21
  264. package/dist/highlighter/themes/themeResolution.js.map +0 -1
  265. package/dist/shiki-stream/tokenizer.d.ts +0 -23
  266. package/dist/shiki-stream/tokenizer.d.ts.map +0 -1
  267. package/dist/shiki-stream/tokenizer.js +0 -72
  268. package/dist/shiki-stream/tokenizer.js.map +0 -1
  269. package/dist/utils/createTransformerWithState.d.ts +0 -12
  270. package/dist/utils/createTransformerWithState.d.ts.map +0 -1
  271. package/dist/utils/createTransformerWithState.js +0 -89
  272. package/dist/utils/createTransformerWithState.js.map +0 -1
  273. package/dist/worker/wasm-B9ZqxnKj.js +0 -8
  274. package/dist/worker/wasm-B9ZqxnKj.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"renderFileWithHighlighter.d.ts","names":[],"sources":["../../src/utils/renderFileWithHighlighter.ts"],"mappings":";;iBAqBgB,0BACd,MAAM,cACN,aAAa,oBACX,OAAO,uBAAuB,uBAAuB,qBAErD,gBACA,cACA,YACA,UACC,4BACF"}
1
+ {"version":3,"file":"renderFileWithHighlighter.d.ts","names":[],"sources":["../../src/utils/renderFileWithHighlighter.ts"],"mappings":";;;iBAmBgB,0BACd,MAAM,cACN,aAAa,oBACX,OAAO,uBAAuB,uBAAuB,qBAErD,gBACA,aACA,cACA,YACA,UACC,4BACF"}
@@ -1,13 +1,12 @@
1
1
  import { linesFromFileContents } from "./computeFileOffsets.js";
2
2
  import { getFiletypeFromFileName } from "./getFiletypeFromFileName.js";
3
3
  import { appendItems } from "./appendItems.js";
4
- import { createTransformerWithState } from "./createTransformerWithState.js";
5
- import { formatCSSVariablePrefix } from "./formatCSSVariablePrefix.js";
6
4
  import { getHighlighterThemeStyles } from "./getHighlighterThemeStyles.js";
7
- import { getLineNodes } from "./getLineNodes.js";
5
+ import { getTokenOptions } from "./getTokenOptions.js";
6
+ import { renderTokenLines } from "./renderTokenLines.js";
8
7
  //#region src/utils/renderFileWithHighlighter.ts
9
8
  const DEFAULT_PLAIN_TEXT_OPTIONS = { forcePlainText: false };
10
- function renderFileWithHighlighter(file, highlighter, { theme, tokenizeMaxLineLength, useTokenTransformer }, { forcePlainText, startingLine, totalLines, lines } = DEFAULT_PLAIN_TEXT_OPTIONS) {
9
+ function renderFileWithHighlighter(file, highlighter, { theme, tokenizeMaxLineLength, useTokenTransformer }, { forcePlainText, lazyLineAST = false, startingLine, totalLines, lines } = DEFAULT_PLAIN_TEXT_OPTIONS) {
11
10
  if (forcePlainText) {
12
11
  startingLine ??= 0;
13
12
  totalLines ??= Infinity;
@@ -16,7 +15,7 @@ function renderFileWithHighlighter(file, highlighter, { theme, tokenizeMaxLineLe
16
15
  totalLines = Infinity;
17
16
  }
18
17
  const isWindowedHighlight = startingLine > 0 || totalLines < Infinity;
19
- const { state, transformers } = createTransformerWithState(useTokenTransformer);
18
+ const state = { lineInfo: [] };
20
19
  const lang = forcePlainText ? "text" : file.lang ?? getFiletypeFromFileName(file.name);
21
20
  const baseThemeType = typeof theme === "string" ? highlighter.getTheme(theme).type : void 0;
22
21
  const themeStyles = getHighlighterThemeStyles({
@@ -28,27 +27,12 @@ function renderFileWithHighlighter(file, highlighter, { theme, tokenizeMaxLineLe
28
27
  lineIndex: shikiLineNumber - 1 + startingLine,
29
28
  lineNumber: shikiLineNumber + startingLine
30
29
  });
31
- const hastConfig = (() => {
32
- if (typeof theme === "string") return {
33
- lang,
34
- theme,
35
- transformers,
36
- defaultColor: false,
37
- cssVariablePrefix: formatCSSVariablePrefix("token"),
38
- tokenizeMaxLineLength,
39
- tokenizeTimeLimit: 0
40
- };
41
- return {
42
- lang,
43
- themes: theme,
44
- transformers,
45
- defaultColor: false,
46
- cssVariablePrefix: formatCSSVariablePrefix("token"),
47
- tokenizeMaxLineLength,
48
- tokenizeTimeLimit: 0
49
- };
50
- })();
51
- const highlightedLines = getLineNodes(highlighter.codeToHast(normalizeHighlightLineEndings(isWindowedHighlight ? extractWindowedFileContent(lines ?? linesFromFileContents(file.contents), startingLine, totalLines) : file.contents), hastConfig));
30
+ const highlightedLines = renderTokenLines(highlighter.codeToTokens(normalizeHighlightLineEndings(isWindowedHighlight ? extractWindowedFileContent(lines ?? linesFromFileContents(file.contents), startingLine, totalLines) : file.contents), getTokenOptions(lang, theme, tokenizeMaxLineLength)).tokens, {
31
+ state,
32
+ useTokenTransformer,
33
+ lazyLineAST: lazyLineAST && !forcePlainText && !useTokenTransformer,
34
+ cacheHtmlStyles: highlighter.name === "highlights"
35
+ });
52
36
  const code = isWindowedHighlight ? new Array(startingLine) : highlightedLines;
53
37
  if (isWindowedHighlight) appendItems(code, highlightedLines);
54
38
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"renderFileWithHighlighter.js","names":[],"sources":["../../src/utils/renderFileWithHighlighter.ts"],"sourcesContent":["import type {\n CodeToHastOptions,\n DiffsHighlighter,\n DiffsThemeNames,\n FileContents,\n ForceFilePlainTextOptions,\n RenderFileOptions,\n ThemedFileResult,\n} from '../types';\nimport { appendItems } from './appendItems';\nimport { linesFromFileContents } from './computeFileOffsets';\nimport { createTransformerWithState } from './createTransformerWithState';\nimport { formatCSSVariablePrefix } from './formatCSSVariablePrefix';\nimport { getFiletypeFromFileName } from './getFiletypeFromFileName';\nimport { getHighlighterThemeStyles } from './getHighlighterThemeStyles';\nimport { getLineNodes } from './getLineNodes';\n\nconst DEFAULT_PLAIN_TEXT_OPTIONS: ForceFilePlainTextOptions = {\n forcePlainText: false,\n};\n\nexport function renderFileWithHighlighter(\n file: FileContents,\n highlighter: DiffsHighlighter,\n { theme, tokenizeMaxLineLength, useTokenTransformer }: RenderFileOptions,\n {\n forcePlainText,\n startingLine,\n totalLines,\n lines,\n }: ForceFilePlainTextOptions = DEFAULT_PLAIN_TEXT_OPTIONS\n): ThemedFileResult {\n if (forcePlainText) {\n startingLine ??= 0;\n totalLines ??= Infinity;\n } else {\n // If we aren't forcing plain text, then we intentionally do not support\n // ranges for highlighting as that could break the syntax highlighting, we\n // we override any values that may have been passed in. Maybe one day we\n // warn about this?\n startingLine = 0;\n totalLines = Infinity;\n }\n const isWindowedHighlight = startingLine > 0 || totalLines < Infinity;\n const { state, transformers } =\n createTransformerWithState(useTokenTransformer);\n const lang = forcePlainText\n ? 'text'\n : (file.lang ?? getFiletypeFromFileName(file.name));\n const baseThemeType =\n typeof theme === 'string' ? highlighter.getTheme(theme).type : undefined;\n const themeStyles = getHighlighterThemeStyles({\n theme,\n highlighter,\n });\n state.lineInfo = (shikiLineNumber: number) => ({\n type: 'context',\n lineIndex: shikiLineNumber - 1 + startingLine,\n lineNumber: shikiLineNumber + startingLine,\n });\n // tokenizeTimeLimit: 0 disables shiki's silent 500ms-per-line tokenization\n // abort. When it trips (slow devices, cold JS-regex-engine compile), the\n // rest of the line collapses to the enclosing scope's color — and since\n // dual-theme rendering tokenizes per theme, the first (dark) pass can smear\n // while the warm second (light) pass stays correct. Pathological content is\n // already guarded by tokenizeMaxLineLength, which renders long lines plain.\n const hastConfig: CodeToHastOptions<DiffsThemeNames> = (() => {\n if (typeof theme === 'string') {\n return {\n lang,\n theme,\n transformers,\n defaultColor: false,\n cssVariablePrefix: formatCSSVariablePrefix('token'),\n tokenizeMaxLineLength,\n tokenizeTimeLimit: 0,\n };\n }\n return {\n lang,\n themes: theme,\n transformers,\n defaultColor: false,\n cssVariablePrefix: formatCSSVariablePrefix('token'),\n tokenizeMaxLineLength,\n tokenizeTimeLimit: 0,\n };\n })();\n const highlightedLines = getLineNodes(\n highlighter.codeToHast(\n normalizeHighlightLineEndings(\n isWindowedHighlight\n ? extractWindowedFileContent(\n lines ?? linesFromFileContents(file.contents),\n startingLine,\n totalLines\n )\n : file.contents\n ),\n hastConfig\n )\n );\n\n // Create sparse array for windowed rendering\n const code = isWindowedHighlight ? new Array(startingLine) : highlightedLines;\n if (isWindowedHighlight) {\n appendItems(code, highlightedLines);\n }\n\n return { code, themeStyles, baseThemeType };\n}\n\n// Shiki does not treat a lone carriage return as a line break. Normalize only\n// the text sent to the highlighter so its output stays aligned with the file\n// model while the original document retains its line endings.\nfunction normalizeHighlightLineEndings(contents: string): string {\n return contents.replace(/\\r(?!\\n)/g, '\\n');\n}\n\nfunction extractWindowedFileContent(\n lines: string[],\n startingLine: number,\n totalLines: number\n): string {\n if (lines.length === 0) {\n return '';\n }\n const endLine = Math.min(startingLine + totalLines, lines.length);\n return lines.slice(startingLine, endLine).join('');\n}\n"],"mappings":";;;;;;;;AAiBA,MAAM,6BAAwD,EAC5D,gBAAgB,MAClB;AAEA,SAAgB,0BACd,MACA,aACA,EAAE,OAAO,uBAAuB,uBAChC,EACE,gBACA,cACA,YACA,UAC6B,4BACb;CAClB,IAAI,gBAAgB;EAClB,iBAAiB;EACjB,eAAe;CACjB,OAAO;EAKL,eAAe;EACf,aAAa;CACf;CACA,MAAM,sBAAsB,eAAe,KAAK,aAAa;CAC7D,MAAM,EAAE,OAAO,iBACb,2BAA2B,mBAAmB;CAChD,MAAM,OAAO,iBACT,SACC,KAAK,QAAQ,wBAAwB,KAAK,IAAI;CACnD,MAAM,gBACJ,OAAO,UAAU,WAAW,YAAY,SAAS,KAAK,CAAC,CAAC,OAAO,KAAA;CACjE,MAAM,cAAc,0BAA0B;EAC5C;EACA;CACF,CAAC;CACD,MAAM,YAAY,qBAA6B;EAC7C,MAAM;EACN,WAAW,kBAAkB,IAAI;EACjC,YAAY,kBAAkB;CAChC;CAOA,MAAM,oBAAwD;EAC5D,IAAI,OAAO,UAAU,UACnB,OAAO;GACL;GACA;GACA;GACA,cAAc;GACd,mBAAmB,wBAAwB,OAAO;GAClD;GACA,mBAAmB;EACrB;EAEF,OAAO;GACL;GACA,QAAQ;GACR;GACA,cAAc;GACd,mBAAmB,wBAAwB,OAAO;GAClD;GACA,mBAAmB;EACrB;CACF,EAAA,CAAG;CACH,MAAM,mBAAmB,aACvB,YAAY,WACV,8BACE,sBACI,2BACE,SAAS,sBAAsB,KAAK,QAAQ,GAC5C,cACA,UACF,IACA,KAAK,QACX,GACA,UACF,CACF;CAGA,MAAM,OAAO,sBAAsB,IAAI,MAAM,YAAY,IAAI;CAC7D,IAAI,qBACF,YAAY,MAAM,gBAAgB;CAGpC,OAAO;EAAE;EAAM;EAAa;CAAc;AAC5C;AAKA,SAAS,8BAA8B,UAA0B;CAC/D,OAAO,SAAS,QAAQ,aAAa,IAAI;AAC3C;AAEA,SAAS,2BACP,OACA,cACA,YACQ;CACR,IAAI,MAAM,WAAW,GACnB,OAAO;CAET,MAAM,UAAU,KAAK,IAAI,eAAe,YAAY,MAAM,MAAM;CAChE,OAAO,MAAM,MAAM,cAAc,OAAO,CAAC,CAAC,KAAK,EAAE;AACnD"}
1
+ {"version":3,"file":"renderFileWithHighlighter.js","names":[],"sources":["../../src/utils/renderFileWithHighlighter.ts"],"sourcesContent":["import type {\n DiffsHighlighter,\n FileContents,\n ForceFilePlainTextOptions,\n RenderFileOptions,\n SharedRenderState,\n ThemedFileResult,\n} from '../types';\nimport { appendItems } from './appendItems';\nimport { linesFromFileContents } from './computeFileOffsets';\nimport { getFiletypeFromFileName } from './getFiletypeFromFileName';\nimport { getHighlighterThemeStyles } from './getHighlighterThemeStyles';\nimport { getTokenOptions } from './getTokenOptions';\nimport { renderTokenLines } from './renderTokenLines';\n\nconst DEFAULT_PLAIN_TEXT_OPTIONS: ForceFilePlainTextOptions = {\n forcePlainText: false,\n};\n\nexport function renderFileWithHighlighter(\n file: FileContents,\n highlighter: DiffsHighlighter,\n { theme, tokenizeMaxLineLength, useTokenTransformer }: RenderFileOptions,\n {\n forcePlainText,\n lazyLineAST = false,\n startingLine,\n totalLines,\n lines,\n }: ForceFilePlainTextOptions = DEFAULT_PLAIN_TEXT_OPTIONS\n): ThemedFileResult {\n if (forcePlainText) {\n startingLine ??= 0;\n totalLines ??= Infinity;\n } else {\n // Tokenization must include preceding lines to preserve lexical state.\n startingLine = 0;\n totalLines = Infinity;\n }\n const isWindowedHighlight = startingLine > 0 || totalLines < Infinity;\n const state: SharedRenderState = { lineInfo: [] };\n const lang = forcePlainText\n ? 'text'\n : (file.lang ?? getFiletypeFromFileName(file.name));\n const baseThemeType =\n typeof theme === 'string' ? highlighter.getTheme(theme).type : undefined;\n const themeStyles = getHighlighterThemeStyles({\n theme,\n highlighter,\n });\n state.lineInfo = (shikiLineNumber: number) => ({\n type: 'context',\n lineIndex: shikiLineNumber - 1 + startingLine,\n lineNumber: shikiLineNumber + startingLine,\n });\n const highlightedLines = renderTokenLines(\n highlighter.codeToTokens(\n normalizeHighlightLineEndings(\n isWindowedHighlight\n ? extractWindowedFileContent(\n lines ?? linesFromFileContents(file.contents),\n startingLine,\n totalLines\n )\n : file.contents\n ),\n getTokenOptions(lang, theme, tokenizeMaxLineLength)\n ).tokens,\n {\n state,\n useTokenTransformer,\n lazyLineAST: lazyLineAST && !forcePlainText && !useTokenTransformer,\n cacheHtmlStyles: highlighter.name === 'highlights',\n }\n );\n\n // Create sparse array for windowed rendering\n const code = isWindowedHighlight ? new Array(startingLine) : highlightedLines;\n if (isWindowedHighlight) {\n appendItems(code, highlightedLines);\n }\n\n return { code, themeStyles, baseThemeType };\n}\n\n// Shiki does not treat a lone carriage return as a line break. Normalize only\n// the text sent to the highlighter so its output stays aligned with the file\n// model while the original document retains its line endings.\nfunction normalizeHighlightLineEndings(contents: string): string {\n return contents.replace(/\\r(?!\\n)/g, '\\n');\n}\n\nfunction extractWindowedFileContent(\n lines: string[],\n startingLine: number,\n totalLines: number\n): string {\n if (lines.length === 0) {\n return '';\n }\n const endLine = Math.min(startingLine + totalLines, lines.length);\n return lines.slice(startingLine, endLine).join('');\n}\n"],"mappings":";;;;;;;AAeA,MAAM,6BAAwD,EAC5D,gBAAgB,MAClB;AAEA,SAAgB,0BACd,MACA,aACA,EAAE,OAAO,uBAAuB,uBAChC,EACE,gBACA,cAAc,OACd,cACA,YACA,UAC6B,4BACb;CAClB,IAAI,gBAAgB;EAClB,iBAAiB;EACjB,eAAe;CACjB,OAAO;EAEL,eAAe;EACf,aAAa;CACf;CACA,MAAM,sBAAsB,eAAe,KAAK,aAAa;CAC7D,MAAM,QAA2B,EAAE,UAAU,CAAC,EAAE;CAChD,MAAM,OAAO,iBACT,SACC,KAAK,QAAQ,wBAAwB,KAAK,IAAI;CACnD,MAAM,gBACJ,OAAO,UAAU,WAAW,YAAY,SAAS,KAAK,CAAC,CAAC,OAAO,KAAA;CACjE,MAAM,cAAc,0BAA0B;EAC5C;EACA;CACF,CAAC;CACD,MAAM,YAAY,qBAA6B;EAC7C,MAAM;EACN,WAAW,kBAAkB,IAAI;EACjC,YAAY,kBAAkB;CAChC;CACA,MAAM,mBAAmB,iBACvB,YAAY,aACV,8BACE,sBACI,2BACE,SAAS,sBAAsB,KAAK,QAAQ,GAC5C,cACA,UACF,IACA,KAAK,QACX,GACA,gBAAgB,MAAM,OAAO,qBAAqB,CACpD,CAAC,CAAC,QACF;EACE;EACA;EACA,aAAa,eAAe,CAAC,kBAAkB,CAAC;EAChD,iBAAiB,YAAY,SAAS;CACxC,CACF;CAGA,MAAM,OAAO,sBAAsB,IAAI,MAAM,YAAY,IAAI;CAC7D,IAAI,qBACF,YAAY,MAAM,gBAAgB;CAGpC,OAAO;EAAE;EAAM;EAAa;CAAc;AAC5C;AAKA,SAAS,8BAA8B,UAA0B;CAC/D,OAAO,SAAS,QAAQ,aAAa,IAAI;AAC3C;AAEA,SAAS,2BACP,OACA,cACA,YACQ;CACR,IAAI,MAAM,WAAW,GACnB,OAAO;CAET,MAAM,UAAU,KAAK,IAAI,eAAe,YAAY,MAAM,MAAM;CAChE,OAAO,MAAM,MAAM,cAAc,OAAO,CAAC,CAAC,KAAK,EAAE;AACnD"}
@@ -0,0 +1,17 @@
1
+ import { ElementContent } from "../node_modules/.pnpm/@types_hast@3.0.4/node_modules/@types/hast/index.js";
2
+ import { DecorationItem, ThemedToken } from "../highlighter/types.js";
3
+ import { SharedRenderState } from "../types.js";
4
+ //#region src/utils/renderTokenLines.d.ts
5
+ interface RenderTokenLinesOptions {
6
+ lazyLineAST?: boolean;
7
+ cacheHtmlStyles?: boolean;
8
+ state?: SharedRenderState;
9
+ useTokenTransformer?: boolean;
10
+ mergeWhitespaces?: 'never' | 'always';
11
+ decorations?: DecorationItem[];
12
+ lineOffsets?: number[];
13
+ }
14
+ declare function renderTokenLines(lines: ThemedToken[][], { state, lazyLineAST, cacheHtmlStyles, useTokenTransformer, mergeWhitespaces, decorations, lineOffsets }: RenderTokenLinesOptions): ElementContent[];
15
+ //#endregion
16
+ export { renderTokenLines };
17
+ //# sourceMappingURL=renderTokenLines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderTokenLines.d.ts","names":[],"sources":["../../src/utils/renderTokenLines.ts"],"mappings":";;;;UAQU;EACR;EACA;EACA,QAAQ;EACR;EACA;EACA,cAAc;EACd;;iBAsBc,iBACd,OAAO,mBAEL,OACA,aACA,iBACA,qBACA,kBACA,aACA,eACC,0BACF"}
@@ -0,0 +1,246 @@
1
+ import { processLine } from "./processLine.js";
2
+ import { setDeferredArrayItem } from "./setDeferredArrayItem.js";
3
+ import { tokenStyle } from "./tokenStyle.js";
4
+ import { wrapTokenFragments } from "./wrapTokenFragments.js";
5
+ //#region src/utils/renderTokenLines.ts
6
+ function renderTokenLines(lines, { state, lazyLineAST = false, cacheHtmlStyles = false, useTokenTransformer = false, mergeWhitespaces = "always", decorations = [], lineOffsets = [] }) {
7
+ let decorationsByLine;
8
+ for (const decoration of decorations) {
9
+ const byLine = decorationsByLine ??= /* @__PURE__ */ new Map();
10
+ const normalized = {
11
+ ...decoration,
12
+ start: getDecorationPosition(decoration.start, lineOffsets),
13
+ end: getDecorationPosition(decoration.end, lineOffsets)
14
+ };
15
+ const lastLine = Math.min(normalized.end.line, lines.length - 1);
16
+ for (let line = normalized.start.line; line <= lastLine; line++) {
17
+ let spans = byLine.get(line);
18
+ if (spans == null) byLine.set(line, spans = []);
19
+ spans.push(normalized);
20
+ }
21
+ }
22
+ const renderLine = (tokens, lineIndex) => {
23
+ let normalized;
24
+ if (useTokenTransformer || mergeWhitespaces !== "never") {
25
+ let pendingWhitespace = "";
26
+ let whitespaceOffset = 0;
27
+ for (let i = 0; i < tokens.length; i++) {
28
+ let token = tokens[i];
29
+ if (useTokenTransformer) {
30
+ const content = token.content.trim();
31
+ if (content !== "" && content !== token.content) {
32
+ normalized ??= tokens.slice(0, i);
33
+ const start = token.content.indexOf(content);
34
+ if (start > 0) normalized.push({
35
+ content: token.content.slice(0, start),
36
+ offset: token.offset
37
+ });
38
+ normalized.push({
39
+ ...token,
40
+ content,
41
+ offset: token.offset + start
42
+ });
43
+ const end = start + content.length;
44
+ if (end < token.content.length) normalized.push({
45
+ content: token.content.slice(end),
46
+ offset: token.offset + end
47
+ });
48
+ continue;
49
+ }
50
+ } else {
51
+ const decoratedWhitespace = ((token.fontStyle ?? 0) & 12) !== 0;
52
+ if (!decoratedWhitespace && /^\s+$/.test(token.content) && i < tokens.length - 1) {
53
+ normalized ??= tokens.slice(0, i);
54
+ if (pendingWhitespace === "") whitespaceOffset = token.offset;
55
+ pendingWhitespace += token.content;
56
+ continue;
57
+ }
58
+ if (pendingWhitespace !== "" && normalized != null) {
59
+ if (decoratedWhitespace) normalized.push({
60
+ content: pendingWhitespace,
61
+ offset: whitespaceOffset
62
+ });
63
+ else token = {
64
+ ...token,
65
+ content: pendingWhitespace + token.content,
66
+ offset: whitespaceOffset
67
+ };
68
+ pendingWhitespace = "";
69
+ }
70
+ }
71
+ normalized?.push(token);
72
+ }
73
+ }
74
+ normalized ??= tokens;
75
+ const line = {
76
+ type: "element",
77
+ tagName: state == null ? "span" : "div",
78
+ properties: state == null ? { class: "line" } : {},
79
+ children: []
80
+ };
81
+ const spans = decorationsByLine?.get(lineIndex);
82
+ const column = spans == null ? appendTokens(line, normalized, useTokenTransformer, cacheHtmlStyles) : appendDecoratedTokens(line, normalized, spans, lineIndex, useTokenTransformer, cacheHtmlStyles);
83
+ if (useTokenTransformer && column === 0) line.children.push({
84
+ type: "element",
85
+ tagName: "br",
86
+ properties: {},
87
+ children: []
88
+ });
89
+ if (useTokenTransformer && spans != null) wrapTokenFragments(line);
90
+ return state == null ? line : processLine(line, lineIndex + 1, state);
91
+ };
92
+ if (!lazyLineAST) return lines.map(renderLine);
93
+ const rows = new Array(lines.length);
94
+ for (let index = 0; index < lines.length; index++) {
95
+ const tokens = lines[index];
96
+ setDeferredArrayItem(rows, index, () => renderLine(tokens, index));
97
+ }
98
+ return rows;
99
+ }
100
+ function appendTokens(line, tokens, useTokenTransformer, cacheHtmlStyles) {
101
+ let column = 0;
102
+ for (const token of tokens) {
103
+ if (token.content === "") continue;
104
+ line.children.push(createTokenSpan(token, tokenStyle(token, cacheHtmlStyles), token.content, column, useTokenTransformer));
105
+ column += token.content.length;
106
+ }
107
+ return column;
108
+ }
109
+ function appendDecoratedTokens(line, tokens, spans, lineIndex, useTokenTransformer, cacheHtmlStyles) {
110
+ if (spans.length > 1) spans.sort((a, b) => {
111
+ if (a.start.line !== b.start.line) return a.start.line - b.start.line;
112
+ if (a.start.character !== b.start.character) return a.start.character - b.start.character;
113
+ if (a.end.line !== b.end.line) return b.end.line - a.end.line;
114
+ return b.end.character - a.end.character;
115
+ });
116
+ const lineLength = tokens.reduce((length, token) => length + token.content.length, 0);
117
+ const boundaries = [];
118
+ for (let order = 0; order < spans.length; order++) {
119
+ const decoration = spans[order];
120
+ const range = {
121
+ decoration,
122
+ order,
123
+ from: decoration.start.line === lineIndex ? decoration.start.character : 0,
124
+ to: decoration.end.line === lineIndex ? decoration.end.character : lineLength
125
+ };
126
+ boundaries.push({
127
+ position: Math.max(0, Math.min(range.from, lineLength)),
128
+ range,
129
+ start: true
130
+ }, {
131
+ position: Math.max(0, Math.min(range.to, lineLength)),
132
+ range,
133
+ start: false
134
+ });
135
+ }
136
+ boundaries.sort((a, b) => a.position - b.position);
137
+ const active = [];
138
+ const decorationStack = [];
139
+ let boundaryIndex = 0;
140
+ const updateActive = (range, add) => {
141
+ let low = 0;
142
+ let high = active.length;
143
+ while (low < high) {
144
+ const middle = low + high >>> 1;
145
+ if (active[middle].order < range.order) low = middle + 1;
146
+ else high = middle;
147
+ }
148
+ if (add) active.splice(low, 0, range);
149
+ else if (active[low] === range) active.splice(low, 1);
150
+ };
151
+ const getParent = () => {
152
+ let parent = line;
153
+ let depth = 0;
154
+ for (const range of active) {
155
+ if (decorationStack[depth]?.range !== range) {
156
+ decorationStack.length = depth;
157
+ const wrapper = {
158
+ type: "element",
159
+ tagName: "span",
160
+ properties: { ...range.decoration.properties },
161
+ children: []
162
+ };
163
+ parent.children.push(wrapper);
164
+ decorationStack.push({
165
+ range,
166
+ node: wrapper
167
+ });
168
+ }
169
+ parent = decorationStack[depth++].node;
170
+ }
171
+ decorationStack.length = depth;
172
+ return parent;
173
+ };
174
+ let parent = line;
175
+ const advanceBoundary = (position) => {
176
+ const first = boundaryIndex;
177
+ while (boundaries[boundaryIndex]?.position === position) boundaryIndex++;
178
+ let hasMarker = false;
179
+ for (let i = first; i < boundaryIndex; i++) {
180
+ const { range, start } = boundaries[i];
181
+ if (!start && range.from !== range.to && position < lineLength) updateActive(range, false);
182
+ }
183
+ for (let i = first; i < boundaryIndex; i++) {
184
+ const { range, start } = boundaries[i];
185
+ if (start && range.from <= position && range.to >= position && (range.to > position || range.from === position || position === lineLength)) {
186
+ updateActive(range, true);
187
+ if (range.from === range.to) hasMarker = true;
188
+ }
189
+ }
190
+ if (hasMarker) {
191
+ getParent();
192
+ for (let i = first; i < boundaryIndex; i++) {
193
+ const { range, start } = boundaries[i];
194
+ if (start && range.from === range.to) updateActive(range, false);
195
+ }
196
+ }
197
+ if (position < lineLength) parent = getParent();
198
+ };
199
+ let column = 0;
200
+ for (const token of tokens) {
201
+ if (token.content === "") continue;
202
+ const start = column;
203
+ const end = start + token.content.length;
204
+ const style = tokenStyle(token, cacheHtmlStyles);
205
+ while (column < end) {
206
+ if (boundaries[boundaryIndex]?.position === column) advanceBoundary(column);
207
+ const to = Math.min(end, boundaries[boundaryIndex]?.position ?? end);
208
+ parent.children.push(createTokenSpan(token, style, column === start && to === end ? token.content : token.content.slice(column - start, to - start), start, useTokenTransformer));
209
+ column = to;
210
+ }
211
+ }
212
+ if (boundaries[boundaryIndex]?.position === column) advanceBoundary(column);
213
+ return column;
214
+ }
215
+ function createTokenSpan(token, style, text, start, useTokenTransformer) {
216
+ const properties = token.htmlAttrs != null ? { ...token.htmlAttrs } : {};
217
+ if (style !== "") properties.style = style;
218
+ if (useTokenTransformer) properties["data-char"] = start;
219
+ return {
220
+ type: "element",
221
+ tagName: "span",
222
+ properties,
223
+ children: [{
224
+ type: "text",
225
+ value: text
226
+ }]
227
+ };
228
+ }
229
+ function getDecorationPosition(position, lineOffsets) {
230
+ if (typeof position !== "number") return position;
231
+ let low = 0;
232
+ let high = lineOffsets.length;
233
+ while (low + 1 < high) {
234
+ const middle = low + high >>> 1;
235
+ if (lineOffsets[middle] <= position) low = middle;
236
+ else high = middle;
237
+ }
238
+ return {
239
+ line: low,
240
+ character: position - (lineOffsets[low] ?? 0)
241
+ };
242
+ }
243
+ //#endregion
244
+ export { renderTokenLines };
245
+
246
+ //# sourceMappingURL=renderTokenLines.js.map
@@ -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\ninterface RenderTokenLinesOptions {\n lazyLineAST?: boolean;\n cacheHtmlStyles?: boolean;\n state?: SharedRenderState;\n useTokenTransformer?: boolean;\n mergeWhitespaces?: 'never' | 'always';\n decorations?: DecorationItem[];\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\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"}
@@ -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,7 @@
1
+ import { ThemedToken } from "../highlighter/types.js";
2
+ import "../types.js";
3
+ //#region src/utils/tokenStyle.d.ts
4
+ declare function tokenStyle(token: ThemedToken, cacheHtmlStyle: boolean): string;
5
+ //#endregion
6
+ export { tokenStyle };
7
+ //# sourceMappingURL=tokenStyle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenStyle.d.ts","names":[],"sources":["../../src/utils/tokenStyle.ts"],"mappings":";;;iBAMgB,WACd,OAAO,aACP"}
@@ -0,0 +1,28 @@
1
+ //#region src/utils/tokenStyle.ts
2
+ const htmlStyleCache = /* @__PURE__ */ new WeakMap();
3
+ function tokenStyle(token, cacheHtmlStyle) {
4
+ const { htmlStyle } = token;
5
+ if (htmlStyle != null) {
6
+ let style = cacheHtmlStyle ? htmlStyleCache.get(htmlStyle) : void 0;
7
+ if (style == null) {
8
+ style = "";
9
+ for (const name in htmlStyle) style += `${style === "" ? "" : ";"}${name}:${htmlStyle[name]}`;
10
+ if (cacheHtmlStyle) htmlStyleCache.set(htmlStyle, style);
11
+ }
12
+ return style;
13
+ }
14
+ let style = token.color != null ? `color:${token.color}` : "";
15
+ if (token.bgColor != null) style += `;background-color:${token.bgColor}`;
16
+ if (token.fontStyle != null) {
17
+ if ((token.fontStyle & 1) !== 0) style += ";font-style:italic";
18
+ if ((token.fontStyle & 2) !== 0) style += ";font-weight:bold";
19
+ const underline = (token.fontStyle & 4) !== 0;
20
+ const strikethrough = (token.fontStyle & 8) !== 0;
21
+ if (underline || strikethrough) style += `;text-decoration:${underline ? "underline" : ""}${underline && strikethrough ? " " : ""}${strikethrough ? "line-through" : ""}`;
22
+ }
23
+ return style.replace(/^;/, "");
24
+ }
25
+ //#endregion
26
+ export { tokenStyle };
27
+
28
+ //# 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\nexport function tokenStyle(\n token: ThemedToken,\n cacheHtmlStyle: boolean\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;AAEnE,SAAgB,WACd,OACA,gBACQ;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,8 @@
1
+ import { CodeToHtmlOptions, TokensResult } from "../highlighter/types.js";
2
+ import "../types.js";
3
+ //#region src/utils/tokensToHtml.d.ts
4
+ /** Serialize highlighted tokens without loading a backend's HTML renderer. */
5
+ declare function tokensToHtml(source: string, result: TokensResult, options: CodeToHtmlOptions, cacheHtmlStyles: boolean): string;
6
+ //#endregion
7
+ export { tokensToHtml };
8
+ //# sourceMappingURL=tokensToHtml.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokensToHtml.d.ts","names":[],"sources":["../../src/utils/tokensToHtml.ts"],"mappings":";;;;iBAOgB,aACd,gBACA,QAAQ,cACR,SAAS,mBACT"}
@@ -0,0 +1,45 @@
1
+ import { hastToHtml } from "./hastToHtml.js";
2
+ import { renderTokenLines } from "./renderTokenLines.js";
3
+ //#region src/utils/tokensToHtml.ts
4
+ /** Serialize highlighted tokens without loading a backend's HTML renderer. */
5
+ function tokensToHtml(source, result, options, cacheHtmlStyles) {
6
+ const lineOffsets = [0];
7
+ 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);
8
+ const code = {
9
+ type: "element",
10
+ tagName: "code",
11
+ properties: {},
12
+ children: []
13
+ };
14
+ const lines = renderTokenLines(result.tokens, {
15
+ decorations: options.decorations,
16
+ mergeWhitespaces: options.mergeWhitespaces,
17
+ lineOffsets,
18
+ cacheHtmlStyles
19
+ });
20
+ for (let i = 0; i < lines.length; i++) {
21
+ if (i > 0) code.children.push({
22
+ type: "text",
23
+ value: "\n"
24
+ });
25
+ code.children.push(lines[i]);
26
+ }
27
+ const root = {
28
+ type: "root",
29
+ children: [{
30
+ type: "element",
31
+ tagName: "pre",
32
+ properties: {
33
+ class: "diffs",
34
+ style: result.rootStyle === false ? void 0 : result.rootStyle ?? [result.fg != null ? `color:${result.fg}` : "", result.bg != null ? `background-color:${result.bg}` : ""].filter(Boolean).join(";"),
35
+ tabIndex: 0
36
+ },
37
+ children: [code]
38
+ }]
39
+ };
40
+ return hastToHtml(root);
41
+ }
42
+ //#endregion
43
+ export { tokensToHtml };
44
+
45
+ //# 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/** Serialize highlighted tokens without loading a backend's HTML renderer. */\nexport function tokensToHtml(\n source: string,\n result: TokensResult,\n options: CodeToHtmlOptions,\n cacheHtmlStyles: boolean\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":";;;;AAOA,SAAgB,aACd,QACA,QACA,SACA,iBACQ;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"}