Merge pull request #1040 from datopian/fix/broken-urls-with-dashes

Support wiki links with special characters and fix links to headings
This commit is contained in:
Leonardo Yuri Farias 2023-11-02 19:40:53 -03:00 committed by GitHub
commit f17c2ed1d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 47 additions and 5 deletions

View File

@ -0,0 +1,5 @@
---
'@portaljs/remark-wiki-link': patch
---
Changed regex to permit any symbols other than #

View File

@ -79,7 +79,7 @@ function fromMarkdown(opts: FromMarkdownOptions = {}) {
data: { isEmbed, target, alias }, data: { isEmbed, target, alias },
} = wikiLink; } = wikiLink;
// eslint-disable-next-line no-useless-escape // eslint-disable-next-line no-useless-escape
const wikiLinkWithHeadingPattern = /([\p{Letter}\d\s\/\.-_]*)(#.*)?/u; const wikiLinkWithHeadingPattern = /^(.*?)(#.*)?$/u;
const [, path, heading = ""] = target.match(wikiLinkWithHeadingPattern); const [, path, heading = ""] = target.match(wikiLinkWithHeadingPattern);
const possibleWikiLinkPermalinks = wikiLinkResolver(path); const possibleWikiLinkPermalinks = wikiLinkResolver(path);
@ -116,7 +116,7 @@ function fromMarkdown(opts: FromMarkdownOptions = {}) {
// remove leading # if the target is a heading on the same page // remove leading # if the target is a heading on the same page
const displayName = alias || target.replace(/^#/, ""); const displayName = alias || target.replace(/^#/, "");
const headingId = heading.replace(/\s+/, "-").toLowerCase(); const headingId = heading.replace(/\s+/g, "-").toLowerCase();
let classNames = wikiLinkClassName; let classNames = wikiLinkClassName;
if (!matchingPermalink) { if (!matchingPermalink) {
classNames += " " + newClassName; classNames += " " + newClassName;

View File

@ -64,7 +64,7 @@ function html(opts: HtmlOptions = {}) {
const { target, alias } = wikiLink; const { target, alias } = wikiLink;
const isEmbed = token.isType === "embed"; const isEmbed = token.isType === "embed";
// eslint-disable-next-line no-useless-escape // eslint-disable-next-line no-useless-escape
const wikiLinkWithHeadingPattern = /([\w\s\/\.-]*)(#.*)?/; const wikiLinkWithHeadingPattern = /^(.*?)(#.*)?$/u;
const [, path, heading = ""] = target.match(wikiLinkWithHeadingPattern); const [, path, heading = ""] = target.match(wikiLinkWithHeadingPattern);
const possibleWikiLinkPermalinks = wikiLinkResolver(path); const possibleWikiLinkPermalinks = wikiLinkResolver(path);
@ -99,7 +99,7 @@ function html(opts: HtmlOptions = {}) {
// remove leading # if the target is a heading on the same page // remove leading # if the target is a heading on the same page
const displayName = alias || target.replace(/^#/, ""); const displayName = alias || target.replace(/^#/, "");
// replace spaces with dashes and lowercase headings // replace spaces with dashes and lowercase headings
const headingId = heading.replace(/\s+/, "-").toLowerCase(); const headingId = heading.replace(/\s+/g, "-").toLowerCase();
let classNames = wikiLinkClassName; let classNames = wikiLinkClassName;
if (!matchingPermalink) { if (!matchingPermalink) {
classNames += " " + newClassName; classNames += " " + newClassName;

View File

@ -6,7 +6,7 @@ import { getPermalinks } from "../src/utils";
// const markdownFolder = path.join(__dirname, "/fixtures/content"); // const markdownFolder = path.join(__dirname, "/fixtures/content");
const markdownFolder = path.join( const markdownFolder = path.join(
".", ".",
"/packages/remark-wiki-link/test/fixtures/content" "test/fixtures/content"
); );
describe("getPermalinks", () => { describe("getPermalinks", () => {

View File

@ -321,4 +321,14 @@ describe("micromark-extension-wiki-link", () => {
); );
}); });
}); });
describe("Links with special characters", () => {
test("parses a link with special characters and symbols", () => {
const serialized = micromark("[[li nk-w(i)th-àcèô íã_a(n)d_underline!:ª%@'*º$ °~./\\#LI NK-W(i)th-àcèô íã_a(n)d_uNdErlinE!:ª%@'*º$ °~./\\]]", "ascii", {
extensions: [syntax()],
htmlExtensions: [html() as any],
});
expect(serialized).toBe(`<p><a href="li nk-w(i)th-àcèô íã_a(n)d_underline!:ª%@'*º$ °~./\\#li-nk-w(i)th-àcèô-íã_a(n)d_underline!:ª%@'*º$-°~./\\" class="internal new">li nk-w(i)th-àcèô íã_a(n)d_underline!:ª%@'*º$ °~./\\#LI NK-W(i)th-àcèô íã_a(n)d_uNdErlinE!:ª%@'*º$ °~./\\</a></p>`);
});
})
}); });

View File

@ -361,6 +361,32 @@ describe("remark-wiki-link", () => {
}); });
}); });
describe("Links with special characters", () => {
test("parses a link with special characters and symbols", () => {
const processor = unified().use(markdown).use(wikiLinkPlugin);
let ast = processor.parse("[[li nk-w(i)th-àcèô íã_a(n)d_underline!:ª%@'*º$ °~./\\#li-nk-w(i)th-àcèô íã_a(n)D_UNDERLINE!:ª%@'*º$ °~./\\]]");
ast = processor.runSync(ast);
expect(select("wikiLink", ast)).not.toEqual(null);
visit(ast, "wikiLink", (node: Node) => {
expect(node.data?.exists).toEqual(false);
expect(node.data?.permalink).toEqual("li nk-w(i)th-àcèô íã_a(n)d_underline!:ª%@'*º$ °~./\\");
expect(node.data?.alias).toEqual(null);
expect(node.data?.hName).toEqual("a");
expect((node.data?.hProperties as any).className).toEqual(
"internal new"
);
expect((node.data?.hProperties as any).href).toEqual(
"li nk-w(i)th-àcèô íã_a(n)d_underline!:ª%@'*º$ °~./\\#li-nk-w(i)th-àcèô-íã_a(n)d_underline!:ª%@'*º$-°~./\\"
);
expect((node.data?.hChildren as any)[0].value).toEqual(
"li nk-w(i)th-àcèô íã_a(n)d_underline!:ª%@'*º$ °~./\\#li-nk-w(i)th-àcèô íã_a(n)D_UNDERLINE!:ª%@'*º$ °~./\\"
);
})
});
})
describe("invalid wiki links", () => { describe("invalid wiki links", () => {
test("doesn't parse a wiki link with two missing closing brackets", () => { test("doesn't parse a wiki link with two missing closing brackets", () => {
const processor = unified().use(markdown).use(wikiLinkPlugin); const processor = unified().use(markdown).use(wikiLinkPlugin);
@ -560,3 +586,4 @@ describe("remark-wiki-link", () => {
}); });
}); });
}); });