@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.
- package/ARTICLE_COPY.md +208 -0
- package/HERO_FIELDS.md +55 -0
- package/ICONS.md +56 -0
- package/LANTERN_MATERIAL.md +60 -0
- package/LICENSE +21 -0
- package/MARKETING_COPY.md +49 -0
- package/MARKETING_PRESET.md +108 -0
- package/PALETTES.md +90 -0
- package/PAPER_THEME.md +128 -0
- package/README.md +745 -0
- package/STATUS_PAGES.md +67 -0
- package/STYLE.md +245 -0
- package/WRITING.md +72 -0
- package/dist/browser/index.js +2345 -0
- package/dist/chunk-44djxk16.js +6872 -0
- package/dist/chunk-5gtx3pza.js +9 -0
- package/dist/chunk-77391vmq.js +454 -0
- package/dist/chunk-7b1586eb.js +1209 -0
- package/dist/chunk-8834fh4n.js +6 -0
- package/dist/chunk-9t8xyqte.js +870 -0
- package/dist/chunk-cejpzyfh.js +446 -0
- package/dist/chunk-eh71jz57.js +429 -0
- package/dist/chunk-evb02bc1.js +516 -0
- package/dist/chunk-h4k7yv6x.js +368 -0
- package/dist/chunk-he8eznb1.js +760 -0
- package/dist/chunk-mr1vdcjq.js +404 -0
- package/dist/chunk-wzvdn8ey.js +116 -0
- package/dist/fonts/nebula-sans/social-fonts.generated.js +53 -0
- package/dist/icons.js +48 -0
- package/dist/index.js +237 -0
- package/dist/launch.js +41 -0
- package/dist/mockups/client.js +422 -0
- package/dist/mockups/index.js +1850 -0
- package/dist/portfolio.js +1549 -0
- package/dist/provider-marks.js +19 -0
- package/dist/react/charts.js +11 -0
- package/dist/react/hero-backdrop.js +8 -0
- package/dist/react/index.js +7252 -0
- package/dist/react/platform-install.js +10 -0
- package/dist/react/server.js +137 -0
- package/dist/stylex-manifest.json +1 -0
- package/dist/stylex.css +5392 -0
- package/dist/syntax-highlighting.js +15 -0
- package/dist/testing.js +250 -0
- package/package.json +377 -0
- package/portfolio-inventory.json +31 -0
- package/scripts/check-lantern-material-snapshot.d.mts +26 -0
- package/scripts/check-lantern-material-snapshot.mjs +126 -0
- package/scripts/check-marketing-snapshot.d.mts +12 -0
- package/scripts/check-marketing-snapshot.mjs +58 -0
- package/scripts/lantern-material-snapshot.ts +101 -0
- package/scripts/marketing-textures.ts +48 -0
- package/scripts/paper-theme-snapshot.ts +97 -0
- package/scripts/product-marketing-snapshot.ts +149 -0
- package/src/appearance-menu.css +266 -0
- package/src/appearance.ts +32 -0
- package/src/article-html.ts +269 -0
- package/src/article.ts +686 -0
- package/src/browser/appearance-menu.ts +604 -0
- package/src/browser/artifact-share.ts +164 -0
- package/src/browser/design-palette.ts +197 -0
- package/src/browser/foil.ts +124 -0
- package/src/browser/hero-light.ts +11 -0
- package/src/browser/index.ts +29 -0
- package/src/browser/status-field.ts +432 -0
- package/src/browser/status-page.ts +100 -0
- package/src/browser/sticky-offset.ts +82 -0
- package/src/browser/theme-color-sync.ts +213 -0
- package/src/charts.css +7 -0
- package/src/compiler-components.css +34 -0
- package/src/compiler-foundation.css +18 -0
- package/src/compiler-palettes.css +7 -0
- package/src/compiler-tokens.css +342 -0
- package/src/components.css +3 -0
- package/src/design-gallery.css +431 -0
- package/src/effects.css +14 -0
- package/src/fonts/geist-mono/GeistMono[wght].woff2 +0 -0
- package/src/fonts/geist-mono/OFL.txt +93 -0
- package/src/fonts/geist-mono/PROVENANCE.md +12 -0
- package/src/fonts/instrument-serif/OFL.txt +93 -0
- package/src/fonts/instrument-serif/UPSTREAM.md +14 -0
- package/src/fonts/instrument-serif/instrument-serif-latin-400.woff2 +0 -0
- package/src/fonts/nebula-sans/LICENSE.txt +96 -0
- package/src/fonts/nebula-sans/NebulaSans-Black.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-BlackItalic.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-Bold.otf +0 -0
- package/src/fonts/nebula-sans/NebulaSans-Bold.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-BoldItalic.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-Book.otf +0 -0
- package/src/fonts/nebula-sans/NebulaSans-Book.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-BookItalic.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-Light.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-LightItalic.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-Medium.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-MediumItalic.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-Semibold.woff2 +0 -0
- package/src/fonts/nebula-sans/NebulaSans-SemiboldItalic.woff2 +0 -0
- package/src/fonts/nebula-sans/PROVENANCE.md +14 -0
- package/src/fonts/nebula-sans/social-fonts.generated.ts +3873 -0
- package/src/fonts.css +106 -0
- package/src/icons/act60/act60.svg +5 -0
- package/src/icons/act60/application.svg +9 -0
- package/src/icons/act60/chapter-compare.svg +3 -0
- package/src/icons/act60/decree-residence.svg +6 -0
- package/src/icons/act60/estimate.svg +7 -0
- package/src/icons/act60/export-services.svg +4 -0
- package/src/icons/act60/investor.svg +13 -0
- package/src/icons/act60/presence.svg +7 -0
- package/src/icons/aicharts/aicharts.svg +6 -0
- package/src/icons/aicharts/cost-compare.svg +4 -0
- package/src/icons/aicharts/task-audio.svg +7 -0
- package/src/icons/aicharts/task-coding.svg +6 -0
- package/src/icons/aicharts/task-images.svg +3 -0
- package/src/icons/aicharts/task-reasoning.svg +9 -0
- package/src/icons/aicharts/task-research.svg +5 -0
- package/src/icons/aicharts/task-video.svg +4 -0
- package/src/icons/manifest.json +1371 -0
- package/src/icons/platonik/conversation.svg +3 -0
- package/src/icons/platonik/creature.svg +7 -0
- package/src/icons/platonik/economy.svg +4 -0
- package/src/icons/platonik/keep-light.svg +6 -0
- package/src/icons/platonik/platonik.svg +7 -0
- package/src/icons/platonik/spark-route.svg +15 -0
- package/src/icons/receipts/act60-retry.receipt.json +888 -0
- package/src/icons/receipts/act60.receipt.json +1366 -0
- package/src/icons/receipts/aicharts.receipt.json +1546 -0
- package/src/icons/receipts/platonik.receipt.json +1011 -0
- package/src/icons/receipts/roughday.receipt.json +770 -0
- package/src/icons/receipts/shared.receipt.json +1296 -0
- package/src/icons/receipts/slopcamera.receipt.json +1495 -0
- package/src/icons/receipts/soundfish-retry.receipt.json +460 -0
- package/src/icons/receipts/soundfish.receipt.json +1709 -0
- package/src/icons/receipts/sponge.receipt.json +1743 -0
- package/src/icons/receipts/stripe-history-retry.receipt.json +145 -0
- package/src/icons/receipts/stripe-history.receipt.json +1202 -0
- package/src/icons/receipts/wordcell.receipt.json +1924 -0
- package/src/icons/roughday/finance.svg +7 -0
- package/src/icons/roughday/roughday.svg +6 -0
- package/src/icons/roughday/technology.svg +4 -0
- package/src/icons/roughday/world.svg +4 -0
- package/src/icons/sets/act60.json +63 -0
- package/src/icons/sets/aicharts.json +63 -0
- package/src/icons/sets/platonik.json +39 -0
- package/src/icons/sets/roughday.json +25 -0
- package/src/icons/sets/shared.json +12 -0
- package/src/icons/sets/slopcamera.json +47 -0
- package/src/icons/sets/soundfish.json +43 -0
- package/src/icons/sets/sponge.json +51 -0
- package/src/icons/sets/stripe-history.json +39 -0
- package/src/icons/sets/wordcell.json +51 -0
- package/src/icons/shared/agent-skill.svg +4 -0
- package/src/icons/shared/cli.svg +5 -0
- package/src/icons/shared/privacy.svg +3 -0
- package/src/icons/shared/research.svg +7 -0
- package/src/icons/shared/sdk.svg +3 -0
- package/src/icons/slopcamera/diagram.svg +3 -0
- package/src/icons/slopcamera/direct-scene.svg +5 -0
- package/src/icons/slopcamera/edit-video.svg +17 -0
- package/src/icons/slopcamera/mcp.svg +3 -0
- package/src/icons/slopcamera/native-world.svg +3 -0
- package/src/icons/slopcamera/slopcamera.svg +11 -0
- package/src/icons/soundfish/agent-ui.svg +7 -0
- package/src/icons/soundfish/collaborate.svg +5 -0
- package/src/icons/soundfish/compose.svg +3 -0
- package/src/icons/soundfish/hear.svg +6 -0
- package/src/icons/soundfish/human-ui.svg +6 -0
- package/src/icons/soundfish/share.svg +3 -0
- package/src/icons/soundfish/soundfish.svg +6 -0
- package/src/icons/sponge/api.svg +3 -0
- package/src/icons/sponge/documents.svg +3 -0
- package/src/icons/sponge/library.svg +3 -0
- package/src/icons/sponge/one-question.svg +5 -0
- package/src/icons/sponge/people-direct.svg +5 -0
- package/src/icons/sponge/read.svg +3 -0
- package/src/icons/sponge/save.svg +4 -0
- package/src/icons/sponge/sponge.svg +7 -0
- package/src/icons/stripe-history/company-history.svg +3 -0
- package/src/icons/stripe-history/evidence.svg +4 -0
- package/src/icons/stripe-history/independence.svg +7 -0
- package/src/icons/stripe-history/publications.svg +11 -0
- package/src/icons/stripe-history/sources.svg +6 -0
- package/src/icons/stripe-history/stripe-history.svg +3 -0
- package/src/icons/wordcell/backlinks.svg +6 -0
- package/src/icons/wordcell/capture.svg +6 -0
- package/src/icons/wordcell/git-provenance.svg +4 -0
- package/src/icons/wordcell/kb.svg +4 -0
- package/src/icons/wordcell/markdown.svg +4 -0
- package/src/icons/wordcell/scopes.svg +3 -0
- package/src/icons/wordcell/search.svg +7 -0
- package/src/icons.generated.ts +734 -0
- package/src/icons.ts +51 -0
- package/src/index.ts +275 -0
- package/src/lantern-material.css +213 -0
- package/src/launch.ts +624 -0
- package/src/marketing-assets/UPSTREAM.md +18 -0
- package/src/marketing-assets/cells.svg +1 -0
- package/src/marketing-assets/grain.svg +1 -0
- package/src/marketing-forced-colors.css +12 -0
- package/src/mockups/client.tsx +415 -0
- package/src/mockups/core.tsx +318 -0
- package/src/mockups/frames.tsx +368 -0
- package/src/mockups/index.ts +14 -0
- package/src/mockups/surfaces.tsx +681 -0
- package/src/mockups.css +2607 -0
- package/src/palette-appearance.ts +45 -0
- package/src/palette-bridge.css +124 -0
- package/src/palette-color.ts +41 -0
- package/src/palette-system.css +721 -0
- package/src/palette-themes.ts +23 -0
- package/src/palette-tokens.stylex.ts +519 -0
- package/src/palettes.css +3 -0
- package/src/palettes.ts +161 -0
- package/src/paper-theme.css +244 -0
- package/src/plain-publication.css +1241 -0
- package/src/plain-site.css +397 -0
- package/src/platforms.ts +151 -0
- package/src/portfolio.generated.json +1595 -0
- package/src/portfolio.generated.ts +1596 -0
- package/src/portfolio.ts +226 -0
- package/src/product-marketing-foundation.css +433 -0
- package/src/product-marketing-preset.css +261 -0
- package/src/product-marketing.css +2186 -0
- package/src/provider-marks.generated.ts +112 -0
- package/src/provider-marks.ts +143 -0
- package/src/react/animated-rail-stage.stylex.ts +15 -0
- package/src/react/animated-rail-stage.tsx +51 -0
- package/src/react/app-shell.stylex.ts +104 -0
- package/src/react/app-shell.tsx +121 -0
- package/src/react/article.tsx +602 -0
- package/src/react/aurora-dots-background.tsx +34 -0
- package/src/react/charts.stylex.ts +563 -0
- package/src/react/charts.tsx +610 -0
- package/src/react/chat.stylex.ts +34 -0
- package/src/react/chat.tsx +155 -0
- package/src/react/design-gallery.tsx +943 -0
- package/src/react/design-palette.stylex.ts +124 -0
- package/src/react/design-palette.tsx +196 -0
- package/src/react/design-theme-context.tsx +41 -0
- package/src/react/effects.stylex.ts +325 -0
- package/src/react/fader.stylex.ts +71 -0
- package/src/react/fader.tsx +151 -0
- package/src/react/foil-card-math.ts +100 -0
- package/src/react/foil-card-surface.stylex.ts +326 -0
- package/src/react/foil-card-surface.tsx +742 -0
- package/src/react/foil-mark.tsx +35 -0
- package/src/react/foil.stylex.ts +163 -0
- package/src/react/haptics.ts +228 -0
- package/src/react/hero-backdrop.tsx +22 -0
- package/src/react/index.ts +38 -0
- package/src/react/keyboard-shortcuts.ts +228 -0
- package/src/react/lantern-material-gallery.tsx +166 -0
- package/src/react/lantern-material.stylex.ts +39 -0
- package/src/react/launch-beats.tsx +73 -0
- package/src/react/navigation-rail.stylex.ts +130 -0
- package/src/react/navigation-rail.tsx +228 -0
- package/src/react/particle-halo.tsx +115 -0
- package/src/react/phaser-dots.tsx +501 -0
- package/src/react/platform-icons.tsx +94 -0
- package/src/react/platform-install.stylex.ts +385 -0
- package/src/react/platform-install.tsx +389 -0
- package/src/react/playback-transport.stylex.ts +14 -0
- package/src/react/playback-transport.tsx +112 -0
- package/src/react/procedural-backdrop.tsx +192 -0
- package/src/react/procedural-recipe.ts +323 -0
- package/src/react/product-marketing.stylex.ts +4469 -0
- package/src/react/product-marketing.tsx +1611 -0
- package/src/react/production-data-preview-notice.stylex.ts +40 -0
- package/src/react/production-data-preview-notice.tsx +34 -0
- package/src/react/provider-mark.stylex.ts +132 -0
- package/src/react/provider-mark.tsx +120 -0
- package/src/react/relative-time.tsx +117 -0
- package/src/react/route-state.stylex.ts +39 -0
- package/src/react/route-state.tsx +350 -0
- package/src/react/server.ts +11 -0
- package/src/react/social-kit-panel.tsx +103 -0
- package/src/react/sticky-offset.tsx +33 -0
- package/src/react/surfaces.stylex.ts +179 -0
- package/src/react/surfaces.tsx +330 -0
- package/src/react/syntax-code.tsx +33 -0
- package/src/react/theme-color-sync.ts +1 -0
- package/src/react/theme-resolution.ts +11 -0
- package/src/react/theme.stylex.ts +276 -0
- package/src/react/theme.tsx +402 -0
- package/src/reading.css +72 -0
- package/src/relative-time.ts +185 -0
- package/src/reset.css +2 -0
- package/src/site-shell.css +16 -0
- package/src/status-page-html.ts +63 -0
- package/src/status-page.css +276 -0
- package/src/status-page.ts +323 -0
- package/src/styles.css +21 -0
- package/src/syntax-code-lexers.ts +303 -0
- package/src/syntax-highlighting.css +78 -0
- package/src/syntax-highlighting.ts +477 -0
- package/src/syntax-tokens.ts +33 -0
- package/src/testing.ts +307 -0
- package/src/tokens.css +3 -0
- package/src/typography.css +86 -0
- package/vendor/evilcharts/LICENSE +21 -0
- package/vendor/evilcharts/UPSTREAM.md +14 -0
- package/vendor/platform-marks/LICENSE +30 -0
- package/vendor/platform-marks/UPSTREAM.md +15 -0
- package/vendor/platform-marks/apple.svg +1 -0
- package/vendor/platform-marks/linux.svg +1 -0
- package/vendor/provider-marks/CRUSH-LICENSE.md +134 -0
- package/vendor/provider-marks/LICENSE +21 -0
- package/vendor/provider-marks/UPSTREAM.md +27 -0
- package/vendor/provider-marks/aider.svg +3 -0
- package/vendor/provider-marks/crush-heartbit.svg +8 -0
- package/vendor/provider-marks/lobehub/alibabacloud-color.svg +1 -0
- package/vendor/provider-marks/lobehub/alibabacloud.svg +1 -0
- package/vendor/provider-marks/lobehub/amp-color.svg +1 -0
- package/vendor/provider-marks/lobehub/amp.svg +1 -0
- package/vendor/provider-marks/lobehub/anthropic.svg +1 -0
- package/vendor/provider-marks/lobehub/claude-color.svg +1 -0
- package/vendor/provider-marks/lobehub/claude.svg +1 -0
- package/vendor/provider-marks/lobehub/claudecode-color.svg +1 -0
- package/vendor/provider-marks/lobehub/claudecode.svg +1 -0
- package/vendor/provider-marks/lobehub/codex-color.svg +1 -0
- package/vendor/provider-marks/lobehub/codex.svg +1 -0
- package/vendor/provider-marks/lobehub/cursor.svg +1 -0
- package/vendor/provider-marks/lobehub/deepseek-color.svg +1 -0
- package/vendor/provider-marks/lobehub/deepseek.svg +1 -0
- package/vendor/provider-marks/lobehub/devin-color.svg +1 -0
- package/vendor/provider-marks/lobehub/devin.svg +1 -0
- package/vendor/provider-marks/lobehub/gemini-color.svg +1 -0
- package/vendor/provider-marks/lobehub/gemini.svg +1 -0
- package/vendor/provider-marks/lobehub/geminicli-color.svg +1 -0
- package/vendor/provider-marks/lobehub/geminicli.svg +1 -0
- package/vendor/provider-marks/lobehub/goose.svg +1 -0
- package/vendor/provider-marks/lobehub/meta-color.svg +1 -0
- package/vendor/provider-marks/lobehub/meta.svg +1 -0
- package/vendor/provider-marks/lobehub/mistral-color.svg +1 -0
- package/vendor/provider-marks/lobehub/mistral.svg +1 -0
- package/vendor/provider-marks/lobehub/moonshot.svg +1 -0
- package/vendor/provider-marks/lobehub/nvidia-color.svg +1 -0
- package/vendor/provider-marks/lobehub/nvidia.svg +1 -0
- package/vendor/provider-marks/lobehub/openai.svg +1 -0
- package/vendor/provider-marks/lobehub/opencode.svg +1 -0
- package/vendor/provider-marks/lobehub/perplexity-color.svg +1 -0
- package/vendor/provider-marks/lobehub/perplexity.svg +1 -0
- package/vendor/provider-marks/lobehub/qwen-color.svg +1 -0
- package/vendor/provider-marks/lobehub/qwen.svg +1 -0
- package/vendor/provider-marks/lobehub/xai.svg +1 -0
- package/vendor/provider-marks/lobehub/zai.svg +1 -0
|
@@ -0,0 +1,1209 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ARTICLE_BYLINE_PREFIX,
|
|
3
|
+
ARTICLE_SOURCES_HEADING,
|
|
4
|
+
ARTICLE_TOC_LABEL,
|
|
5
|
+
articleProvenanceSentence,
|
|
6
|
+
assertArticleAuthor,
|
|
7
|
+
assertArticleCalloutTone,
|
|
8
|
+
assertArticleDates,
|
|
9
|
+
assertArticleHref,
|
|
10
|
+
formatArticleDate
|
|
11
|
+
} from "./chunk-77391vmq.js";
|
|
12
|
+
|
|
13
|
+
// src/palette-color.ts
|
|
14
|
+
function channels(hex) {
|
|
15
|
+
if (!/^#[0-9a-f]{6}$/iu.test(hex))
|
|
16
|
+
throw new Error("Palette colors must be six-digit hex values.");
|
|
17
|
+
return [Number.parseInt(hex.slice(1, 3), 16), Number.parseInt(hex.slice(3, 5), 16), Number.parseInt(hex.slice(5, 7), 16)];
|
|
18
|
+
}
|
|
19
|
+
function mixPaletteColor(color, toward, amount) {
|
|
20
|
+
const target = channels(toward);
|
|
21
|
+
return `#${channels(color).map((value, index) => Math.round(value * (1 - amount) + (target[index] ?? 0) * amount).toString(16).padStart(2, "0")).join("")}`;
|
|
22
|
+
}
|
|
23
|
+
function luminance(hex) {
|
|
24
|
+
const linearize = (channel) => {
|
|
25
|
+
const value = channel / 255;
|
|
26
|
+
return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
|
|
27
|
+
};
|
|
28
|
+
const [red, green, blue] = channels(hex);
|
|
29
|
+
return linearize(red) * 0.2126 + linearize(green) * 0.7152 + linearize(blue) * 0.0722;
|
|
30
|
+
}
|
|
31
|
+
function paletteContrast(a, b) {
|
|
32
|
+
const first = luminance(a);
|
|
33
|
+
const second = luminance(b);
|
|
34
|
+
return (Math.max(first, second) + 0.05) / (Math.min(first, second) + 0.05);
|
|
35
|
+
}
|
|
36
|
+
function readablePaletteColor(color, toward, backgrounds, minimum) {
|
|
37
|
+
for (let step = 0;step <= 100; step += 1) {
|
|
38
|
+
const candidate = mixPaletteColor(color, toward, step / 100);
|
|
39
|
+
if (backgrounds.every((background) => paletteContrast(candidate, background) >= minimum))
|
|
40
|
+
return candidate;
|
|
41
|
+
}
|
|
42
|
+
throw new Error("The authored palette cannot meet its contrast contract.");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/palettes.ts
|
|
46
|
+
var designPalettes = ["catppuccin", "gruvbox", "rose-pine", "tokyo-night", "paper"];
|
|
47
|
+
var designPaletteLabels = {
|
|
48
|
+
catppuccin: "Catppuccin",
|
|
49
|
+
gruvbox: "Gruvbox",
|
|
50
|
+
"rose-pine": "Rosé Pine",
|
|
51
|
+
"tokyo-night": "Tokyo Night",
|
|
52
|
+
paper: "Paper"
|
|
53
|
+
};
|
|
54
|
+
function isDesignPalette(value) {
|
|
55
|
+
return typeof value === "string" && designPalettes.some((palette) => palette === value);
|
|
56
|
+
}
|
|
57
|
+
var designPaletteSources = {
|
|
58
|
+
paper: {
|
|
59
|
+
light: {
|
|
60
|
+
background: "#f8f7f4",
|
|
61
|
+
surface: "#fffefa",
|
|
62
|
+
raised: "#fffefa",
|
|
63
|
+
hover: "#ebe8e3",
|
|
64
|
+
text: "#1c1917",
|
|
65
|
+
muted: "#6f6962",
|
|
66
|
+
border: "#8b8278",
|
|
67
|
+
primary: "#1f5eea",
|
|
68
|
+
danger: "#b23c34",
|
|
69
|
+
warning: "#a65f00",
|
|
70
|
+
success: "#26814d",
|
|
71
|
+
info: "#1f5eea",
|
|
72
|
+
violet: "#7959a5",
|
|
73
|
+
rose: "#a44b65"
|
|
74
|
+
},
|
|
75
|
+
dark: {
|
|
76
|
+
background: "#12100f",
|
|
77
|
+
surface: "#1d1a18",
|
|
78
|
+
raised: "#211d1a",
|
|
79
|
+
hover: "#292522",
|
|
80
|
+
text: "#f5f2ed",
|
|
81
|
+
muted: "#aaa29a",
|
|
82
|
+
border: "#827a72",
|
|
83
|
+
primary: "#8fb0ff",
|
|
84
|
+
danger: "#ef8c82",
|
|
85
|
+
warning: "#efae55",
|
|
86
|
+
success: "#5fc98b",
|
|
87
|
+
info: "#8fb0ff",
|
|
88
|
+
violet: "#b7a0dc",
|
|
89
|
+
rose: "#db91aa"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
catppuccin: {
|
|
93
|
+
dark: {
|
|
94
|
+
background: "#1e1e2e",
|
|
95
|
+
surface: "#181825",
|
|
96
|
+
raised: "#313244",
|
|
97
|
+
hover: "#45475a",
|
|
98
|
+
text: "#cdd6f4",
|
|
99
|
+
muted: "#a6adc8",
|
|
100
|
+
border: "#7f849c",
|
|
101
|
+
primary: "#89b4fa",
|
|
102
|
+
danger: "#f38ba8",
|
|
103
|
+
warning: "#f9e2af",
|
|
104
|
+
success: "#a6e3a1",
|
|
105
|
+
info: "#89dceb",
|
|
106
|
+
violet: "#cba6f7",
|
|
107
|
+
rose: "#f5c2e7"
|
|
108
|
+
},
|
|
109
|
+
light: {
|
|
110
|
+
background: "#eff1f5",
|
|
111
|
+
surface: "#e6e9ef",
|
|
112
|
+
raised: "#dce0e8",
|
|
113
|
+
hover: "#ccd0da",
|
|
114
|
+
text: "#4c4f69",
|
|
115
|
+
muted: "#6c6f85",
|
|
116
|
+
border: "#7c7f93",
|
|
117
|
+
primary: "#1e66f5",
|
|
118
|
+
danger: "#d20f39",
|
|
119
|
+
warning: "#df8e1d",
|
|
120
|
+
success: "#40a02b",
|
|
121
|
+
info: "#179299",
|
|
122
|
+
violet: "#8839ef",
|
|
123
|
+
rose: "#ea76cb"
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
gruvbox: {
|
|
127
|
+
dark: {
|
|
128
|
+
background: "#282828",
|
|
129
|
+
surface: "#1d2021",
|
|
130
|
+
raised: "#3c3836",
|
|
131
|
+
hover: "#504945",
|
|
132
|
+
text: "#ebdbb2",
|
|
133
|
+
muted: "#bdae93",
|
|
134
|
+
border: "#928374",
|
|
135
|
+
primary: "#83a598",
|
|
136
|
+
danger: "#fb4934",
|
|
137
|
+
warning: "#fabd2f",
|
|
138
|
+
success: "#b8bb26",
|
|
139
|
+
info: "#8ec07c",
|
|
140
|
+
violet: "#d3869b",
|
|
141
|
+
rose: "#fe8019"
|
|
142
|
+
},
|
|
143
|
+
light: {
|
|
144
|
+
background: "#fbf1c7",
|
|
145
|
+
surface: "#f9f5d7",
|
|
146
|
+
raised: "#ebdbb2",
|
|
147
|
+
hover: "#d5c4a1",
|
|
148
|
+
text: "#3c3836",
|
|
149
|
+
muted: "#665c54",
|
|
150
|
+
border: "#7c6f64",
|
|
151
|
+
primary: "#076678",
|
|
152
|
+
danger: "#9d0006",
|
|
153
|
+
warning: "#b57614",
|
|
154
|
+
success: "#79740e",
|
|
155
|
+
info: "#427b58",
|
|
156
|
+
violet: "#8f3f71",
|
|
157
|
+
rose: "#af3a03"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"rose-pine": {
|
|
161
|
+
dark: {
|
|
162
|
+
background: "#191724",
|
|
163
|
+
surface: "#1f1d2e",
|
|
164
|
+
raised: "#26233a",
|
|
165
|
+
hover: "#403d52",
|
|
166
|
+
text: "#e0def4",
|
|
167
|
+
muted: "#908caa",
|
|
168
|
+
border: "#908caa",
|
|
169
|
+
primary: "#c4a7e7",
|
|
170
|
+
danger: "#eb6f92",
|
|
171
|
+
warning: "#f6c177",
|
|
172
|
+
success: "#9ccfd8",
|
|
173
|
+
info: "#ebbcba",
|
|
174
|
+
violet: "#c4a7e7",
|
|
175
|
+
rose: "#ebbcba"
|
|
176
|
+
},
|
|
177
|
+
light: {
|
|
178
|
+
background: "#faf4ed",
|
|
179
|
+
surface: "#fffaf3",
|
|
180
|
+
raised: "#f2e9e1",
|
|
181
|
+
hover: "#dfdad9",
|
|
182
|
+
text: "#575279",
|
|
183
|
+
muted: "#797593",
|
|
184
|
+
border: "#797593",
|
|
185
|
+
primary: "#907aa9",
|
|
186
|
+
danger: "#b4637a",
|
|
187
|
+
warning: "#ea9d34",
|
|
188
|
+
success: "#286983",
|
|
189
|
+
info: "#56949f",
|
|
190
|
+
violet: "#907aa9",
|
|
191
|
+
rose: "#d7827e"
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
"tokyo-night": {
|
|
195
|
+
dark: {
|
|
196
|
+
background: "#1a1b26",
|
|
197
|
+
surface: "#16161e",
|
|
198
|
+
raised: "#24283b",
|
|
199
|
+
hover: "#292e42",
|
|
200
|
+
text: "#c0caf5",
|
|
201
|
+
muted: "#a9b1d6",
|
|
202
|
+
border: "#737aa2",
|
|
203
|
+
primary: "#7aa2f7",
|
|
204
|
+
danger: "#f7768e",
|
|
205
|
+
warning: "#e0af68",
|
|
206
|
+
success: "#9ece6a",
|
|
207
|
+
info: "#7dcfff",
|
|
208
|
+
violet: "#bb9af7",
|
|
209
|
+
rose: "#ff9e64"
|
|
210
|
+
},
|
|
211
|
+
light: {
|
|
212
|
+
background: "#e1e2e7",
|
|
213
|
+
surface: "#d0d5e3",
|
|
214
|
+
raised: "#c4c8da",
|
|
215
|
+
hover: "#b7c1e3",
|
|
216
|
+
text: "#3760bf",
|
|
217
|
+
muted: "#6172b0",
|
|
218
|
+
border: "#6172b0",
|
|
219
|
+
primary: "#2e7de9",
|
|
220
|
+
danger: "#f52a65",
|
|
221
|
+
warning: "#8c6c3e",
|
|
222
|
+
success: "#587539",
|
|
223
|
+
info: "#007197",
|
|
224
|
+
violet: "#9854f1",
|
|
225
|
+
rose: "#b15c00"
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
function createPalette(source, mode) {
|
|
230
|
+
const surfaces = [source.background, source.surface, source.raised, source.hover];
|
|
231
|
+
const endpoint = mode === "dark" ? "#ffffff" : "#000000";
|
|
232
|
+
const foreground = readablePaletteColor(source.text, endpoint, surfaces, 7);
|
|
233
|
+
const muted = readablePaletteColor(source.muted, endpoint, surfaces, 4.6);
|
|
234
|
+
const status = (seed) => {
|
|
235
|
+
const soft = mixPaletteColor(source.background, seed, 0.12);
|
|
236
|
+
const color = readablePaletteColor(seed, endpoint, [...surfaces, soft], 4.6);
|
|
237
|
+
const onColor = paletteContrast(color, source.background) >= 4.5 ? source.background : endpoint === "#ffffff" ? "#000000" : "#ffffff";
|
|
238
|
+
return {
|
|
239
|
+
color,
|
|
240
|
+
foreground: onColor,
|
|
241
|
+
soft
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
const primary = status(source.primary);
|
|
245
|
+
const danger = status(source.danger);
|
|
246
|
+
const warning = status(source.warning);
|
|
247
|
+
const success = status(source.success);
|
|
248
|
+
const info = status(source.info);
|
|
249
|
+
return Object.freeze({
|
|
250
|
+
background: source.background,
|
|
251
|
+
foreground,
|
|
252
|
+
muted,
|
|
253
|
+
faint: muted,
|
|
254
|
+
grid: source.raised,
|
|
255
|
+
line: source.hover,
|
|
256
|
+
controlBorder: readablePaletteColor(source.border, endpoint, surfaces, 3.1),
|
|
257
|
+
surface: source.surface,
|
|
258
|
+
surfaceRaised: source.raised,
|
|
259
|
+
surfaceHover: source.hover,
|
|
260
|
+
card: source.surface,
|
|
261
|
+
cardForeground: foreground,
|
|
262
|
+
popover: source.raised,
|
|
263
|
+
popoverForeground: foreground,
|
|
264
|
+
primary: primary.color,
|
|
265
|
+
primaryForeground: primary.foreground,
|
|
266
|
+
primarySoft: primary.soft,
|
|
267
|
+
secondary: source.raised,
|
|
268
|
+
secondaryForeground: foreground,
|
|
269
|
+
accent: primary.soft,
|
|
270
|
+
accentForeground: foreground,
|
|
271
|
+
focus: primary.color,
|
|
272
|
+
scrim: mode === "dark" ? "#000000b8" : "#00000070",
|
|
273
|
+
disabled: source.raised,
|
|
274
|
+
disabledForeground: muted,
|
|
275
|
+
inverse: foreground,
|
|
276
|
+
inverseForeground: source.background,
|
|
277
|
+
danger: danger.color,
|
|
278
|
+
dangerForeground: danger.foreground,
|
|
279
|
+
dangerSoft: danger.soft,
|
|
280
|
+
warning: warning.color,
|
|
281
|
+
warningForeground: warning.foreground,
|
|
282
|
+
warningSoft: warning.soft,
|
|
283
|
+
success: success.color,
|
|
284
|
+
successForeground: success.foreground,
|
|
285
|
+
successSoft: success.soft,
|
|
286
|
+
info: info.color,
|
|
287
|
+
infoForeground: info.foreground,
|
|
288
|
+
infoSoft: info.soft,
|
|
289
|
+
chart1: readablePaletteColor(source.rose, endpoint, surfaces, 4.6),
|
|
290
|
+
chart2: success.color,
|
|
291
|
+
chart3: info.color,
|
|
292
|
+
chart4: warning.color,
|
|
293
|
+
chart5: readablePaletteColor(source.violet, endpoint, surfaces, 4.6)
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
var paletteColors = Object.freeze({
|
|
297
|
+
paper: Object.freeze({
|
|
298
|
+
light: Object.freeze({
|
|
299
|
+
...createPalette(designPaletteSources.paper.light, "light"),
|
|
300
|
+
grid: "#dfdcd6",
|
|
301
|
+
line: "#b9b3ab",
|
|
302
|
+
secondary: "#ebe8e3"
|
|
303
|
+
}),
|
|
304
|
+
dark: Object.freeze({
|
|
305
|
+
...createPalette(designPaletteSources.paper.dark, "dark"),
|
|
306
|
+
grid: "#302b27",
|
|
307
|
+
line: "#514a44",
|
|
308
|
+
secondary: "#292522"
|
|
309
|
+
})
|
|
310
|
+
}),
|
|
311
|
+
catppuccin: Object.freeze({
|
|
312
|
+
light: createPalette(designPaletteSources.catppuccin.light, "light"),
|
|
313
|
+
dark: createPalette(designPaletteSources.catppuccin.dark, "dark")
|
|
314
|
+
}),
|
|
315
|
+
gruvbox: Object.freeze({
|
|
316
|
+
light: createPalette(designPaletteSources.gruvbox.light, "light"),
|
|
317
|
+
dark: createPalette(designPaletteSources.gruvbox.dark, "dark")
|
|
318
|
+
}),
|
|
319
|
+
"rose-pine": Object.freeze({
|
|
320
|
+
light: createPalette(designPaletteSources["rose-pine"].light, "light"),
|
|
321
|
+
dark: createPalette(designPaletteSources["rose-pine"].dark, "dark")
|
|
322
|
+
}),
|
|
323
|
+
"tokyo-night": Object.freeze({
|
|
324
|
+
light: createPalette(designPaletteSources["tokyo-night"].light, "light"),
|
|
325
|
+
dark: createPalette(designPaletteSources["tokyo-night"].dark, "dark")
|
|
326
|
+
})
|
|
327
|
+
});
|
|
328
|
+
// src/appearance.ts
|
|
329
|
+
var designThemes = ["light", "dark", "system"];
|
|
330
|
+
var defaultDesignTheme = "system";
|
|
331
|
+
var designThemeStorageKey = "hraness-design-theme-v1";
|
|
332
|
+
function isDesignTheme(value) {
|
|
333
|
+
return typeof value === "string" && designThemes.some((theme) => theme === value);
|
|
334
|
+
}
|
|
335
|
+
function normalizeDesignTheme(value) {
|
|
336
|
+
return isDesignTheme(value) ? value : defaultDesignTheme;
|
|
337
|
+
}
|
|
338
|
+
function designThemeLabel(theme, labels) {
|
|
339
|
+
return labels?.[theme] ?? `${theme.charAt(0).toUpperCase()}${theme.slice(1)}`;
|
|
340
|
+
}
|
|
341
|
+
function resolveDesignTheme(theme, systemPrefersDark) {
|
|
342
|
+
return theme === "system" ? systemPrefersDark ? "dark" : "light" : theme;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// src/palette-appearance.ts
|
|
346
|
+
var defaultDesignPalettePreference = Object.freeze({
|
|
347
|
+
palette: "catppuccin",
|
|
348
|
+
mode: "dark"
|
|
349
|
+
});
|
|
350
|
+
var designPaletteStorageKey = "hraness-design-palette-v1";
|
|
351
|
+
function parseDesignPalettePreference(value) {
|
|
352
|
+
if (typeof value === "string") {
|
|
353
|
+
if (value.length > 256)
|
|
354
|
+
return null;
|
|
355
|
+
try {
|
|
356
|
+
value = JSON.parse(value);
|
|
357
|
+
} catch {
|
|
358
|
+
return null;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
362
|
+
return null;
|
|
363
|
+
const record = value;
|
|
364
|
+
if (!isDesignPalette(record.palette) || !isDesignTheme(record.mode))
|
|
365
|
+
return null;
|
|
366
|
+
return Object.freeze({
|
|
367
|
+
palette: record.palette,
|
|
368
|
+
mode: record.mode
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
function normalizeDesignPalettePreference(value, fallback = defaultDesignPalettePreference) {
|
|
372
|
+
return parseDesignPalettePreference(value) ?? parseDesignPalettePreference(fallback) ?? defaultDesignPalettePreference;
|
|
373
|
+
}
|
|
374
|
+
function resolveDesignPalettePreference(preference, systemPrefersDark) {
|
|
375
|
+
return {
|
|
376
|
+
palette: preference.palette,
|
|
377
|
+
mode: resolveDesignTheme(preference.mode, systemPrefersDark)
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
// src/palette-themes.ts
|
|
381
|
+
import * as stylex from "@stylexjs/stylex";
|
|
382
|
+
|
|
383
|
+
// src/palette-tokens.stylex.ts
|
|
384
|
+
var catppuccinLight = {
|
|
385
|
+
x18acsur: "xadus2s x18acsur",
|
|
386
|
+
$$css: true
|
|
387
|
+
};
|
|
388
|
+
var catppuccinDark = {
|
|
389
|
+
x18acsur: "x18wthyl x18acsur",
|
|
390
|
+
$$css: true
|
|
391
|
+
};
|
|
392
|
+
var gruvboxLight = {
|
|
393
|
+
x18acsur: "xdktuxt x18acsur",
|
|
394
|
+
$$css: true
|
|
395
|
+
};
|
|
396
|
+
var gruvboxDark = {
|
|
397
|
+
x18acsur: "x1fsd05x x18acsur",
|
|
398
|
+
$$css: true
|
|
399
|
+
};
|
|
400
|
+
var rosePineLight = {
|
|
401
|
+
x18acsur: "x131glkb x18acsur",
|
|
402
|
+
$$css: true
|
|
403
|
+
};
|
|
404
|
+
var rosePineDark = {
|
|
405
|
+
x18acsur: "xivpxii x18acsur",
|
|
406
|
+
$$css: true
|
|
407
|
+
};
|
|
408
|
+
var tokyoNightLight = {
|
|
409
|
+
x18acsur: "x11phk89 x18acsur",
|
|
410
|
+
$$css: true
|
|
411
|
+
};
|
|
412
|
+
var tokyoNightDark = {
|
|
413
|
+
x18acsur: "xgp1gpt x18acsur",
|
|
414
|
+
$$css: true
|
|
415
|
+
};
|
|
416
|
+
var paperLight = {
|
|
417
|
+
x18acsur: "xjfxk3y x18acsur",
|
|
418
|
+
$$css: true
|
|
419
|
+
};
|
|
420
|
+
var paperDark = {
|
|
421
|
+
x18acsur: "x1lresar x18acsur",
|
|
422
|
+
$$css: true
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// src/palette-themes.ts
|
|
426
|
+
var classes = {
|
|
427
|
+
paper: {
|
|
428
|
+
light: stylex.props(paperLight).className,
|
|
429
|
+
dark: stylex.props(paperDark).className
|
|
430
|
+
},
|
|
431
|
+
catppuccin: {
|
|
432
|
+
light: stylex.props(catppuccinLight).className,
|
|
433
|
+
dark: stylex.props(catppuccinDark).className
|
|
434
|
+
},
|
|
435
|
+
gruvbox: {
|
|
436
|
+
light: stylex.props(gruvboxLight).className,
|
|
437
|
+
dark: stylex.props(gruvboxDark).className
|
|
438
|
+
},
|
|
439
|
+
"rose-pine": {
|
|
440
|
+
light: stylex.props(rosePineLight).className,
|
|
441
|
+
dark: stylex.props(rosePineDark).className
|
|
442
|
+
},
|
|
443
|
+
"tokyo-night": {
|
|
444
|
+
light: stylex.props(tokyoNightLight).className,
|
|
445
|
+
dark: stylex.props(tokyoNightDark).className
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
function getDesignPaletteTheme(palette, mode) {
|
|
449
|
+
return {
|
|
450
|
+
className: `hraness-palette ${classes[palette][mode]}`,
|
|
451
|
+
background: paletteColors[palette][mode].background
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
// src/article-html.ts
|
|
455
|
+
var ROOT_CLASS = "plain-site plain-publication plain-publication--embedded";
|
|
456
|
+
var SEPARATOR = '<span aria-hidden="true"> · </span>';
|
|
457
|
+
var ESCAPES = {
|
|
458
|
+
'"': """,
|
|
459
|
+
"&": "&",
|
|
460
|
+
"'": "'",
|
|
461
|
+
"<": "<",
|
|
462
|
+
">": ">"
|
|
463
|
+
};
|
|
464
|
+
function escapeArticleHtml(value) {
|
|
465
|
+
return value.replace(/["&'<>]/gu, (character) => ESCAPES[character] ?? character);
|
|
466
|
+
}
|
|
467
|
+
function classes2(...values) {
|
|
468
|
+
return values.filter((value) => value !== undefined && value !== "").join(" ");
|
|
469
|
+
}
|
|
470
|
+
function dateHtml(label, value) {
|
|
471
|
+
return `${label} <time dateTime="${escapeArticleHtml(value)}">${escapeArticleHtml(formatArticleDate(value))}</time>`;
|
|
472
|
+
}
|
|
473
|
+
function present(value) {
|
|
474
|
+
return value !== undefined && value !== "";
|
|
475
|
+
}
|
|
476
|
+
function renderArticleBylineHtml(author) {
|
|
477
|
+
assertArticleAuthor(author);
|
|
478
|
+
const name = escapeArticleHtml(author.name);
|
|
479
|
+
const linked = author.href === undefined ? name : `<a href="${escapeArticleHtml(author.href)}" rel="author">${name}</a>`;
|
|
480
|
+
return `<span class="plain-publication__byline" data-author-kind="${author.kind}">${ARTICLE_BYLINE_PREFIX} ${linked}</span>`;
|
|
481
|
+
}
|
|
482
|
+
function renderArticleProvenanceHtml(provenance) {
|
|
483
|
+
const sentence = articleProvenanceSentence(provenance);
|
|
484
|
+
return `<p class="plain-publication__provenance" data-drafting="${escapeArticleHtml(provenance.drafting)}" data-reviewer-type="${escapeArticleHtml(provenance.review?.reviewerType ?? "none")}">${escapeArticleHtml(sentence)}</p>`;
|
|
485
|
+
}
|
|
486
|
+
function renderArticleHtml(input) {
|
|
487
|
+
const headingId = input.headingId ?? "article-title";
|
|
488
|
+
const {
|
|
489
|
+
published,
|
|
490
|
+
updated
|
|
491
|
+
} = input;
|
|
492
|
+
assertArticleDates(updated === undefined ? {
|
|
493
|
+
published
|
|
494
|
+
} : {
|
|
495
|
+
published,
|
|
496
|
+
updated
|
|
497
|
+
});
|
|
498
|
+
const toc = input.toc ?? [];
|
|
499
|
+
for (const item of toc) {
|
|
500
|
+
if (!item.href.startsWith("#") || item.href.length < 2)
|
|
501
|
+
throw new RangeError("Contents links must point to a heading in this article.");
|
|
502
|
+
}
|
|
503
|
+
const tocId = `${headingId}-contents`;
|
|
504
|
+
const meta = [input.author === undefined ? "" : renderArticleBylineHtml(input.author) + SEPARATOR, dateHtml("Published", published), updated === undefined ? "" : SEPARATOR + dateHtml("Updated", updated)].join("");
|
|
505
|
+
const header = ['<header class="plain-publication__article-header">', present(input.eyebrow) ? `<p class="plain-publication__eyebrow">${escapeArticleHtml(input.eyebrow)}</p>` : "", `<h1 id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(input.heading)}</h1>`, present(input.dek) ? `<p class="plain-publication__article-dek">${escapeArticleHtml(input.dek)}</p>` : "", `<p class="plain-publication__article-meta">${meta}</p>`, input.provenance === null ? "" : renderArticleProvenanceHtml(input.provenance), "</header>"].join("");
|
|
506
|
+
const nav = toc.length === 0 ? "" : [`<nav aria-labelledby="${escapeArticleHtml(tocId)}" class="plain-publication__toc">`, `<p id="${escapeArticleHtml(tocId)}">${escapeArticleHtml(input.tocLabel ?? ARTICLE_TOC_LABEL)}</p>`, "<ol>", ...toc.map((item) => `<li><a href="${escapeArticleHtml(item.href)}">${escapeArticleHtml(item.label)}</a></li>`), "</ol></nav>"].join("");
|
|
507
|
+
return [`<article aria-labelledby="${escapeArticleHtml(headingId)}" class="${escapeArticleHtml(classes2(ROOT_CLASS, "plain-publication__article", input.className))}" data-hraness-article="" data-toc="${toc.length > 0 ? "aside" : "none"}"${input.id === undefined ? "" : ` id="${escapeArticleHtml(input.id)}"`}>`, header, '<div class="plain-publication__article-layout">', nav, `<div class="plain-publication__article-body">${input.bodyHtml}</div>`, "</div>", present(input.afterHtml) ? `<footer class="plain-publication__article-footer">${input.afterHtml}</footer>` : "", "</article>"].join("");
|
|
508
|
+
}
|
|
509
|
+
function renderArticleSourcesHtml({
|
|
510
|
+
heading = ARTICLE_SOURCES_HEADING,
|
|
511
|
+
headingId = "article-sources",
|
|
512
|
+
sources
|
|
513
|
+
}) {
|
|
514
|
+
if (sources.length === 0)
|
|
515
|
+
return "";
|
|
516
|
+
for (const source of sources)
|
|
517
|
+
assertArticleHref(source.href);
|
|
518
|
+
return [`<section aria-labelledby="${escapeArticleHtml(headingId)}" class="plain-publication__sources">`, `<h2 id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(heading)}</h2>`, "<ol>", ...sources.map((source) => [`<li><a href="${escapeArticleHtml(source.href)}">${escapeArticleHtml(source.title)}</a>`, "<span>", present(source.publisher) ? escapeArticleHtml(source.publisher) + SEPARATOR : "", dateHtml("Checked", source.checkedOn), "</span></li>"].join("")), "</ol></section>"].join("");
|
|
519
|
+
}
|
|
520
|
+
function renderArticleCalloutHtml(input) {
|
|
521
|
+
const tone = input.tone ?? "note";
|
|
522
|
+
assertArticleCalloutTone(tone);
|
|
523
|
+
const body = input.text === undefined ? input.bodyHtml : `<p>${escapeArticleHtml(input.text)}</p>`;
|
|
524
|
+
return `<div class="plain-publication__callout" data-tone="${tone}" role="note">${present(input.label) ? `<strong>${escapeArticleHtml(input.label)}</strong>` : ""}${body}</div>`;
|
|
525
|
+
}
|
|
526
|
+
function assertArticleMark(mark) {
|
|
527
|
+
if (!mark.startsWith("data:image/svg+xml,"))
|
|
528
|
+
assertArticleHref(mark);
|
|
529
|
+
}
|
|
530
|
+
function renderArticleRelatedHtml({
|
|
531
|
+
heading = "Related products",
|
|
532
|
+
headingId = "article-related-products",
|
|
533
|
+
items
|
|
534
|
+
}) {
|
|
535
|
+
if (items.length === 0)
|
|
536
|
+
return "";
|
|
537
|
+
for (const item of items) {
|
|
538
|
+
assertArticleHref(item.href);
|
|
539
|
+
if (present(item.mark))
|
|
540
|
+
assertArticleMark(item.mark);
|
|
541
|
+
}
|
|
542
|
+
return [`<section aria-labelledby="${escapeArticleHtml(headingId)}" class="plain-publication__related">`, `<div class="plain-publication__section-heading"><h2 id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(heading)}</h2></div>`, '<div class="plain-publication__related-grid">', ...items.map((item) => [`<a href="${escapeArticleHtml(item.href)}">`, present(item.mark) ? `<img alt="" class="plain-publication__related-mark" decoding="async" height="44" src="${escapeArticleHtml(item.mark)}" width="44">` : "", `<span class="plain-publication__related-text"><strong>${escapeArticleHtml(item.name)}</strong>`, `<span>${escapeArticleHtml(item.role ?? item.relationship)}</span></span></a>`].join("")), "</div></section>"].join("");
|
|
543
|
+
}
|
|
544
|
+
function renderArticleIndexHtml({
|
|
545
|
+
className,
|
|
546
|
+
heading,
|
|
547
|
+
headingId,
|
|
548
|
+
headingLevel = 2,
|
|
549
|
+
id,
|
|
550
|
+
items,
|
|
551
|
+
summary
|
|
552
|
+
}) {
|
|
553
|
+
if (![1, 2, 3, 4, 5].includes(headingLevel))
|
|
554
|
+
throw new RangeError("Article index heading level must be 1 to 5.");
|
|
555
|
+
const hrefs = new Set;
|
|
556
|
+
for (const item of items) {
|
|
557
|
+
assertArticleHref(item.href);
|
|
558
|
+
assertArticleDates(item.updated === undefined ? {
|
|
559
|
+
published: item.published
|
|
560
|
+
} : {
|
|
561
|
+
published: item.published,
|
|
562
|
+
updated: item.updated
|
|
563
|
+
});
|
|
564
|
+
if (hrefs.has(item.href))
|
|
565
|
+
throw new RangeError(`Article index lists ${item.href} more than once.`);
|
|
566
|
+
hrefs.add(item.href);
|
|
567
|
+
}
|
|
568
|
+
const heading1 = `h${headingLevel}`;
|
|
569
|
+
const entry = `h${headingLevel + 1}`;
|
|
570
|
+
return [`<section aria-labelledby="${escapeArticleHtml(headingId)}" class="${escapeArticleHtml(classes2(ROOT_CLASS, "plain-publication__list", className))}" data-hraness-article-index=""${id === undefined ? "" : ` id="${escapeArticleHtml(id)}"`}>`, `<div class="plain-publication__section-heading"><${heading1} id="${escapeArticleHtml(headingId)}">${escapeArticleHtml(heading)}</${heading1}>`, present(summary) ? `<p>${escapeArticleHtml(summary)}</p>` : "", "</div>", '<div class="plain-publication__article-list">', ...items.map((item) => ['<article class="plain-publication__entry">', present(item.eyebrow) ? `<p class="plain-publication__entry-label">${escapeArticleHtml(item.eyebrow)}</p>` : "", `<${entry} class="plain-publication__entry-title"><a href="${escapeArticleHtml(item.href)}">${escapeArticleHtml(item.title)}</a></${entry}>`, `<p class="plain-publication__entry-dek">${escapeArticleHtml(item.dek)}</p>`, '<p class="plain-publication__entry-meta">', dateHtml("Published", item.published), item.updated === undefined ? "" : SEPARATOR + dateHtml("Updated", item.updated), "</p></article>"].join("")), "</div></section>"].join("");
|
|
571
|
+
}
|
|
572
|
+
// src/status-page.ts
|
|
573
|
+
var STATUS_PAGE_MAX_NEXT = 3;
|
|
574
|
+
var STATUS_PAGE_MAX_ROUTES = 2000;
|
|
575
|
+
var STATUS_PAGE_BACK_LABEL = "Go back";
|
|
576
|
+
var STATUS_PAGE_HINT_PREFIX = "Did you mean";
|
|
577
|
+
var STATUS_PAGE_NEXT_HEADING_ID = "hraness-status-page-next";
|
|
578
|
+
var STATUS_PAGE_AGENT_PREFIX = "AI agents can start at";
|
|
579
|
+
var defaults = {
|
|
580
|
+
"not-found": {
|
|
581
|
+
glyph: "404",
|
|
582
|
+
title: "We can’t find that page",
|
|
583
|
+
summary: "The link may be out of date or mistyped."
|
|
584
|
+
},
|
|
585
|
+
error: {
|
|
586
|
+
glyph: "!",
|
|
587
|
+
title: "This view could not load",
|
|
588
|
+
summary: "Retry this view, or return home and continue from there."
|
|
589
|
+
}
|
|
590
|
+
};
|
|
591
|
+
function assertText(name, value, limit) {
|
|
592
|
+
if (value.trim() === "" || value.length > limit) {
|
|
593
|
+
throw new RangeError(`Status page ${name} must be 1–${limit} characters.`);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
function assertLink(name, link) {
|
|
597
|
+
assertArticleHref(link.href);
|
|
598
|
+
assertText(`${name} label`, link.label, 48);
|
|
599
|
+
if (link.description !== undefined)
|
|
600
|
+
assertText(`${name} description`, link.description, 90);
|
|
601
|
+
}
|
|
602
|
+
var ROUTE_LABEL_LIMIT = 80;
|
|
603
|
+
function hasControlOrSpace(href) {
|
|
604
|
+
for (const character of href) {
|
|
605
|
+
const code = character.codePointAt(0) ?? 0;
|
|
606
|
+
if (code <= 32 || code >= 127 && code <= 159 || /\s/u.test(character))
|
|
607
|
+
return true;
|
|
608
|
+
}
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
function shortRouteLabel(label) {
|
|
612
|
+
const text = label.trim().replace(/\s+/gu, " ");
|
|
613
|
+
if (text.length <= ROUTE_LABEL_LIMIT)
|
|
614
|
+
return text;
|
|
615
|
+
const cut = text.slice(0, ROUTE_LABEL_LIMIT - 1);
|
|
616
|
+
const space = cut.lastIndexOf(" ");
|
|
617
|
+
return `${(space > ROUTE_LABEL_LIMIT / 2 ? cut.slice(0, space) : cut).trimEnd()}…`;
|
|
618
|
+
}
|
|
619
|
+
function usableRoutes(routes) {
|
|
620
|
+
const usable = [];
|
|
621
|
+
for (const route of routes.slice(0, STATUS_PAGE_MAX_ROUTES)) {
|
|
622
|
+
if (typeof route !== "object" || route === null)
|
|
623
|
+
continue;
|
|
624
|
+
const {
|
|
625
|
+
href,
|
|
626
|
+
label
|
|
627
|
+
} = route;
|
|
628
|
+
if (typeof href !== "string" || typeof label !== "string" || label.trim() === "")
|
|
629
|
+
continue;
|
|
630
|
+
if (!isSitePath(href) || hasControlOrSpace(href))
|
|
631
|
+
continue;
|
|
632
|
+
usable.push({
|
|
633
|
+
href,
|
|
634
|
+
label: shortRouteLabel(label)
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
return usable;
|
|
638
|
+
}
|
|
639
|
+
function resolveStatusPage(content = {}) {
|
|
640
|
+
const kind = content.kind ?? "not-found";
|
|
641
|
+
const base = defaults[kind];
|
|
642
|
+
const siteName = content.siteName?.trim();
|
|
643
|
+
if (siteName !== undefined)
|
|
644
|
+
assertText("siteName", siteName, 40);
|
|
645
|
+
const glyph = content.glyph ?? base.glyph;
|
|
646
|
+
assertText("glyph", glyph, 4);
|
|
647
|
+
const title = content.title ?? base.title;
|
|
648
|
+
assertText("title", title, 60);
|
|
649
|
+
const summary = content.summary ?? base.summary;
|
|
650
|
+
assertText("summary", summary, 160);
|
|
651
|
+
const primaryAction = content.primaryAction ?? {
|
|
652
|
+
href: "/",
|
|
653
|
+
label: siteName ? `Go to ${siteName}` : "Go to the homepage"
|
|
654
|
+
};
|
|
655
|
+
assertLink("primaryAction", primaryAction);
|
|
656
|
+
const next = content.next ?? [];
|
|
657
|
+
if (next.length > STATUS_PAGE_MAX_NEXT) {
|
|
658
|
+
throw new RangeError(`A status page lists at most ${STATUS_PAGE_MAX_NEXT} next links; pick the ones that lead to your product.`);
|
|
659
|
+
}
|
|
660
|
+
next.forEach((link) => assertLink("next", link));
|
|
661
|
+
const nextHeading = content.nextHeading ?? "Or start here";
|
|
662
|
+
assertText("nextHeading", nextHeading, 40);
|
|
663
|
+
const routes = usableRoutes(content.routes ?? []);
|
|
664
|
+
if (content.agentIndexHref !== undefined)
|
|
665
|
+
assertArticleHref(content.agentIndexHref);
|
|
666
|
+
return {
|
|
667
|
+
kind,
|
|
668
|
+
glyph,
|
|
669
|
+
title,
|
|
670
|
+
summary,
|
|
671
|
+
primaryAction,
|
|
672
|
+
next,
|
|
673
|
+
nextHeading,
|
|
674
|
+
routes,
|
|
675
|
+
...content.agentIndexHref === undefined ? {} : {
|
|
676
|
+
agentIndexHref: content.agentIndexHref
|
|
677
|
+
}
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
function isSitePath(href) {
|
|
681
|
+
return /^\/(?![/\\])/u.test(href);
|
|
682
|
+
}
|
|
683
|
+
function statusPageRoutesAttribute(routes) {
|
|
684
|
+
if (routes.length === 0)
|
|
685
|
+
return;
|
|
686
|
+
return JSON.stringify(routes.map(({
|
|
687
|
+
href,
|
|
688
|
+
label
|
|
689
|
+
}) => [href, label]));
|
|
690
|
+
}
|
|
691
|
+
function parseStatusPageRoutes(value) {
|
|
692
|
+
if (!value)
|
|
693
|
+
return [];
|
|
694
|
+
let parsed;
|
|
695
|
+
try {
|
|
696
|
+
parsed = JSON.parse(value);
|
|
697
|
+
} catch {
|
|
698
|
+
return [];
|
|
699
|
+
}
|
|
700
|
+
if (!Array.isArray(parsed))
|
|
701
|
+
return [];
|
|
702
|
+
const routes = [];
|
|
703
|
+
for (const entry of parsed.slice(0, STATUS_PAGE_MAX_ROUTES)) {
|
|
704
|
+
if (!Array.isArray(entry))
|
|
705
|
+
continue;
|
|
706
|
+
const [href, label] = entry;
|
|
707
|
+
if (typeof href !== "string" || typeof label !== "string")
|
|
708
|
+
continue;
|
|
709
|
+
if (!isSitePath(href) || label.trim() === "")
|
|
710
|
+
continue;
|
|
711
|
+
routes.push({
|
|
712
|
+
href,
|
|
713
|
+
label
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
return routes;
|
|
717
|
+
}
|
|
718
|
+
var MAX_PATH = 160;
|
|
719
|
+
function normalizeStatusPath(value) {
|
|
720
|
+
let path = value.slice(0, MAX_PATH * 4);
|
|
721
|
+
const end = path.search(/[?#]/u);
|
|
722
|
+
if (end !== -1)
|
|
723
|
+
path = path.slice(0, end);
|
|
724
|
+
try {
|
|
725
|
+
path = decodeURIComponent(path);
|
|
726
|
+
} catch {}
|
|
727
|
+
path = path.toLowerCase().split("/").filter((part, index) => index === 0 || part !== "").join("/");
|
|
728
|
+
path = path.replace(/(?:\/index)?\.html?$/u, "");
|
|
729
|
+
while (path.length > 1 && path.endsWith("/"))
|
|
730
|
+
path = path.slice(0, -1);
|
|
731
|
+
if (!path.startsWith("/"))
|
|
732
|
+
path = `/${path}`;
|
|
733
|
+
return path.slice(0, MAX_PATH);
|
|
734
|
+
}
|
|
735
|
+
var MAX_EDITS = 3;
|
|
736
|
+
var BEYOND = MAX_EDITS + 1;
|
|
737
|
+
function editDistance(a, b, limit) {
|
|
738
|
+
if (Math.abs(a.length - b.length) > limit)
|
|
739
|
+
return limit + 1;
|
|
740
|
+
const columns = b.length + 1;
|
|
741
|
+
let before = new Int32Array(columns).fill(BEYOND);
|
|
742
|
+
let previous = Int32Array.from({
|
|
743
|
+
length: columns
|
|
744
|
+
}, (_, index) => Math.min(index, BEYOND));
|
|
745
|
+
let current = new Int32Array(columns).fill(BEYOND);
|
|
746
|
+
for (let i = 1;i <= a.length; i++) {
|
|
747
|
+
const low = Math.max(1, i - limit);
|
|
748
|
+
const high = Math.min(b.length, i + limit);
|
|
749
|
+
current[low - 1] = low === 1 ? Math.min(i, BEYOND) : BEYOND;
|
|
750
|
+
if (high < b.length)
|
|
751
|
+
current[high + 1] = BEYOND;
|
|
752
|
+
let rowMin = BEYOND;
|
|
753
|
+
for (let j = low;j <= high; j++) {
|
|
754
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
755
|
+
let value = Math.min((previous[j] ?? BEYOND) + 1, (current[j - 1] ?? BEYOND) + 1, (previous[j - 1] ?? BEYOND) + cost);
|
|
756
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {
|
|
757
|
+
value = Math.min(value, (before[j - 2] ?? BEYOND) + 1);
|
|
758
|
+
}
|
|
759
|
+
current[j] = Math.min(value, BEYOND);
|
|
760
|
+
rowMin = Math.min(rowMin, value);
|
|
761
|
+
}
|
|
762
|
+
if (rowMin > limit)
|
|
763
|
+
return limit + 1;
|
|
764
|
+
[before, previous, current] = [previous, current, before];
|
|
765
|
+
}
|
|
766
|
+
return Math.min(previous[b.length] ?? BEYOND, limit + 1);
|
|
767
|
+
}
|
|
768
|
+
function words(path) {
|
|
769
|
+
return path.split(/[/\-_.]+/u).filter((word) => word.length > 0);
|
|
770
|
+
}
|
|
771
|
+
function wordAllowance(word) {
|
|
772
|
+
if (word.length < 4)
|
|
773
|
+
return 0;
|
|
774
|
+
return word.length < 8 ? 1 : 2;
|
|
775
|
+
}
|
|
776
|
+
function wordsMatch(missing, candidate) {
|
|
777
|
+
return missing.every((word) => {
|
|
778
|
+
const allowance = wordAllowance(word);
|
|
779
|
+
return candidate.some((other) => other === word || allowance > 0 && editDistance(word, other, allowance) <= allowance);
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
function candidate(path) {
|
|
783
|
+
const parts = words(path);
|
|
784
|
+
return {
|
|
785
|
+
path,
|
|
786
|
+
words: parts,
|
|
787
|
+
joined: parts.join(""),
|
|
788
|
+
last: path.slice(path.lastIndexOf("/") + 1)
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
function score(missing, page) {
|
|
792
|
+
if (page.path === missing.path)
|
|
793
|
+
return 0;
|
|
794
|
+
if (missing.joined.length >= 6 && missing.joined === page.joined)
|
|
795
|
+
return 0.1;
|
|
796
|
+
const longest = Math.max(missing.path.length, page.path.length);
|
|
797
|
+
const limit = Math.min(MAX_EDITS, Math.floor(longest / 4));
|
|
798
|
+
if (limit > 0 && wordsMatch(missing.words, page.words)) {
|
|
799
|
+
const distance = editDistance(missing.path, page.path, limit);
|
|
800
|
+
if (distance <= limit)
|
|
801
|
+
return distance / longest;
|
|
802
|
+
}
|
|
803
|
+
if (missing.last.length >= 6 && missing.last === page.last)
|
|
804
|
+
return 0.5;
|
|
805
|
+
const longer = missing.words.filter((word) => word.length >= 3);
|
|
806
|
+
if (longer.length >= 2 && longer.length === missing.words.length && longer.every((word) => page.words.includes(word)))
|
|
807
|
+
return 0.6;
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
function suggestStatusRoute(pathname, routes) {
|
|
811
|
+
const normalized = normalizeStatusPath(pathname);
|
|
812
|
+
if (normalized === "/")
|
|
813
|
+
return;
|
|
814
|
+
const exactOnly = normalized.length < 5;
|
|
815
|
+
const missing = candidate(normalized);
|
|
816
|
+
let best;
|
|
817
|
+
for (const route of routes.slice(0, STATUS_PAGE_MAX_ROUTES)) {
|
|
818
|
+
if (!isSitePath(route.href))
|
|
819
|
+
continue;
|
|
820
|
+
const path = normalizeStatusPath(route.href);
|
|
821
|
+
if (path === "/" || exactOnly && path !== normalized)
|
|
822
|
+
continue;
|
|
823
|
+
const value = score(missing, candidate(path));
|
|
824
|
+
if (value === undefined)
|
|
825
|
+
continue;
|
|
826
|
+
if (best === undefined || value < best.score || value === best.score && (path.length < best.path.length || path.length === best.path.length && path < best.path)) {
|
|
827
|
+
best = {
|
|
828
|
+
route,
|
|
829
|
+
score: value,
|
|
830
|
+
path
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
return best?.route;
|
|
835
|
+
}
|
|
836
|
+
// src/status-page-html.ts
|
|
837
|
+
function renderStatusPageHtml(options = {}) {
|
|
838
|
+
const page = resolveStatusPage(options);
|
|
839
|
+
const level = options.titleLevel ?? 1;
|
|
840
|
+
const root = options.rootElement ?? "main";
|
|
841
|
+
const notFound = page.kind === "not-found";
|
|
842
|
+
const routes = notFound ? statusPageRoutesAttribute(page.routes) : undefined;
|
|
843
|
+
const next = page.next.length === 0 ? "" : [`<nav aria-labelledby="${STATUS_PAGE_NEXT_HEADING_ID}" class="hraness-status-page__next">`, `<h${level + 1} class="hraness-status-page__next-heading" id="${STATUS_PAGE_NEXT_HEADING_ID}">${escapeArticleHtml(page.nextHeading)}</h${level + 1}>`, '<ul class="hraness-status-page__next-list">', ...page.next.map((link) => [`<li><a class="hraness-status-page__next-link" href="${escapeArticleHtml(link.href)}">`, `<span class="hraness-status-page__next-label">${escapeArticleHtml(link.label)}</span>`, link.description === undefined ? "" : `<span class="hraness-status-page__next-description">${escapeArticleHtml(link.description)}</span>`, "</a></li>"].join("")), "</ul></nav>"].join("");
|
|
844
|
+
const agent = page.agentIndexHref === undefined ? "" : `<p class="hraness-status-page__agent">${STATUS_PAGE_AGENT_PREFIX} <a href="${escapeArticleHtml(page.agentIndexHref)}">${escapeArticleHtml(page.agentIndexHref)}</a></p>`;
|
|
845
|
+
return [`<${root} class="hraness-status-page"${routes === undefined ? "" : ` data-hraness-status-routes="${escapeArticleHtml(routes)}"`} data-kind="${page.kind}">`, '<div class="hraness-status-page__inner">', `<div aria-hidden="true" class="hraness-status-page__code"><span class="hraness-status-page__glyph">${escapeArticleHtml(page.glyph)}</span><canvas class="hraness-status-page__field"></canvas></div>`, `<h${level} class="hraness-status-page__title">${escapeArticleHtml(page.title)}</h${level}>`, `<p class="hraness-status-page__summary">${escapeArticleHtml(page.summary)}</p>`, notFound ? `<p class="hraness-status-page__hint" hidden="">${STATUS_PAGE_HINT_PREFIX} <a class="hraness-status-page__hint-link" href="/"></a>?</p>` : "", '<div class="hraness-status-page__actions">', `<a class="hraness-status-page__action hraness-foil" data-emphasis="primary" data-foil="" href="${escapeArticleHtml(page.primaryAction.href)}">${escapeArticleHtml(page.primaryAction.label)}</a>`, `<a class="hraness-status-page__back" hidden="" href="/">${STATUS_PAGE_BACK_LABEL}</a>`, "</div>", next, agent, "</div>", `</${root}>`].join("");
|
|
846
|
+
}
|
|
847
|
+
// src/relative-time.ts
|
|
848
|
+
var second = 1000;
|
|
849
|
+
var minute = 60 * second;
|
|
850
|
+
var hour = 60 * minute;
|
|
851
|
+
var day = 24 * hour;
|
|
852
|
+
var week = 7 * day;
|
|
853
|
+
var year = 365.2425 * day;
|
|
854
|
+
var month = year / 12;
|
|
855
|
+
var buckets = [{
|
|
856
|
+
unit: "second",
|
|
857
|
+
milliseconds: second,
|
|
858
|
+
limit: 60
|
|
859
|
+
}, {
|
|
860
|
+
unit: "minute",
|
|
861
|
+
milliseconds: minute,
|
|
862
|
+
limit: 60
|
|
863
|
+
}, {
|
|
864
|
+
unit: "hour",
|
|
865
|
+
milliseconds: hour,
|
|
866
|
+
limit: 24
|
|
867
|
+
}, {
|
|
868
|
+
unit: "day",
|
|
869
|
+
milliseconds: day,
|
|
870
|
+
limit: 7
|
|
871
|
+
}, {
|
|
872
|
+
unit: "week",
|
|
873
|
+
milliseconds: week,
|
|
874
|
+
limit: 4
|
|
875
|
+
}, {
|
|
876
|
+
unit: "month",
|
|
877
|
+
milliseconds: month,
|
|
878
|
+
limit: 12
|
|
879
|
+
}, {
|
|
880
|
+
unit: "year",
|
|
881
|
+
milliseconds: year,
|
|
882
|
+
limit: Number.POSITIVE_INFINITY
|
|
883
|
+
}];
|
|
884
|
+
var relativeTimeUnits = Object.freeze(buckets.map((bucket) => bucket.unit));
|
|
885
|
+
var maximumTime = 8640000000000000;
|
|
886
|
+
var isoDate = /^(\d{4})-(\d{2})-(\d{2})$/u;
|
|
887
|
+
var isoDateTime = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,9}))?)?(Z|[+-]\d{2}:\d{2})$/u;
|
|
888
|
+
function describe(value) {
|
|
889
|
+
if (typeof value === "string")
|
|
890
|
+
return JSON.stringify(value);
|
|
891
|
+
if (value instanceof Date)
|
|
892
|
+
return "an invalid Date";
|
|
893
|
+
return String(value);
|
|
894
|
+
}
|
|
895
|
+
function fromTime(time, label, original) {
|
|
896
|
+
if (!Number.isFinite(time) || Math.abs(time) > maximumTime) {
|
|
897
|
+
throw new RangeError(`${label} must be a valid instant; received ${describe(original)}.`);
|
|
898
|
+
}
|
|
899
|
+
return new Date(time);
|
|
900
|
+
}
|
|
901
|
+
function parseIsoString(value, label) {
|
|
902
|
+
const date = isoDate.exec(value);
|
|
903
|
+
const dateTime = date === null ? isoDateTime.exec(value) : null;
|
|
904
|
+
const parts = date ?? dateTime;
|
|
905
|
+
if (parts === null) {
|
|
906
|
+
throw new RangeError(`${label} must be an ISO 8601 date (YYYY-MM-DD) or a date-time with Z or an offset; received ${describe(value)}.`);
|
|
907
|
+
}
|
|
908
|
+
const [yearText, monthText, dayText, hourText = "00", minuteText = "00", secondText = "00", fraction = "", zone = "Z"] = parts.slice(1);
|
|
909
|
+
const fields = [yearText, monthText, dayText, hourText, minuteText, secondText].map(Number);
|
|
910
|
+
const [y, mo, d, h, mi, s] = fields;
|
|
911
|
+
const offsetHours = zone === "Z" ? 0 : Number(zone.slice(1, 3));
|
|
912
|
+
const offsetRest = zone === "Z" ? 0 : Number(zone.slice(4, 6));
|
|
913
|
+
const offsetMinutes = (zone.startsWith("-") ? -1 : 1) * (offsetHours * 60 + offsetRest);
|
|
914
|
+
const milliseconds = Number(fraction.padEnd(3, "0").slice(0, 3));
|
|
915
|
+
const wall = new Date(0);
|
|
916
|
+
wall.setUTCFullYear(y, mo - 1, d);
|
|
917
|
+
wall.setUTCHours(h, mi, s, milliseconds);
|
|
918
|
+
const valid = h < 24 && mi < 60 && s < 60 && offsetHours < 24 && offsetRest < 60 && wall.getUTCFullYear() === y && wall.getUTCMonth() === mo - 1 && wall.getUTCDate() === d;
|
|
919
|
+
if (!valid)
|
|
920
|
+
throw new RangeError(`${label} must name a real calendar instant; received ${describe(value)}.`);
|
|
921
|
+
return fromTime(wall.getTime() - offsetMinutes * minute, label, value);
|
|
922
|
+
}
|
|
923
|
+
function parseRelativeTimeInput(value, label = "time") {
|
|
924
|
+
if (value instanceof Date)
|
|
925
|
+
return fromTime(value.getTime(), label, value);
|
|
926
|
+
if (typeof value === "number")
|
|
927
|
+
return fromTime(value, label, value);
|
|
928
|
+
if (typeof value === "string")
|
|
929
|
+
return parseIsoString(value.trim(), label);
|
|
930
|
+
throw new TypeError(`${label} must be a Date, epoch milliseconds, or an ISO 8601 string.`);
|
|
931
|
+
}
|
|
932
|
+
function parseReference(value) {
|
|
933
|
+
if (value === undefined)
|
|
934
|
+
return new Date;
|
|
935
|
+
if (value instanceof Date || typeof value === "number")
|
|
936
|
+
return parseRelativeTimeInput(value, "now");
|
|
937
|
+
throw new TypeError("now must be a Date or epoch milliseconds.");
|
|
938
|
+
}
|
|
939
|
+
function parseNumeric(value) {
|
|
940
|
+
if (value === undefined)
|
|
941
|
+
return "auto";
|
|
942
|
+
if (value === "auto" || value === "always")
|
|
943
|
+
return value;
|
|
944
|
+
throw new TypeError(`numeric must be "auto" or "always"; received ${describe(value)}.`);
|
|
945
|
+
}
|
|
946
|
+
function parseLocale(value) {
|
|
947
|
+
if (value === undefined)
|
|
948
|
+
return;
|
|
949
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
950
|
+
throw new TypeError("locale must be a non-empty BCP 47 language tag.");
|
|
951
|
+
}
|
|
952
|
+
return value;
|
|
953
|
+
}
|
|
954
|
+
function resolveRelativeTime(differenceMilliseconds) {
|
|
955
|
+
if (!Number.isFinite(differenceMilliseconds)) {
|
|
956
|
+
throw new RangeError("The time difference must be a finite number of milliseconds.");
|
|
957
|
+
}
|
|
958
|
+
const magnitude = Math.abs(differenceMilliseconds);
|
|
959
|
+
const sign = differenceMilliseconds < 0 || Object.is(differenceMilliseconds, -0) ? -1 : 1;
|
|
960
|
+
for (const bucket of buckets) {
|
|
961
|
+
const amount = Math.round(magnitude / bucket.milliseconds);
|
|
962
|
+
if (amount < bucket.limit) {
|
|
963
|
+
return {
|
|
964
|
+
unit: bucket.unit,
|
|
965
|
+
value: sign * amount
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
throw new RangeError("No relative time unit matched.");
|
|
970
|
+
}
|
|
971
|
+
var formatters = new Map;
|
|
972
|
+
function formatterFor(locale, numeric) {
|
|
973
|
+
const key = `${locale ?? ""}\x00${numeric}`;
|
|
974
|
+
let formatter = formatters.get(key);
|
|
975
|
+
if (formatter === undefined) {
|
|
976
|
+
formatter = new Intl.RelativeTimeFormat(locale, {
|
|
977
|
+
numeric,
|
|
978
|
+
style: "long"
|
|
979
|
+
});
|
|
980
|
+
formatters.set(key, formatter);
|
|
981
|
+
}
|
|
982
|
+
return formatter;
|
|
983
|
+
}
|
|
984
|
+
function formatRelativeTime(target, options = {}) {
|
|
985
|
+
const instant = parseRelativeTimeInput(target, "target");
|
|
986
|
+
const reference = parseReference(options.now);
|
|
987
|
+
const numeric = parseNumeric(options.numeric);
|
|
988
|
+
const locale = parseLocale(options.locale);
|
|
989
|
+
const {
|
|
990
|
+
unit,
|
|
991
|
+
value
|
|
992
|
+
} = resolveRelativeTime(instant.getTime() - reference.getTime());
|
|
993
|
+
return formatterFor(locale, numeric).format(value, unit);
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
// src/index.ts
|
|
997
|
+
var colors = {
|
|
998
|
+
light: {
|
|
999
|
+
background: "#fbf6f2",
|
|
1000
|
+
foreground: "#201b19",
|
|
1001
|
+
muted: "#6b625d",
|
|
1002
|
+
faint: "#6b625d",
|
|
1003
|
+
grid: "#eaded8",
|
|
1004
|
+
line: "#bbaaa2",
|
|
1005
|
+
controlBorder: "#8f8f8f",
|
|
1006
|
+
surface: "#ffffff",
|
|
1007
|
+
surfaceRaised: "#f3ece8",
|
|
1008
|
+
surfaceHover: "#eaded8",
|
|
1009
|
+
card: "#ffffff",
|
|
1010
|
+
cardForeground: "#201b19",
|
|
1011
|
+
popover: "#ffffff",
|
|
1012
|
+
popoverForeground: "#201b19",
|
|
1013
|
+
primary: "#201b19",
|
|
1014
|
+
primaryForeground: "#fbf6f2",
|
|
1015
|
+
secondary: "#f3ece8",
|
|
1016
|
+
secondaryForeground: "#201b19",
|
|
1017
|
+
accent: "#eaded8",
|
|
1018
|
+
accentForeground: "#201b19",
|
|
1019
|
+
info: "#0d61ac",
|
|
1020
|
+
infoSoft: "#d8eaff",
|
|
1021
|
+
focus: "#0d61ac",
|
|
1022
|
+
scrim: "rgba(2, 2, 2, 0.44)",
|
|
1023
|
+
disabled: "#e8ded9",
|
|
1024
|
+
disabledForeground: "#717171",
|
|
1025
|
+
inverse: "#201b19",
|
|
1026
|
+
inverseForeground: "#fbf6f2",
|
|
1027
|
+
success: "#2d6a42",
|
|
1028
|
+
successSoft: "rgba(45, 106, 66, 0.12)",
|
|
1029
|
+
warning: "#785f28",
|
|
1030
|
+
warningSoft: "rgba(120, 95, 40, 0.12)",
|
|
1031
|
+
danger: "#9f3631",
|
|
1032
|
+
dangerSoft: "rgba(159, 54, 49, 0.12)"
|
|
1033
|
+
},
|
|
1034
|
+
dark: {
|
|
1035
|
+
background: "#000000",
|
|
1036
|
+
foreground: "#f2f2ed",
|
|
1037
|
+
muted: "#8f938c",
|
|
1038
|
+
faint: "#8f938c",
|
|
1039
|
+
grid: "#1c1e1b",
|
|
1040
|
+
line: "#5f645d",
|
|
1041
|
+
controlBorder: "#666666",
|
|
1042
|
+
surface: "#0d0e0c",
|
|
1043
|
+
surfaceRaised: "#161814",
|
|
1044
|
+
surfaceHover: "#1c1e1b",
|
|
1045
|
+
card: "#0d0e0c",
|
|
1046
|
+
cardForeground: "#f2f2ed",
|
|
1047
|
+
popover: "#161814",
|
|
1048
|
+
popoverForeground: "#f2f2ed",
|
|
1049
|
+
primary: "#f2f2ed",
|
|
1050
|
+
primaryForeground: "#0d0e0c",
|
|
1051
|
+
secondary: "#252820",
|
|
1052
|
+
secondaryForeground: "#f2f2ed",
|
|
1053
|
+
accent: "#1c1e1b",
|
|
1054
|
+
accentForeground: "#f2f2ed",
|
|
1055
|
+
info: "#6aa9ed",
|
|
1056
|
+
infoSoft: "#152d46",
|
|
1057
|
+
focus: "#6aa9ed",
|
|
1058
|
+
scrim: "rgba(0, 0, 0, 0.72)",
|
|
1059
|
+
disabled: "#262626",
|
|
1060
|
+
disabledForeground: "#777777",
|
|
1061
|
+
inverse: "#f2f2ed",
|
|
1062
|
+
inverseForeground: "#0d0e0c",
|
|
1063
|
+
success: "#76b38e",
|
|
1064
|
+
successSoft: "rgba(118, 179, 142, 0.12)",
|
|
1065
|
+
warning: "#c9ad74",
|
|
1066
|
+
warningSoft: "rgba(201, 173, 116, 0.12)",
|
|
1067
|
+
danger: "#e18982",
|
|
1068
|
+
dangerSoft: "rgba(225, 137, 130, 0.12)"
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1071
|
+
var auroraColors = {
|
|
1072
|
+
light: {
|
|
1073
|
+
violet: "oklch(0.82 0.048 312)",
|
|
1074
|
+
rose: "oklch(0.85 0.044 12)",
|
|
1075
|
+
gold: "oklch(0.92 0.036 96)",
|
|
1076
|
+
mint: "oklch(0.9 0.036 172)",
|
|
1077
|
+
cyan: "oklch(0.84 0.042 236)"
|
|
1078
|
+
},
|
|
1079
|
+
dark: {
|
|
1080
|
+
violet: "oklch(0.58 0.045 312)",
|
|
1081
|
+
rose: "oklch(0.61 0.04 12)",
|
|
1082
|
+
gold: "oklch(0.69 0.035 96)",
|
|
1083
|
+
mint: "oklch(0.63 0.035 172)",
|
|
1084
|
+
cyan: "oklch(0.6 0.04 236)"
|
|
1085
|
+
}
|
|
1086
|
+
};
|
|
1087
|
+
var chromeColors = {
|
|
1088
|
+
light: {
|
|
1089
|
+
deep: "rgb(52 52 64)",
|
|
1090
|
+
shadow: "rgb(58 58 72)",
|
|
1091
|
+
mid: "rgb(92 92 106)",
|
|
1092
|
+
high: "rgb(88 88 100)",
|
|
1093
|
+
glint: "rgb(100 100 112)"
|
|
1094
|
+
},
|
|
1095
|
+
dark: {
|
|
1096
|
+
deep: "rgb(100 102 122)",
|
|
1097
|
+
shadow: "rgb(112 114 136)",
|
|
1098
|
+
mid: "rgb(166 168 190)",
|
|
1099
|
+
high: "rgb(158 160 182)",
|
|
1100
|
+
glint: "rgb(178 180 200)"
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1103
|
+
var chromeGradientStops = {
|
|
1104
|
+
light: [[0, "rgb(52 52 64)"], [10, "rgb(88 88 100)"], [20, "rgb(58 58 72)"], [32, "rgb(100 100 112)"], [42, "rgb(64 64 78)"], [52, "rgb(92 92 106)"], [62, "rgb(54 54 68)"], [72, "rgb(86 86 100)"], [82, "rgb(56 56 70)"], [91, "rgb(80 80 94)"], [100, "rgb(60 60 74)"]],
|
|
1105
|
+
dark: [[0, "rgb(100 102 122)"], [10, "rgb(158 160 182)"], [20, "rgb(112 114 136)"], [32, "rgb(178 180 200)"], [42, "rgb(122 124 148)"], [52, "rgb(166 168 190)"], [62, "rgb(106 108 132)"], [72, "rgb(160 162 186)"], [82, "rgb(110 112 136)"], [91, "rgb(152 154 178)"], [100, "rgb(118 120 142)"]]
|
|
1106
|
+
};
|
|
1107
|
+
var spacing = [0, 4, 8, 12, 16, 20, 24, 32, 48, 64];
|
|
1108
|
+
var radius = {
|
|
1109
|
+
sharp: 0,
|
|
1110
|
+
sm: 4,
|
|
1111
|
+
md: 8,
|
|
1112
|
+
lg: 12,
|
|
1113
|
+
round: 999
|
|
1114
|
+
};
|
|
1115
|
+
var controlRadius = 16;
|
|
1116
|
+
var layout = {
|
|
1117
|
+
chromeInset: 8,
|
|
1118
|
+
edgeInset: 24
|
|
1119
|
+
};
|
|
1120
|
+
var siteThemes = {
|
|
1121
|
+
plain: {
|
|
1122
|
+
bodyClassName: "plain-site",
|
|
1123
|
+
footerClassName: "plain-footer",
|
|
1124
|
+
pageClassName: "plain-page"
|
|
1125
|
+
}
|
|
1126
|
+
};
|
|
1127
|
+
var interaction = {
|
|
1128
|
+
compactTarget: 40,
|
|
1129
|
+
minimumTarget: 48,
|
|
1130
|
+
controlHeight: 52,
|
|
1131
|
+
primaryControlHeight: 56,
|
|
1132
|
+
transportControlHeight: 64
|
|
1133
|
+
};
|
|
1134
|
+
var motion = {
|
|
1135
|
+
duration: {
|
|
1136
|
+
instant: 0,
|
|
1137
|
+
fast: 120,
|
|
1138
|
+
standard: 180,
|
|
1139
|
+
slow: 280
|
|
1140
|
+
},
|
|
1141
|
+
distance: {
|
|
1142
|
+
railEnter: 14,
|
|
1143
|
+
railExit: 10
|
|
1144
|
+
},
|
|
1145
|
+
easing: {
|
|
1146
|
+
standard: "cubic-bezier(0.2, 0, 0, 1)",
|
|
1147
|
+
emphasized: "cubic-bezier(0.16, 1, 0.3, 1)"
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
var elevation = {
|
|
1151
|
+
none: "none",
|
|
1152
|
+
low: "0 1px 2px oklch(0 0 0 / 0.08)",
|
|
1153
|
+
raised: "0 8px 24px -12px oklch(0 0 0 / 0.22)",
|
|
1154
|
+
overlay: "0 18px 48px -18px oklch(0 0 0 / 0.32)"
|
|
1155
|
+
};
|
|
1156
|
+
var stacking = {
|
|
1157
|
+
chrome: 50,
|
|
1158
|
+
modal: 2000,
|
|
1159
|
+
tooltip: 3000,
|
|
1160
|
+
skipLink: 4000
|
|
1161
|
+
};
|
|
1162
|
+
var breakpoints = {
|
|
1163
|
+
compact: 480,
|
|
1164
|
+
medium: 768,
|
|
1165
|
+
wide: 1200,
|
|
1166
|
+
canvas: 1440
|
|
1167
|
+
};
|
|
1168
|
+
var iconography = {
|
|
1169
|
+
size: 20,
|
|
1170
|
+
strokeWidth: 1.5
|
|
1171
|
+
};
|
|
1172
|
+
var typeScale = {
|
|
1173
|
+
caption: 12,
|
|
1174
|
+
label: 14,
|
|
1175
|
+
body: 16,
|
|
1176
|
+
control: 16,
|
|
1177
|
+
controlGlyph: 20,
|
|
1178
|
+
heading: 24,
|
|
1179
|
+
title: 32,
|
|
1180
|
+
display: 56
|
|
1181
|
+
};
|
|
1182
|
+
var fontWeights = {
|
|
1183
|
+
regular: 450,
|
|
1184
|
+
medium: 550,
|
|
1185
|
+
bold: 700
|
|
1186
|
+
};
|
|
1187
|
+
var fontFamilies = {
|
|
1188
|
+
heading: "Nebula Sans",
|
|
1189
|
+
mono: "ui-monospace",
|
|
1190
|
+
text: "Nebula Sans"
|
|
1191
|
+
};
|
|
1192
|
+
var fontFallbacks = {
|
|
1193
|
+
mono: ["SFMono-Regular", "Menlo", "Monaco", "Consolas", "monospace"],
|
|
1194
|
+
text: ["system-ui", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "sans-serif"]
|
|
1195
|
+
};
|
|
1196
|
+
var webTextStack = '"Nebula Sans", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
|
|
1197
|
+
var webMonoStack = 'ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, monospace';
|
|
1198
|
+
var typography = {
|
|
1199
|
+
fontText: webTextStack,
|
|
1200
|
+
fontHeading: webTextStack,
|
|
1201
|
+
fontMono: webMonoStack,
|
|
1202
|
+
fontGeistMono: '"Geist Mono", ui-monospace, "SFMono-Regular", Menlo, Monaco, Consolas, monospace',
|
|
1203
|
+
fontSans: webTextStack
|
|
1204
|
+
};
|
|
1205
|
+
function themeFor(mode) {
|
|
1206
|
+
return colors[mode];
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
export { designPalettes, designPaletteLabels, isDesignPalette, designPaletteSources, paletteColors, designThemes, defaultDesignTheme, designThemeStorageKey, isDesignTheme, normalizeDesignTheme, designThemeLabel, resolveDesignTheme, defaultDesignPalettePreference, designPaletteStorageKey, parseDesignPalettePreference, normalizeDesignPalettePreference, resolveDesignPalettePreference, getDesignPaletteTheme, escapeArticleHtml, renderArticleBylineHtml, renderArticleProvenanceHtml, renderArticleHtml, renderArticleSourcesHtml, renderArticleCalloutHtml, renderArticleRelatedHtml, renderArticleIndexHtml, STATUS_PAGE_MAX_NEXT, STATUS_PAGE_MAX_ROUTES, STATUS_PAGE_BACK_LABEL, STATUS_PAGE_HINT_PREFIX, STATUS_PAGE_NEXT_HEADING_ID, STATUS_PAGE_AGENT_PREFIX, resolveStatusPage, statusPageRoutesAttribute, parseStatusPageRoutes, normalizeStatusPath, suggestStatusRoute, renderStatusPageHtml, relativeTimeUnits, parseRelativeTimeInput, resolveRelativeTime, formatRelativeTime, colors, auroraColors, chromeColors, chromeGradientStops, spacing, radius, controlRadius, layout, siteThemes, interaction, motion, elevation, stacking, breakpoints, iconography, typeScale, fontWeights, fontFamilies, fontFallbacks, typography, themeFor };
|