workpytools 0.1.4__py3-none-any.whl
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.
- workpytools/__init__.py +1 -0
- workpytools/cli.py +76 -0
- workpytools/common/__init__.py +0 -0
- workpytools/common/browser_preview.py +40 -0
- workpytools/common/clipboard.py +318 -0
- workpytools/common/clustering.py +85 -0
- workpytools/common/config.py +44 -0
- workpytools/common/embedding.py +101 -0
- workpytools/common/help_gen.py +542 -0
- workpytools/common/logging.py +12 -0
- workpytools/common/markdown_html.py +15 -0
- workpytools/common/outline_parse.py +81 -0
- workpytools/common/output.py +71 -0
- workpytools/common/powerpoint.py +43 -0
- workpytools/common/shape_cluster.py +75 -0
- workpytools/common/table_shapes.py +157 -0
- workpytools/common/tabular.py +248 -0
- workpytools/common/textfile.py +90 -0
- workpytools/common/walk.py +133 -0
- workpytools/data/__init__.py +0 -0
- workpytools/data/synonym.tsv +3 -0
- workpytools/data/user.dic +2 -0
- workpytools/processing/__init__.py +0 -0
- workpytools/processing/base.py +23 -0
- workpytools/processing/clipfmt.py +143 -0
- workpytools/processing/clipmd.py +237 -0
- workpytools/processing/clipview.py +194 -0
- workpytools/processing/cwc.py +427 -0
- workpytools/processing/denoise.py +81 -0
- workpytools/processing/help.py +47 -0
- workpytools/processing/ikko.py +205 -0
- workpytools/processing/kukiri.py +94 -0
- workpytools/processing/lsdir.py +218 -0
- workpytools/processing/mdtsv.py +177 -0
- workpytools/processing/mokuji.py +91 -0
- workpytools/processing/nagasa.py +94 -0
- workpytools/processing/outline.py +85 -0
- workpytools/processing/profiler.py +277 -0
- workpytools/processing/seiretsu.py +111 -0
- workpytools/processing/tbl.py +358 -0
- workpytools/processing/touka.py +52 -0
- workpytools/processing/vv.py +147 -0
- workpytools-0.1.4.dist-info/METADATA +458 -0
- workpytools-0.1.4.dist-info/RECORD +48 -0
- workpytools-0.1.4.dist-info/WHEEL +5 -0
- workpytools-0.1.4.dist-info/entry_points.txt +20 -0
- workpytools-0.1.4.dist-info/licenses/LICENSE +21 -0
- workpytools-0.1.4.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import html as html_module
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from workpytools.cli import _ENTRY_POINT_ALIASES, _discover_processors
|
|
8
|
+
from workpytools.processing.base import Processor
|
|
9
|
+
|
|
10
|
+
# コマンド名 -> 単体実行ファイル名(拡張子なし)。pyproject.tomlの
|
|
11
|
+
# [project.scripts]は基本的にコマンド名と同名のエントリーポイントを
|
|
12
|
+
# 登録するため、既定はコマンド名そのものとする。help だけは toolh という
|
|
13
|
+
# 別名(help.exeだと紛らわしいため)で登録されているため、cli.pyの
|
|
14
|
+
# _ENTRY_POINT_ALIASES(エントリーポイント名->コマンド名)を逆引きして
|
|
15
|
+
# 例外を反映する。
|
|
16
|
+
_STANDALONE_NAME_OVERRIDES: dict[str, str] = {
|
|
17
|
+
command: entry_point for entry_point, command in _ENTRY_POINT_ALIASES.items()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def standalone_entry_point_name(command_name: str) -> str:
|
|
22
|
+
"""The name of the standalone executable for a command (e.g. "outline"
|
|
23
|
+
for `outline.exe`, "toolh" for the `help` command's `toolh.exe`)."""
|
|
24
|
+
return _STANDALONE_NAME_OVERRIDES.get(command_name, command_name)
|
|
25
|
+
|
|
26
|
+
# --- Before/After 図 ----------------------------------------------------
|
|
27
|
+
#
|
|
28
|
+
# help.htmlは説明文だけだと頭に入りにくいため、各コマンドが「何を」
|
|
29
|
+
# 「どう変える」のかを示すbefore/after図をSVGで自前描画して埋め込む。
|
|
30
|
+
# 汎用アイコンの並びではなく、コマンドごとに専用の絵を1枚ずつ用意する
|
|
31
|
+
# (合体・分解・整列・サイズ統一のような紐しい系のコマンドを見分ける
|
|
32
|
+
# ため)。外部画像・CDNには一切依存しない。
|
|
33
|
+
|
|
34
|
+
_DIAGRAM_VIEWBOX = "0 0 220 90"
|
|
35
|
+
_ARROW_CENTER = (
|
|
36
|
+
'<path d="M96 45 H124 M116 37 L124 45 L116 53" fill="none" '
|
|
37
|
+
'stroke="currentColor" stroke-width="2.5" stroke-linecap="round" '
|
|
38
|
+
'stroke-linejoin="round"/>'
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# コマンド名 -> before/after図のSVG中身(<g>の中に入れる要素)。
|
|
42
|
+
# 左半分(x=10-90)がbefore、中央に矢印、右半分(x=130-210)がafterの構図で揃える。
|
|
43
|
+
_DIAGRAMS: dict[str, str] = {
|
|
44
|
+
"touka": (
|
|
45
|
+
# before: 市松模様なしの背景に円(不透明な背景)
|
|
46
|
+
'<rect x="10" y="15" width="80" height="60" rx="3" fill="#cfe3ff" '
|
|
47
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
48
|
+
'<circle cx="50" cy="45" r="18" fill="#ffb100"/>'
|
|
49
|
+
+ _ARROW_CENTER +
|
|
50
|
+
# after: 市松模様の背景(透過を表す)に同じ円
|
|
51
|
+
'<g>'
|
|
52
|
+
'<rect x="130" y="15" width="80" height="60" rx="3" fill="#eee" '
|
|
53
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
54
|
+
'<rect x="130" y="15" width="10" height="10" fill="#ccc"/>'
|
|
55
|
+
'<rect x="150" y="15" width="10" height="10" fill="#ccc"/>'
|
|
56
|
+
'<rect x="170" y="15" width="10" height="10" fill="#ccc"/>'
|
|
57
|
+
'<rect x="190" y="15" width="10" height="10" fill="#ccc"/>'
|
|
58
|
+
'<rect x="140" y="25" width="10" height="10" fill="#ccc"/>'
|
|
59
|
+
'<rect x="160" y="25" width="10" height="10" fill="#ccc"/>'
|
|
60
|
+
'<rect x="180" y="25" width="10" height="10" fill="#ccc"/>'
|
|
61
|
+
'<rect x="130" y="35" width="10" height="10" fill="#ccc"/>'
|
|
62
|
+
'<rect x="150" y="35" width="10" height="10" fill="#ccc"/>'
|
|
63
|
+
'<rect x="170" y="35" width="10" height="10" fill="#ccc"/>'
|
|
64
|
+
'<rect x="190" y="35" width="10" height="10" fill="#ccc"/>'
|
|
65
|
+
'<circle cx="170" cy="45" r="18" fill="#ffb100"/>'
|
|
66
|
+
"</g>"
|
|
67
|
+
),
|
|
68
|
+
"denoise": (
|
|
69
|
+
# before: ザラついた(ノイズ粒の乗った)円
|
|
70
|
+
'<circle cx="50" cy="45" r="26" fill="#cfe3ff" stroke="currentColor" stroke-width="2"/>'
|
|
71
|
+
+ "".join(
|
|
72
|
+
f'<circle cx="{x}" cy="{y}" r="1.4" fill="#557" />'
|
|
73
|
+
for x, y in [
|
|
74
|
+
(38, 32), (52, 28), (61, 40), (44, 48), (58, 55),
|
|
75
|
+
(35, 50), (48, 58), (63, 30), (40, 40), (55, 45),
|
|
76
|
+
]
|
|
77
|
+
)
|
|
78
|
+
+ _ARROW_CENTER +
|
|
79
|
+
# after: 同じ円だがなめらか(ノイズ粒なし)
|
|
80
|
+
'<circle cx="170" cy="45" r="26" fill="#cfe3ff" stroke="currentColor" stroke-width="2"/>'
|
|
81
|
+
),
|
|
82
|
+
"kukiri": (
|
|
83
|
+
# before: 輪郭がぼやけた(複数の薄い同心円で滲みを表現)四角形
|
|
84
|
+
'<rect x="24" y="19" width="52" height="52" rx="4" fill="none" '
|
|
85
|
+
'stroke="#99a" stroke-width="6" opacity="0.35"/>'
|
|
86
|
+
'<rect x="24" y="19" width="52" height="52" rx="4" fill="#cfe3ff" '
|
|
87
|
+
'stroke="#99a" stroke-width="2" opacity="0.7"/>'
|
|
88
|
+
+ _ARROW_CENTER +
|
|
89
|
+
# after: 輪郭がくっきりした同じ四角形
|
|
90
|
+
'<rect x="144" y="19" width="52" height="52" rx="4" fill="#cfe3ff" '
|
|
91
|
+
'stroke="currentColor" stroke-width="3"/>'
|
|
92
|
+
),
|
|
93
|
+
"cwc": (
|
|
94
|
+
# before: テキスト行
|
|
95
|
+
'<rect x="14" y="15" width="72" height="60" rx="3" fill="none" '
|
|
96
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
97
|
+
'<line x1="22" y1="28" x2="78" y2="28" stroke="currentColor" stroke-width="2.5"/>'
|
|
98
|
+
'<line x1="22" y1="40" x2="78" y2="40" stroke="currentColor" stroke-width="2.5"/>'
|
|
99
|
+
'<line x1="22" y1="52" x2="78" y2="52" stroke="currentColor" stroke-width="2.5"/>'
|
|
100
|
+
'<line x1="22" y1="64" x2="60" y2="64" stroke="currentColor" stroke-width="2.5"/>'
|
|
101
|
+
+ _ARROW_CENTER +
|
|
102
|
+
# after: 大小の単語が散らばったワードクラウド
|
|
103
|
+
'<text x="145" y="35" font-size="16" font-weight="bold" '
|
|
104
|
+
'fill="currentColor">単語</text>'
|
|
105
|
+
'<text x="185" y="30" font-size="9" fill="currentColor">語</text>'
|
|
106
|
+
'<text x="140" y="55" font-size="10" fill="currentColor">頻度</text>'
|
|
107
|
+
'<text x="170" y="60" font-size="20" font-weight="bold" '
|
|
108
|
+
'fill="currentColor">多い</text>'
|
|
109
|
+
'<text x="150" y="75" font-size="8" fill="currentColor">少</text>'
|
|
110
|
+
),
|
|
111
|
+
"clipmd": (
|
|
112
|
+
# before: Markdown記法
|
|
113
|
+
'<rect x="10" y="15" width="80" height="60" rx="3" fill="none" '
|
|
114
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
115
|
+
'<text x="18" y="35" font-size="12" font-family="Consolas, monospace" '
|
|
116
|
+
'fill="currentColor"># 見出し</text>'
|
|
117
|
+
'<text x="18" y="52" font-size="12" font-family="Consolas, monospace" '
|
|
118
|
+
'fill="currentColor">**太字**</text>'
|
|
119
|
+
'<text x="18" y="69" font-size="12" font-family="Consolas, monospace" '
|
|
120
|
+
'fill="currentColor">- 項目</text>'
|
|
121
|
+
+ _ARROW_CENTER +
|
|
122
|
+
# after: リッチテキスト(実際に大きく・太くレンダリングされた見た目)
|
|
123
|
+
'<rect x="130" y="15" width="80" height="60" rx="3" fill="none" '
|
|
124
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
125
|
+
'<text x="138" y="34" font-size="15" font-weight="bold" '
|
|
126
|
+
'fill="currentColor">見出し</text>'
|
|
127
|
+
'<text x="138" y="52" font-size="12" font-weight="bold" '
|
|
128
|
+
'fill="currentColor">太字</text>'
|
|
129
|
+
'<circle cx="140" cy="63" r="1.8" fill="currentColor"/>'
|
|
130
|
+
'<text x="146" y="67" font-size="12" fill="currentColor">項目</text>'
|
|
131
|
+
),
|
|
132
|
+
"mdtsv": (
|
|
133
|
+
# before: Markdownの表記法
|
|
134
|
+
'<rect x="10" y="15" width="80" height="60" rx="3" fill="none" '
|
|
135
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
136
|
+
'<text x="16" y="35" font-size="11" font-family="Consolas, monospace" '
|
|
137
|
+
'fill="currentColor">|a|b|</text>'
|
|
138
|
+
'<text x="16" y="50" font-size="11" font-family="Consolas, monospace" '
|
|
139
|
+
'fill="currentColor">|-|-|</text>'
|
|
140
|
+
'<text x="16" y="65" font-size="11" font-family="Consolas, monospace" '
|
|
141
|
+
'fill="currentColor">|1|2|</text>'
|
|
142
|
+
+ _ARROW_CENTER +
|
|
143
|
+
# after: Excel風のグリッド(TSV貼り付け後の見た目)
|
|
144
|
+
'<rect x="130" y="15" width="80" height="60" rx="2" fill="none" '
|
|
145
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
146
|
+
'<line x1="130" y1="45" x2="210" y2="45" stroke="currentColor" stroke-width="1.5"/>'
|
|
147
|
+
'<line x1="170" y1="15" x2="170" y2="75" stroke="currentColor" stroke-width="1.5"/>'
|
|
148
|
+
'<text x="145" y="35" font-size="12" fill="currentColor">a</text>'
|
|
149
|
+
'<text x="185" y="35" font-size="12" fill="currentColor">b</text>'
|
|
150
|
+
'<text x="145" y="65" font-size="12" fill="currentColor">1</text>'
|
|
151
|
+
'<text x="185" y="65" font-size="12" fill="currentColor">2</text>'
|
|
152
|
+
),
|
|
153
|
+
"clipfmt": (
|
|
154
|
+
# before: 列がずれた表
|
|
155
|
+
'<rect x="10" y="15" width="80" height="60" rx="3" fill="none" '
|
|
156
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
157
|
+
'<text x="16" y="35" font-size="11" font-family="Consolas, monospace" '
|
|
158
|
+
'fill="currentColor">|a|bb|c|</text>'
|
|
159
|
+
'<text x="16" y="50" font-size="11" font-family="Consolas, monospace" '
|
|
160
|
+
'fill="currentColor">|-|-|-|</text>'
|
|
161
|
+
'<text x="16" y="65" font-size="11" font-family="Consolas, monospace" '
|
|
162
|
+
'fill="currentColor">|1|2|3|</text>'
|
|
163
|
+
+ _ARROW_CENTER +
|
|
164
|
+
# after: 列幅が揃ったMarkdown
|
|
165
|
+
'<rect x="130" y="15" width="80" height="60" rx="3" fill="none" '
|
|
166
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
167
|
+
'<text x="136" y="35" font-size="11" font-family="Consolas, monospace" '
|
|
168
|
+
'fill="currentColor">| a | bb | c |</text>'
|
|
169
|
+
'<text x="136" y="50" font-size="11" font-family="Consolas, monospace" '
|
|
170
|
+
'fill="currentColor">| -- | -- | - |</text>'
|
|
171
|
+
'<text x="136" y="65" font-size="11" font-family="Consolas, monospace" '
|
|
172
|
+
'fill="currentColor">| 1 | 2 | 3 |</text>'
|
|
173
|
+
),
|
|
174
|
+
"clipview": (
|
|
175
|
+
# before: クリップボード
|
|
176
|
+
'<rect x="24" y="15" width="52" height="60" rx="3" fill="none" '
|
|
177
|
+
'stroke="currentColor" stroke-width="2.5"/>'
|
|
178
|
+
'<rect x="38" y="10" width="24" height="10" rx="2" fill="currentColor"/>'
|
|
179
|
+
'<line x1="32" y1="35" x2="68" y2="35" stroke="currentColor" stroke-width="2"/>'
|
|
180
|
+
'<line x1="32" y1="47" x2="68" y2="47" stroke="currentColor" stroke-width="2"/>'
|
|
181
|
+
'<line x1="32" y1="59" x2="56" y2="59" stroke="currentColor" stroke-width="2"/>'
|
|
182
|
+
+ _ARROW_CENTER +
|
|
183
|
+
# after: ブラウザウィンドウにレンダリング済みの見出し・段落
|
|
184
|
+
'<rect x="130" y="12" width="80" height="66" rx="3" fill="none" '
|
|
185
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
186
|
+
'<line x1="130" y1="24" x2="210" y2="24" stroke="currentColor" stroke-width="2"/>'
|
|
187
|
+
'<circle cx="137" cy="18" r="1.6" fill="currentColor"/>'
|
|
188
|
+
'<circle cx="144" cy="18" r="1.6" fill="currentColor"/>'
|
|
189
|
+
'<text x="138" y="42" font-size="13" font-weight="bold" '
|
|
190
|
+
'fill="currentColor">見出し</text>'
|
|
191
|
+
'<line x1="138" y1="52" x2="200" y2="52" stroke="currentColor" stroke-width="1.5"/>'
|
|
192
|
+
'<line x1="138" y1="61" x2="200" y2="61" stroke="currentColor" stroke-width="1.5"/>'
|
|
193
|
+
'<line x1="138" y1="70" x2="180" y2="70" stroke="currentColor" stroke-width="1.5"/>'
|
|
194
|
+
),
|
|
195
|
+
"vv": (
|
|
196
|
+
# before: 番号付きの一覧
|
|
197
|
+
'<circle cx="18" cy="24" r="2" fill="currentColor"/>'
|
|
198
|
+
'<line x1="26" y1="24" x2="86" y2="24" stroke="currentColor" stroke-width="2"/>'
|
|
199
|
+
'<circle cx="18" cy="45" r="2" fill="currentColor" opacity="0.4"/>'
|
|
200
|
+
'<line x1="26" y1="45" x2="86" y2="45" stroke="currentColor" '
|
|
201
|
+
'stroke-width="2" opacity="0.4"/>'
|
|
202
|
+
'<circle cx="18" cy="66" r="2" fill="currentColor" opacity="0.4"/>'
|
|
203
|
+
'<line x1="26" y1="66" x2="86" y2="66" stroke="currentColor" '
|
|
204
|
+
'stroke-width="2" opacity="0.4"/>'
|
|
205
|
+
+ _ARROW_CENTER +
|
|
206
|
+
# after: 選んだ1件だけがクリップボードへ
|
|
207
|
+
'<rect x="150" y="15" width="52" height="60" rx="3" fill="none" '
|
|
208
|
+
'stroke="currentColor" stroke-width="2.5"/>'
|
|
209
|
+
'<rect x="164" y="10" width="24" height="10" rx="2" fill="currentColor"/>'
|
|
210
|
+
'<line x1="158" y1="40" x2="194" y2="40" stroke="currentColor" stroke-width="2.5"/>'
|
|
211
|
+
'<line x1="158" y1="52" x2="194" y2="52" stroke="currentColor" stroke-width="2.5"/>'
|
|
212
|
+
),
|
|
213
|
+
"profiler": (
|
|
214
|
+
# before: ふぞろいなセル(欠損混じり)の生データ
|
|
215
|
+
'<rect x="10" y="15" width="80" height="60" rx="2" fill="none" '
|
|
216
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
217
|
+
'<line x1="10" y1="35" x2="90" y2="35" stroke="currentColor" stroke-width="1.5"/>'
|
|
218
|
+
'<line x1="10" y1="55" x2="90" y2="55" stroke="currentColor" stroke-width="1.5"/>'
|
|
219
|
+
'<line x1="45" y1="15" x2="45" y2="75" stroke="currentColor" stroke-width="1.5"/>'
|
|
220
|
+
'<text x="20" y="30" font-size="11" fill="currentColor">12</text>'
|
|
221
|
+
'<text x="55" y="30" font-size="11" fill="currentColor">A</text>'
|
|
222
|
+
'<text x="20" y="50" font-size="11" fill="#c55" opacity="0.7">?</text>'
|
|
223
|
+
'<text x="55" y="50" font-size="11" fill="currentColor">B</text>'
|
|
224
|
+
'<text x="20" y="70" font-size="11" fill="currentColor">7</text>'
|
|
225
|
+
'<text x="55" y="70" font-size="11" fill="#c55" opacity="0.7">?</text>'
|
|
226
|
+
+ _ARROW_CENTER +
|
|
227
|
+
# after: 列ごとの統計(充填率バー)
|
|
228
|
+
'<text x="136" y="26" font-size="10" fill="currentColor">列A 充填 67%</text>'
|
|
229
|
+
'<rect x="136" y="30" width="60" height="6" rx="2" fill="none" '
|
|
230
|
+
'stroke="currentColor" stroke-width="1"/>'
|
|
231
|
+
'<rect x="136" y="30" width="40" height="6" rx="2" fill="currentColor"/>'
|
|
232
|
+
'<text x="136" y="52" font-size="10" fill="currentColor">列B 一意 100%</text>'
|
|
233
|
+
'<rect x="136" y="56" width="60" height="6" rx="2" fill="none" '
|
|
234
|
+
'stroke="currentColor" stroke-width="1"/>'
|
|
235
|
+
'<rect x="136" y="56" width="60" height="6" rx="2" fill="currentColor"/>'
|
|
236
|
+
),
|
|
237
|
+
"lsdir": (
|
|
238
|
+
# before: フォルダツリー
|
|
239
|
+
'<path d="M14 22 L28 22 L32 27 L54 27 L54 40 L14 40 Z" fill="none" '
|
|
240
|
+
'stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>'
|
|
241
|
+
'<path d="M20 46 L34 46 L38 51 L60 51 L60 64 L20 64 Z" fill="none" '
|
|
242
|
+
'stroke="currentColor" stroke-width="2" stroke-linejoin="round" opacity="0.6"/>'
|
|
243
|
+
+ _ARROW_CENTER +
|
|
244
|
+
# after: フラットな一覧表
|
|
245
|
+
'<rect x="130" y="15" width="80" height="60" rx="2" fill="none" '
|
|
246
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
247
|
+
'<line x1="130" y1="30" x2="210" y2="30" stroke="currentColor" stroke-width="1.5"/>'
|
|
248
|
+
'<line x1="130" y1="45" x2="210" y2="45" stroke="currentColor" stroke-width="1.5"/>'
|
|
249
|
+
'<line x1="130" y1="60" x2="210" y2="60" stroke="currentColor" stroke-width="1.5"/>'
|
|
250
|
+
'<line x1="170" y1="15" x2="170" y2="75" stroke="currentColor" stroke-width="1.5"/>'
|
|
251
|
+
),
|
|
252
|
+
"outline": (
|
|
253
|
+
# before: 箇条書きテキスト(アウトライン)
|
|
254
|
+
'<text x="14" y="30" font-size="12" font-family="Consolas, monospace" '
|
|
255
|
+
'fill="currentColor"># 章1</text>'
|
|
256
|
+
'<text x="14" y="46" font-size="12" font-family="Consolas, monospace" '
|
|
257
|
+
'fill="currentColor"># 章2</text>'
|
|
258
|
+
'<text x="14" y="62" font-size="12" font-family="Consolas, monospace" '
|
|
259
|
+
'fill="currentColor"># 章3</text>'
|
|
260
|
+
+ _ARROW_CENTER +
|
|
261
|
+
# after: スライドのサムネイル列
|
|
262
|
+
'<rect x="130" y="18" width="30" height="20" rx="1.5" fill="none" '
|
|
263
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
264
|
+
'<rect x="165" y="18" width="30" height="20" rx="1.5" fill="none" '
|
|
265
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
266
|
+
'<rect x="130" y="45" width="30" height="20" rx="1.5" fill="none" '
|
|
267
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
268
|
+
'<rect x="165" y="45" width="30" height="20" rx="1.5" fill="none" '
|
|
269
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
270
|
+
),
|
|
271
|
+
"mokuji": (
|
|
272
|
+
# before: スライドのサムネイル列
|
|
273
|
+
'<rect x="14" y="18" width="30" height="20" rx="1.5" fill="none" '
|
|
274
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
275
|
+
'<rect x="49" y="18" width="30" height="20" rx="1.5" fill="none" '
|
|
276
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
277
|
+
'<rect x="14" y="45" width="30" height="20" rx="1.5" fill="none" '
|
|
278
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
279
|
+
'<rect x="49" y="45" width="30" height="20" rx="1.5" fill="none" '
|
|
280
|
+
'stroke="currentColor" stroke-width="2"/>'
|
|
281
|
+
+ _ARROW_CENTER +
|
|
282
|
+
# after: 番号付きタイトル一覧(クリップボードへ)
|
|
283
|
+
'<rect x="150" y="10" width="52" height="66" rx="3" fill="none" '
|
|
284
|
+
'stroke="currentColor" stroke-width="2.5"/>'
|
|
285
|
+
'<rect x="164" y="5" width="24" height="10" rx="2" fill="currentColor"/>'
|
|
286
|
+
'<line x1="158" y1="34" x2="194" y2="34" stroke="currentColor" stroke-width="2"/>'
|
|
287
|
+
'<line x1="158" y1="46" x2="194" y2="46" stroke="currentColor" stroke-width="2"/>'
|
|
288
|
+
'<line x1="158" y1="58" x2="188" y2="58" stroke="currentColor" stroke-width="2"/>'
|
|
289
|
+
),
|
|
290
|
+
"ikko": (
|
|
291
|
+
# before: 3つの小さな四角形(縦積み・バラバラなテキストボックス)
|
|
292
|
+
'<rect x="16" y="16" width="68" height="14" rx="1.5" fill="none" '
|
|
293
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
294
|
+
'<rect x="16" y="38" width="68" height="14" rx="1.5" fill="none" '
|
|
295
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
296
|
+
'<rect x="16" y="60" width="68" height="14" rx="1.5" fill="none" '
|
|
297
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
298
|
+
+ _ARROW_CENTER +
|
|
299
|
+
# after: 1つの大きな四角形(3行のテキスト)
|
|
300
|
+
'<rect x="136" y="16" width="68" height="58" rx="2.5" fill="none" '
|
|
301
|
+
'stroke="currentColor" stroke-width="2.5"/>'
|
|
302
|
+
'<line x1="144" y1="34" x2="196" y2="34" stroke="currentColor" stroke-width="2"/>'
|
|
303
|
+
'<line x1="144" y1="46" x2="196" y2="46" stroke="currentColor" stroke-width="2"/>'
|
|
304
|
+
'<line x1="144" y1="58" x2="196" y2="58" stroke="currentColor" stroke-width="2"/>'
|
|
305
|
+
),
|
|
306
|
+
"tbl": (
|
|
307
|
+
# before/after: 表と四角形群を両矢印でつなぐ(相互変換)
|
|
308
|
+
'<rect x="10" y="15" width="80" height="60" rx="2" fill="none" '
|
|
309
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
310
|
+
'<line x1="10" y1="35" x2="90" y2="35" stroke="currentColor" stroke-width="1.5"/>'
|
|
311
|
+
'<line x1="10" y1="55" x2="90" y2="55" stroke="currentColor" stroke-width="1.5"/>'
|
|
312
|
+
'<line x1="36" y1="15" x2="36" y2="75" stroke="currentColor" stroke-width="1.5"/>'
|
|
313
|
+
'<line x1="63" y1="15" x2="63" y2="75" stroke="currentColor" stroke-width="1.5"/>'
|
|
314
|
+
'<path d="M96 39 H124 M116 33 L124 39 L116 45" fill="none" '
|
|
315
|
+
'stroke="currentColor" stroke-width="2.3" stroke-linecap="round" '
|
|
316
|
+
'stroke-linejoin="round"/>'
|
|
317
|
+
'<path d="M124 51 H96 M104 45 L96 51 L104 57" fill="none" '
|
|
318
|
+
'stroke="currentColor" stroke-width="2.3" stroke-linecap="round" '
|
|
319
|
+
'stroke-linejoin="round"/>'
|
|
320
|
+
'<rect x="130" y="16" width="34" height="26" rx="1.5" fill="none" '
|
|
321
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
322
|
+
'<rect x="170" y="16" width="34" height="26" rx="1.5" fill="none" '
|
|
323
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
324
|
+
'<rect x="130" y="48" width="34" height="26" rx="1.5" fill="none" '
|
|
325
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
326
|
+
'<rect x="170" y="48" width="34" height="26" rx="1.5" fill="none" '
|
|
327
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
328
|
+
),
|
|
329
|
+
"seiretsu": (
|
|
330
|
+
# before: 傾いてバラバラな四角形群
|
|
331
|
+
'<rect x="10" y="12" width="24" height="18" rx="1.5" fill="none" '
|
|
332
|
+
'stroke="currentColor" stroke-width="2.2" transform="rotate(-10 22 21)"/>'
|
|
333
|
+
'<rect x="55" y="8" width="24" height="18" rx="1.5" fill="none" '
|
|
334
|
+
'stroke="currentColor" stroke-width="2.2" transform="rotate(7 67 17)"/>'
|
|
335
|
+
'<rect x="18" y="50" width="24" height="18" rx="1.5" fill="none" '
|
|
336
|
+
'stroke="currentColor" stroke-width="2.2" transform="rotate(4 30 59)"/>'
|
|
337
|
+
'<rect x="60" y="55" width="24" height="18" rx="1.5" fill="none" '
|
|
338
|
+
'stroke="currentColor" stroke-width="2.2" transform="rotate(-6 72 64)"/>'
|
|
339
|
+
+ _ARROW_CENTER +
|
|
340
|
+
# after: きれいな格子状に整列
|
|
341
|
+
'<rect x="132" y="15" width="30" height="24" rx="1.5" fill="none" '
|
|
342
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
343
|
+
'<rect x="172" y="15" width="30" height="24" rx="1.5" fill="none" '
|
|
344
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
345
|
+
'<rect x="132" y="49" width="30" height="24" rx="1.5" fill="none" '
|
|
346
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
347
|
+
'<rect x="172" y="49" width="30" height="24" rx="1.5" fill="none" '
|
|
348
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
349
|
+
),
|
|
350
|
+
"nagasa": (
|
|
351
|
+
# before: サイズが不揃いな四角形群(横並び)
|
|
352
|
+
'<rect x="12" y="35" width="16" height="16" rx="1.5" fill="none" '
|
|
353
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
354
|
+
'<rect x="34" y="12" width="20" height="40" rx="1.5" fill="none" '
|
|
355
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
356
|
+
'<rect x="60" y="45" width="24" height="10" rx="1.5" fill="none" '
|
|
357
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
358
|
+
+ _ARROW_CENTER +
|
|
359
|
+
# after: 同じサイズに揃った四角形群
|
|
360
|
+
'<rect x="130" y="15" width="20" height="40" rx="1.5" fill="none" '
|
|
361
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
362
|
+
'<rect x="156" y="15" width="20" height="40" rx="1.5" fill="none" '
|
|
363
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
364
|
+
'<rect x="182" y="15" width="20" height="40" rx="1.5" fill="none" '
|
|
365
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
366
|
+
),
|
|
367
|
+
"help": (
|
|
368
|
+
'<rect x="70" y="12" width="80" height="66" rx="3" fill="none" '
|
|
369
|
+
'stroke="currentColor" stroke-width="2.2"/>'
|
|
370
|
+
'<line x1="70" y1="24" x2="150" y2="24" stroke="currentColor" stroke-width="2"/>'
|
|
371
|
+
'<circle cx="77" cy="18" r="1.6" fill="currentColor"/>'
|
|
372
|
+
'<circle cx="84" cy="18" r="1.6" fill="currentColor"/>'
|
|
373
|
+
'<text x="95" y="52" font-size="24" font-weight="bold" '
|
|
374
|
+
'text-anchor="middle" fill="currentColor">?</text>'
|
|
375
|
+
),
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def _render_diagram_svg(name: str) -> str:
|
|
380
|
+
"""Render the before/after diagram for one command, or an empty string
|
|
381
|
+
if the command has no registered diagram (falls back to text-only)."""
|
|
382
|
+
body = _DIAGRAMS.get(name)
|
|
383
|
+
if body is None:
|
|
384
|
+
return ""
|
|
385
|
+
|
|
386
|
+
return (
|
|
387
|
+
f'<div class="diagram" aria-hidden="true">'
|
|
388
|
+
f'<svg viewBox="{_DIAGRAM_VIEWBOX}"><g>{body}</g></svg>'
|
|
389
|
+
f"</div>"
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
@dataclass(frozen=True)
|
|
394
|
+
class CommandHelp:
|
|
395
|
+
name: str
|
|
396
|
+
summary: str
|
|
397
|
+
usage: str
|
|
398
|
+
full_help: str
|
|
399
|
+
standalone_name: str
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
def collect_command_help() -> list[CommandHelp]:
|
|
403
|
+
"""Build per-command help text by rendering each Processor's own argparse help."""
|
|
404
|
+
processors = _discover_processors()
|
|
405
|
+
results: list[CommandHelp] = []
|
|
406
|
+
|
|
407
|
+
for name in sorted(processors):
|
|
408
|
+
proc = processors[name]
|
|
409
|
+
parser = _build_standalone_parser(proc)
|
|
410
|
+
full_help = parser.format_help()
|
|
411
|
+
results.append(
|
|
412
|
+
CommandHelp(
|
|
413
|
+
name=name,
|
|
414
|
+
summary=proc.help,
|
|
415
|
+
usage=parser.format_usage(),
|
|
416
|
+
full_help=full_help,
|
|
417
|
+
standalone_name=standalone_entry_point_name(name),
|
|
418
|
+
)
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
return results
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _build_standalone_parser(proc: Processor) -> argparse.ArgumentParser:
|
|
425
|
+
parser = argparse.ArgumentParser(prog=proc.name, description=proc.help)
|
|
426
|
+
proc.add_arguments(parser)
|
|
427
|
+
return parser
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
def render_help_html(commands: list[CommandHelp]) -> str:
|
|
431
|
+
rows = []
|
|
432
|
+
for cmd in commands:
|
|
433
|
+
diagram_svg = _render_diagram_svg(cmd.name)
|
|
434
|
+
exe_name = f"{cmd.standalone_name}.exe"
|
|
435
|
+
rows.append(
|
|
436
|
+
"<section class=\"command\">\n"
|
|
437
|
+
f"<h2 id=\"{html_module.escape(cmd.name)}\">{html_module.escape(cmd.name)}</h2>\n"
|
|
438
|
+
f"<p class=\"standalone\">単体実行: "
|
|
439
|
+
f"<code>{html_module.escape(exe_name)}</code></p>\n"
|
|
440
|
+
f"{diagram_svg}\n"
|
|
441
|
+
f"<p class=\"summary\">{html_module.escape(cmd.summary)}</p>\n"
|
|
442
|
+
f"<pre>{html_module.escape(cmd.full_help)}</pre>\n"
|
|
443
|
+
"</section>"
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
toc_items = "\n".join(
|
|
447
|
+
f'<li><a href="#{html_module.escape(c.name)}">{html_module.escape(c.name)}</a>'
|
|
448
|
+
f' <code>({html_module.escape(c.standalone_name)}.exe)</code>'
|
|
449
|
+
f" — {html_module.escape(c.summary)}</li>"
|
|
450
|
+
for c in commands
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
return f"""<!doctype html>
|
|
454
|
+
<html lang="ja">
|
|
455
|
+
<head>
|
|
456
|
+
<meta charset="utf-8">
|
|
457
|
+
<meta http-equiv="Cache-Control" content="no-store">
|
|
458
|
+
<title>tools コマンドヘルプ</title>
|
|
459
|
+
<style>
|
|
460
|
+
:root {{ color-scheme: light dark; }}
|
|
461
|
+
body {{
|
|
462
|
+
max-width: 50rem;
|
|
463
|
+
margin: 2rem auto;
|
|
464
|
+
padding: 0 1rem;
|
|
465
|
+
font-family: -apple-system, "Segoe UI", sans-serif;
|
|
466
|
+
line-height: 1.6;
|
|
467
|
+
color: #222;
|
|
468
|
+
background: #fff;
|
|
469
|
+
}}
|
|
470
|
+
h1 {{ font-size: 1.6rem; }}
|
|
471
|
+
h2 {{
|
|
472
|
+
font-size: 1.2rem;
|
|
473
|
+
margin-top: 2rem;
|
|
474
|
+
border-bottom: 1px solid #ccc;
|
|
475
|
+
padding-bottom: 0.3rem;
|
|
476
|
+
}}
|
|
477
|
+
.summary {{ color: #555; margin: 0.3rem 0 0.8rem; }}
|
|
478
|
+
.standalone {{
|
|
479
|
+
color: #666;
|
|
480
|
+
font-size: 0.85rem;
|
|
481
|
+
margin: 0.2rem 0;
|
|
482
|
+
}}
|
|
483
|
+
.standalone code {{
|
|
484
|
+
background: #eee;
|
|
485
|
+
padding: 0.1rem 0.4rem;
|
|
486
|
+
border-radius: 3px;
|
|
487
|
+
font-family: Consolas, "Courier New", monospace;
|
|
488
|
+
}}
|
|
489
|
+
nav .standalone-hint {{
|
|
490
|
+
font-size: 0.8rem;
|
|
491
|
+
color: #888;
|
|
492
|
+
}}
|
|
493
|
+
pre {{
|
|
494
|
+
background: #f5f5f5;
|
|
495
|
+
padding: 0.8rem;
|
|
496
|
+
overflow-x: auto;
|
|
497
|
+
font-family: Consolas, "Courier New", monospace;
|
|
498
|
+
font-size: 0.85rem;
|
|
499
|
+
}}
|
|
500
|
+
nav ul {{ padding-left: 1.2rem; }}
|
|
501
|
+
nav a {{ text-decoration: none; }}
|
|
502
|
+
nav a:hover {{ text-decoration: underline; }}
|
|
503
|
+
nav code {{
|
|
504
|
+
background: #eee;
|
|
505
|
+
padding: 0.05rem 0.3rem;
|
|
506
|
+
border-radius: 3px;
|
|
507
|
+
font-family: Consolas, "Courier New", monospace;
|
|
508
|
+
font-size: 0.8rem;
|
|
509
|
+
}}
|
|
510
|
+
.diagram {{
|
|
511
|
+
margin: 0.4rem 0 0.6rem;
|
|
512
|
+
color: #666;
|
|
513
|
+
}}
|
|
514
|
+
.diagram svg {{
|
|
515
|
+
width: 100%;
|
|
516
|
+
max-width: 22rem;
|
|
517
|
+
height: auto;
|
|
518
|
+
}}
|
|
519
|
+
@media (prefers-color-scheme: dark) {{
|
|
520
|
+
body {{ color: #ddd; background: #1e1e1e; }}
|
|
521
|
+
h2 {{ border-bottom-color: #555; }}
|
|
522
|
+
.summary {{ color: #aaa; }}
|
|
523
|
+
.standalone {{ color: #aaa; }}
|
|
524
|
+
.standalone code {{ background: #333; }}
|
|
525
|
+
nav code {{ background: #333; }}
|
|
526
|
+
nav .standalone-hint {{ color: #888; }}
|
|
527
|
+
.diagram {{ color: #999; }}
|
|
528
|
+
pre {{ background: #2a2a2a; }}
|
|
529
|
+
}}
|
|
530
|
+
</style>
|
|
531
|
+
</head>
|
|
532
|
+
<body>
|
|
533
|
+
<h1>tools コマンド一覧</h1>
|
|
534
|
+
<nav>
|
|
535
|
+
<ul>
|
|
536
|
+
{toc_items}
|
|
537
|
+
</ul>
|
|
538
|
+
</nav>
|
|
539
|
+
{chr(10).join(rows)}
|
|
540
|
+
</body>
|
|
541
|
+
</html>
|
|
542
|
+
"""
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def markdown_to_html_fragment(markdown_text: str) -> str:
|
|
5
|
+
"""Render Markdown to an HTML fragment (no <html>/<body> wrapper).
|
|
6
|
+
|
|
7
|
+
Uses the commonmark preset with the table extension enabled (disabled by
|
|
8
|
+
default in markdown-it-py). commonmark's html=True also lets raw HTML in
|
|
9
|
+
the Markdown source pass through untouched.
|
|
10
|
+
"""
|
|
11
|
+
from markdown_it import MarkdownIt
|
|
12
|
+
|
|
13
|
+
md = MarkdownIt("commonmark").enable("table")
|
|
14
|
+
rendered: str = md.render(markdown_text)
|
|
15
|
+
return rendered
|