server(export): export Markdown using ATX heading syntax (closes #1251)

This commit is contained in:
Elian Doran 2025-02-22 12:45:21 +02:00
parent a1bfc6aae7
commit 411e3dfa0e
No known key found for this signature in database
3 changed files with 60 additions and 1 deletions

View File

@ -1,3 +1,35 @@
/**
* Reads the level of indentation of the first line and trims the identation for all the text by that amount.
*
* For example, for:
*
* ```json
* {
* "hello": "world"
* }
* ```
*
* it results in:
*
* ```json
* {
* "hello": "world"
* }
* ```
*
* This is meant to be used as a template string, where it allows the indentation of the template without affecting whitespace changes.
*
* @example const html = trimIndentation`\
* <h1>Heading 1</h1>
* <h2>Heading 2</h2>
* <h3>Heading 3</h3>
* <h4>Heading 4</h4>
* <h5>Heading 5</h5>
* <h6>Heading 6</h6>
* `;
* @param strings
* @returns
*/
export function trimIndentation(strings: TemplateStringsArray) { export function trimIndentation(strings: TemplateStringsArray) {
const str = strings.toString(); const str = strings.toString();

View File

@ -74,4 +74,28 @@ describe("Markdown export", () => {
const expected = "~~hello~~Hello ~~world~~"; const expected = "~~hello~~Hello ~~world~~";
expect(markdownExportService.toMarkdown(html)).toBe(expected); expect(markdownExportService.toMarkdown(html)).toBe(expected);
}); });
it("exports headings properly", () => {
const html = trimIndentation`\
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
`;
const expected = trimIndentation`\
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6`;
expect(markdownExportService.toMarkdown(html)).toBe(expected);
});
}); });

View File

@ -24,7 +24,10 @@ const fencedCodeBlockFilter: TurndownService.Rule = {
function toMarkdown(content: string) { function toMarkdown(content: string) {
if (instance === null) { if (instance === null) {
instance = new TurndownService({ codeBlockStyle: "fenced" }); instance = new TurndownService({
headingStyle: "atx",
codeBlockStyle: "fenced"
});
// Filter is heavily based on: https://github.com/mixmark-io/turndown/issues/274#issuecomment-458730974 // Filter is heavily based on: https://github.com/mixmark-io/turndown/issues/274#issuecomment-458730974
instance.addRule("fencedCodeBlock", fencedCodeBlockFilter); instance.addRule("fencedCodeBlock", fencedCodeBlockFilter);
instance.use(turndownPluginGfm.gfm); instance.use(turndownPluginGfm.gfm);