From 997e5a8b491bea8cd7603c0199c440c2c82b1213 Mon Sep 17 00:00:00 2001 From: Kodai Nakamura Date: Sat, 30 May 2026 15:06:07 +0900 Subject: [PATCH] refactor(replace-links): centralize table link escaping Why: - Markdown table escaping is link formatting behavior, not plugin orchestration behavior. - Keeping pipe escaping in main.ts duplicated logic already used by the default link generator and made the Obsidian adapter responsible for markdown rendering details. What: - Add a shared escapeLinkForMarkdownTable helper in replace-links. - Reuse the helper from defaultLinkGenerator and from the Obsidian API link generator path. - Delegate fallback wikilink rendering in main.ts to defaultLinkGenerator. - Add direct coverage for table link escaping behavior. --- src/main.ts | 19 +++++-------------- .../__tests__/replace-links.table.test.ts | 7 ++++++- src/replace-links/replace-links.ts | 17 ++++++++++++----- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/main.ts b/src/main.ts index 3d03f14..a557653 100644 --- a/src/main.ts +++ b/src/main.ts @@ -19,6 +19,8 @@ import { import { PathAndAliases } from "./path-and-aliases.types" import { removeMinimalIndent } from "./remove-minimal-indent" import { + defaultLinkGenerator, + escapeLinkForMarkdownTable, LinkGenerator, LinkGeneratorParams, replaceLinks, @@ -77,11 +79,8 @@ export default class AutomaticLinkerPlugin extends Plugin { if (targetFile instanceof TFile) { // File exists, use Obsidian's generateMarkdownLink API try { - let link = this.app.fileManager.generateMarkdownLink(targetFile, sourcePath, "", alias || "") - if (isInTable && link.includes("|")) { - link = link.replace(/\|/g, "\\|") - } - return link + const link = this.app.fileManager.generateMarkdownLink(targetFile, sourcePath, "", alias || "") + return escapeLinkForMarkdownTable(link, isInTable) } catch (error) { // Fall back to default format if API fails @@ -89,15 +88,7 @@ export default class AutomaticLinkerPlugin extends Plugin { } } - // Fallback: use default wikilink format - let linkContent = linkPath - if (alias) { - linkContent = `${linkPath}|${alias}` - } - if (isInTable && linkContent.includes("|")) { - linkContent = linkContent.replace(/\|/g, "\\|") - } - return `[[${linkContent}]]` + return defaultLinkGenerator({ linkPath, sourcePath, alias, isInTable }) } } diff --git a/src/replace-links/__tests__/replace-links.table.test.ts b/src/replace-links/__tests__/replace-links.table.test.ts index e1c8e54..4d98a83 100644 --- a/src/replace-links/__tests__/replace-links.table.test.ts +++ b/src/replace-links/__tests__/replace-links.table.test.ts @@ -1,8 +1,13 @@ import { describe, it, expect } from "vitest" -import { replaceLinks } from "../replace-links" +import { escapeLinkForMarkdownTable, replaceLinks } from "../replace-links" import { buildCandidateTrieForTest } from "./test-helpers" describe("table", () => { + it("escapes link separators only when rendering inside a markdown table", () => { + expect(escapeLinkForMarkdownTable("[[ns/note1|note1]]", true)).toBe("[[ns/note1\\|note1]]") + expect(escapeLinkForMarkdownTable("[[ns/note1|note1]]", false)).toBe("[[ns/note1|note1]]") + }) + it("escape pipe inside table", () => { const settings = { scoped: false, diff --git a/src/replace-links/replace-links.ts b/src/replace-links/replace-links.ts index 83d6eaf..daf892b 100644 --- a/src/replace-links/replace-links.ts +++ b/src/replace-links/replace-links.ts @@ -346,6 +346,17 @@ const createLinkContent = ( } // Default link generator that creates standard Obsidian wikilinks +export const escapeLinkForMarkdownTable = ( + link: string, + isInTable = false, +): string => { + if (isInTable && link.includes("|")) { + return link.replace(/\|/g, "\\|") + } + + return link +} + export const defaultLinkGenerator: LinkGenerator = ({ linkPath, alias, @@ -357,11 +368,7 @@ export const defaultLinkGenerator: LinkGenerator = ({ linkContent = `${linkPath}|${alias}` } - if (isInTable && linkContent.includes("|")) { - linkContent = linkContent.replace(/\|/g, "\\|") - } - - return `[[${linkContent}]]` + return escapeLinkForMarkdownTable(`[[${linkContent}]]`, isInTable) } // Candidate Validation