@mintlify/common 1.0.1228 → 1.0.1230

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.
@@ -43,6 +43,43 @@ describe('scopeDecoratedNavToPath', () => {
43
43
  expect(es.pages).toEqual([{ title: 'es', href: '/es/get-started/intro' }]);
44
44
  expect(fr.pages).toEqual([{ title: 'fr', href: '/fr/other/page' }]);
45
45
  });
46
+ it('keeps a regional language division active on its own pages', () => {
47
+ const regionalNav = {
48
+ languages: [
49
+ { language: 'en', default: true, pages: [page('/intro'), page('/install')] },
50
+ { language: 'en-GB', pages: [page('/en-gb/intro'), page('/en-gb/install')] },
51
+ ],
52
+ };
53
+ const [en, enGB] = loose(scopeDecoratedNavToPath(regionalNav, '/en-gb/intro')).languages;
54
+ if (!en || !enGB)
55
+ throw new Error('missing languages');
56
+ expect(enGB.pages).toEqual([page('/en-gb/intro'), page('/en-gb/install')]);
57
+ expect(en.pages).toEqual([{ title: 'en', href: '/intro' }]);
58
+ });
59
+ it('stubs a regional language division with the same page under its prefix', () => {
60
+ const regionalNav = {
61
+ languages: [
62
+ { language: 'en', default: true, pages: [page('/intro'), page('/install')] },
63
+ { language: 'en-GB', pages: [page('/en-gb/intro'), page('/en-gb/install')] },
64
+ ],
65
+ };
66
+ const [, enGB] = loose(scopeDecoratedNavToPath(regionalNav, '/install')).languages;
67
+ expect(enGB === null || enGB === void 0 ? void 0 : enGB.pages).toEqual([{ title: 'en-GB', href: '/en-gb/install' }]);
68
+ });
69
+ it('ignores a page field named language when finding configured languages', () => {
70
+ const nav = {
71
+ languages: [
72
+ {
73
+ language: 'en',
74
+ default: true,
75
+ pages: [{ title: 'Setup', href: '/hi-fi/setup', language: 'hi-fi' }],
76
+ },
77
+ { language: 'de', pages: [page('/de/setup'), page('/de/hi-fi/setup')] },
78
+ ],
79
+ };
80
+ const [, de] = loose(scopeDecoratedNavToPath(nav, '/hi-fi/setup')).languages;
81
+ expect(de === null || de === void 0 ? void 0 : de.pages).toEqual([{ title: 'de', href: '/de/hi-fi/setup' }]);
82
+ });
46
83
  it('falls back to the default division when the path is not found', () => {
47
84
  const scoped = scopeDecoratedNavToPath(decoratedNav, '/does/not/exist');
48
85
  const [en, es] = loose(scoped).languages;
@@ -28,4 +28,4 @@ export declare function updateFirstHrefInDivision({ type, currentPath, entry, pa
28
28
  activeGroupNames?: Set<string>;
29
29
  activeDivisionOwner?: object;
30
30
  }): void;
31
- export declare function pathsDifferByOneSegment(a: string, b: string, type: 'version' | 'language'): boolean;
31
+ export declare function pathsDifferByOneSegment(a: string, b: string, type: 'version' | 'language', languages?: readonly string[]): boolean;
@@ -1,4 +1,4 @@
1
- import { locales } from '@mintlify/models';
1
+ import { isKnownLocale } from '@mintlify/models';
2
2
  import { divisions, } from '@mintlify/validation';
3
3
  import { readObjectArrayProperty } from '../divisions/iterateObjectArrayProperty.js';
4
4
  import { isEqualIgnoringLeadingSlash } from '../paths/isEqualIgnoringLeadingSlash.js';
@@ -209,29 +209,30 @@ function findActiveGroupNames(entry, currentPath, activeGroupNames = new Set())
209
209
  }
210
210
  return activeGroupNames;
211
211
  }
212
- function parseLanguagePath(segments) {
212
+ const isLanguageSegment = (segment, languages) => {
213
+ if (segment === undefined)
214
+ return false;
215
+ if (isKnownLocale(segment))
216
+ return true;
217
+ const lowerCaseSegment = segment.toLowerCase();
218
+ return languages.some((language) => language.toLowerCase() === lowerCaseSegment);
219
+ };
220
+ function parseLanguagePath(segments, languages) {
213
221
  let index = 0;
214
222
  let locale;
215
223
  let hasDocsBase = false;
216
224
  const firstSegment = segments[0];
217
225
  const firstIsDocsBase = !!firstSegment && ACCEPTED_BASE_PATHS.includes(firstSegment);
218
- const firstIsLocale = !!firstSegment &&
219
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO: Please fix this violation when you can!
220
- locales.includes(firstSegment);
221
226
  if (firstIsDocsBase) {
222
227
  hasDocsBase = true;
223
228
  index = 1;
224
229
  const maybeLocale = segments[index];
225
- if (maybeLocale &&
226
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO: Please fix this violation when you can!
227
- locales.includes(maybeLocale)) {
228
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO: Please fix this violation when you can!
230
+ if (isLanguageSegment(maybeLocale, languages)) {
229
231
  locale = maybeLocale;
230
232
  index++;
231
233
  }
232
234
  }
233
- else if (firstIsLocale) {
234
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- TODO: Please fix this violation when you can!
235
+ else if (isLanguageSegment(firstSegment, languages)) {
235
236
  locale = firstSegment;
236
237
  index = 1;
237
238
  const maybeDocsBase = segments[index];
@@ -283,8 +284,9 @@ function maybeUpdateFirstHrefInDivision(type, href, finalVersion, inActiveGroup,
283
284
  // we make the BOLD assumption that href is a different version of the same page
284
285
  if (currentVersion !== undefined && finalVersion !== undefined) {
285
286
  const existingRef = firstHrefInDivision.get(finalVersion);
287
+ const languages = type === 'language' ? versionStrings : undefined;
286
288
  if ((existingRef === undefined || DivisionMatchLevel.PATH < existingRef.matchLevel) &&
287
- pathsDifferByOneSegment(href, currentPath, type)) {
289
+ pathsDifferByOneSegment(href, currentPath, type, languages)) {
288
290
  firstHrefInDivision.set(finalVersion, { href, matchLevel: DivisionMatchLevel.PATH });
289
291
  }
290
292
  }
@@ -316,18 +318,19 @@ function maybeUpdateFirstHrefInDivision(type, href, finalVersion, inActiveGroup,
316
318
  }
317
319
  }
318
320
  }
319
- export function pathsDifferByOneSegment(a, b, type) {
321
+ export function pathsDifferByOneSegment(a, b, type, languages = []) {
322
+ var _a, _b;
320
323
  const aSegments = a.split('/').filter(Boolean);
321
324
  const bSegments = b.split('/').filter(Boolean);
322
325
  // For language switching, we need to be more strict - paths should be identical except for the language segment
323
326
  // once normalized, content segments should be identical and only locale prefix may differ.
324
327
  if (type === 'language') {
325
- const aPath = parseLanguagePath(aSegments);
326
- const bPath = parseLanguagePath(bSegments);
328
+ const aPath = parseLanguagePath(aSegments, languages);
329
+ const bPath = parseLanguagePath(bSegments, languages);
327
330
  if (aPath.hasDocsBase !== bPath.hasDocsBase)
328
331
  return false;
329
332
  if (!aPath.locale && !bPath.locale) {
330
- return differByOneLocaleSegment(aPath.contentSegments, bPath.contentSegments);
333
+ return differByOneLocaleSegment(aPath.contentSegments, bPath.contentSegments, languages);
331
334
  }
332
335
  // For language switching, the content parts (including version segments) must be identical.
333
336
  if (aPath.contentSegments.length !== bPath.contentSegments.length)
@@ -340,7 +343,7 @@ export function pathsDifferByOneSegment(a, b, type) {
340
343
  // The paths are language variants if locale presence/value differs.
341
344
  if (!aPath.locale && !bPath.locale)
342
345
  return false;
343
- return aPath.locale !== bPath.locale;
346
+ return ((_a = aPath.locale) === null || _a === void 0 ? void 0 : _a.toLowerCase()) !== ((_b = bPath.locale) === null || _b === void 0 ? void 0 : _b.toLowerCase());
344
347
  }
345
348
  const aStartsWithDocs = aSegments[0] && ACCEPTED_BASE_PATHS.includes(aSegments[0]);
346
349
  const bStartsWithDocs = bSegments[0] && ACCEPTED_BASE_PATHS.includes(bSegments[0]);
@@ -377,22 +380,22 @@ export function pathsDifferByOneSegment(a, b, type) {
377
380
  }
378
381
  return true;
379
382
  }
380
- function isLocale(segment) {
381
- return locales.some((locale) => locale === segment);
382
- }
383
- function differByOneLocaleSegment(a, b) {
383
+ function differByOneLocaleSegment(a, b, languages) {
384
384
  if (a.length === b.length) {
385
385
  const mismatches = a.flatMap((segment, i) => (segment === b[i] ? [] : [i]));
386
386
  if (mismatches.length !== 1)
387
387
  return false;
388
388
  const [index] = mismatches;
389
- return index !== undefined && isLocale(a[index]) && isLocale(b[index]);
389
+ return (index !== undefined &&
390
+ isLanguageSegment(a[index], languages) &&
391
+ isLanguageSegment(b[index], languages));
390
392
  }
391
393
  const [longer, shorter] = a.length > b.length ? [a, b] : [b, a];
392
394
  if (longer.length !== shorter.length + 1)
393
395
  return false;
394
396
  const index = longer.findIndex((segment, i) => segment !== shorter[i]);
395
- return (isLocale(longer[index]) && longer.slice(index + 1).every((s, i) => s === shorter[index + i]));
397
+ return (isLanguageSegment(longer[index], languages) &&
398
+ longer.slice(index + 1).every((s, i) => s === shorter[index + i]));
396
399
  }
397
400
  function checkActiveGroup(group, currentPath) {
398
401
  if (isPage(group)) {