(plugin: CodeSpacePlugin)
| 608 | } |
| 609 | |
| 610 | export function registerCodeEmbedProcessor(plugin: CodeSpacePlugin) { |
| 611 | // Install observer for the main window document to catch any embeds that the post processor misses. |
| 612 | // This is necessary because registerMarkdownPostProcessor may be called before the embed element |
| 613 | // is attached to the workspace leaf, causing resolveSourcePathForEmbed to fail. |
| 614 | const mainWindow = activeWindow; |
| 615 | const mainDoc = activeDocument; |
| 616 | ensureCodeSpaceStylesInDocument(mainDoc, plugin); |
| 617 | installEmbedObserverForDocument(mainDoc, mainWindow, plugin); |
| 618 | installPrintRefreshForDocument(mainDoc, mainWindow, plugin); |
| 619 | |
| 620 | // Use Obsidian's official markdown post processor so we always get a correct ctx.sourcePath. |
| 621 | // This avoids races where MutationObserver runs before embed link attributes are stable. |
| 622 | plugin.registerMarkdownPostProcessor((el, ctx) => { |
| 623 | if (ctx.sourcePath && !ctx.sourcePath.startsWith("Untitled")) { |
| 624 | rememberSourcePath(el, ctx.sourcePath); |
| 625 | } |
| 626 | |
| 627 | ctx.addChild(new CodeEmbedSectionObserverChild(el, plugin, ctx.sourcePath ?? "")); |
| 628 | |
| 629 | // Obsidian renders embedded code files as div.file-embed (edit mode) or span.file-embed (reading mode) |
| 630 | // with div.file-embed-title |
| 631 | const embeds = el.querySelectorAll('.file-embed'); |
| 632 | |
| 633 | for (let i = 0; i < embeds.length; i++) { |
| 634 | const embedEl = embeds[i] as HTMLElement; |
| 635 | // Prefer ctx.sourcePath when available. When unreliable, the main window's |
| 636 | // MutationObserver (installed above) will catch it after DOM stabilizes. |
| 637 | const sourcePath = ctx.sourcePath; |
| 638 | if (sourcePath && !sourcePath.startsWith("Untitled")) { |
| 639 | rememberSourcePath(embedEl, sourcePath); |
| 640 | scheduleProcessCodeEmbed(embedEl, plugin, sourcePath); |
| 641 | } |
| 642 | // If sourcePath is unreliable, rely on the main window observer to pick it up. |
| 643 | } |
| 644 | }); |
| 645 | |
| 646 | // Listen for file changes so we can update embeds when their source files change on disk. |
| 647 | plugin.registerEvent( |
| 648 | plugin.app.vault.on("modify", (changedFile) => { |
| 649 | // 遍历所有文档,查找嵌入了变更文件的嵌入块 |
| 650 | plugin.app.workspace.iterateAllLeaves((leaf) => { |
| 651 | const view = leaf.view as unknown as { |
| 652 | containerEl?: HTMLElement |
| 653 | contentEl?: HTMLElement |
| 654 | file?: TFile |
| 655 | } | null |
| 656 | if (!view) return |
| 657 | |
| 658 | const possibleContainers = [ |
| 659 | view.contentEl, |
| 660 | view.containerEl, |
| 661 | view.containerEl?.querySelector(".markdown-preview-view"), |
| 662 | view.containerEl?.querySelector(".markdown-source-view"), |
| 663 | ] |
| 664 | |
| 665 | for (const container of possibleContainers) { |
| 666 | if (!container) continue |
| 667 |
no test coverage detected