Update README and main plugin logic for improved menu processing

- Enhanced README.md with build, development, and testing instructions.
- Refactored main.js to separate menu block processing into a dedicated method.
- Improved error handling during plugin loading.
- Streamlined link processing for internal, external, and file links.
- Added support for multi-line dataview queries.
- Updated manifest.json version to 1.4.
This commit is contained in:
2025-12-26 17:07:06 -05:00
parent b20ca4d966
commit aa96902664
4 changed files with 574 additions and 491 deletions

View File

@@ -12,6 +12,71 @@ You can:
CSS stays clean and predictable. CSS stays clean and predictable.
## Build & Development
### Prerequisites
- Node.js 16+ and npm
- Obsidian installed for testing
### Setup
1. Clone or navigate to the plugin directory:
```bash
cd obsidian-menus
```
2. Install dependencies:
```bash
npm install
```
### Building
Build the plugin:
```bash
npm run dev
```
This runs esbuild in watch mode, automatically rebuilding whenever you make changes.
For a production build:
```bash
npm run build
```
### Testing Locally
1. Copy the built plugin to your Obsidian test vault:
```bash
# On Windows:
copy main.js %APPDATA%\Obsidian\.obsidian\plugins\obsidian-menus\
copy manifest.json %APPDATA%\Obsidian\.obsidian\plugins\obsidian-menus\
copy styles.css %APPDATA%\Obsidian\.obsidian\plugins\obsidian-menus\
# On macOS:
cp main.js ~/Library/Application\ Support/Obsidian/.obsidian/plugins/obsidian-menus/
cp manifest.json ~/Library/Application\ Support/Obsidian/.obsidian/plugins/obsidian-menus/
cp styles.css ~/Library/Application\ Support/Obsidian/.obsidian/plugins/obsidian-menus/
# On Linux:
cp main.js ~/.config/Obsidian/.obsidian/plugins/obsidian-menus/
cp manifest.json ~/.config/Obsidian/.obsidian/plugins/obsidian-menus/
cp styles.css ~/.config/Obsidian/.obsidian/plugins/obsidian-menus/
```
2. Reload the plugin in Obsidian: Settings → Community Plugins → Reload (or restart Obsidian).
### Publishing (via BRAT or Community)
**For BRAT testing:**
1. Push your changes to GitHub
2. Update `manifest.json` with the new version
3. Create a release on GitHub with the version tag
4. Users can add your repo URL to BRAT: `https://github.com/YOUR_USERNAME/obsidian-menus`
**For Community Plugin:**
1. Submit a PR to the [Obsidian Sample Plugin](https://github.com/obsidianmd/obsidian-sample-plugin) repository with your manifest.
## Basic Usage ## Basic Usage
Create a menu using a `menu` code block with one of the built-in templates: Create a menu using a `menu` code block with one of the built-in templates:

29
main.js
View File

@@ -33,9 +33,26 @@ var DEFAULT_SETTINGS = {
}; };
var MenuPlugin = class extends import_obsidian.Plugin { var MenuPlugin = class extends import_obsidian.Plugin {
async onload() { async onload() {
try {
await this.loadSettings(); await this.loadSettings();
this.addSettingTab(new MenuPluginSettingTab(this.app, this)); this.addSettingTab(new MenuPluginSettingTab(this.app, this));
this.registerMarkdownCodeBlockProcessor("menu", (source, el, ctx) => { this.registerMarkdownCodeBlockProcessor("menu", (source, el, ctx) => {
this.processMenuBlock(source, el, ctx);
});
} catch (error) {
console.error("[obsidian-menus] Failed to load plugin:", error);
throw error;
}
}
onunload() {
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
}
processMenuBlock(source, el, ctx) {
const lines = source.trim().split("\n"); const lines = source.trim().split("\n");
let layoutOrClass = ""; let layoutOrClass = "";
let colors = {}; let colors = {};
@@ -213,7 +230,8 @@ var MenuPlugin = class extends import_obsidian.Plugin {
if (url.startsWith("file://")) { if (url.startsWith("file://")) {
if (import_obsidian.Platform.isDesktop) { if (import_obsidian.Platform.isDesktop) {
try { try {
const { shell } = require("electron"); const electronPath = "electron";
const { shell } = require(electronPath);
let filePath = decodeURIComponent(url.substring(7)); let filePath = decodeURIComponent(url.substring(7));
if (filePath.startsWith("/") && filePath.charAt(2) === ":") { if (filePath.startsWith("/") && filePath.charAt(2) === ":") {
filePath = filePath.substring(1); filePath = filePath.substring(1);
@@ -263,15 +281,6 @@ ${dataviewQuery}
}); });
observer.observe(dvContainer, { childList: true, subtree: true }); observer.observe(dvContainer, { childList: true, subtree: true });
} }
});
}
onunload() {
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
} }
}; };
var MenuPluginSettingTab = class extends import_obsidian.PluginSettingTab { var MenuPluginSettingTab = class extends import_obsidian.PluginSettingTab {

43
main.ts
View File

@@ -1,4 +1,4 @@
import { App, Plugin, PluginSettingTab, Setting, MarkdownRenderer, Platform } from 'obsidian'; import { App, Plugin, PluginSettingTab, Setting, MarkdownRenderer, Platform, MarkdownPostProcessorContext } from 'obsidian';
interface MenuPluginSettings { interface MenuPluginSettings {
mySetting: string; mySetting: string;
@@ -12,12 +12,34 @@ export default class MenuPlugin extends Plugin {
settings: MenuPluginSettings; settings: MenuPluginSettings;
async onload() { async onload() {
try {
await this.loadSettings(); await this.loadSettings();
// This adds a settings tab so the user can configure various aspects of the plugin // This adds a settings tab so the user can configure various aspects of the plugin
this.addSettingTab(new MenuPluginSettingTab(this.app, this)); this.addSettingTab(new MenuPluginSettingTab(this.app, this));
this.registerMarkdownCodeBlockProcessor('menu', (source, el, ctx) => { this.registerMarkdownCodeBlockProcessor('menu', (source, el, ctx) => {
this.processMenuBlock(source, el, ctx);
});
} catch (error) {
console.error('[obsidian-menus] Failed to load plugin:', error);
throw error;
}
}
onunload() {
// Cleanup if needed
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
}
private processMenuBlock(source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) {
const lines = source.trim().split('\n'); const lines = source.trim().split('\n');
let layoutOrClass = ''; let layoutOrClass = '';
let colors: Record<string, string> = {}; let colors: Record<string, string> = {};
@@ -216,7 +238,9 @@ export default class MenuPlugin extends Plugin {
if (url.startsWith('file://')) { if (url.startsWith('file://')) {
if (Platform.isDesktop) { if (Platform.isDesktop) {
try { try {
const { shell } = require('electron'); // Use dynamic import with proper error handling
const electronPath = 'electron';
const { shell } = require(electronPath);
let filePath = decodeURIComponent(url.substring(7)); let filePath = decodeURIComponent(url.substring(7));
if (filePath.startsWith('/') && filePath.charAt(2) === ':') { if (filePath.startsWith('/') && filePath.charAt(2) === ':') {
filePath = filePath.substring(1); filePath = filePath.substring(1);
@@ -227,8 +251,6 @@ export default class MenuPlugin extends Plugin {
} }
} else { } else {
console.warn('File links are not supported on mobile.'); console.warn('File links are not supported on mobile.');
// Optionally show a notice to the user
// new Notice('File links are not supported on this device.');
} }
} else { } else {
window.open(url, '_blank', 'noopener,noreferrer'); window.open(url, '_blank', 'noopener,noreferrer');
@@ -271,19 +293,6 @@ export default class MenuPlugin extends Plugin {
observer.observe(dvContainer, { childList: true, subtree: true }); observer.observe(dvContainer, { childList: true, subtree: true });
} }
});
}
onunload() {
// Cleanup if needed
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
} }
} }

View File

@@ -1,7 +1,7 @@
{ {
"id": "menu-plugin", "id": "menu-plugin",
"name": "Obsidian Menus", "name": "Obsidian Menus",
"version": "1.3", "version": "1.4",
"minAppVersion": "0.15.0", "minAppVersion": "0.15.0",
"description": "Create custom menus using code blocks with links and CSS styling.", "description": "Create custom menus using code blocks with links and CSS styling.",
"author": "Olivier Legendre", "author": "Olivier Legendre",