@hraness/design-kit 0.31.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 (345) hide show
  1. package/ARTICLE_COPY.md +208 -0
  2. package/HERO_FIELDS.md +55 -0
  3. package/ICONS.md +56 -0
  4. package/LANTERN_MATERIAL.md +60 -0
  5. package/LICENSE +21 -0
  6. package/MARKETING_COPY.md +49 -0
  7. package/MARKETING_PRESET.md +108 -0
  8. package/PALETTES.md +90 -0
  9. package/PAPER_THEME.md +128 -0
  10. package/README.md +745 -0
  11. package/STATUS_PAGES.md +67 -0
  12. package/STYLE.md +245 -0
  13. package/WRITING.md +72 -0
  14. package/dist/browser/index.js +2345 -0
  15. package/dist/chunk-44djxk16.js +6872 -0
  16. package/dist/chunk-5gtx3pza.js +9 -0
  17. package/dist/chunk-77391vmq.js +454 -0
  18. package/dist/chunk-7b1586eb.js +1209 -0
  19. package/dist/chunk-8834fh4n.js +6 -0
  20. package/dist/chunk-9t8xyqte.js +870 -0
  21. package/dist/chunk-cejpzyfh.js +446 -0
  22. package/dist/chunk-eh71jz57.js +429 -0
  23. package/dist/chunk-evb02bc1.js +516 -0
  24. package/dist/chunk-h4k7yv6x.js +368 -0
  25. package/dist/chunk-he8eznb1.js +760 -0
  26. package/dist/chunk-mr1vdcjq.js +404 -0
  27. package/dist/chunk-wzvdn8ey.js +116 -0
  28. package/dist/fonts/nebula-sans/social-fonts.generated.js +53 -0
  29. package/dist/icons.js +48 -0
  30. package/dist/index.js +237 -0
  31. package/dist/launch.js +41 -0
  32. package/dist/mockups/client.js +422 -0
  33. package/dist/mockups/index.js +1850 -0
  34. package/dist/portfolio.js +1549 -0
  35. package/dist/provider-marks.js +19 -0
  36. package/dist/react/charts.js +11 -0
  37. package/dist/react/hero-backdrop.js +8 -0
  38. package/dist/react/index.js +7252 -0
  39. package/dist/react/platform-install.js +10 -0
  40. package/dist/react/server.js +137 -0
  41. package/dist/stylex-manifest.json +1 -0
  42. package/dist/stylex.css +5392 -0
  43. package/dist/syntax-highlighting.js +15 -0
  44. package/dist/testing.js +250 -0
  45. package/package.json +377 -0
  46. package/portfolio-inventory.json +31 -0
  47. package/scripts/check-lantern-material-snapshot.d.mts +26 -0
  48. package/scripts/check-lantern-material-snapshot.mjs +126 -0
  49. package/scripts/check-marketing-snapshot.d.mts +12 -0
  50. package/scripts/check-marketing-snapshot.mjs +58 -0
  51. package/scripts/lantern-material-snapshot.ts +101 -0
  52. package/scripts/marketing-textures.ts +48 -0
  53. package/scripts/paper-theme-snapshot.ts +97 -0
  54. package/scripts/product-marketing-snapshot.ts +149 -0
  55. package/src/appearance-menu.css +266 -0
  56. package/src/appearance.ts +32 -0
  57. package/src/article-html.ts +269 -0
  58. package/src/article.ts +686 -0
  59. package/src/browser/appearance-menu.ts +604 -0
  60. package/src/browser/artifact-share.ts +164 -0
  61. package/src/browser/design-palette.ts +197 -0
  62. package/src/browser/foil.ts +124 -0
  63. package/src/browser/hero-light.ts +11 -0
  64. package/src/browser/index.ts +29 -0
  65. package/src/browser/status-field.ts +432 -0
  66. package/src/browser/status-page.ts +100 -0
  67. package/src/browser/sticky-offset.ts +82 -0
  68. package/src/browser/theme-color-sync.ts +213 -0
  69. package/src/charts.css +7 -0
  70. package/src/compiler-components.css +34 -0
  71. package/src/compiler-foundation.css +18 -0
  72. package/src/compiler-palettes.css +7 -0
  73. package/src/compiler-tokens.css +342 -0
  74. package/src/components.css +3 -0
  75. package/src/design-gallery.css +431 -0
  76. package/src/effects.css +14 -0
  77. package/src/fonts/geist-mono/GeistMono[wght].woff2 +0 -0
  78. package/src/fonts/geist-mono/OFL.txt +93 -0
  79. package/src/fonts/geist-mono/PROVENANCE.md +12 -0
  80. package/src/fonts/instrument-serif/OFL.txt +93 -0
  81. package/src/fonts/instrument-serif/UPSTREAM.md +14 -0
  82. package/src/fonts/instrument-serif/instrument-serif-latin-400.woff2 +0 -0
  83. package/src/fonts/nebula-sans/LICENSE.txt +96 -0
  84. package/src/fonts/nebula-sans/NebulaSans-Black.woff2 +0 -0
  85. package/src/fonts/nebula-sans/NebulaSans-BlackItalic.woff2 +0 -0
  86. package/src/fonts/nebula-sans/NebulaSans-Bold.otf +0 -0
  87. package/src/fonts/nebula-sans/NebulaSans-Bold.woff2 +0 -0
  88. package/src/fonts/nebula-sans/NebulaSans-BoldItalic.woff2 +0 -0
  89. package/src/fonts/nebula-sans/NebulaSans-Book.otf +0 -0
  90. package/src/fonts/nebula-sans/NebulaSans-Book.woff2 +0 -0
  91. package/src/fonts/nebula-sans/NebulaSans-BookItalic.woff2 +0 -0
  92. package/src/fonts/nebula-sans/NebulaSans-Light.woff2 +0 -0
  93. package/src/fonts/nebula-sans/NebulaSans-LightItalic.woff2 +0 -0
  94. package/src/fonts/nebula-sans/NebulaSans-Medium.woff2 +0 -0
  95. package/src/fonts/nebula-sans/NebulaSans-MediumItalic.woff2 +0 -0
  96. package/src/fonts/nebula-sans/NebulaSans-Semibold.woff2 +0 -0
  97. package/src/fonts/nebula-sans/NebulaSans-SemiboldItalic.woff2 +0 -0
  98. package/src/fonts/nebula-sans/PROVENANCE.md +14 -0
  99. package/src/fonts/nebula-sans/social-fonts.generated.ts +3873 -0
  100. package/src/fonts.css +106 -0
  101. package/src/icons/act60/act60.svg +5 -0
  102. package/src/icons/act60/application.svg +9 -0
  103. package/src/icons/act60/chapter-compare.svg +3 -0
  104. package/src/icons/act60/decree-residence.svg +6 -0
  105. package/src/icons/act60/estimate.svg +7 -0
  106. package/src/icons/act60/export-services.svg +4 -0
  107. package/src/icons/act60/investor.svg +13 -0
  108. package/src/icons/act60/presence.svg +7 -0
  109. package/src/icons/aicharts/aicharts.svg +6 -0
  110. package/src/icons/aicharts/cost-compare.svg +4 -0
  111. package/src/icons/aicharts/task-audio.svg +7 -0
  112. package/src/icons/aicharts/task-coding.svg +6 -0
  113. package/src/icons/aicharts/task-images.svg +3 -0
  114. package/src/icons/aicharts/task-reasoning.svg +9 -0
  115. package/src/icons/aicharts/task-research.svg +5 -0
  116. package/src/icons/aicharts/task-video.svg +4 -0
  117. package/src/icons/manifest.json +1371 -0
  118. package/src/icons/platonik/conversation.svg +3 -0
  119. package/src/icons/platonik/creature.svg +7 -0
  120. package/src/icons/platonik/economy.svg +4 -0
  121. package/src/icons/platonik/keep-light.svg +6 -0
  122. package/src/icons/platonik/platonik.svg +7 -0
  123. package/src/icons/platonik/spark-route.svg +15 -0
  124. package/src/icons/receipts/act60-retry.receipt.json +888 -0
  125. package/src/icons/receipts/act60.receipt.json +1366 -0
  126. package/src/icons/receipts/aicharts.receipt.json +1546 -0
  127. package/src/icons/receipts/platonik.receipt.json +1011 -0
  128. package/src/icons/receipts/roughday.receipt.json +770 -0
  129. package/src/icons/receipts/shared.receipt.json +1296 -0
  130. package/src/icons/receipts/slopcamera.receipt.json +1495 -0
  131. package/src/icons/receipts/soundfish-retry.receipt.json +460 -0
  132. package/src/icons/receipts/soundfish.receipt.json +1709 -0
  133. package/src/icons/receipts/sponge.receipt.json +1743 -0
  134. package/src/icons/receipts/stripe-history-retry.receipt.json +145 -0
  135. package/src/icons/receipts/stripe-history.receipt.json +1202 -0
  136. package/src/icons/receipts/wordcell.receipt.json +1924 -0
  137. package/src/icons/roughday/finance.svg +7 -0
  138. package/src/icons/roughday/roughday.svg +6 -0
  139. package/src/icons/roughday/technology.svg +4 -0
  140. package/src/icons/roughday/world.svg +4 -0
  141. package/src/icons/sets/act60.json +63 -0
  142. package/src/icons/sets/aicharts.json +63 -0
  143. package/src/icons/sets/platonik.json +39 -0
  144. package/src/icons/sets/roughday.json +25 -0
  145. package/src/icons/sets/shared.json +12 -0
  146. package/src/icons/sets/slopcamera.json +47 -0
  147. package/src/icons/sets/soundfish.json +43 -0
  148. package/src/icons/sets/sponge.json +51 -0
  149. package/src/icons/sets/stripe-history.json +39 -0
  150. package/src/icons/sets/wordcell.json +51 -0
  151. package/src/icons/shared/agent-skill.svg +4 -0
  152. package/src/icons/shared/cli.svg +5 -0
  153. package/src/icons/shared/privacy.svg +3 -0
  154. package/src/icons/shared/research.svg +7 -0
  155. package/src/icons/shared/sdk.svg +3 -0
  156. package/src/icons/slopcamera/diagram.svg +3 -0
  157. package/src/icons/slopcamera/direct-scene.svg +5 -0
  158. package/src/icons/slopcamera/edit-video.svg +17 -0
  159. package/src/icons/slopcamera/mcp.svg +3 -0
  160. package/src/icons/slopcamera/native-world.svg +3 -0
  161. package/src/icons/slopcamera/slopcamera.svg +11 -0
  162. package/src/icons/soundfish/agent-ui.svg +7 -0
  163. package/src/icons/soundfish/collaborate.svg +5 -0
  164. package/src/icons/soundfish/compose.svg +3 -0
  165. package/src/icons/soundfish/hear.svg +6 -0
  166. package/src/icons/soundfish/human-ui.svg +6 -0
  167. package/src/icons/soundfish/share.svg +3 -0
  168. package/src/icons/soundfish/soundfish.svg +6 -0
  169. package/src/icons/sponge/api.svg +3 -0
  170. package/src/icons/sponge/documents.svg +3 -0
  171. package/src/icons/sponge/library.svg +3 -0
  172. package/src/icons/sponge/one-question.svg +5 -0
  173. package/src/icons/sponge/people-direct.svg +5 -0
  174. package/src/icons/sponge/read.svg +3 -0
  175. package/src/icons/sponge/save.svg +4 -0
  176. package/src/icons/sponge/sponge.svg +7 -0
  177. package/src/icons/stripe-history/company-history.svg +3 -0
  178. package/src/icons/stripe-history/evidence.svg +4 -0
  179. package/src/icons/stripe-history/independence.svg +7 -0
  180. package/src/icons/stripe-history/publications.svg +11 -0
  181. package/src/icons/stripe-history/sources.svg +6 -0
  182. package/src/icons/stripe-history/stripe-history.svg +3 -0
  183. package/src/icons/wordcell/backlinks.svg +6 -0
  184. package/src/icons/wordcell/capture.svg +6 -0
  185. package/src/icons/wordcell/git-provenance.svg +4 -0
  186. package/src/icons/wordcell/kb.svg +4 -0
  187. package/src/icons/wordcell/markdown.svg +4 -0
  188. package/src/icons/wordcell/scopes.svg +3 -0
  189. package/src/icons/wordcell/search.svg +7 -0
  190. package/src/icons.generated.ts +734 -0
  191. package/src/icons.ts +51 -0
  192. package/src/index.ts +275 -0
  193. package/src/lantern-material.css +213 -0
  194. package/src/launch.ts +624 -0
  195. package/src/marketing-assets/UPSTREAM.md +18 -0
  196. package/src/marketing-assets/cells.svg +1 -0
  197. package/src/marketing-assets/grain.svg +1 -0
  198. package/src/marketing-forced-colors.css +12 -0
  199. package/src/mockups/client.tsx +415 -0
  200. package/src/mockups/core.tsx +318 -0
  201. package/src/mockups/frames.tsx +368 -0
  202. package/src/mockups/index.ts +14 -0
  203. package/src/mockups/surfaces.tsx +681 -0
  204. package/src/mockups.css +2607 -0
  205. package/src/palette-appearance.ts +45 -0
  206. package/src/palette-bridge.css +124 -0
  207. package/src/palette-color.ts +41 -0
  208. package/src/palette-system.css +721 -0
  209. package/src/palette-themes.ts +23 -0
  210. package/src/palette-tokens.stylex.ts +519 -0
  211. package/src/palettes.css +3 -0
  212. package/src/palettes.ts +161 -0
  213. package/src/paper-theme.css +244 -0
  214. package/src/plain-publication.css +1241 -0
  215. package/src/plain-site.css +397 -0
  216. package/src/platforms.ts +151 -0
  217. package/src/portfolio.generated.json +1595 -0
  218. package/src/portfolio.generated.ts +1596 -0
  219. package/src/portfolio.ts +226 -0
  220. package/src/product-marketing-foundation.css +433 -0
  221. package/src/product-marketing-preset.css +261 -0
  222. package/src/product-marketing.css +2186 -0
  223. package/src/provider-marks.generated.ts +112 -0
  224. package/src/provider-marks.ts +143 -0
  225. package/src/react/animated-rail-stage.stylex.ts +15 -0
  226. package/src/react/animated-rail-stage.tsx +51 -0
  227. package/src/react/app-shell.stylex.ts +104 -0
  228. package/src/react/app-shell.tsx +121 -0
  229. package/src/react/article.tsx +602 -0
  230. package/src/react/aurora-dots-background.tsx +34 -0
  231. package/src/react/charts.stylex.ts +563 -0
  232. package/src/react/charts.tsx +610 -0
  233. package/src/react/chat.stylex.ts +34 -0
  234. package/src/react/chat.tsx +155 -0
  235. package/src/react/design-gallery.tsx +943 -0
  236. package/src/react/design-palette.stylex.ts +124 -0
  237. package/src/react/design-palette.tsx +196 -0
  238. package/src/react/design-theme-context.tsx +41 -0
  239. package/src/react/effects.stylex.ts +325 -0
  240. package/src/react/fader.stylex.ts +71 -0
  241. package/src/react/fader.tsx +151 -0
  242. package/src/react/foil-card-math.ts +100 -0
  243. package/src/react/foil-card-surface.stylex.ts +326 -0
  244. package/src/react/foil-card-surface.tsx +742 -0
  245. package/src/react/foil-mark.tsx +35 -0
  246. package/src/react/foil.stylex.ts +163 -0
  247. package/src/react/haptics.ts +228 -0
  248. package/src/react/hero-backdrop.tsx +22 -0
  249. package/src/react/index.ts +38 -0
  250. package/src/react/keyboard-shortcuts.ts +228 -0
  251. package/src/react/lantern-material-gallery.tsx +166 -0
  252. package/src/react/lantern-material.stylex.ts +39 -0
  253. package/src/react/launch-beats.tsx +73 -0
  254. package/src/react/navigation-rail.stylex.ts +130 -0
  255. package/src/react/navigation-rail.tsx +228 -0
  256. package/src/react/particle-halo.tsx +115 -0
  257. package/src/react/phaser-dots.tsx +501 -0
  258. package/src/react/platform-icons.tsx +94 -0
  259. package/src/react/platform-install.stylex.ts +385 -0
  260. package/src/react/platform-install.tsx +389 -0
  261. package/src/react/playback-transport.stylex.ts +14 -0
  262. package/src/react/playback-transport.tsx +112 -0
  263. package/src/react/procedural-backdrop.tsx +192 -0
  264. package/src/react/procedural-recipe.ts +323 -0
  265. package/src/react/product-marketing.stylex.ts +4469 -0
  266. package/src/react/product-marketing.tsx +1611 -0
  267. package/src/react/production-data-preview-notice.stylex.ts +40 -0
  268. package/src/react/production-data-preview-notice.tsx +34 -0
  269. package/src/react/provider-mark.stylex.ts +132 -0
  270. package/src/react/provider-mark.tsx +120 -0
  271. package/src/react/relative-time.tsx +117 -0
  272. package/src/react/route-state.stylex.ts +39 -0
  273. package/src/react/route-state.tsx +350 -0
  274. package/src/react/server.ts +11 -0
  275. package/src/react/social-kit-panel.tsx +103 -0
  276. package/src/react/sticky-offset.tsx +33 -0
  277. package/src/react/surfaces.stylex.ts +179 -0
  278. package/src/react/surfaces.tsx +330 -0
  279. package/src/react/syntax-code.tsx +33 -0
  280. package/src/react/theme-color-sync.ts +1 -0
  281. package/src/react/theme-resolution.ts +11 -0
  282. package/src/react/theme.stylex.ts +276 -0
  283. package/src/react/theme.tsx +402 -0
  284. package/src/reading.css +72 -0
  285. package/src/relative-time.ts +185 -0
  286. package/src/reset.css +2 -0
  287. package/src/site-shell.css +16 -0
  288. package/src/status-page-html.ts +63 -0
  289. package/src/status-page.css +276 -0
  290. package/src/status-page.ts +323 -0
  291. package/src/styles.css +21 -0
  292. package/src/syntax-code-lexers.ts +303 -0
  293. package/src/syntax-highlighting.css +78 -0
  294. package/src/syntax-highlighting.ts +477 -0
  295. package/src/syntax-tokens.ts +33 -0
  296. package/src/testing.ts +307 -0
  297. package/src/tokens.css +3 -0
  298. package/src/typography.css +86 -0
  299. package/vendor/evilcharts/LICENSE +21 -0
  300. package/vendor/evilcharts/UPSTREAM.md +14 -0
  301. package/vendor/platform-marks/LICENSE +30 -0
  302. package/vendor/platform-marks/UPSTREAM.md +15 -0
  303. package/vendor/platform-marks/apple.svg +1 -0
  304. package/vendor/platform-marks/linux.svg +1 -0
  305. package/vendor/provider-marks/CRUSH-LICENSE.md +134 -0
  306. package/vendor/provider-marks/LICENSE +21 -0
  307. package/vendor/provider-marks/UPSTREAM.md +27 -0
  308. package/vendor/provider-marks/aider.svg +3 -0
  309. package/vendor/provider-marks/crush-heartbit.svg +8 -0
  310. package/vendor/provider-marks/lobehub/alibabacloud-color.svg +1 -0
  311. package/vendor/provider-marks/lobehub/alibabacloud.svg +1 -0
  312. package/vendor/provider-marks/lobehub/amp-color.svg +1 -0
  313. package/vendor/provider-marks/lobehub/amp.svg +1 -0
  314. package/vendor/provider-marks/lobehub/anthropic.svg +1 -0
  315. package/vendor/provider-marks/lobehub/claude-color.svg +1 -0
  316. package/vendor/provider-marks/lobehub/claude.svg +1 -0
  317. package/vendor/provider-marks/lobehub/claudecode-color.svg +1 -0
  318. package/vendor/provider-marks/lobehub/claudecode.svg +1 -0
  319. package/vendor/provider-marks/lobehub/codex-color.svg +1 -0
  320. package/vendor/provider-marks/lobehub/codex.svg +1 -0
  321. package/vendor/provider-marks/lobehub/cursor.svg +1 -0
  322. package/vendor/provider-marks/lobehub/deepseek-color.svg +1 -0
  323. package/vendor/provider-marks/lobehub/deepseek.svg +1 -0
  324. package/vendor/provider-marks/lobehub/devin-color.svg +1 -0
  325. package/vendor/provider-marks/lobehub/devin.svg +1 -0
  326. package/vendor/provider-marks/lobehub/gemini-color.svg +1 -0
  327. package/vendor/provider-marks/lobehub/gemini.svg +1 -0
  328. package/vendor/provider-marks/lobehub/geminicli-color.svg +1 -0
  329. package/vendor/provider-marks/lobehub/geminicli.svg +1 -0
  330. package/vendor/provider-marks/lobehub/goose.svg +1 -0
  331. package/vendor/provider-marks/lobehub/meta-color.svg +1 -0
  332. package/vendor/provider-marks/lobehub/meta.svg +1 -0
  333. package/vendor/provider-marks/lobehub/mistral-color.svg +1 -0
  334. package/vendor/provider-marks/lobehub/mistral.svg +1 -0
  335. package/vendor/provider-marks/lobehub/moonshot.svg +1 -0
  336. package/vendor/provider-marks/lobehub/nvidia-color.svg +1 -0
  337. package/vendor/provider-marks/lobehub/nvidia.svg +1 -0
  338. package/vendor/provider-marks/lobehub/openai.svg +1 -0
  339. package/vendor/provider-marks/lobehub/opencode.svg +1 -0
  340. package/vendor/provider-marks/lobehub/perplexity-color.svg +1 -0
  341. package/vendor/provider-marks/lobehub/perplexity.svg +1 -0
  342. package/vendor/provider-marks/lobehub/qwen-color.svg +1 -0
  343. package/vendor/provider-marks/lobehub/qwen.svg +1 -0
  344. package/vendor/provider-marks/lobehub/xai.svg +1 -0
  345. package/vendor/provider-marks/lobehub/zai.svg +1 -0
@@ -0,0 +1,303 @@
1
+ import { escapeHtml, token, type SyntaxToken } from "./syntax-tokens.js";
2
+
3
+ export const codeLexerLanguages = ["rust", "toml", "yaml", "lean", "tla"] as const;
4
+ export type CodeLexerLanguage = (typeof codeLexerLanguages)[number];
5
+
6
+ const rustKeywords = new Set("as async await break const continue crate dyn else enum extern false fn for if impl in let loop match mod move mut pub ref return self Self static struct super trait true type unsafe use where while union yield".split(" "));
7
+ const rustTypes = new Set("bool char str usize isize u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64".split(" "));
8
+ const leanKeywords = new Set("abbrev axiom by case class deriving do else end example exists export false for forall fun have if import in inductive instance let match namespace noncomputable opaque open partial private protected public return section simp simpa structure termination_by theorem then true universe variable where with def".split(" "));
9
+ const tlaKeywords = new Set("ACTION ASSUME ASSUMPTION AXIOM BOOLEAN BY CASE CHOOSE CONSTANT CONSTANTS COROLLARY DEF DEFINE DEFS DOMAIN ELSE ENABLED EXCEPT EXTENDS FALSE HAVE HIDE IF IN INSTANCE LAMBDA LEMMA LET LOCAL MODULE NEW OBVIOUS OMITTED ONLY OTHER PICK PROOF PROPOSITION PROVE QED RECURSIVE STATE SUBSET SUFFICES TAKE TEMPORAL THEOREM THEN TRUE UNCHANGED UNION USE VARIABLE VARIABLES WITH WITNESS".split(" "));
10
+
11
+ /** Sticky matches consume only at the current cursor; no substring rescanning. */
12
+ function matchAt(pattern: RegExp, source: string, cursor: number): string {
13
+ pattern.lastIndex = cursor;
14
+ return pattern.exec(source)?.[0] ?? "";
15
+ }
16
+
17
+ function lineEnd(source: string, start: number): number {
18
+ let cursor = start;
19
+ while (cursor < source.length && source[cursor] !== "\n" && source[cursor] !== "\r") cursor += 1;
20
+ return cursor;
21
+ }
22
+
23
+ /** Rust, Lean and TLA+ all permit nested block comments. */
24
+ function blockCommentEnd(source: string, start: number, open: string, close: string): number {
25
+ let cursor = start + open.length;
26
+ let depth = 1;
27
+ while (cursor < source.length) {
28
+ if (source.startsWith(open, cursor)) { depth += 1; cursor += open.length; }
29
+ else if (source.startsWith(close, cursor)) {
30
+ depth -= 1;
31
+ cursor += close.length;
32
+ if (depth === 0) return cursor;
33
+ } else cursor += 1;
34
+ }
35
+ return cursor;
36
+ }
37
+
38
+ /** Quotes in raw Rust strings close only with the opening number of hashes. */
39
+ function rustRawStringEnd(source: string, start: number): number | null {
40
+ let cursor = start;
41
+ if (source.startsWith("br", cursor) || source.startsWith("cr", cursor)) cursor += 1;
42
+ if (source[cursor] !== "r") return null;
43
+ cursor += 1;
44
+ const hashesStart = cursor;
45
+ while (source[cursor] === "#") cursor += 1;
46
+ const hashes = cursor - hashesStart;
47
+ if (source[cursor] !== '"') return null;
48
+ cursor += 1;
49
+ while (cursor < source.length) {
50
+ if (source[cursor++] !== '"') continue;
51
+ let seen = 0;
52
+ while (seen < hashes && source[cursor] === "#") { seen += 1; cursor += 1; }
53
+ if (seen === hashes) return cursor;
54
+ }
55
+ return cursor;
56
+ }
57
+
58
+ function quotedEnd(source: string, start: number, quote: string, escapes: boolean, doubled = false): number {
59
+ let cursor = start + 1;
60
+ while (cursor < source.length) {
61
+ const character = source[cursor++];
62
+ if (escapes && character === "\\" && cursor < source.length) cursor += 1;
63
+ else if (character === quote) {
64
+ if (doubled && source[cursor] === quote) cursor += 1;
65
+ else return cursor;
66
+ }
67
+ }
68
+ return cursor;
69
+ }
70
+
71
+ function followingCharacter(source: string, start: number): string {
72
+ let cursor = start;
73
+ while (/\s/u.test(source[cursor] ?? "") && cursor < source.length) cursor += 1;
74
+ return source[cursor] ?? "";
75
+ }
76
+
77
+ /**
78
+ * Keep Unicode words whole without property escapes, which the consumers'
79
+ * Next.js Babel pipeline cannot compile. This is lexical presentation, not
80
+ * identifier validation; whitespace and proof operators still end a word.
81
+ */
82
+ function identifierAt(source: string, start: number): string {
83
+ let cursor = start;
84
+ while (cursor < source.length) {
85
+ const code = source.codePointAt(cursor) ?? 0;
86
+ const ascii = code === 95 || (code >= 65 && code <= 90) || (code >= 97 && code <= 122)
87
+ || (cursor > start && code >= 48 && code <= 57);
88
+ if (!ascii && (code < 128 || /[\s«»∀∃→←↔∧∨¬≤≥≠∈]/u.test(String.fromCodePoint(code)))) break;
89
+ cursor += code > 0xffff ? 2 : 1;
90
+ }
91
+ return source.slice(start, cursor);
92
+ }
93
+
94
+ function highlightProgram(source: string, language: "rust" | "lean" | "tla"): string {
95
+ const html: string[] = [];
96
+ const numbers = /(?:0[xX][0-9a-fA-F_]+|0[bB][01_]+|0[oO][0-7_]+|[0-9][0-9_]*(?:\.(?![.A-Za-z_\u0080-\u{10ffff}])[0-9_]*)?(?:[eE][+-]?[0-9_]+)?)(?:[iu](?:8|16|32|64|128|size)|f(?:32|64))?/uy;
97
+ const rustCharacters = /b?'(?:\\(?:[nrt0\\'"]|x[0-9a-fA-F]{2}|u\{[0-9a-fA-F_]{1,6}\})|[^'\\\r\n])'/uy;
98
+ const tlaWords = /\\[A-Za-z]+/y;
99
+ const keywords = language === "rust" ? rustKeywords : language === "lean" ? leanKeywords : tlaKeywords;
100
+ const lineComment = language === "rust" ? "//" : language === "lean" ? "--" : "\\*";
101
+ const openComment = language === "rust" ? "/*" : language === "lean" ? "/-" : "(*";
102
+ const closeComment = language === "rust" ? "*/" : language === "lean" ? "-/" : "*)";
103
+ let cursor = 0;
104
+ const emit = (kind: SyntaxToken, end: number): void => {
105
+ html.push(token(kind, source.slice(cursor, end)));
106
+ cursor = end;
107
+ };
108
+
109
+ while (cursor < source.length) {
110
+ if (source.startsWith(lineComment, cursor)) { emit("comment", lineEnd(source, cursor)); continue; }
111
+ if (source.startsWith(openComment, cursor)) { emit("comment", blockCommentEnd(source, cursor, openComment, closeComment)); continue; }
112
+ if (language === "rust") {
113
+ const rawEnd = rustRawStringEnd(source, cursor);
114
+ if (rawEnd !== null) { emit("string", rawEnd); continue; }
115
+ const character = matchAt(rustCharacters, source, cursor);
116
+ if (character !== "") { emit("string", cursor + character.length); continue; }
117
+ const lifetime = source[cursor] === "'" ? identifierAt(source, cursor + 1) : "";
118
+ if (lifetime !== "") { emit("variable", cursor + 1 + lifetime.length); continue; }
119
+ if (source.startsWith('b"', cursor) || source.startsWith('c"', cursor)) { emit("string", quotedEnd(source, cursor + 1, '"', true)); continue; }
120
+ if (source.startsWith("r#", cursor)) {
121
+ const identifier = identifierAt(source, cursor + 2);
122
+ if (identifier !== "") { emit("variable", cursor + 2 + identifier.length); continue; }
123
+ }
124
+ }
125
+ if (source[cursor] === '"') { emit("string", quotedEnd(source, cursor, '"', true)); continue; }
126
+ if (language === "lean" && source[cursor] === "«") {
127
+ const end = source.indexOf("»", cursor + 1);
128
+ emit("variable", end === -1 ? source.length : end + 1); continue;
129
+ }
130
+ if (language === "tla") {
131
+ const word = matchAt(tlaWords, source, cursor);
132
+ if (word !== "") { emit("keyword", cursor + word.length); continue; }
133
+ }
134
+ const number = matchAt(numbers, source, cursor);
135
+ if (number !== "") { emit("number", cursor + number.length); continue; }
136
+ const identifier = identifierAt(source, cursor);
137
+ if (identifier !== "") {
138
+ const end = cursor + identifier.length;
139
+ const next = followingCharacter(source, end);
140
+ const kind = keywords.has(identifier) ? "keyword"
141
+ : language === "rust" && rustTypes.has(identifier) ? "type"
142
+ : next === "(" || (language === "rust" && source[end] === "!" && source[end + 1] !== "=") ? "function"
143
+ : /^[A-Z]/u.test(identifier) ? "type" : null;
144
+ if (kind === null) { html.push(escapeHtml(identifier)); cursor = end; }
145
+ else emit(kind, end);
146
+ continue;
147
+ }
148
+ const character = source[cursor] ?? "";
149
+ if (/[{}()[\];,.#:+*/%&|!<>=?~^\\'∀∃λ→←↔∧∨¬≤≥≠∈-]/u.test(character)) emit("operator", cursor + 1);
150
+ else { html.push(escapeHtml(character)); cursor += 1; }
151
+ }
152
+ return html.join("");
153
+ }
154
+
155
+ function tomlStringEnd(source: string, start: number): number {
156
+ const quote = source[start] ?? '"';
157
+ const triple = quote.repeat(3);
158
+ if (!source.startsWith(triple, start)) return quotedEnd(source, start, quote, quote === '"');
159
+ let cursor = start + 3;
160
+ while (cursor < source.length) {
161
+ if (source[cursor] === "\\" && quote === '"') { cursor += Math.min(2, source.length - cursor); continue; }
162
+ if (source.startsWith(triple, cursor)) {
163
+ cursor += 3;
164
+ // TOML permits one or two quote characters just before the closing three.
165
+ for (let extra = 0; extra < 2 && source[cursor] === quote; extra += 1) cursor += 1;
166
+ return cursor;
167
+ }
168
+ cursor += 1;
169
+ }
170
+ return cursor;
171
+ }
172
+
173
+ function highlightToml(source: string): string {
174
+ const html: string[] = [];
175
+ const bare = /[A-Za-z0-9_-]+/y;
176
+ const scalar = /(?:[+-]?(?:inf|nan)|true|false|[+-]?(?:0x[0-9a-fA-F_]+|0o[0-7_]+|0b[01_]+|[0-9][0-9_]*(?:\.[0-9_]+)?(?:[eE][+-]?[0-9_]+)?))(?![A-Za-z0-9_-])/y;
177
+ const date = /[0-9]{4}-[0-9]{2}-[0-9]{2}(?:[Tt ][0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]+)?(?:[Zz]|[+-][0-9]{2}:[0-9]{2})?)?|[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]+)?/y;
178
+ let cursor = 0;
179
+ let expectsKey = true;
180
+ let lineStart = true;
181
+ let table = false;
182
+ const containers: string[] = [];
183
+ const emit = (kind: SyntaxToken, end: number): void => { html.push(token(kind, source.slice(cursor, end))); cursor = end; };
184
+
185
+ while (cursor < source.length) {
186
+ const character = source[cursor] ?? "";
187
+ if (character === "\n" || character === "\r") {
188
+ html.push(character); cursor += 1; lineStart = true; table = false;
189
+ if (containers.length === 0) expectsKey = true;
190
+ continue;
191
+ }
192
+ if (/\s/u.test(character)) { html.push(escapeHtml(character)); cursor += 1; continue; }
193
+ if (character === "#") { emit("comment", lineEnd(source, cursor)); continue; }
194
+ if (lineStart && character === "[" && containers.length === 0) { table = true; expectsKey = true; }
195
+ lineStart = false;
196
+ if (character === '"' || character === "'") {
197
+ emit(expectsKey ? "property" : "string", tomlStringEnd(source, cursor)); continue;
198
+ }
199
+ if (!expectsKey) {
200
+ const value = matchAt(date, source, cursor) || matchAt(scalar, source, cursor);
201
+ if (value !== "") { emit(value === "true" || value === "false" ? "keyword" : "number", cursor + value.length); continue; }
202
+ }
203
+ const word = matchAt(bare, source, cursor);
204
+ if (word !== "") {
205
+ if (expectsKey) emit("property", cursor + word.length);
206
+ else { html.push(escapeHtml(word)); cursor += word.length; }
207
+ continue;
208
+ }
209
+ if (character === "=") expectsKey = false;
210
+ else if (character === "{" || (!table && character === "[")) { containers.push(character); expectsKey = character === "{"; }
211
+ else if (!table && (character === "}" || character === "]")) { containers.pop(); expectsKey = false; }
212
+ else if (character === ",") expectsKey = containers.at(-1) === "{";
213
+ if (/[=.,{}[\]]/u.test(character)) emit("operator", cursor + 1);
214
+ else { html.push(escapeHtml(character)); cursor += 1; }
215
+ }
216
+ return html.join("");
217
+ }
218
+
219
+ /** A YAML block scalar owns indented lines, including comment-looking text. */
220
+ function yamlBlockEnd(source: string, headerEnd: number, parentIndent: number, explicitIndent: number): number {
221
+ let cursor = headerEnd;
222
+ let contentIndent = explicitIndent === 0 ? null : parentIndent + explicitIndent;
223
+ while (cursor < source.length) {
224
+ const start = cursor;
225
+ if (source[cursor] === "\r") cursor += 1;
226
+ if (source[cursor] === "\n") cursor += 1;
227
+ const lineStart = cursor;
228
+ while (source[cursor] === " ") cursor += 1;
229
+ const indent = cursor - lineStart;
230
+ const end = lineEnd(source, cursor);
231
+ if (cursor === end) { cursor = end; continue; }
232
+ if (contentIndent === null) contentIndent = indent > parentIndent ? indent : null;
233
+ if (contentIndent === null || indent < contentIndent) return start;
234
+ cursor = end;
235
+ }
236
+ return cursor;
237
+ }
238
+
239
+ function highlightYaml(source: string): string {
240
+ const html: string[] = [];
241
+ const names = /[&*][^\s,[\]{}]+/y;
242
+ const scalar = /(?:true|false|null|~|[+-]?(?:\.inf|\.nan|0x[0-9a-fA-F_]+|0o[0-7_]+|[0-9][0-9_]*(?:\.[0-9_]*)?(?:[eE][+-]?[0-9_]+)?))(?=$|[\s,\]}])/iy;
243
+ let cursor = 0;
244
+ let lineStart = 0;
245
+ let cachedLineEnd = -1;
246
+ const currentLineEnd = (): number => {
247
+ if (cachedLineEnd < cursor) cachedLineEnd = lineEnd(source, cursor);
248
+ return cachedLineEnd;
249
+ };
250
+ const emit = (kind: SyntaxToken, end: number): void => { html.push(token(kind, source.slice(cursor, end))); cursor = end; };
251
+ while (cursor < source.length) {
252
+ const character = source[cursor] ?? "";
253
+ if (character === "\n" || character === "\r") { html.push(character); cursor += 1; lineStart = cursor; continue; }
254
+ if (/\s/u.test(character)) { html.push(escapeHtml(character)); cursor += 1; continue; }
255
+ if (character === "#") { emit("comment", currentLineEnd()); continue; }
256
+ if (character === '"' || character === "'") {
257
+ const end = quotedEnd(source, cursor, character, character === '"', character === "'");
258
+ emit(followingCharacter(source, end) === ":" ? "property" : "string", end); continue;
259
+ }
260
+ const name = matchAt(names, source, cursor);
261
+ if (name !== "") { emit("variable", cursor + name.length); continue; }
262
+ if ((character === "|" || character === ">") && /^(?:[1-9][+-]?|[+-][1-9]?|)[ \t]*(?:#.*)?$/u.test(source.slice(cursor + 1, currentLineEnd()))) {
263
+ const end = currentLineEnd();
264
+ const header = source.slice(cursor, end);
265
+ const explicit = /[1-9]/u.exec(header)?.[0];
266
+ let indentation = lineStart;
267
+ while (source[indentation] === " ") indentation += 1;
268
+ emit("operator", cursor + 1 + (header.slice(1).match(/^[1-9+-]{0,2}/u)?.[0].length ?? 0));
269
+ const comment = source.indexOf("#", cursor);
270
+ if (comment !== -1 && comment < end) {
271
+ html.push(escapeHtml(source.slice(cursor, comment))); cursor = comment; emit("comment", end);
272
+ } else { html.push(escapeHtml(source.slice(cursor, end))); cursor = end; }
273
+ const bodyEnd = yamlBlockEnd(source, end, indentation - lineStart, Number(explicit ?? 0));
274
+ if (bodyEnd > cursor) emit("string", bodyEnd);
275
+ continue;
276
+ }
277
+ if ((source.startsWith("---", cursor) || source.startsWith("...", cursor)) && cursor === lineStart && /^\s?$/u.test(source[cursor + 3] ?? "")) { emit("marker", cursor + 3); continue; }
278
+ if (/[{}[\],]/u.test(character) || ((character === ":" || character === "-" || character === "?") && /^\s?$/u.test(source[cursor + 1] ?? ""))) { emit("operator", cursor + 1); continue; }
279
+ const value = matchAt(scalar, source, cursor);
280
+ if (value !== "") { emit(/^(?:true|false|null|~)$/iu.test(value) ? "keyword" : "number", cursor + value.length); continue; }
281
+ // Plain YAML scalars can contain spaces and URL colons. Stop only at a
282
+ // mapping separator, flow punctuation, or a whitespace-delimited comment.
283
+ let end = cursor;
284
+ while (end < source.length && source[end] !== "\n" && source[end] !== "\r") {
285
+ if (/[{}[\],]/u.test(source[end] ?? "")
286
+ || (source[end] === ":" && /^\s?$/u.test(source[end + 1] ?? ""))
287
+ || (source[end] === "#" && end > cursor && /\s/u.test(source[end - 1] ?? ""))) break;
288
+ end += 1;
289
+ }
290
+ if (end === cursor) end += 1;
291
+ const valueEnd = source.slice(cursor, end).trimEnd().length + cursor;
292
+ if (source[end] === ":" && valueEnd > cursor) emit("property", valueEnd);
293
+ else { html.push(escapeHtml(source.slice(cursor, end))); cursor = end; }
294
+ }
295
+ return html.join("");
296
+ }
297
+
298
+ /** Token presentation only: these scanners do not validate or execute code. */
299
+ export function highlightCodeLexer(source: string, language: CodeLexerLanguage): string {
300
+ if (language === "toml") return highlightToml(source);
301
+ if (language === "yaml") return highlightYaml(source);
302
+ return highlightProgram(source, language);
303
+ }
@@ -0,0 +1,78 @@
1
+ .syntax-code {
2
+ --syntax-comment: var(--muted, currentColor);
3
+ --syntax-keyword: var(--warning, var(--accent, currentColor));
4
+ --syntax-string: var(--success, var(--accent, currentColor));
5
+ --syntax-number: var(--danger, var(--accent, currentColor));
6
+ --syntax-name: var(--info, var(--accent, currentColor));
7
+ --syntax-sign: var(--muted, currentColor);
8
+ --sh-class: var(--syntax-name);
9
+ --sh-comment: var(--syntax-comment);
10
+ --sh-entity: var(--syntax-number);
11
+ --sh-identifier: var(--foreground, currentColor);
12
+ --sh-jsxliterals: var(--syntax-string);
13
+ --sh-keyword: var(--syntax-keyword);
14
+ --sh-property: var(--syntax-name);
15
+ --sh-sign: var(--syntax-sign);
16
+ --sh-space: currentColor;
17
+ --sh-string: var(--syntax-string);
18
+ text-shadow: none;
19
+ }
20
+
21
+ /* Class-only Sugar High output uses the same palette roles as its default
22
+ * inline output. Keep specificity below the forced-color rule below. */
23
+ .syntax-code :where(.sh__token--class) { color: var(--sh-class); }
24
+ .syntax-code :where(.sh__token--comment) { color: var(--sh-comment); }
25
+ .syntax-code :where(.sh__token--entity) { color: var(--sh-entity); }
26
+ .syntax-code :where(.sh__token--identifier) { color: var(--sh-identifier); }
27
+ .syntax-code :where(.sh__token--jsxliterals) { color: var(--sh-jsxliterals); }
28
+ .syntax-code :where(.sh__token--keyword) { color: var(--sh-keyword); }
29
+ .syntax-code :where(.sh__token--property) { color: var(--sh-property); }
30
+ .syntax-code :where(.sh__token--sign) { color: var(--sh-sign); }
31
+ .syntax-code :where(.sh__token--space) { color: var(--sh-space); }
32
+ .syntax-code :where(.sh__token--string) { color: var(--sh-string); }
33
+
34
+ .syntax-token--comment {
35
+ color: var(--syntax-comment);
36
+ font-style: italic;
37
+ }
38
+
39
+ .syntax-token--keyword,
40
+ .syntax-token--marker {
41
+ color: var(--syntax-keyword);
42
+ }
43
+
44
+ .syntax-token--string,
45
+ .syntax-token--inline {
46
+ color: var(--syntax-string);
47
+ }
48
+
49
+ .syntax-token--command,
50
+ .syntax-token--function,
51
+ .syntax-token--heading,
52
+ .syntax-token--property,
53
+ .syntax-token--type,
54
+ .syntax-token--variable {
55
+ color: var(--syntax-name);
56
+ }
57
+
58
+ .syntax-token--number {
59
+ color: var(--syntax-number);
60
+ }
61
+
62
+ .syntax-token--flag,
63
+ .syntax-token--operator {
64
+ color: var(--syntax-sign);
65
+ }
66
+
67
+ .syntax-token--command,
68
+ .syntax-token--heading {
69
+ font-weight: var(--font-weight-bold, 700);
70
+ }
71
+
72
+ @media (forced-colors: active) {
73
+ .syntax-code,
74
+ .syntax-code span {
75
+ color: CanvasText;
76
+ forced-color-adjust: auto;
77
+ }
78
+ }