@ox-content/vite-plugin 1.0.0-alpha.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk.cjs +39 -49
- package/dist/github.cjs +323 -3
- package/dist/github.cjs.map +1 -0
- package/dist/github.mjs +2 -0
- package/dist/{github2.js → github2.mjs} +2 -3
- package/dist/github2.mjs.map +1 -0
- package/dist/index.cjs +1371 -598
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +114 -69
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1960 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/{index.js → index.mjs} +1383 -623
- package/dist/index.mjs.map +1 -0
- package/dist/mermaid.cjs +115 -3
- package/dist/mermaid.cjs.map +1 -0
- package/dist/{mermaid2.js → mermaid.mjs} +14 -6
- package/dist/mermaid.mjs.map +1 -0
- package/dist/mermaid2.mjs +2 -0
- package/dist/ogp.cjs +316 -3
- package/dist/ogp.cjs.map +1 -0
- package/dist/ogp.mjs +2 -0
- package/dist/{ogp2.js → ogp2.mjs} +2 -3
- package/dist/ogp2.mjs.map +1 -0
- package/dist/tabs.cjs +212 -3
- package/dist/tabs.cjs.map +1 -0
- package/dist/tabs.mjs +2 -0
- package/dist/{tabs2.js → tabs2.mjs} +2 -3
- package/dist/tabs2.mjs.map +1 -0
- package/dist/youtube.cjs +135 -3
- package/dist/youtube.cjs.map +1 -0
- package/dist/youtube.mjs +2 -0
- package/dist/{youtube2.js → youtube2.mjs} +2 -3
- package/dist/youtube2.mjs.map +1 -0
- package/package.json +61 -56
- package/dist/github.js +0 -3
- package/dist/github2.cjs +0 -313
- package/dist/github2.cjs.map +0 -1
- package/dist/github2.js.map +0 -1
- package/dist/index.d.ts +0 -1915
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mermaid.js +0 -3
- package/dist/mermaid2.cjs +0 -92
- package/dist/mermaid2.cjs.map +0 -1
- package/dist/mermaid2.js.map +0 -1
- package/dist/ogp.js +0 -3
- package/dist/ogp2.cjs +0 -306
- package/dist/ogp2.cjs.map +0 -1
- package/dist/ogp2.js.map +0 -1
- package/dist/tabs.js +0 -3
- package/dist/tabs2.cjs +0 -203
- package/dist/tabs2.cjs.map +0 -1
- package/dist/tabs2.js.map +0 -1
- package/dist/youtube.js +0 -3
- package/dist/youtube2.cjs +0 -127
- package/dist/youtube2.cjs.map +0 -1
- package/dist/youtube2.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { EnvironmentOptions, Plugin } from "vite";
|
|
2
|
-
import { LanguageRegistration, LanguageRegistration as LanguageRegistration$1 } from "shiki";
|
|
2
|
+
import { LanguageRegistration, LanguageRegistration as LanguageRegistration$1, ThemeRegistration, ThemeRegistration as ThemeRegistration$1 } from "shiki";
|
|
3
3
|
|
|
4
4
|
//#region src/theme.d.ts
|
|
5
|
-
|
|
6
5
|
/**
|
|
7
6
|
* Theme API for ox-content SSG
|
|
8
7
|
*
|
|
@@ -51,12 +50,25 @@ interface ThemeFonts {
|
|
|
51
50
|
/** Monospace font stack */
|
|
52
51
|
mono?: string;
|
|
53
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* Entry page theme configuration.
|
|
55
|
+
*/
|
|
56
|
+
interface ThemeEntryPage {
|
|
57
|
+
/** Landing page presentation mode */
|
|
58
|
+
mode?: "default" | "subtle";
|
|
59
|
+
}
|
|
54
60
|
/**
|
|
55
61
|
* Theme header configuration.
|
|
56
62
|
*/
|
|
57
63
|
interface ThemeHeader {
|
|
58
64
|
/** Logo image URL */
|
|
59
65
|
logo?: string;
|
|
66
|
+
/** Light mode logo image URL */
|
|
67
|
+
logoLight?: string;
|
|
68
|
+
/** Dark mode logo image URL */
|
|
69
|
+
logoDark?: string;
|
|
70
|
+
/** Whether to render the site name text next to the logo */
|
|
71
|
+
showSiteNameText?: boolean;
|
|
60
72
|
/** Logo width in pixels */
|
|
61
73
|
logoWidth?: number;
|
|
62
74
|
/** Logo height in pixels */
|
|
@@ -119,6 +131,8 @@ interface ThemeConfig {
|
|
|
119
131
|
darkColors?: ThemeColors;
|
|
120
132
|
/** Font configuration (maps to CSS variables) */
|
|
121
133
|
fonts?: ThemeFonts;
|
|
134
|
+
/** Entry page configuration */
|
|
135
|
+
entryPage?: ThemeEntryPage;
|
|
122
136
|
/** Layout configuration (maps to CSS variables) */
|
|
123
137
|
layout?: ThemeLayout;
|
|
124
138
|
/** Header configuration */
|
|
@@ -142,6 +156,7 @@ interface ResolvedThemeConfig {
|
|
|
142
156
|
colors: ThemeColors;
|
|
143
157
|
darkColors: ThemeColors;
|
|
144
158
|
fonts: ThemeFonts;
|
|
159
|
+
entryPage: ThemeEntryPage;
|
|
145
160
|
layout: ThemeLayout;
|
|
146
161
|
header: ThemeHeader;
|
|
147
162
|
footer: ThemeFooter;
|
|
@@ -186,9 +201,6 @@ declare function mergeThemes(...themes: ThemeConfig[]): ThemeConfig;
|
|
|
186
201
|
* Resolves a theme configuration by merging with its extends chain and defaults.
|
|
187
202
|
*/
|
|
188
203
|
declare function resolveTheme(config?: ThemeConfig): ResolvedThemeConfig;
|
|
189
|
-
/**
|
|
190
|
-
* Converts resolved theme to the format expected by Rust NAPI.
|
|
191
|
-
*/
|
|
192
204
|
//#endregion
|
|
193
205
|
//#region src/types.d.ts
|
|
194
206
|
/**
|
|
@@ -208,6 +220,10 @@ interface HeroAction {
|
|
|
208
220
|
interface HeroImage {
|
|
209
221
|
/** Image source URL */
|
|
210
222
|
src: string;
|
|
223
|
+
/** Light mode image source URL */
|
|
224
|
+
lightSrc?: string;
|
|
225
|
+
/** Dark mode image source URL */
|
|
226
|
+
darkSrc?: string;
|
|
211
227
|
/** Alt text */
|
|
212
228
|
alt?: string;
|
|
213
229
|
/** Image width */
|
|
@@ -215,6 +231,15 @@ interface HeroImage {
|
|
|
215
231
|
/** Image height */
|
|
216
232
|
height?: number;
|
|
217
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Hero notice configuration.
|
|
236
|
+
*/
|
|
237
|
+
interface HeroNotice {
|
|
238
|
+
/** Notice title */
|
|
239
|
+
title?: string;
|
|
240
|
+
/** Notice paragraphs */
|
|
241
|
+
body?: string[];
|
|
242
|
+
}
|
|
218
243
|
/**
|
|
219
244
|
* Hero section configuration for entry page.
|
|
220
245
|
*/
|
|
@@ -225,6 +250,8 @@ interface HeroConfig {
|
|
|
225
250
|
text?: string;
|
|
226
251
|
/** Tagline (smaller, muted) */
|
|
227
252
|
tagline?: string;
|
|
253
|
+
/** Notice shown near the top of the hero */
|
|
254
|
+
notice?: HeroNotice;
|
|
228
255
|
/** Hero image */
|
|
229
256
|
image?: HeroImage;
|
|
230
257
|
/** Action buttons */
|
|
@@ -381,13 +408,25 @@ interface OxContentOptions {
|
|
|
381
408
|
* Syntax highlighting theme.
|
|
382
409
|
* @default 'github-dark'
|
|
383
410
|
*/
|
|
384
|
-
highlightTheme?: string;
|
|
411
|
+
highlightTheme?: string | ThemeRegistration$1;
|
|
385
412
|
/**
|
|
386
413
|
* Additional languages for syntax highlighting.
|
|
387
414
|
* Accepts Shiki LanguageRegistration objects (e.g., TextMate grammars).
|
|
388
415
|
* These are loaded alongside the built-in languages.
|
|
389
416
|
*/
|
|
390
417
|
highlightLangs?: LanguageRegistration$1[];
|
|
418
|
+
/**
|
|
419
|
+
* Opt-in code block annotations for fenced code blocks.
|
|
420
|
+
*
|
|
421
|
+
* Supports the configurable attribute syntax by default, and can also opt
|
|
422
|
+
* into VitePress-compatible fence metadata and inline notation.
|
|
423
|
+
*
|
|
424
|
+
* Example:
|
|
425
|
+
* ` ```ts annotate="highlight:1,3-4;warning:6;error:7" `
|
|
426
|
+
*
|
|
427
|
+
* @default false
|
|
428
|
+
*/
|
|
429
|
+
codeAnnotations?: boolean | CodeAnnotationsOptions;
|
|
391
430
|
/**
|
|
392
431
|
* Enable mermaid diagram rendering.
|
|
393
432
|
* @default false
|
|
@@ -460,8 +499,9 @@ interface ResolvedOptions {
|
|
|
460
499
|
taskLists: boolean;
|
|
461
500
|
strikethrough: boolean;
|
|
462
501
|
highlight: boolean;
|
|
463
|
-
highlightTheme: string;
|
|
502
|
+
highlightTheme: string | ThemeRegistration$1;
|
|
464
503
|
highlightLangs: LanguageRegistration$1[];
|
|
504
|
+
codeAnnotations: ResolvedCodeAnnotationsOptions;
|
|
465
505
|
mermaid: boolean;
|
|
466
506
|
frontmatter: boolean;
|
|
467
507
|
toc: boolean;
|
|
@@ -474,6 +514,55 @@ interface ResolvedOptions {
|
|
|
474
514
|
ogViewer: boolean;
|
|
475
515
|
i18n: ResolvedI18nOptions | false;
|
|
476
516
|
}
|
|
517
|
+
/**
|
|
518
|
+
* Supported line annotation kinds for code blocks.
|
|
519
|
+
*/
|
|
520
|
+
type CodeAnnotationKind = "highlight" | "warning" | "error";
|
|
521
|
+
/**
|
|
522
|
+
* Supported code annotation syntaxes.
|
|
523
|
+
*/
|
|
524
|
+
type CodeAnnotationSyntax = "attribute" | "vitepress" | "both";
|
|
525
|
+
/**
|
|
526
|
+
* Opt-in code annotation configuration.
|
|
527
|
+
*/
|
|
528
|
+
interface CodeAnnotationsOptions {
|
|
529
|
+
/**
|
|
530
|
+
* Annotation syntax to enable.
|
|
531
|
+
*
|
|
532
|
+
* - `attribute`: custom attribute syntax like `annotate="highlight:1,3-4"`
|
|
533
|
+
* - `vitepress`: VitePress-compatible syntax like `{1,3-4}` and `[!code warning]`
|
|
534
|
+
* - `both`: enables both syntaxes
|
|
535
|
+
*
|
|
536
|
+
* @default "attribute"
|
|
537
|
+
*/
|
|
538
|
+
notation?: CodeAnnotationSyntax;
|
|
539
|
+
/**
|
|
540
|
+
* Attribute name read from the code fence meta string.
|
|
541
|
+
*
|
|
542
|
+
* Example: `annotate="highlight:1,3-4;warning:6"`
|
|
543
|
+
*
|
|
544
|
+
* @default "annotate"
|
|
545
|
+
*/
|
|
546
|
+
metaKey?: string;
|
|
547
|
+
/**
|
|
548
|
+
* Enable line numbers for all code blocks by default.
|
|
549
|
+
*
|
|
550
|
+
* In `vitepress` or `both` mode, fenced code blocks can override this with
|
|
551
|
+
* `:line-numbers`, `:line-numbers=<start>`, or `:no-line-numbers`.
|
|
552
|
+
*
|
|
553
|
+
* @default false
|
|
554
|
+
*/
|
|
555
|
+
defaultLineNumbers?: boolean;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Resolved code annotation configuration.
|
|
559
|
+
*/
|
|
560
|
+
interface ResolvedCodeAnnotationsOptions {
|
|
561
|
+
enabled: boolean;
|
|
562
|
+
notation: CodeAnnotationSyntax;
|
|
563
|
+
metaKey: string;
|
|
564
|
+
defaultLineNumbers: boolean;
|
|
565
|
+
}
|
|
477
566
|
/**
|
|
478
567
|
* OG image generation options.
|
|
479
568
|
* Uses Chromium-based rendering with customizable templates.
|
|
@@ -704,6 +793,7 @@ interface DocEntry {
|
|
|
704
793
|
private?: boolean;
|
|
705
794
|
file: string;
|
|
706
795
|
line: number;
|
|
796
|
+
endLine: number;
|
|
707
797
|
signature?: string;
|
|
708
798
|
}
|
|
709
799
|
/**
|
|
@@ -731,9 +821,13 @@ interface ExtractedDocs {
|
|
|
731
821
|
entries: DocEntry[];
|
|
732
822
|
}
|
|
733
823
|
/**
|
|
734
|
-
*
|
|
824
|
+
* Machine-readable payload emitted alongside generated docs.
|
|
735
825
|
*/
|
|
736
|
-
|
|
826
|
+
interface GeneratedDocsData {
|
|
827
|
+
version: 1;
|
|
828
|
+
generatedAt: string;
|
|
829
|
+
modules: ExtractedDocs[];
|
|
830
|
+
}
|
|
737
831
|
/**
|
|
738
832
|
* Options for full-text search.
|
|
739
833
|
*/
|
|
@@ -795,6 +889,14 @@ interface SearchResult {
|
|
|
795
889
|
score: number;
|
|
796
890
|
matches: string[];
|
|
797
891
|
snippet: string;
|
|
892
|
+
scopes?: string[];
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* Parsed search query with optional scope prefixes.
|
|
896
|
+
*/
|
|
897
|
+
interface ScopedSearchQuery {
|
|
898
|
+
text: string;
|
|
899
|
+
scopes: string[];
|
|
798
900
|
}
|
|
799
901
|
/**
|
|
800
902
|
* Locale configuration.
|
|
@@ -860,7 +962,6 @@ interface ResolvedI18nOptions {
|
|
|
860
962
|
check: boolean;
|
|
861
963
|
functionNames: string[];
|
|
862
964
|
}
|
|
863
|
-
//# sourceMappingURL=types.d.ts.map
|
|
864
965
|
//#endregion
|
|
865
966
|
//#region src/environment.d.ts
|
|
866
967
|
/**
|
|
@@ -885,13 +986,6 @@ interface ResolvedI18nOptions {
|
|
|
885
986
|
* ```
|
|
886
987
|
*/
|
|
887
988
|
declare function createMarkdownEnvironment(options: ResolvedOptions): EnvironmentOptions;
|
|
888
|
-
/**
|
|
889
|
-
* Environment-specific module transformer.
|
|
890
|
-
*
|
|
891
|
-
* This is called during the transform phase to process
|
|
892
|
-
* Markdown files within the environment context.
|
|
893
|
-
*/
|
|
894
|
-
|
|
895
989
|
//#endregion
|
|
896
990
|
//#region src/transform.d.ts
|
|
897
991
|
/**
|
|
@@ -987,11 +1081,6 @@ interface SsgTransformOptions {
|
|
|
987
1081
|
sourcePath?: string;
|
|
988
1082
|
}
|
|
989
1083
|
declare function transformMarkdown(source: string, filePath: string, options: ResolvedOptions, ssgOptions?: SsgTransformOptions): Promise<TransformResult>;
|
|
990
|
-
/**
|
|
991
|
-
* Extracts imports from Markdown content.
|
|
992
|
-
*
|
|
993
|
-
* Supports importing components for interactive islands.
|
|
994
|
-
*/
|
|
995
1084
|
//#endregion
|
|
996
1085
|
//#region src/docs.d.ts
|
|
997
1086
|
/**
|
|
@@ -1069,25 +1158,16 @@ declare function generateMarkdown(docs: ExtractedDocs[], options: ResolvedDocsOp
|
|
|
1069
1158
|
*/
|
|
1070
1159
|
declare function writeDocs(docs: Record<string, string>, outDir: string, extractedDocs?: ExtractedDocs[], options?: ResolvedDocsOptions): Promise<void>;
|
|
1071
1160
|
declare function resolveDocsOptions(options: DocsOptions | false | undefined): ResolvedDocsOptions | false;
|
|
1072
|
-
//# sourceMappingURL=docs.d.ts.map
|
|
1073
1161
|
//#endregion
|
|
1074
1162
|
//#region src/ssg.d.ts
|
|
1075
1163
|
/**
|
|
1076
1164
|
* Default HTML template for SSG pages with navigation.
|
|
1077
1165
|
*/
|
|
1078
|
-
declare const DEFAULT_HTML_TEMPLATE = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>{{title}}{{#siteName}} - {{siteName}}{{/siteName}}</title>\n {{#description}}<meta name=\"description\" content=\"{{description}}\">{{/description}}\n <!-- Open Graph -->\n <meta property=\"og:type\" content=\"website\">\n <meta property=\"og:title\" content=\"{{title}}{{#siteName}} - {{siteName}}{{/siteName}}\">\n {{#description}}<meta property=\"og:description\" content=\"{{description}}\">{{/description}}\n {{#ogImage}}<meta property=\"og:image\" content=\"{{ogImage}}\">{{/ogImage}}\n <!-- Twitter Card -->\n {{#ogImage}}<meta name=\"twitter:card\" content=\"summary_large_image\">{{/ogImage}}\n {{^ogImage}}<meta name=\"twitter:card\" content=\"summary\">{{/ogImage}}\n <meta name=\"twitter:title\" content=\"{{title}}{{#siteName}} - {{siteName}}{{/siteName}}\">\n {{#description}}<meta name=\"twitter:description\" content=\"{{description}}\">{{/description}}\n {{#ogImage}}<meta name=\"twitter:image\" content=\"{{ogImage}}\">{{/ogImage}}\n <style>\n :root {\n --sidebar-width: 260px;\n --header-height: 60px;\n --max-content-width: 960px;\n --font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --font-mono: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;\n --color-bg: #ffffff;\n --color-bg-alt: #f8f9fa;\n --color-text: #1a1a1a;\n --color-text-muted: #666666;\n --color-border: #e5e7eb;\n --color-primary: #b7410e;\n --color-primary-hover: #ce5937;\n --color-code-bg: #1e293b;\n --color-code-text: #e2e8f0;\n }\n [data-theme=\"dark\"] {\n --color-bg: #141414;\n --color-bg-alt: #141414;\n --color-text: #e5e5e5;\n --color-text-muted: #a3a3a3;\n --color-border: #2a2a2a;\n --color-primary: #c9714a;\n --color-primary-hover: #d4845f;\n --color-code-bg: #1a1a1a;\n --color-code-text: #e5e5e5;\n }\n @media (prefers-color-scheme: dark) {\n :root:not([data-theme=\"light\"]) {\n --color-bg: #141414;\n --color-bg-alt: #141414;\n --color-text: #e5e5e5;\n --color-text-muted: #a3a3a3;\n --color-border: #2a2a2a;\n --color-primary: #c9714a;\n --color-primary-hover: #d4845f;\n --color-code-bg: #1a1a1a;\n --color-code-text: #e5e5e5;\n }\n }\n * { box-sizing: border-box; margin: 0; padding: 0; }\n html { scroll-behavior: smooth; }\n body {\n font-family: var(--font-sans);\n line-height: 1.7;\n color: var(--color-text);\n background: var(--color-bg);\n }\n a { color: var(--color-primary); text-decoration: none; }\n a:hover { color: var(--color-primary-hover); text-decoration: underline; }\n\n /* Header */\n .header {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: var(--header-height);\n background: var(--color-bg);\n border-bottom: 1px solid var(--color-border);\n display: flex;\n align-items: center;\n padding: 0 1.5rem;\n z-index: 100;\n }\n .header-title {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--color-text);\n }\n .header-title:hover { text-decoration: none; }\n .menu-toggle {\n display: none;\n background: none;\n border: none;\n cursor: pointer;\n padding: 0.5rem;\n margin-right: 0.75rem;\n }\n .menu-toggle svg { display: block; }\n .menu-toggle path { stroke: var(--color-text); }\n .header-actions { margin-left: auto; display: flex; align-items: center; gap: 0.5rem; }\n .search-button {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n background: var(--color-bg-alt);\n border: 1px solid var(--color-border);\n border-radius: 6px;\n color: var(--color-text-muted);\n cursor: pointer;\n font-size: 0.875rem;\n transition: border-color 0.15s, color 0.15s;\n }\n .search-button:hover { border-color: var(--color-primary); color: var(--color-text); }\n .search-button svg { width: 16px; height: 16px; }\n .search-button kbd {\n padding: 0.125rem 0.375rem;\n background: var(--color-bg);\n border: 1px solid var(--color-border);\n border-radius: 4px;\n font-family: var(--font-mono);\n font-size: 0.75rem;\n }\n @media (max-width: 640px) {\n .search-button span, .search-button kbd { display: none; }\n .search-button { padding: 0.5rem; }\n }\n .search-modal-overlay {\n display: none;\n position: fixed;\n inset: 0;\n z-index: 200;\n background: rgba(0,0,0,0.6);\n backdrop-filter: blur(4px);\n justify-content: center;\n padding-top: 10vh;\n }\n .search-modal-overlay.open { display: flex; }\n .search-modal {\n width: 100%;\n max-width: 560px;\n margin: 0 1rem;\n background: var(--color-bg);\n border: 1px solid var(--color-border);\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 25px 50px -12px rgba(0,0,0,0.4);\n max-height: 70vh;\n display: flex;\n flex-direction: column;\n }\n .search-header {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 1rem;\n border-bottom: 1px solid var(--color-border);\n }\n .search-header svg { flex-shrink: 0; color: var(--color-text-muted); }\n .search-input {\n flex: 1;\n background: none;\n border: none;\n outline: none;\n font-size: 1rem;\n color: var(--color-text);\n }\n .search-input::placeholder { color: var(--color-text-muted); }\n .search-close {\n padding: 0.25rem 0.5rem;\n background: var(--color-bg-alt);\n border: 1px solid var(--color-border);\n border-radius: 4px;\n color: var(--color-text-muted);\n font-family: var(--font-mono);\n font-size: 0.75rem;\n cursor: pointer;\n }\n .search-results {\n flex: 1;\n overflow-y: auto;\n padding: 0.5rem;\n }\n .search-result {\n display: block;\n padding: 0.75rem 1rem;\n border-radius: 8px;\n color: var(--color-text);\n text-decoration: none;\n }\n .search-result:hover, .search-result.selected { background: var(--color-bg-alt); text-decoration: none; }\n .search-result-title { font-weight: 600; font-size: 0.875rem; margin-bottom: 0.25rem; }\n .search-result-snippet { font-size: 0.8125rem; color: var(--color-text-muted); }\n .search-empty { padding: 2rem 1rem; text-align: center; color: var(--color-text-muted); }\n .search-footer {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 1rem;\n padding: 0.75rem 1rem;\n border-top: 1px solid var(--color-border);\n background: var(--color-bg-alt);\n font-size: 0.75rem;\n color: var(--color-text-muted);\n }\n .search-footer kbd {\n padding: 0.125rem 0.375rem;\n background: var(--color-bg);\n border: 1px solid var(--color-border);\n border-radius: 4px;\n font-family: var(--font-mono);\n }\n .theme-toggle {\n background: none;\n border: none;\n cursor: pointer;\n padding: 0.5rem;\n border-radius: 6px;\n color: var(--color-text-muted);\n transition: background 0.15s, color 0.15s;\n }\n .theme-toggle:hover { background: var(--color-bg-alt); color: var(--color-text); }\n .theme-toggle svg { display: block; width: 20px; height: 20px; }\n .theme-toggle .icon-sun { display: none; }\n .theme-toggle .icon-moon { display: block; }\n [data-theme=\"dark\"] .theme-toggle .icon-sun { display: block; }\n [data-theme=\"dark\"] .theme-toggle .icon-moon { display: none; }\n @media (prefers-color-scheme: dark) {\n :root:not([data-theme=\"light\"]) .theme-toggle .icon-sun { display: block; }\n :root:not([data-theme=\"light\"]) .theme-toggle .icon-moon { display: none; }\n }\n\n /* Layout */\n .layout {\n display: flex;\n padding-top: var(--header-height);\n min-height: 100vh;\n }\n\n /* Sidebar */\n .sidebar {\n position: fixed;\n top: var(--header-height);\n left: 0;\n bottom: 0;\n width: var(--sidebar-width);\n background: var(--color-bg-alt);\n border-right: 1px solid var(--color-border);\n overflow-y: auto;\n padding: 1.5rem 1rem;\n }\n .nav-section { margin-bottom: 1.5rem; }\n .nav-title {\n font-size: 0.75rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--color-text-muted);\n margin-bottom: 0.5rem;\n padding: 0 0.75rem;\n }\n .nav-list { list-style: none; }\n .nav-item { margin: 0.125rem 0; }\n .nav-link {\n display: block;\n padding: 0.5rem 0.75rem;\n border-radius: 6px;\n color: var(--color-text);\n font-size: 0.875rem;\n transition: background 0.15s;\n }\n .nav-link:hover {\n background: var(--color-border);\n text-decoration: none;\n }\n .nav-link.active {\n background: var(--color-primary);\n color: white;\n }\n\n /* Main content */\n .main {\n flex: 1;\n margin-left: var(--sidebar-width);\n padding: 2rem;\n min-width: 0;\n overflow-x: hidden;\n }\n .content {\n max-width: var(--max-content-width);\n margin: 0 auto;\n overflow-wrap: break-word;\n word-wrap: break-word;\n word-break: break-word;\n }\n\n /* TOC (right sidebar) */\n .toc {\n position: fixed;\n top: calc(var(--header-height) + 2rem);\n right: 2rem;\n width: 200px;\n font-size: 0.8125rem;\n }\n .toc-title {\n font-weight: 600;\n margin-bottom: 0.75rem;\n color: var(--color-text-muted);\n }\n .toc-list { list-style: none; }\n .toc-item { margin: 0.375rem 0; }\n .toc-link {\n color: var(--color-text-muted);\n display: block;\n padding-left: calc((var(--depth, 1) - 1) * 0.75rem);\n }\n .toc-link:hover { color: var(--color-primary); }\n @media (max-width: 1200px) { .toc { display: none; } }\n\n /* Typography */\n .content h1 { font-size: 2.25rem; margin-bottom: 1rem; line-height: 1.2; }\n .content h2 { font-size: 1.5rem; margin-top: 2.5rem; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--color-border); }\n .content h3 { font-size: 1.25rem; margin-top: 2rem; margin-bottom: 0.75rem; }\n .content h4 { font-size: 1rem; margin-top: 1.5rem; margin-bottom: 0.5rem; }\n .content p { margin-bottom: 1rem; }\n .content ul, .content ol { margin: 1rem 0; padding-left: 1.5rem; }\n .content li { margin: 0.375rem 0; }\n .content blockquote {\n border-left: 4px solid var(--color-primary);\n padding: 0.5rem 1rem;\n margin: 1rem 0;\n background: var(--color-bg-alt);\n border-radius: 0 6px 6px 0;\n }\n .content code {\n font-family: var(--font-mono);\n font-size: 0.875em;\n background: var(--color-bg-alt);\n padding: 0.2em 0.4em;\n border-radius: 4px;\n word-break: break-all;\n }\n .content pre {\n background: var(--color-code-bg);\n color: var(--color-code-text);\n padding: 1rem 1.25rem;\n border-radius: 8px;\n overflow-x: auto;\n margin: 1.5rem 0;\n line-height: 1.5;\n }\n .content pre code {\n background: transparent;\n padding: 0;\n font-size: 0.8125rem;\n }\n .content table {\n width: 100%;\n border-collapse: collapse;\n margin: 1.5rem 0;\n font-size: 0.875rem;\n }\n .content th, .content td {\n border: 1px solid var(--color-border);\n padding: 0.75rem 1rem;\n text-align: left;\n }\n .content th { background: var(--color-bg-alt); font-weight: 600; }\n .content img { max-width: 100%; height: auto; border-radius: 8px; display: block; }\n .content img[alt*=\"Logo\"] { max-width: 200px; display: block; margin: 1rem 0; }\n .content img[alt*=\"Architecture\"] { max-width: 600px; }\n .content img[alt*=\"Benchmark\"] { max-width: 680px; }\n .content hr { border: none; border-top: 1px solid var(--color-border); margin: 2rem 0; }\n\n /* Responsive */\n @media (max-width: 768px) {\n .menu-toggle { display: block; }\n .sidebar {\n transform: translateX(-100%);\n transition: transform 0.3s ease;\n z-index: 99;\n width: 280px;\n }\n .sidebar.open { transform: translateX(0); }\n .main { margin-left: 0; padding: 1rem 0.75rem; }\n .content { padding: 0 0.25rem; }\n .content h1 { font-size: 1.5rem; line-height: 1.3; margin-bottom: 0.75rem; }\n .content h2 { font-size: 1.2rem; margin-top: 2rem; }\n .content h3 { font-size: 1.1rem; }\n .content p { font-size: 0.9375rem; margin-bottom: 0.875rem; }\n .content ul, .content ol { padding-left: 1.25rem; font-size: 0.9375rem; }\n .content pre {\n padding: 0.75rem;\n font-size: 0.75rem;\n margin: 1rem -0.75rem;\n border-radius: 0;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n .content code { font-size: 0.8125em; }\n .content table {\n display: block;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n font-size: 0.8125rem;\n margin: 1rem -0.75rem;\n width: calc(100% + 1.5rem);\n }\n .content th, .content td { padding: 0.5rem 0.75rem; white-space: nowrap; }\n .content img { margin: 1rem 0; }\n .content img[alt*=\"Logo\"] { max-width: 150px; }\n .content img[alt*=\"Architecture\"] { max-width: 100%; }\n .content img[alt*=\"Benchmark\"] { max-width: 100%; }\n .content blockquote { padding: 0.5rem 0.75rem; margin: 1rem 0; font-size: 0.9375rem; }\n .header { padding: 0 1rem; }\n .header-title { font-size: 1rem; }\n .header-title img { width: 24px; height: 24px; }\n .overlay {\n display: none;\n position: fixed;\n inset: 0;\n background: rgba(0,0,0,0.5);\n z-index: 98;\n }\n .overlay.open { display: block; }\n }\n\n /* Extra small devices */\n @media (max-width: 480px) {\n .main { padding: 0.75rem 0.5rem; }\n .content h1 { font-size: 1.35rem; }\n .content pre { font-size: 0.6875rem; padding: 0.625rem; }\n .content table { font-size: 0.75rem; }\n .content th, .content td { padding: 0.375rem 0.5rem; }\n }\n </style>\n</head>\n<body>\n <header class=\"header\">\n <button class=\"menu-toggle\" aria-label=\"Toggle menu\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\">\n <path d=\"M3 12h18M3 6h18M3 18h18\"/>\n </svg>\n </button>\n <a href=\"{{base}}index.html\" class=\"header-title\">\n <img src=\"{{base}}logo.svg\" alt=\"\" width=\"28\" height=\"28\" style=\"margin-right: 8px; vertical-align: middle;\" />\n {{siteName}}\n </a>\n <div class=\"header-actions\">\n <button class=\"search-button\" aria-label=\"Search\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3\"/>\n </svg>\n <span>Search</span>\n <kbd>/</kbd>\n </button>\n <button class=\"theme-toggle\" aria-label=\"Toggle theme\">\n <svg class=\"icon-sun\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"5\"/><path d=\"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42\"/>\n </svg>\n <svg class=\"icon-moon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\"/>\n </svg>\n </button>\n </div>\n </header>\n <div class=\"search-modal-overlay\">\n <div class=\"search-modal\">\n <div class=\"search-header\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3\"/>\n </svg>\n <input type=\"text\" class=\"search-input\" placeholder=\"Search documentation...\" />\n <button class=\"search-close\">Esc</button>\n </div>\n <div class=\"search-results\"></div>\n <div class=\"search-footer\">\n <span><kbd>\u2191</kbd><kbd>\u2193</kbd> to navigate</span>\n <span><kbd>Enter</kbd> to select</span>\n <span><kbd>Esc</kbd> to close</span>\n </div>\n </div>\n </div>\n <div class=\"overlay\"></div>\n <div class=\"layout\">\n <aside class=\"sidebar\">\n <nav>\n{{navigation}}\n </nav>\n </aside>\n <main class=\"main\">\n <article class=\"content\">\n{{content}}\n </article>\n </main>\n{{#hasToc}}\n <aside class=\"toc\">\n <div class=\"toc-title\">On this page</div>\n <ul class=\"toc-list\">\n{{toc}}\n </ul>\n </aside>\n{{/hasToc}}\n </div>\n <script>\n // Menu toggle\n const toggle = document.querySelector('.menu-toggle');\n const sidebar = document.querySelector('.sidebar');\n const overlay = document.querySelector('.overlay');\n if (toggle && sidebar && overlay) {\n const close = () => { sidebar.classList.remove('open'); overlay.classList.remove('open'); };\n toggle.addEventListener('click', () => {\n sidebar.classList.toggle('open');\n overlay.classList.toggle('open');\n });\n overlay.addEventListener('click', close);\n sidebar.querySelectorAll('a').forEach(a => a.addEventListener('click', close));\n }\n\n // Theme toggle\n const themeToggle = document.querySelector('.theme-toggle');\n const getPreferredTheme = () => {\n const stored = localStorage.getItem('theme');\n if (stored) return stored;\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n };\n const setTheme = (theme) => {\n document.documentElement.setAttribute('data-theme', theme);\n localStorage.setItem('theme', theme);\n };\n // Initialize theme\n setTheme(getPreferredTheme());\n if (themeToggle) {\n themeToggle.addEventListener('click', () => {\n const current = document.documentElement.getAttribute('data-theme') || getPreferredTheme();\n setTheme(current === 'dark' ? 'light' : 'dark');\n });\n }\n\n // Search functionality\n const searchButton = document.querySelector('.search-button');\n const searchOverlay = document.querySelector('.search-modal-overlay');\n const searchInput = document.querySelector('.search-input');\n const searchResults = document.querySelector('.search-results');\n const searchClose = document.querySelector('.search-close');\n let searchIndex = null;\n let selectedIndex = 0;\n let results = [];\n\n const openSearch = () => {\n searchOverlay.classList.add('open');\n searchInput.focus();\n };\n const closeSearch = () => {\n searchOverlay.classList.remove('open');\n searchInput.value = '';\n searchResults.innerHTML = '';\n selectedIndex = 0;\n results = [];\n };\n\n // Load search index\n const loadSearchIndex = async () => {\n if (searchIndex) return;\n try {\n const res = await fetch('{{base}}search-index.json');\n searchIndex = await res.json();\n } catch (e) {\n console.warn('Failed to load search index:', e);\n }\n };\n\n // Tokenize query\n const tokenize = (text) => {\n const tokens = [];\n let current = '';\n for (const char of text) {\n const isCjk = /[\\u4E00-\\u9FFF\\u3400-\\u4DBF\\u3040-\\u309F\\u30A0-\\u30FF\\uAC00-\\uD7AF]/.test(char);\n if (isCjk) {\n if (current) { tokens.push(current.toLowerCase()); current = ''; }\n tokens.push(char);\n } else if (/[a-zA-Z0-9_]/.test(char)) {\n current += char;\n } else if (current) {\n tokens.push(current.toLowerCase());\n current = '';\n }\n }\n if (current) tokens.push(current.toLowerCase());\n return tokens;\n };\n\n // Perform search\n const performSearch = async (query) => {\n if (!query.trim()) {\n searchResults.innerHTML = '';\n results = [];\n return;\n }\n await loadSearchIndex();\n if (!searchIndex) {\n searchResults.innerHTML = '<div class=\"search-empty\">Search index not available</div>';\n return;\n }\n\n const tokens = tokenize(query);\n if (!tokens.length) {\n searchResults.innerHTML = '';\n results = [];\n return;\n }\n\n const k1 = 1.2, b = 0.75;\n const docScores = new Map();\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n const isLast = i === tokens.length - 1;\n let matchingTerms = [];\n if (isLast && token.length >= 2) {\n matchingTerms = Object.keys(searchIndex.index).filter(t => t.startsWith(token));\n } else if (searchIndex.index[token]) {\n matchingTerms = [token];\n }\n\n for (const term of matchingTerms) {\n const postings = searchIndex.index[term] || [];\n const df = searchIndex.df[term] || 1;\n const idf = Math.log((searchIndex.doc_count - df + 0.5) / (df + 0.5) + 1.0);\n\n for (const posting of postings) {\n const doc = searchIndex.documents[posting.doc_idx];\n if (!doc) continue;\n const boost = posting.field === 'Title' ? 10 : posting.field === 'Heading' ? 5 : 1;\n const tf = posting.tf;\n const docLen = doc.body.length;\n const score = idf * ((tf * (k1 + 1)) / (tf + k1 * (1 - b + b * docLen / searchIndex.avg_dl))) * boost;\n\n if (!docScores.has(posting.doc_idx)) {\n docScores.set(posting.doc_idx, { score: 0, matches: new Set() });\n }\n const entry = docScores.get(posting.doc_idx);\n entry.score += score;\n entry.matches.add(term);\n }\n }\n }\n\n results = Array.from(docScores.entries())\n .map(([docIdx, data]) => {\n const doc = searchIndex.documents[docIdx];\n let snippet = '';\n if (doc.body) {\n const bodyLower = doc.body.toLowerCase();\n let firstPos = -1;\n for (const match of data.matches) {\n const pos = bodyLower.indexOf(match);\n if (pos !== -1 && (firstPos === -1 || pos < firstPos)) firstPos = pos;\n }\n const start = Math.max(0, firstPos - 50);\n const end = Math.min(doc.body.length, start + 150);\n snippet = doc.body.slice(start, end);\n if (start > 0) snippet = '...' + snippet;\n if (end < doc.body.length) snippet += '...';\n }\n return { ...doc, score: data.score, snippet };\n })\n .sort((a, b) => b.score - a.score)\n .slice(0, 10);\n\n selectedIndex = 0;\n renderResults();\n };\n\n const renderResults = () => {\n if (!results.length) {\n searchResults.innerHTML = '<div class=\"search-empty\">No results found</div>';\n return;\n }\n searchResults.innerHTML = results.map((r, i) =>\n '<a href=\"' + r.url + '\" class=\"search-result' + (i === selectedIndex ? ' selected' : '') + '\">' +\n '<div class=\"search-result-title\">' + r.title + '</div>' +\n (r.snippet ? '<div class=\"search-result-snippet\">' + r.snippet + '</div>' : '') +\n '</a>'\n ).join('');\n };\n\n // Event listeners\n if (searchButton) searchButton.addEventListener('click', openSearch);\n if (searchClose) searchClose.addEventListener('click', closeSearch);\n if (searchOverlay) searchOverlay.addEventListener('click', (e) => { if (e.target === searchOverlay) closeSearch(); });\n\n let searchTimeout = null;\n if (searchInput) {\n searchInput.addEventListener('input', () => {\n if (searchTimeout) clearTimeout(searchTimeout);\n searchTimeout = setTimeout(() => performSearch(searchInput.value), 150);\n });\n searchInput.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') closeSearch();\n else if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (selectedIndex < results.length - 1) { selectedIndex++; renderResults(); }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (selectedIndex > 0) { selectedIndex--; renderResults(); }\n } else if (e.key === 'Enter' && results[selectedIndex]) {\n e.preventDefault();\n window.location.href = results[selectedIndex].url;\n }\n });\n }\n\n // Global keyboard shortcut (/ or Cmd+K)\n document.addEventListener('keydown', (e) => {\n if ((e.key === '/' && !(e.target instanceof HTMLInputElement)) ||\n ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k')) {\n e.preventDefault();\n openSearch();\n }\n });\n </script>\n</body>\n</html>";
|
|
1079
|
-
/**
|
|
1080
|
-
* Bare HTML template (no navigation, no styles).
|
|
1081
|
-
*/
|
|
1082
|
-
|
|
1166
|
+
declare const DEFAULT_HTML_TEMPLATE = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>{{title}}{{#siteName}} - {{siteName}}{{/siteName}}</title>\n {{#description}}<meta name=\"description\" content=\"{{description}}\">{{/description}}\n <!-- Open Graph -->\n <meta property=\"og:type\" content=\"website\">\n <meta property=\"og:title\" content=\"{{title}}{{#siteName}} - {{siteName}}{{/siteName}}\">\n {{#description}}<meta property=\"og:description\" content=\"{{description}}\">{{/description}}\n {{#ogImage}}<meta property=\"og:image\" content=\"{{ogImage}}\">{{/ogImage}}\n <!-- Twitter Card -->\n {{#ogImage}}<meta name=\"twitter:card\" content=\"summary_large_image\">{{/ogImage}}\n {{^ogImage}}<meta name=\"twitter:card\" content=\"summary\">{{/ogImage}}\n <meta name=\"twitter:title\" content=\"{{title}}{{#siteName}} - {{siteName}}{{/siteName}}\">\n {{#description}}<meta name=\"twitter:description\" content=\"{{description}}\">{{/description}}\n {{#ogImage}}<meta name=\"twitter:image\" content=\"{{ogImage}}\">{{/ogImage}}\n <style>\n :root {\n --sidebar-width: 260px;\n --header-height: 60px;\n --max-content-width: 960px;\n --font-sans: 'IBM Plex Sans', 'Avenir Next', 'Segoe UI Variable', 'Segoe UI', sans-serif;\n --font-mono: 'IBM Plex Mono', 'SFMono-Regular', Consolas, monospace;\n --color-bg: #ffffff;\n --color-bg-alt: #f5f7fb;\n --color-text: #131a30;\n --color-text-muted: #4f607b;\n --color-border: #d2dbea;\n --color-primary: #4f6fae;\n --color-primary-hover: #425f96;\n --color-code-bg: #101a31;\n --color-code-bg-top: #18264a;\n --color-code-text: #edf3ff;\n --color-code-line-highlight: rgba(56, 189, 248, 0.16);\n --color-code-line-warning: rgba(245, 158, 11, 0.18);\n --color-code-line-warning-border: #f59e0b;\n --color-code-line-error: rgba(239, 68, 68, 0.18);\n --color-code-line-error-border: #ef4444;\n --color-code-frame-border: rgba(147, 166, 200, 0.46);\n --surface-noise-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 180'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.2' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23noise)' opacity='0.062'/%3E%3C/svg%3E\");\n --surface-noise-size: 164px 164px;\n }\n [data-theme=\"dark\"] {\n --color-bg: #060816;\n --color-bg-alt: #0d1528;\n --color-text: #ebf2ff;\n --color-text-muted: #8ea0bf;\n --color-border: #223252;\n --color-primary: #86a4da;\n --color-primary-hover: #a3bbe8;\n --color-code-bg: #0a1020;\n --color-code-bg-top: #0a1020;\n --color-code-text: #e7f0ff;\n --color-code-line-highlight: rgba(14, 165, 233, 0.2);\n --color-code-line-warning: rgba(245, 158, 11, 0.2);\n --color-code-line-warning-border: #f59e0b;\n --color-code-line-error: rgba(239, 68, 68, 0.22);\n --color-code-line-error-border: #f87171;\n --color-code-frame-border: rgba(34, 50, 82, 0.92);\n --surface-noise-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 180'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.25' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23noise)' opacity='0.098'/%3E%3C/svg%3E\");\n }\n @media (prefers-color-scheme: dark) {\n :root:not([data-theme=\"light\"]) {\n --color-bg: #060816;\n --color-bg-alt: #0d1528;\n --color-text: #ebf2ff;\n --color-text-muted: #8ea0bf;\n --color-border: #223252;\n --color-primary: #86a4da;\n --color-primary-hover: #a3bbe8;\n --color-code-bg: #0a1020;\n --color-code-bg-top: #0a1020;\n --color-code-text: #e7f0ff;\n --color-code-line-highlight: rgba(14, 165, 233, 0.2);\n --color-code-line-warning: rgba(245, 158, 11, 0.2);\n --color-code-line-warning-border: #f59e0b;\n --color-code-line-error: rgba(239, 68, 68, 0.22);\n --color-code-line-error-border: #f87171;\n --color-code-frame-border: rgba(34, 50, 82, 0.92);\n --surface-noise-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 180'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.25' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23noise)' opacity='0.098'/%3E%3C/svg%3E\");\n }\n }\n * { box-sizing: border-box; margin: 0; padding: 0; }\n html { scroll-behavior: smooth; }\n body {\n font-family: var(--font-sans);\n line-height: 1.7;\n color: var(--color-text);\n background: var(--color-bg);\n background-image: var(--surface-noise-image);\n background-size: var(--surface-noise-size);\n background-repeat: repeat;\n background-blend-mode: soft-light;\n }\n a { color: var(--color-primary); text-decoration: none; }\n a:hover { color: var(--color-primary-hover); text-decoration: underline; }\n\n /* Header */\n .header {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: var(--header-height);\n background: var(--color-bg);\n border-bottom: 1px solid var(--color-border);\n display: flex;\n align-items: center;\n padding: 0 1.5rem;\n z-index: 100;\n }\n .header,\n .sidebar,\n .search-modal,\n .mobile-footer,\n .content .ox-api-entry,\n .content .ox-api-module,\n .content blockquote.ox-callout {\n background-image: var(--surface-noise-image);\n background-size: var(--surface-noise-size);\n background-repeat: repeat;\n background-blend-mode: soft-light;\n }\n .header-title {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--color-text);\n }\n .header-title:hover { text-decoration: none; }\n .menu-toggle {\n display: none;\n background: none;\n border: none;\n cursor: pointer;\n padding: 0.5rem;\n margin-right: 0.75rem;\n }\n .menu-toggle svg { display: block; }\n .menu-toggle path { stroke: var(--color-text); }\n .header-actions { margin-left: auto; display: flex; align-items: center; gap: 0.5rem; }\n .search-button {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 0.75rem;\n background: var(--color-bg-alt);\n border: 1px solid var(--color-border);\n border-radius: 4px;\n color: var(--color-text-muted);\n cursor: pointer;\n font-size: 0.875rem;\n transition: border-color 0.15s, color 0.15s;\n }\n .search-button:hover { border-color: var(--color-primary); color: var(--color-text); }\n .search-button svg { width: 16px; height: 16px; }\n .search-button kbd {\n padding: 0.125rem 0.375rem;\n background: var(--color-bg);\n border: 1px solid var(--color-border);\n border-radius: 4px;\n font-family: var(--font-mono);\n font-size: 0.75rem;\n }\n @media (max-width: 640px) {\n .search-button span, .search-button kbd { display: none; }\n .search-button { padding: 0.5rem; }\n }\n .search-modal-overlay {\n display: none;\n position: fixed;\n inset: 0;\n z-index: 200;\n background: rgba(0,0,0,0.6);\n justify-content: center;\n padding-top: 10vh;\n }\n .search-modal-overlay.open { display: flex; }\n .search-modal {\n width: 100%;\n max-width: 560px;\n margin: 0 1rem;\n background: var(--color-bg);\n border: 1px solid var(--color-border);\n border-radius: 4px;\n overflow: hidden;\n max-height: 70vh;\n display: flex;\n flex-direction: column;\n }\n .search-header {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 1rem;\n border-bottom: 1px solid var(--color-border);\n }\n .search-header svg { flex-shrink: 0; color: var(--color-text-muted); }\n .search-input {\n flex: 1;\n background: none;\n border: none;\n outline: none;\n font-size: 1rem;\n color: var(--color-text);\n }\n .search-input::placeholder { color: var(--color-text-muted); }\n .search-close {\n padding: 0.25rem 0.5rem;\n background: var(--color-bg-alt);\n border: 1px solid var(--color-border);\n border-radius: 4px;\n color: var(--color-text-muted);\n font-family: var(--font-mono);\n font-size: 0.75rem;\n cursor: pointer;\n }\n .search-results {\n flex: 1;\n overflow-y: auto;\n padding: 0.5rem;\n }\n .search-result {\n display: block;\n padding: 0.75rem 1rem;\n border-radius: 4px;\n color: var(--color-text);\n text-decoration: none;\n }\n .search-result:hover, .search-result.selected { background: var(--color-bg-alt); text-decoration: none; }\n .search-result-title { font-weight: 600; font-size: 0.875rem; margin-bottom: 0.25rem; }\n .search-result-snippet { font-size: 0.8125rem; color: var(--color-text-muted); }\n .search-empty { padding: 2rem 1rem; text-align: center; color: var(--color-text-muted); }\n .search-footer {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 1rem;\n padding: 0.75rem 1rem;\n border-top: 1px solid var(--color-border);\n background: var(--color-bg-alt);\n font-size: 0.75rem;\n color: var(--color-text-muted);\n }\n .search-footer kbd {\n padding: 0.125rem 0.375rem;\n background: var(--color-bg);\n border: 1px solid var(--color-border);\n border-radius: 4px;\n font-family: var(--font-mono);\n }\n .theme-toggle {\n background: none;\n border: none;\n cursor: pointer;\n padding: 0.5rem;\n border-radius: 4px;\n color: var(--color-text-muted);\n transition: background 0.15s, color 0.15s;\n }\n .theme-toggle:hover { background: var(--color-bg-alt); color: var(--color-text); }\n .theme-toggle svg { display: block; width: 20px; height: 20px; }\n .theme-toggle .icon-sun { display: none; }\n .theme-toggle .icon-moon { display: block; }\n [data-theme=\"dark\"] .theme-toggle .icon-sun { display: block; }\n [data-theme=\"dark\"] .theme-toggle .icon-moon { display: none; }\n @media (prefers-color-scheme: dark) {\n :root:not([data-theme=\"light\"]) .theme-toggle .icon-sun { display: block; }\n :root:not([data-theme=\"light\"]) .theme-toggle .icon-moon { display: none; }\n }\n\n /* Layout */\n .layout {\n display: flex;\n padding-top: var(--header-height);\n min-height: 100vh;\n }\n\n /* Sidebar */\n .sidebar {\n position: fixed;\n top: var(--header-height);\n left: 0;\n bottom: 0;\n width: var(--sidebar-width);\n background: color-mix(in srgb, var(--color-bg-alt) 16%, var(--color-bg));\n border-right: 1px solid color-mix(in srgb, var(--color-border) 48%, transparent);\n overflow-y: auto;\n padding: 1rem 0.875rem 1.5rem;\n }\n .sidebar--entry { display: none; }\n .sidebar nav {\n display: flex;\n flex-direction: column;\n gap: 1rem;\n }\n .nav-section { margin-bottom: 0; }\n .nav-title {\n font-size: 0.6875rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--color-text-muted);\n margin-bottom: 0.4rem;\n padding: 0 0.625rem;\n }\n .nav-list {\n list-style: none;\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n }\n .nav-item { margin: 0; }\n .nav-link {\n display: block;\n padding: 0.45rem 0.625rem;\n border-radius: 0;\n color: color-mix(in srgb, var(--color-text) 92%, var(--color-text-muted));\n font-size: 0.875rem;\n }\n .nav-link:hover {\n background: color-mix(in srgb, var(--color-bg-alt) 58%, transparent);\n color: var(--color-text);\n text-decoration: none;\n }\n .nav-link.active {\n background: color-mix(in srgb, var(--color-bg-alt) 72%, transparent);\n color: var(--color-text);\n font-weight: 600;\n }\n\n /* Main content */\n .main {\n flex: 1;\n margin-left: var(--sidebar-width);\n padding: 2rem;\n min-width: 0;\n overflow-x: hidden;\n }\n .content {\n max-width: var(--max-content-width);\n margin: 0 auto;\n overflow-wrap: break-word;\n word-wrap: break-word;\n word-break: break-word;\n }\n\n /* TOC (right sidebar) */\n .toc {\n position: fixed;\n top: calc(var(--header-height) + 2rem);\n right: 2rem;\n width: 200px;\n font-size: 0.8125rem;\n }\n .toc-title {\n font-weight: 600;\n margin-bottom: 0.75rem;\n color: var(--color-text-muted);\n }\n .toc-list { list-style: none; }\n .toc-item { margin: 0.375rem 0; }\n .toc-link {\n color: var(--color-text-muted);\n display: block;\n padding-left: calc((var(--depth, 1) - 1) * 0.75rem);\n }\n .toc-link:hover { color: var(--color-primary); }\n @media (max-width: 1200px) { .toc { display: none; } }\n\n /* Typography */\n .content h1 { font-size: 2.25rem; margin-bottom: 1rem; line-height: 1.2; }\n .content h2 { font-size: 1.5rem; margin-top: 2.5rem; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 1px solid var(--color-border); }\n .content h3 { font-size: 1.25rem; margin-top: 2rem; margin-bottom: 0.75rem; }\n .content h4 { font-size: 1rem; margin-top: 1.5rem; margin-bottom: 0.5rem; }\n .content p { margin-bottom: 1rem; }\n .content ul, .content ol { margin: 1rem 0; padding-left: 1.5rem; }\n .content li { margin: 0.375rem 0; }\n .content blockquote {\n border-left: 4px solid var(--color-primary);\n padding: 0.5rem 1rem;\n margin: 1rem 0;\n background: var(--color-bg-alt);\n border-radius: 0 4px 4px 0;\n }\n .content blockquote.ox-callout {\n --callout-accent: var(--color-primary);\n border-left-width: 3px;\n border-left-color: var(--callout-accent);\n padding: 0.9rem 1rem;\n border-radius: 4px;\n background: color-mix(in srgb, var(--color-bg-alt) 92%, var(--callout-accent) 8%);\n }\n .content blockquote.ox-callout.ox-callout--note,\n .content blockquote.ox-callout.ox-callout--important { --callout-accent: var(--color-primary); }\n .content blockquote.ox-callout.ox-callout--tip { --callout-accent: #0891b2; }\n .content blockquote.ox-callout.ox-callout--warning { --callout-accent: #d97706; }\n .content blockquote.ox-callout.ox-callout--caution { --callout-accent: #dc2626; }\n .content .ox-callout-title {\n margin: 0 0 0.5rem;\n font-size: 0.75rem;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--callout-accent, var(--color-primary));\n }\n .content blockquote.ox-callout > :last-child { margin-bottom: 0; }\n .content blockquote.ox-callout > :not(.ox-callout-title):first-of-type { margin-top: 0; }\n .content code {\n font-family: var(--font-mono);\n font-size: 0.875em;\n background: var(--color-bg-alt);\n padding: 0.2em 0.4em;\n border-radius: 4px;\n word-break: break-all;\n }\n .content pre {\n background: linear-gradient(\n 180deg,\n var(--color-code-bg-top) 0,\n var(--color-code-bg) 3.5rem\n ) !important;\n color: var(--color-code-text);\n padding: 1rem 1.25rem;\n border-radius: 4px;\n border: 1px solid var(--color-code-frame-border);\n overflow-x: auto;\n margin: 1.5rem 0;\n line-height: 1.5;\n }\n .content pre code {\n background: transparent;\n border: 0;\n padding: 0;\n border-radius: 0;\n font-size: 0.8125rem;\n word-break: normal;\n }\n .content pre.ox-code-block code {\n display: block;\n }\n .content pre.ox-code-block .line {\n display: block;\n margin: 0 -1.25rem;\n padding: 0 1.25rem;\n }\n .content pre.ox-code-block .ox-code-line--highlight {\n background: var(--color-code-line-highlight);\n }\n .content pre.ox-code-block .ox-code-line--warning {\n background: var(--color-code-line-warning);\n border-left: 3px solid var(--color-code-line-warning-border);\n }\n .content pre.ox-code-block .ox-code-line--error {\n background: var(--color-code-line-error);\n border-left: 3px solid var(--color-code-line-error-border);\n }\n .content table {\n width: 100%;\n border-collapse: collapse;\n margin: 1.5rem 0;\n font-size: 0.875rem;\n }\n .content th, .content td {\n border: 1px solid var(--color-border);\n padding: 0.75rem 1rem;\n text-align: left;\n }\n .content th { background: var(--color-bg-alt); font-weight: 600; }\n .content img { max-width: 100%; height: auto; border-radius: 4px; display: block; }\n .content img[alt*=\"Logo\"] { max-width: 200px; display: block; margin: 1rem 0; }\n .content img[alt*=\"Architecture\"] { max-width: 600px; }\n .content img[alt*=\"Benchmark\"] { max-width: 680px; }\n .content hr { border: none; border-top: 1px solid var(--color-border); margin: 2rem 0; }\n .content .ox-api-controls {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n gap: 0.5rem;\n margin: 0 0 1rem;\n }\n .content .ox-api-controls__button {\n appearance: none;\n border: 1px solid color-mix(in srgb, var(--color-border) 82%, transparent);\n background: color-mix(in srgb, var(--color-bg-alt) 82%, var(--color-bg));\n padding: 0.4rem 0.7rem;\n border-radius: 4px;\n color: color-mix(in srgb, var(--color-text) 82%, var(--color-text-muted));\n font-family: var(--font-mono);\n font-size: 0.78rem;\n font-weight: 600;\n line-height: 1.4;\n cursor: pointer;\n }\n .content .ox-api-controls__button:hover {\n color: var(--color-primary);\n border-color: color-mix(in srgb, var(--color-primary) 38%, var(--color-border));\n background: color-mix(in srgb, var(--color-bg-alt) 68%, var(--color-primary) 6%);\n }\n .content .ox-api-entry,\n .content .ox-api-module {\n margin: 0;\n border: 0;\n border-top: 1px solid color-mix(in srgb, var(--color-border) 74%, transparent);\n border-radius: 0;\n background: transparent;\n overflow: visible;\n }\n .content .ox-api-entry:last-child,\n .content .ox-api-module:last-child {\n border-bottom: 1px solid color-mix(in srgb, var(--color-border) 74%, transparent);\n }\n .content .ox-api-entry summary,\n .content .ox-api-module summary {\n list-style: none;\n cursor: pointer;\n padding: 1rem 0;\n position: relative;\n }\n .content .ox-api-entry summary::-webkit-details-marker,\n .content .ox-api-module summary::-webkit-details-marker { display: none; }\n .content .ox-api-entry summary {\n display: grid;\n grid-template-columns: var(--octc-api-kind-width, 6.5rem) minmax(0, 1fr) auto;\n align-items: start;\n gap: 0.95rem;\n }\n .content .ox-api-entry summary::after,\n .content .ox-api-module summary::after {\n content: \"+\";\n align-self: center;\n color: var(--color-text-muted);\n font-family: var(--font-mono);\n font-size: 0.95rem;\n font-weight: 600;\n line-height: 1;\n }\n .content .ox-api-entry[open] summary::after,\n .content .ox-api-module[open] summary::after {\n content: \"\u2212\";\n color: var(--color-primary);\n }\n .content .ox-api-entry[open] summary,\n .content .ox-api-module[open] summary {\n border-bottom: 1px solid color-mix(in srgb, var(--color-border) 72%, transparent);\n }\n .content .ox-api-entry__kind,\n .content .ox-api-module__kind {\n display: block;\n width: var(--octc-api-kind-width, 6.5rem);\n padding: 0.3rem 0 0;\n background: transparent;\n border: 0;\n font-family: var(--font-mono);\n font-size: 0.76rem;\n font-weight: 600;\n letter-spacing: 0.01em;\n text-align: left;\n white-space: nowrap;\n color: var(--color-text-muted);\n }\n .content .ox-api-module__count {\n display: inline-flex;\n align-items: center;\n padding: 0.2rem 0.48rem;\n border-radius: 4px;\n background: color-mix(in srgb, var(--color-bg-alt) 84%, var(--color-primary) 8%);\n border: 1px solid color-mix(in srgb, var(--color-border) 82%, transparent);\n color: var(--color-text-muted);\n font-family: var(--font-mono);\n font-size: 0.72rem;\n font-weight: 600;\n letter-spacing: 0.03em;\n white-space: nowrap;\n }\n .content .ox-api-entry__name {\n display: block;\n font-family: var(--font-mono);\n font-size: 0.95rem;\n font-weight: 600;\n line-height: 1.55;\n }\n .content .ox-api-entry__signature,\n .content .ox-api-module__signature {\n display: block;\n width: 100%;\n min-width: 0;\n font-family: var(--font-mono);\n font-size: 0.95rem;\n line-height: 1.55;\n white-space: nowrap;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n }\n .content .ox-api-entry__description {\n display: block;\n color: color-mix(in srgb, var(--color-text) 78%, var(--color-text-muted));\n font-size: 0.9rem;\n line-height: 1.6;\n max-width: 72ch;\n }\n .content .ox-api-entry__summary-main {\n min-width: 0;\n display: flex;\n flex-direction: column;\n gap: 0.55rem;\n }\n .content .ox-api-entry__name,\n .content .ox-api-entry__signature,\n .content .ox-api-module__name,\n .content .ox-api-module__signature {\n background: transparent;\n padding: 0;\n border-radius: 0;\n word-break: normal;\n }\n .content code.shiki-inline.ox-api-entry__signature--highlighted,\n .content code.shiki-inline.ox-api-module__signature--highlighted {\n display: block;\n width: 100%;\n max-width: 100%;\n background: linear-gradient(\n 180deg,\n var(--color-code-bg-top) 0,\n var(--color-code-bg) 2.75rem\n ) !important;\n border: 1px solid var(--color-code-frame-border) !important;\n padding: 0.55rem 0.7rem !important;\n border-radius: 4px !important;\n white-space: nowrap;\n overflow-x: auto;\n overflow-y: hidden;\n -webkit-overflow-scrolling: touch;\n }\n .content code.shiki-inline.ox-api-entry__signature--highlighted .line,\n .content code.shiki-inline.ox-api-module__signature--highlighted .line {\n display: block;\n width: max-content;\n min-width: 100%;\n }\n .content .ox-api-entry__body,\n .content .ox-api-module__body { padding: 0.7rem 0 1.9rem; }\n .content .ox-api-entry__body {\n margin-left: calc(var(--octc-api-kind-width, 6.5rem) + 0.95rem);\n margin-top: 0.7rem;\n padding: 1.45rem 1rem 2.1rem 1.1rem;\n border: 1px solid color-mix(in srgb, var(--color-border) 72%, transparent);\n border-radius: 4px;\n background: color-mix(in srgb, var(--color-bg-alt) 68%, transparent);\n }\n .content .ox-api-entry__body > :first-child { margin-top: 0; }\n .content .ox-api-entry__body > :last-child { margin-bottom: 0; }\n .content .ox-api-entry[open] summary {\n padding-bottom: 0.35rem;\n }\n .content .ox-api-entry__section {\n display: grid;\n grid-template-columns: 6.5rem minmax(0, 1fr);\n gap: 0.2rem 1.25rem;\n align-items: start;\n margin-top: 1rem;\n padding-top: 1rem;\n border-top: 1px solid color-mix(in srgb, var(--color-border) 72%, transparent);\n }\n .content .ox-api-entry__section h4 {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 0.25rem;\n font-family: var(--font-mono);\n font-size: 0.78rem;\n font-weight: 700;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n color: var(--color-text-muted);\n }\n .content .ox-api-entry__section > :not(h4) { min-width: 0; }\n .content .ox-api-entry__source {\n margin: 0 0 0.15rem;\n font-family: var(--font-mono);\n font-size: 0.78rem;\n color: var(--color-text-muted);\n }\n .content .ox-api-entry__source a {\n color: inherit;\n text-decoration-color: color-mix(in srgb, var(--color-text-muted) 38%, transparent);\n }\n .content .ox-api-entry__tags,\n .content .ox-api-module__list {\n list-style: none;\n padding-left: 0;\n margin: 0;\n }\n .content .ox-api-entry__tags {\n display: flex;\n flex-wrap: wrap;\n gap: 0.6rem;\n }\n .content .ox-api-entry__tags li {\n display: inline-flex;\n align-items: center;\n gap: 0.45rem;\n padding: 0.4rem 0.55rem;\n border: 1px solid color-mix(in srgb, var(--color-border) 80%, transparent);\n border-radius: 4px;\n background: color-mix(in srgb, var(--color-bg-alt) 72%, transparent);\n }\n .content .ox-api-module__list li {\n display: grid;\n grid-template-columns: var(--octc-api-kind-width, 6.5rem) minmax(0, 1fr);\n align-items: start;\n gap: 1rem;\n padding: 0.85rem 0;\n border-top: 1px solid color-mix(in srgb, var(--color-border) 70%, transparent);\n }\n .content .ox-api-module__list li:first-child { border-top: none; }\n .content .ox-api-entry__tag-name,\n .content .ox-api-module__title { font-weight: 700; }\n .content .ox-api-entry__tag-name {\n color: var(--color-primary);\n font-family: var(--font-mono);\n font-size: 0.74rem;\n }\n .content .ox-api-entry__tag-value {\n color: var(--color-text);\n font-size: 0.84rem;\n line-height: 1.45;\n }\n .content .ox-api-module summary {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto auto;\n align-items: center;\n gap: 0.9rem;\n }\n .content .ox-api-module__body { padding-top: 0.15rem; }\n .content .ox-api-module__item { min-width: 0; }\n .content .ox-api-module__link {\n display: block;\n text-decoration: none;\n }\n .content .ox-api-module__link:hover { text-decoration: none; }\n .content .ox-api-module__name,\n .content .ox-api-module__signature {\n display: block;\n font-family: var(--font-mono);\n font-size: 0.91rem;\n line-height: 1.55;\n color: var(--color-text);\n }\n .content .ox-api-module__summary {\n display: block;\n margin-top: 0.45rem;\n color: color-mix(in srgb, var(--color-text) 76%, var(--color-text-muted));\n font-size: 0.88rem;\n line-height: 1.55;\n }\n .content .ox-api-entry__section--examples pre {\n margin: 0;\n border: 1px solid var(--color-code-frame-border);\n border-radius: 4px;\n }\n .content .ox-api-entry__params {\n list-style: none;\n padding: 0;\n margin: 0;\n }\n .content .ox-api-entry__param {\n padding: 0.8rem 0;\n border-top: 1px solid color-mix(in srgb, var(--color-border) 70%, transparent);\n }\n .content .ox-api-entry__param:first-child {\n padding-top: 0;\n border-top: 0;\n }\n .content .ox-api-entry__param-heading {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 0.5rem;\n }\n .content .ox-api-entry__param-name,\n .content .ox-api-entry__return-type {\n font-family: var(--font-mono);\n font-size: 0.84rem;\n font-weight: 600;\n color: var(--color-text);\n background: color-mix(in srgb, var(--color-bg-alt) 84%, transparent);\n border: 1px solid color-mix(in srgb, var(--color-border) 82%, transparent);\n padding: 0.28rem 0.42rem;\n border-radius: 4px;\n }\n .content .ox-api-entry__param-type {\n font-family: var(--font-mono);\n font-size: 0.78rem;\n color: var(--color-code-text);\n background: color-mix(in srgb, var(--color-code-bg) 96%, #243556);\n border: 1px solid color-mix(in srgb, var(--color-code-bg) 82%, var(--color-border));\n padding: 0.26rem 0.42rem;\n border-radius: 4px;\n }\n .content .ox-api-entry__param-description,\n .content .ox-api-entry__return-description {\n margin: 0.55rem 0 0;\n font-size: 0.88rem;\n line-height: 1.6;\n color: color-mix(in srgb, var(--color-text) 78%, var(--color-text-muted));\n }\n .content .ox-api-entry__return { margin: 0; }\n\n /* Responsive */\n @media (max-width: 768px) {\n .menu-toggle { display: block; }\n .sidebar {\n transform: translateX(-100%);\n z-index: 99;\n width: 280px;\n }\n .sidebar--entry { display: block; }\n .sidebar.open { transform: translateX(0); }\n .main { margin-left: 0; padding: 1rem 0.75rem; }\n .content { padding: 0 0.25rem; }\n .content h1 { font-size: 1.5rem; line-height: 1.3; margin-bottom: 0.75rem; }\n .content h2 { font-size: 1.2rem; margin-top: 2rem; }\n .content h3 { font-size: 1.1rem; }\n .content p { font-size: 0.9375rem; margin-bottom: 0.875rem; }\n .content ul, .content ol { padding-left: 1.25rem; font-size: 0.9375rem; }\n .content pre {\n padding: 0.75rem;\n font-size: 0.75rem;\n margin: 1rem -0.75rem;\n border-radius: 0;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n }\n .content .ox-api-controls {\n justify-content: flex-start;\n gap: 0.75rem;\n }\n .content .ox-api-entry__body {\n margin-left: 0;\n margin-top: 0.55rem;\n padding: 1.2rem 0 1.7rem;\n border-left: 0;\n border-right: 0;\n border-bottom: 0;\n border-radius: 0;\n background: transparent;\n }\n .content .ox-api-entry__section {\n grid-template-columns: 1fr;\n gap: 0.5rem;\n }\n .content .ox-api-entry__tags li,\n .content .ox-api-module__list li,\n .content .ox-api-module summary {\n grid-template-columns: 1fr;\n }\n .content .ox-api-entry__signature { width: 100%; }\n .content pre.ox-code-block .line {\n margin: 0 -0.75rem;\n padding: 0 0.75rem;\n }\n .content code { font-size: 0.8125em; }\n .content table {\n display: block;\n width: max-content;\n min-width: 100%;\n max-width: calc(100vw - 1.5rem);\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n font-size: 0.8125rem;\n margin: 1rem 0;\n border-collapse: separate;\n border-spacing: 0;\n }\n .content th, .content td { padding: 0.5rem 0.75rem; white-space: nowrap; vertical-align: top; }\n .content img { margin: 1rem 0; }\n .content img[alt*=\"Logo\"] { max-width: 150px; }\n .content img[alt*=\"Architecture\"] { max-width: 100%; }\n .content img[alt*=\"Benchmark\"] { max-width: 100%; }\n .content blockquote { padding: 0.5rem 0.75rem; margin: 1rem 0; font-size: 0.9375rem; }\n .header { padding: 0 1rem; }\n .header-title { font-size: 1rem; }\n .header-title:not(.header-title--logo-only) img { width: 24px; height: 24px; }\n .header-title--logo-only .header-logo { width: 152px; height: auto; }\n .overlay {\n display: none;\n position: fixed;\n inset: 0;\n background: transparent;\n z-index: 98;\n }\n .overlay.open { display: block; }\n }\n\n /* Extra small devices */\n @media (max-width: 480px) {\n .main { padding: 0.75rem 0.5rem; }\n .content h1 { font-size: 1.35rem; }\n .content pre { font-size: 0.6875rem; padding: 0.625rem; }\n .content table { max-width: calc(100vw - 1rem); font-size: 0.75rem; }\n .content th, .content td { padding: 0.375rem 0.5rem; }\n }\n </style>\n</head>\n<body>\n <header class=\"header\">\n <button class=\"menu-toggle\" aria-label=\"Toggle menu\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke-width=\"2\" stroke-linecap=\"round\">\n <path d=\"M3 12h18M3 6h18M3 18h18\"/>\n </svg>\n </button>\n <a href=\"{{base}}index.html\" class=\"header-title\">\n <img src=\"{{base}}logo.svg\" alt=\"\" width=\"28\" height=\"28\" style=\"margin-right: 8px; vertical-align: middle;\" />\n {{siteName}}\n </a>\n <div class=\"header-actions\">\n <button class=\"search-button\" aria-label=\"Search\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3\"/>\n </svg>\n <span>Search</span>\n <kbd>/</kbd>\n </button>\n <button class=\"theme-toggle\" aria-label=\"Toggle theme\">\n <svg class=\"icon-sun\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"5\"/><path d=\"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42\"/>\n </svg>\n <svg class=\"icon-moon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <path d=\"M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z\"/>\n </svg>\n </button>\n </div>\n </header>\n <div class=\"search-modal-overlay\">\n <div class=\"search-modal\">\n <div class=\"search-header\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\">\n <circle cx=\"11\" cy=\"11\" r=\"8\"/><path d=\"m21 21-4.3-4.3\"/>\n </svg>\n <input type=\"text\" class=\"search-input\" placeholder=\"Search documentation...\" />\n <button class=\"search-close\">Esc</button>\n </div>\n <div class=\"search-results\"></div>\n <div class=\"search-footer\">\n <span><kbd>\u2191</kbd><kbd>\u2193</kbd> to navigate</span>\n <span><kbd>Enter</kbd> to select</span>\n <span><kbd>Esc</kbd> to close</span>\n </div>\n </div>\n </div>\n <div class=\"overlay\"></div>\n <div class=\"layout\">\n <aside class=\"sidebar{{#entryPage}} sidebar--entry{{/entryPage}}\">\n <nav>\n{{navigation}}\n </nav>\n </aside>\n <main class=\"main\">\n <article class=\"content\">\n{{content}}\n </article>\n </main>\n{{#hasToc}}\n <aside class=\"toc\">\n <div class=\"toc-title\">On this page</div>\n <ul class=\"toc-list\">\n{{toc}}\n </ul>\n </aside>\n{{/hasToc}}\n </div>\n <script>\n // Menu toggle\n const toggle = document.querySelector('.menu-toggle');\n const sidebar = document.querySelector('.sidebar');\n const overlay = document.querySelector('.overlay');\n if (toggle && sidebar && overlay) {\n const close = () => { sidebar.classList.remove('open'); overlay.classList.remove('open'); };\n toggle.addEventListener('click', () => {\n sidebar.classList.toggle('open');\n overlay.classList.toggle('open');\n });\n overlay.addEventListener('click', close);\n sidebar.querySelectorAll('a').forEach(a => a.addEventListener('click', close));\n }\n\n // Theme toggle\n const themeToggle = document.querySelector('.theme-toggle');\n const getPreferredTheme = () => {\n const stored = localStorage.getItem('theme');\n if (stored) return stored;\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n };\n const setTheme = (theme) => {\n document.documentElement.setAttribute('data-theme', theme);\n localStorage.setItem('theme', theme);\n };\n // Initialize theme\n setTheme(getPreferredTheme());\n if (themeToggle) {\n themeToggle.addEventListener('click', () => {\n const current = document.documentElement.getAttribute('data-theme') || getPreferredTheme();\n setTheme(current === 'dark' ? 'light' : 'dark');\n });\n }\n\n document.querySelectorAll('.ox-api-controls').forEach((controls) => {\n const targetSelector = controls.getAttribute('data-ox-api-target');\n if (!targetSelector) return;\n\n controls.querySelectorAll('[data-ox-api-toggle]').forEach((button) => {\n button.addEventListener('click', () => {\n const shouldOpen = button.getAttribute('data-ox-api-toggle') === 'expand';\n document.querySelectorAll(targetSelector).forEach((entry) => {\n if (entry instanceof HTMLDetailsElement) {\n entry.open = shouldOpen;\n }\n });\n });\n });\n });\n\n // Search functionality\n const searchButton = document.querySelector('.search-button');\n const searchOverlay = document.querySelector('.search-modal-overlay');\n const searchInput = document.querySelector('.search-input');\n const searchResults = document.querySelector('.search-results');\n const searchClose = document.querySelector('.search-close');\n let searchIndex = null;\n let selectedIndex = 0;\n let results = [];\n\n const openSearch = () => {\n searchOverlay.classList.add('open');\n searchInput.focus();\n };\n const closeSearch = () => {\n searchOverlay.classList.remove('open');\n searchInput.value = '';\n searchResults.innerHTML = '';\n selectedIndex = 0;\n results = [];\n };\n\n // Load search index\n const loadSearchIndex = async () => {\n if (searchIndex) return;\n try {\n const res = await fetch('{{base}}search-index.json');\n searchIndex = await res.json();\n } catch (e) {\n console.warn('Failed to load search index:', e);\n }\n };\n\n const parseScopedQuery = (query) => {\n const scopes = [];\n const terms = [];\n for (const part of query.trim().split(/\\s+/).filter(Boolean)) {\n if (part.startsWith('@') && part.length > 1) {\n scopes.push(part.slice(1).toLowerCase());\n } else {\n terms.push(part);\n }\n }\n return { text: terms.join(' ').trim(), scopes: [...new Set(scopes)] };\n };\n\n const getScopesForDoc = (doc) => {\n const source = (doc.id || doc.url || '').replace(/^\\/+/, '').toLowerCase();\n const segments = source.split('/').filter(Boolean);\n if (segments.length <= 1) return [];\n\n const scopes = [];\n let current = '';\n for (const segment of segments.slice(0, -1)) {\n current = current ? current + '/' + segment : segment;\n scopes.push(current);\n }\n return scopes;\n };\n\n const matchesScopes = (doc, scopes) => {\n if (!scopes.length) return true;\n const docScopes = new Set(getScopesForDoc(doc));\n return scopes.some((scope) => docScopes.has(scope));\n };\n\n // Tokenize query\n const tokenize = (text) => {\n const tokens = [];\n let current = '';\n for (const char of text) {\n const isCjk = /[\\u4E00-\\u9FFF\\u3400-\\u4DBF\\u3040-\\u309F\\u30A0-\\u30FF\\uAC00-\\uD7AF]/.test(char);\n if (isCjk) {\n if (current) { tokens.push(current.toLowerCase()); current = ''; }\n tokens.push(char);\n } else if (/[a-zA-Z0-9_]/.test(char)) {\n current += char;\n } else if (current) {\n tokens.push(current.toLowerCase());\n current = '';\n }\n }\n if (current) tokens.push(current.toLowerCase());\n return tokens;\n };\n\n // Perform search\n const performSearch = async (query) => {\n await loadSearchIndex();\n if (!searchIndex) {\n searchResults.innerHTML = '<div class=\"search-empty\">Search index not available</div>';\n return;\n }\n\n const parsedQuery = parseScopedQuery(query);\n if (!parsedQuery.text && parsedQuery.scopes.length === 0) {\n searchResults.innerHTML = '';\n results = [];\n return;\n }\n\n const tokens = tokenize(parsedQuery.text);\n const k1 = 1.2, b = 0.75;\n const docScores = new Map();\n\n if (!tokens.length) {\n searchIndex.documents.forEach((doc, docIdx) => {\n if (matchesScopes(doc, parsedQuery.scopes)) {\n docScores.set(docIdx, { score: 0, matches: new Set() });\n }\n });\n }\n\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n const isLast = i === tokens.length - 1;\n let matchingTerms = [];\n if (isLast && token.length >= 2) {\n matchingTerms = Object.keys(searchIndex.index).filter(t => t.startsWith(token));\n } else if (searchIndex.index[token]) {\n matchingTerms = [token];\n }\n\n for (const term of matchingTerms) {\n const postings = searchIndex.index[term] || [];\n const df = searchIndex.df[term] || 1;\n const idf = Math.log((searchIndex.doc_count - df + 0.5) / (df + 0.5) + 1.0);\n\n for (const posting of postings) {\n const doc = searchIndex.documents[posting.doc_idx];\n if (!doc) continue;\n if (!matchesScopes(doc, parsedQuery.scopes)) continue;\n const boost = posting.field === 'Title' ? 10 : posting.field === 'Heading' ? 5 : 1;\n const tf = posting.tf;\n const docLen = doc.body.length;\n const score = idf * ((tf * (k1 + 1)) / (tf + k1 * (1 - b + b * docLen / searchIndex.avg_dl))) * boost;\n\n if (!docScores.has(posting.doc_idx)) {\n docScores.set(posting.doc_idx, { score: 0, matches: new Set() });\n }\n const entry = docScores.get(posting.doc_idx);\n entry.score += score;\n entry.matches.add(term);\n }\n }\n }\n\n results = Array.from(docScores.entries())\n .map(([docIdx, data]) => {\n const doc = searchIndex.documents[docIdx];\n const scopes = getScopesForDoc(doc);\n let snippet = '';\n if (doc.body) {\n const bodyLower = doc.body.toLowerCase();\n let firstPos = -1;\n for (const match of data.matches) {\n const pos = bodyLower.indexOf(match);\n if (pos !== -1 && (firstPos === -1 || pos < firstPos)) firstPos = pos;\n }\n const start = firstPos === -1 ? 0 : Math.max(0, firstPos - 50);\n const end = Math.min(doc.body.length, start + 150);\n snippet = doc.body.slice(start, end);\n if (start > 0) snippet = '...' + snippet;\n if (end < doc.body.length) snippet += '...';\n }\n return { ...doc, score: data.score, scopes, snippet };\n })\n .sort((a, b) => b.score - a.score || a.title.localeCompare(b.title))\n .slice(0, 10);\n\n selectedIndex = 0;\n renderResults();\n };\n\n const renderResults = () => {\n if (!results.length) {\n searchResults.innerHTML = '<div class=\"search-empty\">No results found</div>';\n return;\n }\n searchResults.innerHTML = results.map((r, i) =>\n '<a href=\"' + r.url + '\" class=\"search-result' + (i === selectedIndex ? ' selected' : '') + '\">' +\n '<div class=\"search-result-title\">' + r.title + (r.scopes?.length ? '<span class=\"search-result-scope\">@' + r.scopes[0] + '</span>' : '') + '</div>' +\n (r.snippet ? '<div class=\"search-result-snippet\">' + r.snippet + '</div>' : '') +\n '</a>'\n ).join('');\n };\n\n // Event listeners\n if (searchButton) searchButton.addEventListener('click', openSearch);\n if (searchClose) searchClose.addEventListener('click', closeSearch);\n if (searchOverlay) searchOverlay.addEventListener('click', (e) => { if (e.target === searchOverlay) closeSearch(); });\n\n let searchTimeout = null;\n if (searchInput) {\n searchInput.addEventListener('input', () => {\n if (searchTimeout) clearTimeout(searchTimeout);\n searchTimeout = setTimeout(() => performSearch(searchInput.value), 150);\n });\n searchInput.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') closeSearch();\n else if (e.key === 'ArrowDown') {\n e.preventDefault();\n if (selectedIndex < results.length - 1) { selectedIndex++; renderResults(); }\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n if (selectedIndex > 0) { selectedIndex--; renderResults(); }\n } else if (e.key === 'Enter' && results[selectedIndex]) {\n e.preventDefault();\n window.location.href = results[selectedIndex].url;\n }\n });\n }\n\n // Global keyboard shortcut (/ or Cmd+K)\n document.addEventListener('keydown', (e) => {\n if ((e.key === '/' && !(e.target instanceof HTMLInputElement)) ||\n ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k')) {\n e.preventDefault();\n openSearch();\n }\n });\n </script>\n</body>\n</html>";
|
|
1083
1167
|
/**
|
|
1084
1168
|
* Resolves SSG options with defaults.
|
|
1085
1169
|
*/
|
|
1086
1170
|
declare function resolveSsgOptions(ssg: SsgOptions | boolean | undefined): ResolvedSsgOptions;
|
|
1087
|
-
/**
|
|
1088
|
-
* Extracts title from content or frontmatter.
|
|
1089
|
-
*/
|
|
1090
|
-
|
|
1091
1171
|
/**
|
|
1092
1172
|
* Builds all markdown files to static HTML.
|
|
1093
1173
|
*/
|
|
@@ -1095,7 +1175,6 @@ declare function buildSsg(options: ResolvedOptions, root: string): Promise<{
|
|
|
1095
1175
|
files: string[];
|
|
1096
1176
|
errors: string[];
|
|
1097
1177
|
}>;
|
|
1098
|
-
//# sourceMappingURL=ssg.d.ts.map
|
|
1099
1178
|
//#endregion
|
|
1100
1179
|
//#region src/search.d.ts
|
|
1101
1180
|
/**
|
|
@@ -1110,11 +1189,6 @@ declare function buildSearchIndex(srcDir: string, base: string): Promise<string>
|
|
|
1110
1189
|
* Writes the search index to a file.
|
|
1111
1190
|
*/
|
|
1112
1191
|
declare function writeSearchIndex(indexJson: string, outDir: string): Promise<void>;
|
|
1113
|
-
/**
|
|
1114
|
-
* Client-side search module code.
|
|
1115
|
-
* This is injected into the bundle as a virtual module.
|
|
1116
|
-
*/
|
|
1117
|
-
|
|
1118
1192
|
//#endregion
|
|
1119
1193
|
//#region src/jsx-runtime.d.ts
|
|
1120
1194
|
/**
|
|
@@ -1241,8 +1315,7 @@ interface BasePageProps {
|
|
|
1241
1315
|
* Extended page props with custom frontmatter.
|
|
1242
1316
|
*/
|
|
1243
1317
|
type PageProps<T extends Record<string, unknown> = Record<string, unknown>> = BasePageProps & {
|
|
1244
|
-
/** Custom frontmatter fields */
|
|
1245
|
-
frontmatter: T & Record<string, unknown>;
|
|
1318
|
+
/** Custom frontmatter fields */frontmatter: T & Record<string, unknown>;
|
|
1246
1319
|
};
|
|
1247
1320
|
/**
|
|
1248
1321
|
* Site-wide configuration available in context.
|
|
@@ -1401,7 +1474,6 @@ declare function inferType(value: unknown): string;
|
|
|
1401
1474
|
* Generates TypeScript interface from frontmatter samples.
|
|
1402
1475
|
*/
|
|
1403
1476
|
declare function generateFrontmatterTypes(samples: Record<string, unknown>[], interfaceName?: string): string;
|
|
1404
|
-
//# sourceMappingURL=page-context.d.ts.map
|
|
1405
1477
|
//#endregion
|
|
1406
1478
|
//#region src/theme-renderer.d.ts
|
|
1407
1479
|
/**
|
|
@@ -1504,7 +1576,6 @@ declare function createTheme(config: {
|
|
|
1504
1576
|
layouts: Record<string, ThemeComponent>;
|
|
1505
1577
|
defaultLayout?: string;
|
|
1506
1578
|
}): ThemeComponent;
|
|
1507
|
-
//# sourceMappingURL=theme-renderer.d.ts.map
|
|
1508
1579
|
//#endregion
|
|
1509
1580
|
//#region src/plugins/tabs.d.ts
|
|
1510
1581
|
/**
|
|
@@ -1516,7 +1587,6 @@ declare function transformTabs(html: string): Promise<string>;
|
|
|
1516
1587
|
* This is needed because :has() selectors need unique IDs.
|
|
1517
1588
|
*/
|
|
1518
1589
|
declare function generateTabsCSS(groupCount: number): string;
|
|
1519
|
-
//# sourceMappingURL=tabs.d.ts.map
|
|
1520
1590
|
//#endregion
|
|
1521
1591
|
//#region src/plugins/youtube.d.ts
|
|
1522
1592
|
/**
|
|
@@ -1543,7 +1613,6 @@ declare function extractVideoId(input: string): string | null;
|
|
|
1543
1613
|
* Transform YouTube components in HTML.
|
|
1544
1614
|
*/
|
|
1545
1615
|
declare function transformYouTube(html: string, options?: YouTubeOptions): Promise<string>;
|
|
1546
|
-
//# sourceMappingURL=youtube.d.ts.map
|
|
1547
1616
|
//#endregion
|
|
1548
1617
|
//#region src/plugins/github.d.ts
|
|
1549
1618
|
/**
|
|
@@ -1589,7 +1658,6 @@ declare function prefetchGitHubRepos(repos: string[], options?: GitHubOptions):
|
|
|
1589
1658
|
* Transform GitHub components in HTML.
|
|
1590
1659
|
*/
|
|
1591
1660
|
declare function transformGitHub(html: string, repoDataMap?: Map<string, GitHubRepoData | null>, options?: GitHubOptions): Promise<string>;
|
|
1592
|
-
//# sourceMappingURL=github.d.ts.map
|
|
1593
1661
|
//#endregion
|
|
1594
1662
|
//#region src/plugins/ogp.d.ts
|
|
1595
1663
|
/**
|
|
@@ -1632,7 +1700,6 @@ declare function prefetchOgpData(urls: string[], options?: OgpOptions): Promise<
|
|
|
1632
1700
|
* Transform OgCard components in HTML.
|
|
1633
1701
|
*/
|
|
1634
1702
|
declare function transformOgp(html: string, ogpDataMap?: Map<string, OgpData | null>, options?: OgpOptions): Promise<string>;
|
|
1635
|
-
//# sourceMappingURL=ogp.d.ts.map
|
|
1636
1703
|
//#endregion
|
|
1637
1704
|
//#region src/plugins/mermaid.d.ts
|
|
1638
1705
|
/**
|
|
@@ -1655,7 +1722,6 @@ declare function transformMermaidStatic(html: string, _options?: MermaidOptions)
|
|
|
1655
1722
|
* @deprecated No longer used. Mermaid rendering is now done at build time via NAPI.
|
|
1656
1723
|
*/
|
|
1657
1724
|
declare const mermaidClientScript = "";
|
|
1658
|
-
//# sourceMappingURL=mermaid.d.ts.map
|
|
1659
1725
|
//#endregion
|
|
1660
1726
|
//#region src/plugins/index.d.ts
|
|
1661
1727
|
/**
|
|
@@ -1674,7 +1740,6 @@ interface TransformAllOptions {
|
|
|
1674
1740
|
* Transform all enabled plugins in HTML content.
|
|
1675
1741
|
*/
|
|
1676
1742
|
declare function transformAllPlugins(html: string, options?: TransformAllOptions): Promise<string>;
|
|
1677
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1678
1743
|
//#endregion
|
|
1679
1744
|
//#region src/island/parse.d.ts
|
|
1680
1745
|
/**
|
|
@@ -1694,10 +1759,6 @@ interface ParseIslandsResult {
|
|
|
1694
1759
|
html: string;
|
|
1695
1760
|
islands: IslandInfo[];
|
|
1696
1761
|
}
|
|
1697
|
-
/**
|
|
1698
|
-
* Reset island counter (for testing).
|
|
1699
|
-
*/
|
|
1700
|
-
|
|
1701
1762
|
/**
|
|
1702
1763
|
* Transform Island components in HTML.
|
|
1703
1764
|
*
|
|
@@ -1734,7 +1795,6 @@ declare function extractIslandInfo(html: string): Promise<IslandInfo[]>;
|
|
|
1734
1795
|
* This is a minimal script that imports and initializes islands.
|
|
1735
1796
|
*/
|
|
1736
1797
|
declare function generateHydrationScript(components: string[]): string;
|
|
1737
|
-
//# sourceMappingURL=parse.d.ts.map
|
|
1738
1798
|
//#endregion
|
|
1739
1799
|
//#region src/og-image/types.d.ts
|
|
1740
1800
|
/**
|
|
@@ -1814,7 +1874,6 @@ interface ResolvedOgImageOptions {
|
|
|
1814
1874
|
cache: boolean;
|
|
1815
1875
|
concurrency: number;
|
|
1816
1876
|
}
|
|
1817
|
-
//# sourceMappingURL=types.d.ts.map
|
|
1818
1877
|
//#endregion
|
|
1819
1878
|
//#region src/og-image/browser.d.ts
|
|
1820
1879
|
/**
|
|
@@ -1832,17 +1891,6 @@ interface ResolvedOgImageOptions {
|
|
|
1832
1891
|
interface OgBrowserSession extends AsyncDisposable {
|
|
1833
1892
|
renderPage(html: string, width: number, height: number, publicDir?: string): Promise<Buffer>;
|
|
1834
1893
|
}
|
|
1835
|
-
/**
|
|
1836
|
-
* Opens a Chromium browser and returns a session for rendering OG images.
|
|
1837
|
-
* Returns null if Playwright/Chromium is not available.
|
|
1838
|
-
*
|
|
1839
|
-
* The session implements AsyncDisposable — use `await using` for automatic cleanup:
|
|
1840
|
-
* ```ts
|
|
1841
|
-
* await using session = await openBrowser();
|
|
1842
|
-
* if (!session) return;
|
|
1843
|
-
* const png = await session.renderPage(html, 1200, 630);
|
|
1844
|
-
* ```
|
|
1845
|
-
*/
|
|
1846
1894
|
//#endregion
|
|
1847
1895
|
//#region src/og-image/index.d.ts
|
|
1848
1896
|
/**
|
|
@@ -1875,7 +1923,6 @@ interface OgImageResult {
|
|
|
1875
1923
|
* All errors are non-fatal: failures are reported in results but never throw.
|
|
1876
1924
|
*/
|
|
1877
1925
|
declare function generateOgImages(pages: OgImagePageEntry[], options: ResolvedOgImageOptions, root: string): Promise<OgImageResult[]>;
|
|
1878
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1879
1926
|
//#endregion
|
|
1880
1927
|
//#region src/i18n.d.ts
|
|
1881
1928
|
/**
|
|
@@ -1886,8 +1933,6 @@ declare function resolveI18nOptions(options: I18nOptions | false | undefined): R
|
|
|
1886
1933
|
* Creates the i18n sub-plugin for the Vite plugin array.
|
|
1887
1934
|
*/
|
|
1888
1935
|
declare function createI18nPlugin(resolvedOptions: ResolvedOptions): Plugin;
|
|
1889
|
-
//# sourceMappingURL=i18n.d.ts.map
|
|
1890
|
-
|
|
1891
1936
|
//#endregion
|
|
1892
1937
|
//#region src/index.d.ts
|
|
1893
1938
|
/**
|
|
@@ -1911,5 +1956,5 @@ declare function createI18nPlugin(resolvedOptions: ResolvedOptions): Plugin;
|
|
|
1911
1956
|
*/
|
|
1912
1957
|
declare function oxContent(options?: OxContentOptions): Plugin[];
|
|
1913
1958
|
//#endregion
|
|
1914
|
-
export { type BasePageProps, DEFAULT_HTML_TEMPLATE, DefaultTheme, type DocEntry, type DocsOptions, type EntryPageConfig, type ExtractedDocs, type FeatureConfig, Fragment, type FrontmatterSchema, type GitHubOptions, type GitHubRepoData, type HeroAction, type HeroConfig, type HeroImage, type I18nOptions, type IslandInfo, type JSXChild, type JSXElementType, type JSXNode, type JSXProps, type LanguageRegistration, type LoadStrategy, type LocaleConfig, MarkdownNode, MarkdownTransformer, type MermaidOptions, type NavGroup, type NavItem, type OgBrowserSession, type OgImageOptions, type OgImagePageEntry, type OgImageOptions$1 as OgImagePluginOptions, type OgImageResult, type OgImageTemplateFn, type OgImageTemplateProps, type OgpData, type OgpOptions, type OxContentOptions, type PageData, type PageProps, type ParamDoc, type ParseIslandsResult, type RenderContext, type ResolvedDocsOptions, type ResolvedI18nOptions, type ResolvedOgImageOptions, ResolvedOptions, type ResolvedSearchOptions, type ResolvedSsgOptions, type ResolvedThemeConfig, type ReturnDoc, type SearchDocument, type SearchOptions, type SearchResult, type SiteConfig, type SocialLinks, type SsgOptions, type ThemeColors, type ThemeComponent, type ThemeConfig, type ThemeEmbed, type ThemeFonts, type ThemeFooter, type ThemeHeader, type ThemeLayout, type ThemeProps, type ThemeRenderOptions, TocEntry, type TransformAllOptions, TransformContext, TransformResult, type YouTubeOptions, buildSearchIndex, buildSsg, clearRenderContext, collectGitHubRepos, collectOgpUrls, createI18nPlugin, createMarkdownEnvironment, createTheme, defaultTheme, defineTheme, each, extractDocs, extractIslandInfo, extractVideoId, fetchOgpData, fetchRepoData, generateFrontmatterTypes, generateHydrationScript, generateMarkdown, generateOgImages, generateTabsCSS, generateTypes, hasIslands, inferType, jsx, jsxs, mergeThemes, mermaidClientScript, oxContent, prefetchGitHubRepos, prefetchOgpData, raw, renderAllPages, renderPage, renderToString, resolveDocsOptions, resolveI18nOptions, resolveOgImageOptions, resolveSearchOptions, resolveSsgOptions, resolveTheme, setRenderContext, transformAllPlugins, transformGitHub, transformIslands, transformMarkdown, transformMermaidStatic, transformOgp, transformTabs, transformYouTube, useIsActive, useNav, usePageProps, useRenderContext, useSiteConfig, when, writeDocs, writeSearchIndex };
|
|
1959
|
+
export { type BasePageProps, CodeAnnotationKind, type CodeAnnotationSyntax, type CodeAnnotationsOptions, DEFAULT_HTML_TEMPLATE, DefaultTheme, type DocEntry, type DocsOptions, type EntryPageConfig, type ExtractedDocs, type FeatureConfig, Fragment, type FrontmatterSchema, GeneratedDocsData, type GitHubOptions, type GitHubRepoData, type HeroAction, type HeroConfig, type HeroImage, HeroNotice, type I18nOptions, type IslandInfo, type JSXChild, type JSXElementType, type JSXNode, type JSXProps, type LanguageRegistration, type LoadStrategy, type LocaleConfig, MarkdownNode, MarkdownTransformer, type MermaidOptions, type NavGroup, type NavItem, type OgBrowserSession, type OgImageOptions, type OgImagePageEntry, type OgImageOptions$1 as OgImagePluginOptions, type OgImageResult, type OgImageTemplateFn, type OgImageTemplateProps, type OgpData, type OgpOptions, type OxContentOptions, type PageData, type PageProps, type ParamDoc, type ParseIslandsResult, type RenderContext, type ResolvedCodeAnnotationsOptions, type ResolvedDocsOptions, type ResolvedI18nOptions, type ResolvedOgImageOptions, ResolvedOptions, type ResolvedSearchOptions, type ResolvedSsgOptions, type ResolvedThemeConfig, type ReturnDoc, ScopedSearchQuery, type SearchDocument, type SearchOptions, type SearchResult, type SiteConfig, type SocialLinks, type SsgOptions, type ThemeColors, type ThemeComponent, type ThemeConfig, type ThemeEmbed, type ThemeEntryPage, type ThemeFonts, type ThemeFooter, type ThemeHeader, type ThemeLayout, type ThemeProps, type ThemeRegistration, type ThemeRenderOptions, TocEntry, type TransformAllOptions, TransformContext, TransformResult, type YouTubeOptions, buildSearchIndex, buildSsg, clearRenderContext, collectGitHubRepos, collectOgpUrls, createI18nPlugin, createMarkdownEnvironment, createTheme, defaultTheme, defineTheme, each, extractDocs, extractIslandInfo, extractVideoId, fetchOgpData, fetchRepoData, generateFrontmatterTypes, generateHydrationScript, generateMarkdown, generateOgImages, generateTabsCSS, generateTypes, hasIslands, inferType, jsx, jsxs, mergeThemes, mermaidClientScript, oxContent, prefetchGitHubRepos, prefetchOgpData, raw, renderAllPages, renderPage, renderToString, resolveDocsOptions, resolveI18nOptions, resolveOgImageOptions, resolveSearchOptions, resolveSsgOptions, resolveTheme, setRenderContext, transformAllPlugins, transformGitHub, transformIslands, transformMarkdown, transformMermaidStatic, transformOgp, transformTabs, transformYouTube, useIsActive, useNav, usePageProps, useRenderContext, useSiteConfig, when, writeDocs, writeSearchIndex };
|
|
1915
1960
|
//# sourceMappingURL=index.d.cts.map
|