import { createScope, Styles } from '../src' import { theme } from './ssr/themes' import markdown from 'snarkdown' import Prism from 'prismjs' import 'prismjs/components/prism-javascript' import 'prismjs/components/prism-jsx' import 'prismjs/components/prism-typescript' import 'prismjs/components/prism-tsx' const { define } = createScope('Landing') const Page = define('Page', { base: 'body', margin: 0, padding: theme('spacing-xl'), minHeight: '100vh', fontFamily: theme('fonts-mono'), background: theme('colors-bg'), color: theme('colors-fg'), }) const Container = define('Container', { maxWidth: 800, margin: '0 auto', }) const Pre = define('Pre', { base: 'pre', fontSize: 14, lineHeight: 1.4, marginBottom: theme('spacing-xl'), color: theme('colors-fg'), whiteSpace: 'pre', borderBottom: '1px solid var(--theme-colors-border)', }) const P = define('P', { base: 'p', fontSize: 16, lineHeight: 1.6, marginBottom: theme('spacing-xl'), color: theme('colors-fgMuted'), }) const LinkSection = define('LinkSection', { marginBottom: theme('spacing-xl'), }) const Link = define('Link', { base: 'a', display: 'inline-block', marginRight: theme('spacing-xl'), padding: `${theme('spacing-sm')} ${theme('spacing-lg')}`, background: theme('colors-bgElevated'), border: `1px solid ${theme('colors-border')}`, color: theme('colors-fg'), textDecoration: 'none', fontSize: 14, states: { ':hover': { background: theme('colors-bgHover'), borderColor: theme('colors-borderActive'), } } }) const ThemeToggle = define('ThemeToggle', { position: 'fixed', top: theme('spacing-lg'), right: theme('spacing-lg'), padding: `${theme('spacing-sm')} ${theme('spacing-lg')}`, background: theme('colors-bgElevated'), border: `1px solid ${theme('colors-border')}`, color: theme('colors-fg'), fontSize: 14, cursor: 'pointer', fontFamily: theme('fonts-mono'), states: { ':hover': { background: theme('colors-bgHover'), borderColor: theme('colors-borderActive'), } } }) // Helper to highlight code blocks in markdown HTML function highlightCodeBlocks(html: string): string { return html.replace(/
([\s\S]*?)<\/code><\/pre>/g, (_, lang, code) => {
    // Decode HTML entities
    const decoded = code
      .replace(/</g, '<')
      .replace(/>/g, '>')
      .replace(/&/g, '&')
      .replace(/"/g, '"')
      .replace(/'/g, "'")

    // Map language to Prism grammar (tsx/typescript)
    const grammar = lang === 'tsx' ? Prism.languages.tsx : Prism.languages.typescript

    const highlighted = Prism.highlight(decoded, grammar!, lang)
    return `
${highlighted}
` }) } export const LandingPage = () => { const themeScript = ` function switchTheme(themeName) { document.body.setAttribute('data-theme', themeName) localStorage.setItem('theme', themeName) updateThemeToggle() } function updateThemeToggle() { const currentTheme = document.body.getAttribute('data-theme') const toggle = document.getElementById('theme-toggle') if (toggle) { toggle.textContent = currentTheme === 'dark' ? '☀ light' : '🌙 dark' } } function toggleTheme() { const currentTheme = document.body.getAttribute('data-theme') const newTheme = currentTheme === 'dark' ? 'light' : 'dark' switchTheme(newTheme) } window.switchTheme = switchTheme window.toggleTheme = toggleTheme // Load saved theme or default to dark const savedTheme = localStorage.getItem('theme') || 'dark' document.body.setAttribute('data-theme', savedTheme) updateThemeToggle() ` const prismTheme = ` code[class*="language-"], pre[class*="language-"] { color: var(--theme-colors-fg); background: none; font-family: var(--theme-fonts-mono); text-align: left; white-space: pre; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; hyphens: none; } pre[class*="language-"] { padding: 1em; margin: 0.5em 0; overflow: auto; background: var(--theme-colors-bgElevated); border: 1px solid var(--theme-colors-border); border-radius: 4px; } /* Dark theme colors */ [data-theme="dark"] .token.comment, [data-theme="dark"] .token.prolog, [data-theme="dark"] .token.doctype, [data-theme="dark"] .token.cdata { color: #999999; } [data-theme="dark"] .token.punctuation { color: #808080; } [data-theme="dark"] .token.tag { color: #ff6b6b; } [data-theme="dark"] .token.property, [data-theme="dark"] .token.boolean, [data-theme="dark"] .token.number, [data-theme="dark"] .token.constant, [data-theme="dark"] .token.symbol, [data-theme="dark"] .token.deleted { color: #ffd93d; } [data-theme="dark"] .token.selector, [data-theme="dark"] .token.attr-name, [data-theme="dark"] .token.string, [data-theme="dark"] .token.char, [data-theme="dark"] .token.builtin, [data-theme="dark"] .token.inserted { color: #ff6b6b; } [data-theme="dark"] .token.operator, [data-theme="dark"] .token.entity, [data-theme="dark"] .token.url, [data-theme="dark"] .language-css .token.string, [data-theme="dark"] .style .token.string { color: #d4d4d4; } [data-theme="dark"] .token.atrule, [data-theme="dark"] .token.attr-value, [data-theme="dark"] .token.keyword { color: #bb86fc; } [data-theme="dark"] .token.function, [data-theme="dark"] .token.class-name { color: #4dd0e1; } [data-theme="dark"] .token.regex, [data-theme="dark"] .token.important, [data-theme="dark"] .token.variable { color: #bb86fc; } /* Light theme colors */ [data-theme="light"] .token.comment, [data-theme="light"] .token.prolog, [data-theme="light"] .token.doctype, [data-theme="light"] .token.cdata { color: #888888; } [data-theme="light"] .token.punctuation { color: #666666; } [data-theme="light"] .token.tag { color: #dc143c; } [data-theme="light"] .token.property, [data-theme="light"] .token.boolean, [data-theme="light"] .token.number, [data-theme="light"] .token.constant, [data-theme="light"] .token.symbol, [data-theme="light"] .token.deleted { color: #c9a700; } [data-theme="light"] .token.selector, [data-theme="light"] .token.attr-name, [data-theme="light"] .token.string, [data-theme="light"] .token.char, [data-theme="light"] .token.builtin, [data-theme="light"] .token.inserted { color: #dc143c; } [data-theme="light"] .token.operator, [data-theme="light"] .token.entity, [data-theme="light"] .token.url, [data-theme="light"] .language-css .token.string, [data-theme="light"] .style .token.string { color: #000000; } [data-theme="light"] .token.atrule, [data-theme="light"] .token.attr-value, [data-theme="light"] .token.keyword { color: #9333ea; } [data-theme="light"] .token.function, [data-theme="light"] .token.class-name { color: #0891b2; } [data-theme="light"] .token.regex, [data-theme="light"] .token.important, [data-theme="light"] .token.variable { color: #9333ea; } ` return ( forge