skill-calorie 0.1.1 → 0.2.1

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.
Files changed (144) hide show
  1. package/SKILL.md +207 -0
  2. package/dist/analysis/anomaly/common.d.ts.map +1 -1
  3. package/dist/analysis/anomaly/common.js +2 -1
  4. package/dist/analysis/anomaly/common.js.map +1 -1
  5. package/dist/analysis/cross.d.ts.map +1 -1
  6. package/dist/analysis/cross.js +3 -2
  7. package/dist/analysis/cross.js.map +1 -1
  8. package/dist/analysis/deficit.d.ts.map +1 -1
  9. package/dist/analysis/deficit.js +4 -0
  10. package/dist/analysis/deficit.js.map +1 -1
  11. package/dist/analysis/diet.js +2 -2
  12. package/dist/analysis/diet.js.map +1 -1
  13. package/dist/analysis/exercise.js +5 -5
  14. package/dist/analysis/exercise.js.map +1 -1
  15. package/dist/analysis/review.js +2 -2
  16. package/dist/analysis/review.js.map +1 -1
  17. package/dist/analysis/series.d.ts +7 -1
  18. package/dist/analysis/series.d.ts.map +1 -1
  19. package/dist/analysis/series.js +22 -6
  20. package/dist/analysis/series.js.map +1 -1
  21. package/dist/analysis/utils.d.ts +7 -0
  22. package/dist/analysis/utils.d.ts.map +1 -1
  23. package/dist/analysis/utils.js +7 -0
  24. package/dist/analysis/utils.js.map +1 -1
  25. package/dist/analysis/weightCompare3.js +2 -2
  26. package/dist/analysis/weightCompare3.js.map +1 -1
  27. package/dist/cli/cmd_read.d.ts +21 -3
  28. package/dist/cli/cmd_read.d.ts.map +1 -1
  29. package/dist/cli/cmd_read.js +480 -53
  30. package/dist/cli/cmd_read.js.map +1 -1
  31. package/dist/cli/keys.d.ts +89 -1
  32. package/dist/cli/keys.d.ts.map +1 -1
  33. package/dist/cli/keys.js +30 -0
  34. package/dist/cli/keys.js.map +1 -1
  35. package/dist/cli/write.d.ts +19 -1
  36. package/dist/cli/write.d.ts.map +1 -1
  37. package/dist/cli/write.js +148 -52
  38. package/dist/cli/write.js.map +1 -1
  39. package/dist/db/readonly.d.ts +3 -0
  40. package/dist/db/readonly.d.ts.map +1 -0
  41. package/dist/db/readonly.js +22 -0
  42. package/dist/db/readonly.js.map +1 -0
  43. package/dist/output.d.ts +82 -0
  44. package/dist/output.d.ts.map +1 -0
  45. package/dist/output.js +305 -0
  46. package/dist/output.js.map +1 -0
  47. package/dist/render/copy.d.ts +20 -0
  48. package/dist/render/copy.d.ts.map +1 -0
  49. package/dist/render/copy.js +36 -0
  50. package/dist/render/copy.js.map +1 -0
  51. package/dist/render/dietDocs.d.ts +45 -0
  52. package/dist/render/dietDocs.d.ts.map +1 -0
  53. package/dist/render/dietDocs.js +561 -0
  54. package/dist/render/dietDocs.js.map +1 -0
  55. package/dist/render/envelope.d.ts +32 -6
  56. package/dist/render/envelope.d.ts.map +1 -1
  57. package/dist/render/envelope.js +71 -0
  58. package/dist/render/envelope.js.map +1 -1
  59. package/dist/render/exercisePort.d.ts +161 -0
  60. package/dist/render/exercisePort.d.ts.map +1 -0
  61. package/dist/render/exercisePort.js +395 -0
  62. package/dist/render/exercisePort.js.map +1 -0
  63. package/dist/render/goal.d.ts.map +1 -1
  64. package/dist/render/goal.js +13 -2
  65. package/dist/render/goal.js.map +1 -1
  66. package/dist/render/goalPlate.d.ts +1 -1
  67. package/dist/render/goalPlate.d.ts.map +1 -1
  68. package/dist/render/goalPlate.js +5 -1
  69. package/dist/render/goalPlate.js.map +1 -1
  70. package/dist/render/helpCenter.d.ts +104 -0
  71. package/dist/render/helpCenter.d.ts.map +1 -0
  72. package/dist/render/helpCenter.js +386 -0
  73. package/dist/render/helpCenter.js.map +1 -0
  74. package/dist/render/html.d.ts +12 -0
  75. package/dist/render/html.d.ts.map +1 -1
  76. package/dist/render/html.js +21 -5
  77. package/dist/render/html.js.map +1 -1
  78. package/dist/render/index.d.ts +8 -1
  79. package/dist/render/index.d.ts.map +1 -1
  80. package/dist/render/index.js +5 -1
  81. package/dist/render/index.js.map +1 -1
  82. package/dist/render/nutritionPort.d.ts +89 -0
  83. package/dist/render/nutritionPort.d.ts.map +1 -0
  84. package/dist/render/nutritionPort.js +183 -0
  85. package/dist/render/nutritionPort.js.map +1 -0
  86. package/dist/render/nutritionPortDocs.d.ts +6 -0
  87. package/dist/render/nutritionPortDocs.d.ts.map +1 -0
  88. package/dist/render/nutritionPortDocs.js +317 -0
  89. package/dist/render/nutritionPortDocs.js.map +1 -0
  90. package/dist/render/photo.d.ts +6 -1
  91. package/dist/render/photo.d.ts.map +1 -1
  92. package/dist/render/photo.js +13 -4
  93. package/dist/render/photo.js.map +1 -1
  94. package/dist/render/planPlate.d.ts +2 -1
  95. package/dist/render/planPlate.d.ts.map +1 -1
  96. package/dist/render/planPlate.js +6 -1
  97. package/dist/render/planPlate.js.map +1 -1
  98. package/dist/render/receipt.d.ts +47 -1
  99. package/dist/render/receipt.d.ts.map +1 -1
  100. package/dist/render/receipt.js +67 -3
  101. package/dist/render/receipt.js.map +1 -1
  102. package/dist/render/sportDocs.d.ts +14 -0
  103. package/dist/render/sportDocs.d.ts.map +1 -0
  104. package/dist/render/sportDocs.js +540 -0
  105. package/dist/render/sportDocs.js.map +1 -0
  106. package/dist/render/sportPortDocs.d.ts +8 -0
  107. package/dist/render/sportPortDocs.d.ts.map +1 -0
  108. package/dist/render/sportPortDocs.js +468 -0
  109. package/dist/render/sportPortDocs.js.map +1 -0
  110. package/dist/render/templates.d.ts +4 -0
  111. package/dist/render/templates.d.ts.map +1 -0
  112. package/dist/render/templates.js +29 -0
  113. package/dist/render/templates.js.map +1 -0
  114. package/dist/render/trendDocs.d.ts +11 -0
  115. package/dist/render/trendDocs.d.ts.map +1 -0
  116. package/dist/render/trendDocs.js +445 -0
  117. package/dist/render/trendDocs.js.map +1 -0
  118. package/dist/render/trendMiscPort.d.ts +127 -0
  119. package/dist/render/trendMiscPort.d.ts.map +1 -0
  120. package/dist/render/trendMiscPort.js +277 -0
  121. package/dist/render/trendMiscPort.js.map +1 -0
  122. package/dist/render/trendMiscPortDocs.d.ts +10 -0
  123. package/dist/render/trendMiscPortDocs.d.ts.map +1 -0
  124. package/dist/render/trendMiscPortDocs.js +397 -0
  125. package/dist/render/trendMiscPortDocs.js.map +1 -0
  126. package/dist/render/wizardPort.d.ts +125 -0
  127. package/dist/render/wizardPort.d.ts.map +1 -0
  128. package/dist/render/wizardPort.js +393 -0
  129. package/dist/render/wizardPort.js.map +1 -0
  130. package/dist/render/wizardPortDocs.d.ts +6 -0
  131. package/dist/render/wizardPortDocs.d.ts.map +1 -0
  132. package/dist/render/wizardPortDocs.js +274 -0
  133. package/dist/render/wizardPortDocs.js.map +1 -0
  134. package/dist/triggers/routing.d.ts +141 -0
  135. package/dist/triggers/routing.d.ts.map +1 -0
  136. package/dist/triggers/routing.js +678 -0
  137. package/dist/triggers/routing.js.map +1 -0
  138. package/package.json +5 -3
  139. package/templates/diet.html +40 -0
  140. package/templates/exercise.html +40 -0
  141. package/templates/goal.html +40 -0
  142. package/templates/help.html +40 -0
  143. package/templates/home.html +40 -0
  144. package/templates/photo-gallery.html +40 -0
package/dist/output.js ADDED
@@ -0,0 +1,305 @@
1
+ /** #87 · 输出命名规范复刻(M10 · 手册 §4.1 跨 Skill 通用 · 旧基线逐行对照)。
2
+ *
3
+ * 旧版真值(只读基线 `D:\2Study\StudyNotes\SKILLS\卡路里\scripts\html_paths.py`):
4
+ * - `html_dir()` → `DATA_DIR / "calorie_html"`(`DATA_DIR = find_db_path().parent`,跟随 `SKILLS_DB_PATH`)
5
+ * - `html_name()` → `<command>_<YYYYMMDD>_<HHMMSS>.html`;同秒已有 N 个同名 → 追加 `_(N+1)`(首个冲突 `_2`)
6
+ * - `html_path()` → 一步到位:目录不存在则递归创建
7
+ * - `--output` → 显式路径覆盖,绕过命名规则(旧 `SKILL.md` L104「仍可显式覆盖到任意路径」)
8
+ * - `_sanitize_filename_part()` → `\\ / : * ? " < > | [ ]` → `_`、去前后空格、截断 32 字符
9
+ *
10
+ * 新架构 `<中文command>` 真值来源(#87 侦察结论)= `CALORIE_COMBOS[key].title`
11
+ * (`packages/base-combos/combos.yaml` 同值镜像,两处逐键一致;见 `test/output-naming-87.test.mjs`)。
12
+ * 不取 triggers 的 `wake_word`:唤醒词是用户话术(含空格/括号,如「看体重 vs 摄入(最近 7 天)」),
13
+ * 且与 CLI 组合键非一一对应(一场景多唤醒词),做不了「一个键一个命令名」。
14
+ *
15
+ * 与老家的有意偏离(逐条见 `docs/research/t87-*.md` 偏离记账):
16
+ * 1. 默认落盘改由 CLI 出口(`cli/cmd_read.ts`)执行,本模块只出路径,不做 IO 副作用判断;
17
+ * 2. 同秒冲突用 `readdirSync` + `startsWith` 计数,不用 `glob`——命令名已 sanitize,无 `[]` 元字符,
18
+ * 语义等价且不引入依赖;
19
+ * 3. 显式 `--output` 路径自动建父目录(老家直接 `open()` 会 ENOENT);对旧行为是超集。
20
+ */
21
+ import { mkdirSync, readdirSync, writeFileSync } from 'node:fs';
22
+ import { dirname, join, resolve } from 'node:path';
23
+ import { CALORIE_COMBOS } from './cli/keys.js';
24
+ import { CalorieRenderError } from './render/errors.js';
25
+ import { resolveDbDir } from './paths.js';
26
+ export const HTML_DIR_NAME = 'calorie_html';
27
+ export const HTML_EXT = '.html';
28
+ /** 旧版 `_sanitize_filename_part` 逐字复刻:非法字符 → `_`、trim、截断 32 字符(按字符,中文/emoji 安全)。
29
+ *
30
+ * #87 返修 F1(A2 S2-1):截断必须按 **Unicode 码点**(旧 Python `s[:32]` 语义),不得按 UTF-16 码元。
31
+ * 按码元切会把代理对劈成孤立代理项:落盘时文件系统把它换成 U+FFFD,而 `data.output` 回传的仍是
32
+ * 带 `\ud83d` 的原串 → **回传路径 ≠ 实际落盘文件**。`[...s]` 按码点迭代后再 `slice`,逐字对齐旧版。
33
+ */
34
+ export function sanitizeFilenamePart(text) {
35
+ if (text === null || text === undefined)
36
+ return '';
37
+ let s = String(text).trim();
38
+ for (const ch of '\\/:*?"<>|[]')
39
+ s = s.split(ch).join('_');
40
+ return [...s].slice(0, 32).join('');
41
+ }
42
+ /** 旧版 `datetime.now().strftime("%Y%m%d_%H%M%S")` 等价物(本地时区,零填充)。 */
43
+ export function formatStamp(now) {
44
+ const p = (n) => String(n).padStart(2, '0');
45
+ return (String(now.getFullYear()) +
46
+ p(now.getMonth() + 1) +
47
+ p(now.getDate()) +
48
+ '_' +
49
+ p(now.getHours()) +
50
+ p(now.getMinutes()) +
51
+ p(now.getSeconds()));
52
+ }
53
+ /** `<中文command>` 真值:注册表 `title`(未注册即抛,缺失阻断不返空)。 */
54
+ export function chineseCommandFor(key) {
55
+ const hit = CALORIE_COMBOS[key];
56
+ if (!hit || typeof hit.title !== 'string' || hit.title.length === 0) {
57
+ throw new CalorieRenderError('bad-input', '无中文 command 名(未注册键):' + key);
58
+ }
59
+ return sanitizeFilenamePart(hit.title);
60
+ }
61
+ /** 同秒冲突计数:`<command>_<stamp>*.html`(旧版 `glob` 语义;目录不存在视为 0)。
62
+ *
63
+ * #87 返修 F2(A2 S2-2):旧 `glob.glob()` 在 Windows 下走 `fnmatch.filter` → `os.path.normcase`,
64
+ * 文件名匹配**大小写不敏感**(`..._123000.HTML` 同样计入冲突)。故此处两侧 `toLowerCase()` 后比较:
65
+ * 否则目录内已有 `X.HTML` 时会再选 `X.html`,在 Windows 上**直接覆盖原文件**。
66
+ */
67
+ function countSameSecond(dir, command, stamp) {
68
+ let names;
69
+ try {
70
+ names = readdirSync(dir);
71
+ }
72
+ catch {
73
+ return 0;
74
+ }
75
+ const prefix = (command + '_' + stamp).toLowerCase();
76
+ const ext = HTML_EXT.toLowerCase();
77
+ return names.filter((n) => {
78
+ const lower = n.toLowerCase();
79
+ return lower.startsWith(prefix) && lower.endsWith(ext);
80
+ }).length;
81
+ }
82
+ /** 旧版 `html_name()`:只出文件名 `<command>_<stamp>[_N].html`,冲突时 `N = 同秒已有数 + 1`。 */
83
+ export function htmlFileName(command, opts) {
84
+ const stamp = formatStamp(opts.now);
85
+ const n = countSameSecond(opts.dir, command, stamp);
86
+ return n === 0
87
+ ? command + '_' + stamp + HTML_EXT
88
+ : command + '_' + stamp + '_' + String(n + 1) + HTML_EXT;
89
+ }
90
+ /** 旧版 `html_dir()`:`<SKILLS_DB_PATH>/calorie_html`,递归创建。 */
91
+ export function htmlDir(dbDir = resolveDbDir()) {
92
+ const d = join(dbDir, HTML_DIR_NAME);
93
+ mkdirSync(d, { recursive: true });
94
+ return d;
95
+ }
96
+ /** 旧版 `html_path()`:`<SKILLS_DB_PATH>/calorie_html/<中文command>_<stamp>[_N].html`(完整可写路径)。
97
+ * #119 · 按段拼接:`<覆盖|title>[_回执][_动态段][_内容标识]_<TS>[_N].html`
98
+ * (旧 `html_scene_path()` 类型段 + `_cmd_maps.py` 动态段 + `html_name(suffix=)` 内容标识段)。 */
99
+ export function resolveDefaultHtmlPath(key, opts = {}) {
100
+ const d = htmlDir(opts.dbDir ?? resolveDbDir());
101
+ const segs = [LEGACY_COMMAND_OVERRIDES[key] ?? chineseCommandFor(key)];
102
+ const type = sceneTypeFor(key);
103
+ if (type)
104
+ segs.push(OUTPUT_TYPE_LABELS[type]);
105
+ const dyn = dynamicSegmentFor(key, opts.params ?? {});
106
+ if (dyn)
107
+ segs.push(dyn);
108
+ const suf = opts.suffix ? sanitizeFilenamePart(opts.suffix) : '';
109
+ if (suf)
110
+ segs.push(suf);
111
+ return join(d, htmlFileName(segs.join('_'), { dir: d, now: opts.now ?? new Date() }));
112
+ }
113
+ /** 显式 `--output` / `--html` 落点:命名规则不参与,只保证父目录存在。 */
114
+ export function resolveExplicitHtmlPath(file) {
115
+ mkdirSync(dirname(file), { recursive: true });
116
+ return file;
117
+ }
118
+ /* ── #83 · 三态交付:落盘/只读回退(M4「必须渲染并打开」的机械保证) ───────────────────────── */
119
+ /** 只读/沙箱类写失败码 → ② 内联态(产物随 envelope 回传,绝不因写不进去而文字答)。
120
+ * **结构错**(`EEXIST`/`ENOTDIR`/`EISDIR`/`ENAMETOOLONG` 等)**不**回退:那是落点本身非法,
121
+ * 按旧契约走「渲染失败回执」(exit 5),避免把用户笔误静默变成另一种交付形态。 */
122
+ export const READONLY_WRITE_CODES = ['EACCES', 'EPERM', 'EROFS', 'EBUSY'];
123
+ export function isReadOnlyWriteFailure(e) {
124
+ const code = e?.code;
125
+ return typeof code === 'string' && READONLY_WRITE_CODES.includes(code);
126
+ }
127
+ /** 交付一次 HTML 产物(**唯一落盘点**):
128
+ * - `target` 显式给定时逐字写该路径(回执落点);否则 `explicit`(`--output`/`--html`)>
129
+ * 默认 `<SKILLS_DB_PATH>/calorie_html/<中文command>_<TS>[_N].html`;
130
+ * - 只读类失败 → `{mode:'inline'}`(调用方把产物随 envelope 回传);其余失败**原样抛出**(走回执)。
131
+ * 落点**解析**与写入同在一个 try 内:`calorie_html` 被同名文件占位等解析期失败同样归类(#87 返修 F4)。 */
132
+ export function deliverHtml(input) {
133
+ const bytes = Buffer.byteLength(input.html, 'utf8');
134
+ try {
135
+ const target = input.target ?? input.explicit ?? resolveDefaultHtmlPath(input.key, {
136
+ params: input.params,
137
+ suffix: writeSuffixFor(input.key, input.params),
138
+ now: input.now,
139
+ });
140
+ // #83 返修 R-1(红队 S1):落点可为**相对路径**(`SKILLS_DB_PATH` 本身可为相对,`--output` 亦文档化为
141
+ // 「任意路径」),而 `delivery.path` 契约要求绝对路径。此前把原样字符串回传 → `buildDelivery` 抛
142
+ // `bad-input` → **产物已写盘却 exit 2**。此处与 `writeFileSync` 同口径 `resolve`(写的就是它),
143
+ // 只归一化回传值,落盘行为与旧版逐字一致。
144
+ const written = resolve(target);
145
+ writeFileSync(resolveExplicitHtmlPath(written), input.html, 'utf8');
146
+ return { mode: 'file', path: written, bytes };
147
+ }
148
+ catch (e) {
149
+ if (isReadOnlyWriteFailure(e))
150
+ return { mode: 'inline', reason: e.message, bytes };
151
+ throw e;
152
+ }
153
+ }
154
+ /** #83 · 回执落点:`<SKILLS_DB_PATH>/calorie_html/<中文command>_<TS>[_N].html`(旧 `render_error_receipt.py`
155
+ * 的 `COMMAND_CN = '操作失败'` 逐字对齐;回执本身也走三态,写不进去即内联)。 */
156
+ export function resolveReceiptHtmlPath(command = '操作失败', now = new Date()) {
157
+ const d = htmlDir();
158
+ return join(d, htmlFileName(command, { dir: d, now }));
159
+ }
160
+ /** #119 · 旧 `html_scene_path()` 的「类型中文」段真值(`html_paths.py` OUTPUT_TYPE_LABELS)。 */
161
+ export const OUTPUT_TYPE_LABELS = { process: '过程', result: '结果', receipt: '回执' };
162
+ /** #119 · 该键的旧版类型段:写键一律 `receipt`(旧 `render_*_receipt.py` 全部走 `html_scene_path(..., 'receipt')`);
163
+ * 视图键**默认不加段**(旧视图多数走 `html_path()` 无类型段,只有少数走场景命名,须逐键核对旧脚本后登记)。 */
164
+ export function sceneTypeFor(key) {
165
+ const hit = CALORIE_COMBOS[key];
166
+ return hit?.shape === 'receipt' ? 'receipt' : null;
167
+ }
168
+ /** #119 · 旧 `html_path()` 实参与注册表 `title` 不同的键(逐键核对旧脚本后登记)。
169
+ * `calorie.view.ranking`:旧 `render_food_ranking.py` 用 `'食物排行_' + FOOD_RANKING_CATEGORY_MAP[category]`
170
+ * (`title` 为 `食品排行`,差一字;同秒五榜+全榜互撞的根因,见 `docs/research/t87-output-naming.md` §5.1)。 */
171
+ export const LEGACY_COMMAND_OVERRIDES = {
172
+ 'calorie.view.ranking': '食物排行',
173
+ };
174
+ /** #119 · 旧 `_cmd_maps.py` 的动态参数中文化映射(逐表复刻;未命中即不加段)。
175
+ * 只收录新架构确有同名参数且旧映射无歧义的两张表;其余旧动态场景(体重历史日期驱动、
176
+ * 运动汇总 mode、饮食复盘 type 等)在新分发中无对应参数或已被合并,记残留(见 `docs/research/t119-dynamic-suffix.md`)。 */
177
+ export const DYNAMIC_COMMAND_SEGMENTS = {
178
+ 'calorie.view.ranking': {
179
+ high_calorie: '高热量', low_calorie: '低热量', frequent: '常吃', high_carb: '高碳水', high_protein: '高蛋白', all: '全部',
180
+ },
181
+ 'calorie.view.contraindication': { 腰: '腰', 膝: '膝', 肩: '肩', all: '全部' },
182
+ };
183
+ /** #119 · 动态段:ranking 取 `category`、contraindication 取 `part`;缺省 `all`;旧表未命中 → 不加段。 */
184
+ export function dynamicSegmentFor(key, params) {
185
+ const table = DYNAMIC_COMMAND_SEGMENTS[key];
186
+ if (!table)
187
+ return '';
188
+ const raw = key === 'calorie.view.ranking' ? (params['category'] ?? 'all') : (params['part'] ?? 'all');
189
+ const v = raw === undefined || raw === null ? 'all' : String(raw);
190
+ return sanitizeFilenamePart(table[v] ?? '');
191
+ }
192
+ /** #119 · 旧版 `html_name(suffix=)`/`html_scene_path(suffix=)` 的内容标识段(issue #49/#266/#284/#286 拍板)。
193
+ * 纯 params 派生(落点解析在写库前后均可调用,不读库):需要写后回执值的键(删饮食/删食品/
194
+ * 下架食品/删身材照/id 删体重/删体脂/删围度)返回 '',记残留(见 `docs/research/t119-dynamic-suffix.md`)。
195
+ * 返回值未经 sanitize(由调用方 `resolveDefaultHtmlPath` 统一清洗+截断 32 码点)。 */
196
+ export function writeSuffixFor(key, params) {
197
+ const str = (...names) => {
198
+ for (const n of names) {
199
+ const v = params[n];
200
+ if (typeof v === 'string' && v.trim().length > 0)
201
+ return v.trim();
202
+ }
203
+ return '';
204
+ };
205
+ /** YYYY-MM-DD → YYYYMMDD(旧 `str(date).replace('-', '')`);非法格式原样返回(sanitize 兜底)。 */
206
+ const compactDate = (v) => typeof v === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(v) ? v.replace(/-/g, '') : (typeof v === 'string' ? v : '');
207
+ /** 旧 `format(float(x), 'g')`:去尾零(68.0→'68'、70.5→'70.5');非有限 number → ''。 */
208
+ const numG = (v) => typeof v === 'number' && Number.isFinite(v) ? String(v) : '';
209
+ const firstItem = () => {
210
+ const items = params['items'];
211
+ if (!Array.isArray(items) || items.length === 0)
212
+ return {};
213
+ const o = items[0];
214
+ return typeof o === 'object' && o !== null ? o : {};
215
+ };
216
+ const batchCount = () => (Array.isArray(params['items']) ? params['items'].length : 0);
217
+ switch (key) {
218
+ case 'calorie.diet.add':
219
+ case 'calorie.diet.update':
220
+ return str('foodName', 'food_name'); // 旧:记一餐带食物名(#49)/改后名(#266 Q4A)
221
+ case 'calorie.diet.batch': {
222
+ const first = firstItem();
223
+ const food = typeof first['foodName'] === 'string' && first['foodName'].trim()
224
+ ? String(first['foodName']).trim()
225
+ : (typeof first['food_name'] === 'string' ? String(first['food_name']).trim() : '');
226
+ if (!food)
227
+ return '';
228
+ const n = batchCount();
229
+ return n > 1 ? food + '等' + n + '项' : food; // 旧 #266 Q1A:首食物+等N项
230
+ }
231
+ case 'calorie.diet.copy':
232
+ return compactDate(params['from'] ?? params['fromDate']); // 旧 #266 Q2A:源日期
233
+ case 'calorie.diet.update-by-date':
234
+ case 'calorie.diet.remove-by-date':
235
+ return compactDate(params['date']); // 旧:目标日期
236
+ case 'calorie.diet.remove-by-range':
237
+ return compactDate(params['start']) && compactDate(params['end'])
238
+ ? compactDate(params['start']) + '至' + compactDate(params['end']) : ''; // 旧:起止范围
239
+ case 'calorie.diet.remove-by-type':
240
+ return compactDate(params['date']) + str('mealType'); // 旧:日期+餐别
241
+ case 'calorie.water.log':
242
+ return numG(params['ml']) ? numG(params['ml']) + 'ml' : ''; // 旧 #284 Q1A:毫升
243
+ case 'calorie.weight.log':
244
+ return numG(params['kg']) ? numG(params['kg']) + 'kg' : ''; // 旧 #286:体重值
245
+ case 'calorie.weight.update':
246
+ return compactDate(params['date']) || (numG(params['kg']) ? numG(params['kg']) + 'kg' : ''); // 旧 #284 Q3A:日期
247
+ case 'calorie.weight.remove':
248
+ if (typeof params['date'] === 'string')
249
+ return compactDate(params['date']);
250
+ if (typeof params['start'] === 'string' && typeof params['end'] === 'string') {
251
+ return compactDate(params['start']) + '至' + compactDate(params['end']);
252
+ }
253
+ return ''; // id 删:旧带记录日期(需读库),记残留
254
+ case 'calorie.weight.batch': {
255
+ const first = firstItem();
256
+ const kg = numG(first['kg']);
257
+ if (!kg)
258
+ return '';
259
+ const n = batchCount();
260
+ return n > 1 ? kg + 'kg等' + n + '项' : kg + 'kg'; // 旧 #286:首条体重+等N项
261
+ }
262
+ case 'calorie.exercise.add': {
263
+ if (params['copyFrom'] !== undefined)
264
+ return ''; // 旧带源日期(需读库),记残留
265
+ if (params['items'] !== undefined) {
266
+ const first = firstItem();
267
+ const t = typeof first['type'] === 'string' && first['type'].trim()
268
+ ? String(first['type']).trim()
269
+ : (typeof first['exerciseType'] === 'string' ? String(first['exerciseType']).trim() : '');
270
+ if (!t)
271
+ return '';
272
+ const n = batchCount();
273
+ return n > 1 ? t + '等' + n + '项' : t;
274
+ }
275
+ return str('type', 'exerciseType'); // 旧 render_exercise_receipt:运动类型
276
+ }
277
+ case 'calorie.exercise.update':
278
+ return compactDate(params['date']) || str('type', 'exerciseType');
279
+ case 'calorie.exercise.remove':
280
+ if (typeof params['date'] === 'string')
281
+ return compactDate(params['date']);
282
+ if (typeof params['from'] === 'string' && typeof params['to'] === 'string') {
283
+ return compactDate(params['from']) + '至' + compactDate(params['to']);
284
+ }
285
+ return '';
286
+ case 'calorie.photo.add':
287
+ return str('tag'); // 旧 body_photo_receipt:标签/首项内容
288
+ case 'calorie.photo.tag': {
289
+ const raw = params['tags'] ?? params['tag'];
290
+ if (Array.isArray(raw)) {
291
+ const tags = raw.map(String).filter((t) => t.trim().length > 0);
292
+ return tags.length > 0 ? tags.join('、') : ''; // 旧:'、'.join
293
+ }
294
+ return str('tag');
295
+ }
296
+ case 'calorie.product.add':
297
+ case 'calorie.product.update':
298
+ return str('productName', 'product_name'); // 旧 #284 Q2A:食品名
299
+ case 'calorie.photo.gif':
300
+ return str('tag'); // 旧 gif_planner:tag+数量(数量需读库,记残留)
301
+ default:
302
+ return '';
303
+ }
304
+ }
305
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /** 页面侧复制运行时(**逐字**等于 base-paint 唯一产出者的产出,禁本地改写)。 */
2
+ export declare const COPY_RUNTIME_JS: string;
3
+ /** 页面侧运行时的 `<script>` 包裹(页面模板/片段尾部注入;运行时自身幂等,重复注入等价一次)。 */
4
+ export declare function copyRuntimeScriptHtml(): string;
5
+ /** 复制目标的 actionId/文案(冻结表取用,缺省「复制指令」)。 */
6
+ export declare const CALORIE_COPY_ACTION: {
7
+ readonly actionId: string;
8
+ readonly label: string;
9
+ };
10
+ /** 单个复制按钮(走 `renderActionBar` 的 ghost 复制行;`text` 渲染期写入 `DEFAULT_DATA_ATTR`)。 */
11
+ export declare function copyActionHtml(text: string, action?: {
12
+ readonly actionId: string;
13
+ readonly label: string;
14
+ }): string;
15
+ /** 页面内复制按钮的承载属性名(供测试与调用方断言,恒读冻结常量)。 */
16
+ export declare const COPY_BUTTON_ATTRS: Readonly<{
17
+ readonly actionId: "data-action-id";
18
+ readonly text: "data-t";
19
+ }>;
20
+ //# sourceMappingURL=copy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.d.ts","sourceRoot":"","sources":["../../src/render/copy.ts"],"names":[],"mappings":"AAyBA,oDAAoD;AACpD,eAAO,MAAM,eAAe,EAAE,MAA+B,CAAC;AAE9D,2DAA2D;AAC3D,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED,yCAAyC;AACzC,eAAO,MAAM,mBAAmB,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAA6B,CAAC;AAEnH,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAwB,GAAG,MAAM,CAExI;AAED,uCAAuC;AACvC,eAAO,MAAM,iBAAiB;;;EAGnB,CAAC"}
@@ -0,0 +1,36 @@
1
+ /** #90 · 复制交互接线(裁决 Q13/AC-16①/契约 §3.3):**只消费** base-paint 的复制面。
2
+ *
3
+ * 本文件是「复制交互走 Base P0 双通道」在 skill-calorie 侧的**唯一接线点**,三件东西:
4
+ * ① 页面侧运行时 = `buildSharedHelpersJs()` 的**产出文本**(base-paint 唯一产出者,B3 禁技能侧自产);
5
+ * 它自带双通道(`navigator.clipboard` → `execCommand` 兜底)+ toast 反馈 +
6
+ * `[data-action-id]` 事件委派(激活时读 `data-t`,零内联 `onclick`)。
7
+ * ② 复制按钮 = `renderActionBar({ copyData })` 的**产出 HTML**(不手写按钮、不自造承载属性)。
8
+ * ③ actionId = 冻结表 `HELP_COPY_ACTIONS`(不自造命名;页面内重复由 R27 记账——见下)。
9
+ *
10
+ * 为什么不自己写复制:契约 §6.3「不许自造」明列「只留 `execCommand` 的单通道复制(Q13)」
11
+ * 「第二套共享 JS 产出者(唯一产出者 `buildSharedHelpersJs`)」「自造复制按钮 actionId 或承载属性」。
12
+ *
13
+ * 页面内 actionId 重复的口径(#78 记账 R27):HELP 速查列表每行一个「复制指令」按钮,
14
+ * 逐行写**同一个**冻结 id(`HELP_COPY_ACTIONS.prompt`),与 §3.5.3「每张场景卡逐字写入三个
15
+ * 复制目标 actionId」同形;歧义由**页面侧** helpers 委派解决——它读的是**被点击元素**的
16
+ * `data-t`,不做 id → 元素的反查。`CopyActionHostPort.listActionIds()` 允许含重复(自行去重)。
17
+ */
18
+ import { ACTION_ID_ATTR, DEFAULT_DATA_ATTR, HELP_COPY_ACTIONS, buildSharedHelpersJs, renderActionBar, } from 'base-paint';
19
+ /** 页面侧复制运行时(**逐字**等于 base-paint 唯一产出者的产出,禁本地改写)。 */
20
+ export const COPY_RUNTIME_JS = buildSharedHelpersJs();
21
+ /** 页面侧运行时的 `<script>` 包裹(页面模板/片段尾部注入;运行时自身幂等,重复注入等价一次)。 */
22
+ export function copyRuntimeScriptHtml() {
23
+ return '<script>' + COPY_RUNTIME_JS + '</script>';
24
+ }
25
+ /** 复制目标的 actionId/文案(冻结表取用,缺省「复制指令」)。 */
26
+ export const CALORIE_COPY_ACTION = HELP_COPY_ACTIONS.prompt;
27
+ /** 单个复制按钮(走 `renderActionBar` 的 ghost 复制行;`text` 渲染期写入 `DEFAULT_DATA_ATTR`)。 */
28
+ export function copyActionHtml(text, action = CALORIE_COPY_ACTION) {
29
+ return renderActionBar({ copyData: { actionId: action.actionId, label: action.label, text } });
30
+ }
31
+ /** 页面内复制按钮的承载属性名(供测试与调用方断言,恒读冻结常量)。 */
32
+ export const COPY_BUTTON_ATTRS = Object.freeze({
33
+ actionId: ACTION_ID_ATTR,
34
+ text: DEFAULT_DATA_ATTR,
35
+ });
36
+ //# sourceMappingURL=copy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy.js","sourceRoot":"","sources":["../../src/render/copy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,oDAAoD;AACpD,MAAM,CAAC,MAAM,eAAe,GAAW,oBAAoB,EAAE,CAAC;AAE9D,2DAA2D;AAC3D,MAAM,UAAU,qBAAqB;IACnC,OAAO,UAAU,GAAG,eAAe,GAAG,WAAW,CAAC;AACpD,CAAC;AAED,yCAAyC;AACzC,MAAM,CAAC,MAAM,mBAAmB,GAA0D,iBAAiB,CAAC,MAAM,CAAC;AAEnH,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,SAAgE,mBAAmB;IAC9H,OAAO,eAAe,CAAC,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;AACjG,CAAC;AAED,uCAAuC;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7C,QAAQ,EAAE,cAAc;IACxB,IAAI,EAAE,iBAAiB;CACf,CAAC,CAAC"}
@@ -0,0 +1,45 @@
1
+ /** 明细行最小形(fetch MealRow 的子集;调用方传全行亦可)。 */
2
+ export interface DietMealRow {
3
+ readonly date: string;
4
+ readonly time: string | null;
5
+ readonly food_name: string;
6
+ readonly grams: number;
7
+ readonly calories: number;
8
+ readonly protein: number;
9
+ readonly carbs: number;
10
+ readonly fat: number;
11
+ readonly note?: string | null;
12
+ }
13
+ import type { DaySeries } from '../analysis/series.js';
14
+ import type { FoodRanking, MacroRatio } from '../analysis/diet.js';
15
+ import type { DietOverview, MealDistribution } from './diet.js';
16
+ import type { DietReview } from './analysisPlate.js';
17
+ import type { AllRankings } from './ranking.js';
18
+ import type { HealthPlate } from './health.js';
19
+ import type { DedupeView } from './insightPlate.js';
20
+ import type { ProductLibrary, ProductSearch } from './library.js';
21
+ export interface TodayDietDocInput {
22
+ overview: DietOverview;
23
+ dist: MealDistribution;
24
+ meals: DietMealRow[];
25
+ macro: MacroRatio | null;
26
+ }
27
+ export declare function buildTodayDietDoc(input: TodayDietDocInput): string;
28
+ export interface ViewDietDocInput {
29
+ overview: DietOverview;
30
+ dist: MealDistribution;
31
+ distDate: string;
32
+ days: DaySeries[];
33
+ meals: DietMealRow[];
34
+ mealTotal: number;
35
+ mealsTruncated: boolean;
36
+ }
37
+ export declare function buildViewDietDoc(input: ViewDietDocInput): string;
38
+ export declare function buildDietReviewDoc(r: DietReview, top5: FoodRanking | null): string;
39
+ export declare function buildRankingDoc(r: FoodRanking): string;
40
+ export declare function buildAllRankingsDoc(a: AllRankings): string;
41
+ export declare function buildSearchDoc(s: ProductSearch): string;
42
+ export declare function buildLibraryDoc(lib: ProductLibrary, statsTotal: number): string;
43
+ export declare function buildHealthDoc(h: HealthPlate): string;
44
+ export declare function buildDedupeDoc(v: DedupeView): string;
45
+ //# sourceMappingURL=dietDocs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dietDocs.d.ts","sourceRoot":"","sources":["../../src/render/dietDocs.ts"],"names":[],"mappings":"AAgCA,0CAA0C;AAC1C,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AACD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAuDlE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,YAAY,CAAC;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;CAC1B;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAiElE;AAID,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,YAAY,CAAC;IACvB,IAAI,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;CACzB;AAcD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CA+EhE;AAID,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,MAAM,CAiFlF;AAmBD,wBAAgB,eAAe,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAsCtD;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAuC1D;AAeD,wBAAgB,cAAc,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAyBvD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CA2B/E;AAWD,wBAAgB,cAAc,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CA6DrD;AAID,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAwCpD"}