jamdesk 1.1.167 → 1.1.169

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.
@@ -36,6 +36,10 @@ const SYNCED_FILES = [
36
36
  // three must move together with the canonical.
37
37
  ['build-service/themes/index.ts', 'cli/vendored/themes/index.ts'],
38
38
  ['build-service/components/navigation/Header.tsx', 'cli/vendored/components/navigation/Header.tsx'],
39
+ [
40
+ "build-service/components/navigation/Sidebar.tsx",
41
+ "cli/vendored/components/navigation/Sidebar.tsx",
42
+ ],
39
43
  ];
40
44
  describe('CLI vendored files sync', () => {
41
45
  it.each(SYNCED_FILES)('should have matching content: %s', async (buildServicePath, vendoredPath) => {
@@ -1 +1 @@
1
- {"version":3,"file":"vendored-sync.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/vendored-sync.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vendored-sync.test.js","sourceRoot":"","sources":["../../../src/__tests__/unit/vendored-sync.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jamdesk",
3
- "version": "1.1.167",
3
+ "version": "1.1.169",
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",
@@ -122,36 +122,90 @@ function findFirstPageInGroups(groups: ResolvedGroup[]): string | null {
122
122
  return null;
123
123
  }
124
124
 
125
- /** Find all groups whose `expanded: true` schema flag should open them by default */
126
- function findInitiallyExpandedGroups(groups: ResolvedGroup[]): Set<string> {
127
- const result = new Set<string>();
128
- for (const group of groups) {
129
- if (group.expanded && group.name) result.add(group.name);
130
- if (group.nested) {
131
- findInitiallyExpandedGroups(group.nested).forEach(name => result.add(name));
132
- }
133
- }
134
- return result;
125
+ // A group's position within the resolved navigation tree, expressed as the
126
+ // chain of sibling indices from the root (e.g. `[1, 0]` = second top-level
127
+ // group's first nested group). This is the stable identity for accordion
128
+ // state — see `groupStateKey` for why we key on position rather than name.
129
+ type GroupIndexPath = readonly number[];
130
+
131
+ // The navigation context a group is rendered in. Locale + active tab/anchor
132
+ // scope the accordion state so a manual expansion on one tab (or in one
133
+ // language) never leaks into the same tree position on another — labels and
134
+ // index paths repeat across tabs/locales, but the scope does not.
135
+ function navigationScope(nav: {
136
+ currentLanguage?: string;
137
+ activeTab?: string;
138
+ activeAnchor?: string;
139
+ }): string {
140
+ return [
141
+ nav.currentLanguage ?? 'default',
142
+ nav.activeTab ?? nav.activeAnchor ?? 'root',
143
+ ].join(':');
135
144
  }
136
145
 
137
- /** Find all groups in the path from root to the page containing currentPath */
138
- function findGroupsContainingPath(groups: ResolvedGroup[], currentPath: string, parentNames: string[] = []): Set<string> {
139
- const result = new Set<string>();
140
- for (const group of groups) {
141
- const groupPath = group.name ? [...parentNames, group.name] : parentNames;
146
+ function groupStateKey(scope: string, indexPath: GroupIndexPath): string {
147
+ return `${scope}:${indexPath.join('.')}`;
148
+ }
142
149
 
143
- if (group.pages.some(page => page.path === currentPath)) {
144
- groupPath.forEach(name => result.add(name));
145
- }
150
+ function groupPanelId(scope: string, indexPath: GroupIndexPath): string {
151
+ const safeScope = scope.replace(/[^a-zA-Z0-9_-]/g, '-');
152
+ return `nav-group-${safeScope}-${indexPath.join('-')}`;
153
+ }
146
154
 
147
- if (group.nested) {
148
- const nestedResults = findGroupsContainingPath(group.nested, currentPath, groupPath);
149
- nestedResults.forEach(name => result.add(name));
155
+ /**
156
+ * Collect the scoped state keys of every NAMED ancestor of each group matching
157
+ * `predicate` (including the matching group itself when named), so a
158
+ * qualifying descendant opens the whole chain that leads to it. Walks
159
+ * `group.nested` by sibling index — the same named-group index used while
160
+ * rendering ordered `group.items` — so discovery and rendered keys agree.
161
+ */
162
+ function collectAncestorKeys(
163
+ groups: ResolvedGroup[],
164
+ scope: string,
165
+ predicate: (group: ResolvedGroup) => boolean,
166
+ parentPath: GroupIndexPath = [],
167
+ ancestorKeys: readonly string[] = [],
168
+ ): Set<string> {
169
+ const result = new Set<string>();
170
+ groups.forEach((group, index) => {
171
+ const indexPath = [...parentPath, index];
172
+ const key = groupStateKey(scope, indexPath);
173
+ const nextAncestors = group.name ? [...ancestorKeys, key] : ancestorKeys;
174
+ if (predicate(group)) {
175
+ nextAncestors.forEach((ancestorKey) => result.add(ancestorKey));
150
176
  }
151
- }
177
+ collectAncestorKeys(
178
+ group.nested ?? [], scope, predicate, indexPath, nextAncestors,
179
+ ).forEach((nestedKey) => result.add(nestedKey));
180
+ });
152
181
  return result;
153
182
  }
154
183
 
184
+ /**
185
+ * Named groups that should start open because a descendant carries the
186
+ * `expanded: true` schema flag.
187
+ */
188
+ function findInitiallyExpandedGroups(
189
+ groups: ResolvedGroup[],
190
+ scope: string,
191
+ ): Set<string> {
192
+ return collectAncestorKeys(groups, scope, (group) => Boolean(group.expanded && group.name));
193
+ }
194
+
195
+ /**
196
+ * Named groups on the path from the root to the page at `currentPath`, so the
197
+ * active page's ancestors open by default.
198
+ */
199
+ function findGroupsContainingPath(
200
+ groups: ResolvedGroup[],
201
+ currentPath: string,
202
+ scope: string,
203
+ ): Set<string> {
204
+ return collectAncestorKeys(groups, scope, (group) =>
205
+ group.pages.some((page) => page.path === currentPath),
206
+ );
207
+ }
208
+
155
209
  export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPositionProp, isOpen = false, onClose }: SidebarProps) {
156
210
  const pathname = usePathname() ?? '';
157
211
  const router = useRouter();
@@ -170,6 +224,7 @@ export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPosi
170
224
  // the active page's parent group collapsed on first paint.
171
225
  const [expandedGroups, setExpandedGroups] = useState<Set<string>>(() => {
172
226
  const initialNav = resolveNavigation(config, pathname || '/');
227
+ const initialScope = navigationScope(initialNav);
173
228
  const rootPath = linkPrefix || '/';
174
229
  // `pathname || rootPath` handles both the null-pathname mask (`?? ''`
175
230
  // above) and the bare-root case in one expression — when pathname is the
@@ -181,8 +236,8 @@ export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPosi
181
236
  if (firstPage) seedPath = `${linkPrefix}/${firstPage}`;
182
237
  }
183
238
  const initialPath = seedPath.replace(/^\/(?:docs\/)?/, '');
184
- const seeded = findGroupsContainingPath(initialNav.groups, initialPath);
185
- findInitiallyExpandedGroups(initialNav.groups).forEach((g) => seeded.add(g));
239
+ const seeded = findGroupsContainingPath(initialNav.groups, initialPath, initialScope);
240
+ findInitiallyExpandedGroups(initialNav.groups, initialScope).forEach((g) => seeded.add(g));
186
241
  return seeded;
187
242
  });
188
243
  const [logoError, setLogoError] = useState(false);
@@ -246,6 +301,12 @@ export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPosi
246
301
  return resolveNavigation(config, effectivePathname || pathname || '/');
247
302
  }, [config, effectivePathname, pathname]);
248
303
 
304
+ // Locale + active tab/anchor scope for accordion state keys. Derived from the
305
+ // resolved navigation (never from a visible group label) so manually-toggled
306
+ // groups don't leak their open state across tabs or languages that reuse the
307
+ // same labels and tree positions.
308
+ const scope = navigationScope(resolvedNav);
309
+
249
310
  // Normalize bare root path to first page path for active state highlighting.
250
311
  // When an upstream proxy (e.g., Cloudflare Worker) follows the server redirect
251
312
  // from /docs → /docs/introduction internally, the browser URL stays at /docs.
@@ -263,16 +324,16 @@ export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPosi
263
324
  // Memoize the groups that should be expanded for the current page
264
325
  const groupsForCurrentPage = useMemo(() => {
265
326
  const currentPath = activePathname?.replace(/^\/(?:docs\/)?/, '') || '';
266
- return findGroupsContainingPath(resolvedNav.groups, currentPath);
267
- }, [resolvedNav.groups, activePathname]);
327
+ return findGroupsContainingPath(resolvedNav.groups, currentPath, scope);
328
+ }, [resolvedNav.groups, activePathname, scope]);
268
329
 
269
330
  // Re-evaluated whenever the resolved nav changes (e.g. switching tabs in
270
331
  // multi-tab docs), so newly-flagged `expanded: true` groups open on cross-tab
271
332
  // navigation. Without this re-eval, the schema flag would only be honored at
272
333
  // first mount.
273
334
  const initiallyExpandedGroups = useMemo(
274
- () => findInitiallyExpandedGroups(resolvedNav.groups),
275
- [resolvedNav.groups],
335
+ () => findInitiallyExpandedGroups(resolvedNav.groups, scope),
336
+ [resolvedNav.groups, scope],
276
337
  );
277
338
 
278
339
  // Merge the current page's ancestor groups + `expanded: true` flagged groups
@@ -372,17 +433,19 @@ export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPosi
372
433
  // Prevent body scroll when sidebar is open on mobile
373
434
  useBodyScrollLock(isOpen);
374
435
 
375
- // Toggle group expansion; if expanding, navigate to first page.
436
+ // Toggle group expansion; if expanding, navigate to first page. Top-level
437
+ // sections never visually collapse — for them the toggled key only gates
438
+ // prefetch (see renderGroupContents) while the click still navigates.
376
439
  // The router.push must run AFTER the setState commits — calling it inside the
377
440
  // updater triggers "Cannot update a component (Router) while rendering Sidebar".
378
- const handleGroupClick = useCallback((group: ResolvedGroup) => {
379
- const willExpand = !expandedGroups.has(group.name);
441
+ const handleGroupClick = useCallback((group: ResolvedGroup, key: string) => {
442
+ const willExpand = !expandedGroups.has(key);
380
443
  setExpandedGroups(prev => {
381
444
  const newSet = new Set(prev);
382
- if (prev.has(group.name)) {
383
- newSet.delete(group.name);
445
+ if (prev.has(key)) {
446
+ newSet.delete(key);
384
447
  } else {
385
- newSet.add(group.name);
448
+ newSet.add(key);
386
449
  }
387
450
  return newSet;
388
451
  });
@@ -394,27 +457,124 @@ export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPosi
394
457
  }
395
458
  }, [linkPrefix, expandedGroups, handleButtonNav]);
396
459
 
397
- // Render a navigation group (supports nesting)
398
- function renderGroup(group: ResolvedGroup, level: number = 0) {
399
- const isExpanded = expandedGroups.has(group.name);
460
+ // Render the pages and nested groups inside a group. Split out from
461
+ // renderGroup so a named group can gate its contents behind an expanded panel
462
+ // (mounting them only while open) while an unnamed group renders them inline.
463
+ function renderGroupContents(group: ResolvedGroup, level: number, indexPath: GroupIndexPath) {
464
+ const isExpanded = expandedGroups.has(groupStateKey(scope, indexPath));
465
+ // Top-level sections stay mounted while collapsed-in-state, so their Links
466
+ // hold prefetch until the section is seeded or clicked expanded (don't fan
467
+ // out RSC prefetches for every section on large sites). Closed NESTED named
468
+ // groups never reach here (their contents are unmounted), so a rendered
469
+ // nested named group is always expanded; unnamed groups always prefetch.
470
+ const shouldPrefetch = !group.name || isExpanded;
400
471
 
472
+ if (group.items) {
473
+ // Use ordered items array when available (preserves page/group ordering)
474
+ return (
475
+ <div className={level === 1 ? 'ml-3' : ''}>
476
+ {(() => {
477
+ // Group consecutive pages into single ul elements for continuous border
478
+ const elements: React.ReactNode[] = [];
479
+ let currentPages: typeof group.items = [];
480
+
481
+ const flushPages = () => {
482
+ if (currentPages.length > 0) {
483
+ elements.push(
484
+ <ul key={`pages-${elements.length}`}>
485
+ {currentPages.map((p) => p.type === 'page' && (
486
+ <NavPage
487
+ key={p.page.path}
488
+ page={p.page}
489
+ pathname={activePathname}
490
+ layout={layout}
491
+ onNavigate={handleNavigate}
492
+ linkPrefix={linkPrefix}
493
+ showSpinner={spinnerPathname === `${linkPrefix}/${p.page.path}`}
494
+ prefetch={shouldPrefetch}
495
+ />
496
+ ))}
497
+ </ul>
498
+ );
499
+ currentPages = [];
500
+ }
501
+ };
502
+
503
+ // Track the nested-group sibling index separately from the items
504
+ // index: the i-th nested group is the i-th group-typed item, which
505
+ // is the same index navigation-resolver assigns in `group.nested`.
506
+ // This keeps state keys aligned with the discovery helpers.
507
+ let nestedGroupIndex = 0;
508
+ group.items.forEach((item) => {
509
+ if (item.type === 'page') {
510
+ currentPages.push(item);
511
+ return;
512
+ }
513
+ flushPages();
514
+ const childIndex = nestedGroupIndex++;
515
+ elements.push(
516
+ <div key={groupStateKey(scope, [...indexPath, childIndex])} className={level <= 1 ? '' : 'mt-4'}>
517
+ {renderGroup(item.group, level + 1, [...indexPath, childIndex])}
518
+ </div>
519
+ );
520
+ });
521
+ flushPages();
522
+
523
+ return elements;
524
+ })()}
525
+ </div>
526
+ );
527
+ }
528
+
529
+ // Fallback to legacy pages + nested (for backwards compatibility)
530
+ return (
531
+ <>
532
+ {group.pages.length > 0 && (
533
+ <ul className={level === 1 ? 'ml-3' : ''}>
534
+ {group.pages.map((page) => (
535
+ <NavPage
536
+ key={page.path}
537
+ page={page}
538
+ pathname={activePathname}
539
+ layout={layout}
540
+ onNavigate={handleNavigate}
541
+ linkPrefix={linkPrefix}
542
+ showSpinner={spinnerPathname === `${linkPrefix}/${page.path}`}
543
+ prefetch={shouldPrefetch}
544
+ />
545
+ ))}
546
+ </ul>
547
+ )}
548
+ {group.nested && group.nested.length > 0 && (
549
+ <div className={level === 0 ? '' : level === 1 ? 'ml-3' : 'mt-4'}>
550
+ {group.nested.map((nested, childIndex) => renderGroup(nested, level + 1, [...indexPath, childIndex]))}
551
+ </div>
552
+ )}
553
+ </>
554
+ );
555
+ }
556
+
557
+ // Render a navigation group (supports nesting). Top-level named groups are
558
+ // permanent sections: the header never collapses, its contents stay mounted,
559
+ // and clicking it navigates to the group's first page. Nested named groups
560
+ // are accordions: a button carrying aria-expanded/aria-controls toggles an
561
+ // addressable panel whose descendants mount only while expanded.
562
+ function renderGroup(group: ResolvedGroup, level: number = 0, indexPath: GroupIndexPath = []) {
401
563
  // Skip rendering if group has no name and no content
402
564
  if (!group.name && group.pages.length === 0 && !group.nested?.length && !group.items?.length) {
403
565
  return null;
404
566
  }
405
567
 
406
- // Don't fan out RSC prefetches for collapsed L0 sections on large docs
407
- // sites. L1+ Links are only in the DOM when their named ancestors are
408
- // expanded (see the rendering guard below), so `level !== 0` is safe
409
- // shorthand there.
410
- const shouldPrefetch = level !== 0 || isExpanded || !group.name;
568
+ const key = groupStateKey(scope, indexPath);
569
+ const isExpanded = expandedGroups.has(key);
411
570
 
412
- return (
413
- <div key={group.name || `group-${level}`} className={level === 0 ? 'ml-6' : level === 1 ? '' : 'ml-3'}>
414
- {group.name && (
415
- level === 0 ? (
571
+ if (level === 0) {
572
+ return (
573
+ <div key={key} className="ml-6">
574
+ {group.name && (
416
575
  <button
417
- onClick={() => handleGroupClick(group)}
576
+ type="button"
577
+ onClick={() => handleGroupClick(group, key)}
418
578
  className="flex items-center justify-between w-full text-left mb-2 cursor-pointer"
419
579
  >
420
580
  <span className="text-sm font-semibold text-[var(--color-text-tertiary)] flex items-center gap-2">
@@ -429,101 +589,47 @@ export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPosi
429
589
  )}
430
590
  </span>
431
591
  </button>
432
- ) : (
433
- <button
434
- onClick={() => handleGroupClick(group)}
435
- className={`nav-group-l1 flex items-center gap-1.5 ${layout === 'header-logo' ? 'pr-3' : 'px-3'} py-1.5 rounded-lg text-sm transition-colors w-full text-left text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)] cursor-pointer`}
436
- >
437
- <span className="truncate">{group.name}</span>
438
- <i
439
- className={`fa-solid fa-chevron-right text-[8px] text-[var(--color-text-muted)] transition-transform ${isExpanded ? 'rotate-90' : ''}`}
440
- aria-hidden="true"
441
- />
442
- {group.tag && (
443
- <span className="px-1.5 py-0.5 text-[10px] font-semibold rounded bg-[var(--color-accent)]/15 text-[var(--color-accent)]">
444
- {group.tag}
445
- </span>
446
- )}
447
- </button>
448
- )
449
- )}
592
+ )}
593
+ {renderGroupContents(group, level, indexPath)}
594
+ </div>
595
+ );
596
+ }
450
597
 
451
- {(level === 0 || isExpanded || !group.name) && (
452
- <>
453
- {group.items ? (
454
- // Use ordered items array when available (preserves page/group ordering)
455
- <div className={level === 1 ? 'ml-3' : ''}>
456
- {(() => {
457
- // Group consecutive pages into single ul elements for continuous border
458
- const elements: React.ReactNode[] = [];
459
- let currentPages: typeof group.items = [];
460
-
461
- const flushPages = () => {
462
- if (currentPages.length > 0) {
463
- elements.push(
464
- <ul key={`pages-${elements.length}`}>
465
- {currentPages.map((p) => p.type === 'page' && (
466
- <NavPage
467
- key={p.page.path}
468
- page={p.page}
469
- pathname={activePathname}
470
- layout={layout}
471
- onNavigate={handleNavigate}
472
- linkPrefix={linkPrefix}
473
- showSpinner={spinnerPathname === `${linkPrefix}/${p.page.path}`}
474
- prefetch={shouldPrefetch}
475
- />
476
- ))}
477
- </ul>
478
- );
479
- currentPages = [];
480
- }
481
- };
482
-
483
- group.items.forEach((item, idx) => {
484
- if (item.type === 'page') {
485
- currentPages.push(item);
486
- } else {
487
- flushPages();
488
- elements.push(
489
- <div key={item.group.name || `nested-${idx}`} className={level === 0 ? '' : level === 1 ? '' : 'mt-4'}>
490
- {renderGroup(item.group, level + 1)}
491
- </div>
492
- );
493
- }
494
- });
495
- flushPages();
496
-
497
- return elements;
498
- })()}
499
- </div>
500
- ) : (
501
- // Fallback to legacy pages + nested (for backwards compatibility)
502
- <>
503
- {group.pages.length > 0 && (
504
- <ul className={level === 1 ? 'ml-3' : ''}>
505
- {group.pages.map((page) => (
506
- <NavPage
507
- key={page.path}
508
- page={page}
509
- pathname={activePathname}
510
- layout={layout}
511
- onNavigate={handleNavigate}
512
- linkPrefix={linkPrefix}
513
- showSpinner={spinnerPathname === `${linkPrefix}/${page.path}`}
514
- prefetch={shouldPrefetch}
515
- />
516
- ))}
517
- </ul>
518
- )}
519
- {group.nested && group.nested.length > 0 && (
520
- <div className={level === 0 ? '' : level === 1 ? 'ml-3' : 'mt-4'}>
521
- {group.nested.map((nested) => renderGroup(nested, level + 1))}
522
- </div>
523
- )}
524
- </>
598
+ const panelId = groupPanelId(scope, indexPath);
599
+ const outerClassName = level === 1 ? '' : 'ml-3';
600
+ const buttonClassName = `nav-group-l1 flex items-center gap-1.5 ${layout === 'header-logo' ? 'pr-3' : 'px-3'} py-1.5 rounded-lg text-sm transition-colors w-full text-left text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)] cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-accent)] focus-visible:ring-offset-2`;
601
+
602
+ return (
603
+ <div key={key} className={outerClassName}>
604
+ {group.name && (
605
+ <button
606
+ type="button"
607
+ aria-expanded={isExpanded}
608
+ aria-controls={panelId}
609
+ onClick={() => handleGroupClick(group, key)}
610
+ className={buttonClassName}
611
+ >
612
+ {group.icon && (
613
+ <i className={`${getIconClass(group.icon)} text-[14px]`} aria-hidden="true" />
614
+ )}
615
+ <span className="flex-1 min-w-0 truncate">{group.name}</span>
616
+ {group.tag && (
617
+ <span className="px-1.5 py-0.5 text-[10px] font-semibold rounded bg-[var(--color-accent)]/15 text-[var(--color-accent)]">
618
+ {group.tag}
619
+ </span>
525
620
  )}
526
- </>
621
+ <i
622
+ className={`fa-solid fa-chevron-right text-[8px] text-[var(--color-text-muted)] transition-transform ${isExpanded ? 'rotate-90' : ''}`}
623
+ aria-hidden="true"
624
+ />
625
+ </button>
626
+ )}
627
+ {group.name ? (
628
+ <div id={panelId} hidden={!isExpanded}>
629
+ {isExpanded && renderGroupContents(group, level, indexPath)}
630
+ </div>
631
+ ) : (
632
+ renderGroupContents(group, level, indexPath)
527
633
  )}
528
634
  </div>
529
635
  );
@@ -818,7 +924,7 @@ export function Sidebar({ config, layout = 'header-logo', tabsPosition: tabsPosi
818
924
 
819
925
  {/* Navigation Groups */}
820
926
  <div className="sidebar-nav-groups">
821
- {resolvedNav.groups.map((group) => renderGroup(group))}
927
+ {resolvedNav.groups.map((group, index) => renderGroup(group, 0, [index]))}
822
928
  </div>
823
929
  </nav>
824
930