Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/validators/duplicates.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,21 @@ export function validateAll(files) {
if (!CHECKED_DIRS.includes(topDir)) continue;

const filename = path.basename(relPath);
if (filename === 'index.md' || filename === 'index.mdx') continue;
const isIndex = filename === 'index.md' || filename === 'index.mdx';

// A folder's index.md is a category page whose slug is the folder name, so
// it competes for a slug just like a `<slug>.md` file does. Any other file's
// slug is its own filename. Skip a section-root index (docs/index.md,
// reference/index.md) — it has no competing leaf slug.
let slug;
if (isIndex) {
const parent = path.basename(path.dirname(relPath));
if (parent === topDir) continue;
slug = parent;
Comment on lines +26 to +28

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Fix false negative for nested folders matching the section name.

The section-root check only compares the parent folder's name (path.basename) to topDir. This incorrect conditional will erroneously skip valid category index pages if they reside in a nested folder that happens to share the same name as the top directory (e.g., docs/api/docs/index.md).

Compare the entire parentDir path to topDir instead to accurately isolate section-root files. I also recommend adding a test case like ['docs/a/docs/index.md', 'docs/a/docs.md'] to the test suite to prevent future regressions.

🐛 Proposed fix
-      const parent = path.basename(path.dirname(relPath));
-      if (parent === topDir) continue;
-      slug = parent;
+      const parentDir = path.dirname(relPath);
+      if (parentDir === topDir) continue;
+      slug = path.basename(parentDir);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const parent = path.basename(path.dirname(relPath));
if (parent === topDir) continue;
slug = parent;
const parentDir = path.dirname(relPath);
if (parentDir === topDir) continue;
slug = path.basename(parentDir);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/validators/duplicates.js` around lines 26 - 28, Update the section-root
check in the duplicate validation logic to compare the full parentDir path with
topDir rather than comparing path.basename(parentDir). Preserve slug assignment
for nested folders, including cases such as docs/a/docs/index.md, and add a
regression test covering the recommended nested-path inputs.

} else {
slug = filename.replace(/\.(md|mdx)$/, '');
}

const slug = filename.replace(/\.(md|mdx)$/, '');
const key = `${topDir}:${slug}`;
if (!slugMap.has(key)) slugMap.set(key, []);
slugMap.get(key).push(relPath);
Expand Down
33 changes: 33 additions & 0 deletions test/duplicates.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,36 @@ test('same slug within docs (different subdirs) is flagged', () => {
assert.match(res[0].message, /Duplicate slug: "intro"/);
assert.equal(res[0].severity, 'error');
});

test('a page slug colliding with a category folder (folder/index.md) is flagged', () => {
const res = validateAll([
'reference/API/Other/guides.md',
'reference/API/Other/guides/index.md',
]);
assert.ok(Array.isArray(res) && res.length >= 1, 'expected a duplicate-slug error');
assert.match(res[0].message, /Duplicate slug: "guides"/);
});

test('category-folder slug collisions are section-wide, not per-folder', () => {
// A page in one subdir and a category folder in another, same section.
const res = validateAll([
'reference/A/guides.md',
'reference/B/guides/index.md',
]);
assert.ok(Array.isArray(res) && res.length >= 1);
assert.match(res[0].message, /Duplicate slug: "guides"/);
});

test('a section-root index page is not treated as a competing slug', () => {
// reference/index.md is the section landing; it must not collide with anything.
const res = validateAll(['reference/index.md', 'reference/foo.md']);
assert.equal(res, null);
});

test('a category folder slug in reference does not collide with the same slug in docs', () => {
const res = validateAll([
'docs/guides.md',
'reference/API/Other/guides/index.md',
]);
assert.equal(res, null, 'docs and reference are separate namespaces');
});