fix(app): exclude sentence punctuation from bare Markdown links (#7361)

The shared MD4C permissive autolink scanner consumed trailing path periods and rejected colon boundaries. Fix recognition in the dependency patch and rebuild its web parser so native and web agree. Preserve balanced path parentheses and explicit destinations.
This commit is contained in:
Mohamed Boudra
2026-10-19 10:44:31 +07:00
committed by GitHub
parent b50acc9344
commit 66348a5e5c
2 changed files with 285 additions and 45 deletions
@@ -208,6 +208,56 @@ it("lets the engine own code boundaries while classifying candidate values", asy
]);
});
describe("bare URL sentence punctuation", () => {
it.each([".", ",", ";", ":", "!", "?", ")", ").", "...", "?!"])(
"leaves %s outside the link and preserves the rendered sentence",
async (punctuation) => {
const url = "https://github.com/getpaseo/paseo/pull/7357";
const source = `${url}${punctuation} Not merged.`;
const prepared = prepareMarkdownSource(source);
const tree = recognizeTextLinks(
await parseMarkdown(prepared.render(), { latexMath: false }),
prepared.linkRecognition.text,
prepared.linkRecognition.inlineCode,
);
expect(tree.children?.[0]?.children).toEqual([
{
type: "Link",
attributes: { url },
children: [{ type: "Text", content: url }],
},
{ type: "Text", content: `${punctuation} Not merged.` },
]);
},
);
it.each([
"https://example.com/a.b",
"https://example.com/a?foo=bar&baz=2",
"https://example.com/a#L10",
"https://en.wikipedia.org/wiki/Function_(mathematics)",
"https://example.com/a_(b_(c))",
])("preserves internal URL punctuation: %s", async (url) => {
const tree = await parseMarkdown(prepareMarkdownSource(`${url}.`).render());
expect(tree.children?.[0]?.children).toEqual([
{
type: "Link",
attributes: { url },
children: [{ type: "Text", content: url }],
},
{ type: "Text", content: "." },
]);
});
it.each(["[Authored](https://example.com/a.)", "<https://example.com/a.>"])(
"preserves punctuation in explicit destinations: %s",
async (source) => {
const tree = await parseMarkdown(prepareMarkdownSource(source).render());
expect(tree.children?.[0]?.children?.[0]?.attributes?.url).toBe("https://example.com/a.");
},
);
});
it("requires workspace context for relative inline paths and escapes literal regex characters", () => {
const source = "`src/app/[id].tsx` and `src/a+b.ts` and `README.md` and `/tmp/file.ts`";
const withoutWorkspace = prepareMarkdownSource(source).linkRecognition.inlineCode;
File diff suppressed because one or more lines are too long