diff --git a/.changeset/many-ligers-sneeze.md b/.changeset/many-ligers-sneeze.md new file mode 100644 index 000000000..499eeba75 --- /dev/null +++ b/.changeset/many-ligers-sneeze.md @@ -0,0 +1,5 @@ +--- +'@portaljs/remark-wiki-link': patch +--- + +Changed regex to permit any symbols other than # diff --git a/packages/remark-wiki-link/src/lib/fromMarkdown.ts b/packages/remark-wiki-link/src/lib/fromMarkdown.ts index 4f9036dff..5b5f7b9c8 100644 --- a/packages/remark-wiki-link/src/lib/fromMarkdown.ts +++ b/packages/remark-wiki-link/src/lib/fromMarkdown.ts @@ -79,7 +79,7 @@ function fromMarkdown(opts: FromMarkdownOptions = {}) { data: { isEmbed, target, alias }, } = wikiLink; // eslint-disable-next-line no-useless-escape - const wikiLinkWithHeadingPattern = /([\p{Letter}\d\s\/\.-_]*)(#.*)?/u; + const wikiLinkWithHeadingPattern = /^(.*?)(#.*)?$/u; const [, path, heading = ""] = target.match(wikiLinkWithHeadingPattern); const possibleWikiLinkPermalinks = wikiLinkResolver(path); @@ -116,7 +116,7 @@ function fromMarkdown(opts: FromMarkdownOptions = {}) { // remove leading # if the target is a heading on the same page const displayName = alias || target.replace(/^#/, ""); - const headingId = heading.replace(/\s+/, "-").toLowerCase(); + const headingId = heading.replace(/\s+/g, "-").toLowerCase(); let classNames = wikiLinkClassName; if (!matchingPermalink) { classNames += " " + newClassName; diff --git a/packages/remark-wiki-link/src/lib/html.ts b/packages/remark-wiki-link/src/lib/html.ts index d4a7996fb..1058652f6 100644 --- a/packages/remark-wiki-link/src/lib/html.ts +++ b/packages/remark-wiki-link/src/lib/html.ts @@ -64,7 +64,7 @@ function html(opts: HtmlOptions = {}) { const { target, alias } = wikiLink; const isEmbed = token.isType === "embed"; // eslint-disable-next-line no-useless-escape - const wikiLinkWithHeadingPattern = /([\w\s\/\.-]*)(#.*)?/; + const wikiLinkWithHeadingPattern = /^(.*?)(#.*)?$/u; const [, path, heading = ""] = target.match(wikiLinkWithHeadingPattern); const possibleWikiLinkPermalinks = wikiLinkResolver(path); @@ -99,7 +99,7 @@ function html(opts: HtmlOptions = {}) { // remove leading # if the target is a heading on the same page const displayName = alias || target.replace(/^#/, ""); // replace spaces with dashes and lowercase headings - const headingId = heading.replace(/\s+/, "-").toLowerCase(); + const headingId = heading.replace(/\s+/g, "-").toLowerCase(); let classNames = wikiLinkClassName; if (!matchingPermalink) { classNames += " " + newClassName; diff --git a/packages/remark-wiki-link/test/getPermalinks.spec.ts b/packages/remark-wiki-link/test/getPermalinks.spec.ts index 1e1f51d30..de916171a 100644 --- a/packages/remark-wiki-link/test/getPermalinks.spec.ts +++ b/packages/remark-wiki-link/test/getPermalinks.spec.ts @@ -6,7 +6,7 @@ import { getPermalinks } from "../src/utils"; // const markdownFolder = path.join(__dirname, "/fixtures/content"); const markdownFolder = path.join( ".", - "/packages/remark-wiki-link/test/fixtures/content" + "test/fixtures/content" ); describe("getPermalinks", () => { diff --git a/packages/remark-wiki-link/test/micromarkExtensionWikiLink.spec.ts b/packages/remark-wiki-link/test/micromarkExtensionWikiLink.spec.ts index a2c408c64..663b885c1 100644 --- a/packages/remark-wiki-link/test/micromarkExtensionWikiLink.spec.ts +++ b/packages/remark-wiki-link/test/micromarkExtensionWikiLink.spec.ts @@ -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(`

li nk-w(i)th-àcèô íã_a(n)d_underline!:ª%@'*º$ °~./\\#LI NK-W(i)th-àcèô íã_a(n)d_uNdErlinE!:ª%@'*º$ °~./\\

`); + }); + }) }); diff --git a/packages/remark-wiki-link/test/remarkWikiLink.spec.ts b/packages/remark-wiki-link/test/remarkWikiLink.spec.ts index 6b4e9cc51..276038fc6 100644 --- a/packages/remark-wiki-link/test/remarkWikiLink.spec.ts +++ b/packages/remark-wiki-link/test/remarkWikiLink.spec.ts @@ -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", () => { test("doesn't parse a wiki link with two missing closing brackets", () => { const processor = unified().use(markdown).use(wikiLinkPlugin); @@ -560,3 +586,4 @@ describe("remark-wiki-link", () => { }); }); }); +