@unlaxer/dde-toolkit 0.1.5 → 0.1.7
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/flows/quick.yaml +4 -0
- package/lib/markdown.js +47 -2
- package/package.json +1 -1
- package/skills/dde-session.md +71 -5
- package/version.txt +1 -1
package/flows/quick.yaml
CHANGED
|
@@ -16,6 +16,10 @@ workflow:
|
|
|
16
16
|
- id: scan_glossary
|
|
17
17
|
display_name: "既存 glossary をスキャン"
|
|
18
18
|
note: "docs/glossary/ の既存記事一覧を収集。相互リンク候補 + 抽出除外リストに使う"
|
|
19
|
+
- id: detect_template
|
|
20
|
+
display_name: "記事テンプレートを確定"
|
|
21
|
+
mode: confirm
|
|
22
|
+
note: ".dde-template.md があれば再利用。なければ既存記事の H2 を多数決で抽出 → ユーザー確認 → 保存"
|
|
19
23
|
- id: select_docs
|
|
20
24
|
display_name: "対象ドキュメント群を選択"
|
|
21
25
|
mode: confirm
|
package/lib/markdown.js
CHANGED
|
@@ -85,6 +85,7 @@ export function processMarkdown(content, dictionary, lang = 'en', sourceFile = n
|
|
|
85
85
|
* テキスト内で用語の置換箇所を検出する
|
|
86
86
|
* - 段落ごとに 1 用語 1 回まで
|
|
87
87
|
* - 最長一致(辞書はすでに降順ソート済み)
|
|
88
|
+
* - ASCII 用語は単語境界チェックを適用(複合語内マッチを防ぐ)
|
|
88
89
|
*/
|
|
89
90
|
function findReplacements(text, dictionary, alreadyMatched, lang) {
|
|
90
91
|
// 使用済み範囲を追跡(重複マッチ防止)
|
|
@@ -95,7 +96,20 @@ function findReplacements(text, dictionary, alreadyMatched, lang) {
|
|
|
95
96
|
if (entry.lang !== lang && entry.lang !== 'en') continue;
|
|
96
97
|
if (alreadyMatched.has(entry.term)) continue;
|
|
97
98
|
|
|
98
|
-
|
|
99
|
+
// 単語境界チェックが必要な ASCII 用語は、条件を満たす最初の出現を探す
|
|
100
|
+
let idx = -1;
|
|
101
|
+
const needsBoundary = isAsciiTerm(entry.term);
|
|
102
|
+
let searchFrom = 0;
|
|
103
|
+
while (true) {
|
|
104
|
+
const found = text.indexOf(entry.term, searchFrom);
|
|
105
|
+
if (found === -1) break;
|
|
106
|
+
if (needsBoundary && !hasWordBoundary(text, found, found + entry.term.length)) {
|
|
107
|
+
searchFrom = found + 1;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
idx = found;
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
99
113
|
if (idx === -1) continue;
|
|
100
114
|
|
|
101
115
|
// 重複範囲チェック
|
|
@@ -113,6 +127,23 @@ function findReplacements(text, dictionary, alreadyMatched, lang) {
|
|
|
113
127
|
return replacements;
|
|
114
128
|
}
|
|
115
129
|
|
|
130
|
+
/**
|
|
131
|
+
* 用語が ASCII 文字のみで構成されているか(日本語等は除外)
|
|
132
|
+
*/
|
|
133
|
+
function isAsciiTerm(term) {
|
|
134
|
+
return /^[\x00-\x7F]+$/.test(term);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* text[start..end] の前後が単語文字(\w)でないか確認する
|
|
139
|
+
*/
|
|
140
|
+
function hasWordBoundary(text, start, end) {
|
|
141
|
+
const wordChar = /\w/;
|
|
142
|
+
if (start > 0 && wordChar.test(text[start - 1])) return false;
|
|
143
|
+
if (end < text.length && wordChar.test(text[end])) return false;
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
|
|
116
147
|
/**
|
|
117
148
|
* テキストと置換リストから AST ノード配列を生成
|
|
118
149
|
* @param {string} sourceFile - リンクを埋め込むファイルのパス(相対パス計算用)
|
|
@@ -185,7 +216,21 @@ export function findUnlinked(content, dictionary, lang = 'en') {
|
|
|
185
216
|
|
|
186
217
|
for (const entry of dictionary) {
|
|
187
218
|
if (entry.lang !== lang && entry.lang !== 'en') continue;
|
|
188
|
-
|
|
219
|
+
const text = node.value;
|
|
220
|
+
const needsBoundary = isAsciiTerm(entry.term);
|
|
221
|
+
let found = false;
|
|
222
|
+
let searchFrom = 0;
|
|
223
|
+
while (true) {
|
|
224
|
+
const idx = text.indexOf(entry.term, searchFrom);
|
|
225
|
+
if (idx === -1) break;
|
|
226
|
+
if (needsBoundary && !hasWordBoundary(text, idx, idx + entry.term.length)) {
|
|
227
|
+
searchFrom = idx + 1;
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
found = true;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
if (found) {
|
|
189
234
|
const key = entry.term;
|
|
190
235
|
if (!unlinked.has(key)) {
|
|
191
236
|
unlinked.set(key, { term: entry.term, file: entry.file, count: 0 });
|
package/package.json
CHANGED
package/skills/dde-session.md
CHANGED
|
@@ -67,10 +67,11 @@ DDE toolkit v0.1.3 — Document Deficit Extraction
|
|
|
67
67
|
新規セッションの場合は skip。
|
|
68
68
|
|
|
69
69
|
**0-C: 既存 glossary スキャン(MUST)**
|
|
70
|
-
`docs/glossary/` の `.md` ファイル一覧を収集する。これを
|
|
70
|
+
`docs/glossary/` の `.md` ファイル一覧を収集する。これを 3 つの目的に使う:
|
|
71
71
|
|
|
72
72
|
1. **抽出除外リスト** — 既存記事がある用語は抽出対象から除外(Step 6)
|
|
73
73
|
2. **相互リンク候補リスト** — 「さらに学ぶために」で使えるリンク一覧(Step 7)
|
|
74
|
+
3. **テンプレート抽出** — 既存記事の H2 構造を分析してフォーマットを確定(後述)
|
|
74
75
|
|
|
75
76
|
```
|
|
76
77
|
既存 glossary: 12 記事
|
|
@@ -81,6 +82,72 @@ DDE toolkit v0.1.3 — Document Deficit Extraction
|
|
|
81
82
|
|
|
82
83
|
ファイルが存在しない場合は空リストで OK(新規プロジェクト)。
|
|
83
84
|
|
|
85
|
+
**0-D: 記事テンプレートの確定**
|
|
86
|
+
|
|
87
|
+
まず `docs/glossary/.dde-template.md` が存在するか確認する。
|
|
88
|
+
|
|
89
|
+
- **存在する場合**: そのテンプレートを使用(再分析不要。ユーザーに「既存テンプレートを使用します」と通知)
|
|
90
|
+
- **存在しない場合**: 以下の手順でテンプレートを抽出する
|
|
91
|
+
|
|
92
|
+
**テンプレート自動抽出手順:**
|
|
93
|
+
1. 既存 `.md` ファイルから **EN 用と JA 用それぞれ** 3〜5 件をサンプリング(辞書順)
|
|
94
|
+
2. 各ファイルの H2 見出し(`## ...`)を列挙
|
|
95
|
+
3. **多数決**で共通パターンを確定(過半数のファイルに存在する見出しを採用)
|
|
96
|
+
4. ユーザーに確認・修正を求める:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
既存 glossary のセクション構造を検出しました:
|
|
100
|
+
|
|
101
|
+
EN 記事テンプレート:
|
|
102
|
+
## What is it?
|
|
103
|
+
## Why does it matter?
|
|
104
|
+
## How does it work?
|
|
105
|
+
## How does [project] use it?
|
|
106
|
+
## Common mistakes / attacks
|
|
107
|
+
## Further reading
|
|
108
|
+
|
|
109
|
+
JA 記事テンプレート:
|
|
110
|
+
## これは何?
|
|
111
|
+
## なぜ重要なのか?
|
|
112
|
+
## どう動くのか?
|
|
113
|
+
## [project] ではどう使われている?
|
|
114
|
+
## よくある間違いと攻撃
|
|
115
|
+
## さらに学ぶ
|
|
116
|
+
|
|
117
|
+
このテンプレートで記事を生成します。修正しますか?
|
|
118
|
+
1. このまま使う(推奨)
|
|
119
|
+
2. 修正する
|
|
120
|
+
3. デフォルト(DDE educational format)を使う
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
5. 確定後、`docs/glossary/.dde-template.md` に保存する(次回セッションで再利用)
|
|
124
|
+
|
|
125
|
+
**`.dde-template.md` のフォーマット:**
|
|
126
|
+
```markdown
|
|
127
|
+
<!-- DDE auto-detected template — edit freely -->
|
|
128
|
+
<!-- generated: 2024-01-15 from 5 sample articles -->
|
|
129
|
+
|
|
130
|
+
## en
|
|
131
|
+
|
|
132
|
+
## What is it?
|
|
133
|
+
## Why does it matter?
|
|
134
|
+
## How does it work?
|
|
135
|
+
## How does [project] use it?
|
|
136
|
+
## Common mistakes / attacks
|
|
137
|
+
## Further reading
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## ja
|
|
142
|
+
|
|
143
|
+
## これは何?
|
|
144
|
+
## なぜ重要なのか?
|
|
145
|
+
## どう動くのか?
|
|
146
|
+
## [project] ではどう使われている?
|
|
147
|
+
## よくある間違いと攻撃
|
|
148
|
+
## さらに学ぶ
|
|
149
|
+
```
|
|
150
|
+
|
|
84
151
|
**CRITICAL RULE — 相互リンク**:
|
|
85
152
|
「さらに学ぶために」に書くリンクは、**記事生成時点で `docs/glossary/` に実在するファイルのみ**。
|
|
86
153
|
存在しないファイルへのリンクは絶対に書かない。同一バッチで新規生成する記事同士は相互リンク可。
|
|
@@ -142,15 +209,14 @@ DDE toolkit v0.1.3 — Document Deficit Extraction
|
|
|
142
209
|
|
|
143
210
|
**文字数ではなく「読んだ人にどうなってほしいか」で指定する。**
|
|
144
211
|
|
|
145
|
-
Step 0-
|
|
212
|
+
Step 0-D で確定したテンプレートを使用する。既存 glossary 記事が見つかった場合は「既存に合わせる」が推奨。
|
|
146
213
|
|
|
147
214
|
**既存記事がある場合の表示例:**
|
|
148
215
|
```
|
|
149
|
-
|
|
150
|
-
→ educational narrative(例え話・ASCIIダイアグラム・相互リンクあり)
|
|
216
|
+
テンプレート: docs/glossary/.dde-template.md(5 件から抽出済み)
|
|
151
217
|
|
|
152
218
|
記事のインテントを選んでください:
|
|
153
|
-
1. 既存に合わせる(推奨)—
|
|
219
|
+
1. 既存に合わせる(推奨)— Step 0-D で確定したテンプレート構成を使用
|
|
154
220
|
2. educational — 背景・動機・仕組みごと理解できる記事
|
|
155
221
|
例え話・図・なぜ?を含む。分量は目的に従って自然に決まる
|
|
156
222
|
3. reference — 定義と使い方を簡潔に。調べたい人向け
|
package/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.7
|