mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-09-07 08:01:34 +08:00
feat(markdown): use different approach for reference links
This commit is contained in:
parent
4f22850ea9
commit
6a69e9b208
@ -238,9 +238,15 @@ describe("Markdown export", () => {
|
||||
expect(markdownExportService.toMarkdown(html)).toBe(expected);
|
||||
});
|
||||
|
||||
it("exports reference links as normal links", () => {
|
||||
it("exports normal links verbatim", () => {
|
||||
const html = /*html*/`<p><a href="https://www.google.com">Google</a></p>`;
|
||||
const expected = `[Google](https://www.google.com)`;
|
||||
expect(markdownExportService.toMarkdown(html)).toBe(expected);
|
||||
});
|
||||
|
||||
it("exports reference links verbatim", () => {
|
||||
const html = /*html*/`<p><a class="reference-link" href="../../Canvas.html">Canvas</a></p>`;
|
||||
const expected = `[Canvas](../../Canvas.html)`;
|
||||
const expected = `<a class="reference-link" href="../../Canvas.html">Canvas</a>`;
|
||||
expect(markdownExportService.toMarkdown(html)).toBe(expected);
|
||||
});
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
import TurndownService from "turndown";
|
||||
import TurndownService, { type Rule } from "turndown";
|
||||
import { gfm } from "../../../packages/turndown-plugin-gfm/src/gfm.js";
|
||||
import type { DOMElement } from "react";
|
||||
|
||||
let instance: TurndownService | null = null;
|
||||
|
||||
@ -43,6 +44,7 @@ function toMarkdown(content: string) {
|
||||
instance.addRule("fencedCodeBlock", fencedCodeBlockFilter);
|
||||
instance.addRule("img", buildImageFilter());
|
||||
instance.addRule("admonition", buildAdmonitionFilter());
|
||||
instance.addRule("inlineLink", buildInlineLinkFilter());
|
||||
instance.use(gfm);
|
||||
instance.keep([ "kbd" ]);
|
||||
}
|
||||
@ -93,10 +95,6 @@ function buildImageFilter() {
|
||||
return title.replace(/"/g, '\\"')
|
||||
}
|
||||
|
||||
function cleanAttribute (attribute: string) {
|
||||
return attribute ? attribute.replace(/(\n+\s*)+/g, '\n') : ''
|
||||
}
|
||||
|
||||
const imageFilter: TurndownService.Rule = {
|
||||
filter: "img",
|
||||
replacement(content, node) {
|
||||
@ -153,6 +151,48 @@ function buildAdmonitionFilter() {
|
||||
return admonitionFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Variation of the original ruleset: https://github.com/mixmark-io/turndown/blob/master/src/commonmark-rules.js.
|
||||
*
|
||||
* Detects if the URL is a Trilium reference link and returns it verbatim if that's the case.
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
function buildInlineLinkFilter(): Rule {
|
||||
return {
|
||||
filter: function (node, options) {
|
||||
return (
|
||||
options.linkStyle === 'inlined' &&
|
||||
node.nodeName === 'A' &&
|
||||
!!node.getAttribute('href')
|
||||
)
|
||||
},
|
||||
|
||||
replacement: function (content, _node) {
|
||||
const node = _node as HTMLElement;
|
||||
|
||||
// Return reference links verbatim.
|
||||
if (node.classList.contains("reference-link")) {
|
||||
return node.outerHTML;
|
||||
}
|
||||
|
||||
// Otherwise treat as normal.
|
||||
// TODO: Call super() somehow instead of duplicating the implementation.
|
||||
var href = node.getAttribute('href')
|
||||
if (href) href = href.replace(/([()])/g, '\\$1')
|
||||
var title = cleanAttribute(node.getAttribute('title'))
|
||||
if (title) title = ' "' + title.replace(/"/g, '\\"') + '"'
|
||||
return '[' + content + '](' + href + title + ')'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Taken from upstream since it's not exposed.
|
||||
// https://github.com/mixmark-io/turndown/blob/master/src/commonmark-rules.js
|
||||
function cleanAttribute(attribute: string | null | undefined) {
|
||||
return attribute ? attribute.replace(/(\n+\s*)+/g, '\n') : ''
|
||||
}
|
||||
|
||||
export default {
|
||||
toMarkdown
|
||||
};
|
||||
|
@ -151,8 +151,14 @@ second line 2</code></pre><ul><li>Hello</li><li>world</li></ul><ol><li>Hello</li
|
||||
expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it("imports back to reference links", () => {
|
||||
it("does not touch relative links", () => {
|
||||
const input = `[Canvas](../../Canvas.html)`;
|
||||
const expected = /*html*/`<p><a href="../../Canvas.html">Canvas</a></p>`;
|
||||
expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it("imports back to reference links", () => {
|
||||
const input = `<a class="reference-link" href="../../Canvas.html">Canvas</a>`;
|
||||
const expected = /*html*/`<p><a class="reference-link" href="../../Canvas.html">Canvas</a></p>`;
|
||||
expect(markdownService.renderToHtml(input, "Title")).toStrictEqual(expected);
|
||||
});
|
||||
|
@ -64,17 +64,6 @@ class CustomMarkdownRenderer extends Renderer {
|
||||
return `<blockquote>${body}</blockquote>`;
|
||||
}
|
||||
|
||||
link(data: Tokens.Link): string {
|
||||
let html = super.link(data);
|
||||
|
||||
// Rewrite local/relative links back to reference links.
|
||||
if (data.href.indexOf("://") === -1) {
|
||||
html = html.replace(/^<a /, `<a class="reference-link" `);
|
||||
}
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const renderer = new CustomMarkdownRenderer({ async: false });
|
||||
|
Loading…
x
Reference in New Issue
Block a user