jamdesk 1.1.83 → 1.1.85
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 +1 -1
- package/vendored/components/mdx/Steps.tsx +1 -23
- package/vendored/components/mdx/Update.tsx +1 -1
- package/vendored/components/navigation/LanguageSelector.tsx +57 -30
- package/vendored/themes/base.css +7 -2
- package/vendored/workspace-package-lock.json +33 -149
- package/dist/__tests__/unit/dev-workspace-symlinks.test.d.ts +0 -2
- package/dist/__tests__/unit/dev-workspace-symlinks.test.d.ts.map +0 -1
- package/dist/__tests__/unit/dev-workspace-symlinks.test.js +0 -112
- package/dist/__tests__/unit/dev-workspace-symlinks.test.js.map +0 -1
- package/dist/__tests__/unit/language-filter.test.d.ts +0 -2
- package/dist/__tests__/unit/language-filter.test.d.ts.map +0 -1
- package/dist/__tests__/unit/language-filter.test.js +0 -166
- package/dist/__tests__/unit/language-filter.test.js.map +0 -1
- package/dist/__tests__/unit/output.test.d.ts +0 -2
- package/dist/__tests__/unit/output.test.d.ts.map +0 -1
- package/dist/__tests__/unit/output.test.js +0 -61
- package/dist/__tests__/unit/output.test.js.map +0 -1
- package/dist/lib/language-filter.d.ts +0 -31
- package/dist/lib/language-filter.d.ts.map +0 -1
- package/dist/lib/language-filter.js +0 -14
- package/dist/lib/language-filter.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jamdesk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.85",
|
|
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",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { ReactNode, Children, cloneElement, isValidElement, memo } from 'react';
|
|
4
4
|
import { getIconClass } from '@/lib/icon-utils';
|
|
5
5
|
import { useStepSlug } from './StepSlugContext';
|
|
6
6
|
|
|
@@ -32,32 +32,10 @@ function isStepComponent(child: unknown): boolean {
|
|
|
32
32
|
);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// Non-Step element children render as plain text inside <Steps> with no step
|
|
36
|
-
// circle/number — surface them in dev so authors notice the silent fallback.
|
|
37
|
-
function warnAboutNonStepChildren(childrenArray: readonly unknown[]): void {
|
|
38
|
-
if (process.env.NODE_ENV === 'production') return;
|
|
39
|
-
const offenders = childrenArray.filter(
|
|
40
|
-
(c): c is ReactElement => isValidElement(c) && !isStepComponent(c),
|
|
41
|
-
);
|
|
42
|
-
if (offenders.length === 0) return;
|
|
43
|
-
const labels = offenders.map((c) => {
|
|
44
|
-
const t = c.type;
|
|
45
|
-
if (typeof t === 'string') return `<${t}>`;
|
|
46
|
-
const named = t as { displayName?: string; name?: string };
|
|
47
|
-
return named?.displayName ?? named?.name ?? 'Component';
|
|
48
|
-
});
|
|
49
|
-
console.warn(
|
|
50
|
-
`<Steps> received non-<Step> children: ${labels.join(', ')}. ` +
|
|
51
|
-
'Wrap each step in `<Step title="…">…</Step>` so it renders as a numbered ' +
|
|
52
|
-
'step. Markdown headings inside <Steps> render as plain text.',
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
35
|
export const Steps = memo(function Steps({ children, titleSize = 'p' }: StepsProps) {
|
|
57
36
|
const childrenArray = Children.toArray(children);
|
|
58
37
|
const stepChildren = childrenArray.filter(isStepComponent);
|
|
59
38
|
const totalSteps = stepChildren.length;
|
|
60
|
-
warnAboutNonStepChildren(childrenArray);
|
|
61
39
|
|
|
62
40
|
let stepIndex = 0;
|
|
63
41
|
return (
|
|
@@ -30,7 +30,7 @@ export function Update({ label, description, tags, date, children }: UpdateProps
|
|
|
30
30
|
id={id}
|
|
31
31
|
data-update-label={label}
|
|
32
32
|
data-update-date={date}
|
|
33
|
-
className="my-8 flex flex-col sm:flex-row gap-1 not-prose scroll-mt-20"
|
|
33
|
+
className="my-8 flex flex-col sm:flex-row gap-y-4 sm:gap-y-1 sm:gap-x-1 not-prose scroll-mt-20"
|
|
34
34
|
>
|
|
35
35
|
{/* Date badge - stacked on mobile, left side on desktop */}
|
|
36
36
|
{label && (
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
4
4
|
import { useOnClickOutside } from '@/hooks/useOnClickOutside';
|
|
5
|
+
import { useDelayedNavigationSpinner } from '@/hooks/useDelayedNavigationSpinner';
|
|
5
6
|
import { usePathname, useRouter } from 'next/navigation';
|
|
6
7
|
import type { ResolvedLanguage } from '@/lib/navigation-resolver';
|
|
7
8
|
import type { LanguageCode } from '@/lib/docs-types';
|
|
@@ -41,6 +42,15 @@ export function LanguageSelector({
|
|
|
41
42
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
42
43
|
const listRef = useRef<HTMLUListElement>(null);
|
|
43
44
|
|
|
45
|
+
// 1000ms (vs sidebar's 500ms) — language switches cross more of the RSC
|
|
46
|
+
// tree, so a slightly longer threshold avoids spinner flashes on warm caches
|
|
47
|
+
// while still covering the cache-cold cross-continent case (e.g. Australia
|
|
48
|
+
// hitting the NA-located R2 origin).
|
|
49
|
+
const { pendingPathname, spinnerPathname, onNavigate } =
|
|
50
|
+
useDelayedNavigationSpinner(pathname, 1000);
|
|
51
|
+
const isNavigating = pendingPathname !== null;
|
|
52
|
+
const showSpinner = spinnerPathname !== null;
|
|
53
|
+
|
|
44
54
|
// Find current language
|
|
45
55
|
const currentLanguage = languages.find((l) => l.isActive) || languages[0];
|
|
46
56
|
|
|
@@ -70,9 +80,38 @@ export function LanguageSelector({
|
|
|
70
80
|
// Handle click outside to close
|
|
71
81
|
useOnClickOutside(containerRef, () => setIsOpen(false), isOpen);
|
|
72
82
|
|
|
83
|
+
const handleSelectLanguage = useCallback(
|
|
84
|
+
(lang: ResolvedLanguage) => {
|
|
85
|
+
// Block double-fire while a previous switch is still navigating —
|
|
86
|
+
// the dropdown may still be visually open when the user clicks again.
|
|
87
|
+
if (isNavigating) return;
|
|
88
|
+
|
|
89
|
+
if (lang.code === currentLanguage?.code) {
|
|
90
|
+
setIsOpen(false);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
saveLanguagePreference(lang.code);
|
|
95
|
+
|
|
96
|
+
const basePath = transformLanguagePath(
|
|
97
|
+
pathname || '/docs',
|
|
98
|
+
currentLanguage?.code || actualDefault,
|
|
99
|
+
lang.code,
|
|
100
|
+
actualDefault
|
|
101
|
+
);
|
|
102
|
+
const url = `${linkPrefix}${basePath}`;
|
|
103
|
+
|
|
104
|
+
setIsOpen(false);
|
|
105
|
+
onNavigate(url);
|
|
106
|
+
router.push(url);
|
|
107
|
+
},
|
|
108
|
+
[isNavigating, currentLanguage?.code, actualDefault, pathname, linkPrefix, router, onNavigate]
|
|
109
|
+
);
|
|
110
|
+
|
|
73
111
|
// Handle keyboard navigation
|
|
74
112
|
const handleKeyDown = useCallback(
|
|
75
113
|
(e: React.KeyboardEvent) => {
|
|
114
|
+
if (isNavigating) return;
|
|
76
115
|
switch (e.key) {
|
|
77
116
|
case 'Escape':
|
|
78
117
|
setIsOpen(false);
|
|
@@ -110,7 +149,7 @@ export function LanguageSelector({
|
|
|
110
149
|
break;
|
|
111
150
|
}
|
|
112
151
|
},
|
|
113
|
-
[isOpen, focusedIndex, languages]
|
|
152
|
+
[isOpen, focusedIndex, languages, isNavigating, handleSelectLanguage]
|
|
114
153
|
);
|
|
115
154
|
|
|
116
155
|
// Focus the item when focusedIndex changes
|
|
@@ -121,28 +160,6 @@ export function LanguageSelector({
|
|
|
121
160
|
}
|
|
122
161
|
}, [isOpen, focusedIndex]);
|
|
123
162
|
|
|
124
|
-
// Handle language selection
|
|
125
|
-
const handleSelectLanguage = (lang: ResolvedLanguage) => {
|
|
126
|
-
if (lang.code === currentLanguage?.code) {
|
|
127
|
-
setIsOpen(false);
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Save preference to localStorage
|
|
132
|
-
saveLanguagePreference(lang.code);
|
|
133
|
-
|
|
134
|
-
// Transform path and navigate
|
|
135
|
-
const basePath = transformLanguagePath(
|
|
136
|
-
pathname || '/docs',
|
|
137
|
-
currentLanguage?.code || actualDefault,
|
|
138
|
-
lang.code,
|
|
139
|
-
actualDefault
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
setIsOpen(false);
|
|
143
|
-
router.push(`${linkPrefix}${basePath}`);
|
|
144
|
-
};
|
|
145
|
-
|
|
146
163
|
// Don't render if no languages or only one language
|
|
147
164
|
if (!languages || languages.length <= 1) {
|
|
148
165
|
return null;
|
|
@@ -154,13 +171,15 @@ export function LanguageSelector({
|
|
|
154
171
|
<button
|
|
155
172
|
ref={buttonRef}
|
|
156
173
|
onClick={() => setIsOpen(!isOpen)}
|
|
174
|
+
disabled={isNavigating}
|
|
157
175
|
aria-expanded={isOpen}
|
|
158
176
|
aria-haspopup="listbox"
|
|
159
177
|
aria-label={`${ui.selectLanguage}: ${currentLanguage?.displayName ?? ''}`}
|
|
160
178
|
className={`
|
|
161
|
-
flex items-center gap-2 rounded-lg transition-colors
|
|
179
|
+
flex items-center gap-2 rounded-lg transition-colors
|
|
162
180
|
text-[var(--color-text-secondary)] hover:text-[var(--color-text-primary)]
|
|
163
181
|
hover:bg-[var(--color-bg-tertiary)]
|
|
182
|
+
${isNavigating ? 'cursor-wait opacity-80' : 'cursor-pointer'}
|
|
164
183
|
${compact ? 'px-2 py-1.5' : 'px-3 py-2 w-full'}
|
|
165
184
|
`}
|
|
166
185
|
>
|
|
@@ -177,12 +196,20 @@ export function LanguageSelector({
|
|
|
177
196
|
{currentLanguage?.displayName}
|
|
178
197
|
</span>
|
|
179
198
|
)}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
199
|
+
{showSpinner ? (
|
|
200
|
+
<span
|
|
201
|
+
data-nav-spinner
|
|
202
|
+
aria-hidden="true"
|
|
203
|
+
className="inline-block h-3 w-3 border-2 border-[var(--color-border)] border-t-[var(--color-accent)] rounded-full animate-spin motion-reduce:animate-pulse motion-reduce:[animation-duration:1.5s] flex-shrink-0"
|
|
204
|
+
/>
|
|
205
|
+
) : (
|
|
206
|
+
<i
|
|
207
|
+
className={`fa-solid fa-chevron-${position} text-[10px] text-[var(--color-text-tertiary)] transition-transform ${
|
|
208
|
+
isOpen ? 'rotate-180' : ''
|
|
209
|
+
}`}
|
|
210
|
+
aria-hidden="true"
|
|
211
|
+
/>
|
|
212
|
+
)}
|
|
186
213
|
</button>
|
|
187
214
|
|
|
188
215
|
{/* Dropdown menu */}
|
package/vendored/themes/base.css
CHANGED
|
@@ -828,7 +828,13 @@ pre.shiki[data-line-numbers] .line.diff-remove::after {
|
|
|
828
828
|
|
|
829
829
|
/* Update component content area */
|
|
830
830
|
.update-content {
|
|
831
|
-
margin-top:
|
|
831
|
+
margin-top: 0 !important;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
@media (min-width: 640px) {
|
|
835
|
+
.update-content {
|
|
836
|
+
margin-top: -4px !important;
|
|
837
|
+
}
|
|
832
838
|
}
|
|
833
839
|
|
|
834
840
|
.update-content,
|
|
@@ -1313,4 +1319,3 @@ iframe {
|
|
|
1313
1319
|
cursor: auto;
|
|
1314
1320
|
}
|
|
1315
1321
|
}
|
|
1316
|
-
|
|
@@ -172,41 +172,10 @@
|
|
|
172
172
|
"integrity": "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==",
|
|
173
173
|
"license": "MIT"
|
|
174
174
|
},
|
|
175
|
-
"node_modules/@chevrotain/cst-dts-gen": {
|
|
176
|
-
"version": "12.0.0",
|
|
177
|
-
"resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-12.0.0.tgz",
|
|
178
|
-
"integrity": "sha512-fSL4KXjTl7cDgf0B5Rip9Q05BOrYvkJV/RrBTE/bKDN096E4hN/ySpcBK5B24T76dlQ2i32Zc3PAE27jFnFrKg==",
|
|
179
|
-
"license": "Apache-2.0",
|
|
180
|
-
"dependencies": {
|
|
181
|
-
"@chevrotain/gast": "12.0.0",
|
|
182
|
-
"@chevrotain/types": "12.0.0"
|
|
183
|
-
}
|
|
184
|
-
},
|
|
185
|
-
"node_modules/@chevrotain/gast": {
|
|
186
|
-
"version": "12.0.0",
|
|
187
|
-
"resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-12.0.0.tgz",
|
|
188
|
-
"integrity": "sha512-1ne/m3XsIT8aEdrvT33so0GUC+wkctpUPK6zU9IlOyJLUbR0rg4G7ZiApiJbggpgPir9ERy3FRjT6T7lpgetnQ==",
|
|
189
|
-
"license": "Apache-2.0",
|
|
190
|
-
"dependencies": {
|
|
191
|
-
"@chevrotain/types": "12.0.0"
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
"node_modules/@chevrotain/regexp-to-ast": {
|
|
195
|
-
"version": "12.0.0",
|
|
196
|
-
"resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-12.0.0.tgz",
|
|
197
|
-
"integrity": "sha512-p+EW9MaJwgaHguhoqwOtx/FwuGr+DnNn857sXWOi/mClXIkPGl3rn7hGNWvo31HA3vyeQxjqe+H36yZJwYU8cA==",
|
|
198
|
-
"license": "Apache-2.0"
|
|
199
|
-
},
|
|
200
175
|
"node_modules/@chevrotain/types": {
|
|
201
|
-
"version": "
|
|
202
|
-
"resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-
|
|
203
|
-
"integrity": "sha512-
|
|
204
|
-
"license": "Apache-2.0"
|
|
205
|
-
},
|
|
206
|
-
"node_modules/@chevrotain/utils": {
|
|
207
|
-
"version": "12.0.0",
|
|
208
|
-
"resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-12.0.0.tgz",
|
|
209
|
-
"integrity": "sha512-lB59uJoaGIfOOL9knQqQRfhl9g7x8/wqFkp13zTdkRu1huG9kg6IJs1O8hqj9rs6h7orGxHJUKb+mX3rPbWGhA==",
|
|
176
|
+
"version": "11.1.2",
|
|
177
|
+
"resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.1.2.tgz",
|
|
178
|
+
"integrity": "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==",
|
|
210
179
|
"license": "Apache-2.0"
|
|
211
180
|
},
|
|
212
181
|
"node_modules/@emnapi/runtime": {
|
|
@@ -920,12 +889,12 @@
|
|
|
920
889
|
}
|
|
921
890
|
},
|
|
922
891
|
"node_modules/@mermaid-js/parser": {
|
|
923
|
-
"version": "1.1.
|
|
924
|
-
"resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.1.
|
|
925
|
-
"integrity": "sha512-
|
|
892
|
+
"version": "1.1.1",
|
|
893
|
+
"resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.1.1.tgz",
|
|
894
|
+
"integrity": "sha512-VuHdsYMK1bT6X2JbcAaWAhugTRvRBRyuZgd+c22swUeI9g/ntaxF7CY7dYarhZovofCbUNO0G7JesfmNtjYOCw==",
|
|
926
895
|
"license": "MIT",
|
|
927
896
|
"dependencies": {
|
|
928
|
-
"
|
|
897
|
+
"@chevrotain/types": "~11.1.1"
|
|
929
898
|
}
|
|
930
899
|
},
|
|
931
900
|
"node_modules/@msgpack/msgpack": {
|
|
@@ -2297,34 +2266,6 @@
|
|
|
2297
2266
|
"url": "https://github.com/sponsors/wooorm"
|
|
2298
2267
|
}
|
|
2299
2268
|
},
|
|
2300
|
-
"node_modules/chevrotain": {
|
|
2301
|
-
"version": "12.0.0",
|
|
2302
|
-
"resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-12.0.0.tgz",
|
|
2303
|
-
"integrity": "sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ==",
|
|
2304
|
-
"license": "Apache-2.0",
|
|
2305
|
-
"dependencies": {
|
|
2306
|
-
"@chevrotain/cst-dts-gen": "12.0.0",
|
|
2307
|
-
"@chevrotain/gast": "12.0.0",
|
|
2308
|
-
"@chevrotain/regexp-to-ast": "12.0.0",
|
|
2309
|
-
"@chevrotain/types": "12.0.0",
|
|
2310
|
-
"@chevrotain/utils": "12.0.0"
|
|
2311
|
-
},
|
|
2312
|
-
"engines": {
|
|
2313
|
-
"node": ">=22.0.0"
|
|
2314
|
-
}
|
|
2315
|
-
},
|
|
2316
|
-
"node_modules/chevrotain-allstar": {
|
|
2317
|
-
"version": "0.4.3",
|
|
2318
|
-
"resolved": "https://registry.npmjs.org/chevrotain-allstar/-/chevrotain-allstar-0.4.3.tgz",
|
|
2319
|
-
"integrity": "sha512-2X4mkroolSMKqW+H22pyPMUVDqYZzPhephTmg/NODKb1IGYPHfxfhcW0EjS7wcPJNbze2i4vBWT7zT5FKF2lrQ==",
|
|
2320
|
-
"license": "MIT",
|
|
2321
|
-
"dependencies": {
|
|
2322
|
-
"lodash-es": "^4.18.1"
|
|
2323
|
-
},
|
|
2324
|
-
"peerDependencies": {
|
|
2325
|
-
"chevrotain": "^12.0.0"
|
|
2326
|
-
}
|
|
2327
|
-
},
|
|
2328
2269
|
"node_modules/client-only": {
|
|
2329
2270
|
"version": "0.0.1",
|
|
2330
2271
|
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
|
@@ -2993,9 +2934,9 @@
|
|
|
2993
2934
|
"license": "ISC"
|
|
2994
2935
|
},
|
|
2995
2936
|
"node_modules/enhanced-resolve": {
|
|
2996
|
-
"version": "5.21.
|
|
2997
|
-
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.
|
|
2998
|
-
"integrity": "sha512-
|
|
2937
|
+
"version": "5.21.3",
|
|
2938
|
+
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.3.tgz",
|
|
2939
|
+
"integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==",
|
|
2999
2940
|
"license": "MIT",
|
|
3000
2941
|
"dependencies": {
|
|
3001
2942
|
"graceful-fs": "^4.2.4",
|
|
@@ -3017,6 +2958,16 @@
|
|
|
3017
2958
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
|
3018
2959
|
}
|
|
3019
2960
|
},
|
|
2961
|
+
"node_modules/es-toolkit": {
|
|
2962
|
+
"version": "1.46.1",
|
|
2963
|
+
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.46.1.tgz",
|
|
2964
|
+
"integrity": "sha512-5eNtXOs3tbfxXOj04tjjseeWkRWaoCjdEI+96DgwzZoe6c9juL49pXlzAFTI72aWC9Y8p7168g6XIKjh7k6pyQ==",
|
|
2965
|
+
"license": "MIT",
|
|
2966
|
+
"workspaces": [
|
|
2967
|
+
"docs",
|
|
2968
|
+
"benchmarks"
|
|
2969
|
+
]
|
|
2970
|
+
},
|
|
3020
2971
|
"node_modules/esast-util-from-estree": {
|
|
3021
2972
|
"version": "2.0.0",
|
|
3022
2973
|
"resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz",
|
|
@@ -3817,24 +3768,6 @@
|
|
|
3817
3768
|
"node": ">=0.10.0"
|
|
3818
3769
|
}
|
|
3819
3770
|
},
|
|
3820
|
-
"node_modules/langium": {
|
|
3821
|
-
"version": "4.2.3",
|
|
3822
|
-
"resolved": "https://registry.npmjs.org/langium/-/langium-4.2.3.tgz",
|
|
3823
|
-
"integrity": "sha512-sOPIi4hISFnY7twwV97ca1TsxpBtXq0URu/LL1AvxwccPG/RIBBlKS7a/f/EL6w8lTNaS0EFs/F+IdSOaqYpng==",
|
|
3824
|
-
"license": "MIT",
|
|
3825
|
-
"dependencies": {
|
|
3826
|
-
"@chevrotain/regexp-to-ast": "~12.0.0",
|
|
3827
|
-
"chevrotain": "~12.0.0",
|
|
3828
|
-
"chevrotain-allstar": "~0.4.3",
|
|
3829
|
-
"vscode-languageserver": "~9.0.1",
|
|
3830
|
-
"vscode-languageserver-textdocument": "~1.0.11",
|
|
3831
|
-
"vscode-uri": "~3.1.0"
|
|
3832
|
-
},
|
|
3833
|
-
"engines": {
|
|
3834
|
-
"node": ">=20.10.0",
|
|
3835
|
-
"npm": ">=10.2.3"
|
|
3836
|
-
}
|
|
3837
|
-
},
|
|
3838
3771
|
"node_modules/layout-base": {
|
|
3839
3772
|
"version": "1.0.2",
|
|
3840
3773
|
"resolved": "https://registry.npmjs.org/layout-base/-/layout-base-1.0.2.tgz",
|
|
@@ -4501,14 +4434,14 @@
|
|
|
4501
4434
|
}
|
|
4502
4435
|
},
|
|
4503
4436
|
"node_modules/mermaid": {
|
|
4504
|
-
"version": "11.
|
|
4505
|
-
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.
|
|
4506
|
-
"integrity": "sha512-
|
|
4437
|
+
"version": "11.15.0",
|
|
4438
|
+
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.15.0.tgz",
|
|
4439
|
+
"integrity": "sha512-pTMbcf3rWdtLiYGpmoTjHEpeY8seiy6sR+9nD7LOs8KfUbHE4lOUAprTRqRAcWSQ6MQpdX+YEsxShtGsINtPtw==",
|
|
4507
4440
|
"license": "MIT",
|
|
4508
4441
|
"dependencies": {
|
|
4509
4442
|
"@braintree/sanitize-url": "^7.1.1",
|
|
4510
4443
|
"@iconify/utils": "^3.0.2",
|
|
4511
|
-
"@mermaid-js/parser": "^1.1.
|
|
4444
|
+
"@mermaid-js/parser": "^1.1.1",
|
|
4512
4445
|
"@types/d3": "^7.4.3",
|
|
4513
4446
|
"@upsetjs/venn.js": "^2.0.0",
|
|
4514
4447
|
"cytoscape": "^3.33.1",
|
|
@@ -4519,14 +4452,14 @@
|
|
|
4519
4452
|
"dagre-d3-es": "7.0.14",
|
|
4520
4453
|
"dayjs": "^1.11.19",
|
|
4521
4454
|
"dompurify": "^3.3.1",
|
|
4455
|
+
"es-toolkit": "^1.45.1",
|
|
4522
4456
|
"katex": "^0.16.25",
|
|
4523
4457
|
"khroma": "^2.1.0",
|
|
4524
|
-
"lodash-es": "^4.17.23",
|
|
4525
4458
|
"marked": "^16.3.0",
|
|
4526
4459
|
"roughjs": "^4.6.6",
|
|
4527
4460
|
"stylis": "^4.3.6",
|
|
4528
4461
|
"ts-dedent": "^2.2.0",
|
|
4529
|
-
"uuid": "^11.1.0"
|
|
4462
|
+
"uuid": "^11.1.0 || ^12 || ^13 || ^14.0.0"
|
|
4530
4463
|
}
|
|
4531
4464
|
},
|
|
4532
4465
|
"node_modules/micromark": {
|
|
@@ -6567,16 +6500,16 @@
|
|
|
6567
6500
|
"license": "MIT"
|
|
6568
6501
|
},
|
|
6569
6502
|
"node_modules/uuid": {
|
|
6570
|
-
"version": "
|
|
6571
|
-
"resolved": "https://registry.npmjs.org/uuid/-/uuid-
|
|
6572
|
-
"integrity": "sha512-
|
|
6503
|
+
"version": "14.0.0",
|
|
6504
|
+
"resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.0.tgz",
|
|
6505
|
+
"integrity": "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg==",
|
|
6573
6506
|
"funding": [
|
|
6574
6507
|
"https://github.com/sponsors/broofa",
|
|
6575
6508
|
"https://github.com/sponsors/ctavan"
|
|
6576
6509
|
],
|
|
6577
6510
|
"license": "MIT",
|
|
6578
6511
|
"bin": {
|
|
6579
|
-
"uuid": "dist/
|
|
6512
|
+
"uuid": "dist-node/bin/uuid"
|
|
6580
6513
|
}
|
|
6581
6514
|
},
|
|
6582
6515
|
"node_modules/vfile": {
|
|
@@ -6635,55 +6568,6 @@
|
|
|
6635
6568
|
"url": "https://opencollective.com/unified"
|
|
6636
6569
|
}
|
|
6637
6570
|
},
|
|
6638
|
-
"node_modules/vscode-jsonrpc": {
|
|
6639
|
-
"version": "8.2.0",
|
|
6640
|
-
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz",
|
|
6641
|
-
"integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==",
|
|
6642
|
-
"license": "MIT",
|
|
6643
|
-
"engines": {
|
|
6644
|
-
"node": ">=14.0.0"
|
|
6645
|
-
}
|
|
6646
|
-
},
|
|
6647
|
-
"node_modules/vscode-languageserver": {
|
|
6648
|
-
"version": "9.0.1",
|
|
6649
|
-
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz",
|
|
6650
|
-
"integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==",
|
|
6651
|
-
"license": "MIT",
|
|
6652
|
-
"dependencies": {
|
|
6653
|
-
"vscode-languageserver-protocol": "3.17.5"
|
|
6654
|
-
},
|
|
6655
|
-
"bin": {
|
|
6656
|
-
"installServerIntoExtension": "bin/installServerIntoExtension"
|
|
6657
|
-
}
|
|
6658
|
-
},
|
|
6659
|
-
"node_modules/vscode-languageserver-protocol": {
|
|
6660
|
-
"version": "3.17.5",
|
|
6661
|
-
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz",
|
|
6662
|
-
"integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==",
|
|
6663
|
-
"license": "MIT",
|
|
6664
|
-
"dependencies": {
|
|
6665
|
-
"vscode-jsonrpc": "8.2.0",
|
|
6666
|
-
"vscode-languageserver-types": "3.17.5"
|
|
6667
|
-
}
|
|
6668
|
-
},
|
|
6669
|
-
"node_modules/vscode-languageserver-textdocument": {
|
|
6670
|
-
"version": "1.0.12",
|
|
6671
|
-
"resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz",
|
|
6672
|
-
"integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==",
|
|
6673
|
-
"license": "MIT"
|
|
6674
|
-
},
|
|
6675
|
-
"node_modules/vscode-languageserver-types": {
|
|
6676
|
-
"version": "3.17.5",
|
|
6677
|
-
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz",
|
|
6678
|
-
"integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==",
|
|
6679
|
-
"license": "MIT"
|
|
6680
|
-
},
|
|
6681
|
-
"node_modules/vscode-uri": {
|
|
6682
|
-
"version": "3.1.0",
|
|
6683
|
-
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz",
|
|
6684
|
-
"integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
|
|
6685
|
-
"license": "MIT"
|
|
6686
|
-
},
|
|
6687
6571
|
"node_modules/web-namespaces": {
|
|
6688
6572
|
"version": "2.0.1",
|
|
6689
6573
|
"resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz",
|
|
@@ -6695,9 +6579,9 @@
|
|
|
6695
6579
|
}
|
|
6696
6580
|
},
|
|
6697
6581
|
"node_modules/yaml": {
|
|
6698
|
-
"version": "2.
|
|
6699
|
-
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.
|
|
6700
|
-
"integrity": "sha512-
|
|
6582
|
+
"version": "2.9.0",
|
|
6583
|
+
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
|
|
6584
|
+
"integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
|
|
6701
6585
|
"license": "ISC",
|
|
6702
6586
|
"bin": {
|
|
6703
6587
|
"yaml": "bin.mjs"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dev-workspace-symlinks.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/dev-workspace-symlinks.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @vitest-environment node
|
|
3
|
-
*
|
|
4
|
-
* Tests prepareProjectWorkspaceLinks — replaces the single
|
|
5
|
-
* <workspace>/projects/<name> -> <projectDir> symlink with per-entry
|
|
6
|
-
* symlinks that skip non-active language directories. This is what
|
|
7
|
-
* actually reduces Turbopack's filesystem scan from 403 MDX files to
|
|
8
|
-
* 135 on jamdesk-docs.
|
|
9
|
-
*/
|
|
10
|
-
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
11
|
-
import fs from 'fs-extra';
|
|
12
|
-
import path from 'path';
|
|
13
|
-
import { tmpdir } from 'os';
|
|
14
|
-
import { prepareProjectWorkspaceLinks } from '../../commands/dev.js';
|
|
15
|
-
import { output } from '../../lib/output.js';
|
|
16
|
-
describe('prepareProjectWorkspaceLinks', () => {
|
|
17
|
-
let tmpRoot;
|
|
18
|
-
let projectDir;
|
|
19
|
-
let workspaceProjectDir;
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
tmpRoot = fs.mkdtempSync(path.join(tmpdir(), 'jam-ws-'));
|
|
22
|
-
projectDir = path.join(tmpRoot, 'project');
|
|
23
|
-
workspaceProjectDir = path.join(tmpRoot, 'ws', 'projects', 'project');
|
|
24
|
-
// Set up a project layout that mirrors a multi-language docs project:
|
|
25
|
-
// project/
|
|
26
|
-
// ai/intro.mdx (en at root)
|
|
27
|
-
// development/foo.mdx (en at root)
|
|
28
|
-
// es/ai/intro.mdx (spanish)
|
|
29
|
-
// fr/ai/intro.mdx (french)
|
|
30
|
-
// docs.json
|
|
31
|
-
// images/logo.png
|
|
32
|
-
fs.mkdirpSync(path.join(projectDir, 'ai'));
|
|
33
|
-
fs.writeFileSync(path.join(projectDir, 'ai', 'intro.mdx'), '# en');
|
|
34
|
-
fs.mkdirpSync(path.join(projectDir, 'development'));
|
|
35
|
-
fs.writeFileSync(path.join(projectDir, 'development', 'foo.mdx'), '# en');
|
|
36
|
-
fs.mkdirpSync(path.join(projectDir, 'es', 'ai'));
|
|
37
|
-
fs.writeFileSync(path.join(projectDir, 'es', 'ai', 'intro.mdx'), '# es');
|
|
38
|
-
fs.mkdirpSync(path.join(projectDir, 'fr', 'ai'));
|
|
39
|
-
fs.writeFileSync(path.join(projectDir, 'fr', 'ai', 'intro.mdx'), '# fr');
|
|
40
|
-
fs.writeFileSync(path.join(projectDir, 'docs.json'), '{}');
|
|
41
|
-
fs.mkdirpSync(path.join(projectDir, 'images'));
|
|
42
|
-
fs.writeFileSync(path.join(projectDir, 'images', 'logo.png'), '');
|
|
43
|
-
});
|
|
44
|
-
afterEach(() => {
|
|
45
|
-
fs.removeSync(tmpRoot);
|
|
46
|
-
});
|
|
47
|
-
it('symlinks every top-level entry when skip set is empty', async () => {
|
|
48
|
-
await prepareProjectWorkspaceLinks(projectDir, workspaceProjectDir, new Set());
|
|
49
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'ai', 'intro.mdx'))).toBe(true);
|
|
50
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'es', 'ai', 'intro.mdx'))).toBe(true);
|
|
51
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'fr', 'ai', 'intro.mdx'))).toBe(true);
|
|
52
|
-
});
|
|
53
|
-
it('does not symlink docs.json (caller writes a filtered copy)', async () => {
|
|
54
|
-
// docs.json must not be symlinked — the caller writes a per-language
|
|
55
|
-
// filtered copy, and fs.writeFile through a symlink would clobber the
|
|
56
|
-
// user's source docs.json.
|
|
57
|
-
await prepareProjectWorkspaceLinks(projectDir, workspaceProjectDir, new Set());
|
|
58
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'docs.json'))).toBe(false);
|
|
59
|
-
});
|
|
60
|
-
it('skips entries whose names are in the skip set', async () => {
|
|
61
|
-
await prepareProjectWorkspaceLinks(projectDir, workspaceProjectDir, new Set(['es', 'fr']));
|
|
62
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'ai', 'intro.mdx'))).toBe(true);
|
|
63
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'development', 'foo.mdx'))).toBe(true);
|
|
64
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'images', 'logo.png'))).toBe(true);
|
|
65
|
-
// Skipped:
|
|
66
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'es'))).toBe(false);
|
|
67
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'fr'))).toBe(false);
|
|
68
|
-
// docs.json not symlinked — caller writes a filtered copy.
|
|
69
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'docs.json'))).toBe(false);
|
|
70
|
-
});
|
|
71
|
-
it('rebuilds the workspace links from scratch on subsequent calls', async () => {
|
|
72
|
-
// First call: no skip
|
|
73
|
-
await prepareProjectWorkspaceLinks(projectDir, workspaceProjectDir, new Set());
|
|
74
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'es'))).toBe(true);
|
|
75
|
-
// Second call: skip es
|
|
76
|
-
await prepareProjectWorkspaceLinks(projectDir, workspaceProjectDir, new Set(['es']));
|
|
77
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'es'))).toBe(false);
|
|
78
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'fr'))).toBe(true);
|
|
79
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'ai', 'intro.mdx'))).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
it('handles a pre-existing single symlink at workspaceProjectDir (legacy layout)', async () => {
|
|
82
|
-
// Pre-create the legacy single-symlink layout
|
|
83
|
-
fs.mkdirpSync(path.dirname(workspaceProjectDir));
|
|
84
|
-
fs.symlinkSync(projectDir, workspaceProjectDir, 'junction');
|
|
85
|
-
await prepareProjectWorkspaceLinks(projectDir, workspaceProjectDir, new Set(['es', 'fr']));
|
|
86
|
-
const lstat = fs.lstatSync(workspaceProjectDir);
|
|
87
|
-
expect(lstat.isDirectory()).toBe(true);
|
|
88
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'ai', 'intro.mdx'))).toBe(true);
|
|
89
|
-
expect(fs.existsSync(path.join(workspaceProjectDir, 'es'))).toBe(false);
|
|
90
|
-
});
|
|
91
|
-
it('surfaces friendly error (not raw stack trace) when fs.rm throws ENOTEMPTY', async () => {
|
|
92
|
-
// Regression: before safeRemoveCache, fs.remove raised an unfriendly stack
|
|
93
|
-
// trace when Turbopack still held open files. Now safeRemoveCache detects
|
|
94
|
-
// the race and calls process.exit(1) with a human-readable message.
|
|
95
|
-
const rmSpy = vi.spyOn(fs, 'rm');
|
|
96
|
-
const exitSpy = vi.spyOn(process, 'exit').mockImplementation(((code) => {
|
|
97
|
-
throw new Error(`process.exit:${code}`);
|
|
98
|
-
}));
|
|
99
|
-
const errorSpy = vi.spyOn(output, 'error').mockImplementation(() => undefined);
|
|
100
|
-
const enotempty = Object.assign(new Error('ENOTEMPTY'), { code: 'ENOTEMPTY' });
|
|
101
|
-
// fs.rm will be called by safeRemoveCache; make it fail with ENOTEMPTY
|
|
102
|
-
// even after the internal maxRetries — simulate persistent race condition.
|
|
103
|
-
rmSpy.mockRejectedValue(enotempty);
|
|
104
|
-
await expect(prepareProjectWorkspaceLinks(projectDir, workspaceProjectDir, new Set())).rejects.toThrow('process.exit:1');
|
|
105
|
-
const msg = errorSpy.mock.calls[0]?.[0] ?? '';
|
|
106
|
-
expect(msg).toContain('Another `jamdesk dev` instance');
|
|
107
|
-
expect(msg).toContain('pkill -f');
|
|
108
|
-
expect(exitSpy).toHaveBeenCalledWith(1);
|
|
109
|
-
vi.restoreAllMocks();
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
//# sourceMappingURL=dev-workspace-symlinks.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"dev-workspace-symlinks.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/dev-workspace-symlinks.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"language-filter.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/language-filter.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @vitest-environment node
|
|
3
|
-
*
|
|
4
|
-
* Tests for getActiveLanguageFilter — pure helper that decides which
|
|
5
|
-
* top-level language directories to skip when symlinking project content
|
|
6
|
-
* into the dev workspace. Multi-language sites' non-default languages
|
|
7
|
-
* inflate Turbopack's filesystem scan and balloon cold compile time
|
|
8
|
-
* (jamdesk-docs: 67s with 3 langs vs. 12.5s with 1 lang).
|
|
9
|
-
*/
|
|
10
|
-
import { describe, it, expect } from 'vitest';
|
|
11
|
-
import { getActiveLanguageFilter, isPageInSkippedLanguage, filterConfigByActiveLanguage, } from '../../lib/language-filter.js';
|
|
12
|
-
const config = (langs) => ({
|
|
13
|
-
navigation: { languages: langs.map(l => ({ language: l.language, default: l.default })) },
|
|
14
|
-
});
|
|
15
|
-
describe('getActiveLanguageFilter', () => {
|
|
16
|
-
it('returns null filter when project has no languages array', () => {
|
|
17
|
-
const result = getActiveLanguageFilter({ navigation: {} }, undefined, false);
|
|
18
|
-
expect(result).toEqual({ active: null, skip: new Set() });
|
|
19
|
-
});
|
|
20
|
-
it('returns null filter when project has only one language', () => {
|
|
21
|
-
const result = getActiveLanguageFilter(config([{ language: 'en', default: true }]), undefined, false);
|
|
22
|
-
expect(result).toEqual({ active: 'en', skip: new Set() });
|
|
23
|
-
});
|
|
24
|
-
it('skips non-default languages when active is the default', () => {
|
|
25
|
-
const result = getActiveLanguageFilter(config([
|
|
26
|
-
{ language: 'en', default: true },
|
|
27
|
-
{ language: 'es' },
|
|
28
|
-
{ language: 'fr' },
|
|
29
|
-
]), undefined, false);
|
|
30
|
-
expect(result.active).toBe('en');
|
|
31
|
-
expect(result.skip).toEqual(new Set(['es', 'fr']));
|
|
32
|
-
});
|
|
33
|
-
it('falls back to first language when none is marked default', () => {
|
|
34
|
-
const result = getActiveLanguageFilter(config([{ language: 'en' }, { language: 'es' }, { language: 'fr' }]), undefined, false);
|
|
35
|
-
expect(result.active).toBe('en');
|
|
36
|
-
expect(result.skip).toEqual(new Set(['es', 'fr']));
|
|
37
|
-
});
|
|
38
|
-
it('accepts --lang matching the default language (no-op equivalence)', () => {
|
|
39
|
-
const result = getActiveLanguageFilter(config([
|
|
40
|
-
{ language: 'en', default: true },
|
|
41
|
-
{ language: 'es' },
|
|
42
|
-
]), 'en', false);
|
|
43
|
-
expect(result.active).toBe('en');
|
|
44
|
-
expect(result.skip).toEqual(new Set(['es']));
|
|
45
|
-
});
|
|
46
|
-
it('throws on --lang for a non-default language (initial release scope)', () => {
|
|
47
|
-
// Non-default-language layouts mix root-level default-lang content with
|
|
48
|
-
// <lang>/ subdirs for translations; correctly stripping the default
|
|
49
|
-
// content while keeping <lang>/ takes more work and is deferred to a
|
|
50
|
-
// follow-up. For now, surface the workaround clearly.
|
|
51
|
-
expect(() => getActiveLanguageFilter(config([
|
|
52
|
-
{ language: 'en', default: true },
|
|
53
|
-
{ language: 'es' },
|
|
54
|
-
{ language: 'fr' },
|
|
55
|
-
]), 'es', false)).toThrow(/--lang es: previewing non-default languages.*--all-langs/i);
|
|
56
|
-
});
|
|
57
|
-
it('returns empty skip set when --all-langs is set', () => {
|
|
58
|
-
const result = getActiveLanguageFilter(config([
|
|
59
|
-
{ language: 'en', default: true },
|
|
60
|
-
{ language: 'es' },
|
|
61
|
-
]), undefined, true);
|
|
62
|
-
expect(result.active).toBe('en');
|
|
63
|
-
expect(result.skip).toEqual(new Set());
|
|
64
|
-
});
|
|
65
|
-
it('throws on --lang code that does not exist in docs.json', () => {
|
|
66
|
-
expect(() => getActiveLanguageFilter(config([{ language: 'en', default: true }, { language: 'es' }]), 'de', false)).toThrow(/--lang de.*not.*docs\.json.*Available: en, es/);
|
|
67
|
-
});
|
|
68
|
-
it('handles malformed languages array (entries missing language field) by ignoring them', () => {
|
|
69
|
-
const malformed = {
|
|
70
|
-
navigation: {
|
|
71
|
-
languages: [
|
|
72
|
-
{ language: 'en', default: true },
|
|
73
|
-
{ default: false }, // missing language: ignored
|
|
74
|
-
{ language: 'es' },
|
|
75
|
-
{ language: 42 }, // wrong type: ignored
|
|
76
|
-
],
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
const result = getActiveLanguageFilter(malformed, undefined, false);
|
|
80
|
-
expect(result.active).toBe('en');
|
|
81
|
-
expect(result.skip).toEqual(new Set(['es']));
|
|
82
|
-
});
|
|
83
|
-
it('returns null active when no valid language entries exist', () => {
|
|
84
|
-
const result = getActiveLanguageFilter({ navigation: { languages: [{ default: true }] } }, undefined, false);
|
|
85
|
-
expect(result).toEqual({ active: null, skip: new Set() });
|
|
86
|
-
});
|
|
87
|
-
it('rejects empty-string --lang as an invalid code (commander passes "" through)', () => {
|
|
88
|
-
// commander.js treats `--lang ""` as a value, not as missing — so
|
|
89
|
-
// langOption is "" (defined, but empty). Empty string is never a valid
|
|
90
|
-
// language code; surface it as a clear error rather than silently
|
|
91
|
-
// falling back to the default.
|
|
92
|
-
expect(() => getActiveLanguageFilter(config([{ language: 'en', default: true }, { language: 'es' }]), '', false)).toThrow(/--lang.*not.*docs\.json/);
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
describe('isPageInSkippedLanguage', () => {
|
|
96
|
-
it('returns false when skip set is empty', () => {
|
|
97
|
-
expect(isPageInSkippedLanguage('fr/introduction', new Set())).toBe(false);
|
|
98
|
-
});
|
|
99
|
-
it('returns true when first path segment is a skipped language', () => {
|
|
100
|
-
expect(isPageInSkippedLanguage('fr/introduction', new Set(['fr']))).toBe(true);
|
|
101
|
-
});
|
|
102
|
-
it('returns true for nested paths inside a skipped language', () => {
|
|
103
|
-
expect(isPageInSkippedLanguage('fr/setup/connecting-github', new Set(['fr', 'de']))).toBe(true);
|
|
104
|
-
});
|
|
105
|
-
it('returns false when first segment is the active language', () => {
|
|
106
|
-
expect(isPageInSkippedLanguage('en/introduction', new Set(['fr']))).toBe(false);
|
|
107
|
-
});
|
|
108
|
-
it('returns false for unprefixed root pages', () => {
|
|
109
|
-
expect(isPageInSkippedLanguage('introduction', new Set(['fr']))).toBe(false);
|
|
110
|
-
});
|
|
111
|
-
it('does not match when the skip code is a prefix-substring of a different segment', () => {
|
|
112
|
-
// Guard against startsWith('fr/') matching e.g. 'fr-something/foo'
|
|
113
|
-
expect(isPageInSkippedLanguage('fr-something/foo', new Set(['fr']))).toBe(false);
|
|
114
|
-
});
|
|
115
|
-
it('returns true for a path with a fragment anchor in a skipped language', () => {
|
|
116
|
-
// Broken-anchor warnings from validate-links.cjs surface as link values
|
|
117
|
-
// like `fr/introduction#missing-section` — the fragment lives past the
|
|
118
|
-
// first segment so the language check still works.
|
|
119
|
-
expect(isPageInSkippedLanguage('fr/introduction#setup', new Set(['fr']))).toBe(true);
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
describe('filterConfigByActiveLanguage', () => {
|
|
123
|
-
it('returns the input unchanged (same reference) when skip is empty', () => {
|
|
124
|
-
const config = { name: 'foo', navigation: { languages: [{ language: 'en' }] } };
|
|
125
|
-
const result = filterConfigByActiveLanguage(config, { active: 'en', skip: new Set() });
|
|
126
|
-
expect(result).toBe(config);
|
|
127
|
-
});
|
|
128
|
-
it('drops skipped languages from navigation.languages', () => {
|
|
129
|
-
const config = {
|
|
130
|
-
name: 'jamdesk-docs',
|
|
131
|
-
navigation: {
|
|
132
|
-
languages: [
|
|
133
|
-
{ language: 'en', default: true, tabs: [{ tab: 'Guide' }] },
|
|
134
|
-
{ language: 'fr', tabs: [{ tab: 'Guide' }] },
|
|
135
|
-
{ language: 'de', tabs: [{ tab: 'Guide' }] },
|
|
136
|
-
],
|
|
137
|
-
},
|
|
138
|
-
};
|
|
139
|
-
const result = filterConfigByActiveLanguage(config, {
|
|
140
|
-
active: 'en',
|
|
141
|
-
skip: new Set(['fr', 'de']),
|
|
142
|
-
});
|
|
143
|
-
expect(result.navigation.languages).toEqual([
|
|
144
|
-
{ language: 'en', default: true, tabs: [{ tab: 'Guide' }] },
|
|
145
|
-
]);
|
|
146
|
-
// Top-level fields preserved.
|
|
147
|
-
expect(result.name).toBe('jamdesk-docs');
|
|
148
|
-
// Original config untouched.
|
|
149
|
-
expect(config.navigation.languages).toHaveLength(3);
|
|
150
|
-
});
|
|
151
|
-
it('preserves other navigation fields (tabs, global, anchors, etc.)', () => {
|
|
152
|
-
const config = {
|
|
153
|
-
navigation: {
|
|
154
|
-
languages: [{ language: 'en' }, { language: 'fr' }],
|
|
155
|
-
global: { anchors: [{ anchor: 'Support' }] },
|
|
156
|
-
},
|
|
157
|
-
};
|
|
158
|
-
const result = filterConfigByActiveLanguage(config, {
|
|
159
|
-
active: 'en',
|
|
160
|
-
skip: new Set(['fr']),
|
|
161
|
-
});
|
|
162
|
-
expect(result.navigation.global).toEqual({ anchors: [{ anchor: 'Support' }] });
|
|
163
|
-
expect(result.navigation.languages).toHaveLength(1);
|
|
164
|
-
});
|
|
165
|
-
});
|
|
166
|
-
//# sourceMappingURL=language-filter.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"language-filter.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/language-filter.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"output.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/unit/output.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @vitest-environment node
|
|
3
|
-
*
|
|
4
|
-
* Unit tests for output.runWithSlowHint. Covers the close race where
|
|
5
|
-
* the timer fires on the same tick as the work resolving — `done`
|
|
6
|
-
* must short-circuit the callback to avoid a stale hint after success.
|
|
7
|
-
*/
|
|
8
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
9
|
-
import { output } from '../../lib/output.js';
|
|
10
|
-
describe('output.runWithSlowHint', () => {
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
vi.useFakeTimers();
|
|
13
|
-
});
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
vi.useRealTimers();
|
|
16
|
-
});
|
|
17
|
-
it('does not fire onSlow when work resolves before the threshold', async () => {
|
|
18
|
-
const onSlow = vi.fn();
|
|
19
|
-
const promise = output.runWithSlowHint(1000, onSlow, async () => {
|
|
20
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
21
|
-
return 'done';
|
|
22
|
-
});
|
|
23
|
-
await vi.advanceTimersByTimeAsync(500);
|
|
24
|
-
const result = await promise;
|
|
25
|
-
expect(result).toBe('done');
|
|
26
|
-
expect(onSlow).not.toHaveBeenCalled();
|
|
27
|
-
// Run any pending timers to confirm the hint stays suppressed even
|
|
28
|
-
// if the cleanup happened to lose the clearTimeout race.
|
|
29
|
-
await vi.advanceTimersByTimeAsync(2000);
|
|
30
|
-
expect(onSlow).not.toHaveBeenCalled();
|
|
31
|
-
});
|
|
32
|
-
it('fires onSlow exactly once when work runs past the threshold', async () => {
|
|
33
|
-
const onSlow = vi.fn();
|
|
34
|
-
const promise = output.runWithSlowHint(1000, onSlow, async () => {
|
|
35
|
-
await new Promise((r) => setTimeout(r, 3000));
|
|
36
|
-
return 42;
|
|
37
|
-
});
|
|
38
|
-
await vi.advanceTimersByTimeAsync(1000);
|
|
39
|
-
expect(onSlow).toHaveBeenCalledTimes(1);
|
|
40
|
-
await vi.advanceTimersByTimeAsync(2000);
|
|
41
|
-
const result = await promise;
|
|
42
|
-
expect(result).toBe(42);
|
|
43
|
-
expect(onSlow).toHaveBeenCalledTimes(1);
|
|
44
|
-
});
|
|
45
|
-
it('clears the timer when work rejects', async () => {
|
|
46
|
-
const onSlow = vi.fn();
|
|
47
|
-
const error = new Error('boom');
|
|
48
|
-
const promise = output.runWithSlowHint(1000, onSlow, async () => {
|
|
49
|
-
throw error;
|
|
50
|
-
});
|
|
51
|
-
await expect(promise).rejects.toBe(error);
|
|
52
|
-
await vi.advanceTimersByTimeAsync(2000);
|
|
53
|
-
expect(onSlow).not.toHaveBeenCalled();
|
|
54
|
-
});
|
|
55
|
-
it('returns the work result through to the caller', async () => {
|
|
56
|
-
const onSlow = vi.fn();
|
|
57
|
-
const result = await output.runWithSlowHint(1000, onSlow, async () => ({ a: 1 }));
|
|
58
|
-
expect(result).toEqual({ a: 1 });
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
//# sourceMappingURL=output.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"output.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/output.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Picks which `<lang>/` directories under projectDir to keep as workspace
|
|
3
|
-
* symlinks and which to skip. Skipping non-active language directories
|
|
4
|
-
* shrinks Turbopack's filesystem scan and dropped cold compile from ~67s
|
|
5
|
-
* to ~12s on jamdesk-docs (commit 90d781b4).
|
|
6
|
-
*
|
|
7
|
-
* The dev server still reads content from the user's source tree via
|
|
8
|
-
* JAMDESK_PROJECTS_DIR, so the language picker keeps showing every
|
|
9
|
-
* language and clicks always 200 OK — the workspace symlinks are a
|
|
10
|
-
* Turbopack-only performance layer.
|
|
11
|
-
*
|
|
12
|
-
* Default rules:
|
|
13
|
-
* 1. Language with `default: true`
|
|
14
|
-
* 2. First language in `navigation.languages[]`
|
|
15
|
-
*/
|
|
16
|
-
export interface LanguageFilter {
|
|
17
|
-
active: string | null;
|
|
18
|
-
skip: Set<string>;
|
|
19
|
-
}
|
|
20
|
-
interface NavigationLanguageEntry {
|
|
21
|
-
language?: string;
|
|
22
|
-
default?: boolean;
|
|
23
|
-
}
|
|
24
|
-
interface MinimalConfig {
|
|
25
|
-
navigation?: {
|
|
26
|
-
languages?: NavigationLanguageEntry[];
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
export declare function getActiveLanguageFilter(config: MinimalConfig): LanguageFilter;
|
|
30
|
-
export {};
|
|
31
|
-
//# sourceMappingURL=language-filter.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"language-filter.d.ts","sourceRoot":"","sources":["../../src/lib/language-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnB;AAED,UAAU,uBAAuB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,aAAa;IACrB,UAAU,CAAC,EAAE;QACX,SAAS,CAAC,EAAE,uBAAuB,EAAE,CAAC;KACvC,CAAC;CACH;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc,CAc7E"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export function getActiveLanguageFilter(config) {
|
|
2
|
-
const validEntries = (config.navigation?.languages ?? []).filter((l) => typeof l.language === 'string');
|
|
3
|
-
if (validEntries.length === 0) {
|
|
4
|
-
return { active: null, skip: new Set() };
|
|
5
|
-
}
|
|
6
|
-
const codes = validEntries.map((l) => l.language);
|
|
7
|
-
const active = validEntries.find((l) => l.default)?.language ?? validEntries[0].language;
|
|
8
|
-
if (codes.length === 1) {
|
|
9
|
-
return { active, skip: new Set() };
|
|
10
|
-
}
|
|
11
|
-
const skip = new Set(codes.filter((c) => c !== active));
|
|
12
|
-
return { active, skip };
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=language-filter.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"language-filter.js","sourceRoot":"","sources":["../../src/lib/language-filter.ts"],"names":[],"mappings":"AA+BA,MAAM,UAAU,uBAAuB,CAAC,MAAqB;IAC3D,MAAM,YAAY,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,CAC9D,CAAC,CAAC,EAAgD,EAAE,CAAC,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CACpF,CAAC;IACF,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,EAAU,EAAE,CAAC;IACnD,CAAC;IACD,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,QAAQ,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACzF,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,GAAG,EAAU,EAAE,CAAC;IAC7C,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC;IACxD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC1B,CAAC"}
|