mirror of
https://github.com/raven-pensieve/obsidian-ace-code-editor.git
synced 2026-07-22 05:48:56 +00:00
Initial commit
This commit is contained in:
commit
11350fe432
28 changed files with 3812 additions and 0 deletions
10
.editorconfig
Normal file
10
.editorconfig
Normal 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
3
.eslintignore
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
node_modules/
|
||||
|
||||
main.js
|
||||
32
.eslintrc
Normal file
32
.eslintrc
Normal 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
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal 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
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal 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 | 请在这里提出一般性问题
|
||||
25
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
25
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal 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
258
.github/workflows/release.yml
vendored
Normal 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
32
.gitignore
vendored
Normal 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
1
.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
tag-version-prefix=""
|
||||
287
CONTRIBUTING.md
Normal file
287
CONTRIBUTING.md
Normal 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
0
LICENSE
Normal file
19
MAKEFILE
Normal file
19
MAKEFILE
Normal 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
75
README-zh.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
中文 | [English](./README.md)
|
||||
|
||||
# Obsidian 示例插件
|
||||
这是一个用于 Obsidian (https://obsidian.md) 的示例插件。
|
||||
|
||||
该项目使用 Typescript 提供类型检查和文档支持。
|
||||
此仓库依赖于最新的插件 API(obsidian.d.ts),它以 Typescript 定义格式提供,并包含描述其功能的 TSDoc 注释。
|
||||
|
||||
[](https://github.com/RavenHogWarts/obsidian-plugin-starter/stargazers)
|
||||
[](https://github.com/RavenHogWarts/obsidian-plugin-starter/releases)
|
||||
[](https://github.com/RavenHogWarts/obsidian-plugin-starter/blob/master/LICENSE)
|
||||
[](https://github.com/RavenHogWarts/obsidian-plugin-starter/issues)
|
||||
[](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 历史
|
||||
|
||||
[](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
75
README.md
Normal 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.
|
||||
|
||||
[](https://github.com/RavenHogWarts/obsidian-plugin-starter/stargazers)
|
||||
[](https://github.com/RavenHogWarts/obsidian-plugin-starter/releases)
|
||||
[](https://github.com/RavenHogWarts/obsidian-plugin-starter/blob/master/LICENSE)
|
||||
[](https://github.com/RavenHogWarts/obsidian-plugin-starter/issues)
|
||||
[](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
|
||||
|
||||
[](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
13
manifest-beta.json
Normal 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
13
manifest.json
Normal 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
2139
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
51
package.json
Normal file
51
package.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
61
scripts/changelog-option-zh.js
Normal file
61
scripts/changelog-option-zh.js
Normal 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;
|
||||
},
|
||||
},
|
||||
};
|
||||
61
scripts/changelog-option.js
Normal file
61
scripts/changelog-option.js
Normal 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
61
scripts/copy-to-vault.mjs
Normal 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
129
scripts/esbuild.config.mjs
Normal 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
36
scripts/release-tag.mjs
Normal 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
217
scripts/version-bump.mjs
Normal 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
135
src/main.ts
Normal 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
8
style/styles.css
Normal 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
23
tsconfig.json
Normal 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
3
versions.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"1.0.0": "1.6.7"
|
||||
}
|
||||
Loading…
Reference in a new issue