@aravindc26/velu 0.11.0 → 0.11.3
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 +15 -6
- package/schema/velu.schema.json +1251 -115
- package/src/build.ts +1121 -304
- package/src/cli.ts +90 -26
- package/src/engine/_server.mjs +1684 -277
- package/src/engine/app/(docs)/[...slug]/layout.tsx +371 -0
- package/src/engine/app/(docs)/[...slug]/page.tsx +926 -0
- package/src/engine/app/api/proxy/route.ts +23 -0
- package/src/engine/app/copy-page.css +59 -1
- package/src/engine/app/global.css +3157 -3
- package/src/engine/app/layout.tsx +56 -1
- package/src/engine/app/llms-file/route.ts +87 -0
- package/src/engine/app/llms-full-file/route.ts +62 -0
- package/src/engine/app/md-file/[...slug]/route.ts +409 -0
- package/src/engine/app/page.tsx +45 -0
- package/src/engine/app/robots.txt/route.ts +63 -0
- package/src/engine/app/rss-file/[...slug]/route.ts +169 -0
- package/src/engine/app/sitemap.xml/route.ts +82 -0
- package/src/engine/components/assistant.tsx +16 -5
- package/src/engine/components/changelog-filters.tsx +114 -0
- package/src/engine/components/code-group.tsx +383 -0
- package/src/engine/components/color.tsx +118 -0
- package/src/engine/components/expandable.tsx +77 -0
- package/src/engine/components/icon.tsx +136 -0
- package/src/engine/components/image-zoom-fallback.tsx +147 -0
- package/src/engine/components/image.tsx +111 -0
- package/src/engine/components/manual-api-playground.tsx +154 -0
- package/src/engine/components/mermaid.tsx +142 -0
- package/src/engine/components/openapi-toc-sync.tsx +59 -0
- package/src/engine/components/openapi.tsx +1682 -0
- package/src/engine/components/page-feedback.tsx +153 -0
- package/src/engine/components/product-switcher.tsx +27 -3
- package/src/engine/components/prompt.tsx +90 -0
- package/src/engine/components/providers.tsx +1 -6
- package/src/engine/components/search.tsx +4 -0
- package/src/engine/components/sidebar-links.tsx +13 -15
- package/src/engine/components/synced-tabs.tsx +57 -0
- package/src/engine/components/toc-examples.tsx +110 -0
- package/src/engine/components/view.tsx +344 -0
- package/src/engine/generated/redirects.ts +3 -0
- package/src/engine/lib/changelog.ts +246 -0
- package/src/engine/lib/layout.shared.ts +30 -2
- package/src/engine/lib/llms.ts +444 -0
- package/src/engine/lib/navigation-normalize.mjs +481 -412
- package/src/engine/lib/navigation-normalize.ts +261 -54
- package/src/engine/lib/redirects.ts +194 -0
- package/src/engine/lib/source.ts +107 -4
- package/src/engine/lib/velu.ts +368 -2
- package/src/engine/mdx-components.tsx +648 -0
- package/src/engine/middleware.ts +66 -0
- package/src/engine/public/icons/cursor-dark.svg +12 -0
- package/src/engine/public/icons/cursor-light.svg +12 -0
- package/src/engine/source.config.ts +98 -1
- package/src/engine/src/components/PageTitle.astro +16 -5
- package/src/engine/src/lib/velu.ts +11 -3
- package/src/navigation-normalize.ts +252 -54
- package/src/themes.ts +6 -6
- package/src/validate.ts +119 -6
- package/src/engine/app/(docs)/[[...slug]]/layout.tsx +0 -87
- package/src/engine/app/(docs)/[[...slug]]/page.tsx +0 -146
|
@@ -1,456 +1,525 @@
|
|
|
1
1
|
function isObject(value) {
|
|
2
|
-
|
|
2
|
+
return typeof value === "object" && value !== null;
|
|
3
3
|
}
|
|
4
|
-
|
|
5
4
|
function isSeparator(value) {
|
|
6
|
-
|
|
5
|
+
return isObject(value) && typeof value.separator === "string";
|
|
7
6
|
}
|
|
8
|
-
|
|
9
7
|
function isLink(value) {
|
|
10
|
-
|
|
8
|
+
return isObject(value) && typeof value.href === "string" && typeof value.label === "string";
|
|
11
9
|
}
|
|
12
|
-
|
|
13
10
|
function isGroupLike(value) {
|
|
14
|
-
|
|
11
|
+
return isObject(value) && typeof value.group === "string";
|
|
15
12
|
}
|
|
16
|
-
|
|
17
13
|
function isMenuItem(value) {
|
|
18
|
-
|
|
14
|
+
return isObject(value) && typeof value.item === "string";
|
|
19
15
|
}
|
|
20
|
-
|
|
21
16
|
function isTabLike(value) {
|
|
22
|
-
|
|
17
|
+
return isObject(value) && typeof value.tab === "string";
|
|
23
18
|
}
|
|
24
|
-
|
|
25
19
|
function isAnchorLike(value) {
|
|
26
|
-
|
|
20
|
+
return isObject(value) && typeof value.anchor === "string";
|
|
27
21
|
}
|
|
28
|
-
|
|
29
22
|
function isDropdownLike(value) {
|
|
30
|
-
|
|
23
|
+
return isObject(value) && typeof value.dropdown === "string";
|
|
31
24
|
}
|
|
32
|
-
|
|
33
25
|
function isGroupEntry(value) {
|
|
34
|
-
|
|
26
|
+
return typeof value === "object" && value !== null && "group" in value;
|
|
35
27
|
}
|
|
36
|
-
|
|
37
28
|
function slugify(input, fallback) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
29
|
+
const slug = input
|
|
30
|
+
.toLowerCase()
|
|
31
|
+
.trim()
|
|
32
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
33
|
+
.replace(/^-+|-+$/g, "");
|
|
34
|
+
return slug || fallback;
|
|
44
35
|
}
|
|
45
|
-
|
|
46
36
|
function uniqueSlug(base, used) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
37
|
+
if (!used.has(base)) {
|
|
38
|
+
used.add(base);
|
|
39
|
+
return base;
|
|
40
|
+
}
|
|
41
|
+
let count = 2;
|
|
42
|
+
while (used.has(`${base}-${count}`))
|
|
43
|
+
count += 1;
|
|
44
|
+
const candidate = `${base}-${count}`;
|
|
45
|
+
used.add(candidate);
|
|
46
|
+
return candidate;
|
|
47
|
+
}
|
|
48
|
+
function normalizeOpenApiValue(value) {
|
|
49
|
+
if (typeof value === "string") {
|
|
50
|
+
const trimmed = value.trim();
|
|
51
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
52
|
+
}
|
|
53
|
+
if (Array.isArray(value)) {
|
|
54
|
+
const items = value
|
|
55
|
+
.filter((entry) => typeof entry === "string")
|
|
56
|
+
.map((entry) => entry.trim())
|
|
57
|
+
.filter((entry) => entry.length > 0);
|
|
58
|
+
return items.length > 0 ? items : undefined;
|
|
59
|
+
}
|
|
60
|
+
if (isObject(value)) {
|
|
61
|
+
const source = normalizeOpenApiValue(value.source);
|
|
62
|
+
if (source === undefined || (typeof source === "object" && !Array.isArray(source)))
|
|
63
|
+
return undefined;
|
|
64
|
+
const rawDirectory = typeof value.directory === "string" ? value.directory.trim() : "";
|
|
65
|
+
const directory = rawDirectory ? rawDirectory.replace(/\\/g, "/").replace(/^\/+/, "").replace(/\/+$/, "") : undefined;
|
|
66
|
+
return directory ? { source, directory } : { source };
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
function resolveOpenApiValue(local, inherited) {
|
|
71
|
+
return normalizeOpenApiValue(local) ?? inherited;
|
|
72
|
+
}
|
|
73
|
+
function resolveVersionValue(local, inherited) {
|
|
74
|
+
if (typeof local === "string") {
|
|
75
|
+
const trimmed = local.trim();
|
|
76
|
+
if (trimmed.length > 0)
|
|
77
|
+
return trimmed;
|
|
78
|
+
}
|
|
79
|
+
return inherited;
|
|
58
80
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
81
|
function normalizeLink(value) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
82
|
+
const out = { href: value.href, label: value.label };
|
|
83
|
+
if (typeof value.icon === "string" && value.icon.length > 0)
|
|
84
|
+
out.icon = value.icon;
|
|
85
|
+
if (typeof value.iconType === "string" && value.iconType.length > 0)
|
|
86
|
+
out.iconType = value.iconType;
|
|
87
|
+
return out;
|
|
65
88
|
}
|
|
66
|
-
|
|
67
89
|
function normalizeAnchorLink(value) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
90
|
+
const href = typeof value.href === "string" ? value.href : "#";
|
|
91
|
+
const label = typeof value.anchor === "string" ? value.anchor : "Link";
|
|
92
|
+
const icon = typeof value.icon === "string" ? value.icon : undefined;
|
|
93
|
+
const iconType = typeof value.iconType === "string" ? value.iconType : undefined;
|
|
94
|
+
const out = { href, label };
|
|
95
|
+
if (icon)
|
|
96
|
+
out.icon = icon;
|
|
97
|
+
if (iconType)
|
|
98
|
+
out.iconType = iconType;
|
|
99
|
+
return out;
|
|
72
100
|
}
|
|
73
|
-
|
|
74
101
|
function hasContent(value) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
(Array.isArray(a.anchors) && a.anchors.length > 0) ||
|
|
92
|
-
(Array.isArray(a.dropdowns) && a.dropdowns.length > 0))
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
return hasSimple || hasAnchors;
|
|
102
|
+
const hasSimple = (Array.isArray(value.pages) && value.pages.length > 0) ||
|
|
103
|
+
(Array.isArray(value.groups) && value.groups.length > 0) ||
|
|
104
|
+
(Array.isArray(value.menu) && value.menu.length > 0) ||
|
|
105
|
+
(Array.isArray(value.tabs) && value.tabs.length > 0) ||
|
|
106
|
+
(Array.isArray(value.dropdowns) && value.dropdowns.length > 0) ||
|
|
107
|
+
normalizeOpenApiValue(value.openapi) !== undefined ||
|
|
108
|
+
normalizeOpenApiValue(value.asyncapi) !== undefined;
|
|
109
|
+
const hasAnchors = Array.isArray(value.anchors) &&
|
|
110
|
+
value.anchors.some((a) => isAnchorLike(a) &&
|
|
111
|
+
((Array.isArray(a.tabs) && a.tabs.length > 0) ||
|
|
112
|
+
(Array.isArray(a.groups) && a.groups.length > 0) ||
|
|
113
|
+
(Array.isArray(a.pages) && a.pages.length > 0) ||
|
|
114
|
+
(Array.isArray(a.menu) && a.menu.length > 0) ||
|
|
115
|
+
(Array.isArray(a.anchors) && a.anchors.length > 0) ||
|
|
116
|
+
(Array.isArray(a.dropdowns) && a.dropdowns.length > 0)));
|
|
117
|
+
return hasSimple || hasAnchors;
|
|
96
118
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
119
|
+
function normalizeGroup(rawGroup, usedGroupSlugs, inheritedOpenApi, inheritedVersion) {
|
|
120
|
+
const groupName = typeof rawGroup.group === "string" ? rawGroup.group : "Group";
|
|
121
|
+
const rawSlug = typeof rawGroup.slug === "string" ? rawGroup.slug : groupName;
|
|
122
|
+
const groupSlug = uniqueSlug(slugify(rawSlug, "group"), usedGroupSlugs);
|
|
123
|
+
const openapi = resolveOpenApiValue(rawGroup.openapi, inheritedOpenApi);
|
|
124
|
+
const asyncapi = normalizeOpenApiValue(rawGroup.asyncapi);
|
|
125
|
+
const version = resolveVersionValue(rawGroup.version, inheritedVersion);
|
|
126
|
+
const childUsedSlugs = new Set();
|
|
127
|
+
const pages = collectEntries(rawGroup, childUsedSlugs, openapi, version);
|
|
128
|
+
const out = { group: groupName, slug: groupSlug, pages };
|
|
129
|
+
if (typeof rawGroup.icon === "string")
|
|
130
|
+
out.icon = rawGroup.icon;
|
|
131
|
+
if (typeof rawGroup.iconType === "string")
|
|
132
|
+
out.iconType = rawGroup.iconType;
|
|
133
|
+
if (version !== undefined)
|
|
134
|
+
out.version = version;
|
|
135
|
+
if (typeof rawGroup.tag === "string")
|
|
136
|
+
out.tag = rawGroup.tag;
|
|
137
|
+
if (typeof rawGroup.expanded === "boolean")
|
|
138
|
+
out.expanded = rawGroup.expanded;
|
|
139
|
+
if (typeof rawGroup.description === "string")
|
|
140
|
+
out.description = rawGroup.description;
|
|
141
|
+
if (typeof rawGroup.hidden === "boolean")
|
|
142
|
+
out.hidden = rawGroup.hidden;
|
|
143
|
+
if (openapi !== undefined)
|
|
144
|
+
out.openapi = openapi;
|
|
145
|
+
if (asyncapi !== undefined)
|
|
146
|
+
out.asyncapi = asyncapi;
|
|
147
|
+
return out;
|
|
113
148
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
149
|
+
function normalizeMenuItem(rawItem, usedGroupSlugs, inheritedOpenApi, inheritedVersion) {
|
|
150
|
+
const name = typeof rawItem.item === "string" ? rawItem.item : "Menu";
|
|
151
|
+
const rawSlug = typeof rawItem.slug === "string" ? rawItem.slug : name;
|
|
152
|
+
const slug = uniqueSlug(slugify(rawSlug, "menu"), usedGroupSlugs);
|
|
153
|
+
const openapi = resolveOpenApiValue(rawItem.openapi, inheritedOpenApi);
|
|
154
|
+
const asyncapi = normalizeOpenApiValue(rawItem.asyncapi);
|
|
155
|
+
const version = resolveVersionValue(rawItem.version, inheritedVersion);
|
|
156
|
+
const nestedGroupSlugs = new Set();
|
|
157
|
+
const pages = collectEntries(rawItem, nestedGroupSlugs, openapi, version);
|
|
158
|
+
const out = { group: name, slug, pages };
|
|
159
|
+
if (typeof rawItem.icon === "string")
|
|
160
|
+
out.icon = rawItem.icon;
|
|
161
|
+
if (typeof rawItem.iconType === "string")
|
|
162
|
+
out.iconType = rawItem.iconType;
|
|
163
|
+
if (version !== undefined)
|
|
164
|
+
out.version = version;
|
|
165
|
+
if (openapi !== undefined)
|
|
166
|
+
out.openapi = openapi;
|
|
167
|
+
if (asyncapi !== undefined)
|
|
168
|
+
out.asyncapi = asyncapi;
|
|
169
|
+
return out;
|
|
125
170
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
171
|
+
function normalizeTabAsGroup(rawTab, usedGroupSlugs, inheritedOpenApi, inheritedVersion) {
|
|
172
|
+
const tabName = typeof rawTab.tab === "string" ? rawTab.tab : "Tab";
|
|
173
|
+
const rawSlug = typeof rawTab.slug === "string" ? rawTab.slug : tabName;
|
|
174
|
+
const slug = uniqueSlug(slugify(rawSlug, "tab"), usedGroupSlugs);
|
|
175
|
+
const openapi = resolveOpenApiValue(rawTab.openapi, inheritedOpenApi);
|
|
176
|
+
const asyncapi = normalizeOpenApiValue(rawTab.asyncapi);
|
|
177
|
+
const version = resolveVersionValue(rawTab.version, inheritedVersion);
|
|
178
|
+
const nestedGroupSlugs = new Set();
|
|
179
|
+
const pages = collectEntries(rawTab, nestedGroupSlugs, openapi, version);
|
|
180
|
+
if (typeof rawTab.href === "string" && rawTab.href.length > 0 && !hasContent(rawTab)) {
|
|
181
|
+
pages.push({
|
|
182
|
+
href: rawTab.href,
|
|
183
|
+
label: tabName,
|
|
184
|
+
...(typeof rawTab.icon === "string" ? { icon: rawTab.icon } : {}),
|
|
185
|
+
...(typeof rawTab.iconType === "string" ? { iconType: rawTab.iconType } : {}),
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
const out = { group: tabName, slug, pages };
|
|
189
|
+
if (typeof rawTab.icon === "string")
|
|
190
|
+
out.icon = rawTab.icon;
|
|
191
|
+
if (typeof rawTab.iconType === "string")
|
|
192
|
+
out.iconType = rawTab.iconType;
|
|
193
|
+
if (version !== undefined)
|
|
194
|
+
out.version = version;
|
|
195
|
+
if (openapi !== undefined)
|
|
196
|
+
out.openapi = openapi;
|
|
197
|
+
if (asyncapi !== undefined)
|
|
198
|
+
out.asyncapi = asyncapi;
|
|
199
|
+
return out;
|
|
141
200
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
201
|
+
function normalizeDropdownAsGroup(rawDropdown, usedGroupSlugs, inheritedOpenApi, inheritedVersion) {
|
|
202
|
+
return normalizeTabAsGroup({
|
|
203
|
+
tab: rawDropdown.dropdown,
|
|
204
|
+
slug: rawDropdown.slug,
|
|
205
|
+
icon: rawDropdown.icon,
|
|
206
|
+
iconType: rawDropdown.iconType,
|
|
207
|
+
version: rawDropdown.version,
|
|
208
|
+
href: rawDropdown.href,
|
|
209
|
+
groups: rawDropdown.groups,
|
|
210
|
+
pages: rawDropdown.pages,
|
|
211
|
+
menu: rawDropdown.menu,
|
|
212
|
+
anchors: rawDropdown.anchors,
|
|
213
|
+
dropdowns: rawDropdown.dropdowns,
|
|
214
|
+
tabs: rawDropdown.tabs,
|
|
215
|
+
openapi: rawDropdown.openapi,
|
|
216
|
+
asyncapi: rawDropdown.asyncapi,
|
|
217
|
+
}, usedGroupSlugs, inheritedOpenApi, inheritedVersion);
|
|
159
218
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
219
|
+
function normalizeAnchorAsGroup(rawAnchor, usedGroupSlugs, inheritedOpenApi, inheritedVersion) {
|
|
220
|
+
const anchorName = typeof rawAnchor.anchor === "string" ? rawAnchor.anchor : "Anchor";
|
|
221
|
+
const rawSlug = typeof rawAnchor.slug === "string" ? rawAnchor.slug : anchorName;
|
|
222
|
+
const slug = uniqueSlug(slugify(rawSlug, "anchor"), usedGroupSlugs);
|
|
223
|
+
const openapi = resolveOpenApiValue(rawAnchor.openapi, inheritedOpenApi);
|
|
224
|
+
const asyncapi = normalizeOpenApiValue(rawAnchor.asyncapi);
|
|
225
|
+
const version = resolveVersionValue(rawAnchor.version, inheritedVersion);
|
|
226
|
+
const nestedGroupSlugs = new Set();
|
|
227
|
+
const pages = collectEntries(rawAnchor, nestedGroupSlugs, openapi, version);
|
|
228
|
+
const out = { group: anchorName, slug, pages };
|
|
229
|
+
if (typeof rawAnchor.icon === "string")
|
|
230
|
+
out.icon = rawAnchor.icon;
|
|
231
|
+
if (typeof rawAnchor.iconType === "string")
|
|
232
|
+
out.iconType = rawAnchor.iconType;
|
|
233
|
+
if (version !== undefined)
|
|
234
|
+
out.version = version;
|
|
235
|
+
if (openapi !== undefined)
|
|
236
|
+
out.openapi = openapi;
|
|
237
|
+
if (asyncapi !== undefined)
|
|
238
|
+
out.asyncapi = asyncapi;
|
|
239
|
+
return out;
|
|
171
240
|
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
241
|
+
function collectEntries(rawSection, usedGroupSlugs, inheritedOpenApi, inheritedVersion) {
|
|
242
|
+
const entries = [];
|
|
243
|
+
const hasNonMenuContent = (Array.isArray(rawSection.groups) && rawSection.groups.length > 0) ||
|
|
244
|
+
(Array.isArray(rawSection.pages) && rawSection.pages.length > 0) ||
|
|
245
|
+
(Array.isArray(rawSection.anchors) && rawSection.anchors.length > 0) ||
|
|
246
|
+
(Array.isArray(rawSection.dropdowns) && rawSection.dropdowns.length > 0) ||
|
|
247
|
+
(Array.isArray(rawSection.tabs) && rawSection.tabs.length > 0);
|
|
248
|
+
for (const item of Array.isArray(rawSection.menu) ? rawSection.menu : []) {
|
|
249
|
+
if (hasNonMenuContent)
|
|
250
|
+
break;
|
|
251
|
+
if (isMenuItem(item))
|
|
252
|
+
entries.push(normalizeMenuItem(item, usedGroupSlugs, inheritedOpenApi, inheritedVersion));
|
|
253
|
+
}
|
|
254
|
+
for (const group of Array.isArray(rawSection.groups) ? rawSection.groups : []) {
|
|
255
|
+
if (isGroupLike(group))
|
|
256
|
+
entries.push(normalizeGroup(group, usedGroupSlugs, inheritedOpenApi, inheritedVersion));
|
|
257
|
+
}
|
|
258
|
+
for (const item of Array.isArray(rawSection.pages) ? rawSection.pages : []) {
|
|
259
|
+
if (typeof item === "string")
|
|
260
|
+
entries.push(item);
|
|
261
|
+
else if (isSeparator(item))
|
|
262
|
+
entries.push({ separator: item.separator });
|
|
263
|
+
else if (isLink(item))
|
|
264
|
+
entries.push(normalizeLink(item));
|
|
265
|
+
else if (isGroupLike(item))
|
|
266
|
+
entries.push(normalizeGroup(item, usedGroupSlugs, inheritedOpenApi, inheritedVersion));
|
|
267
|
+
}
|
|
268
|
+
for (const anchor of Array.isArray(rawSection.anchors) ? rawSection.anchors : []) {
|
|
269
|
+
if (!isAnchorLike(anchor))
|
|
270
|
+
continue;
|
|
271
|
+
const hrefOnly = typeof anchor.href === "string" && anchor.href.length > 0 && !hasContent(anchor);
|
|
272
|
+
if (hrefOnly)
|
|
273
|
+
entries.push(normalizeAnchorLink(anchor));
|
|
274
|
+
else
|
|
275
|
+
entries.push(normalizeAnchorAsGroup(anchor, usedGroupSlugs, inheritedOpenApi, inheritedVersion));
|
|
276
|
+
}
|
|
277
|
+
for (const dropdown of Array.isArray(rawSection.dropdowns) ? rawSection.dropdowns : []) {
|
|
278
|
+
if (isDropdownLike(dropdown))
|
|
279
|
+
entries.push(normalizeDropdownAsGroup(dropdown, usedGroupSlugs, inheritedOpenApi, inheritedVersion));
|
|
280
|
+
}
|
|
281
|
+
for (const tab of Array.isArray(rawSection.tabs) ? rawSection.tabs : []) {
|
|
282
|
+
if (isTabLike(tab))
|
|
283
|
+
entries.push(normalizeTabAsGroup(tab, usedGroupSlugs, inheritedOpenApi, inheritedVersion));
|
|
284
|
+
}
|
|
285
|
+
return entries;
|
|
208
286
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
287
|
+
function normalizeTab(rawTab, usedTabSlugs, slugPrefix, inheritedOpenApi, inheritedVersion) {
|
|
288
|
+
const tabName = typeof rawTab.tab === "string" ? rawTab.tab : "Tab";
|
|
289
|
+
const rawSlug = typeof rawTab.slug === "string" ? rawTab.slug : tabName;
|
|
290
|
+
const tabSlugPart = slugify(rawSlug, "tab");
|
|
291
|
+
const fullSlug = slugPrefix ? `${slugPrefix}/${tabSlugPart}` : tabSlugPart;
|
|
292
|
+
const slug = uniqueSlug(fullSlug, usedTabSlugs);
|
|
293
|
+
const openapi = resolveOpenApiValue(rawTab.openapi, inheritedOpenApi);
|
|
294
|
+
const asyncapi = normalizeOpenApiValue(rawTab.asyncapi);
|
|
295
|
+
const version = resolveVersionValue(rawTab.version, inheritedVersion);
|
|
296
|
+
const out = { tab: tabName, slug };
|
|
297
|
+
if (typeof rawTab.icon === "string")
|
|
298
|
+
out.icon = rawTab.icon;
|
|
299
|
+
if (typeof rawTab.iconType === "string")
|
|
300
|
+
out.iconType = rawTab.iconType;
|
|
301
|
+
if (version !== undefined)
|
|
302
|
+
out.version = version;
|
|
303
|
+
if (openapi !== undefined)
|
|
304
|
+
out.openapi = openapi;
|
|
305
|
+
if (asyncapi !== undefined)
|
|
306
|
+
out.asyncapi = asyncapi;
|
|
307
|
+
if (typeof rawTab.href === "string" && rawTab.href.length > 0 && !hasContent(rawTab)) {
|
|
308
|
+
out.href = rawTab.href;
|
|
309
|
+
return out;
|
|
310
|
+
}
|
|
311
|
+
const groupSlugSet = new Set();
|
|
312
|
+
const entries = collectEntries(rawTab, groupSlugSet, openapi, version);
|
|
313
|
+
const groups = [];
|
|
314
|
+
const pages = [];
|
|
315
|
+
for (const entry of entries) {
|
|
316
|
+
if (isGroupEntry(entry))
|
|
317
|
+
groups.push(entry);
|
|
318
|
+
else
|
|
319
|
+
pages.push(entry);
|
|
320
|
+
}
|
|
321
|
+
if (groups.length > 0)
|
|
322
|
+
out.groups = groups;
|
|
323
|
+
if (pages.length > 0)
|
|
324
|
+
out.pages = pages;
|
|
222
325
|
return out;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
const groupSlugSet = new Set();
|
|
226
|
-
const entries = collectEntries(rawTab, groupSlugSet);
|
|
227
|
-
const groups = [];
|
|
228
|
-
const pages = [];
|
|
229
|
-
|
|
230
|
-
for (const entry of entries) {
|
|
231
|
-
if (isGroupEntry(entry)) groups.push(entry);
|
|
232
|
-
else pages.push(entry);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (groups.length > 0) out.groups = groups;
|
|
236
|
-
if (pages.length > 0) out.pages = pages;
|
|
237
|
-
return out;
|
|
238
326
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
slugPrefix
|
|
256
|
-
);
|
|
327
|
+
function normalizeDropdownToTab(rawDropdown, usedTabSlugs, slugPrefix, inheritedOpenApi, inheritedVersion) {
|
|
328
|
+
return normalizeTab({
|
|
329
|
+
tab: rawDropdown.dropdown,
|
|
330
|
+
slug: rawDropdown.slug,
|
|
331
|
+
icon: rawDropdown.icon,
|
|
332
|
+
iconType: rawDropdown.iconType,
|
|
333
|
+
version: rawDropdown.version,
|
|
334
|
+
href: rawDropdown.href,
|
|
335
|
+
groups: rawDropdown.groups,
|
|
336
|
+
pages: rawDropdown.pages,
|
|
337
|
+
menu: rawDropdown.menu,
|
|
338
|
+
anchors: rawDropdown.anchors,
|
|
339
|
+
dropdowns: rawDropdown.dropdowns,
|
|
340
|
+
tabs: rawDropdown.tabs,
|
|
341
|
+
openapi: rawDropdown.openapi,
|
|
342
|
+
asyncapi: rawDropdown.asyncapi,
|
|
343
|
+
}, usedTabSlugs, slugPrefix, inheritedOpenApi, inheritedVersion);
|
|
257
344
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
345
|
+
function normalizeTabList(rawTabs, usedTabSlugs, slugPrefix = "", inheritedOpenApi, inheritedVersion) {
|
|
346
|
+
const tabs = [];
|
|
347
|
+
for (const item of rawTabs) {
|
|
348
|
+
if (isTabLike(item))
|
|
349
|
+
tabs.push(normalizeTab(item, usedTabSlugs, slugPrefix, inheritedOpenApi, inheritedVersion));
|
|
350
|
+
}
|
|
351
|
+
return tabs;
|
|
265
352
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
353
|
+
function normalizeDropdownList(rawDropdowns, usedTabSlugs, slugPrefix = "", inheritedOpenApi, inheritedVersion) {
|
|
354
|
+
const tabs = [];
|
|
355
|
+
for (const item of rawDropdowns) {
|
|
356
|
+
if (isDropdownLike(item))
|
|
357
|
+
tabs.push(normalizeDropdownToTab(item, usedTabSlugs, slugPrefix, inheritedOpenApi, inheritedVersion));
|
|
358
|
+
}
|
|
359
|
+
if (inheritedOpenApi === undefined && inheritedVersion === undefined)
|
|
360
|
+
return tabs;
|
|
361
|
+
return tabs.map((tab) => ({ ...tab, openapi: tab.openapi ?? inheritedOpenApi, version: tab.version ?? inheritedVersion }));
|
|
273
362
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
const hasRootPages = Array.isArray(navigation.pages) && navigation.pages.length > 0;
|
|
406
|
-
const hasRootMenu = Array.isArray(navigation.menu) && navigation.menu.length > 0;
|
|
407
|
-
|
|
408
|
-
if (tabs.length === 0 && (hasRootGroups || hasRootPages || hasRootMenu)) {
|
|
409
|
-
tabs.push(
|
|
410
|
-
normalizeTab(
|
|
411
|
-
{
|
|
412
|
-
tab: 'Documentation',
|
|
413
|
-
slug: 'documentation',
|
|
414
|
-
groups: navigation.groups,
|
|
415
|
-
pages: navigation.pages,
|
|
416
|
-
menu: navigation.menu,
|
|
417
|
-
anchors: navigation.anchors,
|
|
418
|
-
dropdowns: navigation.dropdowns,
|
|
419
|
-
tabs: navigation.tabs,
|
|
420
|
-
},
|
|
421
|
-
usedTabSlugs,
|
|
422
|
-
''
|
|
423
|
-
)
|
|
424
|
-
);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
return tabs;
|
|
363
|
+
function normalizeNavigationTabs(navigation, usedTabSlugs = new Set(), inheritedOpenApi) {
|
|
364
|
+
if (!isObject(navigation))
|
|
365
|
+
return [];
|
|
366
|
+
const sectionOpenApi = resolveOpenApiValue(navigation.openapi, inheritedOpenApi);
|
|
367
|
+
const tabs = [];
|
|
368
|
+
tabs.push(...normalizeTabList(Array.isArray(navigation.tabs) ? navigation.tabs : [], usedTabSlugs, "", sectionOpenApi));
|
|
369
|
+
tabs.push(...normalizeDropdownList(Array.isArray(navigation.dropdowns) ? navigation.dropdowns : [], usedTabSlugs, "", sectionOpenApi));
|
|
370
|
+
if (Array.isArray(navigation.products)) {
|
|
371
|
+
navigation.products.forEach((product, index) => {
|
|
372
|
+
if (!isObject(product))
|
|
373
|
+
return;
|
|
374
|
+
const productName = typeof product.product === "string" ? product.product : `Product ${index + 1}`;
|
|
375
|
+
const prefix = slugify(productName, `product-${index + 1}`);
|
|
376
|
+
const productOpenApi = resolveOpenApiValue(product.openapi, sectionOpenApi);
|
|
377
|
+
tabs.push(...normalizeTabList(Array.isArray(product.tabs) ? product.tabs : [], usedTabSlugs, prefix, productOpenApi));
|
|
378
|
+
tabs.push(...normalizeDropdownList(Array.isArray(product.dropdowns) ? product.dropdowns : [], usedTabSlugs, prefix, productOpenApi));
|
|
379
|
+
if (!Array.isArray(product.tabs) && !Array.isArray(product.dropdowns)) {
|
|
380
|
+
if (hasContent(product)) {
|
|
381
|
+
tabs.push(normalizeTab({
|
|
382
|
+
tab: productName,
|
|
383
|
+
slug: prefix,
|
|
384
|
+
icon: product.icon,
|
|
385
|
+
iconType: product.iconType,
|
|
386
|
+
groups: product.groups,
|
|
387
|
+
pages: product.pages,
|
|
388
|
+
menu: product.menu,
|
|
389
|
+
anchors: product.anchors,
|
|
390
|
+
dropdowns: product.dropdowns,
|
|
391
|
+
tabs: product.tabs,
|
|
392
|
+
openapi: productOpenApi,
|
|
393
|
+
asyncapi: normalizeOpenApiValue(product.asyncapi),
|
|
394
|
+
}, usedTabSlugs, "", productOpenApi));
|
|
395
|
+
}
|
|
396
|
+
else if (typeof product.href === "string" && product.href.length > 0) {
|
|
397
|
+
tabs.push(normalizeTab({
|
|
398
|
+
tab: productName,
|
|
399
|
+
slug: prefix,
|
|
400
|
+
icon: product.icon,
|
|
401
|
+
iconType: product.iconType,
|
|
402
|
+
href: product.href,
|
|
403
|
+
openapi: productOpenApi,
|
|
404
|
+
asyncapi: normalizeOpenApiValue(product.asyncapi),
|
|
405
|
+
}, usedTabSlugs, "", productOpenApi));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
if (Array.isArray(navigation.versions)) {
|
|
411
|
+
navigation.versions.forEach((version, index) => {
|
|
412
|
+
if (!isObject(version))
|
|
413
|
+
return;
|
|
414
|
+
const versionName = typeof version.version === "string" ? version.version : `Version ${index + 1}`;
|
|
415
|
+
const prefix = slugify(versionName, `version-${index + 1}`);
|
|
416
|
+
const versionOpenApi = resolveOpenApiValue(version.openapi, sectionOpenApi);
|
|
417
|
+
tabs.push(...normalizeTabList(Array.isArray(version.tabs) ? version.tabs : [], usedTabSlugs, prefix, versionOpenApi));
|
|
418
|
+
tabs.push(...normalizeDropdownList(Array.isArray(version.dropdowns) ? version.dropdowns : [], usedTabSlugs, prefix, versionOpenApi));
|
|
419
|
+
if (!Array.isArray(version.tabs) && !Array.isArray(version.dropdowns)) {
|
|
420
|
+
if (hasContent(version)) {
|
|
421
|
+
tabs.push(normalizeTab({
|
|
422
|
+
tab: versionName,
|
|
423
|
+
slug: prefix,
|
|
424
|
+
groups: version.groups,
|
|
425
|
+
pages: version.pages,
|
|
426
|
+
menu: version.menu,
|
|
427
|
+
anchors: version.anchors,
|
|
428
|
+
dropdowns: version.dropdowns,
|
|
429
|
+
tabs: version.tabs,
|
|
430
|
+
openapi: versionOpenApi,
|
|
431
|
+
asyncapi: normalizeOpenApiValue(version.asyncapi),
|
|
432
|
+
}, usedTabSlugs, "", versionOpenApi));
|
|
433
|
+
}
|
|
434
|
+
else if (typeof version.href === "string" && version.href.length > 0) {
|
|
435
|
+
tabs.push(normalizeTab({
|
|
436
|
+
tab: versionName,
|
|
437
|
+
slug: prefix,
|
|
438
|
+
href: version.href,
|
|
439
|
+
openapi: versionOpenApi,
|
|
440
|
+
asyncapi: normalizeOpenApiValue(version.asyncapi),
|
|
441
|
+
}, usedTabSlugs, "", versionOpenApi));
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
if (Array.isArray(navigation.anchors)) {
|
|
447
|
+
navigation.anchors.forEach((anchor, index) => {
|
|
448
|
+
if (!isAnchorLike(anchor))
|
|
449
|
+
return;
|
|
450
|
+
const anchorName = typeof anchor.anchor === "string" ? anchor.anchor : `Anchor ${index + 1}`;
|
|
451
|
+
const prefix = slugify(anchorName, `anchor-${index + 1}`);
|
|
452
|
+
const anchorOpenApi = resolveOpenApiValue(anchor.openapi, sectionOpenApi);
|
|
453
|
+
const anchorVersion = resolveVersionValue(anchor.version);
|
|
454
|
+
if (Array.isArray(anchor.tabs)) {
|
|
455
|
+
tabs.push(...normalizeTabList(anchor.tabs, usedTabSlugs, prefix, anchorOpenApi, anchorVersion));
|
|
456
|
+
}
|
|
457
|
+
else if (hasContent(anchor)) {
|
|
458
|
+
tabs.push(normalizeTab({
|
|
459
|
+
tab: anchorName,
|
|
460
|
+
slug: prefix,
|
|
461
|
+
icon: anchor.icon,
|
|
462
|
+
iconType: anchor.iconType,
|
|
463
|
+
version: anchorVersion,
|
|
464
|
+
groups: anchor.groups,
|
|
465
|
+
pages: anchor.pages,
|
|
466
|
+
menu: anchor.menu,
|
|
467
|
+
anchors: anchor.anchors,
|
|
468
|
+
dropdowns: anchor.dropdowns,
|
|
469
|
+
tabs: anchor.tabs,
|
|
470
|
+
openapi: anchorOpenApi,
|
|
471
|
+
asyncapi: normalizeOpenApiValue(anchor.asyncapi),
|
|
472
|
+
}, usedTabSlugs, "", anchorOpenApi, anchorVersion));
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
const hasRootGroups = Array.isArray(navigation.groups) && navigation.groups.length > 0;
|
|
477
|
+
const hasRootPages = Array.isArray(navigation.pages) && navigation.pages.length > 0;
|
|
478
|
+
const hasRootMenu = Array.isArray(navigation.menu) && navigation.menu.length > 0;
|
|
479
|
+
if (tabs.length === 0 && (hasRootGroups || hasRootPages || hasRootMenu)) {
|
|
480
|
+
tabs.push(normalizeTab({
|
|
481
|
+
tab: "Documentation",
|
|
482
|
+
slug: "documentation",
|
|
483
|
+
groups: navigation.groups,
|
|
484
|
+
pages: navigation.pages,
|
|
485
|
+
menu: navigation.menu,
|
|
486
|
+
anchors: navigation.anchors,
|
|
487
|
+
dropdowns: navigation.dropdowns,
|
|
488
|
+
tabs: navigation.tabs,
|
|
489
|
+
openapi: sectionOpenApi,
|
|
490
|
+
asyncapi: normalizeOpenApiValue(navigation.asyncapi),
|
|
491
|
+
}, usedTabSlugs, "", sectionOpenApi));
|
|
492
|
+
}
|
|
493
|
+
return tabs;
|
|
428
494
|
}
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
495
|
+
function normalizeLanguageEntries(languages, inheritedOpenApi) {
|
|
496
|
+
if (!Array.isArray(languages))
|
|
497
|
+
return [];
|
|
498
|
+
return languages
|
|
499
|
+
.filter(isObject)
|
|
500
|
+
.map((entry) => {
|
|
501
|
+
const usedTabSlugs = new Set();
|
|
502
|
+
const languageOpenApi = resolveOpenApiValue(entry.openapi, inheritedOpenApi);
|
|
503
|
+
return {
|
|
504
|
+
...entry,
|
|
505
|
+
tabs: normalizeNavigationTabs(entry, usedTabSlugs, languageOpenApi),
|
|
506
|
+
};
|
|
441
507
|
});
|
|
442
508
|
}
|
|
443
|
-
|
|
444
509
|
export function normalizeConfigNavigation(config) {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
510
|
+
const nav = isObject(config.navigation) ? config.navigation : {};
|
|
511
|
+
const navOpenApi = resolveOpenApiValue(nav.openapi);
|
|
512
|
+
const navAsyncApi = normalizeOpenApiValue(nav.asyncapi);
|
|
513
|
+
return {
|
|
514
|
+
...config,
|
|
515
|
+
navigation: {
|
|
516
|
+
...nav,
|
|
517
|
+
...(navOpenApi !== undefined ? { openapi: navOpenApi } : {}),
|
|
518
|
+
...(navAsyncApi !== undefined ? { asyncapi: navAsyncApi } : {}),
|
|
519
|
+
tabs: normalizeNavigationTabs(nav, new Set(), navOpenApi),
|
|
520
|
+
languages: normalizeLanguageEntries(nav.languages, navOpenApi),
|
|
521
|
+
products: Array.isArray(nav.products) ? nav.products : [],
|
|
522
|
+
versions: Array.isArray(nav.versions) ? nav.versions : [],
|
|
523
|
+
},
|
|
524
|
+
};
|
|
456
525
|
}
|