@astryxdesign/core 0.6.2 → 0.6.3-canary.01fa439

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 (384) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/dist/BottomSheet/BottomSheet.d.ts +1 -1
  3. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  4. package/dist/BottomSheet/BottomSheet.js +3 -1
  5. package/dist/BottomSheet/BottomSheetPanel.d.ts +7 -5
  6. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  7. package/dist/BottomSheet/BottomSheetPanel.js +56 -19
  8. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  9. package/dist/Chat/ChatComposer.js +10 -5
  10. package/dist/Chat/ChatComposerDrawer.d.ts +19 -5
  11. package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
  12. package/dist/Chat/ChatComposerDrawer.js +48 -23
  13. package/dist/Chat/ChatComposerInput.d.ts +11 -3
  14. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  15. package/dist/Chat/ChatComposerInput.js +63 -16
  16. package/dist/Chat/ChatDictationButton.d.ts +3 -2
  17. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  18. package/dist/Chat/ChatDictationButton.js +6 -4
  19. package/dist/Chat/ChatSendButton.js +1 -1
  20. package/dist/Chat/index.d.ts +1 -1
  21. package/dist/Chat/index.d.ts.map +1 -1
  22. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  23. package/dist/CheckboxInput/CheckboxInput.js +12 -2
  24. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  25. package/dist/Collapsible/Collapsible.js +6 -1
  26. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  27. package/dist/CommandPalette/CommandPaletteInput.js +1 -1
  28. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  29. package/dist/ComplexSelector/ComplexSelector.js +1 -1
  30. package/dist/DateInput/DateInput.d.ts.map +1 -1
  31. package/dist/DateInput/DateInput.js +4 -4
  32. package/dist/DateInput/NativeDateField.d.ts.map +1 -1
  33. package/dist/DateInput/NativeDateField.js +16 -16
  34. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  35. package/dist/DateInput/TouchDateField.js +2 -2
  36. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  37. package/dist/DateRangeInput/DateRangeInput.js +4 -4
  38. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  39. package/dist/DateTimeInput/DateTimeInput.js +8 -8
  40. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  41. package/dist/DateTimeInput/TouchDateTimeField.js +4 -4
  42. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +9 -3
  43. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -1
  44. package/dist/DateTimeInput/nativePickerSegmentStyles.js +3 -3
  45. package/dist/Dialog/DialogHeader.d.ts +8 -1
  46. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  47. package/dist/Dialog/DialogHeader.js +10 -1
  48. package/dist/Field/InputClearButton.d.ts +4 -2
  49. package/dist/Field/InputClearButton.d.ts.map +1 -1
  50. package/dist/Field/InputClearButton.js +4 -2
  51. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  52. package/dist/Field/PanelSearchInput.js +1 -1
  53. package/dist/FileInput/FileInput.d.ts.map +1 -1
  54. package/dist/FileInput/FileInput.js +7 -7
  55. package/dist/Kbd/Kbd.d.ts +5 -3
  56. package/dist/Kbd/Kbd.d.ts.map +1 -1
  57. package/dist/Kbd/Kbd.js +36 -42
  58. package/dist/Link/Link.d.ts.map +1 -1
  59. package/dist/Link/Link.js +6 -2
  60. package/dist/Markdown/Markdown.d.ts +8 -2
  61. package/dist/Markdown/Markdown.d.ts.map +1 -1
  62. package/dist/Markdown/Markdown.fr23.bench.d.ts +2 -0
  63. package/dist/Markdown/Markdown.fr23.bench.d.ts.map +1 -0
  64. package/dist/Markdown/Markdown.fr23.bench.js +150 -0
  65. package/dist/Markdown/Markdown.fr23.sampling.d.ts +2 -0
  66. package/dist/Markdown/Markdown.fr23.sampling.d.ts.map +1 -0
  67. package/dist/Markdown/Markdown.fr23.sampling.js +43 -0
  68. package/dist/Markdown/Markdown.js +262 -109
  69. package/dist/Markdown/ast.d.ts +162 -0
  70. package/dist/Markdown/ast.d.ts.map +1 -0
  71. package/dist/Markdown/ast.js +74 -0
  72. package/dist/Markdown/index.d.ts +5 -3
  73. package/dist/Markdown/index.d.ts.map +1 -1
  74. package/dist/Markdown/index.js +3 -2
  75. package/dist/Markdown/parser/index.d.ts +10 -0
  76. package/dist/Markdown/parser/index.d.ts.map +1 -0
  77. package/dist/Markdown/parser/index.js +10 -0
  78. package/dist/Markdown/parser.d.ts +126 -58
  79. package/dist/Markdown/parser.d.ts.map +1 -1
  80. package/dist/Markdown/parser.js +716 -167
  81. package/dist/Markdown/plugins/frontmatter.d.ts +32 -0
  82. package/dist/Markdown/plugins/frontmatter.d.ts.map +1 -0
  83. package/dist/Markdown/plugins/frontmatter.js +132 -0
  84. package/dist/Markdown/plugins/index.d.ts +16 -0
  85. package/dist/Markdown/plugins/index.d.ts.map +1 -0
  86. package/dist/Markdown/plugins/index.js +13 -0
  87. package/dist/Markdown/plugins/protocol.d.ts +191 -0
  88. package/dist/Markdown/plugins/protocol.d.ts.map +1 -0
  89. package/dist/Markdown/plugins/protocol.js +957 -0
  90. package/dist/Markdown/plugins/semanticFence.d.ts +36 -0
  91. package/dist/Markdown/plugins/semanticFence.d.ts.map +1 -0
  92. package/dist/Markdown/plugins/semanticFence.js +213 -0
  93. package/dist/Markdown/plugins/sourceDecoration.d.ts +76 -0
  94. package/dist/Markdown/plugins/sourceDecoration.d.ts.map +1 -0
  95. package/dist/Markdown/plugins/sourceDecoration.js +393 -0
  96. package/dist/Markdown/plugins/textTransform.d.ts +30 -0
  97. package/dist/Markdown/plugins/textTransform.d.ts.map +1 -0
  98. package/dist/Markdown/plugins/textTransform.js +374 -0
  99. package/dist/Markdown/remark.d.ts +196 -0
  100. package/dist/Markdown/remark.d.ts.map +1 -0
  101. package/dist/Markdown/remark.js +1062 -0
  102. package/dist/Markdown/url.d.ts +4 -0
  103. package/dist/Markdown/url.d.ts.map +1 -0
  104. package/dist/Markdown/url.js +25 -0
  105. package/dist/Markdown/utils.d.ts +4 -2
  106. package/dist/Markdown/utils.d.ts.map +1 -1
  107. package/dist/Markdown/utils.js +2 -1
  108. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  109. package/dist/NumberInput/NumberInput.js +4 -4
  110. package/dist/Outline/index.d.ts +1 -0
  111. package/dist/Outline/index.d.ts.map +1 -1
  112. package/dist/Outline/parseOutlineFromMarkdown.d.ts +7 -1
  113. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  114. package/dist/Outline/parseOutlineFromMarkdown.js +14 -8
  115. package/dist/Outline/useOutlineFromMarkdown.d.ts +3 -1
  116. package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
  117. package/dist/Outline/useOutlineFromMarkdown.js +8 -3
  118. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  119. package/dist/PowerSearch/PowerSearchEditPopover.js +46 -30
  120. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  121. package/dist/ProgressBar/ProgressBar.js +36 -31
  122. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  123. package/dist/RadioList/RadioListItem.js +13 -1
  124. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  125. package/dist/SegmentedControl/SegmentedControlItem.js +5 -5
  126. package/dist/Selector/Selector.d.ts +9 -7
  127. package/dist/Selector/Selector.d.ts.map +1 -1
  128. package/dist/Selector/Selector.js +7 -5
  129. package/dist/SideNav/SideNav.d.ts +2 -1
  130. package/dist/SideNav/SideNav.d.ts.map +1 -1
  131. package/dist/SideNav/SideNav.js +9 -3
  132. package/dist/Slider/Slider.d.ts.map +1 -1
  133. package/dist/Slider/Slider.js +28 -12
  134. package/dist/Spinner/Spinner.d.ts.map +1 -1
  135. package/dist/Spinner/Spinner.js +23 -7
  136. package/dist/Switch/Switch.d.ts.map +1 -1
  137. package/dist/Switch/Switch.js +11 -0
  138. package/dist/TabList/Tab.d.ts +1 -1
  139. package/dist/TabList/Tab.d.ts.map +1 -1
  140. package/dist/TabList/Tab.js +20 -7
  141. package/dist/Table/Table.d.ts +1 -0
  142. package/dist/Table/Table.d.ts.map +1 -1
  143. package/dist/Table/Table.js +29 -13
  144. package/dist/TextArea/TextArea.d.ts.map +1 -1
  145. package/dist/TextArea/TextArea.js +1 -1
  146. package/dist/TextInput/TextInput.d.ts.map +1 -1
  147. package/dist/TextInput/TextInput.js +2 -2
  148. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  149. package/dist/TimeInput/TimeInput.js +4 -4
  150. package/dist/ToggleButton/ToggleButton.d.ts +9 -6
  151. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  152. package/dist/ToggleButton/ToggleButton.js +15 -27
  153. package/dist/TreeList/TreeList.d.ts.map +1 -1
  154. package/dist/TreeList/TreeList.js +3 -0
  155. package/dist/TreeList/TreeListItem.d.ts +6 -1
  156. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  157. package/dist/TreeList/TreeListItem.js +12 -2
  158. package/dist/TreeList/TreeListTypes.d.ts +8 -1
  159. package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
  160. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  161. package/dist/Typeahead/BaseTypeahead.js +16 -7
  162. package/dist/astryx.css +18 -7
  163. package/dist/hooks/scrollKeyboardDelegation.d.ts +3 -0
  164. package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -0
  165. package/dist/hooks/scrollKeyboardDelegation.js +146 -0
  166. package/dist/hooks/useScrollableArea.d.ts +6 -2
  167. package/dist/hooks/useScrollableArea.d.ts.map +1 -1
  168. package/dist/hooks/useScrollableArea.js +17 -5
  169. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  170. package/dist/theme/generateThemeRules.js +10 -0
  171. package/dist/utils/interactionOverlay.stylex.d.ts +8 -0
  172. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  173. package/dist/utils/interactionOverlay.stylex.js +9 -0
  174. package/locales/af-ZA.json +530 -1
  175. package/locales/ar-SA.json +490 -1
  176. package/locales/ca-ES.json +514 -1
  177. package/locales/cs-CZ.json +498 -1
  178. package/locales/da-DK.json +522 -1
  179. package/locales/de-DE.json +522 -1
  180. package/locales/el-GR.json +498 -1
  181. package/locales/es-ES.json +510 -1
  182. package/locales/fi-FI.json +498 -1
  183. package/locales/fr-FR.json +534 -1
  184. package/locales/he-IL.json +498 -1
  185. package/locales/hu-HU.json +498 -1
  186. package/locales/it-IT.json +510 -1
  187. package/locales/ja-JP.json +490 -1
  188. package/locales/ko-KR.json +498 -1
  189. package/locales/nl-NL.json +534 -1
  190. package/locales/no-NO.json +510 -1
  191. package/locales/pl-PL.json +506 -1
  192. package/locales/pt-BR.json +506 -1
  193. package/locales/pt-PT.json +506 -1
  194. package/locales/ro-RO.json +506 -1
  195. package/locales/ru-RU.json +498 -1
  196. package/locales/sr-SP.json +498 -1
  197. package/locales/sv-SE.json +502 -1
  198. package/locales/tr-TR.json +498 -1
  199. package/locales/uk-UA.json +498 -1
  200. package/locales/vi-VN.json +502 -1
  201. package/locales/zh-CN.json +490 -1
  202. package/locales/zh-TW.json +490 -1
  203. package/package.json +19 -4
  204. package/src/BottomSheet/BottomSheet.doc.mjs +8 -1
  205. package/src/BottomSheet/BottomSheet.spec.md +46 -20
  206. package/src/BottomSheet/BottomSheet.test.tsx +6 -3
  207. package/src/BottomSheet/BottomSheet.tsx +3 -1
  208. package/src/BottomSheet/BottomSheetKeyboard.test.tsx +195 -0
  209. package/src/BottomSheet/BottomSheetPanel.test.tsx +11 -1
  210. package/src/BottomSheet/BottomSheetPanel.tsx +49 -16
  211. package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +344 -0
  212. package/src/Button/__tests__/Button.a11y.chromium.spec.ts +17 -1
  213. package/src/Button/__tests__/Button.a11y.known-failures.ts +0 -29
  214. package/src/Button/__tests__/Button.a11y.renders.tsx +9 -2
  215. package/src/Button/__tests__/Button.a11y.states.ts +9 -0
  216. package/src/Chat/ChatComposer.doc.mjs +14 -0
  217. package/src/Chat/ChatComposer.spec.md +230 -0
  218. package/src/Chat/ChatComposer.test.tsx +57 -0
  219. package/src/Chat/ChatComposer.tsx +21 -9
  220. package/src/Chat/ChatComposerDrawer.doc.mjs +63 -5
  221. package/src/Chat/ChatComposerDrawer.spec.md +267 -0
  222. package/src/Chat/ChatComposerDrawer.test.tsx +81 -12
  223. package/src/Chat/ChatComposerDrawer.tsx +38 -9
  224. package/src/Chat/ChatComposerInput.doc.mjs +114 -26
  225. package/src/Chat/ChatComposerInput.spec.md +185 -0
  226. package/src/Chat/ChatComposerInput.test.tsx +113 -3
  227. package/src/Chat/ChatComposerInput.tsx +78 -13
  228. package/src/Chat/ChatComposerTokenElement.spec.md +152 -0
  229. package/src/Chat/ChatComposerTokenElement.test.tsx +85 -0
  230. package/src/Chat/ChatDictationButton.doc.mjs +3 -3
  231. package/src/Chat/ChatDictationButton.spec.md +160 -0
  232. package/src/Chat/ChatDictationButton.test.tsx +92 -27
  233. package/src/Chat/ChatDictationButton.tsx +8 -6
  234. package/src/Chat/ChatSendButton.test.tsx +1 -4
  235. package/src/Chat/ChatSendButton.tsx +1 -1
  236. package/src/Chat/index.ts +1 -0
  237. package/src/CheckboxInput/CheckboxInput.doc.mjs +11 -0
  238. package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
  239. package/src/CheckboxInput/CheckboxInput.tsx +21 -1
  240. package/src/ClickableCard/ClickableCard.test.tsx +102 -5
  241. package/src/Collapsible/Collapsible.doc.mjs +11 -0
  242. package/src/Collapsible/Collapsible.test.tsx +21 -0
  243. package/src/Collapsible/Collapsible.tsx +5 -0
  244. package/src/CommandPalette/CommandPaletteInput.tsx +6 -1
  245. package/src/ComplexSelector/ComplexSelector.tsx +6 -1
  246. package/src/DateInput/DateInput.tsx +6 -1
  247. package/src/DateInput/NativeDateField.tsx +24 -8
  248. package/src/DateInput/TouchDateField.tsx +6 -2
  249. package/src/DateRangeInput/DateRangeInput.tsx +6 -1
  250. package/src/DateTimeInput/DateTimeInput.tsx +6 -1
  251. package/src/DateTimeInput/TouchDateTimeField.tsx +6 -1
  252. package/src/DateTimeInput/nativePickerSegmentStyles.ts +24 -8
  253. package/src/Dialog/DialogHeader.doc.mjs +12 -0
  254. package/src/Dialog/DialogHeader.test.tsx +97 -0
  255. package/src/Dialog/DialogHeader.tsx +25 -3
  256. package/src/Dialog/modules/DialogHeader.spec.md +75 -38
  257. package/src/Field/InputClearButton.test.tsx +17 -3
  258. package/src/Field/InputClearButton.tsx +5 -2
  259. package/src/Field/PanelSearchInput.tsx +5 -2
  260. package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +1 -1
  261. package/src/FileInput/FileInput.tsx +11 -2
  262. package/src/Kbd/Kbd.doc.mjs +3 -3
  263. package/src/Kbd/Kbd.test.tsx +57 -1
  264. package/src/Kbd/Kbd.tsx +57 -37
  265. package/src/Layout/LayoutFooter.doc.mjs +17 -0
  266. package/src/Link/Link.doc.mjs +11 -0
  267. package/src/Link/Link.test.tsx +24 -0
  268. package/src/Link/Link.tsx +5 -0
  269. package/src/List/List.spec.md +200 -0
  270. package/src/Markdown/Markdown.doc.mjs +272 -0
  271. package/src/Markdown/Markdown.fr23.bench.ts +174 -0
  272. package/src/Markdown/Markdown.fr23.perf.test.ts +249 -0
  273. package/src/Markdown/Markdown.fr23.sampling.ts +49 -0
  274. package/src/Markdown/Markdown.helpers.perf.test.ts +489 -0
  275. package/src/Markdown/Markdown.public.test.ts +126 -3
  276. package/src/Markdown/Markdown.spec.md +197 -44
  277. package/src/Markdown/Markdown.test.tsx +11 -0
  278. package/src/Markdown/Markdown.tsx +414 -135
  279. package/src/Markdown/ast.test.ts +307 -0
  280. package/src/Markdown/ast.ts +337 -0
  281. package/src/Markdown/incremental.test.ts +12 -0
  282. package/src/Markdown/index.ts +37 -1
  283. package/src/Markdown/modules/remark.spec.md +269 -0
  284. package/src/Markdown/parser/index.ts +64 -0
  285. package/src/Markdown/parser.public.test.ts +103 -0
  286. package/src/Markdown/parser.ts +1180 -235
  287. package/src/Markdown/plugins/frontmatter.test.tsx +125 -0
  288. package/src/Markdown/plugins/frontmatter.ts +198 -0
  289. package/src/Markdown/plugins/index.ts +53 -0
  290. package/src/Markdown/plugins/protocol.test.tsx +1022 -0
  291. package/src/Markdown/plugins/protocol.ts +1618 -0
  292. package/src/Markdown/plugins/semanticFence.test.tsx +546 -0
  293. package/src/Markdown/plugins/semanticFence.ts +424 -0
  294. package/src/Markdown/plugins/sourceDecoration.test.tsx +799 -0
  295. package/src/Markdown/plugins/sourceDecoration.ts +539 -0
  296. package/src/Markdown/plugins/textTransform.test.ts +467 -0
  297. package/src/Markdown/plugins/textTransform.ts +554 -0
  298. package/src/Markdown/remark.test.tsx +1877 -0
  299. package/src/Markdown/remark.ts +1574 -0
  300. package/src/Markdown/url.ts +30 -0
  301. package/src/Markdown/utils.ts +13 -1
  302. package/src/MultiSelector/MultiSelector.test.tsx +1 -35
  303. package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +128 -0
  304. package/src/NumberInput/NumberInput.tsx +6 -1
  305. package/src/Outline/Outline.doc.mjs +7 -5
  306. package/src/Outline/Outline.spec.md +1 -1
  307. package/src/Outline/index.ts +1 -0
  308. package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +142 -0
  309. package/src/Outline/parseOutlineFromMarkdown.ts +40 -10
  310. package/src/Outline/useOutlineFromMarkdown.ts +15 -3
  311. package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
  312. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +150 -1
  313. package/src/PowerSearch/PowerSearchEditPopover.tsx +51 -28
  314. package/src/ProgressBar/ProgressBar.test.tsx +29 -11
  315. package/src/ProgressBar/ProgressBar.tsx +59 -72
  316. package/src/RadioList/RadioList.doc.mjs +11 -0
  317. package/src/RadioList/RadioList.test.tsx +32 -0
  318. package/src/RadioList/RadioListItem.tsx +25 -1
  319. package/src/ScrollableArea/modules/useScrollableArea.spec.md +50 -22
  320. package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
  321. package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
  322. package/src/SegmentedControl/SegmentedControlItem.tsx +6 -9
  323. package/src/Selector/Selector.doc.mjs +2 -2
  324. package/src/Selector/Selector.spec.md +51 -49
  325. package/src/Selector/Selector.test.tsx +61 -55
  326. package/src/Selector/Selector.tsx +23 -14
  327. package/src/Selector/__tests__/Listbox.a11y.chromium.spec.ts +130 -0
  328. package/src/Selector/__tests__/Listbox.a11y.dom.ts +38 -0
  329. package/src/Selector/__tests__/Listbox.a11y.inventory.test.ts +63 -0
  330. package/src/Selector/__tests__/Listbox.a11y.known-failures.ts +37 -0
  331. package/src/Selector/__tests__/Listbox.a11y.states.ts +232 -0
  332. package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +121 -0
  333. package/src/SideNav/SideNav.doc.mjs +1 -1
  334. package/src/SideNav/SideNav.test.tsx +10 -0
  335. package/src/SideNav/SideNav.tsx +14 -2
  336. package/src/Slider/Slider.doc.mjs +17 -3
  337. package/src/Slider/Slider.test.tsx +221 -0
  338. package/src/Slider/Slider.tsx +40 -9
  339. package/src/Spinner/Spinner.test.tsx +4 -0
  340. package/src/Spinner/Spinner.tsx +31 -18
  341. package/src/Switch/Switch.doc.mjs +11 -0
  342. package/src/Switch/Switch.test.tsx +16 -0
  343. package/src/Switch/Switch.tsx +28 -0
  344. package/src/TabList/Tab.tsx +35 -7
  345. package/src/TabList/TabList.doc.mjs +11 -0
  346. package/src/TabList/TabList.spec.md +204 -0
  347. package/src/TabList/TabList.test.tsx +66 -0
  348. package/src/TabList/__tests__/Tabs.a11y.known-failures.ts +1 -34
  349. package/src/Table/Table.doc.mjs +1 -1
  350. package/src/Table/Table.spec.md +54 -40
  351. package/src/Table/Table.test.tsx +83 -10
  352. package/src/Table/Table.tsx +30 -22
  353. package/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts +137 -0
  354. package/src/TextArea/TextArea.tsx +6 -1
  355. package/src/TextInput/TextInput.test.tsx +20 -1
  356. package/src/TextInput/TextInput.tsx +6 -1
  357. package/src/TimeInput/TimeInput.tsx +6 -1
  358. package/src/ToggleButton/ToggleButton.doc.mjs +3 -3
  359. package/src/ToggleButton/ToggleButton.test.tsx +299 -4
  360. package/src/ToggleButton/ToggleButton.tsx +26 -33
  361. package/src/ToggleButton/ToggleButtonGroup.doc.mjs +3 -3
  362. package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +209 -0
  363. package/src/Tokenizer/Tokenizer.spec.md +142 -75
  364. package/src/TreeList/TreeList.doc.mjs +3 -3
  365. package/src/TreeList/TreeList.spec.md +123 -75
  366. package/src/TreeList/TreeList.test.tsx +29 -0
  367. package/src/TreeList/TreeList.tsx +3 -0
  368. package/src/TreeList/TreeListItem.tsx +15 -1
  369. package/src/TreeList/TreeListTypes.ts +11 -1
  370. package/src/Typeahead/BaseTypeahead.spec.md +4 -3
  371. package/src/Typeahead/BaseTypeahead.tsx +21 -7
  372. package/src/Typeahead/Typeahead.test.tsx +53 -0
  373. package/src/__tests__/PressedState.a11y.chromium.spec.ts +813 -0
  374. package/src/__tests__/pressState.ts +93 -0
  375. package/src/hooks/scrollKeyboardDelegation.test.ts +155 -0
  376. package/src/hooks/scrollKeyboardDelegation.ts +233 -0
  377. package/src/hooks/useScrollableArea.doc.mjs +15 -3
  378. package/src/hooks/useScrollableArea.test.tsx +59 -1
  379. package/src/hooks/useScrollableArea.ts +34 -10
  380. package/src/inputFontFloor.test.ts +106 -0
  381. package/src/tailwind-theme.css +0 -6
  382. package/src/theme/generateThemeRules.test.ts +30 -0
  383. package/src/theme/generateThemeRules.ts +10 -0
  384. package/src/utils/interactionOverlay.stylex.ts +20 -0
@@ -141,6 +141,12 @@ export const docs = {
141
141
  'Alignment of prose content within the container when contentWidth is narrower than the available space.',
142
142
  default: "'start'",
143
143
  },
144
+ {
145
+ name: 'plugins',
146
+ type: 'readonly MarkdownPluginEntry[]',
147
+ description:
148
+ 'Ordered extensions created by createMarkdownPlugin(). Plugins may add bounded syntax, immutable typed AST transforms, and typed extension renderers. Use isMarkdownExtensionNode() to narrow extension data observed from other plugins. Renderer callbacks are pure; return a child component when hooks are needed. Omitted and empty lists preserve the released Markdown behavior.',
149
+ },
144
150
  {
145
151
  name: 'inlinePlugins',
146
152
  type: 'MarkdownInlinePlugin[]',
@@ -241,6 +247,41 @@ export const docs = {
241
247
  description:
242
248
  'Use contentWidth to keep prose at a readable line length in wide layouts.',
243
249
  },
250
+ {
251
+ guidance: true,
252
+ description:
253
+ 'Use plugins created by createMarkdownPlugin for reusable syntax, immutable AST transforms, and typed extension rendering. Keep the ordered list stable while its syntax configuration is unchanged.',
254
+ },
255
+ {
256
+ guidance: true,
257
+ description:
258
+ 'Use createMarkdownTextTransform for prose matching; it preserves code, links, images, citations, math, and accepted extension syntax as protected contexts. Provide requiredSubstrings only when they conservatively cover every possible match.',
259
+ },
260
+ {
261
+ guidance: true,
262
+ description:
263
+ 'Use createMarkdownFenceTransform for declared code-fence languages with semantic data. createNode returns an owned block extension node; its standard plugin renderer and toText own presentation. components.code still wins, and a declined or failed proposal keeps the accessible, copyable CodeBlock fallback.',
264
+ },
265
+ {
266
+ guidance: true,
267
+ description:
268
+ 'Use createMarkdownSourceDecoration to attach non-visual metadata — search hits, review annotations — to the blocks a source range touches, and getMarkdownSourceDecorations to read it back in a later plugin. Decorations appear on the settled document rather than on partial streaming chunks, and never change rendering, copyable text, accessible names, ids, focus order, or navigation.',
269
+ },
270
+ {
271
+ guidance: true,
272
+ description:
273
+ 'Import parseMarkdownAst or parseInlineAst from @astryxdesign/core/Markdown/parser when server or React Server Component code needs to run plugins against the canonical readonly tree. The parser and plugin subpaths have no use-client boundary. The Markdown component remains client-owned, so function-bearing plugin entries must not be passed across an RSC serialization boundary.',
274
+ },
275
+ {
276
+ guidance: true,
277
+ description:
278
+ 'Use createMarkdownFrontmatter for typed document metadata. Its parse() method gives the host metadata directly; its plugin removes a complete leading block before rendering and withholds an unfinished block during streaming.',
279
+ },
280
+ {
281
+ guidance: true,
282
+ description:
283
+ "Import createMarkdownRemarkTransform from '@astryxdesign/core/Markdown/remark' only to reuse an existing synchronous transform-only Remark plugin; it stays out of every other bundle. Prove each plugin with fixtures: anything outside the supported MDAST subset — async work, parser or compiler plugins, processor state, raw HTML, unsupported nodes, forged positions, or metadata Astryx cannot represent — keeps the last valid document and reports one diagnostic.",
284
+ },
244
285
  {
245
286
  guidance: true,
246
287
  description:
@@ -288,6 +329,159 @@ import {Text} from '@astryxdesign/core/Text';
288
329
  {'Visit https://example.com or email contact@example.com. ' +
289
330
  'You can also bracket links: <https://docs.example.com>.'}
290
331
  </Markdown>;
332
+ `,
333
+ },
334
+ {
335
+ label: 'Text transform helper',
336
+ code: `
337
+ import {Markdown} from '@astryxdesign/core/Markdown';
338
+ import {
339
+ createMarkdownPlugin,
340
+ createMarkdownTextTransform,
341
+ } from '@astryxdesign/core/Markdown/plugins';
342
+
343
+ const finalLabels = createMarkdownPlugin({
344
+ name: 'final-labels',
345
+ apiVersion: 1,
346
+ transform: createMarkdownTextTransform({
347
+ pattern: /\\bDraft\\b/g,
348
+ requiredSubstrings: ['Draft'],
349
+ replace: () => ({type: 'text', value: 'Final'}),
350
+ }),
351
+ });
352
+
353
+ <Markdown plugins={[finalLabels]}># Draft</Markdown>;
354
+ `,
355
+ },
356
+ {
357
+ label: 'Semantic fence helper',
358
+ code: `
359
+ import {Markdown} from '@astryxdesign/core/Markdown';
360
+ import {
361
+ createMarkdownFenceTransform,
362
+ createMarkdownPlugin,
363
+ type MarkdownExtensionNode,
364
+ } from '@astryxdesign/core/Markdown/plugins';
365
+
366
+ type DiagramNode = MarkdownExtensionNode<
367
+ 'diagrams',
368
+ 'diagram',
369
+ {readonly code: string; readonly label?: string},
370
+ 'block'
371
+ >;
372
+
373
+ const diagrams = createMarkdownPlugin<'diagrams', DiagramNode>({
374
+ name: 'diagrams',
375
+ apiVersion: 1,
376
+ transform: createMarkdownFenceTransform({
377
+ languages: ['mermaid'],
378
+ createNode: ({code, meta}) => ({
379
+ type: 'extension',
380
+ plugin: 'diagrams',
381
+ name: 'diagram',
382
+ display: 'block',
383
+ data: {code, ...(meta == null ? {} : {label: meta})},
384
+ }),
385
+ }),
386
+ renderers: {
387
+ diagram: {
388
+ render: ({node}) => (
389
+ <Diagram source={node.data.code} label={node.data.label} />
390
+ ),
391
+ toText: node => node.data.code,
392
+ },
393
+ },
394
+ });
395
+
396
+ <Markdown plugins={[diagrams]}>
397
+ {'\`\`\`mermaid Checkout flow\\ngraph LR; A-->B\\n\`\`\`'}
398
+ </Markdown>;
399
+ `,
400
+ },
401
+ {
402
+ label: 'Source decoration helper',
403
+ code: `
404
+ import {Markdown} from '@astryxdesign/core/Markdown';
405
+ import {
406
+ createMarkdownPlugin,
407
+ createMarkdownSourceDecoration,
408
+ getMarkdownSourceDecorations,
409
+ } from '@astryxdesign/core/Markdown/plugins';
410
+
411
+ // Ranges are UTF-16 offsets into the same string Markdown renders. Every
412
+ // block a range touches is annotated; rendering, copyable text, and ids
413
+ // never change.
414
+ const searchHits = createMarkdownPlugin({
415
+ name: 'search-hits',
416
+ apiVersion: 1,
417
+ transform: createMarkdownSourceDecoration({
418
+ name: 'search-hit',
419
+ ranges: [{start: 0, end: 15, data: {query: 'release'}}],
420
+ }),
421
+ });
422
+
423
+ const readDecorations = createMarkdownPlugin({
424
+ name: 'read-decorations',
425
+ apiVersion: 1,
426
+ transform: root => {
427
+ report(root.children.map(getMarkdownSourceDecorations));
428
+ return root;
429
+ },
430
+ });
431
+
432
+ <Markdown plugins={[searchHits, readDecorations]}>{source}</Markdown>;
433
+ `,
434
+ },
435
+ {
436
+ label: 'Native frontmatter',
437
+ code: `
438
+ import {Markdown} from '@astryxdesign/core/Markdown';
439
+ import {createMarkdownFrontmatter} from '@astryxdesign/core/Markdown/plugins';
440
+
441
+ const frontmatter = createMarkdownFrontmatter({
442
+ name: 'document-metadata',
443
+ parse: fields => ({
444
+ title: fields.title ?? 'Untitled',
445
+ draft: fields.draft === 'true',
446
+ }),
447
+ });
448
+
449
+ const source = '---\\ntitle: Release notes\\ndraft: true\\n---\\n# Shipped';
450
+ const result = frontmatter.parse(source);
451
+
452
+ <Markdown plugins={[frontmatter.plugin]}>{source}</Markdown>;
453
+ `,
454
+ },
455
+ {
456
+ label: 'Compatible Remark plugin',
457
+ code: `
458
+ import {Markdown} from '@astryxdesign/core/Markdown';
459
+ import {createMarkdownPlugin} from '@astryxdesign/core/Markdown/plugins';
460
+ import {createMarkdownRemarkTransform} from '@astryxdesign/core/Markdown/remark';
461
+
462
+ // A synchronous transform-only Remark plugin in the usual attacher shape.
463
+ const remarkRename =
464
+ ({from, to}) =>
465
+ tree => {
466
+ const rename = node => {
467
+ if (node.type === 'text') {
468
+ node.value = node.value.split(from).join(to);
469
+ }
470
+ node.children?.forEach(rename);
471
+ };
472
+ rename(tree);
473
+ };
474
+
475
+ const productName = createMarkdownPlugin({
476
+ name: 'product-name',
477
+ apiVersion: 1,
478
+ transform: createMarkdownRemarkTransform(remarkRename, {
479
+ from: 'Astryx',
480
+ to: 'Astryx Design',
481
+ }),
482
+ });
483
+
484
+ <Markdown plugins={[productName]}># Astryx release notes</Markdown>;
291
485
  `,
292
486
  },
293
487
  {
@@ -397,6 +591,12 @@ export const docsZh = {
397
591
  '当 contentWidth 小于可用空间时,正文内容在容器内的对齐方式。',
398
592
  default: "'start'",
399
593
  },
594
+ {
595
+ name: 'plugins',
596
+ type: 'readonly MarkdownPluginEntry[]',
597
+ description:
598
+ '由 createMarkdownPlugin() 创建的有序扩展。插件可添加有界语法、不可变的类型化 AST 转换和类型化扩展渲染器。使用 isMarkdownExtensionNode() 缩小从其他插件观察到的扩展数据类型。渲染回调必须是纯函数;需要 Hook 时请返回子组件。省略或传入空列表时保持已发布的 Markdown 行为。',
599
+ },
400
600
  {
401
601
  name: 'inlinePlugins',
402
602
  type: 'MarkdownInlinePlugin[]',
@@ -507,6 +707,41 @@ export const docsZh = {
507
707
  description:
508
708
  'Use contentWidth to keep prose at a readable line length in wide layouts.',
509
709
  },
710
+ {
711
+ guidance: true,
712
+ description:
713
+ 'Use plugins created by createMarkdownPlugin for reusable syntax, immutable AST transforms, and typed extension rendering. Keep the ordered list stable while its syntax configuration is unchanged.',
714
+ },
715
+ {
716
+ guidance: true,
717
+ description:
718
+ 'Use createMarkdownTextTransform for prose matching; it preserves code, links, images, citations, math, and accepted extension syntax as protected contexts. Provide requiredSubstrings only when they conservatively cover every possible match.',
719
+ },
720
+ {
721
+ guidance: true,
722
+ description:
723
+ 'Use createMarkdownFenceTransform for declared code-fence languages with semantic data. createNode returns an owned block extension node; its standard plugin renderer and toText own presentation. components.code still wins, and a declined or failed proposal keeps the accessible, copyable CodeBlock fallback.',
724
+ },
725
+ {
726
+ guidance: true,
727
+ description:
728
+ 'Use createMarkdownSourceDecoration to attach non-visual metadata — search hits, review annotations — to the blocks a source range touches, and getMarkdownSourceDecorations to read it back in a later plugin. Decorations appear on the settled document rather than on partial streaming chunks, and never change rendering, copyable text, accessible names, ids, focus order, or navigation.',
729
+ },
730
+ {
731
+ guidance: true,
732
+ description:
733
+ 'Import parseMarkdownAst or parseInlineAst from @astryxdesign/core/Markdown/parser when server or React Server Component code needs to run plugins against the canonical readonly tree. The parser and plugin subpaths have no use-client boundary. The Markdown component remains client-owned, so function-bearing plugin entries must not be passed across an RSC serialization boundary.',
734
+ },
735
+ {
736
+ guidance: true,
737
+ description:
738
+ 'Use createMarkdownFrontmatter for typed document metadata. Its parse() method gives the host metadata directly; its plugin removes a complete leading block before rendering and withholds an unfinished block during streaming.',
739
+ },
740
+ {
741
+ guidance: true,
742
+ description:
743
+ "Import createMarkdownRemarkTransform from '@astryxdesign/core/Markdown/remark' only to reuse an existing synchronous transform-only Remark plugin; it stays out of every other bundle. Prove each plugin with fixtures: anything outside the supported MDAST subset — async work, parser or compiler plugins, processor state, raw HTML, unsupported nodes, forged positions, or metadata Astryx cannot represent — keeps the last valid document and reports one diagnostic.",
744
+ },
510
745
  {
511
746
  guidance: true,
512
747
  description:
@@ -554,6 +789,41 @@ export const docsDense = {
554
789
  description:
555
790
  'Use contentWidth to keep prose at a readable line length in wide layouts.',
556
791
  },
792
+ {
793
+ guidance: true,
794
+ description:
795
+ 'Use plugins created by createMarkdownPlugin for reusable syntax, immutable AST transforms, and typed extension rendering. Keep the ordered list stable while its syntax configuration is unchanged.',
796
+ },
797
+ {
798
+ guidance: true,
799
+ description:
800
+ 'Use createMarkdownTextTransform for prose matching; it preserves code, links, images, citations, math, and accepted extension syntax as protected contexts. Provide requiredSubstrings only when they conservatively cover every possible match.',
801
+ },
802
+ {
803
+ guidance: true,
804
+ description:
805
+ 'Use createMarkdownFenceTransform for declared code-fence languages with semantic data. createNode returns an owned block extension node; its standard plugin renderer and toText own presentation. components.code still wins, and a declined or failed proposal keeps the accessible, copyable CodeBlock fallback.',
806
+ },
807
+ {
808
+ guidance: true,
809
+ description:
810
+ 'Use createMarkdownSourceDecoration to attach non-visual metadata — search hits, review annotations — to the blocks a source range touches, and getMarkdownSourceDecorations to read it back in a later plugin. Decorations appear on the settled document rather than on partial streaming chunks, and never change rendering, copyable text, accessible names, ids, focus order, or navigation.',
811
+ },
812
+ {
813
+ guidance: true,
814
+ description:
815
+ 'Import parseMarkdownAst or parseInlineAst from @astryxdesign/core/Markdown/parser when server or React Server Component code needs to run plugins against the canonical readonly tree. The parser and plugin subpaths have no use-client boundary. The Markdown component remains client-owned, so function-bearing plugin entries must not be passed across an RSC serialization boundary.',
816
+ },
817
+ {
818
+ guidance: true,
819
+ description:
820
+ 'Use createMarkdownFrontmatter for typed document metadata. Its parse() method gives the host metadata directly; its plugin removes a complete leading block before rendering and withholds an unfinished block during streaming.',
821
+ },
822
+ {
823
+ guidance: true,
824
+ description:
825
+ "Import createMarkdownRemarkTransform from '@astryxdesign/core/Markdown/remark' only to reuse a synchronous transform-only Remark plugin; it stays out of every other bundle and unsupported behavior keeps the last valid document with one diagnostic.",
826
+ },
557
827
  {
558
828
  guidance: true,
559
829
  description:
@@ -598,6 +868,8 @@ export const docsDense = {
598
868
  'number|string. Max width for prose (headings, paragraphs, lists). Tables/code unconstrained.',
599
869
  contentAlign:
600
870
  "'start'|'center'. Prose alignment when contentWidth < container. Default: 'start'.",
871
+ plugins:
872
+ 'readonly MarkdownPluginEntry[]. Ordered syntax, immutable AST transforms, and typed extension renderers from createMarkdownPlugin(). Narrow observed extensions with isMarkdownExtensionNode(); renderer callbacks are pure. Default: omitted or empty.',
601
873
  inlinePlugins:
602
874
  'MarkdownInlinePlugin[]. Regex matches in text nodes -> custom inline React elements. Skips inline/fenced code and math.',
603
875
  autolink:
@@ -0,0 +1,174 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Markdown.fr23.bench.ts
5
+ * @input The AST-036 fixture document and the representative helper set
6
+ * @output One JSON line of FR23 ratios on stdout, for the harness that spawns it
7
+ * @position Benchmark body for Markdown.fr23.perf.test.ts; not a test itself
8
+ *
9
+ * Run as its own process, one measurement at a time, by
10
+ * `Markdown.fr23.perf.test.ts`. The fresh process isolates engine state left
11
+ * behind by other plugin configurations. The harness must also run separately
12
+ * from other tests: a child process still shares machine resources, and CPU
13
+ * time does not remove cache or memory-bandwidth contention.
14
+ *
15
+ * The timed region is exactly the spec's protocol — ten untimed warmups,
16
+ * then nine alternating paired rounds averaging 20 iterations a side,
17
+ * reported as the median of the nine paired ratios — against the omitted
18
+ * baseline, for a stable list and a recreated equivalent one. Each ratio
19
+ * comes from one sample, never a selection by the fastest baseline.
20
+ *
21
+ * The harness retries a fresh process only when the A/A control is invalid.
22
+ * A helper-overhead failure is never retried to obtain a passing sample.
23
+ */
24
+
25
+ import {measureMarkdownPairedRatio} from './Markdown.fr23.sampling';
26
+ import {parseMarkdown} from './parser';
27
+ import {createMarkdownPlugin} from './plugins';
28
+ import type {MarkdownExtensionNode} from './plugins';
29
+ import {createMarkdownFenceTransform} from './plugins/semanticFence';
30
+ import {createMarkdownSourceDecoration} from './plugins/sourceDecoration';
31
+ import {createMarkdownTextTransform} from './plugins/textTransform';
32
+
33
+ let benchmarkSink = 0;
34
+
35
+ /** The fixture `spec:AST-036`'s performance evidence protocol describes. */
36
+ function benchmarkDocument(sections: number): string {
37
+ return Array.from({length: sections}, (_, index) =>
38
+ [
39
+ `## Section ${index}`,
40
+ '',
41
+ `AST-${index} belongs to @{owner-${index}} with TODO follow-up.`,
42
+ '',
43
+ `- First item ${index}`,
44
+ '- Second item',
45
+ '',
46
+ `> Quoted detail ${index}`,
47
+ '',
48
+ '| Item | Detail |',
49
+ '| --- | --- |',
50
+ `| ${index} | ordinary prose |`,
51
+ '',
52
+ '```text',
53
+ `opaque ${index}`,
54
+ '```',
55
+ ].join('\n'),
56
+ ).join('\n\n');
57
+ }
58
+
59
+ /** Matches a prose identifier in every fixture section. */
60
+ const identifierPlugin = createMarkdownPlugin({
61
+ name: 'representative-identifiers',
62
+ apiVersion: 1,
63
+ transform: createMarkdownTextTransform({
64
+ pattern: /\bAST-\d+\b/g,
65
+ requiredSubstrings: ['AST-'],
66
+ replace: match => ({type: 'text', value: match[0].toLowerCase()}),
67
+ }),
68
+ });
69
+
70
+ /** Turns the ordinary text fence each fixture section carries into data. */
71
+ type PerfFenceNode = MarkdownExtensionNode<
72
+ 'representative-fences',
73
+ 'fence',
74
+ {readonly code: string},
75
+ 'block'
76
+ >;
77
+
78
+ const fencePlugin = createMarkdownPlugin<
79
+ 'representative-fences',
80
+ PerfFenceNode
81
+ >({
82
+ name: 'representative-fences',
83
+ apiVersion: 1,
84
+ transform: createMarkdownFenceTransform<readonly ['text'], PerfFenceNode>({
85
+ languages: ['text'],
86
+ createNode: ({code}) => ({
87
+ type: 'extension',
88
+ plugin: 'representative-fences',
89
+ name: 'fence',
90
+ display: 'block',
91
+ data: {code},
92
+ }),
93
+ }),
94
+ renderers: {
95
+ fence: {
96
+ render: ({node}) => node.data.code,
97
+ toText: node => node.data.code,
98
+ },
99
+ },
100
+ });
101
+
102
+ /** Decorates one known source range: the first section heading. */
103
+ function knownRangeDecorationPlugin(source: string) {
104
+ const heading = source.indexOf('## Section 0');
105
+ return createMarkdownPlugin({
106
+ name: 'representative-decoration',
107
+ apiVersion: 1,
108
+ transform: createMarkdownSourceDecoration({
109
+ name: 'representative-decoration',
110
+ ranges: [{start: heading, end: heading + '## Section 0'.length}],
111
+ }),
112
+ });
113
+ }
114
+
115
+ /**
116
+ * Brings the whole pipeline to steady state before anything is measured.
117
+ *
118
+ * The spec's ten warmups precede each measurement, but they are not enough
119
+ * for the FIRST one in a fresh process: the parser, the helpers and the
120
+ * protocol are all still being optimized, so whichever side is measured
121
+ * first carries the cold-start cost. Left alone this reliably inflated
122
+ * `stable` — the first of the two — while `recreated`, run moments later on
123
+ * a hot engine, sat where the real cost is. Priming both configurations
124
+ * here removes that ordering bias; it changes nothing inside the timed
125
+ * region, which is still ten warmups and one nine-pair median.
126
+ */
127
+ function primePipeline(
128
+ configurations: ReadonlyArray<() => number>,
129
+ rounds = 40,
130
+ ): void {
131
+ for (let round = 0; round < rounds; round++) {
132
+ for (const run of configurations) {
133
+ benchmarkSink ^= run();
134
+ }
135
+ }
136
+ void benchmarkSink;
137
+ }
138
+
139
+ function measure(sections: number): {
140
+ stable: number;
141
+ recreated: number;
142
+ control: number;
143
+ } {
144
+ const source = benchmarkDocument(sections);
145
+ const representative = [
146
+ identifierPlugin,
147
+ fencePlugin,
148
+ knownRangeDecorationPlugin(source),
149
+ ];
150
+ const empty = () => parseMarkdown(source).length;
151
+ const withStableList = () =>
152
+ parseMarkdown(source, {plugins: representative}).length;
153
+ const withRecreatedList = () =>
154
+ parseMarkdown(source, {plugins: [...representative]}).length;
155
+ primePipeline([empty, withStableList, withRecreatedList]);
156
+ // The A/A control measures identical work. Only a failed control can
157
+ // invalidate this sample; neither helper ratio participates in selection.
158
+ const control = measureMarkdownPairedRatio(empty, empty);
159
+ return {
160
+ stable: measureMarkdownPairedRatio(empty, withStableList),
161
+ recreated: measureMarkdownPairedRatio(empty, withRecreatedList),
162
+ control,
163
+ };
164
+ }
165
+
166
+ const sections = Number(process.argv[2]);
167
+ if (!Number.isInteger(sections) || sections <= 0) {
168
+ console.error(`Expected a section count, received ${process.argv[2]}`);
169
+ process.exit(2);
170
+ }
171
+ // One line on stdout, so the harness can tell a real result from a crash.
172
+ // `process.stdout.write` rather than `console.log`: this file is a
173
+ // benchmark binary, not a module that should be logging.
174
+ process.stdout.write(`${JSON.stringify({sections, ...measure(sections)})}\n`);