jamdesk 1.1.143 → 1.1.144
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.144",
|
|
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",
|
|
@@ -6,7 +6,7 @@ import Link from 'next/link';
|
|
|
6
6
|
import { usePathname } from 'next/navigation';
|
|
7
7
|
// Icons use Font Awesome CSS classes for lightweight rendering
|
|
8
8
|
import type { DocsConfig, TabsPosition } from '@/lib/docs-types';
|
|
9
|
-
import { normalizeLogo,
|
|
9
|
+
import { normalizeLogo, getIconString } from '@/lib/docs-types';
|
|
10
10
|
import type { LayoutVariant } from '@/themes';
|
|
11
11
|
import { getTheme } from '@/themes';
|
|
12
12
|
import { ThemeToggle } from '@/components/theme/ThemeToggle';
|
|
@@ -136,7 +136,7 @@ export function Header({ config, layout = 'header-logo', tabsPosition: tabsPosit
|
|
|
136
136
|
if (!hasTabs) return [];
|
|
137
137
|
|
|
138
138
|
return navigationTabs.map((tab) => {
|
|
139
|
-
const iconName =
|
|
139
|
+
const iconName = getIconString(tab.icon);
|
|
140
140
|
|
|
141
141
|
// For external tabs, use the href directly
|
|
142
142
|
if (tab.href && !tab.groups && !tab.pages) {
|
|
@@ -489,7 +489,7 @@ export function Header({ config, layout = 'header-logo', tabsPosition: tabsPosit
|
|
|
489
489
|
rel={isExternal ? 'noopener noreferrer' : undefined}
|
|
490
490
|
className="flex items-center gap-1.5 px-2.5 py-1.5 text-sm text-[var(--color-text-tertiary)] hover:text-[var(--color-text-primary)] transition-colors"
|
|
491
491
|
>
|
|
492
|
-
{link.icon && <i className={`${getIconClass(
|
|
492
|
+
{link.icon && <i className={`${getIconClass(getIconString(link.icon))} text-[14px]`} aria-hidden="true" />}
|
|
493
493
|
<span>{resolveLabel(link.label, link.labels)}</span>
|
|
494
494
|
{isExternal && <i className="fa-solid fa-arrow-up-right-from-square text-[10px] opacity-50" aria-hidden="true" />}
|
|
495
495
|
</a>
|
|
@@ -564,6 +564,7 @@ export function Header({ config, layout = 'header-logo', tabsPosition: tabsPosit
|
|
|
564
564
|
isOpen={isSearchOpen}
|
|
565
565
|
onClose={() => setIsSearchOpen(false)}
|
|
566
566
|
popularPages={config.search?.popularPages}
|
|
567
|
+
placeholder={config.search?.prompt}
|
|
567
568
|
/>
|
|
568
569
|
)}
|
|
569
570
|
{searchDevNotice}
|
|
@@ -12,11 +12,13 @@ import { useProjectSlug } from '@/lib/project-slug-context';
|
|
|
12
12
|
import type { SearchResult, SearchGroup } from '@/lib/search-client';
|
|
13
13
|
import { useChatPanelOptional } from '@/hooks/useChatPanel';
|
|
14
14
|
import { modifierKeyLabel } from '@/lib/platform-keys';
|
|
15
|
+
import { getIconString, type IconConfig } from '@/lib/docs-types';
|
|
16
|
+
import { getIconClass } from '@/lib/icon-utils';
|
|
15
17
|
|
|
16
18
|
interface PopularPage {
|
|
17
19
|
title: string;
|
|
18
20
|
slug: string;
|
|
19
|
-
icon?:
|
|
21
|
+
icon?: IconConfig;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
interface SearchModalProps {
|
|
@@ -24,10 +26,14 @@ interface SearchModalProps {
|
|
|
24
26
|
onClose: () => void;
|
|
25
27
|
popularPages?: PopularPage[];
|
|
26
28
|
onNavigate?: (url: string) => void;
|
|
29
|
+
/** Custom placeholder for the search input (docs.json `search.prompt`) */
|
|
30
|
+
placeholder?: string;
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
const DEBOUNCE_MS = 150;
|
|
30
34
|
|
|
35
|
+
const DEFAULT_SEARCH_PLACEHOLDER = 'Search documentation…';
|
|
36
|
+
|
|
31
37
|
// Default popular pages fallback
|
|
32
38
|
const DEFAULT_POPULAR_PAGES: PopularPage[] = [
|
|
33
39
|
{ title: 'Quick Start', slug: 'quickstart', icon: 'rocket' },
|
|
@@ -135,7 +141,7 @@ function countVisibleResults(rows: SearchRow[]): number {
|
|
|
135
141
|
return rows.reduce((n, r) => (r.kind === 'expander' ? n : n + 1), 0);
|
|
136
142
|
}
|
|
137
143
|
|
|
138
|
-
export function SearchModal({ isOpen, onClose, popularPages, onNavigate }: SearchModalProps) {
|
|
144
|
+
export function SearchModal({ isOpen, onClose, popularPages, onNavigate, placeholder }: SearchModalProps) {
|
|
139
145
|
const linkPrefix = useLinkPrefix();
|
|
140
146
|
const projectSlug = useProjectSlug();
|
|
141
147
|
const chatPanel = useChatPanelOptional();
|
|
@@ -522,7 +528,7 @@ export function SearchModal({ isOpen, onClose, popularPages, onNavigate }: Searc
|
|
|
522
528
|
<input
|
|
523
529
|
ref={inputRef}
|
|
524
530
|
type="search"
|
|
525
|
-
placeholder=
|
|
531
|
+
placeholder={placeholder || DEFAULT_SEARCH_PLACEHOLDER}
|
|
526
532
|
value={query}
|
|
527
533
|
onChange={(e) => setQuery(e.target.value)}
|
|
528
534
|
className="flex-1 bg-transparent text-[var(--color-text-primary)] placeholder-[var(--color-text-muted)] outline-none text-base [&::-webkit-search-cancel-button]:appearance-none [&::-webkit-search-decoration]:appearance-none"
|
|
@@ -703,7 +709,7 @@ export function SearchModal({ isOpen, onClose, popularPages, onNavigate }: Searc
|
|
|
703
709
|
: 'hover:bg-[var(--color-bg-secondary)]'
|
|
704
710
|
}`}
|
|
705
711
|
>
|
|
706
|
-
<i className={
|
|
712
|
+
<i className={`${getIconClass(getIconString(page.icon))} text-sm text-[var(--color-text-muted)]`} aria-hidden="true" />
|
|
707
713
|
<span className="text-sm text-[var(--color-text-primary)] truncate">{page.title}</span>
|
|
708
714
|
</button>
|
|
709
715
|
))}
|
|
@@ -685,7 +685,7 @@ export interface SearchConfig {
|
|
|
685
685
|
popularPages?: Array<{
|
|
686
686
|
title: string;
|
|
687
687
|
slug: string;
|
|
688
|
-
icon?:
|
|
688
|
+
icon?: IconConfig;
|
|
689
689
|
}>;
|
|
690
690
|
}
|
|
691
691
|
|
|
@@ -960,7 +960,7 @@ export function normalizeNavPage(page: NavigationPage): {
|
|
|
960
960
|
.pop()
|
|
961
961
|
?.replace(/-/g, ' ')
|
|
962
962
|
.replace(/\b\w/g, (l) => l.toUpperCase()) || page.page,
|
|
963
|
-
icon:
|
|
963
|
+
icon: getIconString(page.icon),
|
|
964
964
|
tag: page.tag,
|
|
965
965
|
};
|
|
966
966
|
}
|
|
@@ -1024,6 +1024,19 @@ export function getIconName(icon: IconConfig | undefined): string | undefined {
|
|
|
1024
1024
|
return icon.name;
|
|
1025
1025
|
}
|
|
1026
1026
|
|
|
1027
|
+
/**
|
|
1028
|
+
* Flatten an icon config to the string getIconClass() understands, preserving
|
|
1029
|
+
* the Font Awesome style as a "style/name" prefix (every IconStyle value is a
|
|
1030
|
+
* getIconClass style prefix). Use this — not getIconName — wherever an icon is
|
|
1031
|
+
* rendered, so a configured `style` survives the flatten. `library` is
|
|
1032
|
+
* intentionally dropped: all icons render via Font Awesome.
|
|
1033
|
+
*/
|
|
1034
|
+
export function getIconString(icon: IconConfig | undefined): string | undefined {
|
|
1035
|
+
if (!icon) return undefined;
|
|
1036
|
+
if (typeof icon === 'string') return icon;
|
|
1037
|
+
return icon.style ? `${icon.style}/${icon.name}` : icon.name;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1027
1040
|
/**
|
|
1028
1041
|
* Get icon library from config
|
|
1029
1042
|
*/
|
|
@@ -18,7 +18,7 @@ import type {
|
|
|
18
18
|
ExternalAnchorConfig,
|
|
19
19
|
} from './docs-types';
|
|
20
20
|
|
|
21
|
-
import { normalizeNavPage,
|
|
21
|
+
import { normalizeNavPage, getIconString } from './docs-types';
|
|
22
22
|
import { getLanguageDisplayInfo, extractLanguageFromPath } from './language-utils';
|
|
23
23
|
import { evictOldest } from './cache-utils';
|
|
24
24
|
|
|
@@ -225,7 +225,7 @@ function resolveGroup(group: GroupConfig): ResolvedGroup {
|
|
|
225
225
|
|
|
226
226
|
return {
|
|
227
227
|
name: group.group,
|
|
228
|
-
icon:
|
|
228
|
+
icon: getIconString(group.icon),
|
|
229
229
|
tag: group.tag,
|
|
230
230
|
pages: resolvedPages,
|
|
231
231
|
expanded: group.expanded,
|
|
@@ -268,7 +268,7 @@ function resolveTabGroups(tab: TabConfig): ResolvedGroup[] {
|
|
|
268
268
|
function resolveTab(tab: TabConfig): ResolvedTab {
|
|
269
269
|
return {
|
|
270
270
|
name: tab.tab,
|
|
271
|
-
icon:
|
|
271
|
+
icon: getIconString(tab.icon),
|
|
272
272
|
href: tab.href,
|
|
273
273
|
isExternal: !!tab.href && !tab.groups && !tab.pages,
|
|
274
274
|
};
|
|
@@ -465,7 +465,7 @@ export function resolveNavigation(
|
|
|
465
465
|
.map((anchor: ExternalAnchorConfig) => ({
|
|
466
466
|
name: anchor.name,
|
|
467
467
|
href: anchor.href,
|
|
468
|
-
icon:
|
|
468
|
+
icon: getIconString(anchor.icon),
|
|
469
469
|
}));
|
|
470
470
|
}
|
|
471
471
|
|
|
@@ -476,7 +476,7 @@ export function resolveNavigation(
|
|
|
476
476
|
result.externalAnchors.push({
|
|
477
477
|
name: anchor.anchor,
|
|
478
478
|
href: anchor.href,
|
|
479
|
-
icon:
|
|
479
|
+
icon: getIconString(anchor.icon),
|
|
480
480
|
});
|
|
481
481
|
}
|
|
482
482
|
}
|
|
@@ -555,7 +555,7 @@
|
|
|
555
555
|
"slug": {
|
|
556
556
|
"type": "string",
|
|
557
557
|
"minLength": 1,
|
|
558
|
-
"description": "Page path
|
|
558
|
+
"description": "Page path, without a leading slash or file extension. A leading slash makes a broken // URL. Nested pages use the folder path: e.g. 'quickstart', or 'guides/authentication' for the file guides/authentication.mdx."
|
|
559
559
|
},
|
|
560
560
|
"icon": {
|
|
561
561
|
"$ref": "#/definitions/iconSchema",
|