insta-toc
Version:
Simultaneously generate, update, and maintain a table of contents for your notes in real time.
200 lines (163 loc) • 8.25 kB
text/typescript
import { describe, test, expect, beforeEach, afterEach } from 'vitest';
import {
testStandardHeadings,
testHandleLinks,
testHeadingsWithoutFirstLevel,
testHeadingsMixed,
testHeadingsWithSpecialChars,
testOmitHeadingRegex,
TestNames,
TestName,
Context,
initialStandardHeadings,
initialHeadingsWithSpecialChars,
initialHeadingsWithoutFirstLevel,
initialHeadingsMixed
} from "./testingObjects";
function testGetIndentationLevel(headingLevel: number, headingLevelStack: number[]) {
// Pop from the stack until we find a heading level less than the current
while (
headingLevelStack.length > 0 && // Avoid indentation for the first heading
headingLevel <= headingLevelStack[headingLevelStack.length - 1]
) {
headingLevelStack.pop();
}
headingLevelStack.push(headingLevel);
const currentIndentLevel = headingLevelStack.length - 1;
return { currentIndentLevel, headingLevelStack };
}
describe('Headings', () => {
let iteration = 0;
let testId: TestName;
const contextObject: Context = {
"testStandardHeadings": {
"initialHeadings": initialStandardHeadings,
"formattedHeadings": [],
"finalResult": ""
},
"testHeadingsWithoutFirstLevel": {
"initialHeadings": initialHeadingsWithoutFirstLevel,
"formattedHeadings": [],
"finalResult": ""
},
"testHeadingsMixed": {
"initialHeadings": initialHeadingsMixed,
"formattedHeadings": [],
"finalResult": ""
},
"testHeadingsWithSpecialChars": {
"initialHeadings": initialHeadingsWithSpecialChars,
"formattedHeadings": [],
"finalResult": ""
}
}
beforeEach(() => {
testId = TestNames[iteration] as TestName;
console.log(`${'#'.repeat(10)}\n${testId}\n${'#'.repeat(10)}\n${contextObject[testId].initialHeadings.join('\n')}`);
});
afterEach(() => {
const finalResultArray = contextObject[testId].finalResult.split('\n')
.reduce<[string, string | undefined][]>((acc, item, index) => {
acc.push([contextObject[testId].initialHeadings[index], item]);
return acc;
}, [])
.flatMap(([val1, val2]) => `\n${val1}\n⬇️ ⬇️ ⬇️\n${val2}\n`); // Explicitly define the initial value type as an array of tuples
console.log(`\nFINAL RESULT:\n${finalResultArray}\n\n${'='.repeat(100)}\n${'='.repeat(100)}\n${'='.repeat(100)}\n\n`);
iteration += 1;
});
test('Returns indented list with links', () => {
const md = (() => {
let testHeadingLevelStack: number[] = [];
const testHeadings: string[] = [];
testStandardHeadings.forEach((test) => {
const { currentIndentLevel, headingLevelStack } = testGetIndentationLevel(test.level, testHeadingLevelStack);
testHeadingLevelStack = headingLevelStack;
const heading = testHandleLinks('testStandardHeadings', test.heading, currentIndentLevel);
testHeadings.push(heading);
contextObject[testId].formattedHeadings.push(heading);
});
return testHeadings.join('\n');
})();
const expectedMd = `
- [[testStandardHeadings#Title 1 Level 1|Title 1 Level 1]]
- [[testStandardHeadings#Title 1 Level 2|Title 1 Level 2]]
- [[testStandardHeadings#Title 1 Level 3|Title 1 Level 3]]
- [[testStandardHeadings#Title 1 Level 4|Title 1 Level 4]]
- [[testStandardHeadings#Title 1 Level 5|Title 1 Level 5]]
- [[testStandardHeadings#Title 1 Level 6|Title 1 Level 6]]
`.trim();
contextObject[testId].finalResult = md;
expect(md).toEqual(expectedMd);
});
test('Returns indented list with links if no first level', () => {
const md = (() => {
let testHeadingLevelStack: number[] = [];
const testHeadings: string[] = [];
testHeadingsWithoutFirstLevel.forEach((test) => {
const { currentIndentLevel, headingLevelStack } = testGetIndentationLevel(test.level, testHeadingLevelStack);
testHeadingLevelStack = headingLevelStack;
const heading = testHandleLinks('testHeadingsWithoutFirstLevel', test.heading, currentIndentLevel);
testHeadings.push(heading);
contextObject[testId].formattedHeadings.push(heading);
});
return testHeadings.join('\n');
})();
const expectedMd = `
- [[testHeadingsWithoutFirstLevel#Title 1 Level 2|Title 1 Level 2]]
- [[testHeadingsWithoutFirstLevel#Title 1 Level 3|Title 1 Level 3]]
- [[testHeadingsWithoutFirstLevel#Title 1 Level 4|Title 1 Level 4]]
- [[testHeadingsWithoutFirstLevel#Title 1 Level 5|Title 1 Level 5]]
- [[testHeadingsWithoutFirstLevel#Title 1 Level 6|Title 1 Level 6]]
`.trim();
contextObject[testId].finalResult = md;
expect(md).toEqual(expectedMd);
});
test('Returns indented list from disorderly headings', () => {
const md = (() => {
let testHeadingLevelStack: number[] = [];
const testHeadings: string[] = [];
testHeadingsMixed.forEach((test) => {
const { currentIndentLevel, headingLevelStack } = testGetIndentationLevel(test.level, testHeadingLevelStack);
testHeadingLevelStack = headingLevelStack;
const heading = testHandleLinks('testHeadingsMixed', test.heading, currentIndentLevel);
testHeadings.push(heading);
contextObject[testId].formattedHeadings.push(heading);
});
return testHeadings.join('\n');
})();
const expectedMd = `
- [[testHeadingsMixed#Title 1 Level 4|Title 1 Level 4]]
- [[testHeadingsMixed#Title 1 Level 1|Title 1 Level 1]]
- [[testHeadingsMixed#Title 1 Level 6|Title 1 Level 6]]
- [[testHeadingsMixed#Title 1 Level 2|Title 1 Level 2]]
- [[testHeadingsMixed#Title 2 Level 2|Title 2 Level 2]]
- [[testHeadingsMixed#Title 1 Level 3|Title 1 Level 3]]
`.trim();
contextObject[testId].finalResult = md;
expect(md).toEqual(expectedMd);
});
test('Returns indented list with sanitized links from special chars and HTML', () => {
const md = (() => {
let testHeadingLevelStack: number[] = [];
const testHeadings: string[] = [];
testHeadingsWithSpecialChars.forEach((test) => {
if (!test.heading.match(testOmitHeadingRegex)) {
const { currentIndentLevel, headingLevelStack } = testGetIndentationLevel(test.level, testHeadingLevelStack);
testHeadingLevelStack = headingLevelStack;
const heading = testHandleLinks('testHeadingsWithSpecialChars', test.heading, currentIndentLevel);
testHeadings.push(heading);
contextObject[testId].formattedHeadings.push(heading);
}
});
return testHeadings.join('\n');
})();
const expectedMd = `
- [[testHeadingsWithSpecialChars#Title 1 \`level 1\` {with special chars}, **bold**, _italic_, a-tag, ==highlighted== and ~~strikethrough~~ text|Title 1 level 1 with special chars, bold, italic, a-tag, highlighted and strikethrough text]]
- [[testHeadingsWithSpecialChars#Title 1 level 2 <em style="color: black">with HTML</em>|Title 1 level 2 with HTML]]
- [[testHeadingsWithSpecialChars#Title 1 level 3 wikilink1 wikilink2 wikitext2 [mdlink](https://mdurl)|Title 1 level 3 wikilink1 wikitext2 mdlink]]
- [[testHeadingsWithSpecialChars#Title 1 level 4 wikilink1 wikilink2 wikitext2 [mdlink1](https://mdurl) wikilink3 wikilink4 wikitext3 [mdlink2](https://mdurl)|Title 1 level 4 wikilink1 wikitext2 mdlink1 wikilink3 wikitext3 mdlink2]]
`.trim();
contextObject[testId].finalResult = md;
expect(md).toEqual(expectedMd);
});
});