mirror of
https://github.com/insile/OpenWords.git
synced 2026-07-22 05:48:39 +00:00
2025/5/1
This commit is contained in:
parent
fd72256548
commit
f5866b1ba6
17 changed files with 4080 additions and 4 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
|
||||
23
.eslintrc
Normal file
23
.eslintrc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"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",
|
||||
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"no-prototype-builtins": "off",
|
||||
"@typescript-eslint/no-empty-function": "off"
|
||||
}
|
||||
}
|
||||
35
.github/workflows/release.yml
vendored
Normal file
35
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
name: Release Obsidian plugin
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18.x"
|
||||
|
||||
- name: Build plugin
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- name: Create release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
tag="${GITHUB_REF#refs/tags/}"
|
||||
|
||||
gh release create "$tag" \
|
||||
--title="$tag" \
|
||||
--draft \
|
||||
main.js manifest.json styles.css
|
||||
1
.npmrc
Normal file
1
.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
tag-version-prefix=""
|
||||
11
README.md
11
README.md
|
|
@ -1,9 +1,9 @@
|
|||
## OpenWords
|
||||
- 简介
|
||||
- **OpenWords** 是一个用于背单词和单词管理的 [Obsidian](https://obsidian.md/) 简单插件, 使用 SuperMemo 2 间隔重复算法以及 OpenText 单词库. 依赖的第三方包主要是用于重复计算的 [supermemo](https://www.npmjs.com/package/supermemo) 和用于词形还原的 [wink-pos-tagger](https://www.npmjs.com/package/wink-pos-tagger)
|
||||
- 
|
||||
- **OpenWords** 是一个用于背单词和单词管理的 [Obsidian](https://obsidian.md/) 简单插件, 插件入口是左侧工具栏的一个按钮加上两个命令. 使用 SuperMemo 2 间隔重复算法以及 OpenText 单词库. 依赖的第三方包主要是用于重复计算的 [supermemo](https://www.npmjs.com/package/supermemo) 和用于词形还原的 [wink-pos-tagger](https://www.npmjs.com/package/wink-pos-tagger). 本插件完全依赖单词文件及其属性, 没有表格, Json 等外部存储, 启动时会读取所有单词缓存属性, 并在更改时写入相应的单词文件, 没有设计过多的搜索功能, 可以使用内置的属性搜索单词
|
||||
- 
|
||||
- 单词
|
||||
- **单词库**以 [OpenText](opentext.net.cn) 为参考, 是 Obsidian 仓库中的一个文件夹, 其中按首字母分类储存所有单词文件, 单词即为文件名, 元数据使用文件 YAML 属性, 其中复选框和标签用于确定插件运行的作用域, 数字和日期是 SM 2 的计算参数. 本插件完全依赖单词文件及其属性, 没有表格, Json 等外部存储, 启动时会读取所有单词缓存属性, 并在更改时写入相应的单词文件
|
||||
- **单词库**以 [OpenText](opentext.net.cn) 为参考, 是 Obsidian 仓库中的一个文件夹, 其中按首字母分类储存所有单词文件, 单词即为文件名, 元数据使用文件 YAML 属性, 其中复选框和标签用于确定插件运行的作用域, 数字和日期是 SM 2 的计算参数
|
||||
- 复选框: `掌握` , 确定插件作用域, 单词被掌握意味着不会被插件处理
|
||||
- 标签: `级别/小学`, `级别/中考`, `级别/高考四级`, `级别/考研`, `级别/六级`, `级别/雅思`, `级别/托福`, `级别/GRE`, 确定插件作用域, 标签意味着当前主要精力范围, 设置中没有勾选意味着不会被插件处理
|
||||
- 数字: `重复次数`, 连续正确回答的次数, 初始值为 0
|
||||
|
|
@ -26,8 +26,11 @@
|
|||
- 背单词
|
||||
- 新词指重复次数为 0 的单词, 它可能是从未被学习过的, 也可能是前面学后面忘了的. 新词调度中 70% 纯随机, 30% 从易记因子和重复次数最低的 20% 中随机; 旧词指重复次数大于 0 的单词, 它是之前回答正确的. 旧词调度从已过期的单词中 70% 纯随机, 30% 从易记因子和重复次数最低的 20% 中随机. 应该尽可能的提高每个单词的重复次数和易记因子
|
||||
- 
|
||||
- 默写单词
|
||||
- 从作用域中随机抽取单词进行拼写, 目前只是一个练习功能, 不会改变更改单词的属性, 按下 `Tab` 键显示答案
|
||||
- 
|
||||
- 添加双链
|
||||
- 为当前活动页面笔记中的单词添加双链, 单词范围是作用域中易记因子小于等于 2.5 的, 所以默认属性都是添加的. 准确率在 90 %
|
||||
- 为当前活动页面笔记中的单词添加双链, 单词范围是作用域中易记因子小于等于 2.5 的, 所以默认属性都是添加的. 准确率在 90 %. 需要文章尽可能规范, 减少不必要的标点符号. 目前只能通过 `ctrl z` 回撤
|
||||
- 
|
||||
- 重置单词属性
|
||||
- 重置作用域单词的重复次数, 间隔, 易记因子, 到期日为默认值, 重置读写会很慢
|
||||
|
|
|
|||
BIN
README/p7.png
BIN
README/p7.png
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 41 KiB |
BIN
README/p8.gif
Normal file
BIN
README/p8.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 413 KiB |
49
esbuild.config.mjs
Normal file
49
esbuild.config.mjs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import esbuild from "esbuild";
|
||||
import process from "process";
|
||||
import builtins from "builtin-modules";
|
||||
|
||||
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 context = await esbuild.context({
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
entryPoints: ["main.ts"],
|
||||
bundle: true,
|
||||
external: [
|
||||
"obsidian",
|
||||
"electron",
|
||||
"@codemirror/autocomplete",
|
||||
"@codemirror/collab",
|
||||
"@codemirror/commands",
|
||||
"@codemirror/language",
|
||||
"@codemirror/lint",
|
||||
"@codemirror/search",
|
||||
"@codemirror/state",
|
||||
"@codemirror/view",
|
||||
"@lezer/common",
|
||||
"@lezer/highlight",
|
||||
"@lezer/lr",
|
||||
...builtins],
|
||||
format: "cjs",
|
||||
target: "es2018",
|
||||
logLevel: "info",
|
||||
sourcemap: prod ? false : "inline",
|
||||
treeShaking: true,
|
||||
outfile: "main.js",
|
||||
minify: prod,
|
||||
});
|
||||
|
||||
if (prod) {
|
||||
await context.rebuild();
|
||||
process.exit(0);
|
||||
} else {
|
||||
await context.watch();
|
||||
}
|
||||
10
manifest.json
Normal file
10
manifest.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "openwords",
|
||||
"name": "OpenWords",
|
||||
"version": "1.0.0",
|
||||
"minAppVersion": "1.8.10",
|
||||
"description": "用于英语学习中背单词与单词管理的插件",
|
||||
"author": "insile",
|
||||
"authorUrl": "https://opentext.net.cn/",
|
||||
"isDesktopOnly": false
|
||||
}
|
||||
2488
package-lock.json
generated
Normal file
2488
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
35
package.json
Normal file
35
package.json
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "openwords",
|
||||
"version": "1.0.0",
|
||||
"description": "用于英语学习中背单词与单词管理的插件",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
||||
},
|
||||
"keywords": [
|
||||
"Obsidian",
|
||||
"English",
|
||||
"words",
|
||||
"learning"
|
||||
],
|
||||
"author": "insile",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
"@types/wink-pos-tagger": "^2.2.6",
|
||||
"@typescript-eslint/eslint-plugin": "5.29.0",
|
||||
"@typescript-eslint/parser": "5.29.0",
|
||||
"builtin-modules": "3.3.0",
|
||||
"esbuild": "0.17.3",
|
||||
"obsidian": "latest",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"dayjs": "^1.11.13",
|
||||
"supermemo": "^2.0.23",
|
||||
"wink-pos-tagger": "^2.2.2"
|
||||
}
|
||||
}
|
||||
192
styles.css
Normal file
192
styles.css
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
/* 学习模式标题 */
|
||||
.type-title {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 设置 */
|
||||
.openwords-toggle-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr); /* 每行 4 列 */
|
||||
gap: 10px; /* 每个 toggle 之间的间距 */
|
||||
/* margin-top: 10px; */
|
||||
}
|
||||
.openwords-toggle-grid .setting-item:first-child {
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid var(--background-modifier-border)
|
||||
}
|
||||
|
||||
.type-modal{
|
||||
width: 650px; /* 设置模态框宽度 */
|
||||
}
|
||||
/* 卡片容器样式 */
|
||||
.anki-card {
|
||||
width: 500px; /* 固定宽度 */
|
||||
height: 300px; /* 固定高度 */
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 8px;
|
||||
margin: 20px auto;
|
||||
background-color: var(--background-primary);
|
||||
text-align: center;
|
||||
cursor: pointer; /* 鼠标悬停时显示手型 */
|
||||
}
|
||||
.anki-card:hover {
|
||||
background-color: var(--background-modifier-hover); /* 鼠标悬停时背景变浅 */
|
||||
}
|
||||
|
||||
/* 单词内容样式 */
|
||||
.anki-card-content {
|
||||
font-size: 2.5em; /* 设置单词字体大小 */
|
||||
font-weight: bold; /* 设置单词加粗 */
|
||||
color: var(--text-normal); /* 设置单词颜色 */
|
||||
}
|
||||
|
||||
/* Markdown 内容样式 */
|
||||
.anki-markdown-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto; /* 添加垂直滚动条 */
|
||||
background-color: var(--background-secondary); /* 更柔和的背景颜色 */
|
||||
color: var(--text-muted); /* 使用正常文本颜色 */
|
||||
font-size: 1.1em; /* 稍微增大字体 */
|
||||
line-height: 1.6; /* 增加行高,提升可读性 */
|
||||
border-radius: 8px; /* 添加圆角 */
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 添加阴影效果 */
|
||||
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; /* 设置优雅的字体 */
|
||||
user-select: text; /* 允许文本选择 */
|
||||
}
|
||||
|
||||
/* 设置容器样式 */
|
||||
.anki-settings {
|
||||
margin-top: 20px;
|
||||
font-size: 1em; /* 减小字体大小 */
|
||||
}
|
||||
|
||||
.anki-settings .setting-item {
|
||||
padding: 5px 10px; /* 减小内边距 */
|
||||
}
|
||||
|
||||
|
||||
/* 单词列表模态框 */
|
||||
.word-list-modal{
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.word-list-title {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
margin-bottom: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.word-list-filters {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.word-list-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5em;
|
||||
}
|
||||
|
||||
.word-list-filters .setting-item:first-child {
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid var(--background-modifier-border)
|
||||
}
|
||||
|
||||
/* 单词项容器样式 */
|
||||
.word-list-item {
|
||||
display: flex; /* 设置为水平布局 */
|
||||
justify-content: space-between; /* 左右对齐 */
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
position: relative; /* 为预览容器提供定位上下文 */
|
||||
}
|
||||
|
||||
/* Markdown 预览容器样式 */
|
||||
.word-preview-inline {
|
||||
font-size: 1em; /* 设置预览内容字体大小 */
|
||||
line-height: 1.5; /* 设置行高 */
|
||||
overflow-y: auto; /* 添加垂直滚动条 */
|
||||
max-height: 300px; /* 设置最大高度 */
|
||||
position: absolute; /* 设置绝对定位 */
|
||||
top: 100%; /* 显示在单词项的下方 */
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 10; /* 确保预览内容在最上层 */
|
||||
background-color: var(--background-secondary);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
display: none; /* 默认隐藏 */
|
||||
user-select: text; /* 允许文本选择 */
|
||||
}
|
||||
|
||||
/* 鼠标悬停时显示预览内容 */
|
||||
.word-text:hover .word-preview-inline {
|
||||
display: block; /* 鼠标悬停时显示预览内容 */
|
||||
}
|
||||
|
||||
/* 单词文本样式 */
|
||||
.word-text {
|
||||
font-size: 1.1em;
|
||||
color: var(--text-normal);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 默写单词模态框样式 */
|
||||
.spelling-modal {
|
||||
width: auto;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
background-color: var(--background-primary);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.spelling-title {
|
||||
font-size: 1.5em;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.input-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.letter-input {
|
||||
width: 50px !important;
|
||||
height: 50px !important;
|
||||
text-align: center;
|
||||
font-size: 1.5em !important;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 5px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.feedback-container {
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
font-size: 1em;
|
||||
color: var(--text-accent);
|
||||
}
|
||||
24
tsconfig.json
Normal file
24
tsconfig.json
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"module": "ESNext",
|
||||
"target": "ES6",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
}
|
||||
14
version-bump.mjs
Normal file
14
version-bump.mjs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { readFileSync, writeFileSync } from "fs";
|
||||
|
||||
const targetVersion = process.env.npm_package_version;
|
||||
|
||||
// read minAppVersion from manifest.json and bump version to target version
|
||||
let manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
|
||||
const { minAppVersion } = manifest;
|
||||
manifest.version = targetVersion;
|
||||
writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
|
||||
|
||||
// update versions.json with target version and minAppVersion from manifest.json
|
||||
let versions = JSON.parse(readFileSync("versions.json", "utf8"));
|
||||
versions[targetVersion] = minAppVersion;
|
||||
writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));
|
||||
3
versions.json
Normal file
3
versions.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"1.0.0": "1.8.10"
|
||||
}
|
||||
Loading…
Reference in a new issue