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.
This commit is contained in:
Kodai Nakamura 2026-05-30 15:06:07 +09:00
parent 83d97e2c39
commit 997e5a8b49
3 changed files with 23 additions and 20 deletions

View file

@ -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 })
}
}

View file

@ -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,

View file

@ -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