Initial commit

This commit is contained in:
RavenHogWarts 2025-05-04 12:05:18 +08:00 committed by GitHub
commit 11350fe432
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 3812 additions and 0 deletions

10
.editorconfig Normal file
View file

@ -0,0 +1,10 @@
# top-most EditorConfig file
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 4
tab_width = 4

3
.eslintignore Normal file
View file

@ -0,0 +1,3 @@
node_modules/
main.js

32
.eslintrc Normal file
View file

@ -0,0 +1,32 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"env": { "node": true },
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"parserOptions": {
"sourceType": "module"
},
"rules": {
"no-unused-vars": "off",
"no-mixed-spaces-and-tabs": "off",
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
"@typescript-eslint/ban-ts-comment": "off",
"no-prototype-builtins": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/no-inferrable-types": "off",
"sort-imports": [
"error",
{
"ignoreCase": true,
"ignoreDeclarationSort": true,
"ignoreMemberSort": false,
"memberSyntaxSortOrder": ["none", "all", "multiple", "single"]
}
]
}
}

40
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,40 @@
---
name: 🐛 Bug Report | Bug 报告
about: Create a report to help us improve | 创建一个 bug 报告以帮助我们改进
title: '[Bug] '
labels: bug
assignees: ''
---
### Bug Description | 问题描述
<!-- A clear and concise description of what the bug is | 清晰简洁地描述这个 bug 是什么 -->
### Steps to Reproduce | 复现步骤
<!-- Steps to reproduce the behavior | 详细描述如何复现这个问题 -->
1. Go to '...' | 打开 '...'
2. Click on '....' | 点击 '....'
3. Scroll down to '....' | 滚动到 '....'
4. See error | 看到错误
### Expected Behavior | 预期行为
<!-- A clear and concise description of what you expected to happen | 清晰简洁地描述你期望发生的事情 -->
### Actual Behavior | 实际行为
<!-- A clear and concise description of what actually happened | 清晰简洁地描述实际发生的事情 -->
### Screenshots | 截图
<!-- If applicable, add screenshots to help explain your problem | 如果适用,添加截图以帮助解释你的问题 -->
### Environment | 环境信息
- OS: [e.g., Windows 10, macOS 12.0] | 操作系统: [例如 Windows 10, macOS 12.0]
- Obsidian Version: [e.g., 1.4.16] | Obsidian 版本: [例如 1.4.16]
- Plugin Version: [e.g., 1.0.0] | 插件版本: [例如 1.0.0]
### Other Plugins | 其他插件
<!-- List enabled plugins, especially those that might be related to this issue | 列出已启用的其他插件,特别是可能与此问题相关的插件 -->
### Additional Context | 附加信息
<!-- Add any other context about the problem here | 添加关于这个问题的任何其他上下文信息 -->
### Console Logs | 控制台日志
<!-- If applicable, provide relevant console logs | 如果适用,请提供相关的控制台日志 -->

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View file

@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: 💬 Discussion Forum | 讨论区
url: https://github.com/RavenHogWarts/obsidian-ravenhogwarts-toolkit/discussions
about: Please ask general questions here | 请在这里提出一般性问题

View file

@ -0,0 +1,25 @@
---
name: 💡 Feature Request | 功能请求
about: Suggest an idea for this project | 为这个项目提出一个想法
title: '[Feature] '
labels: enhancement
assignees: ''
---
### Feature Description | 功能描述
<!-- A clear and concise description of the feature you want | 清晰简洁地描述你想要的功能 -->
### Use Case | 使用场景
<!-- Describe the context where this feature would be used and what problem it solves | 描述这个功能会在什么场景下使用,解决什么问题 -->
### Proposed Solution | 期望的解决方案
<!-- Describe how you'd like this feature to work | 描述你希望这个功能如何工作 -->
### Alternative Solutions | 替代方案
<!-- Describe any alternative solutions or features you've considered | 描述你考虑过的替代解决方案或功能 -->
### Additional Context | 其他上下文
<!-- Add any other context or screenshots about the feature request here | 添加关于功能请求的其他上下文或截图 -->
### Implementation Suggestions | 实现建议
<!-- If you have specific ideas about how to implement this feature, describe them here | 如果你有关于如何实现这个功能的具体想法,请在这里描述 -->

258
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,258 @@
name: Release Obsidian plugin
on:
push:
tags:
- "[0-9]+.[0-9]+.[0-9]+*" # 匹配类似 1.0.0 或 1.0.0-beta.1 的格式
permissions:
contents: write
env:
PLUGIN_NAME: xxx(replace all occurrences of xxx with your plugin name)
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # 获取完整的git历史
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: "18.x"
- name: Prepare manifest
id: prepare_manifest
run: |
if [[ ${{ github.ref }} == *"beta"* ]]; then
cp manifest-beta.json manifest.json
fi
- name: Build
id: build
run: |
npm install -g yarn
yarn
yarn run build --if-present
mkdir ${{ env.PLUGIN_NAME }}
cp main.js manifest.json styles.css ${{ env.PLUGIN_NAME }}
zip -r ${{ env.PLUGIN_NAME }}.zip ${{ env.PLUGIN_NAME }}
ls
echo "tag_name=$(git tag --sort version:refname | tail -n 1)" >> $GITHUB_OUTPUT
- name: Generate Changelog
id: changelog
run: |
# 定义部分名称
declare -A SECTION_MAP
SECTION_MAP["BREAKING CHANGES"]="BREAKING CHANGES"
SECTION_MAP["Features"]="Features"
SECTION_MAP["Bug Fixes"]="Bug Fixes"
SECTION_MAP["Documentation"]="Documentation"
SECTION_MAP["Styles"]="Styles"
SECTION_MAP["Refactors"]="Refactors"
SECTION_MAP["Performance"]="Performance"
SECTION_MAP["Tests"]="Tests"
SECTION_MAP["Build"]="Build"
SECTION_MAP["CI"]="CI"
SECTION_MAP["Chore"]="Chore"
SECTION_MAP["Reverts"]="Reverts"
# 定义中文翻译
declare -A ZH_SECTION_MAP
ZH_SECTION_MAP["BREAKING CHANGES"]="破坏性变更"
ZH_SECTION_MAP["Features"]="新功能"
ZH_SECTION_MAP["Bug Fixes"]="修复"
ZH_SECTION_MAP["Documentation"]="文档"
ZH_SECTION_MAP["Styles"]="样式"
ZH_SECTION_MAP["Refactors"]="重构"
ZH_SECTION_MAP["Performance"]="性能优化"
ZH_SECTION_MAP["Tests"]="测试"
ZH_SECTION_MAP["Build"]="构建"
ZH_SECTION_MAP["CI"]="持续集成"
ZH_SECTION_MAP["Chore"]="杂项"
ZH_SECTION_MAP["Reverts"]="回退"
# 初始化 changelog 文件
CHANGELOG_EN="CHANGELOG.md"
CHANGELOG_ZH="CHANGELOG-zh.md"
TEMP_CHANGELOG="temp_changelog.md"
# 获取当前版本号(从 git tag
CURRENT_VERSION=$(git tag --sort version:refname | tail -n 1)
echo "Current version: $CURRENT_VERSION"
# 使用 awk 提取特定版本的 changelog 内容
extract_changelog() {
local changelog_file=$1
local output_file=$2
local is_chinese=$3
local target_version=$4
> "$output_file" # 初始化空文件
# 确定版本的标题级别 (# 或 ##)
# 分解版本号,检查是否为小版本
IFS='.' read -r major minor patch <<< "$target_version"
# 如果patch不是0那么是小版本使用二级标题 (##)
if [[ -n "$patch" && "$patch" != "0" ]]; then
local title_level="##"
else
# 大版本或次版本,使用一级标题 (#)
local title_level="#"
fi
echo "Looking for version $target_version with title level: $title_level"
# 使用 awk 提取目标版本的内容到临时文件
awk -v version="$target_version" -v level="$title_level" '
BEGIN { found = 0; printing = 0; }
# 当找到目标版本标题时
$0 ~ "^" level " +\\[" version "\\]" {
found = 1;
printing = 1;
next; # 跳过版本标题行
}
# 当找到下一个版本标题时停止打印
printing && $0 ~ "^#+ +\\[" {
printing = 0;
}
# 打印匹配到的内容
printing {
print;
}
# 文件结束时,如果没有找到目标版本,输出警告
END {
if (!found) {
print "Warning: Version " version " not found with title level " level > "/dev/stderr";
exit 1;
}
}' "$changelog_file" > "temp_version_content.md"
# 检查提取内容
if [ ! -s "temp_version_content.md" ]; then
echo "Warning: No content found for version $target_version in $changelog_file" >&2
echo -e "## Changes\n\nNo changelog found for version $target_version.\n" >> "$output_file"
else
echo "Successfully extracted changelog for version $target_version"
echo -e "## Changes\n" >> "$output_file"
cat "temp_version_content.md" >> "$output_file"
fi
# 添加安装说明
if [ "$is_chinese" = true ]; then
echo -e "\n## 如何安装\n" >> "$output_file"
echo -e "1. 下载 \`xxx.zip\` 压缩文件" >> "$output_file"
echo -e "2. 解压到你的 Obsidian 库的插件文件夹内: \`<vault>/.obsidian/plugins/xxx/\`" >> "$output_file"
echo -e "3. 重启 Obsidian" >> "$output_file"
echo -e "4. 在设置中启用 **Yearly Glance**" >> "$output_file"
else
echo -e "\n## Installation\n" >> "$output_file"
echo -e "1. Download the files from the Assets section below" >> "$output_file"
echo -e "2. Copy them to your vault's plugins folder: \`<vault>/.obsidian/plugins/xxx/\`" >> "$output_file"
echo -e "3. Reload Obsidian" >> "$output_file"
echo -e "4. Enable **Yearly Glance** plugin in settings" >> "$output_file"
fi
}
# 处理英文 changelog
if [ -f "$CHANGELOG_EN" ]; then
extract_changelog "$CHANGELOG_EN" "en_$TEMP_CHANGELOG" false "$CURRENT_VERSION"
else
echo "英文 changelog 文件未找到。使用备用方案。"
echo -e "## Changes\n\nNo changelog available.\n\n## Installation\n\n1. Download the files from the Assets section below\n2. Copy them to your vault's plugins folder: \`<vault>/.obsidian/plugins/xxx/\`\n3. Reload Obsidian\n4. Enable plugin in settings" > "en_$TEMP_CHANGELOG"
fi
# 处理中文 changelog
if [ -f "$CHANGELOG_ZH" ]; then
extract_changelog "$CHANGELOG_ZH" "zh_$TEMP_CHANGELOG" true "$CURRENT_VERSION"
# 合并两个 changelogs
echo -e "# English Changelog\n" > "$TEMP_CHANGELOG"
cat "en_$TEMP_CHANGELOG" >> "$TEMP_CHANGELOG"
echo -e "\n\n___\n\n# 中文更新日志\n" >> "$TEMP_CHANGELOG"
cat "zh_$TEMP_CHANGELOG" >> "$TEMP_CHANGELOG"
else
# 如果没有中文 changelog只使用英文版本
cp "en_$TEMP_CHANGELOG" "$TEMP_CHANGELOG"
fi
# 输出 changelog 给 GitHub Actions
echo "changelog<<EOF" >> $GITHUB_OUTPUT
cat "$TEMP_CHANGELOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
draft: false
prerelease: ${{ contains(github.ref, 'beta') }}
body: |
${{ contains(github.ref, 'beta') && '🚧 This is a beta release' || '🎉 This is a stable release' }}
**Version:** ${{ github.ref_name }}
${{ steps.changelog.outputs.changelog }}
## Installation
1. Download the files from the Assets section below
2. Copy them to your vault's plugins folder: `<vault>/.obsidian/plugins/xxx/`
3. Reload Obsidian
4. Enable plugin in settings
- name: Upload zip file
id: upload-zip
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./${{ env.PLUGIN_NAME }}.zip
asset_name: ${{ env.PLUGIN_NAME }}.zip
asset_content_type: application/zip
- name: Upload main.js
id: upload-main
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./main.js
asset_name: main.js
asset_content_type: text/javascript
- name: Upload manifest.json
id: upload-manifest
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./manifest.json
asset_name: manifest.json
asset_content_type: application/json
- name: Upload styles.css
id: upload-styles
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./styles.css
asset_name: styles.css
asset_content_type: text/css

32
.gitignore vendored Normal file
View file

@ -0,0 +1,32 @@
# vscode
.vscode
# Intellij
*.iml
.idea
# npm
node_modules
# Don't include the compiled main.js file in the repo.
# They should be uploaded to GitHub releases instead.
main.js
styles.css
# Exclude sourcemaps
*.map
# obsidian
data.json
# Exclude macOS Finder (System Explorer) View States
.DS_Store
# Exclude Windows Explorer (Resource Manager) View States
Thumbs.db
# other
*.bat
*.zip
.env
dist

1
.npmrc Normal file
View file

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

287
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,287 @@
# Contributing to xxx English Version
Thank you for your interest in contributing to xxx! This document provides guidelines and instructions for contributing to this project.
## Table of Contents
- [Contributing to xxx English Version](#contributing-to-xxx-english-version)
- [Table of Contents](#table-of-contents)
- [Code of Conduct](#code-of-conduct)
- [Getting Started](#getting-started)
- [Development Workflow](#development-workflow)
- [Pull Request Process](#pull-request-process)
- [Coding Standards](#coding-standards)
- [Commit Guidelines](#commit-guidelines)
- [Reporting Bugs](#reporting-bugs)
- [Feature Requests](#feature-requests)
- [贡献指南中文版本](#贡献指南中文版本)
- [目录](#目录)
- [行为准则](#行为准则)
- [入门指南](#入门指南)
- [开发工作流程](#开发工作流程)
- [拉取请求流程](#拉取请求流程)
- [编码标准](#编码标准)
- [提交指南](#提交指南)
- [报告错误](#报告错误)
- [功能请求](#功能请求)
## Code of Conduct
By participating in this project, you are expected to uphold our Code of Conduct:
- Use welcoming and inclusive language
- Be respectful of differing viewpoints and experiences
- Gracefully accept constructive criticism
- Focus on what is best for the community
- Show empathy towards other community members
## Getting Started
1. **Fork the repository** on GitHub
2. **Clone your fork** locally
```bash
git clone https://github.com/your-username/xxx.git
cd xxx
```
3. **Install dependencies**
```bash
npm install
```
4. **Set up development environment**
- Create a `.env` file following the example in `.env.example`
- For local testing with Obsidian, you can use the build:local script
```.env.example
VAULT_PATH=/path/to/your/vault
```
## Development Workflow
1. **Create a branch** for your feature or bugfix:
```bash
git checkout -b feature/your-feature-name
```
or
```bash
git checkout -b fix/issue-you-are-fixing
```
2. **Make your changes** and test them thoroughly
3. **Build and test locally**:
```bash
npm run build:local
```
4. **Commit your changes** following our [commit guidelines](#commit-guidelines)
## Pull Request Process
1. **Update documentation** if necessary
2. **Ensure tests pass** if applicable
3. **Make sure your code lints** without errors(no-explicit-any / no-unused-vars / no-non-null-assertion can be ignore):
```bash
npm run lint
```
4. **Push your branch** to your fork:
```bash
git push origin feature/your-feature-name
```
5. **Create a Pull Request** against the `master` branch of the original repository
6. **Describe your changes** in detail, referencing any related issues
## Coding Standards
- Follow the existing code style in the project
- Use TypeScript for type safety
- Document your code with appropriate comments
- Write clear, descriptive variable and function names
- Fix any linting errors before submitting(no-explicit-any / no-unused-vars / no-non-null-assertion can be ignore):
```bash
npm run lint:fix
```
## Commit Guidelines
We use [Conventional Commits](https://www.conventionalcommits.org/) for commit messages:
```
<type>(<scope>): <description>
[optional body]
[optional footer]
```
Common types include:
- `feat`: A new feature
- `fix`: A bug fix
- `docs`: Documentation changes
- `style`: Code style changes (formatting, etc.)
- `refactor`: Code changes that neither fix bugs nor add features
- `perf`: Performance improvements
- `test`: Adding or updating tests
- `chore`: Changes to the build process or auxiliary tools
You can use our commitizen setup to help format commits correctly:
```bash
git add .
npx cz
```
## Reporting Bugs
When reporting bugs, please include:
- A clear, descriptive title
- Steps to reproduce the issue
- Expected behavior
- Actual behavior
- Screenshots if applicable
- Your environment (OS, Obsidian version, plugin version)
## Feature Requests
Feature requests are welcome. Please provide:
- A clear description of the feature
- Why this feature would be beneficial
- Any implementation ideas you might have
---
# 贡献指南中文版本
感谢您有兴趣为 Yearly Glance 做出贡献!本文档提供了为该项目做出贡献的指南和说明。
## 目录
- [行为准则](#行为准则)
- [入门指南](#入门指南)
- [开发工作流程](#开发工作流程)
- [拉取请求流程](#拉取请求流程)
- [编码标准](#编码标准)
- [提交指南](#提交指南)
- [报告错误](#报告错误)
- [功能请求](#功能请求)
## 行为准则
通过参与此项目,您应当遵守我们的行为准则:
- 使用友好和包容的语言
- 尊重不同的观点和经验
- 优雅地接受建设性批评
- 关注对社区最有利的事情
- 对其他社区成员表示同理心
## 入门指南
1. **在 GitHub 上 Fork 仓库**
2. **在本地克隆您的 Fork**
```bash
git clone https://github.com/your-username/xxx.git
cd xxx
```
3. **安装依赖**
```bash
npm install
```
4. **设置开发环境**
- 按照 `.env.example`的示例创建 `.env` 文件
- 对于与 Obsidian 的本地测试,您可以使用 build:local 脚本
```.env.example
VAULT_PATH=/path/to/your/vault
```
## 开发工作流程
1. **为您的功能或错误修复创建分支**
```bash
git checkout -b feature/您的功能名称
```
```bash
git checkout -b fix/您要修复的问题
```
2. **进行更改** 并彻底测试
3. **在本地构建和测试**
```bash
npm run build:local
```
4. **提交您的更改**,遵循我们的[提交指南](#提交指南)
## 拉取请求流程
1. **必要时更新文档**
2. **确保测试通过**(如果适用)
3. **确保您的代码没有 lint 错误**no-explicit-any / no-unused-vars / no-non-null-assertion 可以忽略):
```bash
npm run lint
```
4. **将您的分支推送**到您的 Fork
```bash
git push origin feature/您的功能名称
```
5. **对原始仓库的 `master` 分支创建拉取请求**
6. **详细描述您的更改**,引用任何相关问题
## 编码标准
- 遵循项目中现有的代码风格
- 使用 TypeScript 确保类型安全
- 用适当的注释记录您的代码
- 编写清晰、描述性的变量和函数名
- 在提交前修复任何 lint 错误no-explicit-any / no-unused-vars / no-non-null-assertion 可以忽略):
```bash
npm run lint:fix
```
## 提交指南
我们使用 [Conventional Commits](https://www.conventionalcommits.org/) 作为提交消息规范:
```
<类型>(<范围>): <描述>
[可选的正文]
[可选的页脚]
```
常见类型包括:
- `feat`: 新功能
- `fix`: 错误修复
- `docs`: 文档变更
- `style`: 代码风格变更(格式化等)
- `refactor`: 既不修复错误也不添加功能的代码变更
- `perf`: 性能改进
- `test`: 添加或更新测试
- `chore`: 构建过程或辅助工具的变更
您可以使用我们的 commitizen 设置来帮助正确格式化提交:
```bash
git add .
npx cz
```
## 报告错误
报告错误时,请包括:
- 清晰、描述性的标题
- 重现问题的步骤
- 预期行为
- 实际行为
- 截图(如适用)
- 您的环境操作系统、Obsidian 版本、插件版本)
## 功能请求
欢迎功能请求。请提供:
- 功能的清晰描述
- 为什么这个功能会有益
- 您可能有的任何实现想法

0
LICENSE Normal file
View file

19
MAKEFILE Normal file
View file

@ -0,0 +1,19 @@
# Release stable version, e.g.: make release v=1.0.0
release:
@git tag "$(v)"
@git push origin "$(v)"
# Release beta version, e.g.: make beta v=1.0.0-beta.1
beta:
@git tag "$(v)"
@git push origin "$(v)"
# Delete a version, e.g.: make del v=1.0.0
del:
@git tag -d "$(v)"
@git push origin --delete "$(v)"
# Legacy command for backward compatibility
push:
@git tag "$(tag)"
@git push origin "$(tag)"

75
README-zh.md Normal file
View file

@ -0,0 +1,75 @@
中文 | [English](./README.md)
# Obsidian 示例插件
这是一个用于 Obsidian (https://obsidian.md) 的示例插件。
该项目使用 Typescript 提供类型检查和文档支持。
此仓库依赖于最新的插件 APIobsidian.d.ts它以 Typescript 定义格式提供,并包含描述其功能的 TSDoc 注释。
[![GitHub stars](https://img.shields.io/github/stars/RavenHogWarts/obsidian-plugin-starter?style=flat&label=星标)](https://github.com/RavenHogWarts/obsidian-plugin-starter/stargazers)
[![Total Downloads](https://img.shields.io/github/downloads/RavenHogWarts/obsidian-plugin-starter/total?style=flat&label=总下载量)](https://github.com/RavenHogWarts/obsidian-plugin-starter/releases)
[![GitHub License](https://img.shields.io/github/license/RavenHogWarts/obsidian-plugin-starter?style=flat&label=许可证)](https://github.com/RavenHogWarts/obsidian-plugin-starter/blob/master/LICENSE)
[![GitHub Issues](https://img.shields.io/github/issues/RavenHogWarts/obsidian-plugin-starter?style=flat&label=问题)](https://github.com/RavenHogWarts/obsidian-plugin-starter/issues)
[![GitHub Last Commit](https://img.shields.io/github/last-commit/RavenHogWarts/obsidian-plugin-starter?style=flat&label=最后提交)](https://github.com/RavenHogWarts/obsidian-plugin-starter/commits/master)
## 安装
### 手动安装
1. 下载最新版本
2. 将 `main.js`、`styles.css` 和 `manifest.json` 复制到你的仓库插件文件夹中:`<vault>/.obsidian/plugins/obsidian-sample-plugin/`
3. 重新加载 Obsidian
4. 在设置 → 社区插件中启用插件
### BRAT推荐给测试用户
1. 安装 [BRAT](https://github.com/TfTHacker/obsidian42-brat) 插件
2. 在 BRAT 设置中点击“添加测试插件”
3. 输入 `RavenHogWarts/obsidian-sample-plugin`
4. 启用插件
## 开发指南
- 克隆此仓库
- 确保你的 NodeJS 版本至少为 v16 (`node --version`)
- 使用 `npm i``yarn` 安装依赖
- 使用 `npm run dev` 启动开发模式并进行实时编译
- 运行 `npm run build` 构建插件
- 运行 `npm run build:local` 构建插件并将其复制到您的 vault 插件文件夹(需要在项目根目录创建一个 `.env` 文件并添加:`VAULT_PATH=/path/to/your/vault`
- 运行 `npm run version` 更新版本号并更新 manifest.json、version.json、package.json
- 运行 `npm run release` 构建插件并更新版本号
## 支持与帮助
如果你遇到任何问题或有建议:
- [在 GitHub 上提交问题](https://github.com/RavenHogWarts/obsidian-plugin-starter/issues)
- [加入讨论](https://github.com/RavenHogWarts/obsidian-plugin-starter/discussions) 提出问题或分享想法
如果你觉得这个插件对你有帮助,可以通过以下方式支持开发:
- 微信/支付宝:[二维码](https://s2.loli.net/2024/05/06/lWBj3ObszUXSV2f.png)
## 许可证
此项目基于 xxx LICENSE 许可 - 详情请参阅 [LICENSE](LICENSE) 文件。
## Star 历史
[![Star 历史图表](https://api.star-history.com/svg?repos=RavenHogWarts/obsidian-plugin-starter&type=Timeline)](https://www.star-history.com/#RavenHogWarts/obsidian-plugin-starter&Timeline)
# 需要修改的文件
在开发或自定义插件时,以下文件可能需要修改:
## [config.yml](./.github/ISSUE_TEMPLATE/config.yml)
- url
## [release.yml](./.github/workflows/release.yml)
- 插件名称 xxx
## [manifest.json](./manifest.json)
- 作者
- 捐赠链接
## [manifest-beta.json](./manifest-beta.json)
- 作者
- 捐赠链接
## [package.json](./package.json)
- 作者

75
README.md Normal file
View file

@ -0,0 +1,75 @@
English | [中文](./README-zh.md)
# Obsidian Sample Plugin
This is a sample plugin for Obsidian (https://obsidian.md).
This project uses Typescript to provide type checking and documentation.
The repo depends on the latest plugin API (obsidian.d.ts) in Typescript Definition format, which contains TSDoc comments describing what it does.
[![GitHub stars](https://img.shields.io/github/stars/RavenHogWarts/obsidian-plugin-starter?style=flat&label=Stars)](https://github.com/RavenHogWarts/obsidian-plugin-starter/stargazers)
[![Total Downloads](https://img.shields.io/github/downloads/RavenHogWarts/obsidian-plugin-starter/total?style=flat&label=Total%20Downloads)](https://github.com/RavenHogWarts/obsidian-plugin-starter/releases)
[![GitHub License](https://img.shields.io/github/license/RavenHogWarts/obsidian-plugin-starter?style=flat&label=License)](https://github.com/RavenHogWarts/obsidian-plugin-starter/blob/master/LICENSE)
[![GitHub Issues](https://img.shields.io/github/issues/RavenHogWarts/obsidian-plugin-starter?style=flat&label=Issues)](https://github.com/RavenHogWarts/obsidian-plugin-starter/issues)
[![GitHub Last Commit](https://img.shields.io/github/last-commit/RavenHogWarts/obsidian-plugin-starter?style=flat&label=Last%20Commit)](https://github.com/RavenHogWarts/obsidian-plugin-starter/commits/master)
## Installation
### Manual Installation
1. Download the latest release
2. Copy `main.js`, `styles.css`, and `manifest.json` to your vault's plugins folder: `<vault>/.obsidian/plugins/obsidian-sample-plugin/`
3. Reload Obsidian
4. Enable the plugin in Settings → Community Plugins
### BRAT (Recommended for Beta Users)
1. Install [BRAT](https://github.com/TfTHacker/obsidian42-brat) plugin
2. Click "Add Beta plugin" in BRAT settings
3. Enter `RavenHogWarts/obsidian-sample-plugin`
4. Enable the plugin
## Development
- Clone this repo
- Make sure your NodeJS is at least v16 (`node --version`)
- `npm i` or `yarn` to install dependencies
- `npm run dev` to start compilation in watch mode
- `npm run build` to build the plugin
- `npm run build:local` to build the plugin and copy it to your vault's plugins folder(need create a .env file in the project root and add the line: VAULT_PATH=/path/to/your/vault)
- `npm run version` to bump the version number and update the manifest.json, version.json, package.json
- `npm run release` to build the plugin and bump the version number
## Support
If you encounter any issues or have suggestions:
- [Open an issue](https://github.com/RavenHogWarts/obsidian-plugin-starter/issues) on GitHub
- [Join the discussion](https://github.com/RavenHogWarts/obsidian-plugin-starter/discussions) for questions and ideas
If you find this plugin helpful, you can support the development through:
- WeChat/Alipay: [QR Code](https://s2.loli.net/2024/05/06/lWBj3ObszUXSV2f.png)
## License
This project is licensed under the xxx LICENSE - see the [LICENSE](LICENSE) file for details.
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=RavenHogWarts/obsidian-plugin-starter&type=Timeline)](https://www.star-history.com/#RavenHogWarts/obsidian-plugin-starter&Timeline)
# Files to Modify
When developing or customizing the plugin, the following files may need to be modified:
## [config.yml](./.github/ISSUE_TEMPLATE/config.yml)
- URL
## [release.yml](./.github/workflows/release.yml)
- Plugin name xxx
## [manifest.json](./manifest.json)
- Author
- Donation link
## [manifest-beta.json](./manifest-beta.json)
- Author
- Donation link
## [package.json](./package.json)
- Author

13
manifest-beta.json Normal file
View file

@ -0,0 +1,13 @@
{
"id": "sample-plugin",
"name": "Sample Plugin",
"version": "1.0.0",
"minAppVersion": "1.6.7",
"description": "Demonstrates some of the capabilities of the Obsidian API.",
"author": "RavenHogWarts",
"authorUrl": "https://github.com/RavenHogWarts",
"fundingUrl": {
"微信/支付宝": "https://s2.loli.net/2024/05/06/lWBj3ObszUXSV2f.png"
},
"isDesktopOnly": true
}

13
manifest.json Normal file
View file

@ -0,0 +1,13 @@
{
"id": "sample-plugin",
"name": "Sample Plugin",
"version": "1.0.0",
"minAppVersion": "1.6.7",
"description": "Demonstrates some of the capabilities of the Obsidian API.",
"author": "RavenHogWarts",
"authorUrl": "https://github.com/RavenHogWarts",
"fundingUrl": {
"微信/支付宝": "https://s2.loli.net/2024/05/06/lWBj3ObszUXSV2f.png"
},
"isDesktopOnly": true
}

2139
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

51
package.json Normal file
View file

@ -0,0 +1,51 @@
{
"name": "obsidian-sample-plugin",
"version": "1.0.0",
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
"main": "main.js",
"scripts": {
"dev": "node scripts/esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node scripts/esbuild.config.mjs production",
"build:local": "tsc -noEmit -skipLibCheck && node scripts/esbuild.config.mjs production && node scripts/copy-to-vault.mjs",
"version": "node scripts/version-bump.mjs",
"changelog:u": "conventional-changelog -p angular -i CHANGELOG.md -s -u -n ./scripts/changelog-option.js && conventional-changelog -p angular -i CHANGELOG-zh.md -s -u -n ./scripts/changelog-option-zh.js",
"changelog:all": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 -n ./scripts/changelog-option.js && conventional-changelog -p angular -i CHANGELOG-zh.md -s -r 0 -n ./scripts/changelog-option-zh.js",
"release:pre": "npm run build && npm run version && npm run changelog:u",
"release:tag": "node scripts/release-tag.mjs",
"lint": "eslint . --ext .ts,.tsx",
"lint:fix": "eslint . --ext .ts,.tsx --fix"
},
"keywords": [
"Obsidian Plugin"
],
"author": "RavenHogWarts",
"license": "MIT",
"engines": {
"node": ">=18.x"
},
"devDependencies": {
"@types/node": "^18.0.0",
"@typescript-eslint/eslint-plugin": "5.29.0",
"@typescript-eslint/parser": "^5.29.0",
"builtin-modules": "3.3.0",
"commitizen": "^4.3.1",
"conventional-changelog-cli": "^5.0.0",
"cz-conventional-changelog": "^3.3.0",
"esbuild": "0.17.3",
"eslint": "^8.57.1",
"fs-extra": "^11.3.0",
"obsidian": "latest",
"postcss": "^8.5.1",
"postcss-nesting": "^13.0.1",
"tslib": "2.4.0",
"typescript": "4.7.4"
},
"dependencies": {
"dotenv": "^16.4.7"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}

View file

@ -0,0 +1,61 @@
module.exports = {
writerOpts: {
transform: (commit, context) => {
// 创建一个新对象而不是修改原对象
const transformedCommit = { ...commit };
// 定义完整的commit类型映射
const typeMap = {
feat: "✨ 新功能",
fix: "🐛 修复",
// docs: "📝 文档",
style: "🎨 样式",
refactor: "♻️ 重构",
perf: "⚡️ 性能优化",
// test: "✅ 测试",
// build: "👷 构建",
// ci: "🔧 持续集成",
// chore: "🔨 杂项",
revert: "⏪️ 回退",
};
// 应用类型映射
if (transformedCommit.type && typeMap[transformedCommit.type]) {
transformedCommit.type = typeMap[transformedCommit.type];
}
// 如果没有匹配的类型,使用默认处理
if (transformedCommit.type === commit.type) {
return false;
}
// 保留URL链接等信息
if (commit.scope === "*") {
transformedCommit.scope = "";
}
// 确保 hash 作为链接文本
if (transformedCommit.hash) {
transformedCommit.shortHash = transformedCommit.hash.substring(
0,
7
);
}
// 处理 BREAKING CHANGE - 创建深层复制
if (commit.notes && commit.notes.length > 0) {
transformedCommit.notes = commit.notes.map((note) => {
// 创建笔记的副本
const noteCopy = { ...note };
// 修改副本而不是原对象
if (noteCopy.title === "BREAKING CHANGE") {
noteCopy.title = "💥 破坏性变更";
}
return noteCopy;
});
}
return transformedCommit;
},
},
};

View file

@ -0,0 +1,61 @@
module.exports = {
writerOpts: {
transform: (commit, context) => {
// 创建一个新对象而不是修改原对象
const transformedCommit = { ...commit };
// 定义完整的commit类型映射
const typeMap = {
feat: "✨ Features",
fix: "🐛 Bug Fixes",
// docs: "📝 Documentation",
style: "🎨 Styles",
refactor: "♻️ Refactor",
perf: "⚡️ Performance",
// test: "✅ Tests",
// build: "👷 Build",
// ci: "🔧 CI",
// chore: "🔨 Chore",
revert: "⏪️ Reverts",
};
// 应用类型映射
if (transformedCommit.type && typeMap[transformedCommit.type]) {
transformedCommit.type = typeMap[transformedCommit.type];
}
// 如果没有匹配的类型,跳过
if (transformedCommit.type === commit.type) {
return false;
}
// 保留URL链接等信息
if (commit.scope === "*") {
transformedCommit.scope = "";
}
// 确保 hash 作为链接文本
if (transformedCommit.hash) {
transformedCommit.shortHash = transformedCommit.hash.substring(
0,
7
);
}
// 处理 BREAKING CHANGE - 创建深层复制
if (commit.notes && commit.notes.length > 0) {
transformedCommit.notes = commit.notes.map((note) => {
// 创建笔记的副本
const noteCopy = { ...note };
// 修改副本而不是原对象
if (noteCopy.title === "BREAKING CHANGE") {
noteCopy.title = "💥 BREAKING CHANGE";
}
return noteCopy;
});
}
return transformedCommit;
},
},
};

61
scripts/copy-to-vault.mjs Normal file
View file

@ -0,0 +1,61 @@
import { copyFile, mkdir, readFile } from "fs/promises";
import { existsSync } from "fs";
import { dirname, join } from "path";
import { fileURLToPath } from "url";
import dotenv from "dotenv";
// 获取当前文件的目录
const __dirname = dirname(fileURLToPath(import.meta.url));
const rootDir = join(__dirname, "..");
// 加载 .env 文件中的环境变量
dotenv.config();
// 获取 VAULT_PATH 环境变量
const VAULT_PATH = process.env.VAULT_PATH;
if (!VAULT_PATH) {
throw new Error(
"VAULT_PATH is not defined. Please create a .env file in the project root and add the line: VAULT_PATH=/path/to/your/vault"
);
}
const manifestPath = join(rootDir, "manifest.json");
async function copyToVault() {
try {
// 从 manifest.json 读取插件 ID
const manifestContent = await readFile(manifestPath, "utf8");
const manifest = JSON.parse(manifestContent);
const pluginId = manifest.id;
if (!pluginId) {
throw new Error("无法从 manifest.json 中获取插件 ID");
}
const pluginDir = join(VAULT_PATH, ".obsidian", "plugins", pluginId);
// 确保插件目录存在
if (!existsSync(pluginDir)) {
await mkdir(pluginDir, { recursive: true });
console.log(`创建目录: ${pluginDir}`);
}
// 要复制的文件列表
const filesToCopy = ["main.js", "manifest.json", "styles.css"];
// 复制文件
for (const file of filesToCopy) {
const sourcePath = join(rootDir, file);
const destPath = join(pluginDir, file);
await copyFile(sourcePath, destPath);
console.log(`复制文件: ${file} -> ${destPath}`);
}
console.log(
`所有文件已成功复制到 Obsidian 库的 ${pluginId} 插件目录!`
);
} catch (error) {
console.error("复制文件时出错:", error);
process.exit(1);
}
}
copyToVault();

129
scripts/esbuild.config.mjs Normal file
View file

@ -0,0 +1,129 @@
import esbuild from "esbuild";
import process from "process";
import postcss from "postcss";
import postcssNesting from "postcss-nesting";
import builtins from "builtin-modules";
import fs from "fs-extra";
import path 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 renamePlugin = () => ({
name: "rename-plugin",
setup(build) {
build.onEnd(async (result) => {
const file = build.initialOptions.outfile;
const parent = path.dirname(file);
const cssFileName = path.join(parent, "main.css");
const newCssFileName = path.join(parent, "styles.css");
if (fs.existsSync(cssFileName)) {
try {
if (fs.existsSync(newCssFileName)) {
fs.unlinkSync(newCssFileName);
}
fs.renameSync(cssFileName, newCssFileName);
} catch (e) {
console.error("Failed to rename CSS file:", e);
}
}
});
},
});
const cssReBuild = () => ({
name: "css-rebuild",
setup(build) {
// 注册一个加载器,用于处理所有 CSS 文件
// filter 参数是一个正则表达式,匹配所有 .css 扩展名的文件
build.onLoad({ filter: /\.css$/ }, async (args) => {
try {
// 读取 CSS 文件内容
// args.path 包含当前处理的 CSS 文件的完整路径
const css = await fs.promises.readFile(args.path, "utf8");
// 使用 PostCSS 处理 CSS 文件
// postcssNesting 插件允许在 CSS 中使用嵌套语法(类似 SCSS
const result = await postcss([postcssNesting]).process(css, {
from: args.path, // 指定源文件路径,用于生成正确的源映射
});
// 获取输出目录路径
// build.initialOptions.outfile 是最终 JS 输出文件的路径
const outDir = path.dirname(build.initialOptions.outfile);
// 确保输出目录存在,如果不存在则创建
if (!fs.existsSync(outDir)) {
fs.mkdirSync(outDir, { recursive: true });
}
// 返回处理后的 CSS 内容
// contents: 处理后的 CSS 代码
// loader: 告诉 esbuild 如何解释这些内容(作为 CSS
return {
contents: result.css,
loader: "css",
};
} catch (error) {
// 错误处理:如果 CSS 处理过程中出现任何错误
console.error("Error processing CSS:", error);
// 返回空内容,避免构建完全失败
// 这样即使 CSS 处理失败,构建过程仍然可以继续
return {
contents: "",
loader: "css",
};
}
});
},
});
const context = await esbuild.context({
banner: {
js: banner,
},
entryPoints: ["src/main.ts"],
bundle: true,
plugins: [renamePlugin(), cssReBuild()],
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: "es2020",
logLevel: "info",
sourcemap: prod ? false : "inline",
treeShaking: true,
outfile: "main.js",
minify: prod,
loader: {
".ttf": "base64",
},
});
if (prod) {
await context.rebuild();
process.exit(0);
} else {
await context.watch();
}

36
scripts/release-tag.mjs Normal file
View file

@ -0,0 +1,36 @@
/**
* 执行发版和打标签操作的专用脚本
*/
import { execSync } from "child_process";
// 从 package.json 获取当前版本号
const version = process.env.npm_package_version;
console.log(`📦 Preparing to release version: ${version}`);
try {
// 执行 git add 操作
console.log("📝 添加文件到 git...");
execSync("git add .", { stdio: "inherit" });
// 执行 git commit 操作
console.log("💾 创建提交...");
execSync(`git commit -m "build: ${version}"`, { stdio: "inherit" });
// 执行 git push 操作
console.log("🚀 推送到远程...");
execSync("git push", { stdio: "inherit" });
// 创建版本标签
console.log(`🏷️ 创建标签: ${version}`);
execSync(`git tag ${version}`, { stdio: "inherit" });
// 推送标签到远程
console.log("📤 推送标签到远程...");
execSync("git push --tags", { stdio: "inherit" });
console.log(`✅ 成功发布版本 ${version}!`);
} catch (error) {
console.error(`❌ 发布失败: ${error.message}`);
process.exit(1);
}

217
scripts/version-bump.mjs Normal file
View file

@ -0,0 +1,217 @@
#!/usr/bin/env node
import { existsSync, readFileSync, writeFileSync } from "fs";
import readline from "readline";
// 检查是否为直接调用模式
const directVersion = process.argv[2];
const isDirectMode = !!directVersion;
// 如果是直接调用模式,直接更新版本
if (isDirectMode) {
updateAllFiles(directVersion);
process.exit(0);
}
// 否则,启动交互式模式
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
// 获取当前版本
const packageJson = JSON.parse(readFileSync("package.json", "utf8"));
const currentVersion = packageJson.version;
console.log(`当前版本: ${currentVersion}`);
// 解析版本号
const [major, minor, patch] = currentVersion.split(".").map(Number);
// 显示选项
console.log("\n请选择版本更新类型:");
console.log(`1. 主版本 (${major + 1}.0.0)`);
console.log(`2. 次版本 (${major}.${minor + 1}.0)`);
console.log(`3. 补丁版本 (${major}.${minor}.${patch + 1})`);
console.log(`4. 自定义版本`);
console.log(`5. Beta 版本 (${currentVersion}-beta.1)`);
rl.question("\n请输入选项 (1-5): ", (answer) => {
let newVersion;
let isBeta = false;
switch (answer) {
case "1":
newVersion = `${major + 1}.0.0`;
break;
case "2":
newVersion = `${major}.${minor + 1}.0`;
break;
case "3":
newVersion = `${major}.${minor}.${patch + 1}`;
break;
case "4":
rl.question("请输入自定义版本号 (x.y.z): ", (customVersion) => {
isBeta = customVersion.includes("-beta");
updateAllFiles(customVersion, isBeta);
rl.close();
});
return;
case "5":
// 检查当前版本是否已经是 beta
if (currentVersion.includes("-beta.")) {
const betaRegex = /-beta\.(\d+)$/;
const match = currentVersion.match(betaRegex);
if (match) {
const betaNum = parseInt(match[1], 10);
newVersion = currentVersion.replace(
betaRegex,
`-beta.${betaNum + 1}`
);
} else {
newVersion = `${currentVersion}-beta.1`;
}
} else {
newVersion = `${currentVersion}-beta.1`;
}
isBeta = true;
break;
default:
console.log("无效选项,使用补丁版本更新");
newVersion = `${major}.${minor}.${patch + 1}`;
}
updateAllFiles(newVersion, isBeta);
rl.close();
});
/**
* 更新所有相关文件的版本号
* @param {string} version 新版本号
* @param {boolean} isBeta 是否为Beta版本
*/
function updateAllFiles(version, isBeta = false) {
try {
console.log(`\n正在更新至版本 ${version}...`);
// 1. 更新 package.json
updatePackageJson(version);
// 2. 更新 manifest.json 或 manifest-beta.json
const minAppVersion = updateManifestJson(version, isBeta);
// 3. 更新 versions.json
updateVersionsJson(version, minAppVersion);
// 提示提交更改
console.log("\n版本已更新。建议执行以下命令:");
if (isBeta) {
console.log(
`git add package.json manifest-beta.json versions.json`
);
} else {
console.log(`git add package.json manifest.json versions.json`);
}
console.log(`git commit -m "build: bump version to ${version}"`);
console.log(`git tag ${version}`);
console.log("\n版本更新完成");
} catch (error) {
console.error("更新版本时出错:", error);
process.exit(1);
}
}
/**
* 更新 package.json 文件
* @param {string} version 新版本号
*/
function updatePackageJson(version) {
try {
const packageJson = JSON.parse(readFileSync("package.json", "utf8"));
packageJson.version = version;
writeFileSync(
"package.json",
JSON.stringify(packageJson, null, "\t") + "\n"
);
console.log(`已更新 package.json 版本至 ${version}`);
} catch (error) {
console.error("更新 package.json 时出错:", error);
throw error;
}
}
/**
* 更新 manifest.json manifest-beta.json 文件
* @param {string} version 新版本号
* @param {boolean} isBeta 是否为Beta版本
* @returns {string} 最低应用版本
*/
function updateManifestJson(version, isBeta = false) {
try {
const manifestFile = isBeta ? "manifest-beta.json" : "manifest.json";
// 检查文件是否存在
if (!existsSync(manifestFile) && isBeta) {
// 如果manifest-beta.json不存在则从manifest.json复制一份
if (existsSync("manifest.json")) {
const manifest = JSON.parse(
readFileSync("manifest.json", "utf8")
);
manifest.version = version;
writeFileSync(
manifestFile,
JSON.stringify(manifest, null, "\t") + "\n"
);
console.log(`已创建并更新 ${manifestFile} 版本至 ${version}`);
return manifest.minAppVersion;
}
}
const manifest = JSON.parse(readFileSync(manifestFile, "utf8"));
const { minAppVersion } = manifest;
manifest.version = version;
writeFileSync(
manifestFile,
JSON.stringify(manifest, null, "\t") + "\n"
);
console.log(`已更新 ${manifestFile} 版本至 ${version}`);
return minAppVersion;
} catch (error) {
console.error(`更新 manifest 文件时出错:`, error);
throw error;
}
}
/**
* 更新 versions.json 文件
* @param {string} version 新版本号
* @param {string} minAppVersion 最低应用版本
*/
function updateVersionsJson(version, minAppVersion) {
try {
// 读取或创建 versions.json
let versions = {};
try {
if (existsSync("versions.json")) {
const versionsContent = readFileSync("versions.json", "utf8");
if (versionsContent.trim()) {
versions = JSON.parse(versionsContent);
}
}
} catch (error) {
console.log("创建新的 versions.json 文件");
}
// 更新版本信息
versions[version] = minAppVersion;
writeFileSync(
"versions.json",
JSON.stringify(versions, null, "\t") + "\n"
);
console.log(
`已更新 versions.json添加版本 ${version} -> ${minAppVersion}`
);
} catch (error) {
console.error("更新 versions.json 时出错:", error);
throw error;
}
}

135
src/main.ts Normal file
View file

@ -0,0 +1,135 @@
import { App, Editor, MarkdownView, Modal, Notice, Plugin, PluginSettingTab, Setting } from 'obsidian';
import '../style/styles.css';
// Remember to rename these classes and interfaces!
interface MyPluginSettings {
mySetting: string;
}
const DEFAULT_SETTINGS: MyPluginSettings = {
mySetting: 'default'
}
export default class MyPlugin extends Plugin {
settings: MyPluginSettings;
async onload() {
await this.loadSettings();
// This creates an icon in the left ribbon.
const ribbonIconEl = this.addRibbonIcon('dice', 'Sample Plugin', (evt: MouseEvent) => {
// Called when the user clicks the icon.
new Notice('This is a notice!');
});
// Perform additional things with the ribbon
ribbonIconEl.addClass('my-plugin-ribbon-class');
// This adds a status bar item to the bottom of the app. Does not work on mobile apps.
const statusBarItemEl = this.addStatusBarItem();
statusBarItemEl.setText('Status Bar Text');
// This adds a simple command that can be triggered anywhere
this.addCommand({
id: 'open-sample-modal-simple',
name: 'Open sample modal (simple)',
callback: () => {
new SampleModal(this.app).open();
}
});
// This adds an editor command that can perform some operation on the current editor instance
this.addCommand({
id: 'sample-editor-command',
name: 'Sample editor command',
editorCallback: (editor: Editor, view: MarkdownView) => {
console.log(editor.getSelection());
editor.replaceSelection('Sample Editor Command');
}
});
// This adds a complex command that can check whether the current state of the app allows execution of the command
this.addCommand({
id: 'open-sample-modal-complex',
name: 'Open sample modal (complex)',
checkCallback: (checking: boolean) => {
// Conditions to check
const markdownView = this.app.workspace.getActiveViewOfType(MarkdownView);
if (markdownView) {
// If checking is true, we're simply "checking" if the command can be run.
// If checking is false, then we want to actually perform the operation.
if (!checking) {
new SampleModal(this.app).open();
}
// This command will only show up in Command Palette when the check function returns true
return true;
}
}
});
// This adds a settings tab so the user can configure various aspects of the plugin
this.addSettingTab(new SampleSettingTab(this.app, this));
// If the plugin hooks up any global DOM events (on parts of the app that doesn't belong to this plugin)
// Using this function will automatically remove the event listener when this plugin is disabled.
this.registerDomEvent(document, 'click', (evt: MouseEvent) => {
console.log('click', evt);
});
// When registering intervals, this function will automatically clear the interval when the plugin is disabled.
this.registerInterval(window.setInterval(() => console.log('setInterval'), 5 * 60 * 1000));
}
onunload() {
}
async loadSettings() {
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
}
async saveSettings() {
await this.saveData(this.settings);
}
}
class SampleModal extends Modal {
constructor(app: App) {
super(app);
}
onOpen() {
const {contentEl} = this;
contentEl.setText('Woah!');
}
onClose() {
const {contentEl} = this;
contentEl.empty();
}
}
class SampleSettingTab extends PluginSettingTab {
plugin: MyPlugin;
constructor(app: App, plugin: MyPlugin) {
super(app, plugin);
this.plugin = plugin;
}
display(): void {
const {containerEl} = this;
containerEl.empty();
new Setting(containerEl)
.setName('Setting #1')
.setDesc('It\'s a secret')
.addText(text => text
.setPlaceholder('Enter your secret')
.setValue(this.plugin.settings.mySetting)
.onChange(async (value) => {
this.plugin.settings.mySetting = value;
await this.plugin.saveSettings();
}));
}
}

8
style/styles.css Normal file
View file

@ -0,0 +1,8 @@
/*
This CSS file will be included with your plugin, and
available in the app when your plugin is enabled.
If your plugin does not need CSS, delete this file.
*/

23
tsconfig.json Normal file
View file

@ -0,0 +1,23 @@
{
"compilerOptions": {
"baseUrl": ".",
"inlineSourceMap": true,
"inlineSources": true,
"module": "ESNext",
"target": "ES2017",
"allowJs": true,
"noImplicitAny": false,
"moduleResolution": "node",
"importHelpers": true,
"isolatedModules": true,
"strictNullChecks": true,
"jsx": "react-jsx",
"lib": ["DOM", "ES5", "ES6", "ES2017", "ES2018", "ES2019", "ES2020"],
"paths": {
"@/*": ["./*"]
},
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["node_modules"]
}

3
versions.json Normal file
View file

@ -0,0 +1,3 @@
{
"1.0.0": "1.6.7"
}