Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/embed-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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');
Expand Down
41 changes: 21 additions & 20 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const DEFAULT_SETTINGS = {
lazyLoadThreshold: '100px',
showFocusHighlight: true,
showHeaderHints: true, // NEW: Header hints (enforcement is always on)
showBacklinksInEmbeds: true,
debugMode: false
};

Expand All @@ -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();
Expand Down Expand Up @@ -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;
}

Expand All @@ -117,21 +118,21 @@ 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}`,
name: `Toggle ${name}`,
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);
},
Expand All @@ -143,7 +144,7 @@ module.exports = class SyncEmbedPlugin extends Plugin {
]
});
});

this.log('Registered header commands with default hotkeys (Alt+2-6)');
}

Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -187,7 +188,7 @@ module.exports = class SyncEmbedPlugin extends Plugin {
}
}
}

return old.call(this, command, ...args);
};
}
Expand All @@ -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: {
Expand All @@ -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);
Expand Down Expand Up @@ -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');
}

Expand All @@ -291,4 +292,4 @@ module.exports = class SyncEmbedPlugin extends Plugin {
console.log('[Sync Embeds]', ...args);
}
}
};
};
33 changes: 22 additions & 11 deletions src/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -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' });

Expand Down Expand Up @@ -225,16 +235,17 @@ class SyncEmbedsSettingTab extends PluginSettingTab {
<li><code>![[Note Name|Custom Title]]</code> - Display with custom title</li>
<li><code>![[Note Name#Section|Custom Title]]</code> - Section with custom title</li>
</ul>

<p><strong>Per-Embed Custom Options:</strong></p>
<ul>
<li><code>![[Note|Alias{height:500px}]]</code> - Custom height for this embed</li>
<li><code>![[Note|Alias{maxHeight:600px}]]</code> - Custom max height</li>
<li><code>![[Note|Alias{title:false}]]</code> - Hide title for this embed</li>
<li><code>![[Note|Alias{backlinks:false}]]</code> - Hide backlinks for this embed</li>
<li><code>![[Note|Alias{height:400px,title:false}]]</code> - Multiple options</li>
</ul>
<p><em>Note: Options go inside curly braces before the closing ]]</em></p>

<p><strong>Dynamic Patterns:</strong></p>
<ul>
<li><code>![[Daily/{{date:YYYY-MM-DD}}|Today]]</code> - Current date with display name</li>
Expand All @@ -245,7 +256,7 @@ class SyncEmbedsSettingTab extends PluginSettingTab {
<li><code>{{time:HH:mm}}</code> - Current time</li>
<li><code>{{title}}</code> - Current note's title</li>
</ul>

<p><strong>Header Management:</strong></p>
<ul>
<li>Use <code>Alt+2</code> through <code>Alt+6</code> to insert headers (H2-H6)</li>
Expand All @@ -256,23 +267,23 @@ class SyncEmbedsSettingTab extends PluginSettingTab {
<li>Whole-note embeds allow H1-H6 freely</li>
<li>These hotkeys can be customized in Obsidian's Hotkeys settings</li>
</ul>

<p><strong>Date Format Examples:</strong></p>
<ul>
<li><code>YYYY-MM-DD</code> - 2024-03-15</li>
<li><code>YYYY/MM/DD</code> - 2024/03/15</li>
<li><code>DD MMM YYYY</code> - 15 Mar 2024</li>
<li><code>dddd, MMMM Do YYYY</code> - Friday, March 15th 2024</li>
</ul>

<p><strong>Complete Example:</strong></p>
<pre><code>\`\`\`sync
![[Daily Notes/{{date:YYYY-MM-DD}}|Today's Note]]
![[Daily Notes/{{date-1d:YYYY-MM-DD}}|Yesterday]]
![[Tasks#Inbox|My Tasks{height:300px}]]
![[Projects/{{title}}#Notes|Project Notes{title:false}]]
\`\`\`</code></pre>

<p><strong>Tips:</strong></p>
<ul>
<li>Use aliases (text after <code>|</code>) with dynamic patterns for better display</li>
Expand All @@ -284,7 +295,7 @@ class SyncEmbedsSettingTab extends PluginSettingTab {
<li>Multiple embeds of the same note/section are allowed</li>
<li>Header hierarchy enforcement maintains document structure in section embeds</li>
</ul>

<p><em>Note: Dynamic patterns are cached for 1 second to improve performance.</em></p>
`;

Expand Down Expand Up @@ -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;
module.exports = SyncEmbedsSettingTab;