mirror of
https://github.com/wenlzhang/obsidian-canvas-format-brush.git
synced 2026-07-22 05:41:31 +00:00
Initial commit
This commit is contained in:
commit
05e5fae703
22 changed files with 2899 additions and 0 deletions
23
.editorconfig
Normal file
23
.editorconfig
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
|
||||
# Change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# We recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,html,rb,css,xml,scss,json}]
|
||||
indent_size = 2
|
||||
2
.eslintignore
Normal file
2
.eslintignore
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
npm node_modules
|
||||
build
|
||||
33
.eslintrc
Normal file
33
.eslintrc
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
// "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"no-useless-escape": "off",
|
||||
"no-var": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"no-prototype-builtins": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"@typescript-eslint/no-this-alias": [
|
||||
"error",
|
||||
{
|
||||
"allowDestructuring": false, // Disallow `const { props, state } = this`; true by default
|
||||
"allowedNames": ["self"] // Allow `const self = this`; `[]` by default
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
31
.eslintrc.json
Normal file
31
.eslintrc.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"no-useless-escape": "off",
|
||||
"no-var": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"no-prototype-builtins": "off",
|
||||
"@typescript-eslint/no-empty-function": "off",
|
||||
"@typescript-eslint/no-this-alias": [
|
||||
"error",
|
||||
{
|
||||
"allowDestructuring": true,
|
||||
"allowedNames": ["self"]
|
||||
}
|
||||
],
|
||||
"require-yield": "off"
|
||||
}
|
||||
}
|
||||
15
.github/FUNDING.yml
vendored
Normal file
15
.github/FUNDING.yml
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# These are supported funding model platforms
|
||||
|
||||
github: wenlzhang # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: f84556 # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
polar: # Replace with a single Polar username
|
||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||
thanks_dev: # Replace with a single thanks.dev username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
55
.github/workflows/release.yml
vendored
Normal file
55
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "[0-9]+.[0-9]+.[0-9]+"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '18'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
|
||||
- name: Generate Release Notes
|
||||
id: generate_notes
|
||||
run: |
|
||||
# Get the latest tag
|
||||
LATEST_TAG=$(git describe --tags --abbrev=0)
|
||||
# Get the previous tag
|
||||
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || git rev-list --max-parents=0 HEAD)
|
||||
# Generate changelog
|
||||
if [ "$PREVIOUS_TAG" = "$(git rev-list --max-parents=0 HEAD)" ]; then
|
||||
CHANGELOG=$(git log --pretty=format:"- %s" $PREVIOUS_TAG..$LATEST_TAG)
|
||||
else
|
||||
CHANGELOG=$(git log --pretty=format:"- %s" $PREVIOUS_TAG..$LATEST_TAG)
|
||||
fi
|
||||
# Save changelog to file
|
||||
echo "$CHANGELOG" > changelog.md
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body_path: changelog.md
|
||||
draft: true
|
||||
files: |
|
||||
build/main.js
|
||||
build/manifest.json
|
||||
build/styles.css
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
/node_modules
|
||||
main.js
|
||||
main.js.map
|
||||
dist/
|
||||
/build
|
||||
1
.npmrc
Normal file
1
.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
tag-version-prefix=""
|
||||
7
CHANGELOG.md
Normal file
7
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
55
README.md
Normal file
55
README.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# Plugin Template
|
||||
|
||||
This is a template for creating plugins for [Obsidian](https://obsidian.md), maintained by [wenlzhang](https://github.com/wenlzhang).
|
||||
|
||||
## Getting started
|
||||
|
||||
1. Clone this repository to your local machine
|
||||
2. Update the following files with your plugin information:
|
||||
- `manifest.json`:
|
||||
- `id`: Your plugin ID (in kebab-case)
|
||||
- `name`: Your plugin name
|
||||
- `author`: Your name
|
||||
- `authorUrl`: Your website or GitHub profile URL
|
||||
- `fundingUrl`: Optional funding information
|
||||
- `package.json`:
|
||||
- `name`: Your plugin name (should match manifest.json)
|
||||
- `description`: Your plugin description
|
||||
- `author`: Your name
|
||||
- `keywords`: Relevant keywords for your plugin
|
||||
|
||||
## Development
|
||||
|
||||
1. Install dependencies:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
2. Start development server:
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
3. Build the plugin:
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
## Testing your plugin
|
||||
|
||||
1. Create a test vault in Obsidian
|
||||
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
|
||||
|
||||
1. Update `versions.json` with your plugin's version history
|
||||
2. Test your plugin thoroughly
|
||||
3. Create a GitHub release
|
||||
4. Submit your plugin to the Obsidian Plugin Gallery
|
||||
|
||||
## Support me
|
||||
|
||||
<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>
|
||||
65
esbuild.config.mjs
Normal file
65
esbuild.config.mjs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
import esbuild from 'esbuild';
|
||||
import builtins from 'builtin-modules';
|
||||
import { copyFileSync, mkdirSync, existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const banner = `/*
|
||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||
if you want to view the source, please visit the github repository of this plugin
|
||||
*/
|
||||
`;
|
||||
|
||||
const prod = process.argv[2] === 'production';
|
||||
|
||||
const buildDir = 'build';
|
||||
|
||||
// Create build directory if it doesn't exist
|
||||
if (!existsSync(buildDir)) {
|
||||
mkdirSync(buildDir);
|
||||
}
|
||||
|
||||
// Copy manifest and styles
|
||||
copyFileSync('manifest.json', join(buildDir, 'manifest.json'));
|
||||
if (existsSync('styles.css')) {
|
||||
copyFileSync('styles.css', join(buildDir, 'styles.css'));
|
||||
}
|
||||
|
||||
try {
|
||||
await esbuild.build({
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
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: prod ? false : 'inline',
|
||||
treeShaking: true,
|
||||
outfile: join(buildDir, 'main.js'),
|
||||
minify: prod,
|
||||
platform: 'node',
|
||||
mainFields: ['browser', 'module', 'main'],
|
||||
write: true,
|
||||
allowOverwrite: true,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Build failed:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
21
jest.config.js
Normal file
21
jest.config.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
||||
export default {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
transform: {
|
||||
'^.+\\.tsx?$': ['ts-jest', {
|
||||
useESM: true,
|
||||
}],
|
||||
},
|
||||
moduleNameMapper: {
|
||||
'^(\\.{1,2}/.*)\\.js$': '$1',
|
||||
},
|
||||
extensionsToTreatAsEsm: ['.ts'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
||||
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$',
|
||||
coverageDirectory: 'coverage',
|
||||
collectCoverageFrom: [
|
||||
'src/**/*.{ts,tsx,js,jsx}',
|
||||
'!src/**/*.d.ts'
|
||||
]
|
||||
};
|
||||
12
manifest.json
Normal file
12
manifest.json
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"id": "plugin-template",
|
||||
"name": "Plugin Template",
|
||||
"version": "0.0.1",
|
||||
"minAppVersion": "1.0.0",
|
||||
"author": "wenlzhang",
|
||||
"authorUrl": "https://github.com/wenlzhang",
|
||||
"fundingUrl": {
|
||||
"Buy Me a Coffee": "https://ko-fi.com/f84556"
|
||||
},
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
2370
package-lock.json
generated
Normal file
2370
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
43
package.json
Normal file
43
package.json
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"name": "plugin-template",
|
||||
"version": "0.0.1",
|
||||
"description": "Plugin Template.",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"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",
|
||||
"pretest": "eslint src/",
|
||||
"test": "jest --passWithNoTests",
|
||||
"prettier": "prettier -w 'src/**/*.ts'",
|
||||
"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/",
|
||||
"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": "",
|
||||
"keywords": [
|
||||
"obsidian"
|
||||
],
|
||||
"author": "wenlzhang",
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.16.0",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/node": "^16.11.7",
|
||||
"@typescript-eslint/eslint-plugin": "^5.40.1",
|
||||
"@typescript-eslint/parser": "^5.40.1",
|
||||
"builtin-modules": "^4.0.0",
|
||||
"esbuild": "^0.13.15",
|
||||
"eslint": "^8.24.0",
|
||||
"eslint-config-standard": "^17.0.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^6.0.0",
|
||||
"jest": "^29.7.0",
|
||||
"obsidian": "latest",
|
||||
"prettier": "^3.4.2",
|
||||
"ts-jest": "^29.2.5",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.1"
|
||||
}
|
||||
}
|
||||
36
src/main.ts
Normal file
36
src/main.ts
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import { Plugin } from 'obsidian';
|
||||
import { SettingsTab } from './settingsTab';
|
||||
import { PluginSettings, DEFAULT_SETTINGS } from './settings';
|
||||
|
||||
export default class MyPlugin extends Plugin {
|
||||
settings: PluginSettings;
|
||||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
|
||||
// Add settings tab
|
||||
this.addSettingTab(new SettingsTab(this.app, this));
|
||||
|
||||
// Add your plugin's functionality here
|
||||
// For example:
|
||||
// this.addCommand({
|
||||
// id: 'example-command',
|
||||
// name: 'Example Command',
|
||||
// callback: () => {
|
||||
// // Command logic
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
onunload() {
|
||||
// Cleanup when the plugin is disabled
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
}
|
||||
10
src/settings.ts
Normal file
10
src/settings.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { App } from 'obsidian';
|
||||
|
||||
export interface PluginSettings {
|
||||
// Add your settings properties here
|
||||
exampleSetting: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: PluginSettings = {
|
||||
exampleSetting: 'default'
|
||||
};
|
||||
29
src/settingsTab.ts
Normal file
29
src/settingsTab.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { App, PluginSettingTab, Setting } from 'obsidian';
|
||||
import type MyPlugin from './main';
|
||||
|
||||
export class SettingsTab extends PluginSettingTab {
|
||||
plugin: MyPlugin;
|
||||
|
||||
constructor(app: App, plugin: MyPlugin) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
|
||||
containerEl.createEl('h2', { text: 'Plugin Settings' });
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Example Setting')
|
||||
.setDesc('This is an example setting')
|
||||
.addText(text => text
|
||||
.setPlaceholder('Enter your setting')
|
||||
.setValue(this.plugin.settings.exampleSetting)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.exampleSetting = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
}
|
||||
}
|
||||
25
tsconfig.json
Normal file
25
tsconfig.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"module": "ESNext",
|
||||
"target": "ES6",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7",
|
||||
"ES2021"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}
|
||||
14
version-bump.mjs
Normal file
14
version-bump.mjs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { readFileSync, writeFileSync } from "fs";
|
||||
|
||||
const targetVersion = process.env.npm_package_version;
|
||||
|
||||
// read minAppVersion from manifest.json and bump version to target version
|
||||
let manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
|
||||
const { minAppVersion } = manifest;
|
||||
manifest.version = targetVersion;
|
||||
writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
|
||||
|
||||
// update versions.json with target version and minAppVersion from manifest.json
|
||||
let versions = JSON.parse(readFileSync("versions.json", "utf8"));
|
||||
versions[targetVersion] = minAppVersion;
|
||||
writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));
|
||||
43
version-changelog.mjs
Normal file
43
version-changelog.mjs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
// Get the new version from package.json
|
||||
const packageJson = JSON.parse(readFileSync('./package.json', 'utf8'));
|
||||
const newVersion = packageJson.version;
|
||||
const date = new Date().toISOString().split('T')[0];
|
||||
|
||||
// Read the current changelog
|
||||
let changelog = readFileSync('./CHANGELOG.md', 'utf8');
|
||||
|
||||
// Get commit messages since last tag
|
||||
const getCommitsSinceLastTag = () => {
|
||||
try {
|
||||
const lastTag = execSync('git describe --tags --abbrev=0', { encoding: 'utf8' }).trim();
|
||||
return execSync(`git log ${lastTag}..HEAD --pretty=format:"- %s"`, { encoding: 'utf8' });
|
||||
} catch (e) {
|
||||
// If no tags exist, get all commits
|
||||
return execSync('git log --pretty=format:"- %s"', { encoding: 'utf8' });
|
||||
}
|
||||
};
|
||||
|
||||
const commitMessages = getCommitsSinceLastTag();
|
||||
|
||||
// Create new version section with proper spacing
|
||||
const newSection = `
|
||||
|
||||
## [${newVersion}] - ${date}
|
||||
|
||||
### Changes
|
||||
|
||||
${commitMessages}
|
||||
`;
|
||||
|
||||
// Insert new section after the header
|
||||
const headerEnd = changelog.indexOf('\n## ');
|
||||
changelog = changelog.slice(0, headerEnd) + newSection + changelog.slice(headerEnd);
|
||||
|
||||
// Write back to CHANGELOG.md
|
||||
writeFileSync('./CHANGELOG.md', changelog);
|
||||
|
||||
// Stage the changelog
|
||||
execSync('git add CHANGELOG.md');
|
||||
3
versions.json
Normal file
3
versions.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"0.0.1": "0.0.1"
|
||||
}
|
||||
Loading…
Reference in a new issue