jamdesk 1.0.23 → 1.1.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/__tests__/unit/package-config.test.js +1 -1
- package/dist/__tests__/unit/package-config.test.js.map +1 -1
- package/dist/lib/deps.js +4 -4
- package/dist/lib/deps.js.map +1 -1
- package/package.json +2 -2
- package/vendored/app/[[...slug]]/page.tsx +31 -16
- package/vendored/app/api/og/route.tsx +13 -23
- package/vendored/app/api/raw-content/[...slug]/route.ts +28 -0
- package/vendored/app/layout.tsx +46 -17
- package/vendored/components/AIActionsMenu.tsx +677 -0
- package/vendored/components/mdx/ApiEndpoint.tsx +2 -1
- package/vendored/components/mdx/ImagePriorityProvider.tsx +53 -0
- package/vendored/components/mdx/MDXComponents.tsx +15 -0
- package/vendored/components/mdx/ZoomableImage.tsx +35 -27
- package/vendored/lib/analytics-script.ts +0 -8
- package/vendored/lib/contextual-defaults.ts +16 -0
- package/vendored/lib/docs-types.ts +11 -3
- package/vendored/lib/enhance-navigation.ts +1 -1
- package/vendored/lib/isr-build-executor.ts +41 -0
- package/vendored/lib/preprocess-mdx.ts +5 -3
- package/vendored/lib/r2-content.ts +2 -0
- package/vendored/lib/redirect-matcher.ts +31 -0
- package/vendored/lib/revalidation-helpers.ts +10 -0
- package/vendored/lib/revalidation-trigger.ts +7 -3
- package/vendored/lib/seo.ts +10 -20
- package/vendored/lib/static-artifacts.ts +43 -0
- package/vendored/lib/static-file-route.ts +11 -1
- package/vendored/schema/docs-schema.json +23 -3
- package/vendored/scripts/copy-files.cjs +47 -4
- package/vendored/components/snippets/generated/CodeLink.tsx +0 -25
- package/vendored/components/snippets/generated/HeaderAPI.tsx +0 -44
- package/vendored/components/snippets/generated/PlansAvailable.tsx +0 -53
- package/vendored/components/snippets/generated/SnippetIntro.tsx +0 -43
|
@@ -20,7 +20,7 @@ describe('package.json validation', () => {
|
|
|
20
20
|
});
|
|
21
21
|
it('has bin entry for CLI', () => {
|
|
22
22
|
expect(pkg.bin).toBeDefined();
|
|
23
|
-
expect(pkg.bin.jamdesk).toBe('
|
|
23
|
+
expect(pkg.bin.jamdesk).toBe('bin/jamdesk.js');
|
|
24
24
|
});
|
|
25
25
|
it('has main entry point', () => {
|
|
26
26
|
expect(pkg.main).toBe('./dist/index.js');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-config.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/package-config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AACvE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAE1D,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,kBAAkB,EAAE,GAAG,EAAE;YAC1B,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACjC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;YACpC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;YAC3B,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,UAAU,EAAE,CAAC;YACrC,MAAM,CAAC,OAAO,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;YAC/B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"package-config.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/package-config.test.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/deps.js
CHANGED
|
@@ -44,9 +44,9 @@ const REQUIRED_DEPS = {
|
|
|
44
44
|
'@orama/orama': '^3.1.18',
|
|
45
45
|
'@orama/plugin-data-persistence': '^3.1.18',
|
|
46
46
|
'react-markdown': '^10.1.0',
|
|
47
|
-
'shiki': '^
|
|
48
|
-
'@shikijs/rehype': '^
|
|
49
|
-
'@shikijs/transformers': '^
|
|
47
|
+
'shiki': '^4.0.1',
|
|
48
|
+
'@shikijs/rehype': '^4.0.1',
|
|
49
|
+
'@shikijs/transformers': '^4.0.1',
|
|
50
50
|
'rehype-highlight': '^7.0.0',
|
|
51
51
|
'rehype-katex': '^7.0.1',
|
|
52
52
|
'rehype-slug': '^6.0.0',
|
|
@@ -54,7 +54,7 @@ const REQUIRED_DEPS = {
|
|
|
54
54
|
'remark-math': '^6.0.0',
|
|
55
55
|
'remark-smartypants': '^3.0.2',
|
|
56
56
|
// Math/LaTeX rendering
|
|
57
|
-
'katex': '^0.16.
|
|
57
|
+
'katex': '^0.16.34',
|
|
58
58
|
// Diagrams
|
|
59
59
|
'mermaid': '^11.12.2',
|
|
60
60
|
// YAML parsing (for OpenAPI specs)
|
package/dist/lib/deps.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deps.js","sourceRoot":"","sources":["../../src/lib/deps.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEvC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,oBAAoB,CAAwB,CAAC;AAExE,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AAExD,uCAAuC;AACvC,MAAM,aAAa,GAA2B;IAC5C,oBAAoB;IACpB,MAAM,EAAE,SAAS;IACjB,8CAA8C;IAC9C,6BAA6B,EAAE,SAAS;IACxC,eAAe,EAAE,SAAS;IAC1B,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,SAAS;IACtB,WAAW,EAAE,SAAS;IACtB,iBAAiB,EAAE,QAAQ;IAC3B,aAAa,EAAE,QAAQ;IACvB,QAAQ;IACR,mCAAmC,EAAE,QAAQ;IAC7C,oCAAoC,EAAE,QAAQ;IAC9C,qCAAqC,EAAE,QAAQ;IAC/C,mCAAmC,EAAE,QAAQ;IAC7C,gCAAgC,EAAE,QAAQ;IAC1C,cAAc,EAAE,UAAU;IAC1B,6BAA6B;IAC7B,aAAa,EAAE,QAAQ;IACvB,YAAY,EAAE,UAAU;IACxB,SAAS,EAAE,QAAQ;IACnB,qBAAqB;IACrB,cAAc,EAAE,SAAS;IACzB,gCAAgC,EAAE,SAAS;IAC3C,gBAAgB,EAAE,SAAS;IAC3B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"deps.js","sourceRoot":"","sources":["../../src/lib/deps.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jamdesk",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "CLI for Jamdesk — build, preview, and deploy documentation sites from MDX. Dev server with hot reload, 50+ components, OpenAPI support, AI search, and Mintlify migration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jamdesk",
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
"devDependencies": {
|
|
110
110
|
"@mdx-js/mdx": "^3.1.1",
|
|
111
111
|
"@types/fs-extra": "^11.0.0",
|
|
112
|
-
"@types/node": "^25.3.
|
|
112
|
+
"@types/node": "^25.3.5",
|
|
113
113
|
"typescript": "^5.3.0",
|
|
114
114
|
"vitest": "^4.0.18"
|
|
115
115
|
},
|
|
@@ -71,6 +71,9 @@ import {
|
|
|
71
71
|
type AuthMethod,
|
|
72
72
|
} from '@/lib/openapi';
|
|
73
73
|
import { ApiEndpoint } from '@/components/mdx/ApiEndpoint';
|
|
74
|
+
import { ImagePriorityProvider } from '@/components/mdx/ImagePriorityProvider';
|
|
75
|
+
import { AIActionsMenu } from '@/components/AIActionsMenu';
|
|
76
|
+
import { getContextualOptions } from '@/lib/contextual-defaults';
|
|
74
77
|
|
|
75
78
|
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'TRACE';
|
|
76
79
|
|
|
@@ -634,6 +637,10 @@ export default async function DocPage({ params }: PageProps) {
|
|
|
634
637
|
</a>
|
|
635
638
|
) : null;
|
|
636
639
|
|
|
640
|
+
// Contextual AI Actions menu options
|
|
641
|
+
const contextualOptions = getContextualOptions(config);
|
|
642
|
+
const hasAiActions = contextualOptions.length > 0;
|
|
643
|
+
|
|
637
644
|
// Prose class for MDX content styling (defined in base.css)
|
|
638
645
|
const proseClasses = 'prose max-w-none';
|
|
639
646
|
|
|
@@ -654,12 +661,14 @@ export default async function DocPage({ params }: PageProps) {
|
|
|
654
661
|
{data.title}
|
|
655
662
|
</h1>
|
|
656
663
|
{rssIcon}
|
|
664
|
+
{hasAiActions && <div className="ml-auto flex-shrink-0 hidden sm:block"><AIActionsMenu options={contextualOptions} projectName={config.name} /></div>}
|
|
657
665
|
</div>
|
|
658
666
|
{data.description && (
|
|
659
667
|
<p className="text-base sm:text-lg text-theme-text-secondary leading-relaxed mt-2 sm:mt-3">
|
|
660
668
|
{data.description}
|
|
661
669
|
</p>
|
|
662
670
|
)}
|
|
671
|
+
{hasAiActions && <div className="mt-3 sm:hidden" style={{ paddingLeft: 0 }}><AIActionsMenu options={contextualOptions} projectName={config.name} /></div>}
|
|
663
672
|
</header>
|
|
664
673
|
)}
|
|
665
674
|
|
|
@@ -684,21 +693,23 @@ export default async function DocPage({ params }: PageProps) {
|
|
|
684
693
|
|
|
685
694
|
{/* Additional MDX content — strip <ResponseExample> on OpenAPI pages
|
|
686
695
|
(auto-generated ResponseExamplePanel already handles responses) */}
|
|
687
|
-
<
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
696
|
+
<ImagePriorityProvider>
|
|
697
|
+
<MDXRemote
|
|
698
|
+
source={openApiEndpointData
|
|
699
|
+
? content.replace(/<ResponseExample>[\s\S]*?<\/ResponseExample>/g, '')
|
|
700
|
+
: content}
|
|
701
|
+
components={AllComponentsWithInline}
|
|
702
|
+
options={{
|
|
703
|
+
// Keep expression props (e.g. cols={2}) compatible under next-mdx-remote v6.
|
|
704
|
+
...mdxSecurityOptions,
|
|
705
|
+
mdxOptions: {
|
|
706
|
+
remarkPlugins: [remarkGfm, ...getTypographyRemarkPlugins(config), ...getLatexRemarkPlugins(config)],
|
|
707
|
+
rehypePlugins: [rehypeNoZoomToData, rehypeClassToClassName, rehypeCodeMeta, createShikiRehypePlugin(highlighter, config), rehypeRestoreDataTitle, ...getLatexRehypePlugins(config), rehypeSlug],
|
|
708
|
+
recmaPlugins: [recmaCompoundComponents],
|
|
709
|
+
},
|
|
710
|
+
}}
|
|
711
|
+
/>
|
|
712
|
+
</ImagePriorityProvider>
|
|
702
713
|
</div>
|
|
703
714
|
|
|
704
715
|
{/* Previous/Next Navigation */}
|
|
@@ -740,18 +751,22 @@ export default async function DocPage({ params }: PageProps) {
|
|
|
740
751
|
{data.title}
|
|
741
752
|
</h1>
|
|
742
753
|
{rssIcon}
|
|
754
|
+
{hasAiActions && <div className="ml-auto flex-shrink-0 hidden sm:block"><AIActionsMenu options={contextualOptions} projectName={config.name} /></div>}
|
|
743
755
|
</div>
|
|
744
756
|
{data.description && (
|
|
745
757
|
<p className="text-base sm:text-lg text-theme-text-secondary leading-relaxed mt-2 sm:mt-3">
|
|
746
758
|
{data.description}
|
|
747
759
|
</p>
|
|
748
760
|
)}
|
|
761
|
+
{hasAiActions && <div className="mt-3 sm:hidden" style={{ paddingLeft: 0 }}><AIActionsMenu options={contextualOptions} projectName={config.name} /></div>}
|
|
749
762
|
</header>
|
|
750
763
|
)}
|
|
751
764
|
|
|
752
765
|
{/* Content */}
|
|
753
766
|
<div className={proseClasses}>
|
|
754
|
-
|
|
767
|
+
<ImagePriorityProvider>
|
|
768
|
+
{hasView ? <ViewWrapper>{mdxContent}</ViewWrapper> : mdxContent}
|
|
769
|
+
</ImagePriorityProvider>
|
|
755
770
|
|
|
756
771
|
{/* Previous/Next Navigation - inside prose to match content width */}
|
|
757
772
|
<PageNavigation currentSlug={slug.join('/')} config={config} isWideMode={isWideMode || hasPanel} />
|
|
@@ -3,25 +3,17 @@ import { NextRequest } from 'next/server';
|
|
|
3
3
|
|
|
4
4
|
export const runtime = 'edge';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
// Warm cream/red-orange palette — matches marketing site OG images
|
|
7
|
+
const ACCENT_COLOR = '#ff3621';
|
|
8
|
+
const ACCENT_GRADIENT = `linear-gradient(90deg, ${ACCENT_COLOR} 0%, #e02e1a 50%, #c4200f 100%)`;
|
|
9
|
+
const BG_GRADIENT = 'linear-gradient(135deg, #faf8f5 0%, #f3f0eb 100%)';
|
|
10
|
+
const TEXT_COLOR = '#1b3139';
|
|
11
|
+
const MUTED_COLOR = '#5a6b73';
|
|
12
|
+
const BADGE_BG = `rgba(255, 54, 33, 0.08)`; // ACCENT_COLOR at 8% opacity
|
|
7
13
|
const MAX_DESCRIPTION_LENGTH = 120;
|
|
8
14
|
const LONG_TITLE_THRESHOLD = 40;
|
|
9
15
|
const FONT_STACK =
|
|
10
16
|
'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
11
|
-
const ACCENT_GRADIENT = `linear-gradient(90deg, ${ACCENT_COLOR} 0%, #C4B5FD 50%, #A78BFA 100%)`;
|
|
12
|
-
|
|
13
|
-
function getThemeColors(isDark: boolean) {
|
|
14
|
-
return {
|
|
15
|
-
text: isDark ? '#ffffff' : '#1a1a2e',
|
|
16
|
-
muted: isDark ? '#a0a0b0' : '#666680',
|
|
17
|
-
background: isDark
|
|
18
|
-
? 'linear-gradient(135deg, #1a1a3e 0%, #0f0f23 100%)'
|
|
19
|
-
: 'linear-gradient(135deg, #f8f8fc 0%, #ffffff 100%)',
|
|
20
|
-
badgeBackground: isDark
|
|
21
|
-
? 'rgba(139, 92, 246, 0.15)'
|
|
22
|
-
: 'rgba(139, 92, 246, 0.1)',
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
17
|
|
|
26
18
|
function truncateText(text: string, maxLength: number): string {
|
|
27
19
|
if (text.length <= maxLength) return text;
|
|
@@ -39,7 +31,7 @@ function truncateText(text: string, maxLength: number): string {
|
|
|
39
31
|
* - section: Section/group name (optional, e.g., "Get Started")
|
|
40
32
|
* - siteName: Site name (optional, defaults to "Documentation")
|
|
41
33
|
* - logo: URL to the project's logo (optional)
|
|
42
|
-
* - theme:
|
|
34
|
+
* - theme: accepted but ignored (always uses cream/warm style)
|
|
43
35
|
*
|
|
44
36
|
* Example:
|
|
45
37
|
* /api/og?title=Introduction§ion=Get%20Started&siteName=Acme%20Docs&logo=https://...
|
|
@@ -52,7 +44,6 @@ export async function GET(request: NextRequest) {
|
|
|
52
44
|
const section = searchParams.get('section') || '';
|
|
53
45
|
const siteName = searchParams.get('siteName') || 'Documentation';
|
|
54
46
|
const logoUrl = searchParams.get('logo') || '';
|
|
55
|
-
const isDark = (searchParams.get('theme') || 'dark') === 'dark';
|
|
56
47
|
|
|
57
48
|
// Fetch logo and convert to base64 data URI for Satori compatibility
|
|
58
49
|
// (Satori doesn't support webp and can fail on remote URLs)
|
|
@@ -70,7 +61,6 @@ export async function GET(request: NextRequest) {
|
|
|
70
61
|
}
|
|
71
62
|
}
|
|
72
63
|
|
|
73
|
-
const colors = getThemeColors(isDark);
|
|
74
64
|
const titleFontSize = title.length > LONG_TITLE_THRESHOLD ? '52px' : '64px';
|
|
75
65
|
|
|
76
66
|
return new ImageResponse(
|
|
@@ -82,7 +72,7 @@ export async function GET(request: NextRequest) {
|
|
|
82
72
|
display: 'flex',
|
|
83
73
|
flexDirection: 'column',
|
|
84
74
|
padding: '60px',
|
|
85
|
-
background:
|
|
75
|
+
background: BG_GRADIENT,
|
|
86
76
|
fontFamily: FONT_STACK,
|
|
87
77
|
}}
|
|
88
78
|
>
|
|
@@ -111,7 +101,7 @@ export async function GET(request: NextRequest) {
|
|
|
111
101
|
style={{
|
|
112
102
|
fontSize: '24px',
|
|
113
103
|
fontWeight: 600,
|
|
114
|
-
color:
|
|
104
|
+
color: MUTED_COLOR,
|
|
115
105
|
textTransform: 'uppercase',
|
|
116
106
|
letterSpacing: '0.05em',
|
|
117
107
|
}}
|
|
@@ -134,7 +124,7 @@ export async function GET(request: NextRequest) {
|
|
|
134
124
|
fontWeight: 500,
|
|
135
125
|
color: ACCENT_COLOR,
|
|
136
126
|
padding: '8px 16px',
|
|
137
|
-
background:
|
|
127
|
+
background: BADGE_BG,
|
|
138
128
|
borderRadius: '20px',
|
|
139
129
|
}}
|
|
140
130
|
>
|
|
@@ -156,7 +146,7 @@ export async function GET(request: NextRequest) {
|
|
|
156
146
|
style={{
|
|
157
147
|
fontSize: titleFontSize,
|
|
158
148
|
fontWeight: 700,
|
|
159
|
-
color:
|
|
149
|
+
color: TEXT_COLOR,
|
|
160
150
|
lineHeight: 1.2,
|
|
161
151
|
margin: 0,
|
|
162
152
|
maxWidth: '900px',
|
|
@@ -169,7 +159,7 @@ export async function GET(request: NextRequest) {
|
|
|
169
159
|
<p
|
|
170
160
|
style={{
|
|
171
161
|
fontSize: '28px',
|
|
172
|
-
color:
|
|
162
|
+
color: MUTED_COLOR,
|
|
173
163
|
marginTop: '24px',
|
|
174
164
|
lineHeight: 1.4,
|
|
175
165
|
maxWidth: '800px',
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getContentLoader } from '@/lib/content-loader';
|
|
2
|
+
import { NextResponse } from 'next/server';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Serve raw MDX content for local dev mode.
|
|
6
|
+
* In production ISR mode, .md URLs are handled by middleware → R2 instead.
|
|
7
|
+
*/
|
|
8
|
+
export async function GET(
|
|
9
|
+
_request: Request,
|
|
10
|
+
{ params }: { params: Promise<{ slug: string[] }> }
|
|
11
|
+
) {
|
|
12
|
+
const { slug } = await params;
|
|
13
|
+
const pagePath = slug.join('/');
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
const loader = getContentLoader();
|
|
17
|
+
const content = await loader.getContent(pagePath);
|
|
18
|
+
return new NextResponse(content, {
|
|
19
|
+
headers: {
|
|
20
|
+
'Content-Type': 'text/markdown; charset=utf-8',
|
|
21
|
+
'Content-Disposition': 'inline',
|
|
22
|
+
'X-Robots-Tag': 'noindex, nofollow',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
} catch {
|
|
26
|
+
return new NextResponse('Not found', { status: 404 });
|
|
27
|
+
}
|
|
28
|
+
}
|
package/vendored/app/layout.tsx
CHANGED
|
@@ -18,6 +18,7 @@ import { ASSET_PREFIX, transformConfigImagePath } from '@/lib/docs-types';
|
|
|
18
18
|
import { LinkPrefixProvider } from '@/lib/link-prefix-context';
|
|
19
19
|
import { getAnalyticsScript } from '@/lib/analytics-script';
|
|
20
20
|
import { buildSiteTitle } from '@/lib/seo';
|
|
21
|
+
import { fetchCustomCss, fetchCustomJs } from '@/lib/r2-content';
|
|
21
22
|
|
|
22
23
|
// Pre-load fonts - Next.js will tree-shake unused ones
|
|
23
24
|
const inter = Inter({
|
|
@@ -89,12 +90,12 @@ export async function generateMetadata(): Promise<Metadata> {
|
|
|
89
90
|
};
|
|
90
91
|
}
|
|
91
92
|
|
|
92
|
-
// Read
|
|
93
|
-
function
|
|
93
|
+
// Read a file from public/ directory for inline injection
|
|
94
|
+
function getLocalFileContent(filename: string): string | null {
|
|
94
95
|
try {
|
|
95
|
-
const
|
|
96
|
-
if (fs.existsSync(
|
|
97
|
-
return fs.readFileSync(
|
|
96
|
+
const filePath = path.join(process.cwd(), 'public', filename);
|
|
97
|
+
if (fs.existsSync(filePath)) {
|
|
98
|
+
return fs.readFileSync(filePath, 'utf8');
|
|
98
99
|
}
|
|
99
100
|
} catch {
|
|
100
101
|
// Ignore errors
|
|
@@ -301,7 +302,24 @@ export default async function RootLayout({
|
|
|
301
302
|
}
|
|
302
303
|
}
|
|
303
304
|
|
|
304
|
-
|
|
305
|
+
// Custom CSS/JS: In ISR mode, _has* flags are set by build.ts on the R2 config.
|
|
306
|
+
// In local dev, the project source docs.json has no _has* flags, so read files directly.
|
|
307
|
+
const isIsr = isIsrMode();
|
|
308
|
+
|
|
309
|
+
let customCss: string | null = null;
|
|
310
|
+
let customJs: string | null = null;
|
|
311
|
+
if (isIsr && resolvedProjectSlug) {
|
|
312
|
+
if (config._hasCustomCss) {
|
|
313
|
+
customCss = await fetchCustomCss(resolvedProjectSlug);
|
|
314
|
+
}
|
|
315
|
+
if (config._hasCustomJs) {
|
|
316
|
+
customJs = await fetchCustomJs(resolvedProjectSlug);
|
|
317
|
+
}
|
|
318
|
+
} else {
|
|
319
|
+
customCss = getLocalFileContent('custom.css');
|
|
320
|
+
customJs = getLocalFileContent('custom.js');
|
|
321
|
+
}
|
|
322
|
+
|
|
305
323
|
const themeName = config.theme as ThemeName | undefined;
|
|
306
324
|
const themeCss = themeName && themeName !== 'jam' ? getThemeCssContent(themeName) : null;
|
|
307
325
|
const fontClassName = getFontClassName(themeName, config.fonts);
|
|
@@ -342,11 +360,22 @@ export default async function RootLayout({
|
|
|
342
360
|
</>
|
|
343
361
|
)}
|
|
344
362
|
{/* Font Awesome CSS for navigation icons - self-hosted web fonts */}
|
|
345
|
-
{/*
|
|
363
|
+
{/* Loaded async (preload + script injection) to avoid render-blocking 40KB CSS */}
|
|
346
364
|
<link
|
|
347
|
-
rel="
|
|
365
|
+
rel="preload"
|
|
348
366
|
href="/_jd/fonts/fontawesome/css/all.min.css"
|
|
367
|
+
as="style"
|
|
349
368
|
/>
|
|
369
|
+
<script
|
|
370
|
+
dangerouslySetInnerHTML={{ __html:
|
|
371
|
+
"var l=document.createElement('link');l.rel='stylesheet';" +
|
|
372
|
+
"l.href='/_jd/fonts/fontawesome/css/all.min.css';" +
|
|
373
|
+
"document.head.appendChild(l);"
|
|
374
|
+
}}
|
|
375
|
+
/>
|
|
376
|
+
<noscript>
|
|
377
|
+
<link rel="stylesheet" href="/_jd/fonts/fontawesome/css/all.min.css" />
|
|
378
|
+
</noscript>
|
|
350
379
|
{/* DNS prefetch for KaTeX CDN - only when latex is enabled */}
|
|
351
380
|
{config.styling?.latex && (
|
|
352
381
|
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net" />
|
|
@@ -476,10 +505,6 @@ export default async function RootLayout({
|
|
|
476
505
|
{customCss && (
|
|
477
506
|
<style dangerouslySetInnerHTML={{ __html: customCss }} />
|
|
478
507
|
)}
|
|
479
|
-
{/* Jamdesk Analytics - tracks page views for analytics dashboard */}
|
|
480
|
-
{analyticsScript && (
|
|
481
|
-
<script dangerouslySetInnerHTML={{ __html: analyticsScript }} />
|
|
482
|
-
)}
|
|
483
508
|
{/* Plausible Analytics */}
|
|
484
509
|
{(config.integrations?.plausible?.domain || config.integrations?.plausible?.scriptUrl) && (
|
|
485
510
|
<PlausibleScript
|
|
@@ -508,17 +533,21 @@ export default async function RootLayout({
|
|
|
508
533
|
<HeaderLinkCopy />
|
|
509
534
|
</ThemeProvider>
|
|
510
535
|
{/* Crisp Chat */}
|
|
511
|
-
{config.integrations?.crisp?.websiteId &&
|
|
536
|
+
{config.integrations?.crisp?.websiteId &&
|
|
537
|
+
/^[a-f0-9-]{36}$/.test(config.integrations.crisp.websiteId) && (
|
|
512
538
|
<script
|
|
513
539
|
dangerouslySetInnerHTML={{
|
|
514
540
|
__html: `window.$crisp=[];window.CRISP_WEBSITE_ID="${config.integrations.crisp.websiteId}";(function(){var d=document;var s=d.createElement("script");s.src="https://client.crisp.chat/l.js";s.async=1;d.getElementsByTagName("head")[0].appendChild(s)})();`,
|
|
515
541
|
}}
|
|
516
542
|
/>
|
|
517
543
|
)}
|
|
518
|
-
{/* Custom JavaScript -
|
|
519
|
-
{
|
|
520
|
-
|
|
521
|
-
|
|
544
|
+
{/* Custom JavaScript - inlined from R2 (ISR) or public/ (dev) */}
|
|
545
|
+
{customJs && (
|
|
546
|
+
<script dangerouslySetInnerHTML={{ __html: customJs }} />
|
|
547
|
+
)}
|
|
548
|
+
{/* Jamdesk Analytics — deferred to body for faster FCP */}
|
|
549
|
+
{analyticsScript && (
|
|
550
|
+
<script dangerouslySetInnerHTML={{ __html: analyticsScript }} />
|
|
522
551
|
)}
|
|
523
552
|
{/* Google Analytics 4 */}
|
|
524
553
|
{config.integrations?.ga4?.measurementId && (
|