Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,73 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Generic includer > should keep directory name as folder name when linkIndex is enabled by default 1`] = `
"path: toc.yaml
items:
- href: index.md
- href: test.md
- name: sub
href: sub/index.md
items:
- href: sub/sub-1.md
- href: sub/sub-2.md
- name: sub
items:
- href: sub/sub/sub-3.md
- name: skip
items:
- name: sub
items:
- href: skip/sub/sub-1.md
"
`;

exports[`Generic includer > should keep folder name when linkIndexAutotitle is set but autotitle is disabled 1`] = `
"path: toc.yaml
items:
- name: index
href: index.md
- name: test
href: test.md
- name: sub
href: sub/index.md
items:
- name: sub-1
href: sub/sub-1.md
- name: sub-2
href: sub/sub-2.md
- name: sub
items:
- name: sub-3
href: sub/sub/sub-3.md
- name: skip
items:
- name: sub
items:
- name: sub-1
href: skip/sub/sub-1.md
"
`;

exports[`Generic includer > should leave directory name empty when linkIndexAutotitle is enabled 1`] = `
"path: toc.yaml
items:
- href: index.md
- href: test.md
- href: sub/index.md
items:
- href: sub/sub-1.md
- href: sub/sub-2.md
- name: sub
items:
- href: sub/sub/sub-3.md
- name: skip
items:
- name: sub
items:
- href: skip/sub/sub-1.md
"
`;

exports[`Generic includer > should preserve insertion order without orderBy 1`] = `
"path: toc.yaml
items:
Expand Down Expand Up @@ -116,6 +184,33 @@ items:
"
`;

exports[`Generic includer > should use directory name when linkIndex is enabled and autotitle is disabled 1`] = `
"path: toc.yaml
items:
- name: index
href: index.md
- name: test
href: test.md
- name: sub
href: sub/index.md
items:
- name: sub-1
href: sub/sub-1.md
- name: sub-2
href: sub/sub-2.md
- name: sub
items:
- name: sub-3
href: sub/sub/sub-3.md
- name: skip
items:
- name: sub
items:
- name: sub-1
href: skip/sub/sub-1.md
"
`;

exports[`Generic includer > should use top path as input root, if input is not specified 1`] = `
"path: toc.yaml
items:
Expand Down
132 changes: 132 additions & 0 deletions src/extensions/generic-includer/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,4 +247,136 @@ describe('Generic includer', () => {

expect(dump(result)).toMatchSnapshot();
});

it('should keep directory name as folder name when linkIndex is enabled by default', async () => {
const {run} = await prepareExtension([
[
'**/*.md',
'./test',
[
'index.md',
'test.md',
'sub/index.md',
'sub/sub-1.md',
'sub/sub-2.md',
'sub/sub/sub-3.md',
'skip/sub/sub-1.md',
] as NormalizedPath[],
],
]);

const result = await getTocHooks(run.toc)
.Includer.for('generic')
.promise(
{path: 'toc.yaml' as NormalizedPath},
{
input: './test',
path: './test/toc.yaml',
linkIndex: true,
},
'toc.yaml' as NormalizedPath,
);

expect(dump(result)).toMatchSnapshot();
});

it('should leave directory name empty when linkIndexAutotitle is enabled', async () => {
const {run} = await prepareExtension([
[
'**/*.md',
'./test',
[
'index.md',
'test.md',
'sub/index.md',
'sub/sub-1.md',
'sub/sub-2.md',
'sub/sub/sub-3.md',
'skip/sub/sub-1.md',
] as NormalizedPath[],
],
]);

const result = await getTocHooks(run.toc)
.Includer.for('generic')
.promise(
{path: 'toc.yaml' as NormalizedPath},
{
input: './test',
path: './test/toc.yaml',
linkIndex: true,
linkIndexAutotitle: true,
},
'toc.yaml' as NormalizedPath,
);

expect(dump(result)).toMatchSnapshot();
});

it('should keep folder name when linkIndexAutotitle is set but autotitle is disabled', async () => {
const {run} = await prepareExtension([
[
'**/*.md',
'./test',
[
'index.md',
'test.md',
'sub/index.md',
'sub/sub-1.md',
'sub/sub-2.md',
'sub/sub/sub-3.md',
'skip/sub/sub-1.md',
] as NormalizedPath[],
],
]);

const result = await getTocHooks(run.toc)
.Includer.for('generic')
.promise(
{path: 'toc.yaml' as NormalizedPath},
{
input: './test',
path: './test/toc.yaml',
autotitle: false,
linkIndex: true,
linkIndexAutotitle: true,
},
'toc.yaml' as NormalizedPath,
);

expect(dump(result)).toMatchSnapshot();
});

it('should use directory name when linkIndex is enabled and autotitle is disabled', async () => {
const {run} = await prepareExtension([
[
'**/*.md',
'./test',
[
'index.md',
'test.md',
'sub/index.md',
'sub/sub-1.md',
'sub/sub-2.md',
'sub/sub/sub-3.md',
'skip/sub/sub-1.md',
] as NormalizedPath[],
],
]);

const result = await getTocHooks(run.toc)
.Includer.for('generic')
.promise(
{path: 'toc.yaml' as NormalizedPath},
{
input: './test',
path: './test/toc.yaml',
autotitle: false,
linkIndex: true,
},
'toc.yaml' as NormalizedPath,
);

expect(dump(result)).toMatchSnapshot();
});
});
29 changes: 22 additions & 7 deletions src/extensions/generic-includer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Options = IncluderOptions<{
input?: RelativePath;
autotitle?: boolean;
linkIndex?: boolean;
linkIndexAutotitle?: boolean;
order?: Order;
orderBy?: OrderBy;
}>;
Expand Down Expand Up @@ -120,17 +121,31 @@ function fillToc(toc: RawToc, graph: Graph, options: Options) {
if (options.linkIndex) {
const indexEntry = entries.find(([k]) => k === 'index');
const childEntries = entries.filter(([k]) => k !== 'index');
const indexHref =
indexEntry && typeof indexEntry[1] === 'string' ? indexEntry[1] : undefined;

if (indexHref) {
const useIndexHeading =
options.linkIndexAutotitle === true && options.autotitle !== false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why not options.linkIndexAutotitle && !options.autotitle?

Copy link
Copy Markdown
Contributor Author

@martyanovandrey martyanovandrey May 5, 2026

Choose a reason for hiding this comment

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

The suggestion inverts the semantics. options.autotitle !== false is true when autotitle is enabled (true or undefined), while !options.autotitle is true when it's disabled (false or undefined). We need the former — deriving a title from index.md's H1 only makes sense when autotitle isn't disabled. The should keep folder name when linkIndexAutotitle is set but autotitle is disabled test covers this.

const result = {
href: indexHref,
items: childEntries.map(item),
};

if (useIndexHeading) {
Comment thread
martyanovandrey marked this conversation as resolved.
return result;
}

return {
name: key as YfmString,
...result,
};
}

const result: RawTocItem = {
return {
name: key as YfmString,
items: childEntries.map(item),
};

if (indexEntry && typeof indexEntry[1] === 'string') {
result.href = indexEntry[1];
}

return result;
}

return {name: key as YfmString, items: entries.map(item)};
Expand Down
Loading
Loading