mirror of
https://github.com/wenlzhang/obsidian-canvas-format-brush.git
synced 2026-07-22 05:41:31 +00:00
Add initial version
This commit is contained in:
parent
05e5fae703
commit
7012cdd492
9 changed files with 6310 additions and 658 deletions
93
README.md
93
README.md
|
|
@ -1,55 +1,64 @@
|
||||||
# Plugin Template
|
# Canvas Format Brush for Obsidian
|
||||||
|
|
||||||
This is a template for creating plugins for [Obsidian](https://obsidian.md), maintained by [wenlzhang](https://github.com/wenlzhang).
|
This plugin allows you to copy formatting attributes from one canvas element and apply them to other canvas elements in [Obsidian](https://obsidian.md).
|
||||||
|
|
||||||
## Getting started
|
## Features
|
||||||
|
|
||||||
1. Clone this repository to your local machine
|
- Copy and paste formatting between canvas elements
|
||||||
2. Update the following files with your plugin information:
|
- Supports copying:
|
||||||
- `manifest.json`:
|
- Card color
|
||||||
- `id`: Your plugin ID (in kebab-case)
|
- Card size
|
||||||
- `name`: Your plugin name
|
- Border color
|
||||||
- `author`: Your name
|
- Background color
|
||||||
- `authorUrl`: Your website or GitHub profile URL
|
- Context menu integration for easy access
|
||||||
- `fundingUrl`: Optional funding information
|
- Status bar indicator showing when format is copied
|
||||||
- `package.json`:
|
- Commands for keyboard shortcuts
|
||||||
- `name`: Your plugin name (should match manifest.json)
|
|
||||||
- `description`: Your plugin description
|
|
||||||
- `author`: Your name
|
|
||||||
- `keywords`: Relevant keywords for your plugin
|
|
||||||
|
|
||||||
## Development
|
## How to Use
|
||||||
|
|
||||||
1. Install dependencies:
|
1. Select a canvas element you want to copy formatting from
|
||||||
```bash
|
2. Right-click and select "Copy format" from the context menu (or use the command)
|
||||||
npm install
|
3. Select one or more canvas elements you want to apply the formatting to
|
||||||
```
|
4. Right-click and select "Paste format" from the context menu (or use the command)
|
||||||
|
|
||||||
2. Start development server:
|
## Commands
|
||||||
```bash
|
|
||||||
npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Build the plugin:
|
- **Copy format from selected canvas element**: Copies formatting attributes from the currently selected canvas element
|
||||||
```bash
|
- **Paste format to selected canvas elements**: Applies the copied formatting to all currently selected canvas elements
|
||||||
npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
## Testing your plugin
|
## Settings
|
||||||
|
|
||||||
1. Create a test vault in Obsidian
|
You can customize which formatting attributes are copied:
|
||||||
2. Create a `.obsidian/plugins` folder in your test vault
|
|
||||||
3. Copy your plugin folder into the plugins folder
|
|
||||||
4. Reload Obsidian to load the plugin (Ctrl/Cmd + R)
|
|
||||||
5. Enable the plugin in Obsidian's settings
|
|
||||||
|
|
||||||
## Publishing your plugin
|
- **Copy color**: Enable/disable copying of the card color
|
||||||
|
- **Copy size**: Enable/disable copying of the card size
|
||||||
|
- **Copy border color**: Enable/disable copying of the border color
|
||||||
|
- **Copy background color**: Enable/disable copying of the background color
|
||||||
|
|
||||||
1. Update `versions.json` with your plugin's version history
|
Additional settings:
|
||||||
2. Test your plugin thoroughly
|
|
||||||
3. Create a GitHub release
|
|
||||||
4. Submit your plugin to the Obsidian Plugin Gallery
|
|
||||||
|
|
||||||
## Support me
|
- **Show status bar item**: Show/hide the format brush status in the status bar
|
||||||
|
- **Enable hotkeys**: Enable/disable hotkeys for copy and paste format (configure in Obsidian hotkeys settings)
|
||||||
|
|
||||||
<a href='https://ko-fi.com/C0C66C1TB' target='_blank'><img height='36' style='border:0px;height:36px;' src='https://storage.ko-fi.com/cdn/kofi1.png?v=3' border='0' alt='Buy Me a Coffee at ko-fi.com' /></a>
|
## Installation
|
||||||
|
|
||||||
|
### From Obsidian
|
||||||
|
|
||||||
|
1. Open Settings in Obsidian
|
||||||
|
2. Go to Community Plugins and turn off Safe Mode
|
||||||
|
3. Click Browse and search for "Canvas Format Brush"
|
||||||
|
4. Install the plugin and enable it
|
||||||
|
|
||||||
|
### Manual Installation
|
||||||
|
|
||||||
|
1. Download the latest release from the releases page
|
||||||
|
2. Extract the zip file into your Obsidian vault's `.obsidian/plugins` folder
|
||||||
|
3. Enable the plugin in Obsidian's Community Plugins settings
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
If you encounter any issues or have suggestions for improvements, please create an issue on the GitHub repository.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the MIT License.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"id": "plugin-template",
|
"id": "canvas-format-brush",
|
||||||
"name": "Plugin Template",
|
"name": "Canvas Format Brush",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"minAppVersion": "1.0.0",
|
"minAppVersion": "1.0.0",
|
||||||
"author": "wenlzhang",
|
"author": "wenlzhang",
|
||||||
|
|
@ -8,5 +8,6 @@
|
||||||
"fundingUrl": {
|
"fundingUrl": {
|
||||||
"Buy Me a Coffee": "https://ko-fi.com/f84556"
|
"Buy Me a Coffee": "https://ko-fi.com/f84556"
|
||||||
},
|
},
|
||||||
|
"description": "Copy and paste formatting between canvas elements, such as card size, color, and other attributes.",
|
||||||
"isDesktopOnly": false
|
"isDesktopOnly": false
|
||||||
}
|
}
|
||||||
6296
package-lock.json
generated
6296
package-lock.json
generated
File diff suppressed because it is too large
Load diff
69
package.json
69
package.json
|
|
@ -1,43 +1,46 @@
|
||||||
{
|
{
|
||||||
"name": "plugin-template",
|
"name": "canvas-format-brush",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"description": "Plugin Template.",
|
"description": "Copy and paste formatting between canvas elements, such as card size, color, and other attributes.",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node esbuild.config.mjs",
|
"dev": "node esbuild.config.mjs",
|
||||||
"build": "npm run prettier && node esbuild.config.mjs production && cp manifest.json build && [ -f styles.css ] && cp styles.css build/ || true",
|
"build": "npm run prettier && node esbuild.config.mjs production && cp manifest.json build && [ -f styles.css ] && cp styles.css build/ || true",
|
||||||
"pretest": "eslint src/",
|
"pretest": "eslint src/",
|
||||||
"test": "jest --passWithNoTests",
|
"test": "jest --passWithNoTests",
|
||||||
"prettier": "prettier -w 'src/**/*.ts'",
|
"prettier": "prettier -w 'src/**/*.ts'",
|
||||||
"preversion": "npm run build && npm run test",
|
"preversion": "npm run build && npm run test",
|
||||||
"version": "node version-bump.mjs && node version-changelog.mjs && git add manifest.json versions.json CHANGELOG.md && cp manifest.json build/",
|
"version": "node version-bump.mjs && node version-changelog.mjs && git add manifest.json versions.json CHANGELOG.md && cp manifest.json build/",
|
||||||
"postversion": "git push && git push --tags && gh release create $npm_package_version -F CHANGELOG.md --draft build/main.js manifest.json $([ -f styles.css ] && echo 'styles.css' || true)"
|
"postversion": "git push && git push --tags && gh release create $npm_package_version -F CHANGELOG.md --draft build/main.js manifest.json $([ -f styles.css ] && echo 'styles.css' || true)"
|
||||||
},
|
},
|
||||||
"version-tag-prefix": "",
|
"version-tag-prefix": "",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"obsidian"
|
"obsidian",
|
||||||
|
"canvas",
|
||||||
|
"format",
|
||||||
|
"brush"
|
||||||
],
|
],
|
||||||
"author": "wenlzhang",
|
"author": "wenlzhang",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.16.0",
|
"@eslint/js": "^9.16.0",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/node": "^16.11.7",
|
"@types/node": "^16.11.7",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
||||||
"@typescript-eslint/parser": "^5.40.1",
|
"@typescript-eslint/parser": "^5.40.1",
|
||||||
"builtin-modules": "^4.0.0",
|
"builtin-modules": "^4.0.0",
|
||||||
"esbuild": "^0.13.15",
|
"esbuild": "^0.13.15",
|
||||||
"eslint": "^8.24.0",
|
"eslint": "^8.24.0",
|
||||||
"eslint-config-standard": "^17.0.0",
|
"eslint-config-standard": "^17.0.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-promise": "^6.0.0",
|
"eslint-plugin-promise": "^6.0.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"obsidian": "latest",
|
"obsidian": "latest",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"ts-jest": "^29.2.5",
|
"ts-jest": "^29.2.5",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.8.1"
|
"tslib": "^2.8.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
318
src/main.ts
318
src/main.ts
|
|
@ -1,9 +1,41 @@
|
||||||
import { Plugin } from 'obsidian';
|
import { Plugin, WorkspaceLeaf, Menu, Notice, setIcon } from "obsidian";
|
||||||
import { SettingsTab } from './settingsTab';
|
import { SettingsTab } from "./settingsTab";
|
||||||
import { PluginSettings, DEFAULT_SETTINGS } from './settings';
|
import { CanvasFormatBrushSettings, DEFAULT_SETTINGS } from "./settings";
|
||||||
|
|
||||||
export default class MyPlugin extends Plugin {
|
// Define interfaces for Canvas API
|
||||||
settings: PluginSettings;
|
interface CanvasNode {
|
||||||
|
id: string;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
color?: string;
|
||||||
|
borderColor?: string;
|
||||||
|
backgroundColor?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Canvas {
|
||||||
|
nodes: Map<string, CanvasNode>;
|
||||||
|
selection: Set<string>;
|
||||||
|
requestSave: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CanvasView {
|
||||||
|
canvas: Canvas;
|
||||||
|
menu?: Menu;
|
||||||
|
getViewType: () => string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class CanvasFormatBrushPlugin extends Plugin {
|
||||||
|
settings: CanvasFormatBrushSettings;
|
||||||
|
statusBarItem: HTMLElement | null = null;
|
||||||
|
copiedFormat: {
|
||||||
|
color?: string;
|
||||||
|
width?: number;
|
||||||
|
height?: number;
|
||||||
|
borderColor?: string;
|
||||||
|
backgroundColor?: string;
|
||||||
|
} | null = null;
|
||||||
|
|
||||||
async onload() {
|
async onload() {
|
||||||
await this.loadSettings();
|
await this.loadSettings();
|
||||||
|
|
@ -11,26 +43,280 @@ export default class MyPlugin extends Plugin {
|
||||||
// Add settings tab
|
// Add settings tab
|
||||||
this.addSettingTab(new SettingsTab(this.app, this));
|
this.addSettingTab(new SettingsTab(this.app, this));
|
||||||
|
|
||||||
// Add your plugin's functionality here
|
// Register commands
|
||||||
// For example:
|
this.addCommand({
|
||||||
// this.addCommand({
|
id: "copy-canvas-format",
|
||||||
// id: 'example-command',
|
name: "Copy format from selected canvas element",
|
||||||
// name: 'Example Command',
|
checkCallback: (checking: boolean) => {
|
||||||
// callback: () => {
|
const canvasView = this.getActiveCanvasView();
|
||||||
// // Command logic
|
if (canvasView && canvasView.canvas.selection.size === 1) {
|
||||||
// }
|
if (!checking) {
|
||||||
// });
|
this.copyFormat(canvasView);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addCommand({
|
||||||
|
id: "paste-canvas-format",
|
||||||
|
name: "Paste format to selected canvas elements",
|
||||||
|
checkCallback: (checking: boolean) => {
|
||||||
|
const canvasView = this.getActiveCanvasView();
|
||||||
|
if (
|
||||||
|
canvasView &&
|
||||||
|
canvasView.canvas.selection.size > 0 &&
|
||||||
|
this.copiedFormat
|
||||||
|
) {
|
||||||
|
if (!checking) {
|
||||||
|
this.pasteFormat(canvasView);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register context menu event
|
||||||
|
this.registerEvent(
|
||||||
|
this.app.workspace.on(
|
||||||
|
"file-menu",
|
||||||
|
(menu: Menu, file: any, source: string) => {
|
||||||
|
// Only add menu items if we're in a canvas view
|
||||||
|
const canvasView = this.getActiveCanvasView();
|
||||||
|
if (canvasView && source === "canvas-menu") {
|
||||||
|
// Only add menu items if there is a selection
|
||||||
|
if (canvasView.canvas.selection.size > 0) {
|
||||||
|
menu.addItem((item) => {
|
||||||
|
item.setTitle("Copy format")
|
||||||
|
.setIcon("clipboard-copy")
|
||||||
|
.onClick(() => this.copyFormat(canvasView))
|
||||||
|
.setSection("canvas-format-brush");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only enable paste if we have a copied format
|
||||||
|
if (this.copiedFormat) {
|
||||||
|
menu.addItem((item) => {
|
||||||
|
item.setTitle("Paste format")
|
||||||
|
.setIcon("clipboard-paste")
|
||||||
|
.onClick(() =>
|
||||||
|
this.pasteFormat(canvasView),
|
||||||
|
)
|
||||||
|
.setSection("canvas-format-brush");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register status bar
|
||||||
|
this.registerEvent(
|
||||||
|
this.app.workspace.on(
|
||||||
|
"active-leaf-change",
|
||||||
|
(leaf: WorkspaceLeaf | null) => {
|
||||||
|
// Check if the active leaf is a canvas view
|
||||||
|
if (
|
||||||
|
leaf &&
|
||||||
|
leaf.view &&
|
||||||
|
leaf.view.getViewType() === "canvas"
|
||||||
|
) {
|
||||||
|
this.updateStatusBar();
|
||||||
|
} else {
|
||||||
|
// Hide status bar if not in canvas view
|
||||||
|
if (this.statusBarItem) {
|
||||||
|
this.statusBarItem.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Initialize status bar
|
||||||
|
this.initStatusBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
onunload() {
|
onunload() {
|
||||||
// Cleanup when the plugin is disabled
|
// Clean up status bar
|
||||||
|
if (this.statusBarItem) {
|
||||||
|
this.statusBarItem.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadSettings() {
|
async loadSettings() {
|
||||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
this.settings = Object.assign(
|
||||||
|
{},
|
||||||
|
DEFAULT_SETTINGS,
|
||||||
|
await this.loadData(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveSettings() {
|
async saveSettings() {
|
||||||
await this.saveData(this.settings);
|
await this.saveData(this.settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getActiveCanvasView(): CanvasView | null {
|
||||||
|
const activeLeaf = this.app.workspace.activeLeaf;
|
||||||
|
if (
|
||||||
|
activeLeaf &&
|
||||||
|
activeLeaf.view &&
|
||||||
|
activeLeaf.view.getViewType() === "canvas"
|
||||||
|
) {
|
||||||
|
return activeLeaf.view as unknown as CanvasView;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
copyFormat(canvasView: CanvasView) {
|
||||||
|
// Get the selected node
|
||||||
|
const selectedNodeId = Array.from(canvasView.canvas.selection)[0];
|
||||||
|
const selectedNode = canvasView.canvas.nodes.get(selectedNodeId);
|
||||||
|
|
||||||
|
if (!selectedNode) {
|
||||||
|
new Notice("No canvas element selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new format object
|
||||||
|
this.copiedFormat = {};
|
||||||
|
|
||||||
|
// Copy only the attributes that are enabled in settings
|
||||||
|
if (this.settings.copyColor && selectedNode.color) {
|
||||||
|
this.copiedFormat.color = selectedNode.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.settings.copySize) {
|
||||||
|
this.copiedFormat.width = selectedNode.width;
|
||||||
|
this.copiedFormat.height = selectedNode.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.settings.copyBorderColor && selectedNode.borderColor) {
|
||||||
|
this.copiedFormat.borderColor = selectedNode.borderColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.settings.copyBackgroundColor && selectedNode.backgroundColor) {
|
||||||
|
this.copiedFormat.backgroundColor = selectedNode.backgroundColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show a notice
|
||||||
|
new Notice("Format copied from canvas element");
|
||||||
|
|
||||||
|
// Update status bar
|
||||||
|
this.updateStatusBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
pasteFormat(canvasView: CanvasView) {
|
||||||
|
if (!this.copiedFormat) {
|
||||||
|
new Notice("No format copied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all selected nodes
|
||||||
|
const selectedNodeIds = Array.from(canvasView.canvas.selection);
|
||||||
|
if (selectedNodeIds.length === 0) {
|
||||||
|
new Notice("No canvas elements selected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply format to all selected nodes
|
||||||
|
let modifiedCount = 0;
|
||||||
|
for (const nodeId of selectedNodeIds) {
|
||||||
|
const node = canvasView.canvas.nodes.get(nodeId);
|
||||||
|
if (node) {
|
||||||
|
modifiedCount++;
|
||||||
|
|
||||||
|
// Apply only the attributes that were copied
|
||||||
|
if (this.copiedFormat.color !== undefined) {
|
||||||
|
node.color = this.copiedFormat.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.copiedFormat.width !== undefined &&
|
||||||
|
this.copiedFormat.height !== undefined
|
||||||
|
) {
|
||||||
|
node.width = this.copiedFormat.width;
|
||||||
|
node.height = this.copiedFormat.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.copiedFormat.borderColor !== undefined) {
|
||||||
|
node.borderColor = this.copiedFormat.borderColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.copiedFormat.backgroundColor !== undefined) {
|
||||||
|
node.backgroundColor = this.copiedFormat.backgroundColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show a notice
|
||||||
|
new Notice(
|
||||||
|
`Format applied to ${modifiedCount} canvas element${modifiedCount > 1 ? "s" : ""}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Force canvas to redraw
|
||||||
|
// This is a hack, but it works to refresh the canvas view
|
||||||
|
const event = new MouseEvent("mousemove", {
|
||||||
|
view: window,
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
});
|
||||||
|
document.dispatchEvent(event);
|
||||||
|
|
||||||
|
// Save changes
|
||||||
|
canvasView.canvas.requestSave();
|
||||||
|
}
|
||||||
|
|
||||||
|
initStatusBar() {
|
||||||
|
// Add status bar item
|
||||||
|
this.statusBarItem = this.addStatusBarItem();
|
||||||
|
this.statusBarItem.addClass("canvas-format-brush-status");
|
||||||
|
|
||||||
|
// Initialize with empty state
|
||||||
|
this.updateStatusBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStatusBar() {
|
||||||
|
if (!this.statusBarItem) return;
|
||||||
|
|
||||||
|
// Only show if enabled in settings and we're in a canvas view
|
||||||
|
const canvasView = this.getActiveCanvasView();
|
||||||
|
if (!this.settings.showStatusBarItem || !canvasView) {
|
||||||
|
this.statusBarItem.style.display = "none";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.statusBarItem.style.display = "block";
|
||||||
|
this.statusBarItem.empty();
|
||||||
|
|
||||||
|
const container = this.statusBarItem.createEl("div", {
|
||||||
|
cls: "canvas-format-brush-container",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Icon
|
||||||
|
const iconEl = container.createEl("div", {
|
||||||
|
cls: "canvas-format-brush-icon",
|
||||||
|
});
|
||||||
|
setIcon(iconEl, "brush");
|
||||||
|
|
||||||
|
// Text
|
||||||
|
const textEl = container.createEl("span", {
|
||||||
|
cls: "canvas-format-brush-text",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.copiedFormat) {
|
||||||
|
textEl.setText("Format copied");
|
||||||
|
|
||||||
|
// Add color preview if color was copied
|
||||||
|
if (this.copiedFormat.color) {
|
||||||
|
const colorPreview = container.createEl("div", {
|
||||||
|
cls: "canvas-format-brush-color-preview",
|
||||||
|
});
|
||||||
|
colorPreview.style.backgroundColor = this.copiedFormat.color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
textEl.setText("No format copied");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,23 @@
|
||||||
import { App } from 'obsidian';
|
import { Plugin } from "obsidian";
|
||||||
|
|
||||||
export interface PluginSettings {
|
export interface CanvasFormatBrushSettings {
|
||||||
// Add your settings properties here
|
copyColor: boolean;
|
||||||
exampleSetting: string;
|
copySize: boolean;
|
||||||
|
copyBorderColor: boolean;
|
||||||
|
copyBackgroundColor: boolean;
|
||||||
|
enableHotkeys: boolean;
|
||||||
|
copyFormatHotkey: string;
|
||||||
|
pasteFormatHotkey: string;
|
||||||
|
showStatusBarItem: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS: PluginSettings = {
|
export const DEFAULT_SETTINGS: CanvasFormatBrushSettings = {
|
||||||
exampleSetting: 'default'
|
copyColor: true,
|
||||||
|
copySize: true,
|
||||||
|
copyBorderColor: true,
|
||||||
|
copyBackgroundColor: true,
|
||||||
|
enableHotkeys: true,
|
||||||
|
copyFormatHotkey: "Ctrl+Shift+C",
|
||||||
|
pasteFormatHotkey: "Ctrl+Shift+V",
|
||||||
|
showStatusBarItem: true,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,16 @@
|
||||||
import { App, PluginSettingTab, Setting } from 'obsidian';
|
import {
|
||||||
import type MyPlugin from './main';
|
App,
|
||||||
|
PluginSettingTab,
|
||||||
|
Setting,
|
||||||
|
ToggleComponent,
|
||||||
|
TextComponent,
|
||||||
|
} from "obsidian";
|
||||||
|
import type CanvasFormatBrushPlugin from "./main";
|
||||||
|
|
||||||
export class SettingsTab extends PluginSettingTab {
|
export class SettingsTab extends PluginSettingTab {
|
||||||
plugin: MyPlugin;
|
plugin: CanvasFormatBrushPlugin;
|
||||||
|
|
||||||
constructor(app: App, plugin: MyPlugin) {
|
constructor(app: App, plugin: CanvasFormatBrushPlugin) {
|
||||||
super(app, plugin);
|
super(app, plugin);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
|
|
@ -13,17 +19,113 @@ export class SettingsTab extends PluginSettingTab {
|
||||||
const { containerEl } = this;
|
const { containerEl } = this;
|
||||||
containerEl.empty();
|
containerEl.empty();
|
||||||
|
|
||||||
containerEl.createEl('h2', { text: 'Plugin Settings' });
|
containerEl.createEl("h2", { text: "Canvas Format Brush settings" });
|
||||||
|
|
||||||
|
// Format Attributes Section
|
||||||
|
containerEl.createEl("h3", { text: "Format attributes" });
|
||||||
|
|
||||||
new Setting(containerEl)
|
new Setting(containerEl)
|
||||||
.setName('Example Setting')
|
.setName("Copy color")
|
||||||
.setDesc('This is an example setting')
|
.setDesc("Copy the color of the canvas element")
|
||||||
.addText(text => text
|
.addToggle((toggle: ToggleComponent) =>
|
||||||
.setPlaceholder('Enter your setting')
|
toggle
|
||||||
.setValue(this.plugin.settings.exampleSetting)
|
.setValue(this.plugin.settings.copyColor)
|
||||||
.onChange(async (value) => {
|
.onChange(async (value: boolean) => {
|
||||||
this.plugin.settings.exampleSetting = value;
|
this.plugin.settings.copyColor = value;
|
||||||
await this.plugin.saveSettings();
|
await this.plugin.saveSettings();
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Copy size")
|
||||||
|
.setDesc("Copy the size of the canvas element")
|
||||||
|
.addToggle((toggle: ToggleComponent) =>
|
||||||
|
toggle
|
||||||
|
.setValue(this.plugin.settings.copySize)
|
||||||
|
.onChange(async (value: boolean) => {
|
||||||
|
this.plugin.settings.copySize = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Copy border color")
|
||||||
|
.setDesc("Copy the border color of the canvas element")
|
||||||
|
.addToggle((toggle: ToggleComponent) =>
|
||||||
|
toggle
|
||||||
|
.setValue(this.plugin.settings.copyBorderColor)
|
||||||
|
.onChange(async (value: boolean) => {
|
||||||
|
this.plugin.settings.copyBorderColor = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Copy background color")
|
||||||
|
.setDesc("Copy the background color of the canvas element")
|
||||||
|
.addToggle((toggle: ToggleComponent) =>
|
||||||
|
toggle
|
||||||
|
.setValue(this.plugin.settings.copyBackgroundColor)
|
||||||
|
.onChange(async (value: boolean) => {
|
||||||
|
this.plugin.settings.copyBackgroundColor = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Hotkeys Section
|
||||||
|
containerEl.createEl("h3", { text: "Hotkeys" });
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Enable hotkeys")
|
||||||
|
.setDesc("Enable hotkeys for copy and paste format")
|
||||||
|
.addToggle((toggle: ToggleComponent) =>
|
||||||
|
toggle
|
||||||
|
.setValue(this.plugin.settings.enableHotkeys)
|
||||||
|
.onChange(async (value: boolean) => {
|
||||||
|
this.plugin.settings.enableHotkeys = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Copy format hotkey")
|
||||||
|
.setDesc("Hotkey to copy format (set in Obsidian hotkeys settings)")
|
||||||
|
.setDisabled(!this.plugin.settings.enableHotkeys)
|
||||||
|
.addText((text: TextComponent) =>
|
||||||
|
text
|
||||||
|
.setPlaceholder("Ctrl+Shift+C")
|
||||||
|
.setValue(this.plugin.settings.copyFormatHotkey)
|
||||||
|
.setDisabled(true),
|
||||||
|
);
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Paste format hotkey")
|
||||||
|
.setDesc(
|
||||||
|
"Hotkey to paste format (set in Obsidian hotkeys settings)",
|
||||||
|
)
|
||||||
|
.setDisabled(!this.plugin.settings.enableHotkeys)
|
||||||
|
.addText((text: TextComponent) =>
|
||||||
|
text
|
||||||
|
.setPlaceholder("Ctrl+Shift+V")
|
||||||
|
.setValue(this.plugin.settings.pasteFormatHotkey)
|
||||||
|
.setDisabled(true),
|
||||||
|
);
|
||||||
|
|
||||||
|
// UI Settings Section
|
||||||
|
containerEl.createEl("h3", { text: "UI settings" });
|
||||||
|
|
||||||
|
new Setting(containerEl)
|
||||||
|
.setName("Show status bar item")
|
||||||
|
.setDesc("Show format brush status in the status bar")
|
||||||
|
.addToggle((toggle: ToggleComponent) =>
|
||||||
|
toggle
|
||||||
|
.setValue(this.plugin.settings.showStatusBarItem)
|
||||||
|
.onChange(async (value: boolean) => {
|
||||||
|
this.plugin.settings.showStatusBarItem = value;
|
||||||
|
await this.plugin.saveSettings();
|
||||||
|
// Update status bar visibility
|
||||||
|
this.plugin.updateStatusBar();
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
29
styles.css
Normal file
29
styles.css
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* Canvas Format Brush Plugin Styles */
|
||||||
|
|
||||||
|
.canvas-format-brush-status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canvas-format-brush-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canvas-format-brush-icon {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canvas-format-brush-text {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canvas-format-brush-color-preview {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid var(--background-modifier-border);
|
||||||
|
}
|
||||||
|
|
@ -15,8 +15,7 @@
|
||||||
"DOM",
|
"DOM",
|
||||||
"ES5",
|
"ES5",
|
||||||
"ES6",
|
"ES6",
|
||||||
"ES7",
|
"ES7"
|
||||||
"ES2021"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue