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.
|
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
29
main.js
@@ -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
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 {
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user