diff --git a/src/embed-manager.js b/src/embed-manager.js index 6c43ac4..e89e677 100644 --- a/src/embed-manager.js +++ b/src/embed-manager.js @@ -319,6 +319,15 @@ class EmbedManager { this.hideInlineTitle(embedData); } + // Handle backlinks visibility + const showBacklinks = customOptions.backlinks !== undefined + ? customOptions.backlinks + : this.plugin.settings.showBacklinksInEmbeds; + + if (!showBacklinks) { + this.hideBacklinks(embedData); + } + // Remove placeholder and show actual content placeholder.remove(); embedContainer.appendChild(view.containerEl); @@ -402,6 +411,18 @@ class EmbedManager { }); } + hideBacklinks(embedData) { + const { view } = embedData; + requestAnimationFrame(() => { + setTimeout(() => { + const backlinksEl = view.containerEl.querySelector('.embedded-backlinks'); + if (backlinksEl) { + backlinksEl.style.display = 'none'; + } + }, 100); + }); + } + renderError(container, message, addGap) { const errorDiv = container.createDiv('sync-embed-error'); if (addGap) errorDiv.addClass('sync-embed-gap'); diff --git a/src/main.js b/src/main.js index e2be48f..85c0849 100644 --- a/src/main.js +++ b/src/main.js @@ -14,6 +14,7 @@ const DEFAULT_SETTINGS = { lazyLoadThreshold: '100px', showFocusHighlight: true, showHeaderHints: true, // NEW: Header hints (enforcement is always on) + showBacklinksInEmbeds: true, debugMode: false }; @@ -30,11 +31,11 @@ module.exports = class SyncEmbedPlugin extends Plugin { async onload() { await this.loadSettings(); - + // Initialize managers this.embedManager = new EmbedManager(this); this.commandInterceptor = new CommandInterceptor(this); - + // Setup command interception with monkey-around if (this.settings.enableCommandInterception) { this.setupCommandInterception(); @@ -86,26 +87,26 @@ module.exports = class SyncEmbedPlugin extends Plugin { // Add settings tab this.addSettingTab(new SyncEmbedsSettingTab(this.app, this)); - + // Apply focus highlight setting this.updateFocusHighlight(); - + // Log successful load this.log('Sync Embeds plugin loaded successfully'); } onunload() { this.log('Unloading Sync Embeds plugin'); - + // Clean up command interception this.uninstallers.forEach(uninstall => uninstall()); this.uninstallers = []; - + // Clean up managers if (this.embedManager) { this.embedManager.cleanup(); } - + this.currentFocusedEmbed = null; } @@ -117,7 +118,7 @@ module.exports = class SyncEmbedPlugin extends Plugin { { level: 5, name: 'Heading 5', key: '5' }, { level: 6, name: 'Heading 6', key: '6' }, ]; - + headerLevels.forEach(({ level, name, key }) => { this.addCommand({ id: `insert-header-${level}`, @@ -125,13 +126,13 @@ module.exports = class SyncEmbedPlugin extends Plugin { editorCallback: (editor, view) => { // Check if we're in a sync embed const focusedEmbed = this.getFocusedEmbed(); - + if (focusedEmbed) { // Use our custom handler const handler = this.commandInterceptor.insertHeaderCommand(level); return handler(focusedEmbed); } - + // Fall back to normal behavior for non-embed editing this.commandInterceptor.insertHeader({ editor }, level); }, @@ -143,7 +144,7 @@ module.exports = class SyncEmbedPlugin extends Plugin { ] }); }); - + this.log('Registered header commands with default hotkeys (Alt+2-6)'); } @@ -155,7 +156,7 @@ module.exports = class SyncEmbedPlugin extends Plugin { const plugin = this; return function(command, ...args) { const focusedEmbed = plugin.getFocusedEmbed(); - + // If embed is focused, check if we should intercept if (focusedEmbed) { // Check for our header commands first @@ -166,17 +167,17 @@ module.exports = class SyncEmbedPlugin extends Plugin { const handler = plugin.commandInterceptor.insertHeaderCommand(level); return handler(focusedEmbed); } - + // Check if we have a custom handler if (plugin.commandInterceptor.hasHandler(command.id)) { plugin.log(`Intercepting command: ${command.id}`); return plugin.commandInterceptor.handle(command.id, focusedEmbed, ...args); } - + // For commands we don't handle, let them execute on the embed's editor // This ensures ALL hotkeys work, including custom user-defined ones plugin.log(`Passing through command to embed: ${command.id}`); - + // Check if command has a callback that expects an editor if (command.editorCallback && focusedEmbed.editor) { try { @@ -187,7 +188,7 @@ module.exports = class SyncEmbedPlugin extends Plugin { } } } - + return old.call(this, command, ...args); }; } @@ -209,7 +210,7 @@ module.exports = class SyncEmbedPlugin extends Plugin { } }); this.uninstallers.push(getActiveViewUninstall); - + // Patch getActiveViewOfType on workspace.activeLeaf as well const getActiveLeafUninstall = around(this.app.workspace, { activeLeaf: { @@ -227,7 +228,7 @@ module.exports = class SyncEmbedPlugin extends Plugin { } }); this.uninstallers.push(getActiveLeafUninstall); - + this.log('Command interception setup complete'); } catch (error) { console.error('Sync Embeds: Failed to setup command interception:', error); @@ -281,7 +282,7 @@ module.exports = class SyncEmbedPlugin extends Plugin { container.style.setProperty('--sync-max-height', this.settings.maxEmbedHeight); container.style.setProperty('--sync-gap', this.settings.gapBetweenEmbeds); }); - + this.log('Refreshed all embeds with new settings'); } @@ -291,4 +292,4 @@ module.exports = class SyncEmbedPlugin extends Plugin { console.log('[Sync Embeds]', ...args); } } -}; \ No newline at end of file +}; diff --git a/src/settings.js b/src/settings.js index 89eca3b..a4c04f1 100644 --- a/src/settings.js +++ b/src/settings.js @@ -158,6 +158,16 @@ class SyncEmbedsSettingTab extends PluginSettingTab { await this.plugin.saveSettings(); })); + new Setting(containerEl) + .setName('Show backlinks in embeds') + .setDesc('Display backlinks section at the bottom of embeds (not applicable if Obsidian\'s global setting for backlinks in documents is disabled)') + .addToggle(toggle => toggle + .setValue(this.plugin.settings.showBacklinksInEmbeds) + .onChange(async (value) => { + this.plugin.settings.showBacklinksInEmbeds = value; + await this.plugin.saveSettings(); + })); + // === HEADER MANAGEMENT SECTION === containerEl.createEl('h3', { text: 'Header Management' }); @@ -225,16 +235,17 @@ class SyncEmbedsSettingTab extends PluginSettingTab {
![[Note Name|Custom Title]] - Display with custom title![[Note Name#Section|Custom Title]] - Section with custom titlePer-Embed Custom Options:
![[Note|Alias{height:500px}]] - Custom height for this embed![[Note|Alias{maxHeight:600px}]] - Custom max height![[Note|Alias{title:false}]] - Hide title for this embed![[Note|Alias{backlinks:false}]] - Hide backlinks for this embed![[Note|Alias{height:400px,title:false}]] - Multiple optionsNote: Options go inside curly braces before the closing ]]
- +Dynamic Patterns:
![[Daily/{{date:YYYY-MM-DD}}|Today]] - Current date with display name{{time:HH:mm}} - Current time{{title}} - Current note's titleHeader Management:
Alt+2 through Alt+6 to insert headers (H2-H6)Date Format Examples:
YYYY-MM-DD - 2024-03-15DD MMM YYYY - 15 Mar 2024dddd, MMMM Do YYYY - Friday, March 15th 2024Complete Example:
\`\`\`sync
![[Daily Notes/{{date:YYYY-MM-DD}}|Today's Note]]
@@ -272,7 +283,7 @@ class SyncEmbedsSettingTab extends PluginSettingTab {
![[Tasks#Inbox|My Tasks{height:300px}]]
![[Projects/{{title}}#Notes|Project Notes{title:false}]]
\`\`\`
-
+
Tips:
|) with dynamic patterns for better displayNote: Dynamic patterns are cached for 1 second to improve performance.
`; @@ -334,17 +345,17 @@ class SyncEmbedsSettingTab extends PluginSettingTab { validateCSSValue(value) { // Basic validation for CSS length values if (!value || value.trim() === '') return false; - + // Allow common CSS units const validPattern = /^(auto|none|\d+(\.\d+)?(px|em|rem|vh|vw|%))$/; const isValid = validPattern.test(value.trim()); - + if (!isValid) { new Notice('Invalid CSS value. Use units like: px, em, rem, vh, vw, %, or "auto"/"none"'); } - + return isValid; } } -module.exports = SyncEmbedsSettingTab; \ No newline at end of file +module.exports = SyncEmbedsSettingTab;