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:
65
README.md
65
README.md
@@ -12,6 +12,71 @@ You can:
|
||||
|
||||
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
|
||||
|
||||
Create a menu using a `menu` code block with one of the built-in templates:
|
||||
|
||||
29
main.js
29
main.js
@@ -33,9 +33,26 @@ var DEFAULT_SETTINGS = {
|
||||
};
|
||||
var MenuPlugin = class extends import_obsidian.Plugin {
|
||||
async onload() {
|
||||
try {
|
||||
await this.loadSettings();
|
||||
this.addSettingTab(new MenuPluginSettingTab(this.app, this));
|
||||
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");
|
||||
let layoutOrClass = "";
|
||||
let colors = {};
|
||||
@@ -213,7 +230,8 @@ var MenuPlugin = class extends import_obsidian.Plugin {
|
||||
if (url.startsWith("file://")) {
|
||||
if (import_obsidian.Platform.isDesktop) {
|
||||
try {
|
||||
const { shell } = require("electron");
|
||||
const electronPath = "electron";
|
||||
const { shell } = require(electronPath);
|
||||
let filePath = decodeURIComponent(url.substring(7));
|
||||
if (filePath.startsWith("/") && filePath.charAt(2) === ":") {
|
||||
filePath = filePath.substring(1);
|
||||
@@ -263,15 +281,6 @@ ${dataviewQuery}
|
||||
});
|
||||
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 {
|
||||
|
||||
43
main.ts
43
main.ts
@@ -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 {
|
||||
mySetting: string;
|
||||
@@ -12,12 +12,34 @@ export default class MenuPlugin extends Plugin {
|
||||
settings: MenuPluginSettings;
|
||||
|
||||
async onload() {
|
||||
try {
|
||||
await this.loadSettings();
|
||||
|
||||
// This adds a settings tab so the user can configure various aspects of the plugin
|
||||
this.addSettingTab(new MenuPluginSettingTab(this.app, this));
|
||||
|
||||
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');
|
||||
let layoutOrClass = '';
|
||||
let colors: Record<string, string> = {};
|
||||
@@ -216,7 +238,9 @@ export default class MenuPlugin extends Plugin {
|
||||
if (url.startsWith('file://')) {
|
||||
if (Platform.isDesktop) {
|
||||
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));
|
||||
if (filePath.startsWith('/') && filePath.charAt(2) === ':') {
|
||||
filePath = filePath.substring(1);
|
||||
@@ -227,8 +251,6 @@ export default class MenuPlugin extends Plugin {
|
||||
}
|
||||
} else {
|
||||
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 {
|
||||
window.open(url, '_blank', 'noopener,noreferrer');
|
||||
@@ -271,19 +293,6 @@ export default class MenuPlugin extends Plugin {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "menu-plugin",
|
||||
"name": "Obsidian Menus",
|
||||
"version": "1.3",
|
||||
"version": "1.4",
|
||||
"minAppVersion": "0.15.0",
|
||||
"description": "Create custom menus using code blocks with links and CSS styling.",
|
||||
"author": "Olivier Legendre",
|
||||
|
||||
Reference in New Issue
Block a user