diff --git a/src/links/helper.ts b/src/links/helper.ts index 182a894..8654ea4 100644 --- a/src/links/helper.ts +++ b/src/links/helper.ts @@ -39,11 +39,15 @@ export function getMathLink(plugin: MathLinks, targetLink: string, sourcePath: s return ""; } + return _getMathLink(plugin, path, subpath, file, subpathResult, sourceFile, isSourceMode); +} + +export function _getMathLink(plugin: MathLinks, path: string, subpath: string, targetFile: TFile | null, subpathResult: HeadingSubpathResult | BlockSubpathResult | null, sourceFile: TFile | null, isSourceMode?: boolean) { let mathLink = ""; plugin.iterateProviders((provider) => { if (isSourceMode && !provider.enableInSourceMode) return; - const provided = provider.provide({ path, subpath }, file, subpathResult, sourceFile); + const provided = provider.provide({ path, subpath }, targetFile, subpathResult, sourceFile); if (provided) { if (provider instanceof NativeProvider && subpathResult?.type == 'heading') { if (mathLink && provided == (path ? path + ' > ' : '') + subpathResult.current.heading) { diff --git a/src/main.ts b/src/main.ts index 238b19d..6fd4389 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,7 +7,7 @@ import { MathLinksAPIAccount } from "./api/deprecated"; import { DeprecatedAPIProvider, NativeProvider, Provider } from "./api/provider"; import { generateMathLinks } from "./links/reading"; import { isExcluded } from "./utils"; -import { patchOutline } from './outline'; +import { patchOutline, patchLinkAutocompletion } from './patchers'; export default class MathLinks extends Plugin { settings: MathLinksSettings; @@ -44,18 +44,23 @@ export default class MathLinks extends Plugin { // Patch the core Outline view to render MathJax in it; try until successful this.app.workspace.onLayoutReady(() => { if (this.settings.renderOutline && (this.app as any).internalPlugins.plugins.outline.enabled) { - const success = patchOutline(this); - if (!success) { - const eventRef = this.app.workspace.on('layout-change', () => { - const success = patchOutline(this); - if (success) this.app.workspace.offref(eventRef); - }); - this.registerEvent(eventRef); - } + this.patch(patchOutline); } + this.patch(patchLinkAutocompletion); }); } + patch(patcher: (plugin: MathLinks) => boolean) { + const success = patcher(this); + if (!success) { + const eventRef = this.app.workspace.on('layout-change', () => { + const success = patcher(this); + if (success) this.app.workspace.offref(eventRef); + }); + this.registerEvent(eventRef); + } + } + getAPIAccount(userPlugin: Readonly): MathLinksAPIAccount { let account = this.apiAccounts.find((account) => account.manifest.id == userPlugin.manifest.id); if (account) return account; diff --git a/src/outline.ts b/src/outline.ts deleted file mode 100644 index 5571853..0000000 --- a/src/outline.ts +++ /dev/null @@ -1,27 +0,0 @@ -// https://github.com/zhaoshenzhai/obsidian-mathlinks/issues/55 -// Patch the core Outline view to render MathJax in it - -import { around } from 'monkey-around'; -import MathLinks from './main'; -import { setMathLink } from './links/helper'; - -export const patchOutline = (plugin: MathLinks): boolean => { - const outlineView = plugin.app.workspace.getLeavesOfType('outline')[0]?.view; - if (!outlineView) return false; - - plugin.register( - around(outlineView.constructor.prototype, { - getItemDom(old) { - return function (arg) { - const ret = old.call(this, arg); - // Wait for the ret.innerEl (div.tree-item-inner) to be fully rendered - // by the core Outline plugin - setTimeout(() => setMathLink(ret.heading.heading, ret.innerEl)); - return ret; - } - }, - }) - ) - - return true; -} diff --git a/src/patchers.ts b/src/patchers.ts new file mode 100644 index 0000000..a273cd8 --- /dev/null +++ b/src/patchers.ts @@ -0,0 +1,96 @@ +import { BlockSubpathResult, HeadingSubpathResult, SearchMatches, TFile, resolveSubpath } from 'obsidian'; +import { around } from 'monkey-around'; +import MathLinks from './main'; +import { _getMathLink, getMathLink, setMathLink } from './links/helper'; +import { EditorSuggest } from 'obsidian'; + +// https://github.com/zhaoshenzhai/obsidian-mathlinks/issues/55 +// Patch the core Outline view to render MathJax in it +export const patchOutline = (plugin: MathLinks): boolean => { + const outlineView = plugin.app.workspace.getLeavesOfType('outline')[0]?.view; + if (!outlineView) return false; + + plugin.register( + around(outlineView.constructor.prototype, { + getItemDom(old) { + return function (arg) { + const ret = old.call(this, arg); + // Wait for the ret.innerEl (div.tree-item-inner) to be fully rendered + // by the core Outline plugin + setTimeout(() => setMathLink(ret.heading.heading, ret.innerEl)); + return ret; + } + }, + }) + ) + + return true; +} + + +// https://github.com/RyotaUshio/obsidian-math-booster/issues/190 +// Patch the built-in link autocompletion to render MathJax in it + +interface LinkInfo { + file: TFile; + matches: SearchMatches | null; + path: string; + score: number; + subpath?: string; +}; + +interface FileLinkInfo extends LinkInfo { + type: "file"; +} + +interface HeadingLinkInfo extends LinkInfo { + type: "heading"; + heading: string; + level: number; + subpath: string; +} + +interface BlockLinkInfo extends LinkInfo { + type: "block"; + idMatch: SearchMatches | null; + subpath: string; + node: any; + display: string; + content: string; +} + +type BuiltInAutocompletion = EditorSuggest; + + +export const patchLinkAutocompletion = (plugin: MathLinks): boolean => { + const suggest = (plugin.app.workspace as any).editorSuggest.suggests[0] as BuiltInAutocompletion; + if (!suggest) return false; + + plugin.register( + around(suggest.constructor.prototype, { + renderSuggestion(old) { + return function (value: FileLinkInfo | HeadingLinkInfo | BlockLinkInfo, el: HTMLElement): void { + const sourceFile = (this as BuiltInAutocompletion).context?.file ?? null; + let subpathResult: HeadingSubpathResult | BlockSubpathResult | null = null; + + if (value.type === "heading" || value.type === "block") { + const cache = plugin.app.metadataCache.getFileCache(value.file); + if (cache) { + subpathResult = resolveSubpath(cache, value.subpath); + } + } + const mathLink = _getMathLink(plugin, value.path, value.subpath ?? "", value.file, subpathResult, sourceFile); + + old.call(this, value, el); + + if (mathLink) { + const titleEl = el.querySelector('.suggestion-title'); + if (titleEl) setMathLink(mathLink, titleEl); + } + } + }, + }) + ) + + return true; +}