import { watch } from 'vue' import { backlinkEventBus } from '@/bus/backlinkEventBus' import { data } from '@/data/data' import { DataType } from '@/data/DataType.enum' import { useFile } from '@/hooks/useFile.hook' import { Backlink } from '@/modules/note/models/Backlink' import { BacklinkNote } from '@/modules/note/models/BacklinkNote' import { resolvePath } from '@/modules/repo/services/resolvePath' import { useUserRepoStore } from '@/modules/repo/store/userRepo.store' import { isExternalLink } from '@/utils/link' import { filenameToNoteTitle } from '@/utils/noteTitle' import { confirmMessage } from '@/utils/notif' const isMarkdown = (filename?: string) => filename?.endsWith('.md') ?? false export const useComputeBacklinks = () => { const store = useUserRepoStore() watch(store, async () => { if (!store.userSettings?.backlink) { return } let notifiedForComputation = false const backlinks: Map = new Map() for (const file of store.files) { if (!isMarkdown(file.path) || !file.sha) { continue } const fileBacklinkId = data.generateId(DataType.BacklinkNote, file.sha) const fileBacklink = await data.get( fileBacklinkId ) if (fileBacklink) { continue } if (!backlinks.has(file.sha)) { backlinks.set(file.sha, []) } const { getContent } = useFile(file.sha, false) const note = await getContent() if (!note) { return } const parser = new DOMParser() const htmlDoc = parser.parseFromString(note, 'text/html') const links = htmlDoc.querySelectorAll('a') for (const link of links) { const href = link.getAttribute('href') ?? '' if (isExternalLink(href) || !isMarkdown(href)) { continue } const path = resolvePath(file.path ?? '', href) const backlinkFile = store.files.find((file) => file.path === path) if (!backlinkFile?.sha || !backlinkFile?.path) { continue } const previousBacklinks = backlinks.get(backlinkFile.sha) ?? [] if (previousBacklinks.find((bl) => bl.sha === file.sha)) { continue } if (!notifiedForComputation) { notifiedForComputation = true confirmMessage('Updating backlinks...') } backlinks.set(backlinkFile.sha, [ ...previousBacklinks, { sha: file.sha, title: filenameToNoteTitle(file.path ?? '') } ]) } } for (const [sha, fileBacklinks] of backlinks) { const fileBacklinkId = data.generateId(DataType.BacklinkNote, sha) const backlinkNote: BacklinkNote = { _id: fileBacklinkId, $type: DataType.BacklinkNote, sha: sha, links: fileBacklinks } await data.update(backlinkNote) backlinkEventBus.emit({ fileSha: sha }) } }) }