@mintlify/common 1.0.1180 → 1.0.1181

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.
@@ -1,5 +1,6 @@
1
1
  import { decoratedNavigationConfig } from './decoratedNavigationConfig.js';
2
2
  import { filterDivisions, isActiveDivision } from './filterDivisions.js';
3
+ import { DivisionMatchLevel } from './updateFirstHrefInDivision.js';
3
4
  describe(filterDivisions, () => {
4
5
  var _a;
5
6
  const defaultArgs = {
@@ -222,6 +223,52 @@ describe(filterDivisions, () => {
222
223
  } }));
223
224
  expect((_a = result.firstHrefInLanguage.get('es')) === null || _a === void 0 ? void 0 : _a.href).toBe('/es/docs/2025_12/getting-started');
224
225
  });
226
+ describe('when the locale follows a version segment', () => {
227
+ const versions = ['26.3', '26.2'];
228
+ const langs = ['en', 'ja'];
229
+ const pagesFor = (base) => ({
230
+ tabs: [
231
+ {
232
+ tab: 'Docs',
233
+ groups: [
234
+ {
235
+ group: 'Getting Started',
236
+ pages: [
237
+ { title: 'Overview', href: `/${base}/overview` },
238
+ { title: 'Getting Started', href: `/${base}/getting-started/getting-started` },
239
+ ],
240
+ },
241
+ ],
242
+ },
243
+ ],
244
+ });
245
+ const prefixed = (version, language) => `${version}/${language}`;
246
+ const unprefixedDefault = (version, language) => language === 'en' ? version : `${version}/${language}`;
247
+ it.each([
248
+ { nesting: 'languages > versions', base: prefixed, languagesFirst: true },
249
+ { nesting: 'versions > languages', base: prefixed, languagesFirst: false },
250
+ { nesting: 'an unprefixed default language', base: unprefixedDefault, languagesFirst: true },
251
+ ])('matches the translated page with $nesting', ({ base, languagesFirst }) => {
252
+ const decoratedNav = languagesFirst
253
+ ? {
254
+ languages: langs.map((language) => ({
255
+ language,
256
+ versions: versions.map((version) => (Object.assign({ version }, pagesFor(base(version, language))))),
257
+ })),
258
+ }
259
+ : {
260
+ versions: versions.map((version) => ({
261
+ version,
262
+ languages: langs.map((language) => (Object.assign({ language }, pagesFor(base(version, language))))),
263
+ })),
264
+ };
265
+ const result = filterDivisions(Object.assign(Object.assign({}, defaultArgs), { currentPath: `/${base('26.3', 'en')}/getting-started/getting-started`, currentVersion: '26.3', currentLanguage: 'en', decoratedNav }));
266
+ expect(result.firstHrefInLanguage.get('ja')).toEqual({
267
+ href: '/26.3/ja/getting-started/getting-started',
268
+ matchLevel: DivisionMatchLevel.PATH,
269
+ });
270
+ });
271
+ });
225
272
  });
226
273
  describe('filterDivisions with partial auth', () => {
227
274
  const defaultArgs = {
@@ -56,6 +56,49 @@ describe('pathsDifferByOneSegment', () => {
56
56
  expect(pathsDifferByOneSegment('/es/docs/2025_12/getting-started', '/docs/getting-started', 'language')).toBe(false);
57
57
  });
58
58
  });
59
+ describe('version-prefixed locale paths', () => {
60
+ it('returns true when only the locale after a version segment differs', () => {
61
+ expect(pathsDifferByOneSegment('/26.3/ja/getting-started/getting-started', '/26.3/en/getting-started/getting-started', 'language')).toBe(true);
62
+ expect(pathsDifferByOneSegment('26.3/ja/intro', '/26.3/en/intro', 'language')).toBe(true);
63
+ expect(pathsDifferByOneSegment('/docs/v2/ja/intro', '/docs/v2/en/intro', 'language')).toBe(true);
64
+ });
65
+ it('handles version-prefixed locale index pages', () => {
66
+ expect(pathsDifferByOneSegment('/26.3/ja/index', '/26.3/en', 'language')).toBe(true);
67
+ });
68
+ it('returns false when the version also differs', () => {
69
+ expect(pathsDifferByOneSegment('/26.2/ja/intro', '/26.3/en/intro', 'language')).toBe(false);
70
+ });
71
+ it('returns false when the differing segment is not a locale on both sides', () => {
72
+ expect(pathsDifferByOneSegment('/26.3/ja/intro', '/26.3/guides/intro', 'language')).toBe(false);
73
+ expect(pathsDifferByOneSegment('/26.2/intro', '/26.3/intro', 'language')).toBe(false);
74
+ });
75
+ it('returns false when the locale is the same', () => {
76
+ expect(pathsDifferByOneSegment('/26.3/ja/intro', '/26.3/ja/intro', 'language')).toBe(false);
77
+ });
78
+ it('returns false when content after the locale differs', () => {
79
+ expect(pathsDifferByOneSegment('/26.3/ja/intro', '/26.3/en/quickstart', 'language')).toBe(false);
80
+ });
81
+ });
82
+ describe('version-prefixed paths with an unprefixed default language', () => {
83
+ it('returns true when one path adds a locale after the version', () => {
84
+ expect(pathsDifferByOneSegment('/v2/es/overview', '/v2/overview', 'language')).toBe(true);
85
+ expect(pathsDifferByOneSegment('/v2/overview', '/v2/es/overview', 'language')).toBe(true);
86
+ expect(pathsDifferByOneSegment('/docs/v2/es/guides/setup', '/docs/v2/guides/setup', 'language')).toBe(true);
87
+ });
88
+ it('handles unprefixed default index pages', () => {
89
+ expect(pathsDifferByOneSegment('/v2/es/index', '/v2', 'language')).toBe(true);
90
+ });
91
+ it('returns false when the extra segment is not a locale', () => {
92
+ expect(pathsDifferByOneSegment('/v2/guides/overview', '/v2/overview', 'language')).toBe(false);
93
+ });
94
+ it('returns false when the rest of the path differs', () => {
95
+ expect(pathsDifferByOneSegment('/v2/es/overview', '/v1/overview', 'language')).toBe(false);
96
+ expect(pathsDifferByOneSegment('/v2/es/overview', '/v2/quickstart', 'language')).toBe(false);
97
+ });
98
+ it('returns false when the paths differ by more than one segment', () => {
99
+ expect(pathsDifferByOneSegment('/v2/es/ja/overview', '/v2/overview', 'language')).toBe(false);
100
+ });
101
+ });
59
102
  });
60
103
  describe('version type', () => {
61
104
  it('returns true for paths that differ by one segment (not last)', () => {
@@ -326,6 +326,9 @@ export function pathsDifferByOneSegment(a, b, type) {
326
326
  const bPath = parseLanguagePath(bSegments);
327
327
  if (aPath.hasDocsBase !== bPath.hasDocsBase)
328
328
  return false;
329
+ if (!aPath.locale && !bPath.locale) {
330
+ return differByOneLocaleSegment(aPath.contentSegments, bPath.contentSegments);
331
+ }
329
332
  // For language switching, the content parts (including version segments) must be identical.
330
333
  if (aPath.contentSegments.length !== bPath.contentSegments.length)
331
334
  return false;
@@ -374,6 +377,23 @@ export function pathsDifferByOneSegment(a, b, type) {
374
377
  }
375
378
  return true;
376
379
  }
380
+ function isLocale(segment) {
381
+ return locales.some((locale) => locale === segment);
382
+ }
383
+ function differByOneLocaleSegment(a, b) {
384
+ if (a.length === b.length) {
385
+ const mismatches = a.flatMap((segment, i) => (segment === b[i] ? [] : [i]));
386
+ if (mismatches.length !== 1)
387
+ return false;
388
+ const [index] = mismatches;
389
+ return index !== undefined && isLocale(a[index]) && isLocale(b[index]);
390
+ }
391
+ const [longer, shorter] = a.length > b.length ? [a, b] : [b, a];
392
+ if (longer.length !== shorter.length + 1)
393
+ return false;
394
+ 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]));
396
+ }
377
397
  function checkActiveGroup(group, currentPath) {
378
398
  if (isPage(group)) {
379
399
  return isEqualIgnoringLeadingSlash(group.href, currentPath);