react-cheminfo 0.7.0 → 0.9.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 (308) hide show
  1. package/README.md +60 -2
  2. package/bin/check-tokens.mjs +105 -0
  3. package/lib/about/core/about.d.ts +95 -0
  4. package/lib/about/core/about.d.ts.map +1 -0
  5. package/lib/about/core/about.js +78 -0
  6. package/lib/about/core/about.js.map +1 -0
  7. package/lib/about/core/index.d.ts +3 -0
  8. package/lib/about/core/index.d.ts.map +1 -0
  9. package/lib/about/core/index.js +2 -0
  10. package/lib/about/core/index.js.map +1 -0
  11. package/lib/about/ui/AboutCitations.d.ts +14 -0
  12. package/lib/about/ui/AboutCitations.d.ts.map +1 -0
  13. package/lib/about/ui/AboutCitations.js +40 -0
  14. package/lib/about/ui/AboutCitations.js.map +1 -0
  15. package/lib/about/ui/AboutPage.d.ts +32 -0
  16. package/lib/about/ui/AboutPage.d.ts.map +1 -0
  17. package/lib/about/ui/AboutPage.js +70 -0
  18. package/lib/about/ui/AboutPage.js.map +1 -0
  19. package/lib/about/ui/AboutSection.d.ts +23 -0
  20. package/lib/about/ui/AboutSection.d.ts.map +1 -0
  21. package/lib/about/ui/AboutSection.js +28 -0
  22. package/lib/about/ui/AboutSection.js.map +1 -0
  23. package/lib/about/ui/index.d.ts +7 -0
  24. package/lib/about/ui/index.d.ts.map +1 -0
  25. package/lib/about/ui/index.js +4 -0
  26. package/lib/about/ui/index.js.map +1 -0
  27. package/lib/chrome/ui/index.d.ts +1 -0
  28. package/lib/chrome/ui/index.d.ts.map +1 -1
  29. package/lib/chrome/ui/index.js +3 -0
  30. package/lib/chrome/ui/index.js.map +1 -1
  31. package/lib/citation/core/index.d.ts +1 -0
  32. package/lib/citation/core/index.d.ts.map +1 -1
  33. package/lib/citation/core/index.js +1 -0
  34. package/lib/citation/core/index.js.map +1 -1
  35. package/lib/citation/core/teachingPaper.d.ts +15 -0
  36. package/lib/citation/core/teachingPaper.d.ts.map +1 -0
  37. package/lib/citation/core/teachingPaper.js +32 -0
  38. package/lib/citation/core/teachingPaper.js.map +1 -0
  39. package/lib/clipboard/ui/CodeBlock.d.ts.map +1 -1
  40. package/lib/clipboard/ui/CodeBlock.js +4 -1
  41. package/lib/clipboard/ui/CodeBlock.js.map +1 -1
  42. package/lib/color/ui/ColorScaleLegend.js +1 -1
  43. package/lib/color/ui/ColorScaleLegend.js.map +1 -1
  44. package/lib/core.d.ts +3 -0
  45. package/lib/core.d.ts.map +1 -1
  46. package/lib/core.js +5 -0
  47. package/lib/core.js.map +1 -1
  48. package/lib/credits/core/credits.d.ts +36 -0
  49. package/lib/credits/core/credits.d.ts.map +1 -1
  50. package/lib/credits/core/credits.js +42 -0
  51. package/lib/credits/core/credits.js.map +1 -1
  52. package/lib/credits/ui/CreditsList.js +1 -1
  53. package/lib/credits/ui/CreditsList.js.map +1 -1
  54. package/lib/delimited/ui/DelimitedTextPanel.js +1 -1
  55. package/lib/delimited/ui/DelimitedTextPanel.js.map +1 -1
  56. package/lib/ecosystem/core/sites.d.ts +1 -1
  57. package/lib/ecosystem/core/sites.d.ts.map +1 -1
  58. package/lib/ecosystem/core/sites.js +10 -0
  59. package/lib/ecosystem/core/sites.js.map +1 -1
  60. package/lib/ecosystem/core/tokens.d.ts.map +1 -1
  61. package/lib/ecosystem/core/tokens.js +1 -0
  62. package/lib/ecosystem/core/tokens.js.map +1 -1
  63. package/lib/ecosystem/ui/EcosystemLinks.js +2 -2
  64. package/lib/ecosystem/ui/EcosystemLinks.js.map +1 -1
  65. package/lib/ecosystem/ui/EcosystemMenu.js +1 -1
  66. package/lib/ecosystem/ui/EcosystemMenu.js.map +1 -1
  67. package/lib/ecosystem/ui/SiteTile.d.ts.map +1 -1
  68. package/lib/ecosystem/ui/SiteTile.js +5 -5
  69. package/lib/ecosystem/ui/SiteTile.js.map +1 -1
  70. package/lib/ecosystem/ui/glyphs.d.ts.map +1 -1
  71. package/lib/ecosystem/ui/glyphs.js +3 -0
  72. package/lib/ecosystem/ui/glyphs.js.map +1 -1
  73. package/lib/orbital/core/index.d.ts +1 -1
  74. package/lib/orbital/core/index.d.ts.map +1 -1
  75. package/lib/orbital/core/index.js +1 -1
  76. package/lib/orbital/core/index.js.map +1 -1
  77. package/lib/orbital/core/realHarmonics.d.ts +5 -2
  78. package/lib/orbital/core/realHarmonics.d.ts.map +1 -1
  79. package/lib/orbital/core/realHarmonics.js.map +1 -1
  80. package/lib/orbital/ui/AtomicOrbitalCanvas.d.ts +18 -0
  81. package/lib/orbital/ui/AtomicOrbitalCanvas.d.ts.map +1 -1
  82. package/lib/orbital/ui/AtomicOrbitalCanvas.js +84 -7
  83. package/lib/orbital/ui/AtomicOrbitalCanvas.js.map +1 -1
  84. package/lib/orbital/ui/AtomicOrbitalViewer.d.ts +13 -0
  85. package/lib/orbital/ui/AtomicOrbitalViewer.d.ts.map +1 -1
  86. package/lib/orbital/ui/AtomicOrbitalViewer.js +1 -1
  87. package/lib/orbital/ui/AtomicOrbitalViewer.js.map +1 -1
  88. package/lib/orbital/ui/camera.d.ts +15 -0
  89. package/lib/orbital/ui/camera.d.ts.map +1 -1
  90. package/lib/orbital/ui/camera.js +68 -0
  91. package/lib/orbital/ui/camera.js.map +1 -1
  92. package/lib/orbital/ui/renderVolume.d.ts.map +1 -1
  93. package/lib/orbital/ui/renderVolume.js +8 -1
  94. package/lib/orbital/ui/renderVolume.js.map +1 -1
  95. package/lib/orbital/ui/serial.d.ts +25 -0
  96. package/lib/orbital/ui/serial.d.ts.map +1 -0
  97. package/lib/orbital/ui/serial.js +25 -0
  98. package/lib/orbital/ui/serial.js.map +1 -0
  99. package/lib/orbital/ui/viewer.d.ts +23 -0
  100. package/lib/orbital/ui/viewer.d.ts.map +1 -1
  101. package/lib/orbital/ui/viewer.js +70 -17
  102. package/lib/orbital/ui/viewer.js.map +1 -1
  103. package/lib/pedagogy/ui/ExerciseProgressHeader.js +1 -1
  104. package/lib/pedagogy/ui/ExerciseProgressHeader.js.map +1 -1
  105. package/lib/pedagogy/ui/GlossaryText.js +2 -2
  106. package/lib/pedagogy/ui/GlossaryText.js.map +1 -1
  107. package/lib/pedagogy/ui/ReferenceSectionBlock.js +5 -2
  108. package/lib/pedagogy/ui/ReferenceSectionBlock.js.map +1 -1
  109. package/lib/pedagogy/ui/SyntaxTooltip.js +2 -2
  110. package/lib/pedagogy/ui/SyntaxTooltip.js.map +1 -1
  111. package/lib/pedagogy/ui/TutorialStepStrip.d.ts +15 -2
  112. package/lib/pedagogy/ui/TutorialStepStrip.d.ts.map +1 -1
  113. package/lib/pedagogy/ui/TutorialStepStrip.js +19 -5
  114. package/lib/pedagogy/ui/TutorialStepStrip.js.map +1 -1
  115. package/lib/pedagogy/ui/index.d.ts +1 -1
  116. package/lib/pedagogy/ui/index.d.ts.map +1 -1
  117. package/lib/pedagogy/ui/index.js.map +1 -1
  118. package/lib/periodic/ui/CategoryLegend.js +1 -1
  119. package/lib/periodic/ui/CategoryLegend.js.map +1 -1
  120. package/lib/periodic/ui/PeriodicTableChrome.js +2 -2
  121. package/lib/periodic/ui/PeriodicTableChrome.js.map +1 -1
  122. package/lib/seo/vite/ogCard.d.ts.map +1 -1
  123. package/lib/seo/vite/ogCard.js +1 -0
  124. package/lib/seo/vite/ogCard.js.map +1 -1
  125. package/lib/share/ui/ShareDialogContent.d.ts.map +1 -1
  126. package/lib/share/ui/ShareDialogContent.js +5 -2
  127. package/lib/share/ui/ShareDialogContent.js.map +1 -1
  128. package/lib/share/ui/SharePartOptions.js +1 -1
  129. package/lib/share/ui/SharePartOptions.js.map +1 -1
  130. package/lib/slides/core/demoLinks.d.ts +43 -0
  131. package/lib/slides/core/demoLinks.d.ts.map +1 -0
  132. package/lib/slides/core/demoLinks.js +104 -0
  133. package/lib/slides/core/demoLinks.js.map +1 -0
  134. package/lib/slides/core/index.d.ts +13 -0
  135. package/lib/slides/core/index.d.ts.map +1 -0
  136. package/lib/slides/core/index.js +7 -0
  137. package/lib/slides/core/index.js.map +1 -0
  138. package/lib/slides/core/sectionHeading.d.ts +19 -0
  139. package/lib/slides/core/sectionHeading.d.ts.map +1 -0
  140. package/lib/slides/core/sectionHeading.js +19 -0
  141. package/lib/slides/core/sectionHeading.js.map +1 -0
  142. package/lib/slides/core/slideNavigation.d.ts +38 -0
  143. package/lib/slides/core/slideNavigation.d.ts.map +1 -0
  144. package/lib/slides/core/slideNavigation.js +65 -0
  145. package/lib/slides/core/slideNavigation.js.map +1 -0
  146. package/lib/slides/core/talk.d.ts +82 -0
  147. package/lib/slides/core/talk.d.ts.map +1 -0
  148. package/lib/slides/core/talk.js +134 -0
  149. package/lib/slides/core/talk.js.map +1 -0
  150. package/lib/slides/core/talkManifest.d.ts +90 -0
  151. package/lib/slides/core/talkManifest.d.ts.map +1 -0
  152. package/lib/slides/core/talkManifest.js +109 -0
  153. package/lib/slides/core/talkManifest.js.map +1 -0
  154. package/lib/slides/core/talkOrigin.d.ts +50 -0
  155. package/lib/slides/core/talkOrigin.d.ts.map +1 -0
  156. package/lib/slides/core/talkOrigin.js +62 -0
  157. package/lib/slides/core/talkOrigin.js.map +1 -0
  158. package/lib/slides/ui/BackToSlides.d.ts +26 -0
  159. package/lib/slides/ui/BackToSlides.d.ts.map +1 -0
  160. package/lib/slides/ui/BackToSlides.js +24 -0
  161. package/lib/slides/ui/BackToSlides.js.map +1 -0
  162. package/lib/slides/ui/DemoLink.d.ts +42 -0
  163. package/lib/slides/ui/DemoLink.d.ts.map +1 -0
  164. package/lib/slides/ui/DemoLink.js +17 -0
  165. package/lib/slides/ui/DemoLink.js.map +1 -0
  166. package/lib/slides/ui/EmbedSlide.d.ts +19 -0
  167. package/lib/slides/ui/EmbedSlide.d.ts.map +1 -0
  168. package/lib/slides/ui/EmbedSlide.js +56 -0
  169. package/lib/slides/ui/EmbedSlide.js.map +1 -0
  170. package/lib/slides/ui/SectionSlide.d.ts +18 -0
  171. package/lib/slides/ui/SectionSlide.d.ts.map +1 -0
  172. package/lib/slides/ui/SectionSlide.js +18 -0
  173. package/lib/slides/ui/SectionSlide.js.map +1 -0
  174. package/lib/slides/ui/Slide.d.ts +52 -0
  175. package/lib/slides/ui/Slide.d.ts.map +1 -0
  176. package/lib/slides/ui/Slide.js +58 -0
  177. package/lib/slides/ui/Slide.js.map +1 -0
  178. package/lib/slides/ui/SlideBody.d.ts +32 -0
  179. package/lib/slides/ui/SlideBody.d.ts.map +1 -0
  180. package/lib/slides/ui/SlideBody.js +27 -0
  181. package/lib/slides/ui/SlideBody.js.map +1 -0
  182. package/lib/slides/ui/Slideshow.d.ts +93 -0
  183. package/lib/slides/ui/Slideshow.d.ts.map +1 -0
  184. package/lib/slides/ui/Slideshow.js +122 -0
  185. package/lib/slides/ui/Slideshow.js.map +1 -0
  186. package/lib/slides/ui/SlideshowBar.d.ts +33 -0
  187. package/lib/slides/ui/SlideshowBar.d.ts.map +1 -0
  188. package/lib/slides/ui/SlideshowBar.js +20 -0
  189. package/lib/slides/ui/SlideshowBar.js.map +1 -0
  190. package/lib/slides/ui/TalkList.d.ts +37 -0
  191. package/lib/slides/ui/TalkList.d.ts.map +1 -0
  192. package/lib/slides/ui/TalkList.js +68 -0
  193. package/lib/slides/ui/TalkList.js.map +1 -0
  194. package/lib/slides/ui/index.d.ts +19 -0
  195. package/lib/slides/ui/index.d.ts.map +1 -0
  196. package/lib/slides/ui/index.js +10 -0
  197. package/lib/slides/ui/index.js.map +1 -0
  198. package/lib/slides/vite/index.d.ts +3 -0
  199. package/lib/slides/vite/index.d.ts.map +1 -0
  200. package/lib/slides/vite/index.js +2 -0
  201. package/lib/slides/vite/index.js.map +1 -0
  202. package/lib/slides/vite/talks.d.ts +50 -0
  203. package/lib/slides/vite/talks.d.ts.map +1 -0
  204. package/lib/slides/vite/talks.js +87 -0
  205. package/lib/slides/vite/talks.js.map +1 -0
  206. package/lib/slides.d.ts +3 -0
  207. package/lib/slides.d.ts.map +1 -0
  208. package/lib/slides.js +3 -0
  209. package/lib/slides.js.map +1 -0
  210. package/lib/structure/ui/StructureEditor.js +2 -2
  211. package/lib/structure/ui/StructureEditor.js.map +1 -1
  212. package/lib/structure/ui/StructurePlaceholder.js +1 -1
  213. package/lib/structure/ui/StructurePlaceholder.js.map +1 -1
  214. package/lib/tokens/core/checkTokens.d.ts +51 -0
  215. package/lib/tokens/core/checkTokens.d.ts.map +1 -0
  216. package/lib/tokens/core/checkTokens.js +188 -0
  217. package/lib/tokens/core/checkTokens.js.map +1 -0
  218. package/lib/tokens/core/colors.d.ts +42 -0
  219. package/lib/tokens/core/colors.d.ts.map +1 -0
  220. package/lib/tokens/core/colors.js +119 -0
  221. package/lib/tokens/core/colors.js.map +1 -0
  222. package/lib/tokens/core/index.d.ts +3 -0
  223. package/lib/tokens/core/index.d.ts.map +1 -0
  224. package/lib/tokens/core/index.js +2 -0
  225. package/lib/tokens/core/index.js.map +1 -0
  226. package/lib/tokens/core/rules.d.ts +23 -0
  227. package/lib/tokens/core/rules.d.ts.map +1 -0
  228. package/lib/tokens/core/rules.js +90 -0
  229. package/lib/tokens/core/rules.js.map +1 -0
  230. package/lib/ui.d.ts +1 -0
  231. package/lib/ui.d.ts.map +1 -1
  232. package/lib/ui.js +1 -0
  233. package/lib/ui.js.map +1 -1
  234. package/lib/vite.d.ts +1 -0
  235. package/lib/vite.d.ts.map +1 -1
  236. package/lib/vite.js +1 -0
  237. package/lib/vite.js.map +1 -1
  238. package/package.json +11 -3
  239. package/src/about/core/about.ts +176 -0
  240. package/src/about/core/index.ts +2 -0
  241. package/src/about/ui/AboutCitations.tsx +79 -0
  242. package/src/about/ui/AboutPage.tsx +177 -0
  243. package/src/about/ui/AboutSection.tsx +56 -0
  244. package/src/about/ui/index.ts +6 -0
  245. package/src/chrome/ui/index.ts +3 -0
  246. package/src/citation/core/index.ts +1 -0
  247. package/src/citation/core/teachingPaper.ts +36 -0
  248. package/src/clipboard/ui/CodeBlock.tsx +4 -1
  249. package/src/color/ui/ColorScaleLegend.tsx +1 -1
  250. package/src/core.ts +5 -0
  251. package/src/credits/core/credits.ts +42 -0
  252. package/src/credits/ui/CreditsList.tsx +1 -1
  253. package/src/delimited/ui/DelimitedTextPanel.tsx +1 -1
  254. package/src/ecosystem/core/sites.ts +12 -0
  255. package/src/ecosystem/core/tokens.ts +1 -0
  256. package/src/ecosystem/ui/EcosystemLinks.tsx +2 -2
  257. package/src/ecosystem/ui/EcosystemMenu.tsx +1 -1
  258. package/src/ecosystem/ui/SiteTile.tsx +7 -5
  259. package/src/ecosystem/ui/glyphs.tsx +40 -0
  260. package/src/orbital/core/index.ts +4 -1
  261. package/src/orbital/core/realHarmonics.ts +5 -2
  262. package/src/orbital/ui/AtomicOrbitalCanvas.tsx +126 -4
  263. package/src/orbital/ui/AtomicOrbitalViewer.tsx +14 -1
  264. package/src/orbital/ui/camera.ts +81 -0
  265. package/src/orbital/ui/renderVolume.ts +8 -1
  266. package/src/orbital/ui/serial.ts +35 -0
  267. package/src/orbital/ui/viewer.ts +72 -13
  268. package/src/pedagogy/ui/ExerciseProgressHeader.tsx +1 -1
  269. package/src/pedagogy/ui/GlossaryText.tsx +2 -2
  270. package/src/pedagogy/ui/ReferenceSectionBlock.tsx +5 -2
  271. package/src/pedagogy/ui/SyntaxTooltip.tsx +2 -2
  272. package/src/pedagogy/ui/TutorialStepStrip.tsx +39 -10
  273. package/src/pedagogy/ui/index.ts +4 -1
  274. package/src/periodic/ui/CategoryLegend.tsx +1 -1
  275. package/src/periodic/ui/PeriodicTableChrome.tsx +2 -2
  276. package/src/seo/vite/ogCard.ts +1 -0
  277. package/src/share/ui/ShareDialogContent.tsx +5 -2
  278. package/src/share/ui/SharePartOptions.tsx +1 -1
  279. package/src/slides/core/demoLinks.ts +113 -0
  280. package/src/slides/core/index.ts +22 -0
  281. package/src/slides/core/sectionHeading.ts +29 -0
  282. package/src/slides/core/slideNavigation.ts +77 -0
  283. package/src/slides/core/talk.ts +203 -0
  284. package/src/slides/core/talkManifest.ts +158 -0
  285. package/src/slides/core/talkOrigin.ts +83 -0
  286. package/src/slides/ui/BackToSlides.tsx +49 -0
  287. package/src/slides/ui/DemoLink.tsx +67 -0
  288. package/src/slides/ui/EmbedSlide.tsx +85 -0
  289. package/src/slides/ui/SectionSlide.tsx +44 -0
  290. package/src/slides/ui/Slide.tsx +143 -0
  291. package/src/slides/ui/SlideBody.tsx +64 -0
  292. package/src/slides/ui/Slideshow.tsx +282 -0
  293. package/src/slides/ui/SlideshowBar.tsx +83 -0
  294. package/src/slides/ui/TalkList.tsx +146 -0
  295. package/src/slides/ui/index.ts +18 -0
  296. package/src/slides/vite/index.ts +2 -0
  297. package/src/slides/vite/talks.ts +126 -0
  298. package/src/slides.ts +2 -0
  299. package/src/structure/ui/StructureEditor.tsx +2 -2
  300. package/src/structure/ui/StructurePlaceholder.tsx +1 -1
  301. package/src/tokens/core/checkTokens.ts +242 -0
  302. package/src/tokens/core/colors.ts +122 -0
  303. package/src/tokens/core/index.ts +6 -0
  304. package/src/tokens/core/rules.ts +103 -0
  305. package/src/ui.ts +1 -0
  306. package/src/vite.ts +1 -0
  307. package/styles/chrome.css +1 -0
  308. package/styles/slides.css +667 -0
@@ -0,0 +1,119 @@
1
+ // tokens-ok: file — the colour reader is tested against literals.
2
+ /**
3
+ * Reading a colour out of source text, in both spellings the same value is
4
+ * written in: `#5f6b7c` and `rgb(95 107 124)`. Both come back as the same six
5
+ * lowercase hex digits, so a table of banned colours holds one entry per
6
+ * colour rather than one per way of typing it.
7
+ */
8
+ /**
9
+ * The colour a hex literal starts at, in `#rgb`, `#rgba`, `#rrggbb` or
10
+ * `#rrggbbaa` form. The alpha, when there is one, says nothing about the
11
+ * colour and is dropped.
12
+ * @param lower - The text being scanned, already lowercased.
13
+ * @param start - The index of the `#`.
14
+ * @returns The colour and its end, or `null` when it is not a hex colour.
15
+ */
16
+ export function readHexColor(lower, start) {
17
+ let end = start + 1;
18
+ while (isHexDigit(lower[end]))
19
+ end++;
20
+ // A run of hex digits running straight into a word is an identifier — a
21
+ // private field, an anchor — rather than a colour.
22
+ if (isWordChar(lower[end]))
23
+ return null;
24
+ const digits = end - start - 1;
25
+ if (digits === 3 || digits === 4) {
26
+ const red = lower[start + 1];
27
+ const green = lower[start + 2];
28
+ const blue = lower[start + 3];
29
+ return { color: `${red}${red}${green}${green}${blue}${blue}`, end };
30
+ }
31
+ if (digits === 6 || digits === 8) {
32
+ return { color: lower.slice(start + 1, start + 7), end };
33
+ }
34
+ return null;
35
+ }
36
+ /**
37
+ * The colour an `rgb()` or `rgba()` call starts at, in either the comma or the
38
+ * space separated spelling.
39
+ *
40
+ * Only a plain byte triple is read: a percentage, a decimal or a variable
41
+ * inside the call means the value cannot be compared with a hex literal, and
42
+ * is left alone rather than guessed at.
43
+ * @param lower - The text being scanned, already lowercased.
44
+ * @param start - The index of the `r`.
45
+ * @returns The colour and its end, or `null` when it is not one.
46
+ */
47
+ export function readRgbColor(lower, start) {
48
+ let open = -1;
49
+ if (lower.startsWith('rgb(', start))
50
+ open = start + 3;
51
+ else if (lower.startsWith('rgba(', start))
52
+ open = start + 4;
53
+ if (open === -1)
54
+ return null;
55
+ const close = lower.indexOf(')', open);
56
+ if (close === -1)
57
+ return null;
58
+ const components = [];
59
+ let value = -1;
60
+ for (let index = open + 1; index < close; index++) {
61
+ const char = lower[index];
62
+ if (char !== undefined && char >= '0' && char <= '9') {
63
+ value = Math.max(value, 0) * 10 + Number(char);
64
+ continue;
65
+ }
66
+ if (value >= 0) {
67
+ components.push(value);
68
+ value = -1;
69
+ }
70
+ // The alpha of the modern syntax, which the colour does not depend on.
71
+ if (char === '/')
72
+ break;
73
+ if (char !== ' ' && char !== ',' && char !== '\t' && char !== '\n') {
74
+ return null;
75
+ }
76
+ }
77
+ if (value >= 0)
78
+ components.push(value);
79
+ if (components.length < 3)
80
+ return null;
81
+ let color = '';
82
+ for (let index = 0; index < 3; index++) {
83
+ const component = components[index];
84
+ if (component === undefined || component > 255)
85
+ return null;
86
+ color += component.toString(16).padStart(2, '0');
87
+ }
88
+ return { color, end: close + 1 };
89
+ }
90
+ /**
91
+ * The `rrggbb` form of a colour written by hand — in an allow list, on a
92
+ * command line — in any of the spellings the scanner itself reads.
93
+ * @param value - The colour, with or without its `#`.
94
+ * @returns The six lowercase hex digits, or `null` when it is not a colour.
95
+ */
96
+ export function normalizeColor(value) {
97
+ const text = value.trim().toLowerCase();
98
+ if (text === '')
99
+ return null;
100
+ let match = null;
101
+ if (text.startsWith('#'))
102
+ match = readHexColor(text, 0);
103
+ else if (text.startsWith('rgb'))
104
+ match = readRgbColor(text, 0);
105
+ else
106
+ match = readHexColor(`#${text}`, 0);
107
+ return match === null ? null : match.color;
108
+ }
109
+ function isHexDigit(char) {
110
+ if (char === undefined)
111
+ return false;
112
+ return (char >= '0' && char <= '9') || (char >= 'a' && char <= 'f');
113
+ }
114
+ function isWordChar(char) {
115
+ if (char === undefined)
116
+ return false;
117
+ return ((char >= '0' && char <= '9') || (char >= 'a' && char <= 'z') || char === '_');
118
+ }
119
+ //# sourceMappingURL=colors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.js","sourceRoot":"","sources":["../../../src/tokens/core/colors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export type { CheckTokensOptions, TokenViolation, TokenViolationKind, } from './checkTokens.ts';
2
+ export { findTokenViolations } from './checkTokens.ts';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tokens/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,kBAAkB,EAClB,cAAc,EACd,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { findTokenViolations } from "./checkTokens.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tokens/core/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { TokenViolationKind } from './checkTokens.ts';
2
+ /** What a colour a site may not write should have been. */
3
+ export interface ColorRule {
4
+ /** Which kind of violation writing it raises. */
5
+ kind: TokenViolationKind;
6
+ /** The token to write instead, in one line. */
7
+ hint: string;
8
+ }
9
+ /**
10
+ * The colours a site may not write, keyed by their six lowercase hex digits.
11
+ *
12
+ * Two things land here. Blueprint's own neutrals and intent blue, which arrive
13
+ * by reading a value off a component and pasting it: they are near the
14
+ * family's greys without being them, which is what makes two of our sites
15
+ * opened side by side read as two products. And the family's own token values
16
+ * re-typed as literals, which pins the page to the colour the token held on
17
+ * the day it was copied — a retune then moves everything except it.
18
+ *
19
+ * `#ffffff` is deliberately absent: `--surface` is white, and so are a hundred
20
+ * legitimate whites in a shadow, a gradient or a `color-mix`.
21
+ */
22
+ export declare const BANNED_COLORS: ReadonlyMap<string, ColorRule>;
23
+ //# sourceMappingURL=rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/tokens/core/rules.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,2DAA2D;AAC3D,MAAM,WAAW,SAAS;IACxB,iDAAiD;IACjD,IAAI,EAAE,kBAAkB,CAAC;IACzB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,SAAS,CA8EvD,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * The colours a site may not write, keyed by their six lowercase hex digits.
3
+ *
4
+ * Two things land here. Blueprint's own neutrals and intent blue, which arrive
5
+ * by reading a value off a component and pasting it: they are near the
6
+ * family's greys without being them, which is what makes two of our sites
7
+ * opened side by side read as two products. And the family's own token values
8
+ * re-typed as literals, which pins the page to the colour the token held on
9
+ * the day it was copied — a retune then moves everything except it.
10
+ *
11
+ * `#ffffff` is deliberately absent: `--surface` is white, and so are a hundred
12
+ * legitimate whites in a shadow, a gradient or a `color-mix`.
13
+ */
14
+ export const BANNED_COLORS = new Map([
15
+ [
16
+ 'f6f7f9',
17
+ {
18
+ kind: 'blueprint-grey',
19
+ hint: "Blueprint's page grey — the family's page is var(--surface-sunken).",
20
+ },
21
+ ],
22
+ [
23
+ 'd3d8de',
24
+ {
25
+ kind: 'blueprint-grey',
26
+ hint: "Blueprint's light grey — the family's line is var(--border).",
27
+ },
28
+ ],
29
+ [
30
+ '5f6b7c',
31
+ {
32
+ kind: 'blueprint-grey',
33
+ hint: "Blueprint's muted text — use var(--text-muted).",
34
+ },
35
+ ],
36
+ [
37
+ '2d72d2',
38
+ {
39
+ kind: 'blueprint-blue',
40
+ hint: "Blueprint's intent blue — the site's own colour is var(--accent).",
41
+ },
42
+ ],
43
+ [
44
+ '137cbd',
45
+ {
46
+ kind: 'blueprint-blue',
47
+ hint: "Blueprint's older intent blue — the site's own colour is var(--accent).",
48
+ },
49
+ ],
50
+ [
51
+ 'f5f7fa',
52
+ {
53
+ kind: 'retyped-token',
54
+ hint: 'the value of --surface-sunken — use var(--surface-sunken).',
55
+ },
56
+ ],
57
+ [
58
+ 'dfe3e8',
59
+ {
60
+ kind: 'retyped-token',
61
+ hint: 'the value of --border — use var(--border).',
62
+ },
63
+ ],
64
+ [
65
+ 'c3cad3',
66
+ {
67
+ kind: 'retyped-token',
68
+ hint: 'the value of --border-strong — use var(--border-strong).',
69
+ },
70
+ ],
71
+ [
72
+ '16202c',
73
+ { kind: 'retyped-token', hint: 'the value of --text — use var(--text).' },
74
+ ],
75
+ [
76
+ '5b6875',
77
+ {
78
+ kind: 'retyped-token',
79
+ hint: 'the value of --text-muted — use var(--text-muted).',
80
+ },
81
+ ],
82
+ [
83
+ '8a96a3',
84
+ {
85
+ kind: 'retyped-token',
86
+ hint: 'the value of --text-faint — use var(--text-faint).',
87
+ },
88
+ ],
89
+ ]);
90
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../../src/tokens/core/rules.ts"],"names":[],"mappings":"AAWA;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,aAAa,GAAmC,IAAI,GAAG,CAGlE;IACA;QACE,QAAQ;QACR;YACE,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,qEAAqE;SAC5E;KACF;IACD;QACE,QAAQ;QACR;YACE,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,8DAA8D;SACrE;KACF;IACD;QACE,QAAQ;QACR;YACE,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,iDAAiD;SACxD;KACF;IACD;QACE,QAAQ;QACR;YACE,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,mEAAmE;SAC1E;KACF;IACD;QACE,QAAQ;QACR;YACE,IAAI,EAAE,gBAAgB;YACtB,IAAI,EAAE,yEAAyE;SAChF;KACF;IACD;QACE,QAAQ;QACR;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,4DAA4D;SACnE;KACF;IACD;QACE,QAAQ;QACR;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,4CAA4C;SACnD;KACF;IACD;QACE,QAAQ;QACR;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,0DAA0D;SACjE;KACF;IACD;QACE,QAAQ;QACR,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,wCAAwC,EAAE;KAC1E;IACD;QACE,QAAQ;QACR;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,oDAAoD;SAC3D;KACF;IACD;QACE,QAAQ;QACR;YACE,IAAI,EAAE,eAAe;YACrB,IAAI,EAAE,oDAAoD;SAC3D;KACF;CACF,CAAC,CAAC"}
package/lib/ui.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './about/ui/index.ts';
1
2
  export * from './capsule/ui/index.ts';
2
3
  export * from './chrome/ui/index.ts';
3
4
  export * from './citation/ui/index.ts';
package/lib/ui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
package/lib/ui.js CHANGED
@@ -1,3 +1,4 @@
1
+ export * from "./about/ui/index.js";
1
2
  export * from "./capsule/ui/index.js";
2
3
  export * from "./chrome/ui/index.js";
3
4
  export * from "./citation/ui/index.js";
package/lib/ui.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC"}
package/lib/vite.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './seo/vite/index.ts';
2
+ export * from './slides/vite/index.ts';
2
3
  //# sourceMappingURL=vite.d.ts.map
package/lib/vite.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC"}
package/lib/vite.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./seo/vite/index.js";
2
+ export * from "./slides/vite/index.js";
2
3
  //# sourceMappingURL=vite.js.map
package/lib/vite.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-cheminfo",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "license": "MIT",
5
5
  "description": "Assembled React components shared by the cheminfo sites: a Cite button and an ecosystem menu",
6
6
  "author": "Luc Patiny",
@@ -14,18 +14,24 @@
14
14
  "exports": {
15
15
  "./core": "./lib/core.js",
16
16
  "./orbital": "./lib/orbital.js",
17
+ "./slides": "./lib/slides.js",
17
18
  "./structure": "./lib/structure.js",
18
19
  "./ui": "./lib/ui.js",
19
20
  "./vite": "./lib/vite.js",
20
21
  "./styles/*.css": "./styles/*.css"
21
22
  },
23
+ "bin": {
24
+ "cheminfo-check-tokens": "bin/check-tokens.mjs"
25
+ },
22
26
  "files": [
27
+ "bin",
23
28
  "lib",
24
29
  "src",
25
30
  "styles"
26
31
  ],
27
32
  "scripts": {
28
33
  "build-storybook": "storybook build",
34
+ "check-tokens": "node bin/check-tokens.mjs styles src",
29
35
  "check-types": "tsc --noEmit",
30
36
  "clean": "rimraf coverage lib storybook-static",
31
37
  "dev": "storybook dev -p 10815",
@@ -34,7 +40,7 @@
34
40
  "prepack": "npm run tsc",
35
41
  "prettier": "prettier --check .",
36
42
  "prettier-write": "prettier --write .",
37
- "test": "npm run test-only && npm run check-types && npm run eslint && npm run prettier",
43
+ "test": "npm run test-only && npm run check-types && npm run check-tokens && npm run eslint && npm run prettier",
38
44
  "test-e2e": "playwright test",
39
45
  "test-e2e-ui": "playwright test --ui",
40
46
  "test-only": "vitest run --coverage",
@@ -42,7 +48,9 @@
42
48
  "tsc-build": "tsc --project tsconfig.build.json"
43
49
  },
44
50
  "dependencies": {
45
- "cheminfo-font": "^1.28.0"
51
+ "cheminfo-font": "^1.28.0",
52
+ "react-markdown": "^10.1.0",
53
+ "rehype-raw": "^7.0.0"
46
54
  },
47
55
  "devDependencies": {
48
56
  "@blueprintjs/core": "^6.18.0",
@@ -0,0 +1,176 @@
1
+ import type { CitedWork } from '../../citation/core/works.ts';
2
+ import type { CreditEntry, CreditId } from '../../credits/core/credits.ts';
3
+ import { credits } from '../../credits/core/credits.ts';
4
+ import { siteById } from '../../ecosystem/core/lookup.ts';
5
+ import type { EcosystemSite, SiteId } from '../../ecosystem/core/sites.ts';
6
+
7
+ /**
8
+ * What a site says about itself: the one page a visitor opens to find out what
9
+ * the tool is, what it stands on, and who to tell when it breaks.
10
+ *
11
+ * Every field is content, never markup. A site writes this record and the page
12
+ * is drawn from it, which is what keeps fourteen About pages in one order and
13
+ * one voice — the shape they were in before was fourteen hand-written pages,
14
+ * each crediting a different half of what it runs on.
15
+ */
16
+ export interface AboutContent {
17
+ /** The site the page belongs to. */
18
+ siteId: SiteId;
19
+ /** One sentence: what this tool is. */
20
+ what: string;
21
+ /**
22
+ * At most two short paragraphs of context — what the site replaces, where
23
+ * its numbers come from, what it deliberately does not do.
24
+ * @default undefined
25
+ */
26
+ paragraphs?: readonly string[];
27
+ /** Three to six one-line entries: what a visitor can do here. */
28
+ can: readonly string[];
29
+ /** Ids into the shared credits registry, in display order. */
30
+ credits: readonly CreditId[];
31
+ /**
32
+ * Works to cite, from the citation module.
33
+ * @default undefined — the site asks for no citation of its own
34
+ */
35
+ cite?: readonly CitedWork[];
36
+ /**
37
+ * Licence the site itself is published under.
38
+ * @default 'MIT'
39
+ */
40
+ license?: string;
41
+ /**
42
+ * Where the sources live.
43
+ * @default the repository of the ECOSYSTEM_SITES record
44
+ */
45
+ repository?: string;
46
+ /**
47
+ * The running version, when the site knows it.
48
+ * @default undefined
49
+ */
50
+ version?: string;
51
+ /**
52
+ * Where a problem is reported.
53
+ * @default the repository's /issues
54
+ */
55
+ issues?: string;
56
+ }
57
+
58
+ /**
59
+ * The same record with nothing left to look up: every default filled in, and
60
+ * every credit id replaced by the entry it names.
61
+ */
62
+ export interface ResolvedAbout {
63
+ /** The site's own record, which carries its name, tagline and colours. */
64
+ site: EcosystemSite;
65
+ what: string;
66
+ /** The context paragraphs, empty when the site writes none. */
67
+ paragraphs: readonly string[];
68
+ can: readonly string[];
69
+ /** The borrowed works themselves, in the order the site names them. */
70
+ credits: CreditEntry[];
71
+ /** The works to cite, empty when the site asks for none. */
72
+ cite: readonly CitedWork[];
73
+ license: string;
74
+ repository: string;
75
+ /** The running version, or `undefined` when the site does not know it. */
76
+ version: string | undefined;
77
+ issues: string;
78
+ }
79
+
80
+ /**
81
+ * Fill in what a site left to the family, and resolve what it named.
82
+ * @param content - What the site wrote about itself.
83
+ * @returns The record the About page is drawn from.
84
+ * @throws {Error} When the site is not one of the family, or when a credit id
85
+ * is not in the registry: an About page that silently drops a borrowed work
86
+ * credits nobody.
87
+ */
88
+ export function resolveAbout(content: AboutContent): ResolvedAbout {
89
+ const site = siteById(content.siteId);
90
+ const repository = content.repository ?? site.repository;
91
+
92
+ return {
93
+ site,
94
+ what: content.what,
95
+ paragraphs: content.paragraphs ?? [],
96
+ can: content.can,
97
+ credits: credits(content.credits),
98
+ cite: content.cite ?? [],
99
+ license: content.license ?? DEFAULT_LICENSE,
100
+ repository,
101
+ version: content.version,
102
+ issues: content.issues ?? `${withoutTrailingSlash(repository)}/issues`,
103
+ };
104
+ }
105
+
106
+ /**
107
+ * What is wrong with a record before anyone reads the page it draws.
108
+ *
109
+ * Short and efficient prose is the house style, and prose is exactly what no
110
+ * test, lint rule or type ever checks: a `what` that runs to a paragraph and a
111
+ * `can` list of a dozen lines both compile. This is where that is caught, so a
112
+ * site can assert it in its own suite rather than discover it in review.
113
+ * @param content - What the site wrote about itself.
114
+ * @returns One line per problem, in reading order; empty when there is none.
115
+ */
116
+ export function aboutProblems(content: AboutContent): string[] {
117
+ const problems: string[] = [];
118
+
119
+ if (content.what.length > WHAT_LIMIT) {
120
+ problems.push(
121
+ `\`what\` is ${content.what.length} characters: one sentence of at most ${WHAT_LIMIT} says what the tool is.`,
122
+ );
123
+ }
124
+
125
+ const can = content.can;
126
+ if (can.length < CAN_MIN || can.length > CAN_MAX) {
127
+ problems.push(
128
+ `\`can\` lists ${can.length} entries: between ${CAN_MIN} and ${CAN_MAX} is what a visitor reads before deciding to stay.`,
129
+ );
130
+ }
131
+ for (let index = 0; index < can.length; index++) {
132
+ const line = can[index] ?? '';
133
+ if (line.length > CAN_LINE_LIMIT) {
134
+ problems.push(
135
+ `\`can\` entry ${index + 1} is ${line.length} characters: one line of at most ${CAN_LINE_LIMIT}, not a sentence about it.`,
136
+ );
137
+ }
138
+ }
139
+
140
+ const paragraphs = content.paragraphs ?? [];
141
+ if (paragraphs.length > PARAGRAPH_MAX) {
142
+ problems.push(
143
+ `\`paragraphs\` holds ${paragraphs.length}: at most ${PARAGRAPH_MAX} short paragraphs of context, and the rest belongs in the README.`,
144
+ );
145
+ }
146
+ for (let index = 0; index < paragraphs.length; index++) {
147
+ const paragraph = paragraphs[index] ?? '';
148
+ if (paragraph.length > PARAGRAPH_LIMIT) {
149
+ problems.push(
150
+ `paragraph ${index + 1} is ${paragraph.length} characters: at most ${PARAGRAPH_LIMIT}, or it is documentation rather than context.`,
151
+ );
152
+ }
153
+ }
154
+
155
+ if (content.credits.length === 0) {
156
+ problems.push(
157
+ '`credits` is empty: every page of ours stands on borrowed work, and naming it is what the section is for.',
158
+ );
159
+ }
160
+
161
+ return problems;
162
+ }
163
+
164
+ /** What a site is published under unless it says otherwise. */
165
+ const DEFAULT_LICENSE = 'MIT';
166
+
167
+ const WHAT_LIMIT = 160;
168
+ const CAN_MIN = 3;
169
+ const CAN_MAX = 6;
170
+ const CAN_LINE_LIMIT = 90;
171
+ const PARAGRAPH_MAX = 2;
172
+ const PARAGRAPH_LIMIT = 400;
173
+
174
+ function withoutTrailingSlash(url: string): string {
175
+ return url.endsWith('/') ? url.slice(0, -1) : url;
176
+ }
@@ -0,0 +1,2 @@
1
+ export type { AboutContent, ResolvedAbout } from './about.ts';
2
+ export { aboutProblems, resolveAbout } from './about.ts';
@@ -0,0 +1,79 @@
1
+ import type { CSSProperties, ReactElement } from 'react';
2
+
3
+ import { DEFAULT_CITATION_STYLE } from '../../citation/core/formats.ts';
4
+ import { doiUrl } from '../../citation/core/reference.ts';
5
+ import type { CitedWork } from '../../citation/core/works.ts';
6
+ import { CitationPreview } from '../../citation/ui/CitationPreview.tsx';
7
+
8
+ export interface AboutCitationsProps {
9
+ /** The works the site asks for, in the order it names them. */
10
+ works: readonly CitedWork[];
11
+ }
12
+
13
+ /**
14
+ * What to cite, and what citing each work credits: a reader handed two
15
+ * references has to be told which is which before they can pick one.
16
+ * @param props - See {@link AboutCitationsProps}.
17
+ * @returns The works, each with its reference and its DOI.
18
+ */
19
+ export function AboutCitations(props: AboutCitationsProps): ReactElement {
20
+ const { works } = props;
21
+
22
+ return (
23
+ <div className="about-citations" style={LIST_STYLE}>
24
+ {works.map((work) => (
25
+ <div key={work.reference.doi} className="about-citation">
26
+ <div style={WHAT_STYLE}>{work.what}</div>
27
+ {work.note === undefined ? null : (
28
+ <p style={NOTE_STYLE}>{work.note}</p>
29
+ )}
30
+ <div style={PLATE_STYLE}>
31
+ <CitationPreview
32
+ reference={work.reference}
33
+ format="text"
34
+ style={DEFAULT_CITATION_STYLE}
35
+ />
36
+ </div>
37
+ <a
38
+ href={doiUrl(work.reference)}
39
+ target="_blank"
40
+ rel="noopener noreferrer"
41
+ style={DOI_STYLE}
42
+ >
43
+ doi:{work.reference.doi}
44
+ </a>
45
+ </div>
46
+ ))}
47
+ </div>
48
+ );
49
+ }
50
+
51
+ const LIST_STYLE = {
52
+ display: 'flex',
53
+ flexDirection: 'column',
54
+ gap: 14,
55
+ } as const satisfies CSSProperties;
56
+
57
+ const WHAT_STYLE = { fontWeight: 600 } as const satisfies CSSProperties;
58
+
59
+ const NOTE_STYLE = {
60
+ margin: '2px 0 6px',
61
+ color: 'var(--text-muted)',
62
+ fontSize: 13,
63
+ } as const satisfies CSSProperties;
64
+
65
+ // The preview is set in the light ink of the tooltip it was drawn for, so it
66
+ // is given the dark plate that ink is legible on.
67
+ const PLATE_STYLE = {
68
+ padding: '8px 10px',
69
+ borderRadius: 'var(--radius)',
70
+ background: 'var(--text)',
71
+ overflow: 'auto',
72
+ } as const satisfies CSSProperties;
73
+
74
+ const DOI_STYLE = {
75
+ display: 'inline-block',
76
+ marginTop: 6,
77
+ color: 'var(--accent)',
78
+ fontSize: 12,
79
+ } as const satisfies CSSProperties;