Skip to content

Commit

Permalink
🐛 #543 ordered toc, subitem with parent index 10
Browse files Browse the repository at this point in the history
  • Loading branch information
yzhang committed Feb 16, 2021
1 parent 388af61 commit c359515
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 4 deletions.
53 changes: 53 additions & 0 deletions src/test/suite/integration/toc.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,59 @@ suite("TOC.", () => {

});

test("Ordered list (list markers larger than 9)", async () => {
await updateConfiguration({ config: [["markdown.extension.toc.orderedList", true]] });
await testCommand('markdown.extension.toc.create',
[
'# H1',
'# H2',
'# H3',
'# H4',
'# H5',
'# H6',
'# H7',
'# H8',
'# H9',
'# H10',
'## H11',
'### H12',
'',
''
],
new Selection(13, 0, 13, 0),
[
'# H1',
'# H2',
'# H3',
'# H4',
'# H5',
'# H6',
'# H7',
'# H8',
'# H9',
'# H10',
'## H11',
'### H12',
'',
'1. [H1](#h1)',
'2. [H2](#h2)',
'3. [H3](#h3)',
'4. [H4](#h4)',
'5. [H5](#h5)',
'6. [H6](#h6)',
'7. [H7](#h7)',
'8. [H8](#h8)',
'9. [H9](#h9)',
'10. [H10](#h10)',
' 1. [H11](#h11)',
' 1. [H12](#h12)',
''
],
new Selection(25, 0, 25, 0)
);
await resetConfiguration();
});

test("Setext headings", () => {
return testCommand('markdown.extension.toc.create',
[
Expand Down
17 changes: 13 additions & 4 deletions src/toc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,19 +263,28 @@ async function generateTocText(doc: TextDocument): Promise<string> {

// The actual level range of a document can be smaller than settings. So we need to calculate the real start level.
const startDepth = Math.max(tocConfig.startDepth, Math.min(...tocEntries.map(h => h.level)));
const order: number[] = new Array(tocConfig.endDepth - startDepth + 1).fill(0); // Used for ordered list
// Order counter for each heading level (from startDepth to endDepth), used only for ordered list
const orderCounter: number[] = new Array(tocConfig.endDepth - startDepth + 1).fill(0);

tocEntries.forEach(entry => {
const relativeLevel = entry.level - startDepth;
const currHeadingOrder = ++orderCounter[relativeLevel];
let indentationFix = '';
if (tocConfig.orderedList) {
const shift = orderCounter.slice(0, relativeLevel).map(c => String(c).length - 1).reduce((a, b) => a + b, 0);
indentationFix = ' '.repeat(shift);
}

const row = [
docConfig.tab.repeat(relativeLevel),
(tocConfig.orderedList ? (orderedListMarkerIsOne ? '1' : ++order[relativeLevel]) + '.' : tocConfig.listMarker) + ' ',
docConfig.tab.repeat(relativeLevel) + indentationFix,
(tocConfig.orderedList ? (orderedListMarkerIsOne ? '1' : currHeadingOrder) + '.' : tocConfig.listMarker) + ' ',
tocConfig.plaintext ? entry.visibleText : `[${entry.visibleText}](#${entry.slug})`
];
toc.push(row.join(''));

// Reset order counter for its sub-headings
if (tocConfig.orderedList) {
order.fill(0, relativeLevel + 1);
orderCounter.fill(0, relativeLevel + 1);
}
});
while (/^[ \t]/.test(toc[0])) {
Expand Down

2 comments on commit c359515

@Lemmingh
Copy link
Collaborator

Choose a reason for hiding this comment

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

It works, but a bit hard to understand.

I'm wondering if it can be redesigned. We can have a deeper discussion next month.

interface ITocEntry {
    order: number;
    marker: "*" | "-" | "+" | "number" | "one";
    content: Readonly<IHeading>;
    children?: ITocEntry[];
    serialize(): string[];
}

interface IToc {
    children: ITocEntry[];
    serialize(): string[];
}

@yzhang-gh
Copy link
Owner

Choose a reason for hiding this comment

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

Sure, let's discuss it later. (I think this is not as important as other redesigns since it is just a small function.)

Please sign in to comment.