jamdesk 1.1.179 → 1.1.180
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jamdesk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.180",
|
|
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",
|
|
@@ -18,6 +18,7 @@ import { renderInlineMarkdown } from '@/lib/inline-markdown';
|
|
|
18
18
|
import { decodePromptSource } from '@/lib/prompt-source-codec';
|
|
19
19
|
|
|
20
20
|
import { ChatGPTIcon, ClaudeIcon, CursorIcon, GeminiIcon, PerplexityIcon } from './ai-action-icons';
|
|
21
|
+
import { useDocsLocale } from './docs-locale-context';
|
|
21
22
|
import { Icon } from './Icon';
|
|
22
23
|
import {
|
|
23
24
|
resolvePromptActions,
|
|
@@ -293,11 +294,12 @@ export function Prompt({
|
|
|
293
294
|
const generatedMenuId = useId();
|
|
294
295
|
const menuId = `prompt-actions-${generatedMenuId}`;
|
|
295
296
|
|
|
297
|
+
const locale = useDocsLocale();
|
|
296
298
|
const prompt = useMemo(() => decodePromptSource(__promptSource), [__promptSource]);
|
|
297
299
|
const hasPrompt = prompt.length > 0;
|
|
298
300
|
const resolvedActions = useMemo(
|
|
299
|
-
() => hasPrompt ? resolvePromptActions(actions, prompt) : [],
|
|
300
|
-
[actions, hasPrompt, prompt],
|
|
301
|
+
() => hasPrompt ? resolvePromptActions(actions, prompt, locale) : [],
|
|
302
|
+
[actions, hasPrompt, locale, prompt],
|
|
301
303
|
);
|
|
302
304
|
const [primary, ...secondary] = resolvedActions;
|
|
303
305
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext, type ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The rendered page's language code, whitelisted against the project's
|
|
7
|
+
* `navigation.languages` (see resolveLocaleFromPath in lib/language-utils.ts —
|
|
8
|
+
* a path segment that merely looks like a language code never counts).
|
|
9
|
+
*
|
|
10
|
+
* Empty string = default/unknown locale; consumers fall back to English.
|
|
11
|
+
* Surfaces without the provider (dashboard editor preview) get the default.
|
|
12
|
+
*/
|
|
13
|
+
const DocsLocaleContext = createContext<string>('');
|
|
14
|
+
|
|
15
|
+
export function DocsLocaleProvider({
|
|
16
|
+
children,
|
|
17
|
+
locale,
|
|
18
|
+
}: {
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
locale: string;
|
|
21
|
+
}): React.ReactElement {
|
|
22
|
+
return (
|
|
23
|
+
<DocsLocaleContext.Provider value={locale}>
|
|
24
|
+
{children}
|
|
25
|
+
</DocsLocaleContext.Provider>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function useDocsLocale(): string {
|
|
30
|
+
return useContext(DocsLocaleContext);
|
|
31
|
+
}
|
|
@@ -119,15 +119,47 @@ export interface ResolvedPromptAction {
|
|
|
119
119
|
label: string;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
const
|
|
123
|
-
cursor:
|
|
124
|
-
claude:
|
|
125
|
-
chatgpt:
|
|
126
|
-
perplexity:
|
|
127
|
-
gemini:
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
122
|
+
const BUILTIN_TOOL_NAMES: Record<Exclude<PromptBuiltinAction, 'copy'>, string> = {
|
|
123
|
+
cursor: 'Cursor',
|
|
124
|
+
claude: 'Claude',
|
|
125
|
+
chatgpt: 'ChatGPT',
|
|
126
|
+
perplexity: 'Perplexity',
|
|
127
|
+
gemini: 'Gemini',
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
// "Open in {tool}" per page language. Keys are lowercased language codes;
|
|
131
|
+
// regional variants fall back to the base language, unknown locales to English.
|
|
132
|
+
const OPEN_IN_TEMPLATES: Record<string, (tool: string) => string> = {
|
|
133
|
+
en: (tool) => `Open in ${tool}`,
|
|
134
|
+
fr: (tool) => `Ouvrir dans ${tool}`,
|
|
135
|
+
es: (tool) => `Abrir en ${tool}`,
|
|
136
|
+
de: (tool) => `In ${tool} öffnen`,
|
|
137
|
+
it: (tool) => `Apri in ${tool}`,
|
|
138
|
+
pt: (tool) => `Abrir no ${tool}`,
|
|
139
|
+
nl: (tool) => `Openen in ${tool}`,
|
|
140
|
+
ja: (tool) => `${tool}で開く`,
|
|
141
|
+
ko: (tool) => `${tool}에서 열기`,
|
|
142
|
+
zh: (tool) => `在 ${tool} 中打开`,
|
|
143
|
+
'zh-tw': (tool) => `在 ${tool} 中開啟`,
|
|
144
|
+
'zh-hk': (tool) => `在 ${tool} 中開啟`,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
export function getBuiltinActionLabel(
|
|
148
|
+
action: Exclude<PromptBuiltinAction, 'copy'>,
|
|
149
|
+
locale = '',
|
|
150
|
+
): string {
|
|
151
|
+
const lowered = locale.toLowerCase();
|
|
152
|
+
const template = OPEN_IN_TEMPLATES[lowered]
|
|
153
|
+
?? OPEN_IN_TEMPLATES[lowered.split('-')[0]]
|
|
154
|
+
?? OPEN_IN_TEMPLATES.en;
|
|
155
|
+
return template(BUILTIN_TOOL_NAMES[action]);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function resolvePromptActions(
|
|
159
|
+
actions: unknown,
|
|
160
|
+
prompt: string,
|
|
161
|
+
locale = '',
|
|
162
|
+
): ResolvedPromptAction[] {
|
|
131
163
|
return normalizePromptActions(actions).flatMap((action) => {
|
|
132
164
|
const href = buildPromptActionUrl(action, prompt);
|
|
133
165
|
if (!href) return [];
|
|
@@ -135,7 +167,7 @@ export function resolvePromptActions(actions: unknown, prompt: string): Resolved
|
|
|
135
167
|
return [{
|
|
136
168
|
action,
|
|
137
169
|
href,
|
|
138
|
-
label: typeof action === 'string' ?
|
|
170
|
+
label: typeof action === 'string' ? getBuiltinActionLabel(action, locale) : action.label,
|
|
139
171
|
}];
|
|
140
172
|
});
|
|
141
173
|
}
|
|
@@ -86,7 +86,8 @@ import {
|
|
|
86
86
|
} from '@/lib/openapi';
|
|
87
87
|
import { classifyOpenApiLoadError } from '@/lib/openapi/classify-load-error';
|
|
88
88
|
import { findOperation, deriveOperationDescription, collectLocalSpecPaths } from '@/lib/openapi/operation-description';
|
|
89
|
-
import { extractLanguageFromPath, isValidLanguageCode } from '@/lib/language-utils';
|
|
89
|
+
import { extractLanguageFromPath, isValidLanguageCode, resolveLocaleFromPath } from '@/lib/language-utils';
|
|
90
|
+
import { DocsLocaleProvider } from '@/components/mdx/docs-locale-context';
|
|
90
91
|
import { findFirstNavPage } from '@/lib/find-first-nav-page';
|
|
91
92
|
import { candidateSpecPaths } from '@/lib/openapi/lang-spec-path';
|
|
92
93
|
import { ApiEndpoint } from '@/components/mdx/ApiEndpoint';
|
|
@@ -419,6 +420,14 @@ export async function renderDocPage(input: RenderInput): Promise<ReactElement> {
|
|
|
419
420
|
const data = parsed.data as FrontmatterData;
|
|
420
421
|
const rawContent = parsed.content;
|
|
421
422
|
|
|
423
|
+
// Whitelisted page locale for localized component chrome (Prompt action
|
|
424
|
+
// labels). Unlike `currentLang` above, this only counts a path prefix that
|
|
425
|
+
// is actually declared in navigation.languages — '' otherwise.
|
|
426
|
+
const docsLocale = resolveLocaleFromPath(
|
|
427
|
+
`/${pagePath}`,
|
|
428
|
+
config.navigation?.languages?.map((l) => l.language) ?? [],
|
|
429
|
+
);
|
|
430
|
+
|
|
422
431
|
const baseUrl = resolveBaseUrl(requestHeaders, projectSlug, hostAtDocs);
|
|
423
432
|
const faqPairs = extractFaqPairs(rawContent);
|
|
424
433
|
const ogImageUrl = buildPageOgImageUrl(config, data, baseUrl);
|
|
@@ -853,21 +862,23 @@ export async function renderDocPage(input: RenderInput): Promise<ReactElement> {
|
|
|
853
862
|
<MdxErrorBlock label="page content" />
|
|
854
863
|
) : (
|
|
855
864
|
<MdxRenderBoundary fallback={<MdxErrorBlock label="page content" />}>
|
|
856
|
-
<
|
|
857
|
-
<
|
|
858
|
-
<
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
865
|
+
<DocsLocaleProvider locale={docsLocale}>
|
|
866
|
+
<StepSlugProvider entries={stepEntries}>
|
|
867
|
+
<UpdateSlugProvider entries={updateEntries}>
|
|
868
|
+
<MDXRemote
|
|
869
|
+
source={effectiveSource}
|
|
870
|
+
components={ComponentsWithUnknownFallback}
|
|
871
|
+
options={{
|
|
872
|
+
...mdxSecurityOptions,
|
|
873
|
+
mdxOptions: {
|
|
874
|
+
...getCommonMdxOptions(config, highlighter),
|
|
875
|
+
recmaPlugins: [recmaCompoundComponents, recmaGuardExpressions],
|
|
876
|
+
},
|
|
877
|
+
}}
|
|
878
|
+
/>
|
|
879
|
+
</UpdateSlugProvider>
|
|
880
|
+
</StepSlugProvider>
|
|
881
|
+
</DocsLocaleProvider>
|
|
871
882
|
</MdxRenderBoundary>
|
|
872
883
|
)}
|
|
873
884
|
</div>
|
|
@@ -885,21 +896,23 @@ export async function renderDocPage(input: RenderInput): Promise<ReactElement> {
|
|
|
885
896
|
<MdxErrorBlock label="page content" />
|
|
886
897
|
) : (
|
|
887
898
|
<MdxRenderBoundary fallback={<MdxErrorBlock label="page content" />}>
|
|
888
|
-
<
|
|
889
|
-
<
|
|
890
|
-
<
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
899
|
+
<DocsLocaleProvider locale={docsLocale}>
|
|
900
|
+
<StepSlugProvider entries={stepEntries}>
|
|
901
|
+
<UpdateSlugProvider entries={updateEntries}>
|
|
902
|
+
<MDXRemote
|
|
903
|
+
source={content}
|
|
904
|
+
components={ComponentsWithUnknownFallback}
|
|
905
|
+
options={{
|
|
906
|
+
...mdxSecurityOptions,
|
|
907
|
+
mdxOptions: {
|
|
908
|
+
...getCommonMdxOptions(config, highlighter),
|
|
909
|
+
recmaPlugins: [recmaCompoundComponents, recmaGuardExpressions],
|
|
910
|
+
},
|
|
911
|
+
}}
|
|
912
|
+
/>
|
|
913
|
+
</UpdateSlugProvider>
|
|
914
|
+
</StepSlugProvider>
|
|
915
|
+
</DocsLocaleProvider>
|
|
903
916
|
</MdxRenderBoundary>
|
|
904
917
|
);
|
|
905
918
|
|