@astryxdesign/core 0.6.2 → 0.6.3-canary.039a67e

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 (621) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/dist/Avatar/Avatar.d.ts.map +1 -1
  3. package/dist/Avatar/Avatar.js +33 -12
  4. package/dist/BottomSheet/BottomSheet.d.ts +1 -1
  5. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  6. package/dist/BottomSheet/BottomSheet.js +3 -1
  7. package/dist/BottomSheet/BottomSheetPanel.d.ts +7 -5
  8. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  9. package/dist/BottomSheet/BottomSheetPanel.js +56 -19
  10. package/dist/Button/Button.d.ts.map +1 -1
  11. package/dist/Button/Button.js +13 -28
  12. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  13. package/dist/Chat/ChatComposer.js +10 -5
  14. package/dist/Chat/ChatComposerDrawer.d.ts +19 -5
  15. package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
  16. package/dist/Chat/ChatComposerDrawer.js +48 -23
  17. package/dist/Chat/ChatComposerInput.d.ts +11 -3
  18. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  19. package/dist/Chat/ChatComposerInput.js +63 -16
  20. package/dist/Chat/ChatDictationButton.d.ts +3 -2
  21. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  22. package/dist/Chat/ChatDictationButton.js +6 -4
  23. package/dist/Chat/ChatLayout.d.ts +19 -0
  24. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  25. package/dist/Chat/ChatLayout.js +19 -0
  26. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  27. package/dist/Chat/ChatLayoutScrollButton.js +44 -34
  28. package/dist/Chat/ChatMessageBubble.d.ts +2 -0
  29. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  30. package/dist/Chat/ChatMessageBubble.js +5 -3
  31. package/dist/Chat/ChatMessageList.d.ts +2 -1
  32. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  33. package/dist/Chat/ChatMessageList.js +4 -3
  34. package/dist/Chat/ChatMessageMetadata.d.ts +5 -4
  35. package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
  36. package/dist/Chat/ChatMessageMetadata.js +12 -9
  37. package/dist/Chat/ChatSendButton.d.ts +2 -1
  38. package/dist/Chat/ChatSendButton.d.ts.map +1 -1
  39. package/dist/Chat/ChatSendButton.js +6 -4
  40. package/dist/Chat/ChatSystemMessage.d.ts +3 -3
  41. package/dist/Chat/ChatSystemMessage.d.ts.map +1 -1
  42. package/dist/Chat/ChatSystemMessage.js +2 -2
  43. package/dist/Chat/ChatTokenizedText.d.ts +6 -6
  44. package/dist/Chat/ChatTokenizedText.js +10 -6
  45. package/dist/Chat/ChatToolCalls.d.ts +7 -9
  46. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  47. package/dist/Chat/ChatToolCalls.js +43 -26
  48. package/dist/Chat/index.d.ts +1 -1
  49. package/dist/Chat/index.d.ts.map +1 -1
  50. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  51. package/dist/CheckboxInput/CheckboxInput.js +12 -2
  52. package/dist/Citation/Citation.d.ts +1 -1
  53. package/dist/Citation/Citation.d.ts.map +1 -1
  54. package/dist/Citation/Citation.js +3 -2
  55. package/dist/CodeBlock/highlightRanges.d.ts.map +1 -1
  56. package/dist/CodeBlock/highlightRanges.js +14 -3
  57. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  58. package/dist/Collapsible/Collapsible.js +6 -1
  59. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  60. package/dist/CommandPalette/CommandPaletteInput.js +1 -1
  61. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  62. package/dist/ComplexSelector/ComplexSelector.js +1 -1
  63. package/dist/DateInput/DateInput.d.ts +25 -5
  64. package/dist/DateInput/DateInput.d.ts.map +1 -1
  65. package/dist/DateInput/DateInput.js +29 -17
  66. package/dist/DateInput/NativeDateField.d.ts.map +1 -1
  67. package/dist/DateInput/NativeDateField.js +16 -16
  68. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  69. package/dist/DateInput/TouchDateField.js +2 -2
  70. package/dist/DateInput/index.d.ts +1 -1
  71. package/dist/DateInput/index.d.ts.map +1 -1
  72. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  73. package/dist/DateRangeInput/DateRangeInput.js +4 -4
  74. package/dist/DateTimeInput/DateTimeInput.d.ts +32 -15
  75. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  76. package/dist/DateTimeInput/DateTimeInput.js +55 -30
  77. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  78. package/dist/DateTimeInput/TouchDateTimeField.js +4 -4
  79. package/dist/DateTimeInput/index.d.ts +1 -1
  80. package/dist/DateTimeInput/index.d.ts.map +1 -1
  81. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +9 -3
  82. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -1
  83. package/dist/DateTimeInput/nativePickerSegmentStyles.js +3 -3
  84. package/dist/Dialog/DialogHeader.d.ts +8 -1
  85. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  86. package/dist/Dialog/DialogHeader.js +13 -4
  87. package/dist/Field/InputClearButton.d.ts +4 -2
  88. package/dist/Field/InputClearButton.d.ts.map +1 -1
  89. package/dist/Field/InputClearButton.js +4 -2
  90. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  91. package/dist/Field/PanelSearchInput.js +1 -1
  92. package/dist/FileInput/FileInput.d.ts.map +1 -1
  93. package/dist/FileInput/FileInput.js +7 -7
  94. package/dist/Icon/Icon.d.ts +6 -31
  95. package/dist/Icon/Icon.d.ts.map +1 -1
  96. package/dist/Icon/Icon.js +8 -71
  97. package/dist/Icon/IconDefaultSizeContext.d.ts +4 -0
  98. package/dist/Icon/IconDefaultSizeContext.d.ts.map +1 -0
  99. package/dist/Icon/IconDefaultSizeContext.js +18 -0
  100. package/dist/Icon/IconSize.stylex.d.ts +65 -0
  101. package/dist/Icon/IconSize.stylex.d.ts.map +1 -0
  102. package/dist/Icon/IconSize.stylex.js +75 -0
  103. package/dist/Item/Item.d.ts +1 -1
  104. package/dist/Item/Item.d.ts.map +1 -1
  105. package/dist/Item/Item.js +4 -3
  106. package/dist/Kbd/Kbd.d.ts +5 -3
  107. package/dist/Kbd/Kbd.d.ts.map +1 -1
  108. package/dist/Kbd/Kbd.js +36 -42
  109. package/dist/Link/Link.d.ts.map +1 -1
  110. package/dist/Link/Link.js +6 -2
  111. package/dist/Link/useLinkComponent.d.ts +5 -15
  112. package/dist/Link/useLinkComponent.d.ts.map +1 -1
  113. package/dist/Link/useLinkComponent.js +34 -51
  114. package/dist/List/List.d.ts +19 -1
  115. package/dist/List/List.d.ts.map +1 -1
  116. package/dist/List/List.js +9 -2
  117. package/dist/List/ListContext.d.ts +1 -0
  118. package/dist/List/ListContext.d.ts.map +1 -1
  119. package/dist/List/ListContext.js +2 -1
  120. package/dist/List/ListItem.d.ts +1 -1
  121. package/dist/List/ListItem.d.ts.map +1 -1
  122. package/dist/List/ListItem.js +9 -2
  123. package/dist/Markdown/Markdown.d.ts +8 -2
  124. package/dist/Markdown/Markdown.d.ts.map +1 -1
  125. package/dist/Markdown/Markdown.fr23.bench.d.ts +2 -0
  126. package/dist/Markdown/Markdown.fr23.bench.d.ts.map +1 -0
  127. package/dist/Markdown/Markdown.fr23.bench.js +150 -0
  128. package/dist/Markdown/Markdown.fr23.sampling.d.ts +2 -0
  129. package/dist/Markdown/Markdown.fr23.sampling.d.ts.map +1 -0
  130. package/dist/Markdown/Markdown.fr23.sampling.js +43 -0
  131. package/dist/Markdown/Markdown.js +262 -109
  132. package/dist/Markdown/ast.d.ts +162 -0
  133. package/dist/Markdown/ast.d.ts.map +1 -0
  134. package/dist/Markdown/ast.js +74 -0
  135. package/dist/Markdown/index.d.ts +5 -3
  136. package/dist/Markdown/index.d.ts.map +1 -1
  137. package/dist/Markdown/index.js +3 -2
  138. package/dist/Markdown/parser/index.d.ts +10 -0
  139. package/dist/Markdown/parser/index.d.ts.map +1 -0
  140. package/dist/Markdown/parser/index.js +10 -0
  141. package/dist/Markdown/parser.d.ts +126 -58
  142. package/dist/Markdown/parser.d.ts.map +1 -1
  143. package/dist/Markdown/parser.js +726 -177
  144. package/dist/Markdown/plugins/frontmatter.d.ts +32 -0
  145. package/dist/Markdown/plugins/frontmatter.d.ts.map +1 -0
  146. package/dist/Markdown/plugins/frontmatter.js +132 -0
  147. package/dist/Markdown/plugins/index.d.ts +17 -0
  148. package/dist/Markdown/plugins/index.d.ts.map +1 -0
  149. package/dist/Markdown/plugins/index.js +14 -0
  150. package/dist/Markdown/plugins/protocol.d.ts +191 -0
  151. package/dist/Markdown/plugins/protocol.d.ts.map +1 -0
  152. package/dist/Markdown/plugins/protocol.js +957 -0
  153. package/dist/Markdown/plugins/semanticFence.d.ts +36 -0
  154. package/dist/Markdown/plugins/semanticFence.d.ts.map +1 -0
  155. package/dist/Markdown/plugins/semanticFence.js +213 -0
  156. package/dist/Markdown/plugins/softBreaks.d.ts +3 -0
  157. package/dist/Markdown/plugins/softBreaks.d.ts.map +1 -0
  158. package/dist/Markdown/plugins/softBreaks.js +172 -0
  159. package/dist/Markdown/plugins/sourceDecoration.d.ts +76 -0
  160. package/dist/Markdown/plugins/sourceDecoration.d.ts.map +1 -0
  161. package/dist/Markdown/plugins/sourceDecoration.js +393 -0
  162. package/dist/Markdown/plugins/textTransform.d.ts +30 -0
  163. package/dist/Markdown/plugins/textTransform.d.ts.map +1 -0
  164. package/dist/Markdown/plugins/textTransform.js +374 -0
  165. package/dist/Markdown/remark.d.ts +196 -0
  166. package/dist/Markdown/remark.d.ts.map +1 -0
  167. package/dist/Markdown/remark.js +1062 -0
  168. package/dist/Markdown/url.d.ts +6 -0
  169. package/dist/Markdown/url.d.ts.map +1 -0
  170. package/dist/Markdown/url.js +31 -0
  171. package/dist/Markdown/utils.d.ts +4 -2
  172. package/dist/Markdown/utils.d.ts.map +1 -1
  173. package/dist/Markdown/utils.js +2 -1
  174. package/dist/MetadataList/MetadataList.js +3 -3
  175. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  176. package/dist/NumberInput/NumberInput.js +4 -4
  177. package/dist/Outline/index.d.ts +1 -0
  178. package/dist/Outline/index.d.ts.map +1 -1
  179. package/dist/Outline/parseOutlineFromMarkdown.d.ts +7 -1
  180. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  181. package/dist/Outline/parseOutlineFromMarkdown.js +14 -8
  182. package/dist/Outline/useOutlineFromMarkdown.d.ts +3 -1
  183. package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
  184. package/dist/Outline/useOutlineFromMarkdown.js +8 -3
  185. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  186. package/dist/PowerSearch/PowerSearchEditPopover.js +46 -30
  187. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  188. package/dist/PowerSearch/PowerSearchValueEditor.js +5 -0
  189. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  190. package/dist/ProgressBar/ProgressBar.js +36 -31
  191. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  192. package/dist/RadioList/RadioListItem.js +13 -1
  193. package/dist/ScrollableArea/ScrollableArea.d.ts +1 -0
  194. package/dist/ScrollableArea/ScrollableArea.d.ts.map +1 -1
  195. package/dist/ScrollableArea/ScrollableArea.js +1 -0
  196. package/dist/SegmentedControl/SegmentedControl.d.ts +1 -1
  197. package/dist/SegmentedControl/SegmentedControl.d.ts.map +1 -1
  198. package/dist/SegmentedControl/SegmentedControl.js +1 -0
  199. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  200. package/dist/SegmentedControl/SegmentedControlItem.js +5 -5
  201. package/dist/Selector/Selector.d.ts +9 -7
  202. package/dist/Selector/Selector.d.ts.map +1 -1
  203. package/dist/Selector/Selector.js +16 -7
  204. package/dist/SideNav/SideNav.d.ts +2 -1
  205. package/dist/SideNav/SideNav.d.ts.map +1 -1
  206. package/dist/SideNav/SideNav.js +9 -3
  207. package/dist/Slider/Slider.d.ts.map +1 -1
  208. package/dist/Slider/Slider.js +28 -12
  209. package/dist/Spinner/Spinner.d.ts.map +1 -1
  210. package/dist/Spinner/Spinner.js +23 -7
  211. package/dist/Switch/Switch.d.ts.map +1 -1
  212. package/dist/Switch/Switch.js +11 -0
  213. package/dist/TabList/Tab.d.ts +1 -1
  214. package/dist/TabList/Tab.d.ts.map +1 -1
  215. package/dist/TabList/Tab.js +20 -7
  216. package/dist/Table/Table.d.ts +1 -0
  217. package/dist/Table/Table.d.ts.map +1 -1
  218. package/dist/Table/Table.js +29 -13
  219. package/dist/TextArea/TextArea.d.ts.map +1 -1
  220. package/dist/TextArea/TextArea.js +1 -1
  221. package/dist/TextInput/TextInput.d.ts.map +1 -1
  222. package/dist/TextInput/TextInput.js +2 -2
  223. package/dist/TimeInput/TimeInput.d.ts +30 -14
  224. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  225. package/dist/TimeInput/TimeInput.js +61 -13
  226. package/dist/TimeInput/TouchTimeField.d.ts +11 -0
  227. package/dist/TimeInput/TouchTimeField.d.ts.map +1 -0
  228. package/dist/TimeInput/TouchTimeField.js +417 -0
  229. package/dist/TimeInput/index.d.ts +1 -1
  230. package/dist/TimeInput/index.d.ts.map +1 -1
  231. package/dist/Timer/Timer.d.ts +49 -0
  232. package/dist/Timer/Timer.d.ts.map +1 -0
  233. package/dist/Timer/Timer.js +158 -0
  234. package/dist/Timer/index.d.ts +9 -0
  235. package/dist/Timer/index.d.ts.map +1 -0
  236. package/dist/Timer/index.js +10 -0
  237. package/dist/ToggleButton/ToggleButton.d.ts +9 -6
  238. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  239. package/dist/ToggleButton/ToggleButton.js +15 -27
  240. package/dist/TopNav/TopNavMenu.d.ts +1 -1
  241. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  242. package/dist/TopNav/TopNavMenu.js +3 -2
  243. package/dist/TreeList/TreeList.d.ts.map +1 -1
  244. package/dist/TreeList/TreeList.js +3 -0
  245. package/dist/TreeList/TreeListItem.d.ts +6 -1
  246. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  247. package/dist/TreeList/TreeListItem.js +12 -2
  248. package/dist/TreeList/TreeListTypes.d.ts +8 -1
  249. package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
  250. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  251. package/dist/Typeahead/BaseTypeahead.js +16 -7
  252. package/dist/astryx.css +27 -11
  253. package/dist/hooks/scrollKeyboardDelegation.d.ts +3 -0
  254. package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -0
  255. package/dist/hooks/scrollKeyboardDelegation.js +146 -0
  256. package/dist/hooks/useClickableContainer.d.ts +10 -1
  257. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  258. package/dist/hooks/useClickableContainer.js +15 -4
  259. package/dist/hooks/useScrollableArea.d.ts +6 -2
  260. package/dist/hooks/useScrollableArea.d.ts.map +1 -1
  261. package/dist/hooks/useScrollableArea.js +17 -5
  262. package/dist/index.d.ts +1 -0
  263. package/dist/index.d.ts.map +1 -1
  264. package/dist/index.js +3 -0
  265. package/dist/theme/declarationBoundary.d.ts +17 -0
  266. package/dist/theme/declarationBoundary.d.ts.map +1 -0
  267. package/dist/theme/declarationBoundary.js +343 -0
  268. package/dist/theme/defineTheme.d.ts +3 -0
  269. package/dist/theme/defineTheme.d.ts.map +1 -1
  270. package/dist/theme/defineTheme.js +4 -1
  271. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  272. package/dist/theme/derivedVarRegistry.js +4 -0
  273. package/dist/theme/generateThemeRules.d.ts +15 -7
  274. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  275. package/dist/theme/generateThemeRules.js +143 -35
  276. package/dist/theme/themeAdaptations.d.ts +5 -3
  277. package/dist/theme/themeAdaptations.d.ts.map +1 -1
  278. package/dist/theme/themeAdaptations.js +33 -5
  279. package/dist/utils/inputPresentation.d.ts +55 -0
  280. package/dist/utils/inputPresentation.d.ts.map +1 -0
  281. package/dist/utils/inputPresentation.js +108 -0
  282. package/dist/utils/interactionOverlay.stylex.d.ts +8 -0
  283. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  284. package/dist/utils/interactionOverlay.stylex.js +9 -0
  285. package/dist/utils/safeUrl.d.ts +11 -0
  286. package/dist/utils/safeUrl.d.ts.map +1 -0
  287. package/dist/utils/safeUrl.js +78 -0
  288. package/locales/af-ZA.json +530 -1
  289. package/locales/ar-SA.json +490 -1
  290. package/locales/ca-ES.json +514 -1
  291. package/locales/cs-CZ.json +498 -1
  292. package/locales/da-DK.json +522 -1
  293. package/locales/de-DE.json +522 -1
  294. package/locales/el-GR.json +498 -1
  295. package/locales/es-ES.json +510 -1
  296. package/locales/fi-FI.json +498 -1
  297. package/locales/fr-FR.json +534 -1
  298. package/locales/he-IL.json +498 -1
  299. package/locales/hu-HU.json +498 -1
  300. package/locales/it-IT.json +510 -1
  301. package/locales/ja-JP.json +490 -1
  302. package/locales/ko-KR.json +498 -1
  303. package/locales/nl-NL.json +534 -1
  304. package/locales/no-NO.json +510 -1
  305. package/locales/pl-PL.json +506 -1
  306. package/locales/pt-BR.json +506 -1
  307. package/locales/pt-PT.json +506 -1
  308. package/locales/ro-RO.json +506 -1
  309. package/locales/ru-RU.json +498 -1
  310. package/locales/sr-SP.json +498 -1
  311. package/locales/sv-SE.json +502 -1
  312. package/locales/tr-TR.json +498 -1
  313. package/locales/uk-UA.json +498 -1
  314. package/locales/vi-VN.json +502 -1
  315. package/locales/zh-CN.json +490 -1
  316. package/locales/zh-TW.json +490 -1
  317. package/package.json +24 -4
  318. package/src/Avatar/Avatar.doc.mjs +1 -1
  319. package/src/Avatar/Avatar.test.tsx +30 -0
  320. package/src/Avatar/Avatar.tsx +38 -14
  321. package/src/BottomSheet/BottomSheet.doc.mjs +8 -1
  322. package/src/BottomSheet/BottomSheet.spec.md +46 -20
  323. package/src/BottomSheet/BottomSheet.test.tsx +6 -3
  324. package/src/BottomSheet/BottomSheet.tsx +3 -1
  325. package/src/BottomSheet/BottomSheetKeyboard.test.tsx +195 -0
  326. package/src/BottomSheet/BottomSheetPanel.test.tsx +11 -1
  327. package/src/BottomSheet/BottomSheetPanel.tsx +49 -16
  328. package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +344 -0
  329. package/src/Button/Button.doc.mjs +5 -5
  330. package/src/Button/Button.tsx +15 -13
  331. package/src/Button/__tests__/Button.a11y.chromium.spec.ts +17 -1
  332. package/src/Button/__tests__/Button.a11y.known-failures.ts +0 -29
  333. package/src/Button/__tests__/Button.a11y.renders.tsx +9 -2
  334. package/src/Button/__tests__/Button.a11y.states.ts +9 -0
  335. package/src/Chat/ChatComposer.doc.mjs +14 -0
  336. package/src/Chat/ChatComposer.spec.md +230 -0
  337. package/src/Chat/ChatComposer.test.tsx +57 -0
  338. package/src/Chat/ChatComposer.tsx +21 -9
  339. package/src/Chat/ChatComposerDrawer.doc.mjs +63 -5
  340. package/src/Chat/ChatComposerDrawer.spec.md +267 -0
  341. package/src/Chat/ChatComposerDrawer.test.tsx +81 -12
  342. package/src/Chat/ChatComposerDrawer.tsx +38 -9
  343. package/src/Chat/ChatComposerInput.doc.mjs +114 -26
  344. package/src/Chat/ChatComposerInput.spec.md +185 -0
  345. package/src/Chat/ChatComposerInput.test.tsx +113 -3
  346. package/src/Chat/ChatComposerInput.tsx +78 -13
  347. package/src/Chat/ChatComposerTokenElement.spec.md +152 -0
  348. package/src/Chat/ChatComposerTokenElement.test.tsx +85 -0
  349. package/src/Chat/ChatDictationButton.doc.mjs +3 -3
  350. package/src/Chat/ChatDictationButton.spec.md +160 -0
  351. package/src/Chat/ChatDictationButton.test.tsx +92 -27
  352. package/src/Chat/ChatDictationButton.tsx +8 -6
  353. package/src/Chat/ChatLayout.doc.mjs +12 -4
  354. package/src/Chat/ChatLayout.spec.md +271 -0
  355. package/src/Chat/ChatLayout.test.tsx +28 -0
  356. package/src/Chat/ChatLayout.tsx +19 -0
  357. package/src/Chat/ChatLayoutScrollButton.spec.md +338 -0
  358. package/src/Chat/ChatLayoutScrollButton.test.tsx +31 -0
  359. package/src/Chat/ChatLayoutScrollButton.tsx +31 -14
  360. package/src/Chat/ChatMessageBubble.doc.mjs +28 -15
  361. package/src/Chat/ChatMessageBubble.spec.md +263 -0
  362. package/src/Chat/ChatMessageBubble.test.tsx +93 -0
  363. package/src/Chat/ChatMessageBubble.tsx +8 -3
  364. package/src/Chat/ChatMessageList.spec.md +222 -0
  365. package/src/Chat/ChatMessageList.test.tsx +64 -2
  366. package/src/Chat/ChatMessageList.tsx +4 -3
  367. package/src/Chat/ChatMessageMetadata.doc.mjs +57 -3
  368. package/src/Chat/ChatMessageMetadata.spec.md +220 -0
  369. package/src/Chat/ChatMessageMetadata.test.tsx +34 -0
  370. package/src/Chat/ChatMessageMetadata.tsx +13 -13
  371. package/src/Chat/ChatSendButton.doc.mjs +32 -0
  372. package/src/Chat/ChatSendButton.spec.md +227 -0
  373. package/src/Chat/ChatSendButton.test.tsx +128 -8
  374. package/src/Chat/ChatSendButton.tsx +6 -4
  375. package/src/Chat/ChatSystemMessage.doc.mjs +115 -12
  376. package/src/Chat/ChatSystemMessage.spec.md +225 -0
  377. package/src/Chat/ChatSystemMessage.test.tsx +112 -20
  378. package/src/Chat/ChatSystemMessage.tsx +4 -6
  379. package/src/Chat/ChatTokenizedText.doc.mjs +96 -9
  380. package/src/Chat/ChatTokenizedText.spec.md +190 -0
  381. package/src/Chat/ChatTokenizedText.test.tsx +60 -1
  382. package/src/Chat/ChatTokenizedText.tsx +14 -8
  383. package/src/Chat/ChatToolCalls.doc.mjs +4 -1
  384. package/src/Chat/ChatToolCalls.spec.md +194 -0
  385. package/src/Chat/ChatToolCalls.test.tsx +83 -0
  386. package/src/Chat/ChatToolCalls.tsx +46 -21
  387. package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +514 -0
  388. package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +740 -0
  389. package/src/Chat/__tests__/ChatMessageBubble.a11y.chromium.spec.ts +457 -0
  390. package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.test.ts +91 -0
  391. package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.ts +91 -0
  392. package/src/Chat/__tests__/ChatMessageList.a11y.chromium.spec.ts +456 -0
  393. package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +413 -0
  394. package/src/Chat/__tests__/ChatSendButton.a11y.chromium.spec.ts +1522 -0
  395. package/src/Chat/__tests__/ChatSystemMessage.a11y.chromium.spec.ts +1004 -0
  396. package/src/Chat/__tests__/ChatTokenizedText.a11y.chromium.spec.ts +573 -0
  397. package/src/Chat/index.ts +1 -0
  398. package/src/CheckboxInput/CheckboxInput.doc.mjs +11 -0
  399. package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
  400. package/src/CheckboxInput/CheckboxInput.tsx +21 -1
  401. package/src/Citation/Citation.doc.mjs +2 -2
  402. package/src/Citation/Citation.test.tsx +17 -0
  403. package/src/Citation/Citation.tsx +4 -2
  404. package/src/ClickableCard/ClickableCard.doc.mjs +2 -2
  405. package/src/ClickableCard/ClickableCard.test.tsx +102 -5
  406. package/src/CodeBlock/highlightRanges.test.ts +143 -1
  407. package/src/CodeBlock/highlightRanges.ts +15 -5
  408. package/src/Collapsible/Collapsible.doc.mjs +11 -0
  409. package/src/Collapsible/Collapsible.test.tsx +21 -0
  410. package/src/Collapsible/Collapsible.tsx +5 -0
  411. package/src/CommandPalette/CommandPaletteInput.tsx +6 -1
  412. package/src/ComplexSelector/ComplexSelector.tsx +6 -1
  413. package/src/DateInput/DateInput.doc.mjs +38 -9
  414. package/src/DateInput/DateInput.tsx +59 -17
  415. package/src/DateInput/NativeDateField.tsx +24 -8
  416. package/src/DateInput/Presentation.test.tsx +121 -0
  417. package/src/DateInput/TouchDateField.tsx +6 -2
  418. package/src/DateInput/index.ts +1 -0
  419. package/src/DateRangeInput/DateRangeInput.tsx +6 -1
  420. package/src/DateTimeInput/DateTimeInput.doc.mjs +28 -12
  421. package/src/DateTimeInput/DateTimeInput.tsx +93 -37
  422. package/src/DateTimeInput/Presentation.test.tsx +89 -0
  423. package/src/DateTimeInput/TouchDateTimeField.tsx +6 -1
  424. package/src/DateTimeInput/index.ts +1 -0
  425. package/src/DateTimeInput/nativePickerSegmentStyles.ts +24 -8
  426. package/src/Dialog/Dialog.doc.mjs +2 -0
  427. package/src/Dialog/DialogHeader.doc.mjs +22 -0
  428. package/src/Dialog/DialogHeader.test.tsx +167 -3
  429. package/src/Dialog/DialogHeader.tsx +37 -6
  430. package/src/Dialog/modules/DialogHeader.spec.md +101 -42
  431. package/src/DropdownMenu/DropdownMenu.test.tsx +5 -2
  432. package/src/Field/InputClearButton.test.tsx +17 -3
  433. package/src/Field/InputClearButton.tsx +5 -2
  434. package/src/Field/PanelSearchInput.tsx +5 -2
  435. package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +1 -1
  436. package/src/FileInput/FileInput.tsx +11 -2
  437. package/src/Icon/Icon.doc.mjs +7 -5
  438. package/src/Icon/Icon.spec.md +81 -40
  439. package/src/Icon/Icon.test.tsx +6 -3
  440. package/src/Icon/Icon.tsx +20 -68
  441. package/src/Icon/IconDefaultSizeContext.ts +23 -0
  442. package/src/Icon/IconSize.stylex.ts +70 -0
  443. package/src/IconButton/IconButton.doc.mjs +3 -3
  444. package/src/IconButton/IconButton.test.tsx +40 -0
  445. package/src/Item/Item.doc.mjs +6 -2
  446. package/src/Item/Item.tsx +9 -3
  447. package/src/Kbd/Kbd.doc.mjs +3 -3
  448. package/src/Kbd/Kbd.test.tsx +57 -1
  449. package/src/Kbd/Kbd.tsx +57 -37
  450. package/src/Layout/LayoutFooter.doc.mjs +17 -0
  451. package/src/Link/Link.doc.mjs +17 -4
  452. package/src/Link/Link.test.tsx +24 -0
  453. package/src/Link/Link.tsx +5 -0
  454. package/src/Link/LinkProvider.doc.mjs +2 -2
  455. package/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts +261 -0
  456. package/src/Link/useLinkComponent.test.tsx +333 -0
  457. package/src/Link/useLinkComponent.ts +29 -57
  458. package/src/List/List.doc.mjs +6 -0
  459. package/src/List/List.spec.md +200 -0
  460. package/src/List/List.test.tsx +117 -1
  461. package/src/List/List.tsx +22 -2
  462. package/src/List/ListContext.tsx +3 -1
  463. package/src/List/ListItem.doc.mjs +2 -2
  464. package/src/List/ListItem.source-build.test.mjs +41 -0
  465. package/src/List/ListItem.tsx +26 -2
  466. package/src/Markdown/Markdown.doc.mjs +300 -2
  467. package/src/Markdown/Markdown.fr23.bench.ts +174 -0
  468. package/src/Markdown/Markdown.fr23.perf.test.ts +249 -0
  469. package/src/Markdown/Markdown.fr23.sampling.ts +49 -0
  470. package/src/Markdown/Markdown.helpers.perf.test.ts +489 -0
  471. package/src/Markdown/Markdown.public.test.ts +130 -3
  472. package/src/Markdown/Markdown.renderBoundary.test.tsx +72 -0
  473. package/src/Markdown/Markdown.spec.md +210 -45
  474. package/src/Markdown/Markdown.test.tsx +87 -3
  475. package/src/Markdown/Markdown.tsx +414 -135
  476. package/src/Markdown/ast.test.ts +307 -0
  477. package/src/Markdown/ast.ts +337 -0
  478. package/src/Markdown/incremental.test.ts +43 -0
  479. package/src/Markdown/index.ts +37 -1
  480. package/src/Markdown/modules/remark.spec.md +269 -0
  481. package/src/Markdown/modules/softBreaks.spec.md +137 -0
  482. package/src/Markdown/parser/index.ts +64 -0
  483. package/src/Markdown/parser.public.test.ts +103 -0
  484. package/src/Markdown/parser.test.ts +38 -6
  485. package/src/Markdown/parser.ts +1221 -242
  486. package/src/Markdown/plugins/frontmatter.test.tsx +125 -0
  487. package/src/Markdown/plugins/frontmatter.ts +198 -0
  488. package/src/Markdown/plugins/index.ts +54 -0
  489. package/src/Markdown/plugins/protocol.test.tsx +1022 -0
  490. package/src/Markdown/plugins/protocol.ts +1618 -0
  491. package/src/Markdown/plugins/semanticFence.test.tsx +546 -0
  492. package/src/Markdown/plugins/semanticFence.ts +424 -0
  493. package/src/Markdown/plugins/softBreaks.test.tsx +172 -0
  494. package/src/Markdown/plugins/softBreaks.ts +169 -0
  495. package/src/Markdown/plugins/sourceDecoration.test.tsx +799 -0
  496. package/src/Markdown/plugins/sourceDecoration.ts +539 -0
  497. package/src/Markdown/plugins/textTransform.test.ts +467 -0
  498. package/src/Markdown/plugins/textTransform.ts +554 -0
  499. package/src/Markdown/remark.test.tsx +1877 -0
  500. package/src/Markdown/remark.ts +1574 -0
  501. package/src/Markdown/url.ts +36 -0
  502. package/src/Markdown/utils.ts +13 -1
  503. package/src/MetadataList/MetadataList.test.tsx +4 -2
  504. package/src/MetadataList/MetadataList.tsx +3 -3
  505. package/src/MultiSelector/MultiSelector.test.tsx +1 -35
  506. package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +128 -0
  507. package/src/NumberInput/NumberInput.tsx +6 -1
  508. package/src/Outline/Outline.doc.mjs +7 -5
  509. package/src/Outline/Outline.spec.md +1 -1
  510. package/src/Outline/index.ts +1 -0
  511. package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +142 -0
  512. package/src/Outline/parseOutlineFromMarkdown.ts +40 -10
  513. package/src/Outline/useOutlineFromMarkdown.ts +15 -3
  514. package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
  515. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +150 -1
  516. package/src/PowerSearch/PowerSearchEditPopover.tsx +51 -28
  517. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +51 -0
  518. package/src/PowerSearch/PowerSearchValueEditor.tsx +4 -0
  519. package/src/ProgressBar/ProgressBar.test.tsx +29 -11
  520. package/src/ProgressBar/ProgressBar.tsx +59 -72
  521. package/src/RadioList/RadioList.doc.mjs +11 -0
  522. package/src/RadioList/RadioList.test.tsx +32 -0
  523. package/src/RadioList/RadioListItem.tsx +25 -1
  524. package/src/ScrollableArea/ScrollableArea.tsx +1 -0
  525. package/src/ScrollableArea/modules/useScrollableArea.spec.md +50 -22
  526. package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
  527. package/src/SegmentedControl/SegmentedControl.test.tsx +61 -0
  528. package/src/SegmentedControl/SegmentedControl.tsx +2 -1
  529. package/src/SegmentedControl/SegmentedControlItem.tsx +6 -9
  530. package/src/Selector/Selector.doc.mjs +3 -3
  531. package/src/Selector/Selector.spec.md +51 -49
  532. package/src/Selector/Selector.test.tsx +61 -55
  533. package/src/Selector/Selector.tsx +34 -15
  534. package/src/Selector/__tests__/Listbox.a11y.chromium.spec.ts +130 -0
  535. package/src/Selector/__tests__/Listbox.a11y.dom.ts +38 -0
  536. package/src/Selector/__tests__/Listbox.a11y.inventory.test.ts +63 -0
  537. package/src/Selector/__tests__/Listbox.a11y.known-failures.ts +37 -0
  538. package/src/Selector/__tests__/Listbox.a11y.states.ts +232 -0
  539. package/src/Selector/__tests__/Selector.a11y.chromium.spec.ts +45 -0
  540. package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +121 -0
  541. package/src/SideNav/SideNav.doc.mjs +1 -1
  542. package/src/SideNav/SideNav.test.tsx +10 -0
  543. package/src/SideNav/SideNav.tsx +14 -2
  544. package/src/Slider/Slider.doc.mjs +17 -3
  545. package/src/Slider/Slider.test.tsx +221 -0
  546. package/src/Slider/Slider.tsx +40 -9
  547. package/src/Spinner/Spinner.test.tsx +4 -0
  548. package/src/Spinner/Spinner.tsx +31 -18
  549. package/src/Switch/Switch.doc.mjs +11 -0
  550. package/src/Switch/Switch.test.tsx +16 -0
  551. package/src/Switch/Switch.tsx +28 -0
  552. package/src/TabList/Tab.tsx +35 -7
  553. package/src/TabList/TabList.doc.mjs +11 -0
  554. package/src/TabList/TabList.spec.md +204 -0
  555. package/src/TabList/TabList.test.tsx +66 -0
  556. package/src/TabList/__tests__/Tabs.a11y.known-failures.ts +1 -34
  557. package/src/Table/Table.doc.mjs +1 -1
  558. package/src/Table/Table.spec.md +54 -40
  559. package/src/Table/Table.test.tsx +83 -10
  560. package/src/Table/Table.tsx +30 -22
  561. package/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts +137 -0
  562. package/src/TextArea/TextArea.tsx +6 -1
  563. package/src/TextInput/TextInput.test.tsx +20 -1
  564. package/src/TextInput/TextInput.tsx +6 -1
  565. package/src/TimeInput/NativeTimeInput.test.tsx +36 -3
  566. package/src/TimeInput/Presentation.test.tsx +148 -0
  567. package/src/TimeInput/TimeInput.doc.mjs +21 -5
  568. package/src/TimeInput/TimeInput.tsx +102 -11
  569. package/src/TimeInput/TouchTimeField.tsx +572 -0
  570. package/src/TimeInput/index.ts +1 -0
  571. package/src/Timer/Timer.doc.mjs +183 -0
  572. package/src/Timer/Timer.spec.md +215 -0
  573. package/src/Timer/Timer.test.tsx +302 -0
  574. package/src/Timer/Timer.tsx +258 -0
  575. package/src/Timer/index.ts +11 -0
  576. package/src/ToggleButton/ToggleButton.doc.mjs +3 -3
  577. package/src/ToggleButton/ToggleButton.test.tsx +299 -4
  578. package/src/ToggleButton/ToggleButton.tsx +26 -33
  579. package/src/ToggleButton/ToggleButtonGroup.doc.mjs +3 -3
  580. package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +209 -0
  581. package/src/Token/Token.doc.mjs +2 -2
  582. package/src/Tokenizer/Tokenizer.spec.md +142 -75
  583. package/src/TopNav/TopNavMenu.doc.mjs +2 -2
  584. package/src/TopNav/TopNavMenu.test.tsx +30 -0
  585. package/src/TopNav/TopNavMenu.tsx +7 -2
  586. package/src/TreeList/TreeList.doc.mjs +3 -3
  587. package/src/TreeList/TreeList.spec.md +123 -75
  588. package/src/TreeList/TreeList.test.tsx +29 -0
  589. package/src/TreeList/TreeList.tsx +3 -0
  590. package/src/TreeList/TreeListItem.tsx +15 -1
  591. package/src/TreeList/TreeListTypes.ts +11 -1
  592. package/src/Typeahead/BaseTypeahead.spec.md +4 -3
  593. package/src/Typeahead/BaseTypeahead.tsx +21 -7
  594. package/src/Typeahead/Typeahead.test.tsx +53 -0
  595. package/src/__tests__/PressedState.a11y.chromium.spec.ts +813 -0
  596. package/src/__tests__/pressState.ts +93 -0
  597. package/src/hooks/scrollKeyboardDelegation.test.ts +155 -0
  598. package/src/hooks/scrollKeyboardDelegation.ts +233 -0
  599. package/src/hooks/useClickableContainer.test.tsx +236 -0
  600. package/src/hooks/useClickableContainer.ts +20 -4
  601. package/src/hooks/useScrollableArea.doc.mjs +15 -3
  602. package/src/hooks/useScrollableArea.test.tsx +59 -1
  603. package/src/hooks/useScrollableArea.ts +34 -10
  604. package/src/index.ts +3 -0
  605. package/src/inputFontFloor.test.ts +106 -0
  606. package/src/tailwind-theme.css +0 -6
  607. package/src/theme/Theme.test.tsx +32 -0
  608. package/src/theme/declarationBoundary.test.ts +126 -0
  609. package/src/theme/declarationBoundary.ts +347 -0
  610. package/src/theme/defineTheme.ts +4 -0
  611. package/src/theme/derivedVarRegistry.test.ts +7 -0
  612. package/src/theme/derivedVarRegistry.ts +1 -0
  613. package/src/theme/generateThemeRules.test.ts +526 -1
  614. package/src/theme/generateThemeRules.ts +231 -50
  615. package/src/theme/themeAdaptations.test.ts +211 -1
  616. package/src/theme/themeAdaptations.ts +50 -4
  617. package/src/theme/tokenValueCompat.test.ts +4 -1
  618. package/src/utils/inputPresentation.ts +143 -0
  619. package/src/utils/interactionOverlay.stylex.ts +20 -0
  620. package/src/utils/safeUrl.test.ts +88 -0
  621. package/src/utils/safeUrl.ts +85 -0
@@ -0,0 +1,799 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file sourceDecoration.test.tsx
5
+ * @input Validated source ranges, overlapping claims, and decorated documents
6
+ * @output Behavioral, determinism, invariance, streaming, and ownership coverage
7
+ * @position Acceptance tests for the optional Markdown source-decoration helper
8
+ */
9
+
10
+ import {renderToString} from 'react-dom/server';
11
+ import {describe, expect, expectTypeOf, it, vi} from 'vitest';
12
+ import {Markdown} from '../Markdown';
13
+ import {
14
+ createIncrementalState,
15
+ parseMarkdown,
16
+ parseMarkdownAst,
17
+ parseMarkdownAstIncremental,
18
+ parseMarkdownIncremental,
19
+ trimStreamingArtifacts,
20
+ } from '../parser';
21
+ import {createMarkdownPlugin} from './protocol';
22
+ import type {
23
+ MarkdownExtensionNode,
24
+ MarkdownSyntaxPluginDefinition,
25
+ MarkdownTransform,
26
+ } from './protocol';
27
+ import {parseOutlineFromMarkdown} from '../../Outline/parseOutlineFromMarkdown';
28
+ import {
29
+ createMarkdownSourceDecoration,
30
+ getMarkdownSourceDecorations,
31
+ } from './sourceDecoration';
32
+ import type {MarkdownSourceDecoration} from './sourceDecoration';
33
+
34
+ const SOURCE = [
35
+ '# Release notes',
36
+ '',
37
+ 'Ada shipped the parser.',
38
+ '',
39
+ '> Quoted detail',
40
+ ].join('\n');
41
+
42
+ type Seen = Map<string, ReadonlyArray<MarkdownSourceDecoration>>;
43
+
44
+ function spanOf(text: string, source: string = SOURCE) {
45
+ const start = source.indexOf(text);
46
+ expect(start).toBeGreaterThanOrEqual(0);
47
+ return {start, end: start + text.length};
48
+ }
49
+
50
+ /**
51
+ * Reads decorations back through the public protocol: a transform that runs
52
+ * after the decorating one observes exactly what later plugins and rendering
53
+ * observe.
54
+ */
55
+ function observerPlugin(name: string, seen: Seen) {
56
+ return createMarkdownPlugin({
57
+ name,
58
+ apiVersion: 1,
59
+ transform(root) {
60
+ seen.clear();
61
+ root.children.forEach((block, index) => {
62
+ seen.set(`${index}:${block.type}`, getMarkdownSourceDecorations(block));
63
+ });
64
+ return root;
65
+ },
66
+ });
67
+ }
68
+
69
+ function decorationPlugin(
70
+ name: string,
71
+ transform: MarkdownTransform<never>,
72
+ ): ReturnType<typeof createMarkdownPlugin> {
73
+ return createMarkdownPlugin({name, apiVersion: 1, transform});
74
+ }
75
+
76
+ function decorationsFor(
77
+ source: string,
78
+ ranges: ReadonlyArray<{start: number; end: number}>,
79
+ name = 'hit',
80
+ ): Seen {
81
+ const seen: Seen = new Map();
82
+ parseMarkdown(source, {
83
+ plugins: [
84
+ decorationPlugin(
85
+ `${name}-decoration`,
86
+ createMarkdownSourceDecoration({name, ranges}),
87
+ ),
88
+ observerPlugin(`${name}-observer`, seen),
89
+ ],
90
+ });
91
+ return seen;
92
+ }
93
+
94
+ describe('createMarkdownSourceDecoration', () => {
95
+ it('decorates positioned blocks without the caller opting into sourceRanges', () => {
96
+ const paragraph = spanOf('Ada shipped the parser.');
97
+ const seen: Seen = new Map();
98
+ parseMarkdown(SOURCE, {
99
+ plugins: [
100
+ decorationPlugin(
101
+ 'covers-paragraph',
102
+ createMarkdownSourceDecoration({
103
+ name: 'review-hit',
104
+ ranges: [{...paragraph, data: {reviewer: 'ada'}}],
105
+ }),
106
+ ),
107
+ observerPlugin('covers-paragraph-observer', seen),
108
+ ],
109
+ });
110
+
111
+ expect(seen.get('1:paragraph')).toEqual([
112
+ {name: 'review-hit', data: {reviewer: 'ada'}},
113
+ ]);
114
+ expect(seen.get('0:heading')).toEqual([]);
115
+ expect(seen.get('2:blockquote')).toEqual([]);
116
+ });
117
+
118
+ it('decorates every block a range touches, including partial overlap', () => {
119
+ const heading = spanOf('# Release notes');
120
+ const paragraph = spanOf('Ada shipped the parser.');
121
+
122
+ // One range covering two whole blocks.
123
+ const spanning = decorationsFor(SOURCE, [
124
+ {start: heading.start, end: paragraph.end},
125
+ ]);
126
+ expect(spanning.get('0:heading')).toEqual([{name: 'hit'}]);
127
+ expect(spanning.get('1:paragraph')).toEqual([{name: 'hit'}]);
128
+ expect(spanning.get('2:blockquote')).toEqual([]);
129
+
130
+ // A range strictly inside one block still decorates that block: a search
131
+ // hit is a sub-span of the prose it was found in.
132
+ const inside = decorationsFor(SOURCE, [spanOf('shipped')]);
133
+ expect(inside.get('1:paragraph')).toEqual([{name: 'hit'}]);
134
+ expect(inside.get('0:heading')).toEqual([]);
135
+
136
+ // A range straddling a boundary touches both blocks.
137
+ const straddling = decorationsFor(SOURCE, [
138
+ {start: paragraph.end - 4, end: spanOf('> Quoted detail').start + 3},
139
+ ]);
140
+ expect(straddling.get('1:paragraph')).toEqual([{name: 'hit'}]);
141
+ expect(straddling.get('2:blockquote')).toEqual([{name: 'hit'}]);
142
+ });
143
+
144
+ it('is observable through the rendered component without changing its output', () => {
145
+ const paragraph = spanOf('Ada shipped the parser.');
146
+ const seen: Seen = new Map();
147
+ const plugins = [
148
+ decorationPlugin(
149
+ 'component-decoration',
150
+ createMarkdownSourceDecoration({
151
+ name: 'search-hit',
152
+ ranges: [paragraph],
153
+ }),
154
+ ),
155
+ observerPlugin('component-observer', seen),
156
+ ];
157
+
158
+ const decorated = renderToString(
159
+ <Markdown plugins={plugins}>{SOURCE}</Markdown>,
160
+ );
161
+
162
+ expect(seen.get('1:paragraph')).toEqual([{name: 'search-hit'}]);
163
+ expect(decorated).toBe(renderToString(<Markdown>{SOURCE}</Markdown>));
164
+ });
165
+
166
+ it('is observable through Outline without changing heading identity', () => {
167
+ const seen: Seen = new Map();
168
+ const plugins = [
169
+ decorationPlugin(
170
+ 'outline-decoration',
171
+ createMarkdownSourceDecoration({
172
+ name: 'search-hit',
173
+ ranges: [spanOf('# Release notes')],
174
+ }),
175
+ ),
176
+ observerPlugin('outline-observer', seen),
177
+ ];
178
+
179
+ expect(parseOutlineFromMarkdown(SOURCE, {plugins})).toEqual(
180
+ parseOutlineFromMarkdown(SOURCE),
181
+ );
182
+ expect(seen.get('0:heading')).toEqual([{name: 'search-hit'}]);
183
+ });
184
+
185
+ it('exposes decorations only on the settled snapshot, never present then absent', () => {
186
+ // An ordinary table: while it streams, the covering block is re-parsed
187
+ // from paragraph to table and its extent changes under the range.
188
+ const source = [
189
+ '# Title',
190
+ '',
191
+ 'Intro prose here.',
192
+ '',
193
+ '| Item | Detail |',
194
+ '| --- | --- |',
195
+ '| 1 | two |',
196
+ '',
197
+ 'Tail prose.',
198
+ ].join('\n');
199
+
200
+ for (const target of [
201
+ 'Intro prose here.',
202
+ '| Item | Detail |',
203
+ '| 1 | two |',
204
+ 'Tail prose.',
205
+ ]) {
206
+ const start = source.indexOf(target);
207
+ const range = {start, end: start + target.length};
208
+ const seen: Seen = new Map();
209
+ const plugins = [
210
+ decorationPlugin(
211
+ 'streaming-decoration',
212
+ createMarkdownSourceDecoration({name: 'hit', ranges: [range]}),
213
+ ),
214
+ observerPlugin('streaming-observer', seen),
215
+ ];
216
+
217
+ const state = createIncrementalState();
218
+ const presence: boolean[] = [];
219
+ for (let length = 1; length <= source.length; length++) {
220
+ const chunk = source.slice(0, length);
221
+ const isFinal = length === source.length;
222
+ parseMarkdownIncremental(
223
+ isFinal ? chunk : trimStreamingArtifacts(chunk, {}),
224
+ state,
225
+ {plugins, isFinal},
226
+ );
227
+ presence.push([...seen.values()].some(entries => entries.length > 0));
228
+ }
229
+
230
+ // Monotone by construction: absent while the source can still change,
231
+ // present once it cannot. No present -> absent transition exists.
232
+ expect(presence.slice(0, -1).every(shown => !shown)).toBe(true);
233
+ expect(presence[presence.length - 1]).toBe(true);
234
+ }
235
+ });
236
+
237
+ it('decorates blocks an earlier transform reordered', () => {
238
+ const heading = spanOf('# Release notes');
239
+ const quote = spanOf('> Quoted detail');
240
+ // A transform that reverses the document puts spans out of source order,
241
+ // so a sweep that assumed document order would miss or mis-assign them.
242
+ const reverse = createMarkdownPlugin({
243
+ name: 'reverse-blocks',
244
+ apiVersion: 1,
245
+ transform: root => ({...root, children: [...root.children].reverse()}),
246
+ });
247
+ const seen: Seen = new Map();
248
+ parseMarkdown(SOURCE, {
249
+ plugins: [
250
+ reverse,
251
+ decorationPlugin(
252
+ 'reordered',
253
+ createMarkdownSourceDecoration({
254
+ name: 'hit',
255
+ ranges: [heading, {...quote, data: {tail: true}}],
256
+ }),
257
+ ),
258
+ observerPlugin('reordered-observer', seen),
259
+ ],
260
+ });
261
+
262
+ // Reversed order: blockquote, paragraph, heading.
263
+ expect(seen.get('0:blockquote')).toEqual([
264
+ {name: 'hit', data: {tail: true}},
265
+ ]);
266
+ expect(seen.get('1:paragraph')).toEqual([]);
267
+ expect(seen.get('2:heading')).toEqual([{name: 'hit'}]);
268
+ });
269
+
270
+ it('resolves overlapping, duplicate, and unordered ranges deterministically', () => {
271
+ const paragraph = spanOf('Ada shipped the parser.');
272
+ const wide = {start: 0, end: paragraph.end};
273
+ const run = () => {
274
+ const seen: Seen = new Map();
275
+ parseMarkdown(SOURCE, {
276
+ plugins: [
277
+ decorationPlugin(
278
+ 'overlaps',
279
+ createMarkdownSourceDecoration({
280
+ name: 'hit',
281
+ ranges: [
282
+ {...paragraph, data: {rank: 2}},
283
+ wide,
284
+ {...paragraph, data: {rank: 1}},
285
+ // Exact duplicate of the first range.
286
+ {...paragraph, data: {rank: 2}},
287
+ paragraph,
288
+ ],
289
+ }),
290
+ ),
291
+ observerPlugin('overlaps-observer', seen),
292
+ ],
293
+ });
294
+ return seen.get('1:paragraph');
295
+ };
296
+
297
+ // Sorted by start, then end, then payload; the repeated rank-2 range
298
+ // collapses into one entry.
299
+ expect(run()).toEqual([
300
+ // The wide range starts first.
301
+ {name: 'hit'},
302
+ // Then the three paragraph-aligned ranges, payload-free first.
303
+ {name: 'hit'},
304
+ {name: 'hit', data: {rank: 1}},
305
+ {name: 'hit', data: {rank: 2}},
306
+ ]);
307
+ expect(run()).toEqual(run());
308
+ });
309
+
310
+ it('records each range once per block however many blocks it sweeps', () => {
311
+ const sections = 200;
312
+ const source = Array.from(
313
+ {length: sections},
314
+ (_, index) => `Section ${index} prose.`,
315
+ ).join('\n\n');
316
+ // One range per block plus one range spanning the whole document.
317
+ const ranges = [
318
+ {start: 0, end: source.length},
319
+ ...Array.from({length: sections}, (_, index) =>
320
+ spanOf(`Section ${index} prose.`, source),
321
+ ),
322
+ ];
323
+ const seen = decorationsFor(source, ranges);
324
+
325
+ expect(seen.size).toBe(sections);
326
+ for (let index = 0; index < sections; index++) {
327
+ // The document-wide range and exactly this block's own range.
328
+ expect(seen.get(`${index}:paragraph`)).toEqual([
329
+ {name: 'hit'},
330
+ {name: 'hit'},
331
+ ]);
332
+ }
333
+ });
334
+
335
+ it('appends later plugins after earlier ones', () => {
336
+ const paragraph = spanOf('Ada shipped the parser.');
337
+ const seen: Seen = new Map();
338
+ parseMarkdown(SOURCE, {
339
+ plugins: [
340
+ decorationPlugin(
341
+ 'first-pass',
342
+ createMarkdownSourceDecoration({name: 'first', ranges: [paragraph]}),
343
+ ),
344
+ decorationPlugin(
345
+ 'second-pass',
346
+ createMarkdownSourceDecoration({name: 'second', ranges: [paragraph]}),
347
+ ),
348
+ observerPlugin('order-observer', seen),
349
+ ],
350
+ });
351
+
352
+ expect(seen.get('1:paragraph')).toEqual([
353
+ {name: 'first'},
354
+ {name: 'second'},
355
+ ]);
356
+ });
357
+
358
+ it('leaves parsed results, rendered output, and heading identity unchanged', () => {
359
+ const decorated = decorationPlugin(
360
+ 'invariance',
361
+ createMarkdownSourceDecoration({
362
+ name: 'hit',
363
+ ranges: [spanOf('# Release notes'), spanOf('Ada shipped the parser.')],
364
+ }),
365
+ );
366
+
367
+ expect(parseMarkdown(SOURCE, {plugins: [decorated]})).toEqual(
368
+ parseMarkdown(SOURCE),
369
+ );
370
+ expect(
371
+ parseMarkdown(SOURCE, {sourceRanges: true, plugins: [decorated]}),
372
+ ).toEqual(parseMarkdown(SOURCE, {sourceRanges: true}));
373
+
374
+ const plain = renderToString(<Markdown>{SOURCE}</Markdown>);
375
+ const withDecoration = renderToString(
376
+ <Markdown plugins={[decorated]}>{SOURCE}</Markdown>,
377
+ );
378
+ expect(withDecoration).toBe(plain);
379
+ });
380
+
381
+ it('never mutates the document a transform received', () => {
382
+ const paragraph = spanOf('Ada shipped the parser.');
383
+ const before: ReadonlyArray<MarkdownSourceDecoration>[] = [];
384
+ const after: ReadonlyArray<MarkdownSourceDecoration>[] = [];
385
+ const capture = (
386
+ name: string,
387
+ sink: ReadonlyArray<MarkdownSourceDecoration>[],
388
+ ) =>
389
+ createMarkdownPlugin({
390
+ name,
391
+ apiVersion: 1,
392
+ transform(root) {
393
+ const block = root.children[1];
394
+ sink.push(getMarkdownSourceDecorations(block));
395
+ expect(Object.isFrozen(block)).toBe(true);
396
+ return root;
397
+ },
398
+ });
399
+
400
+ parseMarkdown(SOURCE, {
401
+ plugins: [
402
+ capture('mutation-before', before),
403
+ decorationPlugin(
404
+ 'mutation-decorate',
405
+ createMarkdownSourceDecoration({name: 'hit', ranges: [paragraph]}),
406
+ ),
407
+ capture('mutation-after', after),
408
+ ],
409
+ });
410
+
411
+ expect(before).toEqual([[]]);
412
+ expect(after).toEqual([[{name: 'hit'}]]);
413
+ });
414
+
415
+ it('freezes every sibling before an untrusted plugin observes the tree', () => {
416
+ // A trusted helper carries undecorated siblings over by identity. Those
417
+ // siblings must still be deeply frozen before plugin-authored code runs,
418
+ // or a later plugin can mutate a node the helper never touched.
419
+ const source = '# Title\n\nAlpha prose.\n\nBeta prose.\n\nGamma prose.';
420
+ const target = source.indexOf('Beta prose.');
421
+ const observed: {type: string; frozen: boolean; textFrozen: boolean}[] = [];
422
+ let mutationRejected = false;
423
+
424
+ const attacker = createMarkdownPlugin({
425
+ name: 'sibling-attacker',
426
+ apiVersion: 1,
427
+ transform(root) {
428
+ root.children.forEach(block => {
429
+ const child =
430
+ 'children' in block
431
+ ? (block.children[0] as object | undefined)
432
+ : undefined;
433
+ observed.push({
434
+ type: block.type,
435
+ frozen: Object.isFrozen(block),
436
+ textFrozen: child == null || Object.isFrozen(child),
437
+ });
438
+ });
439
+ // Attempt an in-place edit of an UNDECORATED sibling's text node.
440
+ const victim = root.children[1];
441
+ const text =
442
+ victim.type === 'paragraph'
443
+ ? (victim.children[0] as {value: string})
444
+ : undefined;
445
+ try {
446
+ if (text != null) {
447
+ text.value = 'HACKED';
448
+ }
449
+ mutationRejected = text?.value !== 'HACKED';
450
+ } catch {
451
+ mutationRejected = true;
452
+ }
453
+ return root;
454
+ },
455
+ });
456
+
457
+ const blocks = parseMarkdown(source, {
458
+ plugins: [
459
+ decorationPlugin(
460
+ 'sibling-decoration',
461
+ createMarkdownSourceDecoration({
462
+ name: 'hit',
463
+ ranges: [{start: target, end: target + 'Beta prose.'.length}],
464
+ }),
465
+ ),
466
+ attacker,
467
+ ],
468
+ });
469
+
470
+ expect(observed).toHaveLength(4);
471
+ expect(observed.every(entry => entry.frozen && entry.textFrozen)).toBe(
472
+ true,
473
+ );
474
+ expect(mutationRejected).toBe(true);
475
+ // The undecorated sibling reached rendering unchanged.
476
+ expect(blocks[1]).toEqual({
477
+ type: 'paragraph',
478
+ children: [{type: 'text', content: 'Alpha prose.'}],
479
+ });
480
+ });
481
+
482
+ it('leaves a prior streamed snapshot untouched when a later chunk decorates', () => {
483
+ const source = 'Alpha prose.\n\nBeta prose.';
484
+ const target = source.indexOf('Beta prose.');
485
+ const plugins = [
486
+ decorationPlugin(
487
+ 'snapshot-decoration',
488
+ createMarkdownSourceDecoration({
489
+ name: 'hit',
490
+ ranges: [{start: target, end: target + 'Beta prose.'.length}],
491
+ }),
492
+ ),
493
+ ];
494
+
495
+ const state = createIncrementalState();
496
+ const partial = parseMarkdownAstIncremental(
497
+ source.slice(0, target),
498
+ state,
499
+ {plugins, isFinal: false},
500
+ ).children;
501
+ const partialSnapshot = JSON.parse(JSON.stringify(partial));
502
+ const partialBlocks = [...partial];
503
+
504
+ parseMarkdownAstIncremental(source, state, {plugins, isFinal: true});
505
+
506
+ // The earlier snapshot is a settled value a caller may still hold: the
507
+ // later chunk's decoration must not have reached back into it.
508
+ expect(JSON.parse(JSON.stringify(partial))).toEqual(partialSnapshot);
509
+ expect(partialBlocks.map(getMarkdownSourceDecorations)).toEqual(
510
+ partialBlocks.map(() => []),
511
+ );
512
+ });
513
+
514
+ it('copies caller ranges so later mutation cannot change decorations', () => {
515
+ const paragraph = spanOf('Ada shipped the parser.');
516
+ const payload = {reviewer: 'ada'};
517
+ const ranges = [{...paragraph, data: payload}];
518
+ const transform = createMarkdownSourceDecoration({name: 'hit', ranges});
519
+ payload.reviewer = 'linus';
520
+ ranges.push({start: 0, end: 4, data: payload});
521
+
522
+ const seen: Seen = new Map();
523
+ parseMarkdown(SOURCE, {
524
+ plugins: [
525
+ decorationPlugin('immutable-options', transform),
526
+ observerPlugin('immutable-options-observer', seen),
527
+ ],
528
+ });
529
+
530
+ expect(seen.get('1:paragraph')).toEqual([
531
+ {name: 'hit', data: {reviewer: 'ada'}},
532
+ ]);
533
+ expect(seen.get('0:heading')).toEqual([]);
534
+ });
535
+
536
+ it('leaves plugin extension nodes to their owner', () => {
537
+ type NoteNode = MarkdownExtensionNode<
538
+ 'decoration-notes',
539
+ 'note',
540
+ {readonly body: string},
541
+ 'block'
542
+ >;
543
+ const source = ':::note\nOwned by the plugin\n:::\n\nAda shipped it.';
544
+ const notes = createMarkdownPlugin<'decoration-notes', NoteNode>({
545
+ name: 'decoration-notes',
546
+ apiVersion: 1,
547
+ parseKey: 'v1',
548
+ syntax: {
549
+ block: [
550
+ {
551
+ startsWith: [':::note'],
552
+ maxSpan: 200,
553
+ tokenize({source: input, offset, end, isFinal}) {
554
+ const close = input.indexOf('\n:::', offset + 7);
555
+ if (close < 0 || close + 4 > end) {
556
+ return isFinal ? {status: 'no-match'} : {status: 'defer'};
557
+ }
558
+ return {
559
+ status: 'match',
560
+ end: close + 4,
561
+ node: {
562
+ type: 'extension',
563
+ plugin: 'decoration-notes',
564
+ name: 'note',
565
+ display: 'block',
566
+ data: {body: input.slice(offset + 7, close).trim()},
567
+ },
568
+ };
569
+ },
570
+ },
571
+ ],
572
+ },
573
+ renderers: {
574
+ note: {
575
+ render: ({node}) => node.data.body,
576
+ toText: node => node.data.body,
577
+ },
578
+ },
579
+ } satisfies MarkdownSyntaxPluginDefinition<'decoration-notes', NoteNode>);
580
+
581
+ const seen: Seen = new Map();
582
+ const blocks = parseMarkdown(source, {
583
+ plugins: [
584
+ notes,
585
+ decorationPlugin(
586
+ 'extension-ownership',
587
+ createMarkdownSourceDecoration({
588
+ name: 'hit',
589
+ ranges: [{start: 0, end: source.length}],
590
+ }),
591
+ ),
592
+ observerPlugin('extension-ownership-observer', seen),
593
+ ],
594
+ });
595
+
596
+ expect(seen.get('0:extension')).toEqual([]);
597
+ expect(seen.get('1:paragraph')).toEqual([{name: 'hit'}]);
598
+ expect(blocks[0]).toMatchObject({
599
+ type: 'extension',
600
+ data: {body: 'Owned by the plugin'},
601
+ });
602
+ });
603
+
604
+ it('stores decorations in a versioned Core-owned envelope', () => {
605
+ const root = parseMarkdownAst(SOURCE, {
606
+ plugins: [
607
+ decorationPlugin(
608
+ 'envelope-shape',
609
+ createMarkdownSourceDecoration({
610
+ name: 'hit',
611
+ ranges: [spanOf('Ada shipped the parser.')],
612
+ }),
613
+ ),
614
+ ],
615
+ });
616
+
617
+ expect(root.children[1]?.data).toEqual({
618
+ 'astryx:sourceDecorations': {
619
+ kind: 'astryx.markdown.sourceDecorations',
620
+ version: 1,
621
+ entries: [{name: 'hit'}],
622
+ },
623
+ });
624
+ });
625
+
626
+ it('never merges into foreign data and reports the skip once', () => {
627
+ const warning = vi.spyOn(console, 'warn').mockImplementation(() => {});
628
+ const seen: Seen = new Map();
629
+ // Two foreign shapes: an opaque scalar, and an unbranded array parked at
630
+ // the envelope key by another plugin.
631
+ const foreign = createMarkdownPlugin({
632
+ name: 'foreign-data',
633
+ apiVersion: 1,
634
+ transform(root) {
635
+ return {
636
+ ...root,
637
+ children: root.children.map(block => {
638
+ if (block.type === 'heading') {
639
+ return {...block, data: 'opaque'};
640
+ }
641
+ if (block.type === 'blockquote') {
642
+ return {
643
+ ...block,
644
+ data: {'astryx:sourceDecorations': [{name: 'forged'}]},
645
+ };
646
+ }
647
+ return block;
648
+ }),
649
+ };
650
+ },
651
+ });
652
+
653
+ parseMarkdown(SOURCE, {
654
+ plugins: [
655
+ foreign,
656
+ decorationPlugin(
657
+ 'foreign-data-decoration',
658
+ createMarkdownSourceDecoration({
659
+ name: 'hit',
660
+ ranges: [{start: 0, end: SOURCE.length}],
661
+ }),
662
+ ),
663
+ observerPlugin('foreign-data-observer', seen),
664
+ ],
665
+ });
666
+
667
+ expect(seen.get('0:heading')).toEqual([]);
668
+ expect(seen.get('2:blockquote')).toEqual([]);
669
+ expect(seen.get('1:paragraph')).toEqual([{name: 'hit'}]);
670
+ expect(warning).toHaveBeenCalledTimes(1);
671
+ expect(warning.mock.calls[0]?.[0]).toContain('foreign-data-decoration');
672
+ warning.mockRestore();
673
+ });
674
+
675
+ it('keeps unrelated data on a node it decorates', () => {
676
+ const paragraph = spanOf('Ada shipped the parser.');
677
+ const annotate = createMarkdownPlugin({
678
+ name: 'annotate-first',
679
+ apiVersion: 1,
680
+ transform(root) {
681
+ return {
682
+ ...root,
683
+ children: root.children.map(block =>
684
+ block.type === 'paragraph'
685
+ ? {...block, data: {owner: 'ada'}}
686
+ : block,
687
+ ),
688
+ };
689
+ },
690
+ });
691
+
692
+ const root = parseMarkdownAst(SOURCE, {
693
+ plugins: [
694
+ annotate,
695
+ decorationPlugin(
696
+ 'annotate-decoration',
697
+ createMarkdownSourceDecoration({name: 'hit', ranges: [paragraph]}),
698
+ ),
699
+ ],
700
+ });
701
+
702
+ expect(root.children[1]?.data).toEqual({
703
+ owner: 'ada',
704
+ 'astryx:sourceDecorations': {
705
+ kind: 'astryx.markdown.sourceDecorations',
706
+ version: 1,
707
+ entries: [{name: 'hit'}],
708
+ },
709
+ });
710
+ });
711
+
712
+ it('rejects invalid options at creation', () => {
713
+ expect(() =>
714
+ createMarkdownSourceDecoration({name: ' ', ranges: []}),
715
+ ).toThrow(TypeError);
716
+ expect(() =>
717
+ createMarkdownSourceDecoration({
718
+ name: 'hit',
719
+ ranges: [{start: 4, end: 4}],
720
+ }),
721
+ ).toThrow(TypeError);
722
+ expect(() =>
723
+ createMarkdownSourceDecoration({
724
+ name: 'hit',
725
+ ranges: [{start: -1, end: 4}],
726
+ }),
727
+ ).toThrow(TypeError);
728
+ expect(() =>
729
+ createMarkdownSourceDecoration({
730
+ name: 'hit',
731
+ ranges: [{start: 0, end: 1.5}],
732
+ }),
733
+ ).toThrow(TypeError);
734
+ expect(() =>
735
+ createMarkdownSourceDecoration({
736
+ name: 'hit',
737
+ ranges: [
738
+ {start: 0, end: 4, data: {render: (() => null) as unknown as string}},
739
+ ],
740
+ }),
741
+ ).toThrow(TypeError);
742
+ });
743
+
744
+ it('treats an empty range list as a no-op transform', () => {
745
+ const seen = decorationsFor(SOURCE, []);
746
+ expect([...seen.values()].flat()).toEqual([]);
747
+ });
748
+
749
+ it('types as an extension-free transform and reads only its own envelope', () => {
750
+ const transform = createMarkdownSourceDecoration({
751
+ name: 'hit',
752
+ ranges: [{start: 0, end: 4}],
753
+ });
754
+ expectTypeOf(transform).toExtend<MarkdownTransform<never>>();
755
+ // A decoration plugin introduces no extension nodes, so it needs no
756
+ // renderers.
757
+ const plugin = createMarkdownPlugin({
758
+ name: 'typed-decoration',
759
+ apiVersion: 1,
760
+ transform,
761
+ });
762
+ expectTypeOf(plugin.name).toEqualTypeOf<string>();
763
+ expectTypeOf(getMarkdownSourceDecorations({})).toEqualTypeOf<
764
+ ReadonlyArray<MarkdownSourceDecoration>
765
+ >();
766
+
767
+ expect(getMarkdownSourceDecorations({data: 'opaque'})).toEqual([]);
768
+ expect(
769
+ getMarkdownSourceDecorations({data: {decorations: [{name: 'x'}]}}),
770
+ ).toEqual([]);
771
+ expect(
772
+ getMarkdownSourceDecorations({
773
+ data: {'astryx:sourceDecorations': [{name: 'x'}]},
774
+ }),
775
+ ).toEqual([]);
776
+ expect(
777
+ getMarkdownSourceDecorations({
778
+ data: {
779
+ 'astryx:sourceDecorations': {
780
+ kind: 'astryx.markdown.sourceDecorations',
781
+ version: 2,
782
+ entries: [{name: 'x'}],
783
+ },
784
+ },
785
+ }),
786
+ ).toEqual([]);
787
+ expect(
788
+ getMarkdownSourceDecorations({
789
+ data: {
790
+ 'astryx:sourceDecorations': {
791
+ kind: 'astryx.markdown.sourceDecorations',
792
+ version: 1,
793
+ entries: [{name: 'x'}],
794
+ },
795
+ },
796
+ }),
797
+ ).toEqual([{name: 'x'}]);
798
+ });
799
+ });