@mintlify/common 1.0.1331 → 1.0.1333

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.
@@ -0,0 +1,425 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { getScopedNavForPath } from './scopeNavToPath.js';
3
+ const page = (href, extra = {}) => { var _a; return (Object.assign({ title: (_a = href.split('/').filter(Boolean).at(-1)) !== null && _a !== void 0 ? _a : 'Home', href }, extra)); };
4
+ const group = (name, pages, extra = {}) => (Object.assign({ group: name, pages }, extra));
5
+ const tabsAnchorsNav = {
6
+ tabs: [
7
+ {
8
+ tab: 'Guides',
9
+ groups: [
10
+ group('Start', [
11
+ page('/guides/intro'),
12
+ group('Nested', [page('/guides/nested/a'), page('/guides/nested/b', { hidden: true })]),
13
+ group('With root', [page('/guides/root/child')], { root: page('/guides/root') }),
14
+ ]),
15
+ group('Hidden', [page('/guides/secret')], { hidden: true }),
16
+ ],
17
+ },
18
+ {
19
+ tab: 'API',
20
+ anchors: [
21
+ {
22
+ anchor: 'REST',
23
+ groups: [
24
+ group('Endpoints', [
25
+ page('/api/rest/list', { openapi: 'GET /list', version: '1.0' }),
26
+ page('/api/rest/index'),
27
+ ]),
28
+ ],
29
+ },
30
+ { anchor: 'GraphQL', groups: [group('Schema', [page('/api/graphql/schema')])] },
31
+ ],
32
+ },
33
+ { tab: 'Gated', groups: [group('Private', [page('/gated/a', { groups: ['admin'] })])] },
34
+ {
35
+ tab: 'Menu',
36
+ menu: [
37
+ { item: 'One', groups: [group('One', [page('/menu/one/a'), page('/menu/one/b')])] },
38
+ { item: 'Two', groups: [group('Two', [page('/menu/two/a')])] },
39
+ ],
40
+ },
41
+ ],
42
+ };
43
+ const versionsNav = {
44
+ versions: [
45
+ {
46
+ version: 'v2',
47
+ default: true,
48
+ tabs: [
49
+ {
50
+ tab: 'Docs',
51
+ groups: [group('Start', [page('/quickstart'), page('/guides/setup'), page('/shared')])],
52
+ },
53
+ { tab: 'Reference', groups: [group('Reference', [page('/reference/api')])] },
54
+ ],
55
+ },
56
+ {
57
+ version: 'v1',
58
+ tabs: [
59
+ {
60
+ tab: 'Docs',
61
+ groups: [
62
+ group('Start', [page('/v1/quickstart'), page('/v1/guides/setup'), page('/shared')]),
63
+ ],
64
+ },
65
+ { tab: 'Reference', groups: [group('Reference', [page('/v1/reference/api')])] },
66
+ ],
67
+ },
68
+ { version: 'v0', hidden: true, groups: [group('Old', [page('/v0/quickstart')])] },
69
+ ],
70
+ };
71
+ const languagesNav = {
72
+ languages: [
73
+ {
74
+ language: 'en',
75
+ default: true,
76
+ dropdowns: [
77
+ {
78
+ dropdown: 'Guides',
79
+ groups: [group('Guides', [page('/intro'), page('/setup/index'), page('/common')])],
80
+ },
81
+ { dropdown: 'API', groups: [group('API', [page('/api/users')])] },
82
+ ],
83
+ },
84
+ {
85
+ language: 'fr',
86
+ dropdowns: [
87
+ {
88
+ dropdown: 'Guides',
89
+ groups: [group('Guides', [page('/fr/intro'), page('/fr/setup/index'), page('/common')])],
90
+ },
91
+ { dropdown: 'API', groups: [group('API', [page('/fr/api/users')])] },
92
+ ],
93
+ },
94
+ { language: 'ja', groups: [group('Guides', [page('/ja/intro'), page('/ja/setup')])] },
95
+ ],
96
+ };
97
+ const versionsLanguagesNav = {
98
+ versions: ['v2', 'v1'].map((version, index) => (Object.assign(Object.assign({ version }, (index === 0 ? { default: true } : {})), { languages: ['en', 'es'].map((language) => ({
99
+ language,
100
+ groups: [
101
+ group('Docs', [
102
+ page(`/docs/${version}/${language}/start`),
103
+ page(`/docs/${version}/${language}/guide/index`),
104
+ page('/docs/changelog'),
105
+ ]),
106
+ ],
107
+ })) }))),
108
+ };
109
+ const productsNav = {
110
+ products: [
111
+ {
112
+ product: 'Cloud',
113
+ versions: [
114
+ { version: '2024', groups: [group('Start', [page('/cloud/2024/start')])] },
115
+ { version: '2023', groups: [group('Start', [page('/cloud/2023/start')])] },
116
+ ],
117
+ },
118
+ {
119
+ product: 'Server',
120
+ tabs: [
121
+ { tab: 'Docs', groups: [group('Start', [page('/server/start'), page('/shared/page')])] },
122
+ { tab: 'Ops', groups: [group('Ops', [page('/server/ops')])] },
123
+ ],
124
+ },
125
+ { product: 'Edge', groups: [group('Start', [page('/edge/start'), page('/shared/page')])] },
126
+ ],
127
+ global: { anchors: [{ anchor: 'Blog', href: 'https://example.com/blog' }] },
128
+ };
129
+ function collectHrefs(node, out = []) {
130
+ if (Array.isArray(node)) {
131
+ for (const entry of node)
132
+ collectHrefs(entry, out);
133
+ }
134
+ else if (node && typeof node === 'object') {
135
+ for (const [key, value] of Object.entries(node)) {
136
+ if (key === 'href' && typeof value === 'string' && value.startsWith('/'))
137
+ out.push(value);
138
+ else
139
+ collectHrefs(value, out);
140
+ }
141
+ }
142
+ return out;
143
+ }
144
+ function pathsFor(nav) {
145
+ const hrefs = collectHrefs(nav);
146
+ return [
147
+ ...new Set([
148
+ ...hrefs,
149
+ ...hrefs.map((href) => `${href}/`),
150
+ ...hrefs.map((href) => href.slice(1)),
151
+ '/',
152
+ '/does-not-exist',
153
+ '/fr/does-not-exist',
154
+ ]),
155
+ ];
156
+ }
157
+ const serialize = (value) => JSON.stringify(value, (_, inner) => inner instanceof Map ? [...inner.entries()] : inner);
158
+ function digests(nav, options) {
159
+ return Object.fromEntries(pathsFor(nav).map((currentPath) => [
160
+ currentPath,
161
+ createHash('sha256')
162
+ .update(serialize(getScopedNavForPath(Object.assign({ decoratedNav: nav, currentPath }, options))))
163
+ .digest('hex')
164
+ .slice(0, 12),
165
+ ]));
166
+ }
167
+ describe('getScopedNavForPath output parity', () => {
168
+ it('tabs, anchors, menus and nested groups', () => {
169
+ expect(digests(tabsAnchorsNav, {})).toMatchInlineSnapshot(`
170
+ {
171
+ "/": "b164f1d8199a",
172
+ "/api/graphql/schema": "c5e2f017725e",
173
+ "/api/graphql/schema/": "c5e2f017725e",
174
+ "/api/rest/index": "3faf8ced1e80",
175
+ "/api/rest/index/": "3faf8ced1e80",
176
+ "/api/rest/list": "3faf8ced1e80",
177
+ "/api/rest/list/": "3faf8ced1e80",
178
+ "/does-not-exist": "b164f1d8199a",
179
+ "/fr/does-not-exist": "b164f1d8199a",
180
+ "/gated/a": "b164f1d8199a",
181
+ "/gated/a/": "b164f1d8199a",
182
+ "/guides/intro": "b0fe73b6d719",
183
+ "/guides/intro/": "b0fe73b6d719",
184
+ "/guides/nested/a": "b0fe73b6d719",
185
+ "/guides/nested/a/": "b0fe73b6d719",
186
+ "/guides/nested/b": "b0fe73b6d719",
187
+ "/guides/nested/b/": "b0fe73b6d719",
188
+ "/guides/root": "b0fe73b6d719",
189
+ "/guides/root/": "b0fe73b6d719",
190
+ "/guides/root/child": "b0fe73b6d719",
191
+ "/guides/root/child/": "b0fe73b6d719",
192
+ "/guides/secret": "b0fe73b6d719",
193
+ "/guides/secret/": "b0fe73b6d719",
194
+ "/menu/one/a": "be3f5e269da6",
195
+ "/menu/one/a/": "be3f5e269da6",
196
+ "/menu/one/b": "be3f5e269da6",
197
+ "/menu/one/b/": "be3f5e269da6",
198
+ "/menu/two/a": "7870d2717c4d",
199
+ "/menu/two/a/": "7870d2717c4d",
200
+ "api/graphql/schema": "c5e2f017725e",
201
+ "api/rest/index": "3faf8ced1e80",
202
+ "api/rest/list": "3faf8ced1e80",
203
+ "gated/a": "b164f1d8199a",
204
+ "guides/intro": "b0fe73b6d719",
205
+ "guides/nested/a": "b0fe73b6d719",
206
+ "guides/nested/b": "b0fe73b6d719",
207
+ "guides/root": "b0fe73b6d719",
208
+ "guides/root/child": "b0fe73b6d719",
209
+ "guides/secret": "b0fe73b6d719",
210
+ "menu/one/a": "be3f5e269da6",
211
+ "menu/one/b": "be3f5e269da6",
212
+ "menu/two/a": "7870d2717c4d",
213
+ }
214
+ `);
215
+ expect(digests(tabsAnchorsNav, { userGroups: new Set(['admin']) })).toMatchInlineSnapshot(`
216
+ {
217
+ "/": "b164f1d8199a",
218
+ "/api/graphql/schema": "c5e2f017725e",
219
+ "/api/graphql/schema/": "c5e2f017725e",
220
+ "/api/rest/index": "3faf8ced1e80",
221
+ "/api/rest/index/": "3faf8ced1e80",
222
+ "/api/rest/list": "3faf8ced1e80",
223
+ "/api/rest/list/": "3faf8ced1e80",
224
+ "/does-not-exist": "b164f1d8199a",
225
+ "/fr/does-not-exist": "b164f1d8199a",
226
+ "/gated/a": "a5cdba5c1760",
227
+ "/gated/a/": "a5cdba5c1760",
228
+ "/guides/intro": "b0fe73b6d719",
229
+ "/guides/intro/": "b0fe73b6d719",
230
+ "/guides/nested/a": "b0fe73b6d719",
231
+ "/guides/nested/a/": "b0fe73b6d719",
232
+ "/guides/nested/b": "b0fe73b6d719",
233
+ "/guides/nested/b/": "b0fe73b6d719",
234
+ "/guides/root": "b0fe73b6d719",
235
+ "/guides/root/": "b0fe73b6d719",
236
+ "/guides/root/child": "b0fe73b6d719",
237
+ "/guides/root/child/": "b0fe73b6d719",
238
+ "/guides/secret": "b0fe73b6d719",
239
+ "/guides/secret/": "b0fe73b6d719",
240
+ "/menu/one/a": "be3f5e269da6",
241
+ "/menu/one/a/": "be3f5e269da6",
242
+ "/menu/one/b": "be3f5e269da6",
243
+ "/menu/one/b/": "be3f5e269da6",
244
+ "/menu/two/a": "7870d2717c4d",
245
+ "/menu/two/a/": "7870d2717c4d",
246
+ "api/graphql/schema": "c5e2f017725e",
247
+ "api/rest/index": "3faf8ced1e80",
248
+ "api/rest/list": "3faf8ced1e80",
249
+ "gated/a": "a5cdba5c1760",
250
+ "guides/intro": "b0fe73b6d719",
251
+ "guides/nested/a": "b0fe73b6d719",
252
+ "guides/nested/b": "b0fe73b6d719",
253
+ "guides/root": "b0fe73b6d719",
254
+ "guides/root/child": "b0fe73b6d719",
255
+ "guides/secret": "b0fe73b6d719",
256
+ "menu/one/a": "be3f5e269da6",
257
+ "menu/one/b": "be3f5e269da6",
258
+ "menu/two/a": "7870d2717c4d",
259
+ }
260
+ `);
261
+ });
262
+ it('versions', () => {
263
+ expect(digests(versionsNav, {})).toMatchInlineSnapshot(`
264
+ {
265
+ "/": "a3a6b3f26290",
266
+ "/does-not-exist": "a120c6f89c5f",
267
+ "/fr/does-not-exist": "59880e1c5936",
268
+ "/guides/setup": "e58e2eaec18b",
269
+ "/guides/setup/": "b1595f127a2a",
270
+ "/quickstart": "24ad4d62870a",
271
+ "/quickstart/": "de2826f50469",
272
+ "/reference/api": "17542c57b247",
273
+ "/reference/api/": "3e2b1f7da854",
274
+ "/shared": "ce6fd04be10b",
275
+ "/shared/": "97a2d70ad480",
276
+ "/v0/quickstart": "8a6945a438f9",
277
+ "/v0/quickstart/": "f6cb867758e4",
278
+ "/v1/guides/setup": "dc0f01d08673",
279
+ "/v1/guides/setup/": "1a4743246337",
280
+ "/v1/quickstart": "df35cd3e181f",
281
+ "/v1/quickstart/": "e767413b1a96",
282
+ "/v1/reference/api": "c06d95864979",
283
+ "/v1/reference/api/": "aa56623c0d44",
284
+ "guides/setup": "b1595f127a2a",
285
+ "quickstart": "de2826f50469",
286
+ "reference/api": "3e2b1f7da854",
287
+ "shared": "97a2d70ad480",
288
+ "v0/quickstart": "f6cb867758e4",
289
+ "v1/guides/setup": "1a4743246337",
290
+ "v1/quickstart": "e767413b1a96",
291
+ "v1/reference/api": "aa56623c0d44",
292
+ }
293
+ `);
294
+ expect(digests(versionsNav, { isPreview: true })).toMatchInlineSnapshot(`
295
+ {
296
+ "/": "a3a6b3f26290",
297
+ "/does-not-exist": "a120c6f89c5f",
298
+ "/fr/does-not-exist": "59880e1c5936",
299
+ "/guides/setup": "e58e2eaec18b",
300
+ "/guides/setup/": "b1595f127a2a",
301
+ "/quickstart": "24ad4d62870a",
302
+ "/quickstart/": "de2826f50469",
303
+ "/reference/api": "17542c57b247",
304
+ "/reference/api/": "3e2b1f7da854",
305
+ "/shared": "ce6fd04be10b",
306
+ "/shared/": "97a2d70ad480",
307
+ "/v0/quickstart": "8a6945a438f9",
308
+ "/v0/quickstart/": "f6cb867758e4",
309
+ "/v1/guides/setup": "dc0f01d08673",
310
+ "/v1/guides/setup/": "1a4743246337",
311
+ "/v1/quickstart": "df35cd3e181f",
312
+ "/v1/quickstart/": "e767413b1a96",
313
+ "/v1/reference/api": "c06d95864979",
314
+ "/v1/reference/api/": "aa56623c0d44",
315
+ "guides/setup": "b1595f127a2a",
316
+ "quickstart": "de2826f50469",
317
+ "reference/api": "3e2b1f7da854",
318
+ "shared": "97a2d70ad480",
319
+ "v0/quickstart": "f6cb867758e4",
320
+ "v1/guides/setup": "1a4743246337",
321
+ "v1/quickstart": "e767413b1a96",
322
+ "v1/reference/api": "aa56623c0d44",
323
+ }
324
+ `);
325
+ });
326
+ it('languages with dropdowns', () => {
327
+ expect(digests(languagesNav, {})).toMatchInlineSnapshot(`
328
+ {
329
+ "/": "ce979c08a813",
330
+ "/api/users": "409a8bf89b12",
331
+ "/api/users/": "67303141cc2b",
332
+ "/common": "6a906ddff7ed",
333
+ "/common/": "0ce5c4e26b68",
334
+ "/does-not-exist": "7b2297bd3c37",
335
+ "/fr/api/users": "74357df8abce",
336
+ "/fr/api/users/": "54f1754c78ec",
337
+ "/fr/does-not-exist": "4585811e9e55",
338
+ "/fr/intro": "bd863a638c87",
339
+ "/fr/intro/": "64a54ad30002",
340
+ "/fr/setup/index": "114db8775a25",
341
+ "/fr/setup/index/": "c9bbfa1409ed",
342
+ "/intro": "6f7c1eed4eb0",
343
+ "/intro/": "226189728e46",
344
+ "/ja/intro": "9c2bdcc77e67",
345
+ "/ja/intro/": "e91e95c0d64d",
346
+ "/ja/setup": "f8dc7c43ffa6",
347
+ "/ja/setup/": "54dc061e722f",
348
+ "/setup/index": "447a9220de76",
349
+ "/setup/index/": "8ea6ad31a816",
350
+ "api/users": "67303141cc2b",
351
+ "common": "0ce5c4e26b68",
352
+ "fr/api/users": "54f1754c78ec",
353
+ "fr/intro": "64a54ad30002",
354
+ "fr/setup/index": "c9bbfa1409ed",
355
+ "intro": "226189728e46",
356
+ "ja/intro": "e91e95c0d64d",
357
+ "ja/setup": "54dc061e722f",
358
+ "setup/index": "8ea6ad31a816",
359
+ }
360
+ `);
361
+ });
362
+ it('versions with nested languages', () => {
363
+ expect(digests(versionsLanguagesNav, {})).toMatchInlineSnapshot(`
364
+ {
365
+ "/": "f42475557de1",
366
+ "/docs/changelog": "1c437381d128",
367
+ "/docs/changelog/": "7ed106295923",
368
+ "/docs/v1/en/guide/index": "01ed89e70ec8",
369
+ "/docs/v1/en/guide/index/": "5c88d880ec09",
370
+ "/docs/v1/en/start": "86e6dc6965e7",
371
+ "/docs/v1/en/start/": "a2bd9a3ca66e",
372
+ "/docs/v1/es/guide/index": "8cbc0aa147df",
373
+ "/docs/v1/es/guide/index/": "88cb825c7e75",
374
+ "/docs/v1/es/start": "18a79a976c03",
375
+ "/docs/v1/es/start/": "8f93d39494ca",
376
+ "/docs/v2/en/guide/index": "1039a56814fa",
377
+ "/docs/v2/en/guide/index/": "343311793bf6",
378
+ "/docs/v2/en/start": "fb154445b16b",
379
+ "/docs/v2/en/start/": "5cfdb9264aea",
380
+ "/docs/v2/es/guide/index": "b6601238d322",
381
+ "/docs/v2/es/guide/index/": "022d893c2bf1",
382
+ "/docs/v2/es/start": "d8e25e691661",
383
+ "/docs/v2/es/start/": "1653d195887e",
384
+ "/does-not-exist": "02fb2562a795",
385
+ "/fr/does-not-exist": "9b0cf71320d5",
386
+ "docs/changelog": "7ed106295923",
387
+ "docs/v1/en/guide/index": "5c88d880ec09",
388
+ "docs/v1/en/start": "a2bd9a3ca66e",
389
+ "docs/v1/es/guide/index": "88cb825c7e75",
390
+ "docs/v1/es/start": "8f93d39494ca",
391
+ "docs/v2/en/guide/index": "343311793bf6",
392
+ "docs/v2/en/start": "5cfdb9264aea",
393
+ "docs/v2/es/guide/index": "022d893c2bf1",
394
+ "docs/v2/es/start": "1653d195887e",
395
+ }
396
+ `);
397
+ });
398
+ it('products', () => {
399
+ expect(digests(productsNav, { includeProductVersionMetadata: true })).toMatchInlineSnapshot(`
400
+ {
401
+ "/": "1af414279ab1",
402
+ "/cloud/2023/start": "f8aaa97b676b",
403
+ "/cloud/2023/start/": "11cd502cf7e8",
404
+ "/cloud/2024/start": "4eee4b390dc3",
405
+ "/cloud/2024/start/": "b9a023fac78f",
406
+ "/does-not-exist": "c62a87b10ab2",
407
+ "/edge/start": "7107a0374787",
408
+ "/edge/start/": "7107a0374787",
409
+ "/fr/does-not-exist": "48a7b2f4e521",
410
+ "/server/ops": "236b31c9ab2c",
411
+ "/server/ops/": "236b31c9ab2c",
412
+ "/server/start": "742795eaea66",
413
+ "/server/start/": "742795eaea66",
414
+ "/shared/page": "70251a3f47ad",
415
+ "/shared/page/": "70251a3f47ad",
416
+ "cloud/2023/start": "11cd502cf7e8",
417
+ "cloud/2024/start": "b9a023fac78f",
418
+ "edge/start": "7107a0374787",
419
+ "server/ops": "236b31c9ab2c",
420
+ "server/start": "742795eaea66",
421
+ "shared/page": "70251a3f47ad",
422
+ }
423
+ `);
424
+ });
425
+ });
@@ -32,10 +32,11 @@ export function updateFirstHrefInDivision({ type, currentPath, entry, parentGrou
32
32
  entry.root
33
33
  : undefined;
34
34
  const isRootActive = root !== undefined &&
35
+ currentDivisionValue === nearestDivisionValue &&
35
36
  isPage(root) &&
36
- isEqualIgnoringLeadingSlash(root.href, currentPath) &&
37
- currentDivisionValue === nearestDivisionValue;
38
- const isActivePages = entry.pages.some((subEntry) => isPage(subEntry) && isEqualIgnoringLeadingSlash(subEntry.href, currentPath)) && currentDivisionValue === nearestDivisionValue;
37
+ isEqualIgnoringLeadingSlash(root.href, currentPath);
38
+ const isActivePages = currentDivisionValue === nearestDivisionValue &&
39
+ entry.pages.some((subEntry) => isPage(subEntry) && isEqualIgnoringLeadingSlash(subEntry.href, currentPath));
39
40
  if (root !== undefined) {
40
41
  updateFirstHrefInDivision({
41
42
  type,
@@ -82,7 +83,7 @@ export function updateFirstHrefInDivision({ type, currentPath, entry, parentGrou
82
83
  if (typeof group !== 'object')
83
84
  continue;
84
85
  const groupName = 'group' in group && typeof group.group === 'string' ? group.group : undefined;
85
- const matchesCurrentDivisionGroup = checkActiveGroup(group, currentPath) && currentDivisionValue === nearestDivisionValue;
86
+ const matchesCurrentDivisionGroup = currentDivisionValue === nearestDivisionValue && checkActiveGroup(group, currentPath);
86
87
  const matchesActiveSiblingGroup = type === 'version' &&
87
88
  currentDivisionValue !== nearestDivisionValue &&
88
89
  !!groupName &&
@@ -239,11 +240,17 @@ let lastTarget;
239
240
  function getTarget(path, languages) {
240
241
  if ((lastTarget === null || lastTarget === void 0 ? void 0 : lastTarget.path) !== path || lastTarget.languages !== languages) {
241
242
  const segments = toSegments(path);
243
+ const languagePath = parseLanguagePath(segments, languages);
244
+ const lastContentSegment = languagePath.contentSegments.at(-1);
242
245
  lastTarget = {
243
246
  path,
244
247
  languages,
245
248
  segments,
246
- languagePath: parseLanguagePath(segments, languages),
249
+ languagePath,
250
+ versionAnchor: segments.at(-1),
251
+ languageAnchor: isLanguageSegment(lastContentSegment, languages)
252
+ ? undefined
253
+ : lastContentSegment,
247
254
  };
248
255
  }
249
256
  return lastTarget;
@@ -363,8 +370,11 @@ function maybeUpdateFirstHrefInDivision(type, href, finalVersion, inActiveGroup,
363
370
  export function pathsDifferByOneSegment(a, b, type, languages = NO_LANGUAGES) {
364
371
  var _a, _b;
365
372
  const languageSet = getLowerCaseLanguageSet(languages);
366
- const aSegments = toSegments(a);
367
373
  const target = getTarget(b, languageSet);
374
+ const anchor = type === 'language' ? target.languageAnchor : target.versionAnchor;
375
+ if (anchor !== undefined && !a.includes(anchor))
376
+ return false;
377
+ const aSegments = toSegments(a);
368
378
  const bSegments = target.segments;
369
379
  // For language switching, we need to be more strict - paths should be identical except for the language segment
370
380
  // once normalized, content segments should be identical and only locale prefix may differ.