From 32b36e8982697c3a29fcb266408a7bb285385746 Mon Sep 17 00:00:00 2001 From: Michael Makarov Date: Mon, 8 Jun 2026 17:50:37 +0300 Subject: [PATCH] chore: add dist release build --- .gitignore | 1 + README.md | 153 +++++++++++++++++++++++++++++++++++++---- package.json | 1 + scripts/build-dist.mjs | 46 +++++++++++++ 4 files changed, 187 insertions(+), 14 deletions(-) create mode 100644 scripts/build-dist.mjs diff --git a/.gitignore b/.gitignore index af551c3..01bb5f0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ node_modules/ main.js +dist/ *.map data.json .DS_Store diff --git a/README.md b/README.md index ea89302..ead2e1b 100644 --- a/README.md +++ b/README.md @@ -2,22 +2,105 @@ obMenu is a modern Markdown formatting toolbar for Obsidian. -It helps users apply common Markdown actions without memorizing every command or hotkey. +It gives writers a compact editing toolbar for common Markdown actions while keeping the editor focused and the cursor where typing should continue. + +> Status: pre-release. The core toolbar, formatting commands, settings, tests, and local release build are in place. The plugin is not published to the Obsidian community plugin directory yet. ## Features -- Formatting buttons for bold, italic, strikethrough, underline, code, highlight, block quote, checkbox, links, and H1-H6 headings. -- Fixed, selection, and cursor toolbar modes. -- Default and compact visual styles. -- Configurable toolbar items. +### Markdown Formatting -## Inspiration +- Bold +- Italic +- Strikethrough +- Underline +- Highlight +- Inline code +- Code block +- Block quote +- Checkbox +- Bulleted list +- Numbered list +- Markdown link +- Wikilink +- Headings H1-H6 -obMenu is a clean-room implementation inspired by cMenu, an earlier Obsidian formatting toolbar plugin. This project does not copy cMenu source files. +### Heading Menu -## License +The default toolbar includes a grouped heading action. Clicking it opens a menu for H1 through H6, so the toolbar stays compact without losing direct heading controls. -MIT License. Copyright (c) 2026 Michael Makarov. +### Toolbar Placement + +obMenu supports three placement modes: + +- `fixed`: keeps the toolbar at the bottom of the workspace. +- `selection`: shows the toolbar near selected text. +- `cursor`: positions the toolbar near the current editor selection/caret when a measurable browser selection rect is available. + +Contextual placement is clamped to the viewport and includes safeguards for small windows and oversized toolbars. + +### Visual Styles + +- `default`: Obsidian-native toolbar density. +- `compact`: smaller buttons for a tighter writing surface. + +Both styles use Obsidian theme variables and work with light and dark themes. + +### Settings + +The settings tab currently supports: + +- Enabling or disabling the toolbar. +- Choosing the placement mode. +- Choosing the visual style. +- Resetting toolbar items to defaults. +- Viewing the current toolbar item list. + +The settings model is normalized on load, so stale or malformed saved data falls back to safe defaults. + +### Editor Behavior + +- Toolbar actions refocus the active Markdown editor. +- Empty inline-format actions place the cursor between inserted markers. +- Existing inline wrappers can be removed by toggling the same wrapper around selected text. +- Checkbox toggling preserves indentation and handles empty checked or unchecked task items. + +## Installation + +obMenu is currently installed manually from a local release build. + +Build the release folder: + +```bash +npm run build:dist +``` + +Copy the generated folder: + +```text +dist/obmenu +``` + +to your vault: + +```text +.obsidian/plugins/obmenu +``` + +Then enable `obMenu` from Obsidian's community plugin settings. + +## Release Build + +`npm run build:dist` creates a clean release folder: + +```text +dist/obmenu/main.js +dist/obmenu/manifest.json +dist/obmenu/styles.css +dist/obmenu/LICENSE +``` + +`dist/` is intentionally ignored by Git. Rebuild it whenever you want a fresh copyable plugin folder. ## Development @@ -33,14 +116,56 @@ Run tests: npm run test ``` -Build the plugin: +Build the root plugin bundle: ```bash npm run build ``` -The Obsidian plugin artifacts are: +Build the copyable release folder: -- `main.js` -- `manifest.json` -- `styles.css` +```bash +npm run build:dist +``` + +## Validation + +The current automated checks cover: + +- Settings normalization. +- Markdown transform behavior. +- H1-H6 heading application. +- Checkbox edge cases. +- Toolbar command registry. +- Contextual toolbar positioning. + +Recommended pre-release checks: + +```bash +npm run test +npm run build +npm run build:dist +npm audit --omit=dev +``` + +## Roadmap + +Planned follow-up work: + +- Drag-and-drop toolbar item ordering. +- UI for adding and removing custom Obsidian commands. +- More precise cursor geometry when Obsidian exposes a stable editor-coordinate API. +- Manual smoke-test notes for common Obsidian themes and vault layouts. +- Release automation for packaged plugin artifacts. + +## Privacy + +obMenu runs locally inside Obsidian. It does not send notes, selections, settings, or telemetry to any external service. + +## Inspiration + +obMenu is a clean-room implementation inspired by cMenu, an earlier Obsidian formatting toolbar plugin. This project does not copy cMenu source files. + +## License + +MIT License. Copyright (c) 2026 Michael Makarov. diff --git a/package.json b/package.json index 71d3ddd..4679765 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "scripts": { "dev": "node esbuild.config.mjs", "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production", + "build:dist": "tsc -noEmit -skipLibCheck && node scripts/build-dist.mjs", "test": "vitest run", "test:watch": "vitest" }, diff --git a/scripts/build-dist.mjs b/scripts/build-dist.mjs new file mode 100644 index 0000000..b3ed37b --- /dev/null +++ b/scripts/build-dist.mjs @@ -0,0 +1,46 @@ +import esbuild from "esbuild"; +import builtins from "builtin-modules"; +import { copyFile, mkdir, rm } from "node:fs/promises"; +import { join } from "node:path"; + +const distDir = "dist/obmenu"; + +await rm(distDir, { recursive: true, force: true }); +await mkdir(distDir, { recursive: true }); + +await esbuild.build({ + banner: { + js: "/* obMenu - a clean-room Obsidian Markdown toolbar */", + }, + entryPoints: ["src/main.ts"], + bundle: true, + external: [ + "obsidian", + "electron", + "@codemirror/autocomplete", + "@codemirror/collab", + "@codemirror/commands", + "@codemirror/language", + "@codemirror/lint", + "@codemirror/search", + "@codemirror/state", + "@codemirror/view", + "@lezer/common", + "@lezer/highlight", + "@lezer/lr", + ...builtins, + ], + format: "cjs", + target: "es2018", + logLevel: "info", + sourcemap: false, + treeShaking: true, + outfile: join(distDir, "main.js"), + minify: true, +}); + +await Promise.all([ + copyFile("manifest.json", join(distDir, "manifest.json")), + copyFile("styles.css", join(distDir, "styles.css")), + copyFile("LICENSE", join(distDir, "LICENSE")), +]);