react-cheminfo 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (844) hide show
  1. package/README.md +111 -23
  2. package/lib/capsule/ui/CapsuleFilter.d.ts +61 -0
  3. package/lib/capsule/ui/CapsuleFilter.d.ts.map +1 -0
  4. package/lib/capsule/ui/CapsuleFilter.js +33 -0
  5. package/lib/capsule/ui/CapsuleFilter.js.map +1 -0
  6. package/lib/capsule/ui/index.d.ts +3 -0
  7. package/lib/capsule/ui/index.d.ts.map +1 -0
  8. package/lib/capsule/ui/index.js +2 -0
  9. package/lib/capsule/ui/index.js.map +1 -0
  10. package/lib/chrome/ui/NavLink.d.ts +27 -0
  11. package/lib/chrome/ui/NavLink.d.ts.map +1 -0
  12. package/lib/chrome/ui/NavLink.js +36 -0
  13. package/lib/chrome/ui/NavLink.js.map +1 -0
  14. package/lib/chrome/ui/NavMenuButton.d.ts +40 -0
  15. package/lib/chrome/ui/NavMenuButton.d.ts.map +1 -0
  16. package/lib/chrome/ui/NavMenuButton.js +26 -0
  17. package/lib/chrome/ui/NavMenuButton.js.map +1 -0
  18. package/lib/chrome/ui/SiteFooter.d.ts +39 -0
  19. package/lib/chrome/ui/SiteFooter.d.ts.map +1 -0
  20. package/lib/chrome/ui/SiteFooter.js +17 -0
  21. package/lib/chrome/ui/SiteFooter.js.map +1 -0
  22. package/lib/chrome/ui/SiteHeader.d.ts +59 -0
  23. package/lib/chrome/ui/SiteHeader.d.ts.map +1 -0
  24. package/lib/chrome/ui/SiteHeader.js +28 -0
  25. package/lib/chrome/ui/SiteHeader.js.map +1 -0
  26. package/lib/chrome/ui/index.d.ts +12 -0
  27. package/lib/chrome/ui/index.d.ts.map +1 -0
  28. package/lib/chrome/ui/index.js +6 -0
  29. package/lib/chrome/ui/index.js.map +1 -0
  30. package/lib/chrome/ui/navItem.d.ts +57 -0
  31. package/lib/chrome/ui/navItem.d.ts.map +1 -0
  32. package/lib/chrome/ui/navItem.js +10 -0
  33. package/lib/chrome/ui/navItem.js.map +1 -0
  34. package/lib/chrome/ui/useCompactHeader.d.ts +31 -0
  35. package/lib/chrome/ui/useCompactHeader.d.ts.map +1 -0
  36. package/lib/chrome/ui/useCompactHeader.js +50 -0
  37. package/lib/chrome/ui/useCompactHeader.js.map +1 -0
  38. package/lib/citation/core/clipboard.d.ts +12 -3
  39. package/lib/citation/core/clipboard.d.ts.map +1 -1
  40. package/lib/citation/core/clipboard.js +21 -10
  41. package/lib/citation/core/clipboard.js.map +1 -1
  42. package/lib/citation/core/download.d.ts +11 -3
  43. package/lib/citation/core/download.d.ts.map +1 -1
  44. package/lib/citation/core/download.js +17 -13
  45. package/lib/citation/core/download.js.map +1 -1
  46. package/lib/citation/core/index.d.ts +4 -3
  47. package/lib/citation/core/index.d.ts.map +1 -1
  48. package/lib/citation/core/index.js +3 -3
  49. package/lib/citation/core/index.js.map +1 -1
  50. package/lib/citation/core/works.d.ts +44 -0
  51. package/lib/citation/core/works.d.ts.map +1 -0
  52. package/lib/citation/core/works.js +51 -0
  53. package/lib/citation/core/works.js.map +1 -0
  54. package/lib/citation/ui/CitationMenu.d.ts +20 -3
  55. package/lib/citation/ui/CitationMenu.d.ts.map +1 -1
  56. package/lib/citation/ui/CitationMenu.js +60 -49
  57. package/lib/citation/ui/CitationMenu.js.map +1 -1
  58. package/lib/citation/ui/CitationPreview.d.ts +5 -2
  59. package/lib/citation/ui/CitationPreview.d.ts.map +1 -1
  60. package/lib/citation/ui/CitationPreview.js +9 -4
  61. package/lib/citation/ui/CitationPreview.js.map +1 -1
  62. package/lib/citation/ui/CiteButton.d.ts +13 -6
  63. package/lib/citation/ui/CiteButton.d.ts.map +1 -1
  64. package/lib/citation/ui/CiteButton.js +5 -4
  65. package/lib/citation/ui/CiteButton.js.map +1 -1
  66. package/lib/citation/ui/CopyFormatEntries.d.ts +31 -0
  67. package/lib/citation/ui/CopyFormatEntries.d.ts.map +1 -0
  68. package/lib/citation/ui/CopyFormatEntries.js +29 -0
  69. package/lib/citation/ui/CopyFormatEntries.js.map +1 -0
  70. package/lib/citation/ui/WorkEntry.d.ts +18 -0
  71. package/lib/citation/ui/WorkEntry.d.ts.map +1 -0
  72. package/lib/citation/ui/WorkEntry.js +32 -0
  73. package/lib/citation/ui/WorkEntry.js.map +1 -0
  74. package/lib/citation/ui/entries.d.ts +7 -7
  75. package/lib/citation/ui/entries.d.ts.map +1 -1
  76. package/lib/citation/ui/entries.js +11 -13
  77. package/lib/citation/ui/entries.js.map +1 -1
  78. package/lib/citation/ui/index.d.ts +2 -2
  79. package/lib/citation/ui/index.d.ts.map +1 -1
  80. package/lib/citation/ui/index.js.map +1 -1
  81. package/lib/citation/ui/useCopyFeedback.d.ts +20 -0
  82. package/lib/citation/ui/useCopyFeedback.d.ts.map +1 -0
  83. package/lib/citation/ui/useCopyFeedback.js +49 -0
  84. package/lib/citation/ui/useCopyFeedback.js.map +1 -0
  85. package/lib/clipboard/core/index.d.ts +2 -0
  86. package/lib/clipboard/core/index.d.ts.map +1 -0
  87. package/lib/clipboard/core/index.js +2 -0
  88. package/lib/clipboard/core/index.js.map +1 -0
  89. package/lib/clipboard/core/writeToClipboard.d.ts +12 -0
  90. package/lib/clipboard/core/writeToClipboard.d.ts.map +1 -0
  91. package/lib/clipboard/core/writeToClipboard.js +49 -0
  92. package/lib/clipboard/core/writeToClipboard.js.map +1 -0
  93. package/lib/clipboard/ui/CodeBlock.d.ts +43 -0
  94. package/lib/clipboard/ui/CodeBlock.d.ts.map +1 -0
  95. package/lib/clipboard/ui/CodeBlock.js +49 -0
  96. package/lib/clipboard/ui/CodeBlock.js.map +1 -0
  97. package/lib/clipboard/ui/CopyButton.d.ts +64 -0
  98. package/lib/clipboard/ui/CopyButton.d.ts.map +1 -0
  99. package/lib/clipboard/ui/CopyButton.js +21 -0
  100. package/lib/clipboard/ui/CopyButton.js.map +1 -0
  101. package/lib/clipboard/ui/index.d.ts +7 -0
  102. package/lib/clipboard/ui/index.d.ts.map +1 -0
  103. package/lib/clipboard/ui/index.js +4 -0
  104. package/lib/clipboard/ui/index.js.map +1 -0
  105. package/lib/clipboard/ui/useCopyToClipboard.d.ts +24 -0
  106. package/lib/clipboard/ui/useCopyToClipboard.d.ts.map +1 -0
  107. package/lib/clipboard/ui/useCopyToClipboard.js +36 -0
  108. package/lib/clipboard/ui/useCopyToClipboard.js.map +1 -0
  109. package/lib/color/core/contrast.d.ts +43 -0
  110. package/lib/color/core/contrast.d.ts.map +1 -0
  111. package/lib/color/core/contrast.js +61 -0
  112. package/lib/color/core/contrast.js.map +1 -0
  113. package/lib/color/core/hex.d.ts +26 -0
  114. package/lib/color/core/hex.d.ts.map +1 -0
  115. package/lib/color/core/hex.js +44 -0
  116. package/lib/color/core/hex.js.map +1 -0
  117. package/lib/color/core/index.d.ts +5 -0
  118. package/lib/color/core/index.d.ts.map +1 -0
  119. package/lib/color/core/index.js +3 -0
  120. package/lib/color/core/index.js.map +1 -0
  121. package/lib/color/core/scale.d.ts +52 -0
  122. package/lib/color/core/scale.d.ts.map +1 -0
  123. package/lib/color/core/scale.js +96 -0
  124. package/lib/color/core/scale.js.map +1 -0
  125. package/lib/color/ui/ColorScaleLegend.d.ts +38 -0
  126. package/lib/color/ui/ColorScaleLegend.d.ts.map +1 -0
  127. package/lib/color/ui/ColorScaleLegend.js +68 -0
  128. package/lib/color/ui/ColorScaleLegend.js.map +1 -0
  129. package/lib/color/ui/index.d.ts +3 -0
  130. package/lib/color/ui/index.d.ts.map +1 -0
  131. package/lib/color/ui/index.js +2 -0
  132. package/lib/color/ui/index.js.map +1 -0
  133. package/lib/core.d.ts +11 -0
  134. package/lib/core.d.ts.map +1 -1
  135. package/lib/core.js +11 -0
  136. package/lib/core.js.map +1 -1
  137. package/lib/credits/core/credits.d.ts +144 -0
  138. package/lib/credits/core/credits.d.ts.map +1 -0
  139. package/lib/credits/core/credits.js +156 -0
  140. package/lib/credits/core/credits.js.map +1 -0
  141. package/lib/credits/core/index.d.ts +3 -0
  142. package/lib/credits/core/index.d.ts.map +1 -0
  143. package/lib/credits/core/index.js +2 -0
  144. package/lib/credits/core/index.js.map +1 -0
  145. package/lib/credits/ui/CreditsList.d.ts +29 -0
  146. package/lib/credits/ui/CreditsList.d.ts.map +1 -0
  147. package/lib/credits/ui/CreditsList.js +33 -0
  148. package/lib/credits/ui/CreditsList.js.map +1 -0
  149. package/lib/credits/ui/index.d.ts +3 -0
  150. package/lib/credits/ui/index.d.ts.map +1 -0
  151. package/lib/credits/ui/index.js +2 -0
  152. package/lib/credits/ui/index.js.map +1 -0
  153. package/lib/delimited/core/delimiters.d.ts +31 -0
  154. package/lib/delimited/core/delimiters.d.ts.map +1 -0
  155. package/lib/delimited/core/delimiters.js +46 -0
  156. package/lib/delimited/core/delimiters.js.map +1 -0
  157. package/lib/delimited/core/index.d.ts +9 -0
  158. package/lib/delimited/core/index.d.ts.map +1 -0
  159. package/lib/delimited/core/index.js +5 -0
  160. package/lib/delimited/core/index.js.map +1 -0
  161. package/lib/delimited/core/readDelimited.d.ts +32 -0
  162. package/lib/delimited/core/readDelimited.d.ts.map +1 -0
  163. package/lib/delimited/core/readDelimited.js +122 -0
  164. package/lib/delimited/core/readDelimited.js.map +1 -0
  165. package/lib/delimited/core/rowsToDelimited.d.ts +59 -0
  166. package/lib/delimited/core/rowsToDelimited.d.ts.map +1 -0
  167. package/lib/delimited/core/rowsToDelimited.js +87 -0
  168. package/lib/delimited/core/rowsToDelimited.js.map +1 -0
  169. package/lib/delimited/core/toDelimited.d.ts +38 -0
  170. package/lib/delimited/core/toDelimited.d.ts.map +1 -0
  171. package/lib/delimited/core/toDelimited.js +45 -0
  172. package/lib/delimited/core/toDelimited.js.map +1 -0
  173. package/lib/delimited/ui/DelimitedTextDialog.d.ts +22 -0
  174. package/lib/delimited/ui/DelimitedTextDialog.d.ts.map +1 -0
  175. package/lib/delimited/ui/DelimitedTextDialog.js +17 -0
  176. package/lib/delimited/ui/DelimitedTextDialog.js.map +1 -0
  177. package/lib/delimited/ui/DelimitedTextPanel.d.ts +56 -0
  178. package/lib/delimited/ui/DelimitedTextPanel.d.ts.map +1 -0
  179. package/lib/delimited/ui/DelimitedTextPanel.js +55 -0
  180. package/lib/delimited/ui/DelimitedTextPanel.js.map +1 -0
  181. package/lib/delimited/ui/index.d.ts +5 -0
  182. package/lib/delimited/ui/index.d.ts.map +1 -0
  183. package/lib/delimited/ui/index.js +3 -0
  184. package/lib/delimited/ui/index.js.map +1 -0
  185. package/lib/disclosure/ui/CollapsibleSection.d.ts +57 -0
  186. package/lib/disclosure/ui/CollapsibleSection.d.ts.map +1 -0
  187. package/lib/disclosure/ui/CollapsibleSection.js +60 -0
  188. package/lib/disclosure/ui/CollapsibleSection.js.map +1 -0
  189. package/lib/disclosure/ui/index.d.ts +5 -0
  190. package/lib/disclosure/ui/index.d.ts.map +1 -0
  191. package/lib/disclosure/ui/index.js +3 -0
  192. package/lib/disclosure/ui/index.js.map +1 -0
  193. package/lib/disclosure/ui/useDisclosure.d.ts +22 -0
  194. package/lib/disclosure/ui/useDisclosure.d.ts.map +1 -0
  195. package/lib/disclosure/ui/useDisclosure.js +18 -0
  196. package/lib/disclosure/ui/useDisclosure.js.map +1 -0
  197. package/lib/download/core/downloadBlob.d.ts +10 -0
  198. package/lib/download/core/downloadBlob.d.ts.map +1 -0
  199. package/lib/download/core/downloadBlob.js +20 -0
  200. package/lib/download/core/downloadBlob.js.map +1 -0
  201. package/lib/download/core/downloadText.d.ts +9 -0
  202. package/lib/download/core/downloadText.d.ts.map +1 -0
  203. package/lib/download/core/downloadText.js +14 -0
  204. package/lib/download/core/downloadText.js.map +1 -0
  205. package/lib/download/core/index.d.ts +4 -0
  206. package/lib/download/core/index.d.ts.map +1 -0
  207. package/lib/download/core/index.js +4 -0
  208. package/lib/download/core/index.js.map +1 -0
  209. package/lib/download/core/sanitizeFileName.d.ts +15 -0
  210. package/lib/download/core/sanitizeFileName.d.ts.map +1 -0
  211. package/lib/download/core/sanitizeFileName.js +33 -0
  212. package/lib/download/core/sanitizeFileName.js.map +1 -0
  213. package/lib/ecosystem/core/index.d.ts +3 -0
  214. package/lib/ecosystem/core/index.d.ts.map +1 -1
  215. package/lib/ecosystem/core/index.js +3 -0
  216. package/lib/ecosystem/core/index.js.map +1 -1
  217. package/lib/ecosystem/core/links.d.ts +11 -0
  218. package/lib/ecosystem/core/links.d.ts.map +1 -0
  219. package/lib/ecosystem/core/links.js +28 -0
  220. package/lib/ecosystem/core/links.js.map +1 -0
  221. package/lib/ecosystem/core/lookup.d.ts +32 -0
  222. package/lib/ecosystem/core/lookup.d.ts.map +1 -0
  223. package/lib/ecosystem/core/lookup.js +55 -0
  224. package/lib/ecosystem/core/lookup.js.map +1 -0
  225. package/lib/ecosystem/core/sites.d.ts +3 -1
  226. package/lib/ecosystem/core/sites.d.ts.map +1 -1
  227. package/lib/ecosystem/core/sites.js +18 -3
  228. package/lib/ecosystem/core/sites.js.map +1 -1
  229. package/lib/ecosystem/core/tokens.d.ts +21 -0
  230. package/lib/ecosystem/core/tokens.d.ts.map +1 -0
  231. package/lib/ecosystem/core/tokens.js +42 -0
  232. package/lib/ecosystem/core/tokens.js.map +1 -0
  233. package/lib/ecosystem/ui/SiteTheme.d.ts +18 -0
  234. package/lib/ecosystem/ui/SiteTheme.d.ts.map +1 -0
  235. package/lib/ecosystem/ui/SiteTheme.js +16 -0
  236. package/lib/ecosystem/ui/SiteTheme.js.map +1 -0
  237. package/lib/ecosystem/ui/Wordmark.d.ts +30 -0
  238. package/lib/ecosystem/ui/Wordmark.d.ts.map +1 -0
  239. package/lib/ecosystem/ui/Wordmark.js +26 -0
  240. package/lib/ecosystem/ui/Wordmark.js.map +1 -0
  241. package/lib/ecosystem/ui/glyphs.js +1 -1
  242. package/lib/ecosystem/ui/glyphs.js.map +1 -1
  243. package/lib/ecosystem/ui/index.d.ts +4 -0
  244. package/lib/ecosystem/ui/index.d.ts.map +1 -1
  245. package/lib/ecosystem/ui/index.js +2 -0
  246. package/lib/ecosystem/ui/index.js.map +1 -1
  247. package/lib/ecosystem/ui/marks.d.ts +30 -4
  248. package/lib/ecosystem/ui/marks.d.ts.map +1 -1
  249. package/lib/ecosystem/ui/marks.js +13 -3
  250. package/lib/ecosystem/ui/marks.js.map +1 -1
  251. package/lib/error/ui/ErrorBoundary.d.ts +60 -0
  252. package/lib/error/ui/ErrorBoundary.d.ts.map +1 -0
  253. package/lib/error/ui/ErrorBoundary.js +59 -0
  254. package/lib/error/ui/ErrorBoundary.js.map +1 -0
  255. package/lib/error/ui/ErrorFallback.d.ts +38 -0
  256. package/lib/error/ui/ErrorFallback.d.ts.map +1 -0
  257. package/lib/error/ui/ErrorFallback.js +16 -0
  258. package/lib/error/ui/ErrorFallback.js.map +1 -0
  259. package/lib/error/ui/index.d.ts +5 -0
  260. package/lib/error/ui/index.d.ts.map +1 -0
  261. package/lib/error/ui/index.js +3 -0
  262. package/lib/error/ui/index.js.map +1 -0
  263. package/lib/error/ui/toError.d.ts +11 -0
  264. package/lib/error/ui/toError.d.ts.map +1 -0
  265. package/lib/error/ui/toError.js +35 -0
  266. package/lib/error/ui/toError.js.map +1 -0
  267. package/lib/format/core/index.d.ts +5 -0
  268. package/lib/format/core/index.d.ts.map +1 -0
  269. package/lib/format/core/index.js +5 -0
  270. package/lib/format/core/index.js.map +1 -0
  271. package/lib/format/core/missing.d.ts +7 -0
  272. package/lib/format/core/missing.d.ts.map +1 -0
  273. package/lib/format/core/missing.js +7 -0
  274. package/lib/format/core/missing.js.map +1 -0
  275. package/lib/format/core/numbers.d.ts +40 -0
  276. package/lib/format/core/numbers.d.ts.map +1 -0
  277. package/lib/format/core/numbers.js +81 -0
  278. package/lib/format/core/numbers.js.map +1 -0
  279. package/lib/format/core/units.d.ts +17 -0
  280. package/lib/format/core/units.d.ts.map +1 -0
  281. package/lib/format/core/units.js +54 -0
  282. package/lib/format/core/units.js.map +1 -0
  283. package/lib/format/core/words.d.ts +12 -0
  284. package/lib/format/core/words.d.ts.map +1 -0
  285. package/lib/format/core/words.js +14 -0
  286. package/lib/format/core/words.js.map +1 -0
  287. package/lib/help/ui/HelpBody.d.ts +57 -0
  288. package/lib/help/ui/HelpBody.d.ts.map +1 -0
  289. package/lib/help/ui/HelpBody.js +44 -0
  290. package/lib/help/ui/HelpBody.js.map +1 -0
  291. package/lib/help/ui/HelpIcon.d.ts +33 -0
  292. package/lib/help/ui/HelpIcon.d.ts.map +1 -0
  293. package/lib/help/ui/HelpIcon.js +16 -0
  294. package/lib/help/ui/HelpIcon.js.map +1 -0
  295. package/lib/help/ui/HelpToolbarButton.d.ts +45 -0
  296. package/lib/help/ui/HelpToolbarButton.d.ts.map +1 -0
  297. package/lib/help/ui/HelpToolbarButton.js +17 -0
  298. package/lib/help/ui/HelpToolbarButton.js.map +1 -0
  299. package/lib/help/ui/HelpTooltip.d.ts +36 -0
  300. package/lib/help/ui/HelpTooltip.d.ts.map +1 -0
  301. package/lib/help/ui/HelpTooltip.js +24 -0
  302. package/lib/help/ui/HelpTooltip.js.map +1 -0
  303. package/lib/help/ui/index.d.ts +9 -0
  304. package/lib/help/ui/index.d.ts.map +1 -0
  305. package/lib/help/ui/index.js +5 -0
  306. package/lib/help/ui/index.js.map +1 -0
  307. package/lib/hooks/ui/index.d.ts +7 -0
  308. package/lib/hooks/ui/index.d.ts.map +1 -0
  309. package/lib/hooks/ui/index.js +5 -0
  310. package/lib/hooks/ui/index.js.map +1 -0
  311. package/lib/hooks/ui/listNavigation.d.ts +54 -0
  312. package/lib/hooks/ui/listNavigation.d.ts.map +1 -0
  313. package/lib/hooks/ui/listNavigation.js +77 -0
  314. package/lib/hooks/ui/listNavigation.js.map +1 -0
  315. package/lib/hooks/ui/useContainerSize.d.ts +15 -0
  316. package/lib/hooks/ui/useContainerSize.d.ts.map +1 -0
  317. package/lib/hooks/ui/useContainerSize.js +24 -0
  318. package/lib/hooks/ui/useContainerSize.js.map +1 -0
  319. package/lib/hooks/ui/useDebouncedValue.d.ts +12 -0
  320. package/lib/hooks/ui/useDebouncedValue.d.ts.map +1 -0
  321. package/lib/hooks/ui/useDebouncedValue.js +24 -0
  322. package/lib/hooks/ui/useDebouncedValue.js.map +1 -0
  323. package/lib/hooks/ui/useListKeyboardNavigation.d.ts +17 -0
  324. package/lib/hooks/ui/useListKeyboardNavigation.d.ts.map +1 -0
  325. package/lib/hooks/ui/useListKeyboardNavigation.js +25 -0
  326. package/lib/hooks/ui/useListKeyboardNavigation.js.map +1 -0
  327. package/lib/hooks/ui/useResizeObserver.d.ts +20 -0
  328. package/lib/hooks/ui/useResizeObserver.d.ts.map +1 -0
  329. package/lib/hooks/ui/useResizeObserver.js +37 -0
  330. package/lib/hooks/ui/useResizeObserver.js.map +1 -0
  331. package/lib/orbital/core/atomicGrid.d.ts +27 -0
  332. package/lib/orbital/core/atomicGrid.d.ts.map +1 -1
  333. package/lib/orbital/core/atomicGrid.js +37 -1
  334. package/lib/orbital/core/atomicGrid.js.map +1 -1
  335. package/lib/orbital/core/index.d.ts +9 -7
  336. package/lib/orbital/core/index.d.ts.map +1 -1
  337. package/lib/orbital/core/index.js +7 -6
  338. package/lib/orbital/core/index.js.map +1 -1
  339. package/lib/orbital/core/isovalue.d.ts +60 -0
  340. package/lib/orbital/core/isovalue.d.ts.map +1 -0
  341. package/lib/orbital/core/isovalue.js +128 -0
  342. package/lib/orbital/core/isovalue.js.map +1 -0
  343. package/lib/orbital/core/sample.d.ts +15 -1
  344. package/lib/orbital/core/sample.d.ts.map +1 -1
  345. package/lib/orbital/core/sample.js +10 -3
  346. package/lib/orbital/core/sample.js.map +1 -1
  347. package/lib/orbital/ui/AtomicOrbitalCanvas.d.ts +6 -1
  348. package/lib/orbital/ui/AtomicOrbitalCanvas.d.ts.map +1 -1
  349. package/lib/orbital/ui/AtomicOrbitalCanvas.js +12 -2
  350. package/lib/orbital/ui/AtomicOrbitalCanvas.js.map +1 -1
  351. package/lib/orbital/ui/AtomicOrbitalViewer.d.ts +5 -1
  352. package/lib/orbital/ui/AtomicOrbitalViewer.d.ts.map +1 -1
  353. package/lib/orbital/ui/AtomicOrbitalViewer.js.map +1 -1
  354. package/lib/orbital/ui/renderVolume.d.ts +6 -3
  355. package/lib/orbital/ui/renderVolume.d.ts.map +1 -1
  356. package/lib/orbital/ui/renderVolume.js +14 -15
  357. package/lib/orbital/ui/renderVolume.js.map +1 -1
  358. package/lib/orbital/ui/viewer.d.ts +3 -1
  359. package/lib/orbital/ui/viewer.d.ts.map +1 -1
  360. package/lib/orbital/ui/viewer.js +3 -2
  361. package/lib/orbital/ui/viewer.js.map +1 -1
  362. package/lib/orbital/ui/volumeField.d.ts +5 -21
  363. package/lib/orbital/ui/volumeField.d.ts.map +1 -1
  364. package/lib/orbital/ui/volumeField.js +5 -45
  365. package/lib/orbital/ui/volumeField.js.map +1 -1
  366. package/lib/pedagogy/core/glossary.d.ts +79 -0
  367. package/lib/pedagogy/core/glossary.d.ts.map +1 -0
  368. package/lib/pedagogy/core/glossary.js +71 -0
  369. package/lib/pedagogy/core/glossary.js.map +1 -0
  370. package/lib/pedagogy/core/index.d.ts +8 -0
  371. package/lib/pedagogy/core/index.d.ts.map +1 -0
  372. package/lib/pedagogy/core/index.js +4 -0
  373. package/lib/pedagogy/core/index.js.map +1 -0
  374. package/lib/pedagogy/core/jsonStorage.d.ts +21 -0
  375. package/lib/pedagogy/core/jsonStorage.d.ts.map +1 -0
  376. package/lib/pedagogy/core/jsonStorage.js +55 -0
  377. package/lib/pedagogy/core/jsonStorage.js.map +1 -0
  378. package/lib/pedagogy/core/progress.d.ts +116 -0
  379. package/lib/pedagogy/core/progress.d.ts.map +1 -0
  380. package/lib/pedagogy/core/progress.js +122 -0
  381. package/lib/pedagogy/core/progress.js.map +1 -0
  382. package/lib/pedagogy/core/types.d.ts +74 -0
  383. package/lib/pedagogy/core/types.d.ts.map +1 -0
  384. package/lib/pedagogy/core/types.js +8 -0
  385. package/lib/pedagogy/core/types.js.map +1 -0
  386. package/lib/pedagogy/core/validation.d.ts +79 -0
  387. package/lib/pedagogy/core/validation.d.ts.map +1 -0
  388. package/lib/pedagogy/core/validation.js +47 -0
  389. package/lib/pedagogy/core/validation.js.map +1 -0
  390. package/lib/pedagogy/ui/ExerciseActions.d.ts +74 -0
  391. package/lib/pedagogy/ui/ExerciseActions.d.ts.map +1 -0
  392. package/lib/pedagogy/ui/ExerciseActions.js +22 -0
  393. package/lib/pedagogy/ui/ExerciseActions.js.map +1 -0
  394. package/lib/pedagogy/ui/ExerciseProgressHeader.d.ts +43 -0
  395. package/lib/pedagogy/ui/ExerciseProgressHeader.d.ts.map +1 -0
  396. package/lib/pedagogy/ui/ExerciseProgressHeader.js +43 -0
  397. package/lib/pedagogy/ui/ExerciseProgressHeader.js.map +1 -0
  398. package/lib/pedagogy/ui/ExerciseTags.d.ts +49 -0
  399. package/lib/pedagogy/ui/ExerciseTags.d.ts.map +1 -0
  400. package/lib/pedagogy/ui/ExerciseTags.js +22 -0
  401. package/lib/pedagogy/ui/ExerciseTags.js.map +1 -0
  402. package/lib/pedagogy/ui/GlossaryProvider.d.ts +19 -0
  403. package/lib/pedagogy/ui/GlossaryProvider.d.ts.map +1 -0
  404. package/lib/pedagogy/ui/GlossaryProvider.js +16 -0
  405. package/lib/pedagogy/ui/GlossaryProvider.js.map +1 -0
  406. package/lib/pedagogy/ui/GlossaryText.d.ts +50 -0
  407. package/lib/pedagogy/ui/GlossaryText.d.ts.map +1 -0
  408. package/lib/pedagogy/ui/GlossaryText.js +79 -0
  409. package/lib/pedagogy/ui/GlossaryText.js.map +1 -0
  410. package/lib/pedagogy/ui/HintLadder.d.ts +38 -0
  411. package/lib/pedagogy/ui/HintLadder.d.ts.map +1 -0
  412. package/lib/pedagogy/ui/HintLadder.js +33 -0
  413. package/lib/pedagogy/ui/HintLadder.js.map +1 -0
  414. package/lib/pedagogy/ui/ReferenceGrid.d.ts +31 -0
  415. package/lib/pedagogy/ui/ReferenceGrid.d.ts.map +1 -0
  416. package/lib/pedagogy/ui/ReferenceGrid.js +25 -0
  417. package/lib/pedagogy/ui/ReferenceGrid.js.map +1 -0
  418. package/lib/pedagogy/ui/ReferenceSectionBlock.d.ts +64 -0
  419. package/lib/pedagogy/ui/ReferenceSectionBlock.d.ts.map +1 -0
  420. package/lib/pedagogy/ui/ReferenceSectionBlock.js +78 -0
  421. package/lib/pedagogy/ui/ReferenceSectionBlock.js.map +1 -0
  422. package/lib/pedagogy/ui/SyntaxTooltip.d.ts +94 -0
  423. package/lib/pedagogy/ui/SyntaxTooltip.d.ts.map +1 -0
  424. package/lib/pedagogy/ui/SyntaxTooltip.js +79 -0
  425. package/lib/pedagogy/ui/SyntaxTooltip.js.map +1 -0
  426. package/lib/pedagogy/ui/TestCaseList.d.ts +35 -0
  427. package/lib/pedagogy/ui/TestCaseList.d.ts.map +1 -0
  428. package/lib/pedagogy/ui/TestCaseList.js +63 -0
  429. package/lib/pedagogy/ui/TestCaseList.js.map +1 -0
  430. package/lib/pedagogy/ui/TutorialStepStrip.d.ts +42 -0
  431. package/lib/pedagogy/ui/TutorialStepStrip.d.ts.map +1 -0
  432. package/lib/pedagogy/ui/TutorialStepStrip.js +98 -0
  433. package/lib/pedagogy/ui/TutorialStepStrip.js.map +1 -0
  434. package/lib/pedagogy/ui/exerciseMeta.d.ts +24 -0
  435. package/lib/pedagogy/ui/exerciseMeta.d.ts.map +1 -0
  436. package/lib/pedagogy/ui/exerciseMeta.js +38 -0
  437. package/lib/pedagogy/ui/exerciseMeta.js.map +1 -0
  438. package/lib/pedagogy/ui/glossaryContext.d.ts +17 -0
  439. package/lib/pedagogy/ui/glossaryContext.d.ts.map +1 -0
  440. package/lib/pedagogy/ui/glossaryContext.js +19 -0
  441. package/lib/pedagogy/ui/glossaryContext.js.map +1 -0
  442. package/lib/pedagogy/ui/index.d.ts +27 -0
  443. package/lib/pedagogy/ui/index.d.ts.map +1 -0
  444. package/lib/pedagogy/ui/index.js +15 -0
  445. package/lib/pedagogy/ui/index.js.map +1 -0
  446. package/lib/pedagogy/ui/tutorialLevels.d.ts +18 -0
  447. package/lib/pedagogy/ui/tutorialLevels.d.ts.map +1 -0
  448. package/lib/pedagogy/ui/tutorialLevels.js +14 -0
  449. package/lib/pedagogy/ui/tutorialLevels.js.map +1 -0
  450. package/lib/router/core/address.d.ts +42 -0
  451. package/lib/router/core/address.d.ts.map +1 -0
  452. package/lib/router/core/address.js +64 -0
  453. package/lib/router/core/address.js.map +1 -0
  454. package/lib/router/core/basePath.d.ts +49 -0
  455. package/lib/router/core/basePath.d.ts.map +1 -0
  456. package/lib/router/core/basePath.js +78 -0
  457. package/lib/router/core/basePath.js.map +1 -0
  458. package/lib/router/core/index.d.ts +8 -0
  459. package/lib/router/core/index.d.ts.map +1 -0
  460. package/lib/router/core/index.js +5 -0
  461. package/lib/router/core/index.js.map +1 -0
  462. package/lib/router/core/legacyHash.d.ts +45 -0
  463. package/lib/router/core/legacyHash.d.ts.map +1 -0
  464. package/lib/router/core/legacyHash.js +50 -0
  465. package/lib/router/core/legacyHash.js.map +1 -0
  466. package/lib/router/core/pageAddresses.d.ts +50 -0
  467. package/lib/router/core/pageAddresses.d.ts.map +1 -0
  468. package/lib/router/core/pageAddresses.js +56 -0
  469. package/lib/router/core/pageAddresses.js.map +1 -0
  470. package/lib/router/core/query.d.ts +41 -0
  471. package/lib/router/core/query.d.ts.map +1 -0
  472. package/lib/router/core/query.js +64 -0
  473. package/lib/router/core/query.js.map +1 -0
  474. package/lib/router/core/tabRouter.d.ts +111 -0
  475. package/lib/router/core/tabRouter.d.ts.map +1 -0
  476. package/lib/router/core/tabRouter.js +87 -0
  477. package/lib/router/core/tabRouter.js.map +1 -0
  478. package/lib/seo/core/documentMeta.d.ts +45 -0
  479. package/lib/seo/core/documentMeta.d.ts.map +1 -0
  480. package/lib/seo/core/documentMeta.js +69 -0
  481. package/lib/seo/core/documentMeta.js.map +1 -0
  482. package/lib/seo/core/index.d.ts +9 -0
  483. package/lib/seo/core/index.d.ts.map +1 -0
  484. package/lib/seo/core/index.js +5 -0
  485. package/lib/seo/core/index.js.map +1 -0
  486. package/lib/seo/core/pageMeta.d.ts +60 -0
  487. package/lib/seo/core/pageMeta.d.ts.map +1 -0
  488. package/lib/seo/core/pageMeta.js +91 -0
  489. package/lib/seo/core/pageMeta.js.map +1 -0
  490. package/lib/seo/core/routes.d.ts +52 -0
  491. package/lib/seo/core/routes.d.ts.map +1 -0
  492. package/lib/seo/core/routes.js +62 -0
  493. package/lib/seo/core/routes.js.map +1 -0
  494. package/lib/seo/core/siteFiles.d.ts +73 -0
  495. package/lib/seo/core/siteFiles.d.ts.map +1 -0
  496. package/lib/seo/core/siteFiles.js +100 -0
  497. package/lib/seo/core/siteFiles.js.map +1 -0
  498. package/lib/seo/vite/index.d.ts +5 -0
  499. package/lib/seo/vite/index.d.ts.map +1 -0
  500. package/lib/seo/vite/index.js +3 -0
  501. package/lib/seo/vite/index.js.map +1 -0
  502. package/lib/seo/vite/ogCard.d.ts +33 -0
  503. package/lib/seo/vite/ogCard.d.ts.map +1 -0
  504. package/lib/seo/vite/ogCard.js +72 -0
  505. package/lib/seo/vite/ogCard.js.map +1 -0
  506. package/lib/seo/vite/prerender.d.ts +58 -0
  507. package/lib/seo/vite/prerender.d.ts.map +1 -0
  508. package/lib/seo/vite/prerender.js +76 -0
  509. package/lib/seo/vite/prerender.js.map +1 -0
  510. package/lib/share/core/config.d.ts +63 -0
  511. package/lib/share/core/config.d.ts.map +1 -0
  512. package/lib/share/core/config.js +125 -0
  513. package/lib/share/core/config.js.map +1 -0
  514. package/lib/share/core/escape.d.ts +15 -0
  515. package/lib/share/core/escape.d.ts.map +1 -0
  516. package/lib/share/core/escape.js +22 -0
  517. package/lib/share/core/escape.js.map +1 -0
  518. package/lib/share/core/index.d.ts +9 -0
  519. package/lib/share/core/index.d.ts.map +1 -0
  520. package/lib/share/core/index.js +5 -0
  521. package/lib/share/core/index.js.map +1 -0
  522. package/lib/share/core/params.d.ts +93 -0
  523. package/lib/share/core/params.d.ts.map +1 -0
  524. package/lib/share/core/params.js +111 -0
  525. package/lib/share/core/params.js.map +1 -0
  526. package/lib/share/core/query.d.ts +30 -0
  527. package/lib/share/core/query.d.ts.map +1 -0
  528. package/lib/share/core/query.js +68 -0
  529. package/lib/share/core/query.js.map +1 -0
  530. package/lib/share/core/url.d.ts +57 -0
  531. package/lib/share/core/url.d.ts.map +1 -0
  532. package/lib/share/core/url.js +49 -0
  533. package/lib/share/core/url.js.map +1 -0
  534. package/lib/share/core/vocabulary.d.ts +51 -0
  535. package/lib/share/core/vocabulary.d.ts.map +1 -0
  536. package/lib/share/core/vocabulary.js +2 -0
  537. package/lib/share/core/vocabulary.js.map +1 -0
  538. package/lib/share/ui/HiddenPartsProvider.d.ts +19 -0
  539. package/lib/share/ui/HiddenPartsProvider.d.ts.map +1 -0
  540. package/lib/share/ui/HiddenPartsProvider.js +15 -0
  541. package/lib/share/ui/HiddenPartsProvider.js.map +1 -0
  542. package/lib/share/ui/PagePart.d.ts +18 -0
  543. package/lib/share/ui/PagePart.d.ts.map +1 -0
  544. package/lib/share/ui/PagePart.js +16 -0
  545. package/lib/share/ui/PagePart.js.map +1 -0
  546. package/lib/share/ui/ShareButton.d.ts +42 -0
  547. package/lib/share/ui/ShareButton.d.ts.map +1 -0
  548. package/lib/share/ui/ShareButton.js +18 -0
  549. package/lib/share/ui/ShareButton.js.map +1 -0
  550. package/lib/share/ui/ShareDialog.d.ts +73 -0
  551. package/lib/share/ui/ShareDialog.d.ts.map +1 -0
  552. package/lib/share/ui/ShareDialog.js +19 -0
  553. package/lib/share/ui/ShareDialog.js.map +1 -0
  554. package/lib/share/ui/ShareDialogContent.d.ts +13 -0
  555. package/lib/share/ui/ShareDialogContent.d.ts.map +1 -0
  556. package/lib/share/ui/ShareDialogContent.js +71 -0
  557. package/lib/share/ui/ShareDialogContent.js.map +1 -0
  558. package/lib/share/ui/SharePartOptions.d.ts +18 -0
  559. package/lib/share/ui/SharePartOptions.d.ts.map +1 -0
  560. package/lib/share/ui/SharePartOptions.js +22 -0
  561. package/lib/share/ui/SharePartOptions.js.map +1 -0
  562. package/lib/share/ui/draft.d.ts +13 -0
  563. package/lib/share/ui/draft.d.ts.map +1 -0
  564. package/lib/share/ui/draft.js +16 -0
  565. package/lib/share/ui/draft.js.map +1 -0
  566. package/lib/share/ui/hiddenParts.d.ts +17 -0
  567. package/lib/share/ui/hiddenParts.d.ts.map +1 -0
  568. package/lib/share/ui/hiddenParts.js +21 -0
  569. package/lib/share/ui/hiddenParts.js.map +1 -0
  570. package/lib/share/ui/index.d.ts +10 -0
  571. package/lib/share/ui/index.d.ts.map +1 -0
  572. package/lib/share/ui/index.js +6 -0
  573. package/lib/share/ui/index.js.map +1 -0
  574. package/lib/shared/ui/index.d.ts +2 -1
  575. package/lib/shared/ui/index.d.ts.map +1 -1
  576. package/lib/shared/ui/index.js +1 -1
  577. package/lib/shared/ui/index.js.map +1 -1
  578. package/lib/state/ui/index.d.ts +3 -0
  579. package/lib/state/ui/index.d.ts.map +1 -0
  580. package/lib/state/ui/index.js +2 -0
  581. package/lib/state/ui/index.js.map +1 -0
  582. package/lib/state/ui/mergeStored.d.ts +27 -0
  583. package/lib/state/ui/mergeStored.d.ts.map +1 -0
  584. package/lib/state/ui/mergeStored.js +82 -0
  585. package/lib/state/ui/mergeStored.js.map +1 -0
  586. package/lib/state/ui/persistBucket.d.ts +65 -0
  587. package/lib/state/ui/persistBucket.d.ts.map +1 -0
  588. package/lib/state/ui/persistBucket.js +90 -0
  589. package/lib/state/ui/persistBucket.js.map +1 -0
  590. package/lib/structure/core/editorValue.d.ts +69 -0
  591. package/lib/structure/core/editorValue.d.ts.map +1 -0
  592. package/lib/structure/core/editorValue.js +72 -0
  593. package/lib/structure/core/editorValue.js.map +1 -0
  594. package/lib/structure/core/fragmentQuery.d.ts +33 -0
  595. package/lib/structure/core/fragmentQuery.d.ts.map +1 -0
  596. package/lib/structure/core/fragmentQuery.js +37 -0
  597. package/lib/structure/core/fragmentQuery.js.map +1 -0
  598. package/lib/structure/core/index.d.ts +11 -0
  599. package/lib/structure/core/index.d.ts.map +1 -0
  600. package/lib/structure/core/index.js +6 -0
  601. package/lib/structure/core/index.js.map +1 -0
  602. package/lib/structure/core/molfile.d.ts +42 -0
  603. package/lib/structure/core/molfile.d.ts.map +1 -0
  604. package/lib/structure/core/molfile.js +74 -0
  605. package/lib/structure/core/molfile.js.map +1 -0
  606. package/lib/structure/core/readStructure.d.ts +37 -0
  607. package/lib/structure/core/readStructure.d.ts.map +1 -0
  608. package/lib/structure/core/readStructure.js +59 -0
  609. package/lib/structure/core/readStructure.js.map +1 -0
  610. package/lib/structure/core/structureSource.d.ts +34 -0
  611. package/lib/structure/core/structureSource.d.ts.map +1 -0
  612. package/lib/structure/core/structureSource.js +32 -0
  613. package/lib/structure/core/structureSource.js.map +1 -0
  614. package/lib/structure/core/toolbarFloor.d.ts +16 -0
  615. package/lib/structure/core/toolbarFloor.d.ts.map +1 -0
  616. package/lib/structure/core/toolbarFloor.js +27 -0
  617. package/lib/structure/core/toolbarFloor.js.map +1 -0
  618. package/lib/structure/ui/EditorCanvas.d.ts +55 -0
  619. package/lib/structure/ui/EditorCanvas.d.ts.map +1 -0
  620. package/lib/structure/ui/EditorCanvas.js +41 -0
  621. package/lib/structure/ui/EditorCanvas.js.map +1 -0
  622. package/lib/structure/ui/Structure.d.ts +122 -0
  623. package/lib/structure/ui/Structure.d.ts.map +1 -0
  624. package/lib/structure/ui/Structure.js +28 -0
  625. package/lib/structure/ui/Structure.js.map +1 -0
  626. package/lib/structure/ui/StructureEditor.d.ts +75 -0
  627. package/lib/structure/ui/StructureEditor.d.ts.map +1 -0
  628. package/lib/structure/ui/StructureEditor.js +83 -0
  629. package/lib/structure/ui/StructureEditor.js.map +1 -0
  630. package/lib/structure/ui/StructurePlaceholder.d.ts +29 -0
  631. package/lib/structure/ui/StructurePlaceholder.d.ts.map +1 -0
  632. package/lib/structure/ui/StructurePlaceholder.js +19 -0
  633. package/lib/structure/ui/StructurePlaceholder.js.map +1 -0
  634. package/lib/structure/ui/StructureSvg.d.ts +58 -0
  635. package/lib/structure/ui/StructureSvg.d.ts.map +1 -0
  636. package/lib/structure/ui/StructureSvg.js +33 -0
  637. package/lib/structure/ui/StructureSvg.js.map +1 -0
  638. package/lib/structure/ui/index.d.ts +19 -0
  639. package/lib/structure/ui/index.d.ts.map +1 -0
  640. package/lib/structure/ui/index.js +15 -0
  641. package/lib/structure/ui/index.js.map +1 -0
  642. package/lib/structure/ui/useToolbarFloor.d.ts +26 -0
  643. package/lib/structure/ui/useToolbarFloor.d.ts.map +1 -0
  644. package/lib/structure/ui/useToolbarFloor.js +70 -0
  645. package/lib/structure/ui/useToolbarFloor.js.map +1 -0
  646. package/lib/structure.d.ts +3 -0
  647. package/lib/structure.d.ts.map +1 -0
  648. package/lib/structure.js +3 -0
  649. package/lib/structure.js.map +1 -0
  650. package/lib/ui.d.ts +13 -0
  651. package/lib/ui.d.ts.map +1 -1
  652. package/lib/ui.js +13 -0
  653. package/lib/ui.js.map +1 -1
  654. package/lib/vite.d.ts +2 -0
  655. package/lib/vite.d.ts.map +1 -0
  656. package/lib/vite.js +2 -0
  657. package/lib/vite.js.map +1 -0
  658. package/lib/worker/core/errors.d.ts +15 -0
  659. package/lib/worker/core/errors.d.ts.map +1 -0
  660. package/lib/worker/core/errors.js +15 -0
  661. package/lib/worker/core/errors.js.map +1 -0
  662. package/lib/worker/core/index.d.ts +5 -0
  663. package/lib/worker/core/index.d.ts.map +1 -0
  664. package/lib/worker/core/index.js +3 -0
  665. package/lib/worker/core/index.js.map +1 -0
  666. package/lib/worker/core/messages.d.ts +48 -0
  667. package/lib/worker/core/messages.d.ts.map +1 -0
  668. package/lib/worker/core/messages.js +2 -0
  669. package/lib/worker/core/messages.js.map +1 -0
  670. package/lib/worker/core/workerChannel.d.ts +69 -0
  671. package/lib/worker/core/workerChannel.d.ts.map +1 -0
  672. package/lib/worker/core/workerChannel.js +121 -0
  673. package/lib/worker/core/workerChannel.js.map +1 -0
  674. package/package.json +22 -4
  675. package/src/capsule/ui/CapsuleFilter.tsx +119 -0
  676. package/src/capsule/ui/index.ts +2 -0
  677. package/src/chrome/ui/NavLink.tsx +88 -0
  678. package/src/chrome/ui/NavMenuButton.tsx +95 -0
  679. package/src/chrome/ui/SiteFooter.tsx +65 -0
  680. package/src/chrome/ui/SiteHeader.tsx +119 -0
  681. package/src/chrome/ui/index.ts +11 -0
  682. package/src/chrome/ui/navItem.ts +60 -0
  683. package/src/chrome/ui/useCompactHeader.ts +81 -0
  684. package/src/citation/core/clipboard.ts +27 -11
  685. package/src/citation/core/download.ts +25 -15
  686. package/src/citation/core/index.ts +8 -3
  687. package/src/citation/core/works.ts +81 -0
  688. package/src/citation/ui/CitationMenu.tsx +104 -89
  689. package/src/citation/ui/CitationPreview.tsx +18 -8
  690. package/src/citation/ui/CiteButton.tsx +24 -9
  691. package/src/citation/ui/CopyFormatEntries.tsx +84 -0
  692. package/src/citation/ui/WorkEntry.tsx +80 -0
  693. package/src/citation/ui/entries.tsx +18 -20
  694. package/src/citation/ui/index.ts +10 -2
  695. package/src/citation/ui/useCopyFeedback.ts +76 -0
  696. package/src/clipboard/core/index.ts +1 -0
  697. package/src/clipboard/core/writeToClipboard.ts +47 -0
  698. package/src/clipboard/ui/CodeBlock.tsx +110 -0
  699. package/src/clipboard/ui/CopyButton.tsx +111 -0
  700. package/src/clipboard/ui/index.ts +9 -0
  701. package/src/clipboard/ui/useCopyToClipboard.ts +57 -0
  702. package/src/color/core/contrast.ts +85 -0
  703. package/src/color/core/hex.ts +57 -0
  704. package/src/color/core/index.ts +4 -0
  705. package/src/color/core/scale.ts +132 -0
  706. package/src/color/ui/ColorScaleLegend.tsx +144 -0
  707. package/src/color/ui/index.ts +2 -0
  708. package/src/core.ts +11 -0
  709. package/src/credits/core/credits.ts +183 -0
  710. package/src/credits/core/index.ts +2 -0
  711. package/src/credits/ui/CreditsList.tsx +82 -0
  712. package/src/credits/ui/index.ts +2 -0
  713. package/src/delimited/core/delimiters.ts +64 -0
  714. package/src/delimited/core/index.ts +11 -0
  715. package/src/delimited/core/readDelimited.ts +132 -0
  716. package/src/delimited/core/rowsToDelimited.ts +135 -0
  717. package/src/delimited/core/toDelimited.ts +69 -0
  718. package/src/delimited/ui/DelimitedTextDialog.tsx +49 -0
  719. package/src/delimited/ui/DelimitedTextPanel.tsx +161 -0
  720. package/src/delimited/ui/index.ts +4 -0
  721. package/src/disclosure/ui/CollapsibleSection.tsx +150 -0
  722. package/src/disclosure/ui/index.ts +4 -0
  723. package/src/disclosure/ui/useDisclosure.ts +35 -0
  724. package/src/download/core/downloadBlob.ts +19 -0
  725. package/src/download/core/downloadText.ts +19 -0
  726. package/src/download/core/index.ts +3 -0
  727. package/src/download/core/sanitizeFileName.ts +33 -0
  728. package/src/ecosystem/core/index.ts +3 -0
  729. package/src/ecosystem/core/links.ts +29 -0
  730. package/src/ecosystem/core/lookup.ts +57 -0
  731. package/src/ecosystem/core/sites.ts +21 -4
  732. package/src/ecosystem/core/tokens.ts +47 -0
  733. package/src/ecosystem/ui/SiteTheme.tsx +23 -0
  734. package/src/ecosystem/ui/Wordmark.tsx +65 -0
  735. package/src/ecosystem/ui/glyphs.tsx +1 -1
  736. package/src/ecosystem/ui/index.ts +4 -0
  737. package/src/ecosystem/ui/marks.tsx +54 -15
  738. package/src/error/ui/ErrorBoundary.tsx +94 -0
  739. package/src/error/ui/ErrorFallback.tsx +64 -0
  740. package/src/error/ui/index.ts +4 -0
  741. package/src/error/ui/toError.ts +33 -0
  742. package/src/format/core/index.ts +9 -0
  743. package/src/format/core/missing.ts +6 -0
  744. package/src/format/core/numbers.ts +84 -0
  745. package/src/format/core/units.ts +60 -0
  746. package/src/format/core/words.ts +17 -0
  747. package/src/help/ui/HelpBody.tsx +130 -0
  748. package/src/help/ui/HelpIcon.tsx +53 -0
  749. package/src/help/ui/HelpToolbarButton.tsx +72 -0
  750. package/src/help/ui/HelpTooltip.tsx +72 -0
  751. package/src/help/ui/index.ts +8 -0
  752. package/src/hooks/ui/index.ts +6 -0
  753. package/src/hooks/ui/listNavigation.ts +116 -0
  754. package/src/hooks/ui/useContainerSize.ts +32 -0
  755. package/src/hooks/ui/useDebouncedValue.ts +29 -0
  756. package/src/hooks/ui/useListKeyboardNavigation.ts +37 -0
  757. package/src/hooks/ui/useResizeObserver.ts +50 -0
  758. package/src/orbital/core/atomicGrid.ts +53 -1
  759. package/src/orbital/core/index.ts +7 -16
  760. package/src/orbital/core/isovalue.ts +146 -0
  761. package/src/orbital/core/sample.ts +25 -5
  762. package/src/orbital/ui/AtomicOrbitalCanvas.tsx +19 -3
  763. package/src/orbital/ui/AtomicOrbitalViewer.tsx +5 -1
  764. package/src/orbital/ui/renderVolume.ts +29 -16
  765. package/src/orbital/ui/viewer.ts +6 -1
  766. package/src/orbital/ui/volumeField.ts +5 -49
  767. package/src/pedagogy/core/glossary.ts +122 -0
  768. package/src/pedagogy/core/index.ts +28 -0
  769. package/src/pedagogy/core/jsonStorage.ts +51 -0
  770. package/src/pedagogy/core/progress.ts +205 -0
  771. package/src/pedagogy/core/types.ts +78 -0
  772. package/src/pedagogy/core/validation.ts +109 -0
  773. package/src/pedagogy/ui/ExerciseActions.tsx +129 -0
  774. package/src/pedagogy/ui/ExerciseProgressHeader.tsx +135 -0
  775. package/src/pedagogy/ui/ExerciseTags.tsx +85 -0
  776. package/src/pedagogy/ui/GlossaryProvider.tsx +31 -0
  777. package/src/pedagogy/ui/GlossaryText.tsx +164 -0
  778. package/src/pedagogy/ui/HintLadder.tsx +95 -0
  779. package/src/pedagogy/ui/ReferenceGrid.tsx +69 -0
  780. package/src/pedagogy/ui/ReferenceSectionBlock.tsx +175 -0
  781. package/src/pedagogy/ui/SyntaxTooltip.tsx +222 -0
  782. package/src/pedagogy/ui/TestCaseList.tsx +122 -0
  783. package/src/pedagogy/ui/TutorialStepStrip.tsx +230 -0
  784. package/src/pedagogy/ui/exerciseMeta.ts +45 -0
  785. package/src/pedagogy/ui/glossaryContext.ts +23 -0
  786. package/src/pedagogy/ui/index.ts +37 -0
  787. package/src/pedagogy/ui/tutorialLevels.ts +27 -0
  788. package/src/router/core/address.ts +74 -0
  789. package/src/router/core/basePath.ts +76 -0
  790. package/src/router/core/index.ts +26 -0
  791. package/src/router/core/legacyHash.ts +77 -0
  792. package/src/router/core/pageAddresses.ts +106 -0
  793. package/src/router/core/query.ts +87 -0
  794. package/src/router/core/tabRouter.ts +214 -0
  795. package/src/seo/core/documentMeta.ts +92 -0
  796. package/src/seo/core/index.ts +26 -0
  797. package/src/seo/core/pageMeta.ts +127 -0
  798. package/src/seo/core/routes.ts +79 -0
  799. package/src/seo/core/siteFiles.ts +150 -0
  800. package/src/seo/vite/index.ts +4 -0
  801. package/src/seo/vite/ogCard.ts +92 -0
  802. package/src/seo/vite/prerender.ts +156 -0
  803. package/src/share/core/config.ts +165 -0
  804. package/src/share/core/escape.ts +22 -0
  805. package/src/share/core/index.ts +31 -0
  806. package/src/share/core/params.ts +176 -0
  807. package/src/share/core/query.ts +72 -0
  808. package/src/share/core/url.ts +105 -0
  809. package/src/share/core/vocabulary.ts +60 -0
  810. package/src/share/ui/HiddenPartsProvider.tsx +34 -0
  811. package/src/share/ui/PagePart.tsx +26 -0
  812. package/src/share/ui/ShareButton.tsx +84 -0
  813. package/src/share/ui/ShareDialog.tsx +114 -0
  814. package/src/share/ui/ShareDialogContent.tsx +189 -0
  815. package/src/share/ui/SharePartOptions.tsx +51 -0
  816. package/src/share/ui/draft.ts +19 -0
  817. package/src/share/ui/hiddenParts.ts +22 -0
  818. package/src/share/ui/index.ts +9 -0
  819. package/src/shared/ui/index.ts +2 -1
  820. package/src/state/ui/index.ts +6 -0
  821. package/src/state/ui/mergeStored.ts +87 -0
  822. package/src/state/ui/persistBucket.ts +147 -0
  823. package/src/structure/core/editorValue.ts +116 -0
  824. package/src/structure/core/fragmentQuery.ts +50 -0
  825. package/src/structure/core/index.ts +13 -0
  826. package/src/structure/core/molfile.ts +90 -0
  827. package/src/structure/core/readStructure.ts +73 -0
  828. package/src/structure/core/structureSource.ts +57 -0
  829. package/src/structure/core/toolbarFloor.ts +31 -0
  830. package/src/structure/ui/EditorCanvas.tsx +130 -0
  831. package/src/structure/ui/Structure.tsx +183 -0
  832. package/src/structure/ui/StructureEditor.tsx +196 -0
  833. package/src/structure/ui/StructurePlaceholder.tsx +48 -0
  834. package/src/structure/ui/StructureSvg.tsx +110 -0
  835. package/src/structure/ui/index.ts +22 -0
  836. package/src/structure/ui/useToolbarFloor.ts +93 -0
  837. package/src/structure.ts +2 -0
  838. package/src/ui.ts +13 -0
  839. package/src/vite.ts +1 -0
  840. package/src/worker/core/errors.ts +15 -0
  841. package/src/worker/core/index.ts +8 -0
  842. package/src/worker/core/messages.ts +47 -0
  843. package/src/worker/core/workerChannel.ts +218 -0
  844. package/styles/chrome.css +223 -0
@@ -0,0 +1,106 @@
1
+ import { normalizePath, splitAddress } from './address.ts';
2
+ import { joinBasePath, normalizeBasePath, stripBasePath } from './basePath.ts';
3
+
4
+ /**
5
+ * The table of everything the site answers, read by the three things that must
6
+ * agree on it: the build, which writes one HTML file per entry and the sitemap
7
+ * listing them; the server or the entrypoint, which titles the page it hands
8
+ * out; and the running app, which retitles the tab after an in-app move.
9
+ *
10
+ * Pure and DOM-free, so the prerender script imports the same table under Node
11
+ * that the browser imports at run time. A page missing from it is a page a
12
+ * search engine only ever sees as the home page.
13
+ * @param options - The pages, in the order the site presents them.
14
+ * @returns The three lookups the build and the app share.
15
+ */
16
+ export function createPageAddresses<Page extends PageWithPath>(
17
+ options: PageAddressesOptions<Page>,
18
+ ): PageAddresses<Page> {
19
+ const pages = options.pages;
20
+ const first = pages[0];
21
+ if (first === undefined) {
22
+ throw new Error('createPageAddresses needs at least one page');
23
+ }
24
+ const home: Page = first;
25
+ const basePath = normalizeBasePath(options.basePath ?? '');
26
+
27
+ const byPath = new Map<string, Page>();
28
+ for (const page of pages) {
29
+ byPath.set(normalizePath(page.path), page);
30
+ }
31
+
32
+ function everyPage(): readonly Page[] {
33
+ return pages;
34
+ }
35
+
36
+ function canonicalPathOf(page: Page): string {
37
+ return joinBasePath(basePath, normalizePath(page.path));
38
+ }
39
+
40
+ function pageAt(address: string): Page {
41
+ const path = normalizePath(
42
+ stripBasePath(basePath, splitAddress(address).path),
43
+ );
44
+ const exact = byPath.get(path);
45
+ if (exact !== undefined) return exact;
46
+ return deepestPageUnder(pages, path) ?? home;
47
+ }
48
+
49
+ return { everyPage, canonicalPathOf, pageAt };
50
+ }
51
+
52
+ /** The one thing a page must carry: the address it is reachable at. */
53
+ export interface PageWithPath {
54
+ /** Address from the site's own root, e.g. `/exercises`. */
55
+ path: string;
56
+ }
57
+
58
+ /** How a site's pages are turned into addresses. */
59
+ export interface PageAddressesOptions<Page extends PageWithPath> {
60
+ /**
61
+ * Every page, deep addresses included. The first is the home page, and is
62
+ * what an address the site does not know opens.
63
+ */
64
+ pages: readonly Page[];
65
+ /**
66
+ * The path the site is served under: nothing on a host of its own, `/surge`
67
+ * as one tool among several on a shared one.
68
+ * @default ''
69
+ */
70
+ basePath?: string;
71
+ }
72
+
73
+ /** The lookups a site's pages answer. */
74
+ export interface PageAddresses<Page extends PageWithPath> {
75
+ /** Every page, in the order given: what the sitemap lists and the build writes. */
76
+ everyPage: () => readonly Page[];
77
+ /**
78
+ * The address a page is indexed under, mount path included and query string
79
+ * dropped — a structure being edited and a share configuration are not pages.
80
+ */
81
+ canonicalPathOf: (page: Page) => string;
82
+ /**
83
+ * The page an address opens. An address below a page it does not list is that
84
+ * page — a link written before an exercise was renamed still opens, and is
85
+ * indexed as the exercises — and an address it knows nothing about is the
86
+ * home page.
87
+ */
88
+ pageAt: (address: string) => Page;
89
+ }
90
+
91
+ function deepestPageUnder<Page extends PageWithPath>(
92
+ pages: readonly Page[],
93
+ path: string,
94
+ ): Page | undefined {
95
+ let deepest: Page | undefined;
96
+ let depth = 0;
97
+ for (const page of pages) {
98
+ const candidate = normalizePath(page.path);
99
+ if (candidate === '/' || candidate.length <= depth) continue;
100
+ if (path.startsWith(`${candidate}/`)) {
101
+ deepest = page;
102
+ depth = candidate.length;
103
+ }
104
+ }
105
+ return deepest;
106
+ }
@@ -0,0 +1,87 @@
1
+ import { safeDecode } from './address.ts';
2
+
3
+ /** How a query string is read and written. */
4
+ export interface QueryStringOptions {
5
+ /**
6
+ * Keep a `+` in a value as the character it is, rather than reading it as
7
+ * the space `URLSearchParams` decodes it to. A SMILES carries `+` for a
8
+ * charged atom, and `CC[N+](C)(C)C` handed out in a link has to survive.
9
+ * @default true
10
+ */
11
+ literalPlus?: boolean;
12
+ /**
13
+ * Write a parameter carrying nothing back as the bare key, so a hand-typed
14
+ * flag such as `?embed` survives the round trip. Left off, an empty value is
15
+ * dropped and an unconfigured link stays clean.
16
+ * @default false
17
+ */
18
+ keepEmptyValues?: boolean;
19
+ }
20
+
21
+ /**
22
+ * Read a query string.
23
+ *
24
+ * Forgiving by design, because the address is hand-editable and arrives from
25
+ * bookmarks, course pages and lecture slides: a repeated key keeps its last
26
+ * value, a key carrying nothing is kept as an empty value so a bare `?embed`
27
+ * reads as present, and an escape that does not decode is taken literally.
28
+ * @param search - The query string, with or without its leading `?`.
29
+ * @param options - How the values are decoded.
30
+ * @returns One entry per key, decoded.
31
+ */
32
+ export function parseQueryString(
33
+ search: string,
34
+ options: QueryStringOptions = {},
35
+ ): Record<string, string> {
36
+ const literalPlus = options.literalPlus ?? true;
37
+ const query: Record<string, string> = {};
38
+ const text = search.startsWith('?') ? search.slice(1) : search;
39
+ for (const part of text.split('&')) {
40
+ if (part === '') continue;
41
+ const index = part.indexOf('=');
42
+ const rawKey = index === -1 ? part : part.slice(0, index);
43
+ const rawValue = index === -1 ? '' : part.slice(index + 1);
44
+ const key = decodeValue(rawKey, literalPlus);
45
+ if (key === '') continue;
46
+ query[key] = decodeValue(rawValue, literalPlus);
47
+ }
48
+ return query;
49
+ }
50
+
51
+ /**
52
+ * Write a query string.
53
+ *
54
+ * A parameter left at nothing is dropped unless `keepEmptyValues` asks for it,
55
+ * and `undefined` or `null` removes a parameter outright, so a page can hand
56
+ * its whole state to this function and get back only what it actually carries.
57
+ * @param params - The parameters, in the order they should be written.
58
+ * @param options - How the values are encoded.
59
+ * @returns The query string, without its leading `?`, empty when nothing is carried.
60
+ */
61
+ export function formatQueryString(
62
+ params: Readonly<Record<string, string | undefined | null>>,
63
+ options: QueryStringOptions = {},
64
+ ): string {
65
+ const keepEmptyValues = options.keepEmptyValues ?? false;
66
+ const parts: string[] = [];
67
+ for (const [key, value] of Object.entries(params)) {
68
+ if (key === '' || value === undefined || value === null) continue;
69
+ if (value === '') {
70
+ if (keepEmptyValues) parts.push(encodeValue(key));
71
+ continue;
72
+ }
73
+ parts.push(`${encodeValue(key)}=${encodeValue(value)}`);
74
+ }
75
+ return parts.join('&');
76
+ }
77
+
78
+ // A comma is legal in a query value and is what separates the keys of `hide`
79
+ // and the formulas of a list; escaped to `%2C` a link stops being one a teacher
80
+ // can read out loud.
81
+ function encodeValue(value: string): string {
82
+ return encodeURIComponent(value).replaceAll('%2C', ',');
83
+ }
84
+
85
+ function decodeValue(value: string, literalPlus: boolean): string {
86
+ return safeDecode(literalPlus ? value : value.replaceAll('+', ' '));
87
+ }
@@ -0,0 +1,214 @@
1
+ import { splitAddress, splitPath } from './address.ts';
2
+ import { joinBasePath, normalizeBasePath, stripBasePath } from './basePath.ts';
3
+ import { pathFromLegacyHash } from './legacyHash.ts';
4
+ import type { QueryStringOptions } from './query.ts';
5
+ import { formatQueryString, parseQueryString } from './query.ts';
6
+
7
+ /**
8
+ * The two directions between an address and the page it names.
9
+ *
10
+ * Both functions are pure: they take and return strings, never touch
11
+ * `location`, and know none of the parameter names the tool carries — the share
12
+ * configuration owns those. That is what makes the round trip unit-testable
13
+ * without a DOM, and usable from a prerender script under Node.
14
+ * @param options - The tabs of the site and how their addresses are written.
15
+ * @returns The parser, the serialiser, and the test for a known tab.
16
+ */
17
+ export function createTabRouter<Tab extends string>(
18
+ options: TabRouterOptions<Tab>,
19
+ ): TabRouter<Tab> {
20
+ const mode = options.mode ?? 'path';
21
+ const basePath = normalizeBasePath(options.basePath ?? '');
22
+ const adoptLegacyHash = options.adoptLegacyHash ?? false;
23
+ const queryOptions: QueryStringOptions = {
24
+ literalPlus: options.literalPlus ?? true,
25
+ keepEmptyValues: options.keepEmptyValues ?? false,
26
+ };
27
+
28
+ const definitions = new Map<string, NormalizedTab>();
29
+ for (const tab of options.tabs) {
30
+ const definition = typeof tab === 'string' ? { id: tab } : tab;
31
+ definitions.set(definition.id, {
32
+ path: normalizeTabPath(definition.path ?? `/${definition.id}`),
33
+ takesId: definition.takesId ?? false,
34
+ });
35
+ }
36
+ definitions.set(
37
+ options.home,
38
+ definitions.get(options.home) ?? { path: '/', takesId: false },
39
+ );
40
+
41
+ const tabBySegment = new Map<string, Tab>();
42
+ for (const [id, definition] of definitions) {
43
+ const segment = definition.path.slice(1);
44
+ if (segment !== '') tabBySegment.set(segment, id as Tab);
45
+ }
46
+
47
+ function isTab(value: string): value is Tab {
48
+ return definitions.has(value);
49
+ }
50
+
51
+ function parse(address: string): TabRoute<Tab> {
52
+ const parts = readAddress(address, mode, basePath, adoptLegacyHash);
53
+ const params = parseQueryString(parts.search, queryOptions);
54
+ const segments = splitPath(parts.path);
55
+ const first = segments[0];
56
+ const tab = first === undefined ? undefined : tabBySegment.get(first);
57
+ if (tab === undefined) return { tab: options.home, id: null, params };
58
+ const second = segments[1];
59
+ const takesId = definitions.get(tab)?.takesId ?? false;
60
+ return { tab, id: takesId && second !== undefined ? second : null, params };
61
+ }
62
+
63
+ function format(route: TabRouteInput<Tab>): string {
64
+ const tab = definitions.has(route.tab) ? route.tab : options.home;
65
+ const definition = definitions.get(tab);
66
+ const base = tab === options.home ? '/' : (definition?.path ?? '/');
67
+ const id = definition?.takesId === true ? (route.id ?? null) : null;
68
+ const path =
69
+ id === null || base === '/' ? base : `${base}/${encodeURIComponent(id)}`;
70
+ const search = formatQueryString(route.params ?? {}, queryOptions);
71
+ const address = mode === 'hash' ? `#${path}` : joinBasePath(basePath, path);
72
+ return search === '' ? address : `${address}?${search}`;
73
+ }
74
+
75
+ return { parse, format, isTab };
76
+ }
77
+
78
+ /** A tab whose address carries more than the tab's own name. */
79
+ export interface TabDefinition<Tab extends string = string> {
80
+ /** Identifier of the tab, as the state and the components name it. */
81
+ id: Tab;
82
+ /**
83
+ * The address of the tab, from the site's own root. The home tab is always
84
+ * written as `/`, whatever it declares here, so the site has one address for
85
+ * it instead of two holding the same thing.
86
+ * @default `/${id}`
87
+ */
88
+ path?: string;
89
+ /**
90
+ * Whether the tab addresses one of its items in a second path segment — a
91
+ * tutorial step, an exercise, an element — so a lecturer can hand out a deep
92
+ * link and a crawler indexes each item as a page of its own.
93
+ * @default false
94
+ */
95
+ takesId?: boolean;
96
+ }
97
+
98
+ /** How the addresses of a site's tabs are read and written. */
99
+ export interface TabRouterOptions<Tab extends string> {
100
+ /** Every tab of the site, named on its own or described in full. */
101
+ tabs: ReadonlyArray<Tab | TabDefinition<Tab>>;
102
+ /**
103
+ * The tab living at the root, and the one an address the site does not know
104
+ * opens — a link written before a rename still lands somewhere.
105
+ */
106
+ home: Tab;
107
+ /**
108
+ * Whether the address is the path or the fragment. A public tool must use
109
+ * `'path'`: a `#` is dropped by half the tools that pass links around, the
110
+ * server never sees it, and a crawler indexes the whole site as one page.
111
+ * `'hash'` exists only so a site already routing that way can adopt this
112
+ * router before it moves.
113
+ * @default 'path'
114
+ */
115
+ mode?: 'path' | 'hash';
116
+ /**
117
+ * The path the site is served under: nothing on a host of its own, `/surge`
118
+ * as one tool among several on a shared one.
119
+ * @default ''
120
+ */
121
+ basePath?: string;
122
+ /**
123
+ * Read a `+` in a value as the character it is rather than as a space.
124
+ * Without it a shared SMILES breaks.
125
+ * @default true
126
+ */
127
+ literalPlus?: boolean;
128
+ /**
129
+ * Write a parameter carrying nothing back as the bare key, so a hand-typed
130
+ * `?embed` survives the round trip.
131
+ * @default false
132
+ */
133
+ keepEmptyValues?: boolean;
134
+ /**
135
+ * Also read an address whose page is named by an old `#/tab/item` fragment,
136
+ * so links handed out before the site routed by path keep working.
137
+ * @default false
138
+ */
139
+ adoptLegacyHash?: boolean;
140
+ }
141
+
142
+ /** Where the app is: which tab, what it has open, and how it is set up. */
143
+ export interface TabRoute<Tab extends string = string> {
144
+ /** The tab the address opens. */
145
+ tab: Tab;
146
+ /** The item its second segment names, `null` on a tab that takes none. */
147
+ id: string | null;
148
+ /** Decoded query parameters, the tool's own and the share configuration's. */
149
+ params: Record<string, string>;
150
+ }
151
+
152
+ /** A route as a caller writes it, the parts it does not carry left out. */
153
+ export interface TabRouteInput<Tab extends string = string> {
154
+ /** The tab to open; one the router does not know falls back to the home tab. */
155
+ tab: Tab;
156
+ /**
157
+ * The item the tab has open, ignored by a tab that addresses none.
158
+ * @default null
159
+ */
160
+ id?: string | null;
161
+ /**
162
+ * Query parameters to carry; an empty, `undefined` or `null` value is left out.
163
+ * @default {}
164
+ */
165
+ params?: Record<string, string | undefined | null>;
166
+ }
167
+
168
+ /** The string ↔ route mapping of a site. */
169
+ export interface TabRouter<Tab extends string = string> {
170
+ /**
171
+ * The route an address denotes. An unknown tab, a trailing slash, an empty
172
+ * address and an escape that does not decode all resolve to something
173
+ * sensible rather than throwing.
174
+ */
175
+ parse: (address: string) => TabRoute<Tab>;
176
+ /** The address a route is reachable at, mount path and query included. */
177
+ format: (route: TabRouteInput<Tab>) => string;
178
+ /** Whether a string read out of an address names one of the site's tabs. */
179
+ isTab: (value: string) => value is Tab;
180
+ }
181
+
182
+ interface NormalizedTab {
183
+ path: string;
184
+ takesId: boolean;
185
+ }
186
+
187
+ function readAddress(
188
+ address: string,
189
+ mode: 'path' | 'hash',
190
+ basePath: string,
191
+ adoptLegacyHash: boolean,
192
+ ): { path: string; search: string } {
193
+ if (mode === 'hash') {
194
+ const fragment = address.includes('#')
195
+ ? splitAddress(address).fragment
196
+ : address;
197
+ const { path, search } = splitAddress(fragment);
198
+ return { path, search };
199
+ }
200
+
201
+ const outer = splitAddress(address);
202
+ const path = stripBasePath(basePath, outer.path);
203
+ if (adoptLegacyHash && path === '/') {
204
+ const legacy = pathFromLegacyHash(address);
205
+ if (legacy !== null) return splitAddress(legacy);
206
+ }
207
+ return { path, search: outer.search };
208
+ }
209
+
210
+ function normalizeTabPath(path: string): string {
211
+ const opened = path.startsWith('/') ? path : `/${path}`;
212
+ const closed = opened.replace(/\/+$/, '');
213
+ return closed === '' ? '/' : closed;
214
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Keep the head in step with the page on screen after an in-app move.
3
+ *
4
+ * The server, or the build that wrote one file per address, already titled the
5
+ * page it handed out; this is what a click inside the app changes, and what a
6
+ * crawler that renders the page reads afterwards. Every access to the document
7
+ * is guarded, so a prerender script importing this under Node does nothing
8
+ * rather than throwing.
9
+ * @param meta - What the page on screen is called and where it is indexed.
10
+ */
11
+ export function writeDocumentMeta(meta: DocumentMeta): void {
12
+ if (typeof document === 'undefined') return;
13
+ documentTitle(meta.title);
14
+ if (meta.description !== undefined) metaDescription(meta.description);
15
+ if (meta.canonical !== undefined) canonicalLink(meta.canonical);
16
+ }
17
+
18
+ /**
19
+ * Name the browser tab.
20
+ * @param title - The title of the page, site name included.
21
+ */
22
+ export function documentTitle(title: string): void {
23
+ if (typeof document === 'undefined') return;
24
+ document.title = title;
25
+ }
26
+
27
+ /**
28
+ * Point the canonical link at the address the page is indexed under, creating
29
+ * the tag when the served page carries none.
30
+ *
31
+ * The query string is dropped, and so is any fragment: the structure being
32
+ * edited and the configuration a shared link carries are not pages of their
33
+ * own, and indexing them as such splits one result into hundreds.
34
+ * @param href - The address of the page, absolute so a crawler can resolve it.
35
+ */
36
+ export function canonicalLink(href: string): void {
37
+ if (typeof document === 'undefined') return;
38
+ const address = withoutQuery(href);
39
+ if (address === '') return;
40
+
41
+ const existing = document.querySelector<HTMLLinkElement>(
42
+ 'link[rel="canonical"]',
43
+ );
44
+ if (existing) {
45
+ existing.href = address;
46
+ return;
47
+ }
48
+
49
+ const link = document.createElement('link');
50
+ link.rel = 'canonical';
51
+ document.head.append(link);
52
+ link.href = address;
53
+ }
54
+
55
+ /** What a page is called and where it is indexed. */
56
+ export interface DocumentMeta {
57
+ /** The title of the tab, the search result and the shared card. */
58
+ title: string;
59
+ /**
60
+ * One sentence describing this page, in the words someone would search for.
61
+ * Left out, the description the page was served with stays as it is — which
62
+ * is what every crawler but a rendering one has already read.
63
+ * @default undefined
64
+ */
65
+ description?: string;
66
+ /**
67
+ * The absolute address the page is indexed under. Left out, the canonical
68
+ * link the page was served with stays as it is.
69
+ * @default undefined
70
+ */
71
+ canonical?: string;
72
+ }
73
+
74
+ function metaDescription(content: string): void {
75
+ const existing = document.querySelector<HTMLMetaElement>(
76
+ 'meta[name="description"]',
77
+ );
78
+ if (existing) {
79
+ existing.content = content;
80
+ return;
81
+ }
82
+
83
+ const meta = document.createElement('meta');
84
+ meta.name = 'description';
85
+ document.head.append(meta);
86
+ meta.content = content;
87
+ }
88
+
89
+ function withoutQuery(href: string): string {
90
+ const cut = href.search(/[?#]/);
91
+ return cut === -1 ? href : href.slice(0, cut);
92
+ }
@@ -0,0 +1,26 @@
1
+ export type { DocumentMeta } from './documentMeta.ts';
2
+ export {
3
+ canonicalLink,
4
+ documentTitle,
5
+ writeDocumentMeta,
6
+ } from './documentMeta.ts';
7
+ export type { PageMetaOptions } from './pageMeta.ts';
8
+ export {
9
+ injectPageMeta,
10
+ insertBeforeHeadEnd,
11
+ pageDocumentMeta,
12
+ } from './pageMeta.ts';
13
+ export type { RouteMeta } from './routes.ts';
14
+ export {
15
+ homeRoute,
16
+ pageMetaFor,
17
+ routeFor,
18
+ trimTrailingSlash,
19
+ } from './routes.ts';
20
+ export type { SiteFilesOptions, StructuredDataOptions } from './siteFiles.ts';
21
+ export {
22
+ noscriptIndex,
23
+ robotsTxt,
24
+ sitemapXml,
25
+ structuredDataScript,
26
+ } from './siteFiles.ts';
@@ -0,0 +1,127 @@
1
+ /**
2
+ * The head of the page a crawler is handed.
3
+ *
4
+ * Googlebot renders JavaScript, but Bing, a Slack unfurl, an LMS preview and
5
+ * every academic indexer read the HTML that came off the wire — so the title,
6
+ * the description and the canonical of a page must already be in it. A site
7
+ * with a server rewrites them per request; a static one writes one file per
8
+ * address at build time. Both call this, which is pure string work: no
9
+ * `window`, no `node:fs`.
10
+ */
11
+
12
+ import { siteById, siteDisplayName } from '../../ecosystem/core/lookup.ts';
13
+ import type { EcosystemSite, SiteId } from '../../ecosystem/core/sites.ts';
14
+ import { escapeAttribute, escapeText } from '../../share/core/escape.ts';
15
+
16
+ import type { DocumentMeta } from './documentMeta.ts';
17
+ import type { RouteMeta } from './routes.ts';
18
+ import { pageMetaFor, trimTrailingSlash } from './routes.ts';
19
+
20
+ /** Which site is being served, and what it answers. */
21
+ export interface PageMetaOptions {
22
+ /** The site, named or passed. */
23
+ site: EcosystemSite | SiteId;
24
+ /** Every address it answers, each with its title and description. */
25
+ routes: readonly RouteMeta[];
26
+ /** The address being written, query string included. */
27
+ url: string;
28
+ /**
29
+ * Origin every absolute address is built on. A server passes the one the
30
+ * request arrived on; a build leaves it out and the site's own host is used.
31
+ * @default `https://<the site's host>`
32
+ */
33
+ origin?: string;
34
+ /**
35
+ * The card a link to the page unfurls into, as an absolute address or a path.
36
+ * @default '/og.png'
37
+ */
38
+ image?: string;
39
+ }
40
+
41
+ /**
42
+ * Give a page the title, the description and the canonical address of the route
43
+ * it answers, plus the card a link to it unfurls into.
44
+ * @param html - The built page.
45
+ * @param options - Which site, which address, and where it is served from.
46
+ * @returns The page, with its head rewritten for that route.
47
+ */
48
+ export function injectPageMeta(html: string, options: PageMetaOptions): string {
49
+ const site = resolveSite(options.site);
50
+ const meta = pageMetaFor(options.routes, options.url);
51
+ const name = siteDisplayName(site);
52
+ const origin = trimTrailingSlash(options.origin ?? `https://${site.host}`);
53
+ const { title, canonical } = pageDocumentMeta(options);
54
+ const image = absolute(options.image ?? '/og.png', origin);
55
+
56
+ const head = [
57
+ `<link rel="canonical" href="${escapeAttribute(canonical)}" />`,
58
+ '<meta property="og:type" content="website" />',
59
+ `<meta property="og:site_name" content="${escapeAttribute(name)}" />`,
60
+ `<meta property="og:title" content="${escapeAttribute(title)}" />`,
61
+ `<meta property="og:description" content="${escapeAttribute(meta.description)}" />`,
62
+ `<meta property="og:url" content="${escapeAttribute(canonical)}" />`,
63
+ `<meta property="og:image" content="${escapeAttribute(image)}" />`,
64
+ '<meta name="twitter:card" content="summary_large_image" />',
65
+ ].join('\n');
66
+
67
+ return insertBeforeHeadEnd(
68
+ replaceDescription(replaceTitle(html, title), meta.description),
69
+ head,
70
+ );
71
+ }
72
+
73
+ /**
74
+ * What the page on screen is called and where it is indexed, for the app to
75
+ * write after an in-app move.
76
+ *
77
+ * The same title and canonical the build wrote into the file it served, so a
78
+ * click that changes the page cannot disagree with the page a crawler fetched.
79
+ * @param options - Which site, which address, and where it is served from.
80
+ * @returns The title, the description and the canonical of that address.
81
+ */
82
+ export function pageDocumentMeta(options: PageMetaOptions): Required<DocumentMeta> {
83
+ const site = resolveSite(options.site);
84
+ const meta = pageMetaFor(options.routes, options.url);
85
+ const origin = trimTrailingSlash(options.origin ?? `https://${site.host}`);
86
+ return {
87
+ title: `${meta.title} — ${siteDisplayName(site)}`,
88
+ description: meta.description,
89
+ canonical: `${origin}${meta.path}`,
90
+ };
91
+ }
92
+
93
+ /**
94
+ * Put an addition at the end of the head, where a tracking snippet and a
95
+ * structured-data block both belong.
96
+ * @param html - The page.
97
+ * @param addition - The markup to add, taken as written.
98
+ * @returns The page, with the addition before `</head>`.
99
+ */
100
+ export function insertBeforeHeadEnd(html: string, addition: string): string {
101
+ const head = html.lastIndexOf('</head>');
102
+ if (head === -1) return `${html}\n${addition}\n`;
103
+ return `${html.slice(0, head)}${addition}\n${html.slice(head)}`;
104
+ }
105
+
106
+ function resolveSite(site: EcosystemSite | SiteId): EcosystemSite {
107
+ return typeof site === 'string' ? siteById(site) : site;
108
+ }
109
+
110
+ function absolute(target: string, origin: string): string {
111
+ return target.startsWith('/') ? `${origin}${target}` : target;
112
+ }
113
+
114
+ function replaceTitle(html: string, title: string): string {
115
+ const replacement = `<title>${escapeText(title)}</title>`;
116
+ return html.includes('<title>')
117
+ ? html.replace(/<title>[\s\S]*?<\/title>/, replacement)
118
+ : insertBeforeHeadEnd(html, replacement);
119
+ }
120
+
121
+ function replaceDescription(html: string, description: string): string {
122
+ const replacement = `<meta name="description" content="${escapeAttribute(description)}" />`;
123
+ const existing = /<meta[^>]*name="description"[^>]*>/;
124
+ return existing.test(html)
125
+ ? html.replace(existing, replacement)
126
+ : insertBeforeHeadEnd(html, replacement);
127
+ }