jamdesk 1.1.19 → 1.1.21
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/openapi-server-variable-description.test.d.ts +2 -0
- package/dist/__tests__/unit/openapi-server-variable-description.test.d.ts.map +1 -0
- package/dist/__tests__/unit/openapi-server-variable-description.test.js +55 -0
- package/dist/__tests__/unit/openapi-server-variable-description.test.js.map +1 -0
- package/dist/__tests__/unit/openapi.test.js +20 -5
- package/dist/__tests__/unit/openapi.test.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +3 -1
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +15 -2
- package/dist/commands/dev.js.map +1 -1
- package/dist/lib/deps.js +6 -6
- package/dist/lib/deps.js.map +1 -1
- package/package.json +6 -4
- package/scripts/patch-openapi-schemas.js +91 -0
- package/vendored/app/[[...slug]]/page.tsx +24 -39
- package/vendored/app/layout.tsx +16 -7
- package/vendored/components/FontAwesomeLoader.tsx +2 -1
- package/vendored/components/mdx/YouTube.tsx +21 -3
- package/vendored/components/search/SearchModal.tsx +15 -12
- package/vendored/components/snippets/generated/CodeLink.tsx +25 -0
- package/vendored/components/snippets/generated/HeaderAPI.tsx +44 -0
- package/vendored/components/snippets/generated/PlansAvailable.tsx +53 -0
- package/vendored/lib/analytics-client.ts +9 -27
- package/vendored/lib/docs-types.ts +16 -8
- package/vendored/lib/email-templates/build-failure.tsx +3 -0
- package/vendored/lib/extract-highlights.ts +2 -0
- package/vendored/lib/font-awesome.ts +2 -0
- package/vendored/lib/indexnow.ts +3 -1
- package/vendored/lib/isr-build-executor.ts +4 -1
- package/vendored/lib/page-isr-helpers.ts +9 -0
- package/vendored/lib/paths.ts +21 -9
- package/vendored/lib/project-slug-context.tsx +27 -0
- package/vendored/lib/r2-manifest.ts +1 -0
- package/vendored/next.config.js +2 -0
- package/vendored/schema/docs-schema.json +17 -0
- package/vendored/components/snippets/generated/ar__SnippetIntro.tsx +0 -43
- package/vendored/components/snippets/generated/es__SnippetIntro.tsx +0 -43
- package/vendored/components/snippets/generated/ja__SnippetIntro.tsx +0 -43
- package/vendored/components/snippets/generated/ko__SnippetIntro.tsx +0 -43
- package/vendored/postcss.config.js +0 -6
package/vendored/lib/paths.ts
CHANGED
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Import these instead of using __dirname directly.
|
|
2
|
+
* Path Helpers
|
|
3
|
+
*
|
|
4
|
+
* Centralized build-service paths derived from the CJS `__dirname` of this file.
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
|
-
import { fileURLToPath } from 'url';
|
|
9
7
|
import { dirname, join } from 'path';
|
|
8
|
+
import { existsSync } from 'fs';
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the build-service root directory.
|
|
12
|
+
*
|
|
13
|
+
* In source (tsx / vitest): __dirname = build-service/lib → parent is root.
|
|
14
|
+
* In compiled CJS: __dirname = build-service/dist/lib → grandparent is root.
|
|
15
|
+
*
|
|
16
|
+
* We walk up from __dirname until we find the directory containing package.json.
|
|
17
|
+
*/
|
|
18
|
+
function findProjectRoot(): string {
|
|
19
|
+
let dir = dirname(__dirname); // one level up from lib/
|
|
20
|
+
if (existsSync(join(dir, 'package.json'))) return dir;
|
|
21
|
+
dir = dirname(dir); // two levels up (from dist/lib/)
|
|
22
|
+
if (existsSync(join(dir, 'package.json'))) return dir;
|
|
23
|
+
// Fallback — should never happen
|
|
24
|
+
return dirname(__dirname);
|
|
25
|
+
}
|
|
14
26
|
|
|
15
27
|
// Export common paths
|
|
16
28
|
export const LIB_DIR = __dirname;
|
|
17
|
-
export const BUILD_SERVICE_DIR =
|
|
29
|
+
export const BUILD_SERVICE_DIR = findProjectRoot();
|
|
18
30
|
export const PROJECTS_DIR = join(BUILD_SERVICE_DIR, 'projects');
|
|
19
31
|
export const SCRIPTS_DIR = join(BUILD_SERVICE_DIR, 'scripts');
|
|
20
32
|
export const PUBLIC_DIR = join(BUILD_SERVICE_DIR, 'public');
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext, type ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
// `NEXT_PUBLIC_PROJECT_SLUG` is inlined at build time and unset in the
|
|
6
|
+
// multi-tenant ISR deployment, so the slug has to flow through context.
|
|
7
|
+
// `layout.tsx` seeds the value from the `x-project-slug` header set by
|
|
8
|
+
// middleware. Empty string means "unknown" — consumers should no-op.
|
|
9
|
+
const ProjectSlugContext = createContext<string>('');
|
|
10
|
+
|
|
11
|
+
export function ProjectSlugProvider({
|
|
12
|
+
children,
|
|
13
|
+
slug,
|
|
14
|
+
}: {
|
|
15
|
+
children: ReactNode;
|
|
16
|
+
slug: string;
|
|
17
|
+
}): React.ReactElement {
|
|
18
|
+
return (
|
|
19
|
+
<ProjectSlugContext.Provider value={slug}>
|
|
20
|
+
{children}
|
|
21
|
+
</ProjectSlugContext.Provider>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function useProjectSlug(): string {
|
|
26
|
+
return useContext(ProjectSlugContext);
|
|
27
|
+
}
|
package/vendored/next.config.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
/** @type {import('next').NextConfig} */
|
|
14
14
|
const nextConfig = {
|
|
15
|
+
poweredByHeader: false,
|
|
15
16
|
// Hide dev indicator (floating icon in bottom-left)
|
|
16
17
|
devIndicators: false,
|
|
17
18
|
// Rewrite /_jd/ asset paths to public/ in dev (ISR middleware handles this in production)
|
|
@@ -20,6 +21,7 @@ const nextConfig = {
|
|
|
20
21
|
{ source: '/_jd/images/:path*', destination: '/images/:path*' },
|
|
21
22
|
{ source: '/_jd/videos/:path*', destination: '/videos/:path*' },
|
|
22
23
|
{ source: '/_jd/playground/:path*', destination: '/api/playground/:path*' },
|
|
24
|
+
{ source: '/_jd/:path*', destination: '/:path*' },
|
|
23
25
|
];
|
|
24
26
|
},
|
|
25
27
|
// Allow /_jd/ image paths with ?v= cache-busting query strings in <Image>
|
|
@@ -1544,6 +1544,17 @@
|
|
|
1544
1544
|
},
|
|
1545
1545
|
"additionalProperties": false,
|
|
1546
1546
|
"description": "Configuration for the jamdesk spellcheck command"
|
|
1547
|
+
},
|
|
1548
|
+
"images": {
|
|
1549
|
+
"type": "object",
|
|
1550
|
+
"description": "Image optimization settings for documentation builds",
|
|
1551
|
+
"properties": {
|
|
1552
|
+
"convertToWebp": {
|
|
1553
|
+
"type": "boolean",
|
|
1554
|
+
"description": "Automatically convert PNG and JPG images to WebP format during builds. Reduces image sizes by 60-80% for faster page loads. SVG and GIF files are not converted. Default: false"
|
|
1555
|
+
}
|
|
1556
|
+
},
|
|
1557
|
+
"additionalProperties": false
|
|
1547
1558
|
}
|
|
1548
1559
|
},
|
|
1549
1560
|
"required": [
|
|
@@ -1660,6 +1671,9 @@
|
|
|
1660
1671
|
},
|
|
1661
1672
|
"spellcheck": {
|
|
1662
1673
|
"$ref": "#/anyOf/0/properties/spellcheck"
|
|
1674
|
+
},
|
|
1675
|
+
"images": {
|
|
1676
|
+
"$ref": "#/anyOf/0/properties/images"
|
|
1663
1677
|
}
|
|
1664
1678
|
},
|
|
1665
1679
|
"required": [
|
|
@@ -1776,6 +1790,9 @@
|
|
|
1776
1790
|
},
|
|
1777
1791
|
"spellcheck": {
|
|
1778
1792
|
"$ref": "#/anyOf/0/properties/spellcheck"
|
|
1793
|
+
},
|
|
1794
|
+
"images": {
|
|
1795
|
+
"$ref": "#/anyOf/0/properties/images"
|
|
1779
1796
|
}
|
|
1780
1797
|
},
|
|
1781
1798
|
"required": [
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// Auto-generated file - do not edit manually
|
|
2
|
-
// @ts-nocheck
|
|
3
|
-
|
|
4
|
-
import React from 'react';
|
|
5
|
-
|
|
6
|
-
// Import built-in MDX components that snippets can use
|
|
7
|
-
import { Note, Info, Warning, Tip, Check, Danger, Callout } from '@/components/mdx/Callouts';
|
|
8
|
-
import { Card } from '@/components/mdx/Card';
|
|
9
|
-
import { CardGroup } from '@/components/mdx/CardGroup';
|
|
10
|
-
import { ParamField } from '@/components/mdx/ParamField';
|
|
11
|
-
import { ResponseField } from '@/components/mdx/ResponseField';
|
|
12
|
-
import { Accordion, AccordionGroup } from '@/components/mdx/Accordion';
|
|
13
|
-
import { CodeGroup } from '@/components/mdx/CodeGroup';
|
|
14
|
-
import { Steps, Step } from '@/components/mdx/Steps';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// Helper component for rendering plain MDX snippets
|
|
18
|
-
// Content is from project snippets (controlled source), not user input
|
|
19
|
-
const PlainMdxSnippet = ({ content }: { content: string }) => {
|
|
20
|
-
const formattedContent = content
|
|
21
|
-
.split('\n\n')
|
|
22
|
-
.map((paragraph) => {
|
|
23
|
-
let html = paragraph.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
|
24
|
-
html = html.replace(/\*([^*]+)\*/g, '<em>$1</em>');
|
|
25
|
-
html = html.replace(/\`([^\`]+)\`/g, '<code>$1</code>');
|
|
26
|
-
return html;
|
|
27
|
-
})
|
|
28
|
-
.filter(p => p.trim());
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<div className="snippet-content">
|
|
32
|
-
{formattedContent.map((p, i) => (
|
|
33
|
-
<p key={i} dangerouslySetInnerHTML={{ __html: p }} />
|
|
34
|
-
))}
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const SnippetIntro = () => {
|
|
40
|
-
return <PlainMdxSnippet content={"أحد المبادئ الأساسية في تطوير البرمجيات هو مبدأ DRY (Don't Repeat\nYourself). وهذا مبدأ ينطبق على التوثيق أيضًا.\nإذا وجدت نفسك تكرر المحتوى نفسه في عدة أماكن، ففكّر في إنشاء مقتطف\nمخصص (snippet) للحفاظ على content الخاص بك متزامنًا."} />;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export default SnippetIntro;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// Auto-generated file - do not edit manually
|
|
2
|
-
// @ts-nocheck
|
|
3
|
-
|
|
4
|
-
import React from 'react';
|
|
5
|
-
|
|
6
|
-
// Import built-in MDX components that snippets can use
|
|
7
|
-
import { Note, Info, Warning, Tip, Check, Danger, Callout } from '@/components/mdx/Callouts';
|
|
8
|
-
import { Card } from '@/components/mdx/Card';
|
|
9
|
-
import { CardGroup } from '@/components/mdx/CardGroup';
|
|
10
|
-
import { ParamField } from '@/components/mdx/ParamField';
|
|
11
|
-
import { ResponseField } from '@/components/mdx/ResponseField';
|
|
12
|
-
import { Accordion, AccordionGroup } from '@/components/mdx/Accordion';
|
|
13
|
-
import { CodeGroup } from '@/components/mdx/CodeGroup';
|
|
14
|
-
import { Steps, Step } from '@/components/mdx/Steps';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// Helper component for rendering plain MDX snippets
|
|
18
|
-
// Content is from project snippets (controlled source), not user input
|
|
19
|
-
const PlainMdxSnippet = ({ content }: { content: string }) => {
|
|
20
|
-
const formattedContent = content
|
|
21
|
-
.split('\n\n')
|
|
22
|
-
.map((paragraph) => {
|
|
23
|
-
let html = paragraph.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
|
24
|
-
html = html.replace(/\*([^*]+)\*/g, '<em>$1</em>');
|
|
25
|
-
html = html.replace(/\`([^\`]+)\`/g, '<code>$1</code>');
|
|
26
|
-
return html;
|
|
27
|
-
})
|
|
28
|
-
.filter(p => p.trim());
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<div className="snippet-content">
|
|
32
|
-
{formattedContent.map((p, i) => (
|
|
33
|
-
<p key={i} dangerouslySetInnerHTML={{ __html: p }} />
|
|
34
|
-
))}
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const SnippetIntro = () => {
|
|
40
|
-
return <PlainMdxSnippet content={"Uno de los principios fundamentales del desarrollo de software es DRY (Don't Repeat Yourself). Este es un principio que también se aplica a la documentación. Si te encuentras repitiendo el mismo contenido en varios lugares, deberías considerar crear un snippet personalizado para mantener tu contenido sincronizado."} />;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export default SnippetIntro;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// Auto-generated file - do not edit manually
|
|
2
|
-
// @ts-nocheck
|
|
3
|
-
|
|
4
|
-
import React from 'react';
|
|
5
|
-
|
|
6
|
-
// Import built-in MDX components that snippets can use
|
|
7
|
-
import { Note, Info, Warning, Tip, Check, Danger, Callout } from '@/components/mdx/Callouts';
|
|
8
|
-
import { Card } from '@/components/mdx/Card';
|
|
9
|
-
import { CardGroup } from '@/components/mdx/CardGroup';
|
|
10
|
-
import { ParamField } from '@/components/mdx/ParamField';
|
|
11
|
-
import { ResponseField } from '@/components/mdx/ResponseField';
|
|
12
|
-
import { Accordion, AccordionGroup } from '@/components/mdx/Accordion';
|
|
13
|
-
import { CodeGroup } from '@/components/mdx/CodeGroup';
|
|
14
|
-
import { Steps, Step } from '@/components/mdx/Steps';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// Helper component for rendering plain MDX snippets
|
|
18
|
-
// Content is from project snippets (controlled source), not user input
|
|
19
|
-
const PlainMdxSnippet = ({ content }: { content: string }) => {
|
|
20
|
-
const formattedContent = content
|
|
21
|
-
.split('\n\n')
|
|
22
|
-
.map((paragraph) => {
|
|
23
|
-
let html = paragraph.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
|
24
|
-
html = html.replace(/\*([^*]+)\*/g, '<em>$1</em>');
|
|
25
|
-
html = html.replace(/\`([^\`]+)\`/g, '<code>$1</code>');
|
|
26
|
-
return html;
|
|
27
|
-
})
|
|
28
|
-
.filter(p => p.trim());
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<div className="snippet-content">
|
|
32
|
-
{formattedContent.map((p, i) => (
|
|
33
|
-
<p key={i} dangerouslySetInnerHTML={{ __html: p }} />
|
|
34
|
-
))}
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const SnippetIntro = () => {
|
|
40
|
-
return <PlainMdxSnippet content={"ソフトウェア開発の中核となる原則の一つに、DRY(Don't Repeat Yourself)があります。この原則はドキュメントにも当てはまります。同じ内容を複数の場所で繰り返している場合は、内容を常に同期させておけるように、カスタムスニペットの作成を検討してください。"} />;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export default SnippetIntro;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
// Auto-generated file - do not edit manually
|
|
2
|
-
// @ts-nocheck
|
|
3
|
-
|
|
4
|
-
import React from 'react';
|
|
5
|
-
|
|
6
|
-
// Import built-in MDX components that snippets can use
|
|
7
|
-
import { Note, Info, Warning, Tip, Check, Danger, Callout } from '@/components/mdx/Callouts';
|
|
8
|
-
import { Card } from '@/components/mdx/Card';
|
|
9
|
-
import { CardGroup } from '@/components/mdx/CardGroup';
|
|
10
|
-
import { ParamField } from '@/components/mdx/ParamField';
|
|
11
|
-
import { ResponseField } from '@/components/mdx/ResponseField';
|
|
12
|
-
import { Accordion, AccordionGroup } from '@/components/mdx/Accordion';
|
|
13
|
-
import { CodeGroup } from '@/components/mdx/CodeGroup';
|
|
14
|
-
import { Steps, Step } from '@/components/mdx/Steps';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// Helper component for rendering plain MDX snippets
|
|
18
|
-
// Content is from project snippets (controlled source), not user input
|
|
19
|
-
const PlainMdxSnippet = ({ content }: { content: string }) => {
|
|
20
|
-
const formattedContent = content
|
|
21
|
-
.split('\n\n')
|
|
22
|
-
.map((paragraph) => {
|
|
23
|
-
let html = paragraph.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
|
24
|
-
html = html.replace(/\*([^*]+)\*/g, '<em>$1</em>');
|
|
25
|
-
html = html.replace(/\`([^\`]+)\`/g, '<code>$1</code>');
|
|
26
|
-
return html;
|
|
27
|
-
})
|
|
28
|
-
.filter(p => p.trim());
|
|
29
|
-
|
|
30
|
-
return (
|
|
31
|
-
<div className="snippet-content">
|
|
32
|
-
{formattedContent.map((p, i) => (
|
|
33
|
-
<p key={i} dangerouslySetInnerHTML={{ __html: p }} />
|
|
34
|
-
))}
|
|
35
|
-
</div>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const SnippetIntro = () => {
|
|
40
|
-
return <PlainMdxSnippet content={"소프트웨어 개발의 핵심 원칙 중 하나는 DRY(Don't Repeat Yourself)입니다. 이 원칙은 문서 작성에도 그대로 적용됩니다. 동일한 content를 여러 곳에서 반복해서 작성하고 있다면, content를 일관되게 유지할 수 있도록 커스텀 스니펫을 만드는 것을 고려해야 합니다."} />;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export default SnippetIntro;
|