@fxri/toolkit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE +9 -0
- package/README.md +101 -0
- package/SPEC.md +100 -0
- package/TRADEMARK.md +47 -0
- package/dist/cli.cjs +20 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +20 -0
- package/dist/index.cjs +19 -0
- package/dist/index.d.cts +55 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +19 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 唐启云
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/NOTICE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# @fxri/toolkit
|
|
2
|
+
|
|
3
|
+
开发工程化工具集:任务管理 + 多语言 CHANGELOG 发布。
|
|
4
|
+
|
|
5
|
+
## ✨ 特性
|
|
6
|
+
|
|
7
|
+
- 📋 **任务管理** - 扫描、总览、按完成时间归档 Markdown 任务文件(语言无关,见 [SPEC.md](./SPEC.md))
|
|
8
|
+
- 🌍 **多语言 CHANGELOG** - 封装 changesets,标题中文化/英文,语言通过 `--lang` 选择,可扩展
|
|
9
|
+
- 🚀 **CLI + 库 API 双形态** - 可命令行使用,也可作为库引入
|
|
10
|
+
|
|
11
|
+
## 📦 安装
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# 项目依赖
|
|
15
|
+
pnpm add -D @fxri/toolkit
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# 全局安装
|
|
20
|
+
pnpm install -g @fxri/toolkit
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 🔧 CLI 命令
|
|
24
|
+
|
|
25
|
+
### 任务管理(tasks)
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx toolkit tasks # 任务总览
|
|
29
|
+
npx toolkit tasks archive # 归档已完成任务
|
|
30
|
+
npx toolkit tasks --dir <path> # 指定任务目录(默认 .tasks)
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### CHANGELOG(changelog)
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx toolkit changelog # 创建变更集(等价 changeset)
|
|
37
|
+
npx toolkit changelog version # 发版 + 格式化(默认中文)
|
|
38
|
+
npx toolkit changelog version --lang en # 指定语言(当前 zh / en)
|
|
39
|
+
npx toolkit changelog format # 仅格式化已有 CHANGELOG
|
|
40
|
+
npx toolkit changelog status / publish # 其余 changeset 子命令透传
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 接入 package.json
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{
|
|
47
|
+
"devDependencies": { "@fxri/toolkit": "^1.0.0" },
|
|
48
|
+
"scripts": {
|
|
49
|
+
"tasks": "toolkit tasks",
|
|
50
|
+
"tasks:archive": "toolkit tasks archive",
|
|
51
|
+
"changeset": "toolkit changelog",
|
|
52
|
+
"version": "toolkit changelog version"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## 📚 库 API
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import {
|
|
61
|
+
listTasks, printTasks, archiveTasks, parseFrontmatter,
|
|
62
|
+
languages, DEFAULT_LANG, localDate, formatChangelogs,
|
|
63
|
+
} from "@fxri/toolkit"
|
|
64
|
+
|
|
65
|
+
// 任务管理
|
|
66
|
+
const tasks = listTasks(".tasks")
|
|
67
|
+
printTasks(".tasks")
|
|
68
|
+
const result = archiveTasks(".tasks")
|
|
69
|
+
|
|
70
|
+
// CHANGELOG 格式化(默认中文)
|
|
71
|
+
formatChangelogs(".", localDate(), languages[DEFAULT_LANG])
|
|
72
|
+
formatChangelogs(".", localDate(), languages.en)
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 语言扩展
|
|
76
|
+
|
|
77
|
+
新增语言只需在 `languages` 里追加一个映射项:
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
export const languages = {
|
|
81
|
+
zh: { replacements: { "### Major Changes": "### 🚨 重大变更", ... }, deps: "- 更新依赖" },
|
|
82
|
+
en: { replacements: {}, deps: "- Updated dependencies" },
|
|
83
|
+
// 未来:ja / ko / ...
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## ⚙️ 环境要求
|
|
88
|
+
|
|
89
|
+
- Node.js >= 20
|
|
90
|
+
|
|
91
|
+
## 📄 版权信息
|
|
92
|
+
|
|
93
|
+
作者:唐启云 <tqy@fxri.net>
|
|
94
|
+
|
|
95
|
+
版权:Copyright © 2026 方弦研究所. All rights reserved.
|
|
96
|
+
|
|
97
|
+
网站:[方弦研究信息网](https://fxri.net:444/)
|
|
98
|
+
|
|
99
|
+
协议:[MIT License](./LICENSE)
|
|
100
|
+
|
|
101
|
+
商标:"方弦™"为第 42 类商标(注册号 89648411),本开源许可不授予商标使用权,详见 [TRADEMARK.md](./TRADEMARK.md)
|
package/SPEC.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# 任务文件规范(SPEC)
|
|
2
|
+
|
|
3
|
+
> 本规范**语言无关**,定义任务文件的目录结构、文件格式与归档规则。任何语言(Node / PHP / Java / Go 等)均可按本规范实现读写;@fxri/toolkit 的 `tasks` 域仅为参考实现。
|
|
4
|
+
|
|
5
|
+
## 1. 目录结构
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
.tasks/
|
|
9
|
+
├── active/ # 实时任务(未完成)
|
|
10
|
+
│ └── {年月}/ # YYYYMM,如 202609
|
|
11
|
+
│ └── {年月日}-{用户名}-{任务简述}.md
|
|
12
|
+
└── archive/ # 任务归档(已完成)
|
|
13
|
+
└── {年月}/
|
|
14
|
+
└── {年月日}.md # 某天归档
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 2. active 任务文件
|
|
18
|
+
|
|
19
|
+
### 2.1 命名
|
|
20
|
+
|
|
21
|
+
`{年月日}-{用户名}-{任务简述}.md`,示例 `20260902-唐启云-忘记密码.md`
|
|
22
|
+
|
|
23
|
+
- `年月日` = 任务创建日,`YYYYMMDD` 直接拼(不加 `-`)
|
|
24
|
+
- `用户名` = git 用户名
|
|
25
|
+
- `任务简述` = 简短中文短语(不加空格)
|
|
26
|
+
|
|
27
|
+
### 2.2 内容
|
|
28
|
+
|
|
29
|
+
文件顶部为 frontmatter(两行 `---` 包裹的 YAML 键值块),随后为正文。
|
|
30
|
+
|
|
31
|
+
```markdown
|
|
32
|
+
---
|
|
33
|
+
owner: 唐启云
|
|
34
|
+
status: 进行中
|
|
35
|
+
created: 20260902
|
|
36
|
+
updated: 20260902
|
|
37
|
+
completed: ''
|
|
38
|
+
depends_on: []
|
|
39
|
+
scope: app
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
# 任务标题
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
| 字段 | 类型 | 说明 |
|
|
46
|
+
| --- | --- | --- |
|
|
47
|
+
| owner | string | 负责人(git 用户名) |
|
|
48
|
+
| status | enum | `待办` / `进行中` / `已完成` / `阻塞` / `已放弃` |
|
|
49
|
+
| created | string | 创建日 `YYYYMMDD` |
|
|
50
|
+
| updated | string | 更新日 `YYYYMMDD` |
|
|
51
|
+
| completed | string | 完成时间 `YYYY-MM-DD HH:mm`,`status` 为 `已完成`/`已放弃` 时必填 |
|
|
52
|
+
| depends_on | array | 依赖的任务文件 |
|
|
53
|
+
| scope | string | 影响范围 |
|
|
54
|
+
|
|
55
|
+
## 3. archive 归档文件
|
|
56
|
+
|
|
57
|
+
### 3.1 命名
|
|
58
|
+
|
|
59
|
+
`{年月日}.md`,按任务**完成时间**的日期(`YYYYMMDD`)划分。
|
|
60
|
+
|
|
61
|
+
### 3.2 内容
|
|
62
|
+
|
|
63
|
+
同一天完成的任务整合进同一文件,**按完成时间升序排序**,任务之间用 `---` 分隔:
|
|
64
|
+
|
|
65
|
+
```markdown
|
|
66
|
+
# 20260902 归档
|
|
67
|
+
|
|
68
|
+
## 20260902-唐启云-忘记密码
|
|
69
|
+
|
|
70
|
+
> 负责人:唐启云 状态:已完成 范围:app 完成时间:2026-09-02 14:30
|
|
71
|
+
|
|
72
|
+
# 忘记密码
|
|
73
|
+
(正文)
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 20260902-唐启云-其他任务
|
|
78
|
+
|
|
79
|
+
> 完成时间:2026-09-02 15:00
|
|
80
|
+
|
|
81
|
+
(正文)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## 4. 归档规则
|
|
85
|
+
|
|
86
|
+
1. 归档触发是**人工 / 事件驱动**,非定时任务。
|
|
87
|
+
2. **任务级归档**:`status ∈ {已完成, 已放弃}` 且带 `completed` 的任务可归档。
|
|
88
|
+
3. `待办` / `进行中` / `阻塞` 均不归档。
|
|
89
|
+
4. 归档文件按 `completed` 的日期(`YYYYMMDD`)划分。
|
|
90
|
+
5. 归档文件内任务按 `completed` 升序排序(`YYYY-MM-DD HH:mm` 字符串排序即时间序)。
|
|
91
|
+
|
|
92
|
+
## 5. 其他语言实现要点
|
|
93
|
+
|
|
94
|
+
按本规范实现时,需覆盖:
|
|
95
|
+
|
|
96
|
+
1. **frontmatter 解析**:读取文件顶部 `---` 之间的 `key: value` 行。
|
|
97
|
+
2. **目录遍历**:`active/` 下仅一层年月子目录,收集 `.md` 文件。
|
|
98
|
+
3. **完成时间提取**:从 frontmatter 的 `completed` 字段读取。
|
|
99
|
+
4. **归档合并**:读取已有归档文件的任务块,与新任务合并后按 `completed` 排序,重写归档文件。
|
|
100
|
+
5. **任务块分隔**:归档文件内任务以 `---` + `## ` 为边界,勿将正文内部的 `## ` 小节误判为任务边界。
|
package/TRADEMARK.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# 商标声明
|
|
2
|
+
|
|
3
|
+
## 基本信息
|
|
4
|
+
|
|
5
|
+
| 项目 | 内容 |
|
|
6
|
+
|---|---|
|
|
7
|
+
| 商标名称 | 方弦™ |
|
|
8
|
+
| 商标类型 | 文字商标 |
|
|
9
|
+
| 商标说明 | 商标由文字"方弦"组成 |
|
|
10
|
+
| 商标类别 | 第 42 类(共 10 项) |
|
|
11
|
+
| 注册号 | 89648411 |
|
|
12
|
+
| 申请人 | 唐启云 |
|
|
13
|
+
| 递交商标局 | 2026-01-12 |
|
|
14
|
+
| 版本 | 基础版 |
|
|
15
|
+
|
|
16
|
+
## 第 42 类服务项目
|
|
17
|
+
|
|
18
|
+
计算机出租;计算机软件设计;为他人研究和开发新产品;计算机软件维护;把有形的数据或文件转换成电子媒体;为他人创建和维护网站;网络服务器出租;提供互联网搜索引擎;托管计算机站(网站);云计算。
|
|
19
|
+
|
|
20
|
+
## 权利状态
|
|
21
|
+
|
|
22
|
+
本商标已向中国国家知识产权局商标局递交注册申请(申请号:89648411,递交日:2026-01-12),**目前尚未核准注册**。
|
|
23
|
+
|
|
24
|
+
在核准注册前,本商标标注为"方弦™",仅用于指明该名称的归属,不构成注册商标声明。
|
|
25
|
+
|
|
26
|
+
## 授权范围
|
|
27
|
+
|
|
28
|
+
本仓库的开源许可证(MIT License)仅授予代码的使用、修改和分发权利,**不构成对任何商标、服务标记或品牌名称的授权许可**。
|
|
29
|
+
|
|
30
|
+
任何派生作品、修改版本、商业产品均不得使用"方弦"名称、Logo 或相关标识,除非获得书面授权。
|
|
31
|
+
|
|
32
|
+
## 使用规范
|
|
33
|
+
|
|
34
|
+
- 在开源社区讨论、文档引用中提及本项目时,可使用"方弦™"指代本项目名称
|
|
35
|
+
- 未经书面授权,不得在任何商业产品、服务或宣传材料中使用"方弦"标识
|
|
36
|
+
|
|
37
|
+
## 获取授权
|
|
38
|
+
|
|
39
|
+
如需将"方弦"商标用于商业用途,请联系:唐启云 <tqy@fxri.net>
|
|
40
|
+
|
|
41
|
+
## 侵权处理
|
|
42
|
+
|
|
43
|
+
如发现未经授权使用"方弦"商标的行为,请通过上述联系方式举报。
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
*本声明随商标审查进度更新。*
|
package/dist/cli.cjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var W=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,g=W();var _=require("module"),B=require("child_process");var j=require("fs"),y=require("path");function v(e){let o=e.match(/^---\r?\n([\s\S]*?)\r?\n---/);if(!o)return{};let n={};for(let t of o[1].split(/\r?\n/)){let s=t.indexOf(":");if(s===-1)continue;let i=t.slice(0,s).trim(),c=t.slice(s+1).trim();i&&(n[i]=c)}return n}function $(e){let o=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);return o?e.slice(o[0].length):e}var u=require("fs"),h=require("path");function T(e){if(!(0,u.existsSync)(e))return[];let o=[];for(let n of(0,u.readdirSync)(e)){let t=(0,h.join)(e,n);if((0,u.statSync)(t).isDirectory())for(let s of(0,u.readdirSync)(t))s.endsWith(".md")&&o.push((0,h.join)(t,s));else n.endsWith(".md")&&o.push(t)}return o}function L(e){let n=(0,h.basename)(e,(0,h.extname)(e)).match(/^(\d{8})/);return n?n[1]:""}function I(e=".tasks"){let o=(0,y.join)(e,"active");return T(o).map(n=>{let t=(0,j.readFileSync)(n,"utf8"),s=v(t),i=t.split(/\r?\n/).find(c=>c.startsWith("# ")&&!c.startsWith("#!"))?.replace(/^#\s*/,"")||(0,y.basename)(n,".md");return{file:n,name:(0,y.basename)(n,".md"),date:L(n),title:i,frontmatter:s,body:$(t).trim()}})}function R(e=".tasks"){let o=I(e);if(o.length===0){console.log("\u5F53\u524D\u65E0\u6D3B\u8DC3\u4EFB\u52A1");return}let n=["\u8FDB\u884C\u4E2D","\u963B\u585E","\u5F85\u529E","\u5DF2\u5B8C\u6210","\u5DF2\u653E\u5F03","\u672A\u6807\u6CE8"],t={};for(let i of o){let c=n.includes(i.frontmatter.status)?i.frontmatter.status:"\u672A\u6807\u6CE8";(t[c]||=[]).push(i)}console.log(`\u4EFB\u52A1\u603B\u89C8\uFF1A
|
|
3
|
+
`);let s=0;for(let i of n){let c=t[i]||[];if(c.length!==0){s+=c.length,console.log(`\u3010${i}\u3011${c.length} \u9879`);for(let r of c)console.log(` ${r.date} ${(r.frontmatter.owner||"\u672A\u6807\u6CE8").padEnd(8)} ${r.title}`);console.log("")}}console.log(`\u5171 ${s} \u4E2A\u4EFB\u52A1\u6587\u4EF6`)}var l=require("fs"),p=require("path");var U=["\u5DF2\u5B8C\u6210","\u5DF2\u653E\u5F03"];function q(e){let o=(0,l.readFileSync)(e,"utf8"),n=[],t=/## (.+?)\n\n> [^\n]*完成时间:([^\n]+)\n\n([\s\S]*?)(?=\n\n---\n\n## |$)/g,s;for(;s=t.exec(o);)n.push({block:s[0].trim(),completed:s[2].trim()});return n}function M(e=".tasks"){let o=(0,p.join)(e,"active"),n=(0,p.join)(e,"archive"),t=T(o);if(t.length===0)return console.log("\u5F53\u524D\u65E0\u6D3B\u8DC3\u4EFB\u52A1\uFF0C\u65E0\u9700\u5F52\u6863"),{archived:0,skipped:[]};let s=[],i=[];for(let r of t){let m=(0,l.readFileSync)(r,"utf8"),f=v(m);if(!U.includes(f.status))continue;let k=f.completed;if(!k){i.push((0,p.basename)(r,".md")),console.log(`\u8DF3\u8FC7 ${(0,p.basename)(r,".md")}\uFF1A\u7F3A\u5C11 completed \u5B8C\u6210\u65F6\u95F4`);continue}s.push({file:r,name:(0,p.basename)(r,".md"),owner:f.owner||"\u672A\u6807\u6CE8",status:f.status||"\u672A\u6807\u6CE8",scope:f.scope||"-",completed:k,body:$(m).trim()})}if(s.length===0)return console.log("\u672C\u6B21\u65E0\u53EF\u5F52\u6863\u4EFB\u52A1"),{archived:0,skipped:i};let c={};for(let r of s){let m=r.completed.replace(/-/g,"").slice(0,8);(c[m]||=[]).push(r)}for(let[r,m]of Object.entries(c)){let f=(0,p.join)(n,r.slice(0,6));(0,l.mkdirSync)(f,{recursive:!0});let k=(0,p.join)(f,`${r}.md`),F=(0,l.existsSync)(k)?q(k):[];F.push(...m.map(a=>({block:`## ${a.name}
|
|
4
|
+
|
|
5
|
+
> \u8D1F\u8D23\u4EBA\uFF1A${a.owner}\u3000\u72B6\u6001\uFF1A${a.status}\u3000\u8303\u56F4\uFF1A${a.scope}\u3000\u5B8C\u6210\u65F6\u95F4\uFF1A${a.completed}
|
|
6
|
+
|
|
7
|
+
${a.body}`,completed:a.completed}))),F.sort((a,P)=>a.completed.localeCompare(P.completed)),(0,l.writeFileSync)(k,`# ${r} \u5F52\u6863
|
|
8
|
+
|
|
9
|
+
> \u672C\u6587\u4EF6\u7531 \`toolkit tasks archive\` \u81EA\u52A8\u751F\u6210\u3002
|
|
10
|
+
|
|
11
|
+
${F.map(a=>a.block).join(`
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
`)}
|
|
16
|
+
`,"utf8");for(let a of m)(0,l.unlinkSync)(a.file);console.log(`\u5DF2\u5F52\u6863 ${m.length} \u4E2A\u4EFB\u52A1 \u2192 ${r}.md`)}return console.log(`\u5171\u5F52\u6863 ${s.length} \u4E2A\u4EFB\u52A1`),{archived:s.length,skipped:i}}var x={zh:{replacements:{"### Major Changes":"### \u{1F6A8} \u91CD\u5927\u53D8\u66F4","### \u91CD\u5927\u53D8\u66F4":"### \u{1F6A8} \u91CD\u5927\u53D8\u66F4","### Minor Changes":"### \u2728 \u65B0\u589E\u529F\u80FD","### \u65B0\u589E\u529F\u80FD":"### \u2728 \u65B0\u589E\u529F\u80FD","### Patch Changes":"### \u{1F41B} \u8865\u4E01\u4FEE\u590D","### \u8865\u4E01\u4FEE\u590D":"### \u{1F41B} \u8865\u4E01\u4FEE\u590D","### Dependent Changes":"### \u{1F517} \u4F9D\u8D56\u53D8\u66F4","### \u4F9D\u8D56\u53D8\u66F4":"### \u{1F517} \u4F9D\u8D56\u53D8\u66F4","- Updated dependencies":"- \u66F4\u65B0\u4F9D\u8D56"},deps:"- \u66F4\u65B0\u4F9D\u8D56"},en:{replacements:{"### Major Changes":"### \u{1F6A8} Major Changes","### Minor Changes":"### \u2728 Minor Changes","### Patch Changes":"### \u{1F41B} Patch Changes","### Dependent Changes":"### \u{1F517} Dependent Changes"},deps:"- Updated dependencies"}},S="zh";var C=require("fs");var E=require("fs"),b=require("path");function N(e){let o=[],n=new Set(["node_modules",".git","dist"]),t=s=>{let i;try{i=(0,E.readdirSync)(s,{withFileTypes:!0})}catch{return}for(let c of i)if(c.isDirectory()){if(n.has(c.name))continue;t((0,b.join)(s,c.name))}else c.name==="CHANGELOG.md"&&o.push((0,b.join)(s,c.name))};return t(e),o}function w(){let e=new Date,o=n=>String(n).padStart(2,"0");return`${e.getFullYear()}-${o(e.getMonth()+1)}-${o(e.getDate())}`}function z(e,o,n){let t=(0,C.readFileSync)(e,"utf8");for(let[r,m]of Object.entries(n.replacements))t=t.replaceAll(r,m);for(;t.includes(`${n.deps}
|
|
17
|
+
${n.deps}`);)t=t.replace(`${n.deps}
|
|
18
|
+
${n.deps}`,n.deps);for(;;){let r=t.replace(/^- (.+)\n- \1$/m,"- $1");if(r===t)break;t=r}let s=t.split(`
|
|
19
|
+
`),i=[];for(let r=0;r<s.length;r++)i.push(s[r]),/^## \d+\.\d+\.\d+/.test(s[r])&&!s[r+1]?.startsWith("> ")&&i.push(`> ${o} \u53D1\u5E03`);let c=i.join(`
|
|
20
|
+
`);return c!==t?((0,C.writeFileSync)(e,c,"utf8"),!0):!1}function A(e,o,n){let t=[];for(let s of N(e))z(s,o,n)&&t.push(s);if(t.length===0)console.log("\u65E0 CHANGELOG \u9700\u8981\u66F4\u65B0");else for(let s of t)console.log(`changelog \u5DF2\u66F4\u65B0\uFF1A${s}`);return t}var H=(0,_.createRequire)(g),Y=H.resolve("@changesets/cli/bin.js"),D=e=>{(0,B.execSync)(`node "${Y}" ${e.join(" ")}`,{stdio:"inherit"})},G=process.argv.slice(2),O=G[0],d=G.slice(1);if(O==="tasks"){let e=d.indexOf("--dir"),o=e>=0&&d[e+1]?d[e+1]:".tasks";(d.find(t=>!t.startsWith("--")&&t!==o)||"list")==="archive"?M(o):R(o)}else if(O==="changelog"){let e=d.indexOf("--lang"),o=e>=0&&d[e+1]?d[e+1]:S,n=d.filter((s,i)=>i!==e&&i!==e+1),t=n[0];t==="version"?(D(["version"]),A(".",w(),x[o]??x[S])):t==="format"?A(".",w(),x[o]??x[S]):D(t?n:[])}else console.log("\u7528\u6CD5\uFF1Atoolkit <tasks|changelog> ..."),console.log(" toolkit tasks \u4EFB\u52A1\u603B\u89C8"),console.log(" toolkit tasks archive \u5F52\u6863\u5DF2\u5B8C\u6210\u4EFB\u52A1"),console.log(" toolkit changelog \u521B\u5EFA\u53D8\u66F4\u96C6"),console.log(" toolkit changelog version \u53D1\u7248 + \u591A\u8BED\u8A00\u683C\u5F0F\u5316"),console.log(" toolkit changelog format \u7EAF\u683C\u5F0F\u5316");
|
package/dist/cli.d.cts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{createRequire as et}from"module";import{execSync as nt}from"child_process";import{readFileSync as q}from"fs";import{join as z,basename as D}from"path";function u(e){let o=e.match(/^---\r?\n([\s\S]*?)\r?\n---/);if(!o)return{};let n={};for(let t of o[1].split(/\r?\n/)){let s=t.indexOf(":");if(s===-1)continue;let i=t.slice(0,s).trim(),c=t.slice(s+1).trim();i&&(n[i]=c)}return n}function k(e){let o=e.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);return o?e.slice(o[0].length):e}import{existsSync as G,readdirSync as b,statSync as U}from"fs";import{join as A,basename as W,extname as P}from"path";function y(e){if(!G(e))return[];let o=[];for(let n of b(e)){let t=A(e,n);if(U(t).isDirectory())for(let s of b(t))s.endsWith(".md")&&o.push(A(t,s));else n.endsWith(".md")&&o.push(t)}return o}function w(e){let n=W(e,P(e)).match(/^(\d{8})/);return n?n[1]:""}function H(e=".tasks"){let o=z(e,"active");return y(o).map(n=>{let t=q(n,"utf8"),s=u(t),i=t.split(/\r?\n/).find(c=>c.startsWith("# ")&&!c.startsWith("#!"))?.replace(/^#\s*/,"")||D(n,".md");return{file:n,name:D(n,".md"),date:w(n),title:i,frontmatter:s,body:k(t).trim()}})}function j(e=".tasks"){let o=H(e);if(o.length===0){console.log("\u5F53\u524D\u65E0\u6D3B\u8DC3\u4EFB\u52A1");return}let n=["\u8FDB\u884C\u4E2D","\u963B\u585E","\u5F85\u529E","\u5DF2\u5B8C\u6210","\u5DF2\u653E\u5F03","\u672A\u6807\u6CE8"],t={};for(let i of o){let c=n.includes(i.frontmatter.status)?i.frontmatter.status:"\u672A\u6807\u6CE8";(t[c]||=[]).push(i)}console.log(`\u4EFB\u52A1\u603B\u89C8\uFF1A
|
|
3
|
+
`);let s=0;for(let i of n){let c=t[i]||[];if(c.length!==0){s+=c.length,console.log(`\u3010${i}\u3011${c.length} \u9879`);for(let r of c)console.log(` ${r.date} ${(r.frontmatter.owner||"\u672A\u6807\u6CE8").padEnd(8)} ${r.title}`);console.log("")}}console.log(`\u5171 ${s} \u4E2A\u4EFB\u52A1\u6587\u4EF6`)}import{readFileSync as E,writeFileSync as I,mkdirSync as Y,unlinkSync as J,existsSync as K}from"fs";import{join as v,basename as T}from"path";var L=["\u5DF2\u5B8C\u6210","\u5DF2\u653E\u5F03"];function Q(e){let o=E(e,"utf8"),n=[],t=/## (.+?)\n\n> [^\n]*完成时间:([^\n]+)\n\n([\s\S]*?)(?=\n\n---\n\n## |$)/g,s;for(;s=t.exec(o);)n.push({block:s[0].trim(),completed:s[2].trim()});return n}function M(e=".tasks"){let o=v(e,"active"),n=v(e,"archive"),t=y(o);if(t.length===0)return console.log("\u5F53\u524D\u65E0\u6D3B\u8DC3\u4EFB\u52A1\uFF0C\u65E0\u9700\u5F52\u6863"),{archived:0,skipped:[]};let s=[],i=[];for(let r of t){let l=E(r,"utf8"),g=u(l);if(!L.includes(g.status))continue;let d=g.completed;if(!d){i.push(T(r,".md")),console.log(`\u8DF3\u8FC7 ${T(r,".md")}\uFF1A\u7F3A\u5C11 completed \u5B8C\u6210\u65F6\u95F4`);continue}s.push({file:r,name:T(r,".md"),owner:g.owner||"\u672A\u6807\u6CE8",status:g.status||"\u672A\u6807\u6CE8",scope:g.scope||"-",completed:d,body:k(l).trim()})}if(s.length===0)return console.log("\u672C\u6B21\u65E0\u53EF\u5F52\u6863\u4EFB\u52A1"),{archived:0,skipped:i};let c={};for(let r of s){let l=r.completed.replace(/-/g,"").slice(0,8);(c[l]||=[]).push(r)}for(let[r,l]of Object.entries(c)){let g=v(n,r.slice(0,6));Y(g,{recursive:!0});let d=v(g,`${r}.md`),$=K(d)?Q(d):[];$.push(...l.map(a=>({block:`## ${a.name}
|
|
4
|
+
|
|
5
|
+
> \u8D1F\u8D23\u4EBA\uFF1A${a.owner}\u3000\u72B6\u6001\uFF1A${a.status}\u3000\u8303\u56F4\uFF1A${a.scope}\u3000\u5B8C\u6210\u65F6\u95F4\uFF1A${a.completed}
|
|
6
|
+
|
|
7
|
+
${a.body}`,completed:a.completed}))),$.sort((a,B)=>a.completed.localeCompare(B.completed)),I(d,`# ${r} \u5F52\u6863
|
|
8
|
+
|
|
9
|
+
> \u672C\u6587\u4EF6\u7531 \`toolkit tasks archive\` \u81EA\u52A8\u751F\u6210\u3002
|
|
10
|
+
|
|
11
|
+
${$.map(a=>a.block).join(`
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
`)}
|
|
16
|
+
`,"utf8");for(let a of l)J(a.file);console.log(`\u5DF2\u5F52\u6863 ${l.length} \u4E2A\u4EFB\u52A1 \u2192 ${r}.md`)}return console.log(`\u5171\u5F52\u6863 ${s.length} \u4E2A\u4EFB\u52A1`),{archived:s.length,skipped:i}}var h={zh:{replacements:{"### Major Changes":"### \u{1F6A8} \u91CD\u5927\u53D8\u66F4","### \u91CD\u5927\u53D8\u66F4":"### \u{1F6A8} \u91CD\u5927\u53D8\u66F4","### Minor Changes":"### \u2728 \u65B0\u589E\u529F\u80FD","### \u65B0\u589E\u529F\u80FD":"### \u2728 \u65B0\u589E\u529F\u80FD","### Patch Changes":"### \u{1F41B} \u8865\u4E01\u4FEE\u590D","### \u8865\u4E01\u4FEE\u590D":"### \u{1F41B} \u8865\u4E01\u4FEE\u590D","### Dependent Changes":"### \u{1F517} \u4F9D\u8D56\u53D8\u66F4","### \u4F9D\u8D56\u53D8\u66F4":"### \u{1F517} \u4F9D\u8D56\u53D8\u66F4","- Updated dependencies":"- \u66F4\u65B0\u4F9D\u8D56"},deps:"- \u66F4\u65B0\u4F9D\u8D56"},en:{replacements:{"### Major Changes":"### \u{1F6A8} Major Changes","### Minor Changes":"### \u2728 Minor Changes","### Patch Changes":"### \u{1F41B} Patch Changes","### Dependent Changes":"### \u{1F517} Dependent Changes"},deps:"- Updated dependencies"}},x="zh";import{readFileSync as X,writeFileSync as Z}from"fs";import{readdirSync as V}from"fs";import{join as O}from"path";function R(e){let o=[],n=new Set(["node_modules",".git","dist"]),t=s=>{let i;try{i=V(s,{withFileTypes:!0})}catch{return}for(let c of i)if(c.isDirectory()){if(n.has(c.name))continue;t(O(s,c.name))}else c.name==="CHANGELOG.md"&&o.push(O(s,c.name))};return t(e),o}function F(){let e=new Date,o=n=>String(n).padStart(2,"0");return`${e.getFullYear()}-${o(e.getMonth()+1)}-${o(e.getDate())}`}function tt(e,o,n){let t=X(e,"utf8");for(let[r,l]of Object.entries(n.replacements))t=t.replaceAll(r,l);for(;t.includes(`${n.deps}
|
|
17
|
+
${n.deps}`);)t=t.replace(`${n.deps}
|
|
18
|
+
${n.deps}`,n.deps);for(;;){let r=t.replace(/^- (.+)\n- \1$/m,"- $1");if(r===t)break;t=r}let s=t.split(`
|
|
19
|
+
`),i=[];for(let r=0;r<s.length;r++)i.push(s[r]),/^## \d+\.\d+\.\d+/.test(s[r])&&!s[r+1]?.startsWith("> ")&&i.push(`> ${o} \u53D1\u5E03`);let c=i.join(`
|
|
20
|
+
`);return c!==t?(Z(e,c,"utf8"),!0):!1}function S(e,o,n){let t=[];for(let s of R(e))tt(s,o,n)&&t.push(s);if(t.length===0)console.log("\u65E0 CHANGELOG \u9700\u8981\u66F4\u65B0");else for(let s of t)console.log(`changelog \u5DF2\u66F4\u65B0\uFF1A${s}`);return t}var ot=et(import.meta.url),st=ot.resolve("@changesets/cli/bin.js"),C=e=>{nt(`node "${st}" ${e.join(" ")}`,{stdio:"inherit"})},_=process.argv.slice(2),N=_[0],f=_.slice(1);if(N==="tasks"){let e=f.indexOf("--dir"),o=e>=0&&f[e+1]?f[e+1]:".tasks";(f.find(t=>!t.startsWith("--")&&t!==o)||"list")==="archive"?M(o):j(o)}else if(N==="changelog"){let e=f.indexOf("--lang"),o=e>=0&&f[e+1]?f[e+1]:x,n=f.filter((s,i)=>i!==e&&i!==e+1),t=n[0];t==="version"?(C(["version"]),S(".",F(),h[o]??h[x])):t==="format"?S(".",F(),h[o]??h[x]):C(t?n:[])}else console.log("\u7528\u6CD5\uFF1Atoolkit <tasks|changelog> ..."),console.log(" toolkit tasks \u4EFB\u52A1\u603B\u89C8"),console.log(" toolkit tasks archive \u5F52\u6863\u5DF2\u5B8C\u6210\u4EFB\u52A1"),console.log(" toolkit changelog \u521B\u5EFA\u53D8\u66F4\u96C6"),console.log(" toolkit changelog version \u53D1\u7248 + \u591A\u8BED\u8A00\u683C\u5F0F\u5316"),console.log(" toolkit changelog format \u7EAF\u683C\u5F0F\u5316");
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
var S=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var W=(n,o)=>{for(var r in o)S(n,r,{get:o[r],enumerable:!0})},_=(n,o,r,t)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of P(o))!U.call(n,e)&&e!==r&&S(n,e,{get:()=>o[e],enumerable:!(t=G(o,e))||t.enumerable});return n};var z=n=>_(S({},"__esModule",{value:!0}),n);var q={};W(q,{DEFAULT_LANG:()=>Y,DONE_STATUSES:()=>b,archiveTasks:()=>E,collectChangelogs:()=>$,dateFromFileName:()=>F,formatChangelog:()=>j,formatChangelogs:()=>O,languages:()=>H,listTaskFiles:()=>y,listTasks:()=>A,localDate:()=>R,parseArchiveTasks:()=>w,parseFrontmatter:()=>k,printTasks:()=>M,stripFrontmatter:()=>x});module.exports=z(q);var b=["\u5DF2\u5B8C\u6210","\u5DF2\u653E\u5F03"];function k(n){let o=n.match(/^---\r?\n([\s\S]*?)\r?\n---/);if(!o)return{};let r={};for(let t of o[1].split(/\r?\n/)){let e=t.indexOf(":");if(e===-1)continue;let a=t.slice(0,e).trim(),i=t.slice(e+1).trim();a&&(r[a]=i)}return r}function x(n){let o=n.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);return o?n.slice(o[0].length):n}var d=require("fs"),u=require("path");function y(n){if(!(0,d.existsSync)(n))return[];let o=[];for(let r of(0,d.readdirSync)(n)){let t=(0,u.join)(n,r);if((0,d.statSync)(t).isDirectory())for(let e of(0,d.readdirSync)(t))e.endsWith(".md")&&o.push((0,u.join)(t,e));else r.endsWith(".md")&&o.push(t)}return o}function F(n){let r=(0,u.basename)(n,(0,u.extname)(n)).match(/^(\d{8})/);return r?r[1]:""}var L=require("fs"),T=require("path");function A(n=".tasks"){let o=(0,T.join)(n,"active");return y(o).map(r=>{let t=(0,L.readFileSync)(r,"utf8"),e=k(t),a=t.split(/\r?\n/).find(i=>i.startsWith("# ")&&!i.startsWith("#!"))?.replace(/^#\s*/,"")||(0,T.basename)(r,".md");return{file:r,name:(0,T.basename)(r,".md"),date:F(r),title:a,frontmatter:e,body:x(t).trim()}})}function M(n=".tasks"){let o=A(n);if(o.length===0){console.log("\u5F53\u524D\u65E0\u6D3B\u8DC3\u4EFB\u52A1");return}let r=["\u8FDB\u884C\u4E2D","\u963B\u585E","\u5F85\u529E","\u5DF2\u5B8C\u6210","\u5DF2\u653E\u5F03","\u672A\u6807\u6CE8"],t={};for(let a of o){let i=r.includes(a.frontmatter.status)?a.frontmatter.status:"\u672A\u6807\u6CE8";(t[i]||=[]).push(a)}console.log(`\u4EFB\u52A1\u603B\u89C8\uFF1A
|
|
2
|
+
`);let e=0;for(let a of r){let i=t[a]||[];if(i.length!==0){e+=i.length,console.log(`\u3010${a}\u3011${i.length} \u9879`);for(let s of i)console.log(` ${s.date} ${(s.frontmatter.owner||"\u672A\u6807\u6CE8").padEnd(8)} ${s.title}`);console.log("")}}console.log(`\u5171 ${e} \u4E2A\u4EFB\u52A1\u6587\u4EF6`)}var l=require("fs"),m=require("path");function w(n){let o=(0,l.readFileSync)(n,"utf8"),r=[],t=/## (.+?)\n\n> [^\n]*完成时间:([^\n]+)\n\n([\s\S]*?)(?=\n\n---\n\n## |$)/g,e;for(;e=t.exec(o);)r.push({block:e[0].trim(),completed:e[2].trim()});return r}function E(n=".tasks"){let o=(0,m.join)(n,"active"),r=(0,m.join)(n,"archive"),t=y(o);if(t.length===0)return console.log("\u5F53\u524D\u65E0\u6D3B\u8DC3\u4EFB\u52A1\uFF0C\u65E0\u9700\u5F52\u6863"),{archived:0,skipped:[]};let e=[],a=[];for(let s of t){let p=(0,l.readFileSync)(s,"utf8"),g=k(p);if(!b.includes(g.status))continue;let h=g.completed;if(!h){a.push((0,m.basename)(s,".md")),console.log(`\u8DF3\u8FC7 ${(0,m.basename)(s,".md")}\uFF1A\u7F3A\u5C11 completed \u5B8C\u6210\u65F6\u95F4`);continue}e.push({file:s,name:(0,m.basename)(s,".md"),owner:g.owner||"\u672A\u6807\u6CE8",status:g.status||"\u672A\u6807\u6CE8",scope:g.scope||"-",completed:h,body:x(p).trim()})}if(e.length===0)return console.log("\u672C\u6B21\u65E0\u53EF\u5F52\u6863\u4EFB\u52A1"),{archived:0,skipped:a};let i={};for(let s of e){let p=s.completed.replace(/-/g,"").slice(0,8);(i[p]||=[]).push(s)}for(let[s,p]of Object.entries(i)){let g=(0,m.join)(r,s.slice(0,6));(0,l.mkdirSync)(g,{recursive:!0});let h=(0,m.join)(g,`${s}.md`),C=(0,l.existsSync)(h)?w(h):[];C.push(...p.map(c=>({block:`## ${c.name}
|
|
3
|
+
|
|
4
|
+
> \u8D1F\u8D23\u4EBA\uFF1A${c.owner}\u3000\u72B6\u6001\uFF1A${c.status}\u3000\u8303\u56F4\uFF1A${c.scope}\u3000\u5B8C\u6210\u65F6\u95F4\uFF1A${c.completed}
|
|
5
|
+
|
|
6
|
+
${c.body}`,completed:c.completed}))),C.sort((c,B)=>c.completed.localeCompare(B.completed)),(0,l.writeFileSync)(h,`# ${s} \u5F52\u6863
|
|
7
|
+
|
|
8
|
+
> \u672C\u6587\u4EF6\u7531 \`toolkit tasks archive\` \u81EA\u52A8\u751F\u6210\u3002
|
|
9
|
+
|
|
10
|
+
${C.map(c=>c.block).join(`
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
`)}
|
|
15
|
+
`,"utf8");for(let c of p)(0,l.unlinkSync)(c.file);console.log(`\u5DF2\u5F52\u6863 ${p.length} \u4E2A\u4EFB\u52A1 \u2192 ${s}.md`)}return console.log(`\u5171\u5F52\u6863 ${e.length} \u4E2A\u4EFB\u52A1`),{archived:e.length,skipped:a}}var H={zh:{replacements:{"### Major Changes":"### \u{1F6A8} \u91CD\u5927\u53D8\u66F4","### \u91CD\u5927\u53D8\u66F4":"### \u{1F6A8} \u91CD\u5927\u53D8\u66F4","### Minor Changes":"### \u2728 \u65B0\u589E\u529F\u80FD","### \u65B0\u589E\u529F\u80FD":"### \u2728 \u65B0\u589E\u529F\u80FD","### Patch Changes":"### \u{1F41B} \u8865\u4E01\u4FEE\u590D","### \u8865\u4E01\u4FEE\u590D":"### \u{1F41B} \u8865\u4E01\u4FEE\u590D","### Dependent Changes":"### \u{1F517} \u4F9D\u8D56\u53D8\u66F4","### \u4F9D\u8D56\u53D8\u66F4":"### \u{1F517} \u4F9D\u8D56\u53D8\u66F4","- Updated dependencies":"- \u66F4\u65B0\u4F9D\u8D56"},deps:"- \u66F4\u65B0\u4F9D\u8D56"},en:{replacements:{"### Major Changes":"### \u{1F6A8} Major Changes","### Minor Changes":"### \u2728 Minor Changes","### Patch Changes":"### \u{1F41B} Patch Changes","### Dependent Changes":"### \u{1F517} Dependent Changes"},deps:"- Updated dependencies"}},Y="zh";var N=require("fs"),D=require("path");function $(n){let o=[],r=new Set(["node_modules",".git","dist"]),t=e=>{let a;try{a=(0,N.readdirSync)(e,{withFileTypes:!0})}catch{return}for(let i of a)if(i.isDirectory()){if(r.has(i.name))continue;t((0,D.join)(e,i.name))}else i.name==="CHANGELOG.md"&&o.push((0,D.join)(e,i.name))};return t(n),o}var v=require("fs");function R(){let n=new Date,o=r=>String(r).padStart(2,"0");return`${n.getFullYear()}-${o(n.getMonth()+1)}-${o(n.getDate())}`}function j(n,o,r){let t=(0,v.readFileSync)(n,"utf8");for(let[s,p]of Object.entries(r.replacements))t=t.replaceAll(s,p);for(;t.includes(`${r.deps}
|
|
16
|
+
${r.deps}`);)t=t.replace(`${r.deps}
|
|
17
|
+
${r.deps}`,r.deps);for(;;){let s=t.replace(/^- (.+)\n- \1$/m,"- $1");if(s===t)break;t=s}let e=t.split(`
|
|
18
|
+
`),a=[];for(let s=0;s<e.length;s++)a.push(e[s]),/^## \d+\.\d+\.\d+/.test(e[s])&&!e[s+1]?.startsWith("> ")&&a.push(`> ${o} \u53D1\u5E03`);let i=a.join(`
|
|
19
|
+
`);return i!==t?((0,v.writeFileSync)(n,i,"utf8"),!0):!1}function O(n,o,r){let t=[];for(let e of $(n))j(e,o,r)&&t.push(e);if(t.length===0)console.log("\u65E0 CHANGELOG \u9700\u8981\u66F4\u65B0");else for(let e of t)console.log(`changelog \u5DF2\u66F4\u65B0\uFF1A${e}`);return t}0&&(module.exports={DEFAULT_LANG,DONE_STATUSES,archiveTasks,collectChangelogs,dateFromFileName,formatChangelog,formatChangelogs,languages,listTaskFiles,listTasks,localDate,parseArchiveTasks,parseFrontmatter,printTasks,stripFrontmatter});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
type TaskStatus = "待办" | "进行中" | "已完成" | "阻塞" | "已放弃";
|
|
2
|
+
declare const DONE_STATUSES: TaskStatus[];
|
|
3
|
+
interface TaskFrontmatter {
|
|
4
|
+
owner: string;
|
|
5
|
+
status: TaskStatus;
|
|
6
|
+
created: string;
|
|
7
|
+
updated: string;
|
|
8
|
+
completed: string;
|
|
9
|
+
depends_on: string[];
|
|
10
|
+
scope: string;
|
|
11
|
+
}
|
|
12
|
+
interface Task {
|
|
13
|
+
file: string;
|
|
14
|
+
name: string;
|
|
15
|
+
date: string;
|
|
16
|
+
title: string;
|
|
17
|
+
frontmatter: TaskFrontmatter;
|
|
18
|
+
body: string;
|
|
19
|
+
}
|
|
20
|
+
interface ArchiveBlock {
|
|
21
|
+
block: string;
|
|
22
|
+
completed: string;
|
|
23
|
+
}
|
|
24
|
+
interface ArchiveResult {
|
|
25
|
+
archived: number;
|
|
26
|
+
skipped: string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
declare function parseFrontmatter(content: string): Partial<TaskFrontmatter>;
|
|
30
|
+
declare function stripFrontmatter(content: string): string;
|
|
31
|
+
|
|
32
|
+
declare function listTaskFiles(dir: string): string[];
|
|
33
|
+
declare function dateFromFileName(file: string): string;
|
|
34
|
+
|
|
35
|
+
declare function listTasks(tasksDir?: string): Task[];
|
|
36
|
+
declare function printTasks(tasksDir?: string): void;
|
|
37
|
+
|
|
38
|
+
declare function parseArchiveTasks(file: string): ArchiveBlock[];
|
|
39
|
+
declare function archiveTasks(tasksDir?: string): ArchiveResult;
|
|
40
|
+
|
|
41
|
+
type LanguageMap = Record<string, string>;
|
|
42
|
+
interface ChangelogLanguage {
|
|
43
|
+
replacements: LanguageMap;
|
|
44
|
+
deps: string;
|
|
45
|
+
}
|
|
46
|
+
declare const languages: Record<string, ChangelogLanguage>;
|
|
47
|
+
declare const DEFAULT_LANG = "zh";
|
|
48
|
+
|
|
49
|
+
declare function collectChangelogs(dir: string): string[];
|
|
50
|
+
|
|
51
|
+
declare function localDate(): string;
|
|
52
|
+
declare function formatChangelog(file: string, today: string, lang: ChangelogLanguage): boolean;
|
|
53
|
+
declare function formatChangelogs(dir: string, today: string, lang: ChangelogLanguage): string[];
|
|
54
|
+
|
|
55
|
+
export { type ArchiveBlock, type ArchiveResult, type ChangelogLanguage, DEFAULT_LANG, DONE_STATUSES, type LanguageMap, type Task, type TaskFrontmatter, type TaskStatus, archiveTasks, collectChangelogs, dateFromFileName, formatChangelog, formatChangelogs, languages, listTaskFiles, listTasks, localDate, parseArchiveTasks, parseFrontmatter, printTasks, stripFrontmatter };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
type TaskStatus = "待办" | "进行中" | "已完成" | "阻塞" | "已放弃";
|
|
2
|
+
declare const DONE_STATUSES: TaskStatus[];
|
|
3
|
+
interface TaskFrontmatter {
|
|
4
|
+
owner: string;
|
|
5
|
+
status: TaskStatus;
|
|
6
|
+
created: string;
|
|
7
|
+
updated: string;
|
|
8
|
+
completed: string;
|
|
9
|
+
depends_on: string[];
|
|
10
|
+
scope: string;
|
|
11
|
+
}
|
|
12
|
+
interface Task {
|
|
13
|
+
file: string;
|
|
14
|
+
name: string;
|
|
15
|
+
date: string;
|
|
16
|
+
title: string;
|
|
17
|
+
frontmatter: TaskFrontmatter;
|
|
18
|
+
body: string;
|
|
19
|
+
}
|
|
20
|
+
interface ArchiveBlock {
|
|
21
|
+
block: string;
|
|
22
|
+
completed: string;
|
|
23
|
+
}
|
|
24
|
+
interface ArchiveResult {
|
|
25
|
+
archived: number;
|
|
26
|
+
skipped: string[];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
declare function parseFrontmatter(content: string): Partial<TaskFrontmatter>;
|
|
30
|
+
declare function stripFrontmatter(content: string): string;
|
|
31
|
+
|
|
32
|
+
declare function listTaskFiles(dir: string): string[];
|
|
33
|
+
declare function dateFromFileName(file: string): string;
|
|
34
|
+
|
|
35
|
+
declare function listTasks(tasksDir?: string): Task[];
|
|
36
|
+
declare function printTasks(tasksDir?: string): void;
|
|
37
|
+
|
|
38
|
+
declare function parseArchiveTasks(file: string): ArchiveBlock[];
|
|
39
|
+
declare function archiveTasks(tasksDir?: string): ArchiveResult;
|
|
40
|
+
|
|
41
|
+
type LanguageMap = Record<string, string>;
|
|
42
|
+
interface ChangelogLanguage {
|
|
43
|
+
replacements: LanguageMap;
|
|
44
|
+
deps: string;
|
|
45
|
+
}
|
|
46
|
+
declare const languages: Record<string, ChangelogLanguage>;
|
|
47
|
+
declare const DEFAULT_LANG = "zh";
|
|
48
|
+
|
|
49
|
+
declare function collectChangelogs(dir: string): string[];
|
|
50
|
+
|
|
51
|
+
declare function localDate(): string;
|
|
52
|
+
declare function formatChangelog(file: string, today: string, lang: ChangelogLanguage): boolean;
|
|
53
|
+
declare function formatChangelogs(dir: string, today: string, lang: ChangelogLanguage): string[];
|
|
54
|
+
|
|
55
|
+
export { type ArchiveBlock, type ArchiveResult, type ChangelogLanguage, DEFAULT_LANG, DONE_STATUSES, type LanguageMap, type Task, type TaskFrontmatter, type TaskStatus, archiveTasks, collectChangelogs, dateFromFileName, formatChangelog, formatChangelogs, languages, listTaskFiles, listTasks, localDate, parseArchiveTasks, parseFrontmatter, printTasks, stripFrontmatter };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
var $=["\u5DF2\u5B8C\u6210","\u5DF2\u653E\u5F03"];function d(r){let o=r.match(/^---\r?\n([\s\S]*?)\r?\n---/);if(!o)return{};let e={};for(let t of o[1].split(/\r?\n/)){let n=t.indexOf(":");if(n===-1)continue;let a=t.slice(0,n).trim(),i=t.slice(n+1).trim();a&&(e[a]=i)}return e}function u(r){let o=r.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/);return o?r.slice(o[0].length):r}import{existsSync as M,readdirSync as v,statSync as E}from"fs";import{join as C,basename as N,extname as R}from"path";function h(r){if(!M(r))return[];let o=[];for(let e of v(r)){let t=C(r,e);if(E(t).isDirectory())for(let n of v(t))n.endsWith(".md")&&o.push(C(t,n));else e.endsWith(".md")&&o.push(t)}return o}function y(r){let e=N(r,R(r)).match(/^(\d{8})/);return e?e[1]:""}import{readFileSync as O}from"fs";import{join as B,basename as S}from"path";function b(r=".tasks"){let o=B(r,"active");return h(o).map(e=>{let t=O(e,"utf8"),n=d(t),a=t.split(/\r?\n/).find(i=>i.startsWith("# ")&&!i.startsWith("#!"))?.replace(/^#\s*/,"")||S(e,".md");return{file:e,name:S(e,".md"),date:y(e),title:a,frontmatter:n,body:u(t).trim()}})}function G(r=".tasks"){let o=b(r);if(o.length===0){console.log("\u5F53\u524D\u65E0\u6D3B\u8DC3\u4EFB\u52A1");return}let e=["\u8FDB\u884C\u4E2D","\u963B\u585E","\u5F85\u529E","\u5DF2\u5B8C\u6210","\u5DF2\u653E\u5F03","\u672A\u6807\u6CE8"],t={};for(let a of o){let i=e.includes(a.frontmatter.status)?a.frontmatter.status:"\u672A\u6807\u6CE8";(t[i]||=[]).push(a)}console.log(`\u4EFB\u52A1\u603B\u89C8\uFF1A
|
|
2
|
+
`);let n=0;for(let a of e){let i=t[a]||[];if(i.length!==0){n+=i.length,console.log(`\u3010${a}\u3011${i.length} \u9879`);for(let s of i)console.log(` ${s.date} ${(s.frontmatter.owner||"\u672A\u6807\u6CE8").padEnd(8)} ${s.title}`);console.log("")}}console.log(`\u5171 ${n} \u4E2A\u4EFB\u52A1\u6587\u4EF6`)}import{readFileSync as A,writeFileSync as P,mkdirSync as U,unlinkSync as W,existsSync as _}from"fs";import{join as k,basename as T}from"path";function w(r){let o=A(r,"utf8"),e=[],t=/## (.+?)\n\n> [^\n]*完成时间:([^\n]+)\n\n([\s\S]*?)(?=\n\n---\n\n## |$)/g,n;for(;n=t.exec(o);)e.push({block:n[0].trim(),completed:n[2].trim()});return e}function z(r=".tasks"){let o=k(r,"active"),e=k(r,"archive"),t=h(o);if(t.length===0)return console.log("\u5F53\u524D\u65E0\u6D3B\u8DC3\u4EFB\u52A1\uFF0C\u65E0\u9700\u5F52\u6863"),{archived:0,skipped:[]};let n=[],a=[];for(let s of t){let l=A(s,"utf8"),p=d(l);if(!$.includes(p.status))continue;let f=p.completed;if(!f){a.push(T(s,".md")),console.log(`\u8DF3\u8FC7 ${T(s,".md")}\uFF1A\u7F3A\u5C11 completed \u5B8C\u6210\u65F6\u95F4`);continue}n.push({file:s,name:T(s,".md"),owner:p.owner||"\u672A\u6807\u6CE8",status:p.status||"\u672A\u6807\u6CE8",scope:p.scope||"-",completed:f,body:u(l).trim()})}if(n.length===0)return console.log("\u672C\u6B21\u65E0\u53EF\u5F52\u6863\u4EFB\u52A1"),{archived:0,skipped:a};let i={};for(let s of n){let l=s.completed.replace(/-/g,"").slice(0,8);(i[l]||=[]).push(s)}for(let[s,l]of Object.entries(i)){let p=k(e,s.slice(0,6));U(p,{recursive:!0});let f=k(p,`${s}.md`),x=_(f)?w(f):[];x.push(...l.map(c=>({block:`## ${c.name}
|
|
3
|
+
|
|
4
|
+
> \u8D1F\u8D23\u4EBA\uFF1A${c.owner}\u3000\u72B6\u6001\uFF1A${c.status}\u3000\u8303\u56F4\uFF1A${c.scope}\u3000\u5B8C\u6210\u65F6\u95F4\uFF1A${c.completed}
|
|
5
|
+
|
|
6
|
+
${c.body}`,completed:c.completed}))),x.sort((c,L)=>c.completed.localeCompare(L.completed)),P(f,`# ${s} \u5F52\u6863
|
|
7
|
+
|
|
8
|
+
> \u672C\u6587\u4EF6\u7531 \`toolkit tasks archive\` \u81EA\u52A8\u751F\u6210\u3002
|
|
9
|
+
|
|
10
|
+
${x.map(c=>c.block).join(`
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
`)}
|
|
15
|
+
`,"utf8");for(let c of l)W(c.file);console.log(`\u5DF2\u5F52\u6863 ${l.length} \u4E2A\u4EFB\u52A1 \u2192 ${s}.md`)}return console.log(`\u5171\u5F52\u6863 ${n.length} \u4E2A\u4EFB\u52A1`),{archived:n.length,skipped:a}}var ht={zh:{replacements:{"### Major Changes":"### \u{1F6A8} \u91CD\u5927\u53D8\u66F4","### \u91CD\u5927\u53D8\u66F4":"### \u{1F6A8} \u91CD\u5927\u53D8\u66F4","### Minor Changes":"### \u2728 \u65B0\u589E\u529F\u80FD","### \u65B0\u589E\u529F\u80FD":"### \u2728 \u65B0\u589E\u529F\u80FD","### Patch Changes":"### \u{1F41B} \u8865\u4E01\u4FEE\u590D","### \u8865\u4E01\u4FEE\u590D":"### \u{1F41B} \u8865\u4E01\u4FEE\u590D","### Dependent Changes":"### \u{1F517} \u4F9D\u8D56\u53D8\u66F4","### \u4F9D\u8D56\u53D8\u66F4":"### \u{1F517} \u4F9D\u8D56\u53D8\u66F4","- Updated dependencies":"- \u66F4\u65B0\u4F9D\u8D56"},deps:"- \u66F4\u65B0\u4F9D\u8D56"},en:{replacements:{"### Major Changes":"### \u{1F6A8} Major Changes","### Minor Changes":"### \u2728 Minor Changes","### Patch Changes":"### \u{1F41B} Patch Changes","### Dependent Changes":"### \u{1F517} Dependent Changes"},deps:"- Updated dependencies"}},kt="zh";import{readdirSync as H}from"fs";import{join as D}from"path";function F(r){let o=[],e=new Set(["node_modules",".git","dist"]),t=n=>{let a;try{a=H(n,{withFileTypes:!0})}catch{return}for(let i of a)if(i.isDirectory()){if(e.has(i.name))continue;t(D(n,i.name))}else i.name==="CHANGELOG.md"&&o.push(D(n,i.name))};return t(r),o}import{readFileSync as Y,writeFileSync as q}from"fs";function I(){let r=new Date,o=e=>String(e).padStart(2,"0");return`${r.getFullYear()}-${o(r.getMonth()+1)}-${o(r.getDate())}`}function j(r,o,e){let t=Y(r,"utf8");for(let[s,l]of Object.entries(e.replacements))t=t.replaceAll(s,l);for(;t.includes(`${e.deps}
|
|
16
|
+
${e.deps}`);)t=t.replace(`${e.deps}
|
|
17
|
+
${e.deps}`,e.deps);for(;;){let s=t.replace(/^- (.+)\n- \1$/m,"- $1");if(s===t)break;t=s}let n=t.split(`
|
|
18
|
+
`),a=[];for(let s=0;s<n.length;s++)a.push(n[s]),/^## \d+\.\d+\.\d+/.test(n[s])&&!n[s+1]?.startsWith("> ")&&a.push(`> ${o} \u53D1\u5E03`);let i=a.join(`
|
|
19
|
+
`);return i!==t?(q(r,i,"utf8"),!0):!1}function J(r,o,e){let t=[];for(let n of F(r))j(n,o,e)&&t.push(n);if(t.length===0)console.log("\u65E0 CHANGELOG \u9700\u8981\u66F4\u65B0");else for(let n of t)console.log(`changelog \u5DF2\u66F4\u65B0\uFF1A${n}`);return t}export{kt as DEFAULT_LANG,$ as DONE_STATUSES,z as archiveTasks,F as collectChangelogs,y as dateFromFileName,j as formatChangelog,J as formatChangelogs,ht as languages,h as listTaskFiles,b as listTasks,I as localDate,w as parseArchiveTasks,d as parseFrontmatter,G as printTasks,u as stripFrontmatter};
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fxri/toolkit",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "开发工程化工具集:任务管理 + 多语言 CHANGELOG 发布。",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "唐启云",
|
|
8
|
+
"email": "tqy@fxri.net",
|
|
9
|
+
"url": "https://fxri.net:444/"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://git.fxy.ink:444/fxri/develop/0001.base/toolkit.git"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"bin": {
|
|
18
|
+
"toolkit": "dist/cli.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md",
|
|
23
|
+
"SPEC.md",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"TRADEMARK.md",
|
|
26
|
+
"NOTICE",
|
|
27
|
+
"package.json"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"dev": "pnpm build:debug && node ./dist/cli.js",
|
|
31
|
+
"build": "cross-env NODE_ENV=production tsup",
|
|
32
|
+
"build:debug": "cross-env NODE_ENV=development tsup --config tsup.dev.config.ts",
|
|
33
|
+
"release": "pnpm build && pnpm publish"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"toolkit",
|
|
37
|
+
"task",
|
|
38
|
+
"changelog",
|
|
39
|
+
"changesets",
|
|
40
|
+
"i18n"
|
|
41
|
+
],
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@changesets/cli": "^2.31.1"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^20.19.21",
|
|
47
|
+
"cross-env": "^10.1.0",
|
|
48
|
+
"tsup": "^8.5.0",
|
|
49
|
+
"typescript": "^5.9.3"
|
|
50
|
+
},
|
|
51
|
+
"packageManager": "pnpm@10.34.4",
|
|
52
|
+
"engines": {
|
|
53
|
+
"node": ">=20"
|
|
54
|
+
},
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"registry": "https://registry.npmjs.org/",
|
|
57
|
+
"access": "public"
|
|
58
|
+
}
|
|
59
|
+
}
|