Initial commit

This commit is contained in:
wenlzhang 2025-02-25 16:10:47 +01:00 committed by GitHub
commit f398500e4a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 2899 additions and 0 deletions

23
.editorconfig Normal file
View 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
View file

@ -0,0 +1,2 @@
npm node_modules
build

33
.eslintrc Normal file
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,6 @@
/node_modules
main.js
main.js.map
dist/
/build

1
.npmrc Normal file
View file

@ -0,0 +1 @@
tag-version-prefix=""

7
CHANGELOG.md Normal file
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

43
package.json Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,3 @@
{
"0.0.1": "0.0.1"
}