9848803f4f
The /docs deploy from #3860 still returned HTTP 500 with `EvalError: Code generation from strings disallowed for this context` (captured via `wrangler tail`). `next-mdx-remote/rsc` compiles MDX to JSX *at runtime* using `new Function()` style code generation. Cloudflare Workers' security sandbox bans all dynamic code generation from strings, even from inside trusted code, so any worker invocation that touched the docs page threw immediately. Switch to a build-time markdown -> HTML pipeline: - Drop `next-mdx-remote` and `gray-matter`. Add `marked` (pure-JS, no eval). - `web/scripts/generate-docs-content.mjs` now runs each markdown source through `marked.parse()` (gfm enabled) at build time and writes the resulting HTML strings into `web/lib/docs-content.generated.ts`. - `web/app/[locale]/docs/page.tsx` renders each section as `<article className="docs-content" dangerouslySetInnerHTML={{ __html: section.html }} />`. No MDX runtime, no JSX compilation at request time, just static HTML injection. - `web/app/globals.css` adds a `@layer components` block targeting `.docs-content h1..h4, p, a, ul, ol, li, blockquote, code, pre, table, thead, th, td, hr, strong`. Same shadcn-themed look that the dropped `mdx-components.tsx` provided, applied via CSS instead of React component overrides. - `web/components/docs/mdx-components.tsx` removed. We lose MDX features (JSX inside markdown), but the docs are pure markdown anyway. `docs/` remains the SoT; the marketing site renders identical content with no eval and no fs at runtime.
295 lines
6.7 KiB
CSS
295 lines
6.7 KiB
CSS
@import "tailwindcss";
|
|
|
|
@plugin "tailwindcss-animate";
|
|
|
|
@custom-variant dark (&:where(.dark, .dark *));
|
|
|
|
@theme {
|
|
--font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif;
|
|
--font-mono: var(--font-geist-mono), ui-monospace, SFMono-Regular, monospace;
|
|
--font-manrope: var(--font-manrope), sans-serif;
|
|
|
|
--color-background: var(--background);
|
|
--color-foreground: var(--foreground);
|
|
|
|
--color-card: var(--card);
|
|
--color-card-foreground: var(--card-foreground);
|
|
|
|
--color-popover: var(--popover);
|
|
--color-popover-foreground: var(--popover-foreground);
|
|
|
|
--color-primary: var(--primary);
|
|
--color-primary-foreground: var(--primary-foreground);
|
|
|
|
--color-secondary: var(--secondary);
|
|
--color-secondary-foreground: var(--secondary-foreground);
|
|
|
|
--color-muted: var(--muted);
|
|
--color-muted-foreground: var(--muted-foreground);
|
|
|
|
--color-accent: var(--accent);
|
|
--color-accent-foreground: var(--accent-foreground);
|
|
|
|
--color-destructive: var(--destructive);
|
|
--color-destructive-foreground: var(--destructive-foreground);
|
|
|
|
--color-border: var(--border);
|
|
--color-input: var(--input);
|
|
--color-ring: var(--ring);
|
|
|
|
--color-chart-1: var(--chart-1);
|
|
--color-chart-2: var(--chart-2);
|
|
--color-chart-3: var(--chart-3);
|
|
--color-chart-4: var(--chart-4);
|
|
--color-chart-5: var(--chart-5);
|
|
|
|
--radius-lg: var(--radius);
|
|
--radius-md: calc(var(--radius) - 2px);
|
|
--radius-sm: calc(var(--radius) - 4px);
|
|
|
|
--animate-accordion-down: accordion-down 0.2s ease-out;
|
|
--animate-accordion-up: accordion-up 0.2s ease-out;
|
|
|
|
@keyframes accordion-down {
|
|
from {
|
|
height: 0;
|
|
}
|
|
to {
|
|
height: var(--radix-accordion-content-height);
|
|
}
|
|
}
|
|
@keyframes accordion-up {
|
|
from {
|
|
height: var(--radix-accordion-content-height);
|
|
}
|
|
to {
|
|
height: 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
The default border color has changed to `currentColor` in Tailwind CSS v4,
|
|
so we've added these compatibility styles to make sure everything still
|
|
looks the same as it did with Tailwind CSS v3.
|
|
*/
|
|
@layer base {
|
|
*,
|
|
::after,
|
|
::before,
|
|
::backdrop,
|
|
::file-selector-button {
|
|
border-color: var(--color-gray-200, currentColor);
|
|
}
|
|
}
|
|
|
|
@layer base {
|
|
:root {
|
|
/* Dark Theme Only - Terminal/Hacker Aesthetic */
|
|
|
|
/* Colors */
|
|
--background: #0a0a0a;
|
|
--foreground: #ededed;
|
|
|
|
--card: #111111;
|
|
--card-foreground: #ededed;
|
|
|
|
--popover: #111111;
|
|
--popover-foreground: #ededed;
|
|
|
|
--primary: #00d4ff;
|
|
--primary-foreground: #000000;
|
|
|
|
--secondary: #7c3aed;
|
|
--secondary-foreground: #ffffff;
|
|
|
|
--muted: #1a1a1a;
|
|
--muted-foreground: #a1a1a1;
|
|
|
|
--accent: #1a1a1a;
|
|
--accent-foreground: #ededed;
|
|
|
|
--destructive: #ef4444;
|
|
--destructive-foreground: #ffffff;
|
|
|
|
--border: #262626;
|
|
--input: #262626;
|
|
--ring: #00d4ff;
|
|
|
|
/* Charts */
|
|
--chart-1: #00d4ff;
|
|
--chart-2: #7c3aed;
|
|
--chart-3: #10b981;
|
|
--chart-4: #f59e0b;
|
|
--chart-5: #ef4444;
|
|
|
|
/* Code */
|
|
--code-bg: #1e1e2e;
|
|
--code-text: #cdd6f4;
|
|
|
|
/* Spacing */
|
|
--radius: 0.5rem;
|
|
|
|
/* Typography */
|
|
--font-geist-sans: var(--font-geist-sans);
|
|
--font-geist-mono: var(--font-geist-mono);
|
|
--font-manrope: var(--font-manrope);
|
|
--font-inter: var(--font-inter);
|
|
|
|
/* Semantic Fonts */
|
|
--font-heading: var(--font-manrope);
|
|
--font-body: var(--font-geist-sans);
|
|
--font-code: var(--font-geist-mono);
|
|
}
|
|
}
|
|
|
|
@layer base {
|
|
* {
|
|
@apply border-border;
|
|
}
|
|
body {
|
|
@apply bg-background text-foreground;
|
|
font-feature-settings:
|
|
"rlig" 1,
|
|
"calt" 1;
|
|
}
|
|
h1,
|
|
h2,
|
|
h3,
|
|
h4,
|
|
h5,
|
|
h6 {
|
|
font-family: var(--font-manrope);
|
|
}
|
|
|
|
[lang|="ko"] h1,
|
|
[lang|="ko"] h2,
|
|
[lang|="ko"] h3,
|
|
[lang|="ko"] h4,
|
|
[lang|="ko"] h5,
|
|
[lang|="ko"] h6,
|
|
[lang|="ja"] h1,
|
|
[lang|="ja"] h2,
|
|
[lang|="ja"] h3,
|
|
[lang|="ja"] h4,
|
|
[lang|="ja"] h5,
|
|
[lang|="ja"] h6,
|
|
[lang|="zh"] h1,
|
|
[lang|="zh"] h2,
|
|
[lang|="zh"] h3,
|
|
[lang|="zh"] h4,
|
|
[lang|="zh"] h5,
|
|
[lang|="zh"] h6 {
|
|
letter-spacing: normal !important;
|
|
text-wrap: pretty;
|
|
}
|
|
|
|
:where([lang|="ko"], [lang|="ja"], [lang|="zh"])
|
|
:where(p, li, blockquote, figcaption, td, th, a, button, span) {
|
|
overflow-wrap: break-word;
|
|
}
|
|
|
|
[lang|="ko"]
|
|
:where(h1, h2, h3, h4, h5, h6, p, li, blockquote, figcaption, td, th, a, button, span) {
|
|
word-break: keep-all;
|
|
}
|
|
|
|
:where([lang|="ja"], [lang|="zh"])
|
|
:where(h1, h2, h3, h4, h5, h6, p, li, blockquote, figcaption, td, th, a, button, span) {
|
|
word-break: normal;
|
|
line-break: strict;
|
|
}
|
|
|
|
html {
|
|
scroll-behavior: auto;
|
|
}
|
|
|
|
::selection {
|
|
@apply bg-primary/20 text-primary;
|
|
}
|
|
|
|
::-webkit-scrollbar {
|
|
width: 10px;
|
|
height: 10px;
|
|
}
|
|
::-webkit-scrollbar-track {
|
|
@apply bg-muted;
|
|
}
|
|
::-webkit-scrollbar-thumb {
|
|
@apply bg-border hover:bg-muted-foreground/50 rounded-full transition-colors;
|
|
}
|
|
}
|
|
|
|
@layer utilities {
|
|
.glow-cyan {
|
|
box-shadow: 0 0 15px -5px rgba(0, 212, 255, 0.3);
|
|
}
|
|
.glow-purple {
|
|
box-shadow: 0 0 15px -5px rgba(124, 58, 237, 0.3);
|
|
}
|
|
|
|
.text-glow-cyan {
|
|
text-shadow: 0 0 8px rgba(0, 212, 255, 0.3);
|
|
}
|
|
}
|
|
|
|
@layer components {
|
|
.docs-content h1 {
|
|
@apply mt-8 mb-4 scroll-mt-24 text-4xl font-bold tracking-tight first:mt-0;
|
|
}
|
|
.docs-content h2 {
|
|
@apply mt-12 mb-4 scroll-mt-24 text-2xl font-semibold tracking-tight;
|
|
}
|
|
.docs-content h3 {
|
|
@apply mt-8 mb-3 scroll-mt-24 text-xl font-semibold tracking-tight;
|
|
}
|
|
.docs-content h4 {
|
|
@apply mt-6 mb-2 scroll-mt-24 text-lg font-semibold tracking-tight;
|
|
}
|
|
.docs-content p {
|
|
@apply text-muted-foreground my-4 leading-7;
|
|
}
|
|
.docs-content a {
|
|
@apply text-primary font-medium underline underline-offset-4;
|
|
}
|
|
.docs-content ul {
|
|
@apply text-muted-foreground my-4 ml-6 list-disc space-y-1;
|
|
}
|
|
.docs-content ol {
|
|
@apply text-muted-foreground my-4 ml-6 list-decimal space-y-1;
|
|
}
|
|
.docs-content li {
|
|
@apply leading-7;
|
|
}
|
|
.docs-content blockquote {
|
|
@apply border-primary/40 my-6 border-l-4 pl-4 italic;
|
|
}
|
|
.docs-content code:not(pre code) {
|
|
@apply bg-muted text-foreground rounded px-1.5 py-0.5 font-mono text-sm;
|
|
}
|
|
.docs-content pre {
|
|
@apply border-border/50 my-4 overflow-x-auto rounded-lg border bg-[#1e1e2e] p-4 font-mono text-sm text-[#cdd6f4] shadow-sm;
|
|
}
|
|
.docs-content pre code {
|
|
@apply bg-transparent p-0 text-inherit;
|
|
}
|
|
.docs-content table {
|
|
@apply border-border my-6 w-full border-collapse border text-sm;
|
|
}
|
|
.docs-content thead {
|
|
@apply bg-muted;
|
|
}
|
|
.docs-content th {
|
|
@apply border-border border px-3 py-2 text-left font-semibold;
|
|
}
|
|
.docs-content td {
|
|
@apply border-border text-muted-foreground border px-3 py-2;
|
|
}
|
|
.docs-content hr {
|
|
@apply border-border my-8;
|
|
}
|
|
.docs-content strong {
|
|
@apply text-foreground font-semibold;
|
|
}
|
|
}
|