mirror of
https://github.com/kdnk/obsidian-automatic-linker.git
synced 2026-07-22 05:37:46 +00:00
fix: resolve lint and formatting errors in AI Link Enhancer implementation
This commit is contained in:
parent
82ac311afb
commit
76e0da3ac9
7 changed files with 33 additions and 34 deletions
|
|
@ -1,4 +1,4 @@
|
|||
export const request = async () => ({});
|
||||
export const request = async () => ({})
|
||||
export class Notice {
|
||||
constructor() {}
|
||||
hide() {}
|
||||
|
|
|
|||
|
|
@ -17,26 +17,26 @@ describe("replaceLinks with AI disambiguation", () => {
|
|||
it("should use the AI-resolved path for unlinked words", () => {
|
||||
const body = "I have a meeting."
|
||||
const resolvedAmbiguities = new Map([["meeting", "work/meeting"]])
|
||||
|
||||
|
||||
const result = replaceLinks({
|
||||
body,
|
||||
linkResolverContext: context,
|
||||
resolvedAmbiguities,
|
||||
})
|
||||
|
||||
|
||||
expect(result).toBe("I have a [[work/meeting|meeting]].")
|
||||
})
|
||||
|
||||
it("should correct existing links if resolvedAmbiguities contains them", () => {
|
||||
const body = "Check [[private/meeting|meeting]] notes."
|
||||
const resolvedAmbiguities = new Map([["[[private/meeting|meeting]]", "work/meeting"]])
|
||||
|
||||
|
||||
const result = replaceLinks({
|
||||
body,
|
||||
linkResolverContext: context,
|
||||
resolvedAmbiguities,
|
||||
})
|
||||
|
||||
|
||||
expect(result).toBe("Check [[work/meeting|meeting]] notes.")
|
||||
})
|
||||
|
||||
|
|
@ -44,13 +44,13 @@ describe("replaceLinks with AI disambiguation", () => {
|
|||
const body = "Check [[private/meeting]] notes."
|
||||
// The resolveAmbiguities scanner uses the full link as key
|
||||
const resolvedAmbiguities = new Map([["[[private/meeting]]", "work/meeting"]])
|
||||
|
||||
|
||||
const result = replaceLinks({
|
||||
body,
|
||||
linkResolverContext: context,
|
||||
resolvedAmbiguities,
|
||||
})
|
||||
|
||||
|
||||
expect(result).toBe("Check [[work/meeting|private/meeting]] notes.")
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -734,9 +734,6 @@ const processStandardText = (
|
|||
// Case comparison happened during trie traversal if ignoreCase is true.
|
||||
const candidateData = candidateMap.get(trieCandidateKey)
|
||||
|
||||
// Store the original text matched for potential use as display text
|
||||
const originalMatchedText = text.substring(i, i + lastCandidate.length)
|
||||
|
||||
if (candidateData) {
|
||||
// Check if this is a self-link and should be prevented
|
||||
if (isSelfLink(candidateData, filePath, settings)) {
|
||||
|
|
@ -968,23 +965,23 @@ export const replaceLinks = ({
|
|||
const mIndex = match.index
|
||||
const segment = bodyWithPlaceholders.slice(lastIndex, mIndex)
|
||||
resultBody += processTextSegment(segment)
|
||||
|
||||
|
||||
const fullMatch = match[0]
|
||||
if (resolvedAmbiguities?.has(fullMatch)) {
|
||||
// Existing link replacement
|
||||
const resolvedPath = resolvedAmbiguities.get(fullMatch)!
|
||||
const { linkPath, alias: resolvedAlias } = extractLinkParts(resolvedPath)
|
||||
|
||||
|
||||
// Try to extract existing alias from the matched link
|
||||
const existingLinkRegex = /\[\[([^|\]]+)(?:\|([^\]]+))?\]\]/
|
||||
const linkMatch = fullMatch.match(existingLinkRegex)
|
||||
const existingPath = linkMatch ? linkMatch[1] : ""
|
||||
const existingAlias = linkMatch ? linkMatch[2] : undefined
|
||||
|
||||
// Use resolved alias if present, otherwise use existing alias,
|
||||
|
||||
// Use resolved alias if present, otherwise use existing alias,
|
||||
// otherwise use existing path (as alias if it was a simple link)
|
||||
const finalAlias = resolvedAlias || existingAlias || (fullMatch.includes("|") ? undefined : existingPath)
|
||||
|
||||
|
||||
const isInTable = isIndexInsideMarkdownTable(bodyWithPlaceholders, mIndex)
|
||||
resultBody += linkGenerator({
|
||||
linkPath,
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ describe("resolveAmbiguities", () => {
|
|||
it("should identify ambiguous unlinked words", async () => {
|
||||
const text = "I have a meeting tomorrow."
|
||||
vi.mocked(aiClient.resolveAmbiguitiesBatch).mockResolvedValue(
|
||||
new Map([["meeting", "work/meeting"]])
|
||||
new Map([["meeting", "work/meeting"]]),
|
||||
)
|
||||
|
||||
const result = await resolveAmbiguities(text, candidateMap, trie, mockSettings)
|
||||
|
|
@ -48,8 +48,8 @@ describe("resolveAmbiguities", () => {
|
|||
expect.objectContaining({
|
||||
word: "meeting",
|
||||
candidates: ["work/meeting", "private/meeting"],
|
||||
})
|
||||
])
|
||||
}),
|
||||
]),
|
||||
)
|
||||
expect(result.get("meeting")).toBe("work/meeting")
|
||||
})
|
||||
|
|
@ -57,7 +57,7 @@ describe("resolveAmbiguities", () => {
|
|||
it("should identify ambiguous existing links for verification", async () => {
|
||||
const text = "Check the [[private/meeting|meeting]] notes."
|
||||
vi.mocked(aiClient.resolveAmbiguitiesBatch).mockResolvedValue(
|
||||
new Map([["[[private/meeting|meeting]]", "work/meeting"]])
|
||||
new Map([["[[private/meeting|meeting]]", "work/meeting"]]),
|
||||
)
|
||||
|
||||
const result = await resolveAmbiguities(text, candidateMap, trie, mockSettings)
|
||||
|
|
@ -68,8 +68,8 @@ describe("resolveAmbiguities", () => {
|
|||
expect.objectContaining({
|
||||
word: "[[private/meeting|meeting]]",
|
||||
candidates: ["work/meeting", "private/meeting"],
|
||||
})
|
||||
])
|
||||
}),
|
||||
]),
|
||||
)
|
||||
expect(result.get("[[private/meeting|meeting]]")).toBe("work/meeting")
|
||||
})
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ export const callAI = async (
|
|||
|
||||
const data = JSON.parse(response)
|
||||
return data.choices[0].message.content
|
||||
} catch (error) {
|
||||
}
|
||||
catch (error) {
|
||||
console.error("AI Link Enhancer API Error:", error)
|
||||
throw error
|
||||
}
|
||||
|
|
@ -83,10 +84,10 @@ ${JSON.stringify(requests, null, 2)}
|
|||
`
|
||||
|
||||
const resultRaw = await callAI(settings, prompt)
|
||||
|
||||
|
||||
// Clean up potential markdown code blocks if the AI included them
|
||||
const cleanJson = resultRaw.replace(/```json\n?/, "").replace(/\n?```/, "").trim()
|
||||
|
||||
|
||||
const result = JSON.parse(cleanJson)
|
||||
const resultMap = new Map<string, string>()
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export const resolveAmbiguities = async (
|
|||
settings: AutomaticLinkerSettings,
|
||||
): Promise<Map<string, string>> => {
|
||||
const requests: AIResolveRequest[] = []
|
||||
|
||||
|
||||
// 1. Scan for existing links [[Path|Alias]] or [[Path]]
|
||||
const existingLinkRegex = /\[\[([^|\]]+)(?:\|([^\]]+))?\]\]/g
|
||||
let match: RegExpExecArray | null
|
||||
|
|
@ -18,12 +18,12 @@ export const resolveAmbiguities = async (
|
|||
const fullMatch = match[0]
|
||||
const path = match[1]
|
||||
const alias = match[2] || path
|
||||
|
||||
|
||||
const candidateData = candidateMap.get(alias)
|
||||
if (candidateData && candidateData.candidates.length > 1) {
|
||||
const start = Math.max(0, match.index - settings.aiMaxContext)
|
||||
const end = Math.min(text.length, match.index + fullMatch.length + settings.aiMaxContext)
|
||||
|
||||
|
||||
requests.push({
|
||||
word: fullMatch, // Using the full link as the "word" key for replacement
|
||||
text: text.slice(start, end),
|
||||
|
|
@ -38,7 +38,7 @@ export const resolveAmbiguities = async (
|
|||
while (i < text.length) {
|
||||
let node = trie
|
||||
let j = i
|
||||
let lastMatch: { word: string; data: CandidateData; index: number } | null = null
|
||||
let lastMatch: { word: string, data: CandidateData, index: number } | null = null
|
||||
|
||||
while (j < text.length && node.children.has(text[j].toLowerCase())) {
|
||||
node = node.children.get(text[j].toLowerCase())!
|
||||
|
|
@ -53,13 +53,13 @@ export const resolveAmbiguities = async (
|
|||
|
||||
if (lastMatch && lastMatch.data.candidates.length > 1) {
|
||||
// Check if it's already inside a link (simple check)
|
||||
const isInsideLink = text.slice(Math.max(0, i - 2), i) === "[[" ||
|
||||
text.slice(i + lastMatch.word.length, i + lastMatch.word.length + 2) === "]]"
|
||||
|
||||
const isInsideLink = text.slice(Math.max(0, i - 2), i) === "[["
|
||||
|| text.slice(i + lastMatch.word.length, i + lastMatch.word.length + 2) === "]]"
|
||||
|
||||
if (!isInsideLink) {
|
||||
const start = Math.max(0, i - settings.aiMaxContext)
|
||||
const end = Math.min(text.length, i + lastMatch.word.length + settings.aiMaxContext)
|
||||
|
||||
|
||||
requests.push({
|
||||
word: lastMatch.word,
|
||||
text: text.slice(start, end),
|
||||
|
|
@ -67,7 +67,8 @@ export const resolveAmbiguities = async (
|
|||
})
|
||||
}
|
||||
i += lastMatch.word.length
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export default defineConfig({
|
|||
test: {
|
||||
includeSource: ["src/**/*.{js,ts}"],
|
||||
alias: {
|
||||
"obsidian": path.resolve(__dirname, "./src/__mocks__/obsidian.ts"),
|
||||
obsidian: path.resolve(__dirname, "./src/__mocks__/obsidian.ts"),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue