@promptctl/rich-js 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (410) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +20 -110
  3. package/THIRD-PARTY-NOTICES +81 -0
  4. package/dist/core/box.d.ts +0 -1
  5. package/dist/core/box.js +0 -1
  6. package/dist/core/cells.d.ts +0 -1
  7. package/dist/core/cells.js +0 -1
  8. package/dist/core/color.d.ts +6 -1
  9. package/dist/core/color.js +6 -1
  10. package/dist/core/console.d.ts +13 -4
  11. package/dist/core/console.js +78 -87
  12. package/dist/core/emoji.d.ts +0 -1
  13. package/dist/core/emoji.js +0 -1
  14. package/dist/core/export-html.d.ts +24 -0
  15. package/dist/core/export-html.js +106 -0
  16. package/dist/core/export-lines.d.ts +121 -0
  17. package/dist/core/export-lines.js +141 -0
  18. package/dist/core/highlighter.d.ts +0 -1
  19. package/dist/core/highlighter.js +0 -1
  20. package/dist/core/json.d.ts +0 -1
  21. package/dist/core/json.js +0 -1
  22. package/dist/core/markup.d.ts +33 -2
  23. package/dist/core/markup.js +128 -16
  24. package/dist/core/measure.d.ts +0 -1
  25. package/dist/core/measure.js +0 -1
  26. package/dist/core/oklch.d.ts +34 -1
  27. package/dist/core/oklch.js +52 -5
  28. package/dist/core/osc8.d.ts +68 -0
  29. package/dist/core/osc8.js +90 -0
  30. package/dist/core/pretty.d.ts +21 -2
  31. package/dist/core/pretty.js +90 -16
  32. package/dist/core/protocol.d.ts +18 -2
  33. package/dist/core/protocol.js +0 -1
  34. package/dist/core/render.d.ts +0 -1
  35. package/dist/core/render.js +3 -10
  36. package/dist/core/segment.d.ts +0 -1
  37. package/dist/core/segment.js +0 -1
  38. package/dist/core/spinnerData.d.ts +0 -1
  39. package/dist/core/spinnerData.js +0 -1
  40. package/dist/core/strip.d.ts +19 -3
  41. package/dist/core/strip.js +58 -11
  42. package/dist/core/style.d.ts +3 -8
  43. package/dist/core/style.js +85 -68
  44. package/dist/core/subscription.d.ts +0 -1
  45. package/dist/core/subscription.js +0 -1
  46. package/dist/core/text.d.ts +1 -8
  47. package/dist/core/text.js +28 -31
  48. package/dist/core/wrap.d.ts +0 -1
  49. package/dist/core/wrap.js +0 -1
  50. package/dist/host/host-stream.d.ts +0 -1
  51. package/dist/host/host-stream.js +0 -1
  52. package/dist/host/index.d.ts +0 -1
  53. package/dist/host/index.js +0 -1
  54. package/dist/host/terminal-host.d.ts +0 -1
  55. package/dist/host/terminal-host.js +0 -1
  56. package/dist/index.d.ts +6 -5
  57. package/dist/index.js +4 -3
  58. package/dist/node/prompt.d.ts +0 -1
  59. package/dist/node/prompt.js +0 -1
  60. package/dist/node/save.d.ts +2 -7
  61. package/dist/node/save.js +0 -1
  62. package/dist/node/terminal-host.d.ts +0 -1
  63. package/dist/node/terminal-host.js +0 -1
  64. package/dist/node/traceback.d.ts +0 -1
  65. package/dist/node/traceback.js +0 -1
  66. package/dist/renderables/align.d.ts +0 -1
  67. package/dist/renderables/align.js +0 -1
  68. package/dist/renderables/columns.d.ts +12 -1
  69. package/dist/renderables/columns.js +29 -5
  70. package/dist/renderables/constrain.d.ts +0 -1
  71. package/dist/renderables/constrain.js +0 -1
  72. package/dist/renderables/flexStrip.d.ts +0 -1
  73. package/dist/renderables/flexStrip.js +0 -1
  74. package/dist/renderables/group.d.ts +0 -1
  75. package/dist/renderables/group.js +0 -1
  76. package/dist/renderables/layout.d.ts +0 -1
  77. package/dist/renderables/layout.js +20 -7
  78. package/dist/renderables/live.d.ts +0 -1
  79. package/dist/renderables/live.js +0 -1
  80. package/dist/renderables/markdown.d.ts +0 -1
  81. package/dist/renderables/markdown.js +0 -1
  82. package/dist/renderables/padding.d.ts +0 -1
  83. package/dist/renderables/padding.js +0 -1
  84. package/dist/renderables/panel.d.ts +0 -1
  85. package/dist/renderables/panel.js +12 -4
  86. package/dist/renderables/progress.d.ts +0 -1
  87. package/dist/renderables/progress.js +7 -2
  88. package/dist/renderables/progressBar.d.ts +0 -1
  89. package/dist/renderables/progressBar.js +0 -1
  90. package/dist/renderables/prompt.d.ts +0 -1
  91. package/dist/renderables/prompt.js +0 -1
  92. package/dist/renderables/rule.d.ts +0 -1
  93. package/dist/renderables/rule.js +0 -1
  94. package/dist/renderables/spinner.d.ts +0 -1
  95. package/dist/renderables/spinner.js +0 -1
  96. package/dist/renderables/status.d.ts +0 -1
  97. package/dist/renderables/status.js +0 -1
  98. package/dist/renderables/syntax.d.ts +0 -1
  99. package/dist/renderables/syntax.js +0 -1
  100. package/dist/renderables/table.d.ts +0 -1
  101. package/dist/renderables/table.js +8 -3
  102. package/dist/renderables/traceback.d.ts +8 -7
  103. package/dist/renderables/traceback.js +14 -10
  104. package/dist/renderables/tree.d.ts +0 -1
  105. package/dist/renderables/tree.js +0 -1
  106. package/dist/template-bindings/color-funcs.d.ts +0 -1
  107. package/dist/template-bindings/color-funcs.js +0 -1
  108. package/dist/template-bindings/helpers.d.ts +0 -1
  109. package/dist/template-bindings/helpers.js +0 -1
  110. package/dist/template-bindings/index.d.ts +0 -1
  111. package/dist/template-bindings/index.js +0 -1
  112. package/dist/template-bindings/palette-funcs.d.ts +0 -1
  113. package/dist/template-bindings/palette-funcs.js +0 -1
  114. package/dist/template-bindings/style-funcs.d.ts +0 -1
  115. package/dist/template-bindings/style-funcs.js +0 -1
  116. package/dist/themes/buildPalette.d.ts +0 -1
  117. package/dist/themes/buildPalette.js +0 -1
  118. package/dist/themes/colorMath.d.ts +0 -1
  119. package/dist/themes/colorMath.js +0 -1
  120. package/dist/themes/colorRef.d.ts +0 -1
  121. package/dist/themes/colorRef.js +0 -1
  122. package/dist/themes/data/atom-one-dark.d.ts +0 -1
  123. package/dist/themes/data/atom-one-dark.js +0 -1
  124. package/dist/themes/data/atom-one-light.d.ts +0 -1
  125. package/dist/themes/data/atom-one-light.js +0 -1
  126. package/dist/themes/data/catppuccin-frappe.d.ts +0 -1
  127. package/dist/themes/data/catppuccin-frappe.js +0 -1
  128. package/dist/themes/data/catppuccin-latte.d.ts +0 -1
  129. package/dist/themes/data/catppuccin-latte.js +0 -1
  130. package/dist/themes/data/catppuccin-macchiato.d.ts +0 -1
  131. package/dist/themes/data/catppuccin-macchiato.js +0 -1
  132. package/dist/themes/data/catppuccin-mocha.d.ts +0 -1
  133. package/dist/themes/data/catppuccin-mocha.js +0 -1
  134. package/dist/themes/data/cyberpunk.d.ts +0 -1
  135. package/dist/themes/data/cyberpunk.js +0 -1
  136. package/dist/themes/data/default.d.ts +0 -1
  137. package/dist/themes/data/default.js +0 -1
  138. package/dist/themes/data/dracula.d.ts +0 -1
  139. package/dist/themes/data/dracula.js +0 -1
  140. package/dist/themes/data/flexoki.d.ts +0 -1
  141. package/dist/themes/data/flexoki.js +0 -1
  142. package/dist/themes/data/gruvbox.d.ts +0 -1
  143. package/dist/themes/data/gruvbox.js +0 -1
  144. package/dist/themes/data/index.d.ts +0 -1
  145. package/dist/themes/data/index.js +0 -1
  146. package/dist/themes/data/monokai.d.ts +0 -1
  147. package/dist/themes/data/monokai.js +0 -1
  148. package/dist/themes/data/nord.d.ts +0 -1
  149. package/dist/themes/data/nord.js +0 -1
  150. package/dist/themes/data/rose-pine-dawn.d.ts +0 -1
  151. package/dist/themes/data/rose-pine-dawn.js +0 -1
  152. package/dist/themes/data/rose-pine-moon.d.ts +0 -1
  153. package/dist/themes/data/rose-pine-moon.js +0 -1
  154. package/dist/themes/data/rose-pine.d.ts +0 -1
  155. package/dist/themes/data/rose-pine.js +0 -1
  156. package/dist/themes/data/solarized-dark.d.ts +0 -1
  157. package/dist/themes/data/solarized-dark.js +0 -1
  158. package/dist/themes/data/solarized-light.d.ts +0 -1
  159. package/dist/themes/data/solarized-light.js +0 -1
  160. package/dist/themes/data/svg-export.d.ts +0 -1
  161. package/dist/themes/data/svg-export.js +0 -1
  162. package/dist/themes/data/textual-ansi.d.ts +0 -1
  163. package/dist/themes/data/textual-ansi.js +0 -1
  164. package/dist/themes/data/textual-dark.d.ts +0 -1
  165. package/dist/themes/data/textual-dark.js +0 -1
  166. package/dist/themes/data/textual-light.d.ts +0 -1
  167. package/dist/themes/data/textual-light.js +0 -1
  168. package/dist/themes/data/tokyo-night.d.ts +0 -1
  169. package/dist/themes/data/tokyo-night.js +0 -1
  170. package/dist/themes/data/types.d.ts +0 -1
  171. package/dist/themes/data/types.js +0 -1
  172. package/dist/themes/palette.d.ts +0 -1
  173. package/dist/themes/palette.js +0 -1
  174. package/dist/themes/ramp.d.ts +0 -1
  175. package/dist/themes/ramp.js +0 -1
  176. package/dist/themes/registry.d.ts +0 -1
  177. package/dist/themes/registry.js +0 -1
  178. package/dist/themes/terminalThemes.d.ts +0 -1
  179. package/dist/themes/terminalThemes.js +0 -1
  180. package/dist/themes/transpose.d.ts +0 -1
  181. package/dist/themes/transpose.js +0 -1
  182. package/dist/widgets/button.d.ts +0 -1
  183. package/dist/widgets/button.js +0 -1
  184. package/dist/widgets/checkbox.d.ts +0 -1
  185. package/dist/widgets/checkbox.js +0 -1
  186. package/dist/widgets/dropdown.d.ts +0 -1
  187. package/dist/widgets/dropdown.js +0 -1
  188. package/dist/widgets/event-router.d.ts +0 -1
  189. package/dist/widgets/event-router.js +0 -1
  190. package/dist/widgets/focus-manager.d.ts +0 -1
  191. package/dist/widgets/focus-manager.js +0 -1
  192. package/dist/widgets/index.d.ts +0 -1
  193. package/dist/widgets/index.js +0 -1
  194. package/dist/widgets/screen.d.ts +0 -1
  195. package/dist/widgets/screen.js +0 -1
  196. package/dist/widgets/slider.d.ts +0 -1
  197. package/dist/widgets/slider.js +0 -1
  198. package/dist/widgets/static-item.d.ts +0 -1
  199. package/dist/widgets/static-item.js +0 -1
  200. package/dist/widgets/text-input.d.ts +0 -1
  201. package/dist/widgets/text-input.js +0 -1
  202. package/dist/widgets/toggle.d.ts +0 -1
  203. package/dist/widgets/toggle.js +0 -1
  204. package/dist/widgets/types.d.ts +0 -1
  205. package/dist/widgets/types.js +0 -1
  206. package/dist/widgets/widget-base.d.ts +0 -1
  207. package/dist/widgets/widget-base.js +0 -1
  208. package/package.json +4 -3
  209. package/dist/core/box.d.ts.map +0 -1
  210. package/dist/core/box.js.map +0 -1
  211. package/dist/core/cells.d.ts.map +0 -1
  212. package/dist/core/cells.js.map +0 -1
  213. package/dist/core/color.d.ts.map +0 -1
  214. package/dist/core/color.js.map +0 -1
  215. package/dist/core/console.d.ts.map +0 -1
  216. package/dist/core/console.js.map +0 -1
  217. package/dist/core/emoji.d.ts.map +0 -1
  218. package/dist/core/emoji.js.map +0 -1
  219. package/dist/core/highlighter.d.ts.map +0 -1
  220. package/dist/core/highlighter.js.map +0 -1
  221. package/dist/core/json.d.ts.map +0 -1
  222. package/dist/core/json.js.map +0 -1
  223. package/dist/core/markup.d.ts.map +0 -1
  224. package/dist/core/markup.js.map +0 -1
  225. package/dist/core/measure.d.ts.map +0 -1
  226. package/dist/core/measure.js.map +0 -1
  227. package/dist/core/oklch.d.ts.map +0 -1
  228. package/dist/core/oklch.js.map +0 -1
  229. package/dist/core/pretty.d.ts.map +0 -1
  230. package/dist/core/pretty.js.map +0 -1
  231. package/dist/core/protocol.d.ts.map +0 -1
  232. package/dist/core/protocol.js.map +0 -1
  233. package/dist/core/render.d.ts.map +0 -1
  234. package/dist/core/render.js.map +0 -1
  235. package/dist/core/sanitize.d.ts +0 -16
  236. package/dist/core/sanitize.d.ts.map +0 -1
  237. package/dist/core/sanitize.js +0 -19
  238. package/dist/core/sanitize.js.map +0 -1
  239. package/dist/core/segment.d.ts.map +0 -1
  240. package/dist/core/segment.js.map +0 -1
  241. package/dist/core/spinnerData.d.ts.map +0 -1
  242. package/dist/core/spinnerData.js.map +0 -1
  243. package/dist/core/strip.d.ts.map +0 -1
  244. package/dist/core/strip.js.map +0 -1
  245. package/dist/core/style.d.ts.map +0 -1
  246. package/dist/core/style.js.map +0 -1
  247. package/dist/core/subscription.d.ts.map +0 -1
  248. package/dist/core/subscription.js.map +0 -1
  249. package/dist/core/text.d.ts.map +0 -1
  250. package/dist/core/text.js.map +0 -1
  251. package/dist/core/wrap.d.ts.map +0 -1
  252. package/dist/core/wrap.js.map +0 -1
  253. package/dist/host/host-stream.d.ts.map +0 -1
  254. package/dist/host/host-stream.js.map +0 -1
  255. package/dist/host/index.d.ts.map +0 -1
  256. package/dist/host/index.js.map +0 -1
  257. package/dist/host/terminal-host.d.ts.map +0 -1
  258. package/dist/host/terminal-host.js.map +0 -1
  259. package/dist/index.d.ts.map +0 -1
  260. package/dist/index.js.map +0 -1
  261. package/dist/node/prompt.d.ts.map +0 -1
  262. package/dist/node/prompt.js.map +0 -1
  263. package/dist/node/save.d.ts.map +0 -1
  264. package/dist/node/save.js.map +0 -1
  265. package/dist/node/terminal-host.d.ts.map +0 -1
  266. package/dist/node/terminal-host.js.map +0 -1
  267. package/dist/node/traceback.d.ts.map +0 -1
  268. package/dist/node/traceback.js.map +0 -1
  269. package/dist/renderables/align.d.ts.map +0 -1
  270. package/dist/renderables/align.js.map +0 -1
  271. package/dist/renderables/columns.d.ts.map +0 -1
  272. package/dist/renderables/columns.js.map +0 -1
  273. package/dist/renderables/constrain.d.ts.map +0 -1
  274. package/dist/renderables/constrain.js.map +0 -1
  275. package/dist/renderables/flexStrip.d.ts.map +0 -1
  276. package/dist/renderables/flexStrip.js.map +0 -1
  277. package/dist/renderables/group.d.ts.map +0 -1
  278. package/dist/renderables/group.js.map +0 -1
  279. package/dist/renderables/layout.d.ts.map +0 -1
  280. package/dist/renderables/layout.js.map +0 -1
  281. package/dist/renderables/live.d.ts.map +0 -1
  282. package/dist/renderables/live.js.map +0 -1
  283. package/dist/renderables/markdown.d.ts.map +0 -1
  284. package/dist/renderables/markdown.js.map +0 -1
  285. package/dist/renderables/padding.d.ts.map +0 -1
  286. package/dist/renderables/padding.js.map +0 -1
  287. package/dist/renderables/panel.d.ts.map +0 -1
  288. package/dist/renderables/panel.js.map +0 -1
  289. package/dist/renderables/progress.d.ts.map +0 -1
  290. package/dist/renderables/progress.js.map +0 -1
  291. package/dist/renderables/progressBar.d.ts.map +0 -1
  292. package/dist/renderables/progressBar.js.map +0 -1
  293. package/dist/renderables/prompt.d.ts.map +0 -1
  294. package/dist/renderables/prompt.js.map +0 -1
  295. package/dist/renderables/rule.d.ts.map +0 -1
  296. package/dist/renderables/rule.js.map +0 -1
  297. package/dist/renderables/spinner.d.ts.map +0 -1
  298. package/dist/renderables/spinner.js.map +0 -1
  299. package/dist/renderables/status.d.ts.map +0 -1
  300. package/dist/renderables/status.js.map +0 -1
  301. package/dist/renderables/syntax.d.ts.map +0 -1
  302. package/dist/renderables/syntax.js.map +0 -1
  303. package/dist/renderables/table.d.ts.map +0 -1
  304. package/dist/renderables/table.js.map +0 -1
  305. package/dist/renderables/traceback.d.ts.map +0 -1
  306. package/dist/renderables/traceback.js.map +0 -1
  307. package/dist/renderables/tree.d.ts.map +0 -1
  308. package/dist/renderables/tree.js.map +0 -1
  309. package/dist/template-bindings/color-funcs.d.ts.map +0 -1
  310. package/dist/template-bindings/color-funcs.js.map +0 -1
  311. package/dist/template-bindings/helpers.d.ts.map +0 -1
  312. package/dist/template-bindings/helpers.js.map +0 -1
  313. package/dist/template-bindings/index.d.ts.map +0 -1
  314. package/dist/template-bindings/index.js.map +0 -1
  315. package/dist/template-bindings/palette-funcs.d.ts.map +0 -1
  316. package/dist/template-bindings/palette-funcs.js.map +0 -1
  317. package/dist/template-bindings/style-funcs.d.ts.map +0 -1
  318. package/dist/template-bindings/style-funcs.js.map +0 -1
  319. package/dist/themes/buildPalette.d.ts.map +0 -1
  320. package/dist/themes/buildPalette.js.map +0 -1
  321. package/dist/themes/colorMath.d.ts.map +0 -1
  322. package/dist/themes/colorMath.js.map +0 -1
  323. package/dist/themes/colorRef.d.ts.map +0 -1
  324. package/dist/themes/colorRef.js.map +0 -1
  325. package/dist/themes/data/atom-one-dark.d.ts.map +0 -1
  326. package/dist/themes/data/atom-one-dark.js.map +0 -1
  327. package/dist/themes/data/atom-one-light.d.ts.map +0 -1
  328. package/dist/themes/data/atom-one-light.js.map +0 -1
  329. package/dist/themes/data/catppuccin-frappe.d.ts.map +0 -1
  330. package/dist/themes/data/catppuccin-frappe.js.map +0 -1
  331. package/dist/themes/data/catppuccin-latte.d.ts.map +0 -1
  332. package/dist/themes/data/catppuccin-latte.js.map +0 -1
  333. package/dist/themes/data/catppuccin-macchiato.d.ts.map +0 -1
  334. package/dist/themes/data/catppuccin-macchiato.js.map +0 -1
  335. package/dist/themes/data/catppuccin-mocha.d.ts.map +0 -1
  336. package/dist/themes/data/catppuccin-mocha.js.map +0 -1
  337. package/dist/themes/data/cyberpunk.d.ts.map +0 -1
  338. package/dist/themes/data/cyberpunk.js.map +0 -1
  339. package/dist/themes/data/default.d.ts.map +0 -1
  340. package/dist/themes/data/default.js.map +0 -1
  341. package/dist/themes/data/dracula.d.ts.map +0 -1
  342. package/dist/themes/data/dracula.js.map +0 -1
  343. package/dist/themes/data/flexoki.d.ts.map +0 -1
  344. package/dist/themes/data/flexoki.js.map +0 -1
  345. package/dist/themes/data/gruvbox.d.ts.map +0 -1
  346. package/dist/themes/data/gruvbox.js.map +0 -1
  347. package/dist/themes/data/index.d.ts.map +0 -1
  348. package/dist/themes/data/index.js.map +0 -1
  349. package/dist/themes/data/monokai.d.ts.map +0 -1
  350. package/dist/themes/data/monokai.js.map +0 -1
  351. package/dist/themes/data/nord.d.ts.map +0 -1
  352. package/dist/themes/data/nord.js.map +0 -1
  353. package/dist/themes/data/rose-pine-dawn.d.ts.map +0 -1
  354. package/dist/themes/data/rose-pine-dawn.js.map +0 -1
  355. package/dist/themes/data/rose-pine-moon.d.ts.map +0 -1
  356. package/dist/themes/data/rose-pine-moon.js.map +0 -1
  357. package/dist/themes/data/rose-pine.d.ts.map +0 -1
  358. package/dist/themes/data/rose-pine.js.map +0 -1
  359. package/dist/themes/data/solarized-dark.d.ts.map +0 -1
  360. package/dist/themes/data/solarized-dark.js.map +0 -1
  361. package/dist/themes/data/solarized-light.d.ts.map +0 -1
  362. package/dist/themes/data/solarized-light.js.map +0 -1
  363. package/dist/themes/data/svg-export.d.ts.map +0 -1
  364. package/dist/themes/data/svg-export.js.map +0 -1
  365. package/dist/themes/data/textual-ansi.d.ts.map +0 -1
  366. package/dist/themes/data/textual-ansi.js.map +0 -1
  367. package/dist/themes/data/textual-dark.d.ts.map +0 -1
  368. package/dist/themes/data/textual-dark.js.map +0 -1
  369. package/dist/themes/data/textual-light.d.ts.map +0 -1
  370. package/dist/themes/data/textual-light.js.map +0 -1
  371. package/dist/themes/data/tokyo-night.d.ts.map +0 -1
  372. package/dist/themes/data/tokyo-night.js.map +0 -1
  373. package/dist/themes/data/types.d.ts.map +0 -1
  374. package/dist/themes/data/types.js.map +0 -1
  375. package/dist/themes/palette.d.ts.map +0 -1
  376. package/dist/themes/palette.js.map +0 -1
  377. package/dist/themes/ramp.d.ts.map +0 -1
  378. package/dist/themes/ramp.js.map +0 -1
  379. package/dist/themes/registry.d.ts.map +0 -1
  380. package/dist/themes/registry.js.map +0 -1
  381. package/dist/themes/terminalThemes.d.ts.map +0 -1
  382. package/dist/themes/terminalThemes.js.map +0 -1
  383. package/dist/themes/transpose.d.ts.map +0 -1
  384. package/dist/themes/transpose.js.map +0 -1
  385. package/dist/widgets/button.d.ts.map +0 -1
  386. package/dist/widgets/button.js.map +0 -1
  387. package/dist/widgets/checkbox.d.ts.map +0 -1
  388. package/dist/widgets/checkbox.js.map +0 -1
  389. package/dist/widgets/dropdown.d.ts.map +0 -1
  390. package/dist/widgets/dropdown.js.map +0 -1
  391. package/dist/widgets/event-router.d.ts.map +0 -1
  392. package/dist/widgets/event-router.js.map +0 -1
  393. package/dist/widgets/focus-manager.d.ts.map +0 -1
  394. package/dist/widgets/focus-manager.js.map +0 -1
  395. package/dist/widgets/index.d.ts.map +0 -1
  396. package/dist/widgets/index.js.map +0 -1
  397. package/dist/widgets/screen.d.ts.map +0 -1
  398. package/dist/widgets/screen.js.map +0 -1
  399. package/dist/widgets/slider.d.ts.map +0 -1
  400. package/dist/widgets/slider.js.map +0 -1
  401. package/dist/widgets/static-item.d.ts.map +0 -1
  402. package/dist/widgets/static-item.js.map +0 -1
  403. package/dist/widgets/text-input.d.ts.map +0 -1
  404. package/dist/widgets/text-input.js.map +0 -1
  405. package/dist/widgets/toggle.d.ts.map +0 -1
  406. package/dist/widgets/toggle.js.map +0 -1
  407. package/dist/widgets/types.d.ts.map +0 -1
  408. package/dist/widgets/types.js.map +0 -1
  409. package/dist/widgets/widget-base.d.ts.map +0 -1
  410. package/dist/widgets/widget-base.js.map +0 -1
@@ -14,8 +14,9 @@
14
14
  * (`[bold]a[italic]b[/bold]c[/italic]`) because a style is an annotation and
15
15
  * annotations may overlap freely; a plugin tag is a replacement whose handler
16
16
  * takes one contiguous `inner`, so an overlapping pair has no slice to hand it
17
- * and is rejected with a `MarkupError`.
17
+ * and is rejected with a `MarkupSyntaxError`.
18
18
  */
19
+ import { cellLen } from "./cells.js";
19
20
  import { Style, StyleSyntaxError } from "./style.js";
20
21
  import { RichText, Span } from "./text.js";
21
22
  import { emojiReplace } from "./emoji.js";
@@ -45,6 +46,94 @@ export class MarkupError extends Error {
45
46
  this.name = "MarkupError";
46
47
  }
47
48
  }
49
+ // --- MarkupSyntaxError ---
50
+ /**
51
+ * A markup string that cannot be parsed, with where it went wrong.
52
+ *
53
+ * [LAW:types-are-the-program] A subclass rather than optional fields on
54
+ * `MarkupError`, because the parent is also what `MarkupRegistry.register`
55
+ * throws, and a registration has no source text to point into. Every error this
56
+ * class describes has a location, so none of its fields is optional and no
57
+ * caller has to ask whether one is present — `instanceof` is the only question.
58
+ *
59
+ * [LAW:one-source-of-truth] The constructor takes the facts the parser holds —
60
+ * the string, the offset of the offending tag, what was open — and derives
61
+ * `line`, `column` and the message from them, so the numbers a caller reads
62
+ * and the caret the message draws cannot disagree.
63
+ */
64
+ export class MarkupSyntaxError extends MarkupError {
65
+ /** The problem alone, with no location, for callers building their own message. */
66
+ reason;
67
+ /** The whole markup string that failed, as the caller passed it. */
68
+ markup;
69
+ /** Index into `markup` of the tag the parser rejected. */
70
+ offset;
71
+ /** 1-based line of `offset`; lines are separated by `\n`. */
72
+ line;
73
+ /** 1-based column of `offset` within its line, in UTF-16 code units. */
74
+ column;
75
+ /**
76
+ * The opening tags still open at `offset`, outermost first, as written. For
77
+ * overlapping plugin tags, only plugin tags are named.
78
+ */
79
+ openTags;
80
+ constructor(reason, markup, offset, openTags) {
81
+ const lineStart = markup.lastIndexOf("\n", offset - 1) + 1;
82
+ const lineEnd = markup.indexOf("\n", offset);
83
+ const text = markup.slice(lineStart, lineEnd === -1 ? markup.length : lineEnd);
84
+ const line = countNewlines(markup.slice(0, lineStart)) + 1;
85
+ const column = offset - lineStart + 1;
86
+ const open = openTags.length > 0 ? openTags.join(" ") : "none";
87
+ super(`${printable(reason)} (line ${line}, column ${column})\n` +
88
+ `${excerpt(text, offset - lineStart)}\n` +
89
+ `Open tags: ${printable(open)}`);
90
+ this.name = "MarkupSyntaxError";
91
+ this.reason = reason;
92
+ this.markup = markup;
93
+ this.offset = offset;
94
+ this.line = line;
95
+ this.column = column;
96
+ this.openTags = openTags;
97
+ }
98
+ }
99
+ function countNewlines(text) {
100
+ return text.split("\n").length - 1;
101
+ }
102
+ // Code points shown either side of the error before the excerpt is cut and
103
+ // marked with an ellipsis. Enough to recognise the surrounding tags on a line
104
+ // that is long, templated, or machine-assembled, without printing all of it.
105
+ const EXCERPT_CONTEXT = 30;
106
+ /**
107
+ * `text` with each C0 control and DEL shown as one space.
108
+ *
109
+ * [LAW:single-enforcer] Every part of the message that quotes the caller's
110
+ * markup passes through here: the reason and the open tags quote tag text, and
111
+ * the tag grammar admits control characters, so an `ESC ]` inside a tag would
112
+ * otherwise open an OSC sequence in the terminal printing the error. In the
113
+ * excerpt it also keeps the caret aligned, since a control occupies no cell.
114
+ * The fields keep the text as written; only the message is made printable.
115
+ */
116
+ function printable(text) {
117
+ return text.replace(/[\x00-\x1f\x7f]/g, " ");
118
+ }
119
+ /**
120
+ * Two lines: the source line around `index`, and a caret under it.
121
+ *
122
+ * The window is cut in code points, so a surrogate pair is never split, and the
123
+ * caret is placed by cell width, so a wide character before the error still
124
+ * leaves it under the right cell.
125
+ */
126
+ function excerpt(text, index) {
127
+ const chars = Array.from(printable(text));
128
+ const at = Array.from(text.slice(0, index)).length;
129
+ const from = Math.max(0, at - EXCERPT_CONTEXT);
130
+ const to = Math.min(chars.length, at + EXCERPT_CONTEXT);
131
+ const head = from > 0 ? "…" : "";
132
+ const tail = to < chars.length ? "…" : "";
133
+ const before = head + chars.slice(from, at).join("");
134
+ const shown = before + chars.slice(at, to).join("") + tail;
135
+ return ` ${shown}\n ${" ".repeat(cellLen(before))}^`;
136
+ }
48
137
  // --- escape ---
49
138
  /**
50
139
  * Escapes markup characters so they render as literal text.
@@ -106,6 +195,9 @@ function parseTags(markup) {
106
195
  }
107
196
  return tags;
108
197
  }
198
+ function wholeString(markup) {
199
+ return { source: markup, base: 0, enclosing: [] };
200
+ }
109
201
  /**
110
202
  * Parses the built-in style dialect — `[bold red]text[/bold red]` — into a
111
203
  * `RichText` with styled spans. Module-private on purpose: `renderMarkup` is
@@ -127,7 +219,7 @@ function parseTags(markup) {
127
219
  * function names; an empty registry puts it in the data, where the one
128
220
  * boundary admits both.
129
221
  */
130
- function render(markup, baseStyle, options) {
222
+ function render(markup, origin, baseStyle, options) {
131
223
  // Fast path: no brackets at all
132
224
  if (!HAS_TAG_RE.test(markup)) {
133
225
  let text = markup;
@@ -145,6 +237,10 @@ function render(markup, baseStyle, options) {
145
237
  let plainText = "";
146
238
  const spans = [];
147
239
  const openStack = [];
240
+ const unparsable = (reason, tag) => new MarkupSyntaxError(reason, origin.source, origin.base + tag.start, [
241
+ ...origin.enclosing,
242
+ ...openStack.map((opened) => opened.tag),
243
+ ]);
148
244
  let lastEnd = 0;
149
245
  for (const tag of tags) {
150
246
  // Add text before this tag
@@ -154,7 +250,9 @@ function render(markup, baseStyle, options) {
154
250
  if (tag.isImplicitClose) {
155
251
  // [/] — close the most recent open tag
156
252
  if (openStack.length === 0) {
157
- throw new MarkupError("Closing tag [/] has nothing to close");
253
+ // [/] never closes a plugin tag, so an enclosing plugin tag can be open
254
+ // here while no style tag is.
255
+ throw unparsable(`Closing tag ${tag.fullMatch} has no open style tag to close`, tag);
158
256
  }
159
257
  const opened = openStack.pop();
160
258
  spans.push(new Span(opened.textStart, plainText.length, openTagStyle(opened)));
@@ -163,7 +261,7 @@ function render(markup, baseStyle, options) {
163
261
  // [/style] — find and close matching open tag
164
262
  const idx = findLastOpen(openStack, tag.styleName);
165
263
  if (idx === -1) {
166
- throw new MarkupError(`Closing tag [/${tag.styleName}] doesn't match any open tag`);
264
+ throw unparsable(`Closing tag ${tag.fullMatch} doesn't match any open tag`, tag);
167
265
  }
168
266
  const opened = openStack[idx];
169
267
  spans.push(new Span(opened.textStart, plainText.length, openTagStyle(opened)));
@@ -172,6 +270,7 @@ function render(markup, baseStyle, options) {
172
270
  else {
173
271
  // Opening tag
174
272
  openStack.push({
273
+ tag: tag.fullMatch,
175
274
  styleName: tag.styleName,
176
275
  parameters: tag.parameters,
177
276
  textStart: plainText.length,
@@ -390,20 +489,23 @@ function parsePluginAttrs(after) {
390
489
  * append path is uniform.
391
490
  */
392
491
  export function renderMarkup(markup, options) {
492
+ return renderSlice(markup, wholeString(markup), options);
493
+ }
494
+ function renderSlice(markup, origin, options) {
393
495
  const registry = options?.registry ?? globalMarkupRegistry;
394
496
  const baseStyle = options?.baseStyle;
395
497
  const doEmoji = options?.emoji !== false;
396
498
  // Fast path: no `[` at all → no possible tags.
397
499
  if (!HAS_TAG_RE.test(markup)) {
398
- return render(markup, baseStyle, { emoji: doEmoji });
500
+ return render(markup, origin, baseStyle, { emoji: doEmoji });
399
501
  }
400
502
  const tags = parseTags(markup);
401
503
  // Pair each opening plugin tag with its matching closer up-front, so the
402
504
  // splice walk can just iterate top-level pairs in source order with no
403
505
  // nested-state book-keeping.
404
- const { annotated, topLevel: tagPairs } = pairPluginTags(tags, registry);
506
+ const { annotated, topLevel: tagPairs } = pairPluginTags(tags, registry, origin);
405
507
  if (tagPairs.size === 0) {
406
- return render(markup, baseStyle, { emoji: doEmoji });
508
+ return render(markup, origin, baseStyle, { emoji: doEmoji });
407
509
  }
408
510
  // [LAW:one-type-per-behavior] Always assemble a single RichText. Fragments
409
511
  // between plugin pairs are parsed by the built-in `render`, plugin pairs
@@ -415,22 +517,26 @@ export function renderMarkup(markup, options) {
415
517
  const open = annotated[openIdx];
416
518
  const close = annotated[closeIdx];
417
519
  if (open.start > cursor) {
418
- out.append(render(markup.slice(cursor, open.start), baseStyle, { emoji: doEmoji }));
520
+ out.append(render(markup.slice(cursor, open.start), offsetBy(origin, cursor), baseStyle, { emoji: doEmoji }));
419
521
  }
420
522
  const innerRaw = markup.slice(open.end, close.start);
421
- const innerRichText = renderMarkup(innerRaw, options);
523
+ const innerRichText = renderSlice(innerRaw, { ...offsetBy(origin, open.end), enclosing: [...origin.enclosing, open.fullMatch] }, options);
422
524
  const handler = registry.get(open.pluginName);
423
525
  out.append(handler({ attrs: open.attrs, children: innerRichText, raw: innerRaw }));
424
526
  cursor = close.end;
425
527
  }
426
528
  if (cursor < markup.length) {
427
- out.append(render(markup.slice(cursor), baseStyle, { emoji: doEmoji }));
529
+ out.append(render(markup.slice(cursor), offsetBy(origin, cursor), baseStyle, { emoji: doEmoji }));
428
530
  }
429
531
  if (baseStyle)
430
532
  out.stylize(baseStyle);
431
533
  return out;
432
534
  }
433
- function pairPluginTags(tags, registry) {
535
+ /** The origin of a sub-slice starting `offset` into the slice `origin` describes. */
536
+ function offsetBy(origin, offset) {
537
+ return { ...origin, base: origin.base + offset };
538
+ }
539
+ function pairPluginTags(tags, registry, origin) {
434
540
  // Annotate tags with plugin info, then pair openers with closers. Only
435
541
  // top-level pairs are returned; inner pairs will be re-discovered by the
436
542
  // recursive `renderMarkup` call on the inner slice.
@@ -477,11 +583,18 @@ function pairPluginTags(tags, registry) {
477
583
  // hand it. A style span may overlap because it annotates; a plugin pair
478
584
  // may not because it replaces.
479
585
  if (annotated[closeIdx].end > outerEnd) {
480
- const inner = annotated[openIdx].pluginName;
481
- const outer = annotated[outerOpenIdx].pluginName;
482
- throw new MarkupError(`Plugin tag [${inner}] overlaps [${outer}]: plugin tags must nest, ` +
586
+ const inner = annotated[openIdx];
587
+ const outer = annotated[outerOpenIdx];
588
+ // The caret goes under the outer pair's closing tag, the point where
589
+ // nesting breaks. This pass sees plugin tags only; of those, a pair is
590
+ // open there when it opens before that tag and closes at or after it.
591
+ const caret = annotated[pairs.get(outerOpenIdx)].start;
592
+ const openAtCaret = sortedOpens
593
+ .filter((o) => annotated[o].start < caret && annotated[pairs.get(o)].start >= caret)
594
+ .map((o) => annotated[o].fullMatch);
595
+ throw new MarkupSyntaxError(`Plugin tag [${inner.pluginName}] overlaps [${outer.pluginName}]: plugin tags must nest, ` +
483
596
  `because a handler receives one contiguous slice. ` +
484
- `Close [/${inner}] before [/${outer}].`);
597
+ `Close [/${inner.pluginName}] before [/${outer.pluginName}].`, origin.source, origin.base + caret, [...origin.enclosing, ...openAtCaret]);
485
598
  }
486
599
  continue;
487
600
  }
@@ -504,4 +617,3 @@ function annotatePluginTag(tag, registry) {
504
617
  const attrs = tag.isClosing ? {} : parsePluginAttrs(after);
505
618
  return { ...tag, pluginName: name, attrs };
506
619
  }
507
- //# sourceMappingURL=markup.js.map
@@ -25,4 +25,3 @@ export declare class Measurement {
25
25
  static get(options: RenderOptions, measurable: Measurable): Measurement;
26
26
  }
27
27
  export declare function measureRenderables(options: RenderOptions, measurables: Measurable[]): Measurement;
28
- //# sourceMappingURL=measure.d.ts.map
@@ -59,4 +59,3 @@ export function measureRenderables(options, measurables) {
59
59
  }
60
60
  return new Measurement(minOfAll, maxOfAll);
61
61
  }
62
- //# sourceMappingURL=measure.js.map
@@ -41,6 +41,13 @@ export interface ThemeKey {
41
41
  /** Additive on lightness; applied *after* the scale. */
42
42
  readonly lightnessShift: number;
43
43
  }
44
+ /** How far `Oklch.mixAxes` moves each axis toward its target, each in [0, 1]. */
45
+ export interface OklchWeights {
46
+ readonly l: number;
47
+ readonly c: number;
48
+ readonly h: number;
49
+ readonly alpha: number;
50
+ }
44
51
  export declare const IDENTITY: ThemeKey;
45
52
  /**
46
53
  * Flip lightness around the midpoint (`L' = 1 - L`) with hue and chroma
@@ -70,6 +77,7 @@ export declare function isIdentityKey(k: ThemeKey): boolean;
70
77
  * sRGB-quantization step normalizes them.
71
78
  */
72
79
  export declare class Oklch {
80
+ #private;
73
81
  readonly l: number;
74
82
  readonly c: number;
75
83
  readonly h: number;
@@ -115,6 +123,32 @@ export declare class Oklch {
115
123
  * there too.
116
124
  */
117
125
  mix(toward: Oklch, t: number): Oklch;
126
+ /**
127
+ * `mix` with each axis moved its own share of the way: `weights.l` of the
128
+ * lightness gap, `weights.c` of the chroma gap, and so on, each in [0, 1].
129
+ * `mix(toward, t)` is `mixAxes` with every weight `t` — one interpolation,
130
+ * so the shorter-arc hue and the powerless-endpoint rule are the same
131
+ * whichever is called.
132
+ *
133
+ * It exists because perceptual axes are independent: a tint can take most of
134
+ * a hue's colourfulness while keeping close to the lightness it started at,
135
+ * which a single `t` cannot say — raising `t` for chroma drags lightness with
136
+ * it. Every weight is required: an axis left out would need a default, and
137
+ * "unchanged" (0) and "same as the others" are both plausible readings.
138
+ *
139
+ * A weak `h` beside a strong `c` shows the starting colour's hue at high
140
+ * chroma. The powerless rule covers only a truly achromatic start, so a
141
+ * near-grey whose hue is noise (a theme surface at c ≈ 0.004) keeps that
142
+ * noise in proportion. To land on the target's hue, pass `h: 1`.
143
+ */
144
+ mixAxes(toward: Oklch, weights: OklchWeights): Oklch;
145
+ /**
146
+ * ΔE_OK — the Euclidean distance between this colour and `other` in OKLab
147
+ * (CSS Color 4's `deltaEOK`), where ~0.02 is the smallest difference the eye
148
+ * resolves. Alpha is not a coordinate of the space and does not count.
149
+ * Symmetric and pure.
150
+ */
151
+ deltaE(other: Oklch): number;
118
152
  /** Linear-sRGB coordinates for an explicit (l, C, h). Pure; `toRgba` passes
119
153
  * already-normalized values so this never sees out-of-range inputs. */
120
154
  private toLinearRgb;
@@ -125,4 +159,3 @@ export declare class Oklch {
125
159
  */
126
160
  private findInGamutChroma;
127
161
  }
128
- //# sourceMappingURL=oklch.d.ts.map
@@ -20,7 +20,11 @@
20
20
  * nothing else from inside the project. Nothing in core/ depends back on
21
21
  * this file.
22
22
  */
23
+ var _a;
23
24
  import { ColorRgba } from "./color.js";
25
+ // The axes `mixAxes` checks, named once so a weights object's own keys — a
26
+ // missing one, or an extra field riding along — never decide what is checked.
27
+ const OKLCH_AXES = ["l", "c", "h", "alpha"];
24
28
  export const IDENTITY = Object.freeze({
25
29
  hueShift: 0,
26
30
  chromaScale: 1,
@@ -144,7 +148,7 @@ export class Oklch {
144
148
  const bLab = 0.0259040371 * lCube + 0.7827717662 * mCube - 0.8086757660 * sCube;
145
149
  const C = Math.sqrt(aLab * aLab + bLab * bLab);
146
150
  const H = wrapHue(Math.atan2(bLab, aLab) * (180 / Math.PI));
147
- return new Oklch(L, C, hueOf(C, H), a);
151
+ return new _a(L, C, hueOf(C, H), a);
148
152
  }
149
153
  /**
150
154
  * Polar → OKLab → linear → sRGB (with chroma-bisection gamut clamping).
@@ -181,7 +185,7 @@ export class Oklch {
181
185
  const newL = clamp01(this.l * k.lightnessScale + k.lightnessShift);
182
186
  const newC = Math.max(0, this.c * k.chromaScale);
183
187
  const newH = wrapHue(this.h + k.hueShift);
184
- return new Oklch(newL, newC, hueOf(newC, newH), this.alpha);
188
+ return new _a(newL, newC, hueOf(newC, newH), this.alpha);
185
189
  }
186
190
  /**
187
191
  * The color `t` of the way from this one toward `toward`, in OKLCH.
@@ -208,6 +212,38 @@ export class Oklch {
208
212
  if (!(t >= 0 && t <= 1)) {
209
213
  throw new RangeError(`Oklch.mix: t must be in [0, 1]; got ${t}`);
210
214
  }
215
+ return this.#interpolate(toward, t, t, t, t);
216
+ }
217
+ /**
218
+ * `mix` with each axis moved its own share of the way: `weights.l` of the
219
+ * lightness gap, `weights.c` of the chroma gap, and so on, each in [0, 1].
220
+ * `mix(toward, t)` is `mixAxes` with every weight `t` — one interpolation,
221
+ * so the shorter-arc hue and the powerless-endpoint rule are the same
222
+ * whichever is called.
223
+ *
224
+ * It exists because perceptual axes are independent: a tint can take most of
225
+ * a hue's colourfulness while keeping close to the lightness it started at,
226
+ * which a single `t` cannot say — raising `t` for chroma drags lightness with
227
+ * it. Every weight is required: an axis left out would need a default, and
228
+ * "unchanged" (0) and "same as the others" are both plausible readings.
229
+ *
230
+ * A weak `h` beside a strong `c` shows the starting colour's hue at high
231
+ * chroma. The powerless rule covers only a truly achromatic start, so a
232
+ * near-grey whose hue is noise (a theme surface at c ≈ 0.004) keeps that
233
+ * noise in proportion. To land on the target's hue, pass `h: 1`.
234
+ */
235
+ mixAxes(toward, weights) {
236
+ for (const axis of OKLCH_AXES) {
237
+ const w = weights[axis];
238
+ if (!(w >= 0 && w <= 1)) {
239
+ throw new RangeError(`Oklch.mixAxes: ${axis} weight must be in [0, 1]; got ${w}`);
240
+ }
241
+ }
242
+ return this.#interpolate(toward, weights.l, weights.c, weights.h, weights.alpha);
243
+ }
244
+ // The one interpolation both entry points share; each has already checked
245
+ // its own weights, so this is the arithmetic alone.
246
+ #interpolate(toward, wl, wc, wh, walpha) {
211
247
  const thisHasHue = this.c >= ACHROMATIC_EPS;
212
248
  const towardHasHue = toward.c >= ACHROMATIC_EPS;
213
249
  const fromH = wrapHue(thisHasHue ? this.h : towardHasHue ? toward.h : 0);
@@ -219,8 +255,19 @@ export class Oklch {
219
255
  const arc = toH - fromH;
220
256
  const fromU = arc < -180 ? fromH - 360 : fromH;
221
257
  const toU = arc > 180 ? toH - 360 : toH;
222
- const c = lerp(this.c, toward.c, t);
223
- return new Oklch(lerp(this.l, toward.l, t), c, hueOf(c, wrapHue(lerp(fromU, toU, t))), lerp(this.alpha, toward.alpha, t));
258
+ const c = lerp(this.c, toward.c, wc);
259
+ return new _a(lerp(this.l, toward.l, wl), c, hueOf(c, wrapHue(lerp(fromU, toU, wh))), lerp(this.alpha, toward.alpha, walpha));
260
+ }
261
+ /**
262
+ * ΔE_OK — the Euclidean distance between this colour and `other` in OKLab
263
+ * (CSS Color 4's `deltaEOK`), where ~0.02 is the smallest difference the eye
264
+ * resolves. Alpha is not a coordinate of the space and does not count.
265
+ * Symmetric and pure.
266
+ */
267
+ deltaE(other) {
268
+ const a = (this.h * Math.PI) / 180;
269
+ const b = (other.h * Math.PI) / 180;
270
+ return Math.hypot(this.l - other.l, this.c * Math.cos(a) - other.c * Math.cos(b), this.c * Math.sin(a) - other.c * Math.sin(b));
224
271
  }
225
272
  /** Linear-sRGB coordinates for an explicit (l, C, h). Pure; `toRgba` passes
226
273
  * already-normalized values so this never sees out-of-range inputs. */
@@ -262,4 +309,4 @@ export class Oklch {
262
309
  return lo;
263
310
  }
264
311
  }
265
- //# sourceMappingURL=oklch.js.map
312
+ _a = Oklch;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * The OSC 8 hyperlink wire grammar — which bytes may not appear inside a
3
+ * link, how a link becomes bytes, and how bytes are read back as a link.
4
+ *
5
+ * [LAW:one-source-of-truth] Every producer (`segmentsToString`,
6
+ * `Style.render`) opens a link through `osc8Open` and closes it with
7
+ * `OSC8_CLOSE`; every consumer that reads rendered bytes (a width measure, a
8
+ * test extracting URLs) matches them with `OSC8`; the data-model boundary
9
+ * (RichText) cleans URLs with `stripOscTerminators`. All four read the one
10
+ * terminator set below, so the bytes a sanitizer removes and the bytes a
11
+ * reader stops at cannot disagree.
12
+ *
13
+ * [LAW:locality-or-seam] This module depends on nothing; every consumer
14
+ * imports downward.
15
+ *
16
+ * The `id=` parameter is what makes one link hover as one link. A terminal
17
+ * treats cells as the same hyperlink when they share BOTH the URI and the id
18
+ * (the OSC 8 spec, and VTE / iTerm2 / kitty / WezTerm alike); without an id,
19
+ * each open sequence is its own link. The coalescer can only share one OSC 8
20
+ * pair across a run of identical SGR, so a link whose text changes style
21
+ * mid-span — a bold glyph beside plain text, a padded cell — is emitted as
22
+ * several pairs, and would highlight piecewise on hover.
23
+ *
24
+ * [LAW:types-are-the-program] The id is a pure function of the URI, so the
25
+ * byte stream stays a pure function of (style, text, colorSystem): no counter,
26
+ * no construction-order dependence. The consequence is deliberate: two spans
27
+ * with the same URI hover as one link wherever they sit on screen, adjacent
28
+ * or not — a click on either does the same thing, so they ARE one link.
29
+ * Because terminals key on the (id, URI) PAIR, a hash collision between two
30
+ * different URIs merges nothing — the URIs still differ — so a 32-bit hash is
31
+ * exact, not approximate.
32
+ */
33
+ /** Remove every byte that could break a URL out of its OSC 8 wrap. */
34
+ export declare function stripOscTerminators(url: string): string;
35
+ /**
36
+ * The bytes that open a hyperlink to `url`.
37
+ *
38
+ * [LAW:single-enforcer] Wire-byte trust boundary — the URL is sanitized at
39
+ * the one place it becomes an OSC 8 sequence, whichever upstream API attached
40
+ * it to the Style (RichText sanitizes at its data-model boundary too; a Style
41
+ * built directly with `new Style({ link })` reaches here unsanitized).
42
+ */
43
+ export declare function osc8Open(url: string): string;
44
+ /** The bytes that close the current hyperlink. */
45
+ export declare const OSC8_CLOSE = "\u001B]8;;\u001B\\";
46
+ /**
47
+ * Matches one OSC 8 sequence — an open or a close — terminated by `ESC \`,
48
+ * BEL, or the 8-bit ST. Group 1 is the params, group 2 the URI; both are empty
49
+ * on a close. To read bytes back use `osc8Sequences`; this pattern is exported
50
+ * for composing into a larger one (a width measure's zero-width alternation).
51
+ */
52
+ export declare const OSC8: RegExp;
53
+ /** One OSC 8 sequence found in rendered bytes. A close has `uri === ""`. */
54
+ export interface Osc8Sequence {
55
+ /** Offset of the sequence in the scanned string. */
56
+ readonly index: number;
57
+ /** Length of the whole sequence, terminator included. */
58
+ readonly length: number;
59
+ /** The params field (`id=…`); empty on a close. */
60
+ readonly params: string;
61
+ /** The URI; empty on a close. */
62
+ readonly uri: string;
63
+ }
64
+ /**
65
+ * Every OSC 8 sequence in `text`, in order — the typed way to read rendered
66
+ * bytes back.
67
+ */
68
+ export declare function osc8Sequences(text: string): Osc8Sequence[];
@@ -0,0 +1,90 @@
1
+ /**
2
+ * The OSC 8 hyperlink wire grammar — which bytes may not appear inside a
3
+ * link, how a link becomes bytes, and how bytes are read back as a link.
4
+ *
5
+ * [LAW:one-source-of-truth] Every producer (`segmentsToString`,
6
+ * `Style.render`) opens a link through `osc8Open` and closes it with
7
+ * `OSC8_CLOSE`; every consumer that reads rendered bytes (a width measure, a
8
+ * test extracting URLs) matches them with `OSC8`; the data-model boundary
9
+ * (RichText) cleans URLs with `stripOscTerminators`. All four read the one
10
+ * terminator set below, so the bytes a sanitizer removes and the bytes a
11
+ * reader stops at cannot disagree.
12
+ *
13
+ * [LAW:locality-or-seam] This module depends on nothing; every consumer
14
+ * imports downward.
15
+ *
16
+ * The `id=` parameter is what makes one link hover as one link. A terminal
17
+ * treats cells as the same hyperlink when they share BOTH the URI and the id
18
+ * (the OSC 8 spec, and VTE / iTerm2 / kitty / WezTerm alike); without an id,
19
+ * each open sequence is its own link. The coalescer can only share one OSC 8
20
+ * pair across a run of identical SGR, so a link whose text changes style
21
+ * mid-span — a bold glyph beside plain text, a padded cell — is emitted as
22
+ * several pairs, and would highlight piecewise on hover.
23
+ *
24
+ * [LAW:types-are-the-program] The id is a pure function of the URI, so the
25
+ * byte stream stays a pure function of (style, text, colorSystem): no counter,
26
+ * no construction-order dependence. The consequence is deliberate: two spans
27
+ * with the same URI hover as one link wherever they sit on screen, adjacent
28
+ * or not — a click on either does the same thing, so they ARE one link.
29
+ * Because terminals key on the (id, URI) PAIR, a hash collision between two
30
+ * different URIs merges nothing — the URIs still differ — so a 32-bit hash is
31
+ * exact, not approximate.
32
+ */
33
+ /**
34
+ * The bytes that prematurely terminate an OSC 8 sequence: ESC (`\x1b`, which
35
+ * begins ST `ESC \`), BEL (`\x07`), and the 8-bit ST (`\x9c`).
36
+ */
37
+ const TERMINATORS = "\\x1b\\x07\\x9c";
38
+ const TERMINATOR_RE = new RegExp(`[${TERMINATORS}]`, "g");
39
+ /** Remove every byte that could break a URL out of its OSC 8 wrap. */
40
+ export function stripOscTerminators(url) {
41
+ return url.replace(TERMINATOR_RE, "");
42
+ }
43
+ const utf8 = new TextEncoder();
44
+ /**
45
+ * FNV-1a, 32-bit, over the URL's UTF-8 bytes, as 8 lowercase hex digits — a
46
+ * legal `id=` value (no `:`/`;`). UTF-8 rather than UTF-16 code units, so any
47
+ * other runtime computing standard FNV-1a over the same URL gets the same id.
48
+ */
49
+ function linkId(url) {
50
+ let h = 0x811c9dc5;
51
+ for (const byte of utf8.encode(url)) {
52
+ h ^= byte;
53
+ h = Math.imul(h, 0x01000193);
54
+ }
55
+ return (h >>> 0).toString(16).padStart(8, "0");
56
+ }
57
+ /**
58
+ * The bytes that open a hyperlink to `url`.
59
+ *
60
+ * [LAW:single-enforcer] Wire-byte trust boundary — the URL is sanitized at
61
+ * the one place it becomes an OSC 8 sequence, whichever upstream API attached
62
+ * it to the Style (RichText sanitizes at its data-model boundary too; a Style
63
+ * built directly with `new Style({ link })` reaches here unsanitized).
64
+ */
65
+ export function osc8Open(url) {
66
+ const clean = stripOscTerminators(url);
67
+ return `\x1b]8;id=${linkId(clean)};${clean}\x1b\\`;
68
+ }
69
+ /** The bytes that close the current hyperlink. */
70
+ export const OSC8_CLOSE = "\x1b]8;;\x1b\\";
71
+ /**
72
+ * Matches one OSC 8 sequence — an open or a close — terminated by `ESC \`,
73
+ * BEL, or the 8-bit ST. Group 1 is the params, group 2 the URI; both are empty
74
+ * on a close. To read bytes back use `osc8Sequences`; this pattern is exported
75
+ * for composing into a larger one (a width measure's zero-width alternation).
76
+ */
77
+ export const OSC8 = new RegExp(`\\x1b\\]8;([^;${TERMINATORS}]*);([^${TERMINATORS}]*)(?:\\x1b\\\\|\\x07|\\x9c)`);
78
+ const OSC8_SCAN = new RegExp(OSC8.source, "g");
79
+ /**
80
+ * Every OSC 8 sequence in `text`, in order — the typed way to read rendered
81
+ * bytes back.
82
+ */
83
+ export function osc8Sequences(text) {
84
+ return [...text.matchAll(OSC8_SCAN)].map((m) => ({
85
+ index: m.index,
86
+ length: m[0].length,
87
+ params: m[1],
88
+ uri: m[2],
89
+ }));
90
+ }
@@ -97,7 +97,27 @@ export declare class Pretty implements Renderable, Measurable {
97
97
  private _format;
98
98
  /** The arms for a non-null object, with `value` already on the open path. */
99
99
  private _formatObject;
100
- /** One position, with every value in it laid out. */
100
+ /**
101
+ * One position, with every value in it laid out.
102
+ *
103
+ * `at.column` is where `slot.head` begins. Rather than hand-tracking a
104
+ * second, parallel "column so far" alongside `out` — two values a future
105
+ * edit could update out of step, silently reintroducing a stale-budget bug
106
+ * of the same shape this file just fixed — each hole derives its own
107
+ * column fresh from `out` via `lineColumn`, the one place "text just
108
+ * emitted" becomes "column now". [LAW:one-source-of-truth] `out` is
109
+ * already the complete record; `column` is a read of it, not a second copy
110
+ * of the same fact. `_joinOneLine`'s probe sibling tracks the analogous
111
+ * thing via `budget` shrinking instead, because a probe already discards
112
+ * anything that overruns and so never needs to know where a multi-line
113
+ * insert's last line ends.
114
+ *
115
+ * Each hole's `reserve` is its own `tail` plus, only for the slot's last
116
+ * hole, whatever `at.reserve` already asked this whole slot to leave room
117
+ * for (`_formatObject`'s trailing `,`). An earlier hole's tail is never
118
+ * folded into a later hole's reserve — it is spent, not carried, the moment
119
+ * `out` grows past it.
120
+ */
101
121
  private _expandSlot;
102
122
  /** The one-line form of a value, or `null` when it will not fit `at.budget`. */
103
123
  private _oneLine;
@@ -119,4 +139,3 @@ export declare class Pretty implements Renderable, Measurable {
119
139
  private _slotOneLine;
120
140
  private _addIndentGuides;
121
141
  }
122
- //# sourceMappingURL=pretty.d.ts.map