import { describe, it, expect } from "vitest"; import { trimIndentation } from "@triliumnext/commons"; import markdownService from "./markdown.js"; describe("markdown", () => { it("rewrites language of known language tags", () => { const conversionTable = { "nginx": "language-text-x-nginx-conf", "diff": "language-text-x-diff", "javascript": "language-application-javascript-env-backend", "css": "language-text-css", "mips": "language-text-x-asm-mips" }; for (const [ input, output ] of Object.entries(conversionTable)) { const result = markdownService.renderToHtml(trimIndentation`\ \`\`\`${input} Hi \`\`\` `, "title"); expect(result).toBe(trimIndentation`\
Hi
`); } }); it("rewrites language of unknown language tags", () => { const result = markdownService.renderToHtml(trimIndentation`\ \`\`\`unknownlanguage Hi \`\`\` `, "title"); expect(result).toBe(trimIndentation`\
Hi
`); }); it("converts h1 heading", () => { const result = markdownService.renderToHtml(trimIndentation`\ # Hello ## world # another one Hello, world `, "title"); expect(result).toBe(`

Hello

world

another one

Hello, world

`); }); it("parses duplicate title with escape correctly", () => { const titles = [ "What's new", "Node.js, Electron and `better-sqlite3`" ]; for (const title of titles) { const result = markdownService.renderToHtml(trimIndentation`\ # ${title} Hi there `, title) expect(result).toBe(`

Hi there

`); } }); it("trims unnecessary whitespace", () => { const input = `\ ## Heading 1 Title \`\`\` code block 1 second line 2 \`\`\` * Hello * world 1. Hello 2. World `; const expected = `\

Heading 1

Title

code block 1
second line 2
  1. Hello
  2. World
`; expect(markdownService.renderToHtml(input, "Troubleshooting")).toBe(expected); }); it("imports admonitions properly", () => { const space = " "; // editor config trimming space. const input = trimIndentation`\ Before > [!NOTE] > This is a note. > [!TIP] > This is a tip. > [!IMPORTANT] > This is a very important information. > [!CAUTION] > This is a caution. > [!WARNING] > ## Title goes here >${space} > This is a warning. After`; const expected = `

Before

After

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("imports images with same outcome as if inserted from CKEditor", () => { const input = "![](api/attachments/YbkR3wt2zMcA/image/image)"; const expected = `

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("maintains code blocks with XML/HTML", () => { const input = trimIndentation`\ Before \`\`\` ... \`\`\` After`; const expected = trimIndentation`\

Before

<application
                ...
                android:testOnly="false">
                ...
            </application>

After

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("does not escape unneeded characters", () => { const input = `It's important to note that these examples are not natively supported by Trilium out of the box; instead, they demonstrate what you can build within Trilium.`; const expected = `

It's important to note that these examples are not natively supported by Trilium out of the box; instead, they demonstrate what you can build within Trilium.

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("preserves  ", () => { const input = `Hello world.`; const expected = /*html*/`

Hello world.

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("converts non-breaking space character to  ", () => { const input = `Hello\u00a0world.`; const expected = /*html*/`

Hello world.

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("supports normal links", () => { const input = `[Google](https://www.google.com)`; const expected = /*html*/`

Google

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("does not touch relative links", () => { const input = `[Canvas](../../Canvas.html)`; const expected = /*html*/`

Canvas

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("imports back to reference links", () => { const input = `Canvas`; const expected = /*html*/`

Canvas

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("preserves figures and images with sizes", () => { const scenarios = [ /*html*/`
`, /*html*/`
`, /*html*/`` ]; for (const scenario of scenarios) { expect(markdownService.renderToHtml(scenario, "Title")).toStrictEqual(scenario); } }); it("converts inline math expressions into Mathtex format", () => { const input = `The equation is\u00a0$e=mc^{2}$.`; const expected = /*html*/`

The equation is \\(e=mc^{2}\\).

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("converts multiple inline math expressions into Mathtex format", () => { const input = `Energy: $e=mc^{2}$, Force: $F=ma$.`; const expected = /*html*/`

Energy: \\(e=mc^{2}\\), Force: \\(F=ma\\).

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("converts display math expressions into Mathtex format", () => { const input = `$$\sqrt{x^{2}+1}$$`; const expected = /*html*/`

\\[\sqrt{x^{2}+1}\\]

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("preserves escaped math expressions", () => { const scenarios = [ "\\$\\$\sqrt{x^{2}+1}\\$\\$", "The equation is \\$e=mc^{2}\\$." ]; for (const scenario of scenarios) { expect(markdownService.renderToHtml(scenario, "Title")).toStrictEqual(`

${scenario}

`); } }); it("preserves table with column widths", () => { const html = /*html*/`
   
1Go to any location on openstreetmap.org and right click to bring up the context menu. Select the “Show address” item.
2The address will be visible in the top-left of the screen, in the place of the search bar.    

Select the coordinates and copy them into the clipboard.
3Simply paste the value inside the text box into the #geolocation attribute of a child note of the map and then it should be displayed on the map.
`; expect(markdownService.renderToHtml(html, "Title")).toStrictEqual(html); }); it("generates strike-through text", () => { const input = `~~Hello~~ world.`; const expected = /*html*/`

Hello world.

`; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("does not generate additional spacing when importing lists", () => { const input = trimIndentation`\ ### 🐞 Bugfixes * [v0.90.4 docker does not read USER\_UID and USER\_GID from environment](https://github.com/TriliumNext/Notes/issues/331) * [Invalid CSRF token on Android phone](https://github.com/TriliumNext/Notes/issues/318) * [Excess spacing in lists](https://github.com/TriliumNext/Notes/issues/341)`; const expected = [ /*html*/`

🐞 Bugfixes

`, /*html*/`` ].join(""); expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); it("imports todo lists properly", () => { const input = trimIndentation`\ - [x] Hello - [ ] World`; const expected = ``; expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected); }); });