base-paint 0.3.0 → 0.3.2
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/README.md +8 -0
- package/dist/blocks.d.ts +143 -6
- package/dist/blocks.d.ts.map +1 -1
- package/dist/blocks.js +1060 -35
- package/dist/blocks.js.map +1 -1
- package/dist/charts.d.ts +6 -4
- package/dist/charts.d.ts.map +1 -1
- package/dist/charts.js +378 -64
- package/dist/charts.js.map +1 -1
- package/dist/controls.d.ts +20 -5
- package/dist/controls.d.ts.map +1 -1
- package/dist/controls.js +246 -34
- package/dist/controls.js.map +1 -1
- package/dist/font.d.ts +12 -0
- package/dist/font.d.ts.map +1 -0
- package/dist/font.js +12 -0
- package/dist/font.js.map +1 -0
- package/dist/help.d.ts +3 -3
- package/dist/help.js +12 -12
- package/dist/help.js.map +1 -1
- package/dist/helpShell.d.ts +57 -0
- package/dist/helpShell.d.ts.map +1 -0
- package/dist/helpShell.js +65 -0
- package/dist/helpShell.js.map +1 -0
- package/dist/index.d.ts +10 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/injector.d.ts +1 -1
- package/dist/output/saveHtml.d.ts +64 -0
- package/dist/output/saveHtml.d.ts.map +1 -0
- package/dist/output/saveHtml.js +339 -0
- package/dist/output/saveHtml.js.map +1 -0
- package/dist/pageShapes.d.ts +117 -0
- package/dist/pageShapes.d.ts.map +1 -0
- package/dist/pageShapes.js +366 -0
- package/dist/pageShapes.js.map +1 -0
- package/dist/pageUi.d.ts +37 -0
- package/dist/pageUi.d.ts.map +1 -0
- package/dist/pageUi.js +237 -0
- package/dist/pageUi.js.map +1 -0
- package/dist/spec/charts.d.ts +12 -3
- package/dist/spec/charts.d.ts.map +1 -1
- package/dist/spec/charts.js +1 -1
- package/dist/spec/charts.js.map +1 -1
- package/dist/spec/controls.d.ts +30 -5
- package/dist/spec/controls.d.ts.map +1 -1
- package/dist/spec/controls.js +14 -3
- package/dist/spec/controls.js.map +1 -1
- package/dist/spec/help.d.ts +4 -4
- package/dist/spec/help.d.ts.map +1 -1
- package/dist/spec/help.js +2 -2
- package/dist/spec/index.d.ts +6 -3
- package/dist/spec/index.d.ts.map +1 -1
- package/dist/spec/index.js +27 -2
- package/dist/spec/index.js.map +1 -1
- package/dist/style.d.ts.map +1 -1
- package/dist/style.js +283 -55
- package/dist/style.js.map +1 -1
- package/package.json +6 -2
package/dist/style.js
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* (`:root` 改写/Q14 禁入项/深色区 → 抛不导出的 `StyleSheetError`;D3 修订见 §8.11)。
|
|
17
17
|
*/
|
|
18
18
|
import { chartsCss } from './charts.js';
|
|
19
|
+
import { BODY_FONT_STACK } from './font.js';
|
|
19
20
|
import { ACTION_BAR_DEFAULTS, TOAST_DEFAULTS } from './spec/index.js';
|
|
20
21
|
import { CONTROL_STYLE_SECTIONS, CSS_VAR_TOKENS, STYLE_FORBIDDEN_TOKENS, STYLE_SHEET_ID } from './spec/style.js';
|
|
21
22
|
export const STYLE_PREFIX = 'ilife-';
|
|
@@ -59,18 +60,13 @@ function rootBlock() {
|
|
|
59
60
|
lines.push('}');
|
|
60
61
|
return lines.join(LF);
|
|
61
62
|
}
|
|
62
|
-
/**
|
|
63
|
-
* 裁定 R7/施工单 B-D2(a)
|
|
63
|
+
/** 页级基础(非控件区):**本票不产**。
|
|
64
|
+
* 裁定 R7/施工单 B-D2(a):共享页面模板/KPI/表格/回到顶部等**无闭集归属**的样式归 #104
|
|
64
65
|
* (区块组件 owner),#75 只产 11 token + 8 个闭集样式区;`extraCss` 语义被
|
|
65
|
-
* 契约 doc:299-300 限死(只许技能作用域 token
|
|
66
|
+
* 契约 doc:299-300 限死(只许技能作用域 token 覆盖块),**不得**塞共享页面模板的样式。 */
|
|
66
67
|
/** 主色 alpha 派生(`ghostBorderAlpha` 等):RGB 与 `--blue` 同源(`#007aff`)。
|
|
67
68
|
* 这是**派生字面量**、不是第二份 token 表(不新增 token 名,doc:299)。 */
|
|
68
69
|
const BLUE_RGB = '0, 122, 255';
|
|
69
|
-
/** 正文栈(H-06:首位 `"SF Pro Display"`,后接系统兜底+`"Noto Sans SC"`)。
|
|
70
|
-
* **局部 CSS 常量**、不是 token(D-5 纪律:不新增 token 名);等宽栈不动(D-13,各 `font-family: "SF Mono", monospace` 原样保留)。
|
|
71
|
-
* B1 原栈见 `docs/research/benchmark-visual-spec.md:105`(`body`);按 #89 返修方案把 `"SF Pro Display"` 提首位、
|
|
72
|
-
* 尾部补 `"Noto Sans SC"`(修前正文 computed 回落实测,CJK 渲染不变);落点仅 `.ilife-help-shell`(T22:壳层样式归 #104,不得产 `body` 规则)。 */
|
|
73
|
-
const BODY_FONT_STACK = '"SF Pro Display", -apple-system, BlinkMacSystemFont, "PingFang SC", "Microsoft YaHei", "Noto Sans SC", sans-serif';
|
|
74
70
|
/** 焦点环(视觉尺 H-20 强制项):`:focus-visible` 覆盖全部可交互控件。 */
|
|
75
71
|
function focusRing(selector) {
|
|
76
72
|
return selector + ':focus-visible {' + LF + ' outline: 2px solid var(--blue);' + LF + ' outline-offset: 2px;' + LF + '}';
|
|
@@ -99,6 +95,13 @@ const SECTION_BUILDERS = {
|
|
|
99
95
|
// 时靠换行分层,代价是把关闭按钮挤到第三行)。根因已由 `controls.ts` 的结构对齐修掉
|
|
100
96
|
// (helpers 与静态产出器/旧层同构:`icon? + .toast-body(> .toast-title-row + detail) + .toast-close`),
|
|
101
97
|
// 补丁一并删除 → 关闭按钮与标题恒同行。
|
|
98
|
+
// 卡面色(2026-09-12 用户裁定改用**老技能**版):深色毛玻璃,逐值取自
|
|
99
|
+
// 老仓 `公共组件/assets/base.js:75` 的 `.hm-toast` 串——底色 rgba(28,28,30,.94)、
|
|
100
|
+
// 毛玻璃 blur(20px) saturate(180%)、主字 #f0f0f0、投影 0 10px 32px rgba(0,0,0,.32)
|
|
101
|
+
// + 0 0 0 .5px rgba(255,255,255,.08) inset(原样的「无描边、靠内影收边」)。
|
|
102
|
+
// 几何(圆角 14px/内距 13-14-16/min 300/max 480/gap 12)与老仓逐值相同,本次不动。
|
|
103
|
+
// 取字面量而非 token:本卡是**深色面**,不随浅色 token 变——这是本次的唯一例外,记账见
|
|
104
|
+
// `docs/visual-spec-blocks.md` §B-12 的 2026-09-12 裁定行。
|
|
102
105
|
'.' + p + 'toast {',
|
|
103
106
|
' display: flex;',
|
|
104
107
|
' align-items: flex-start;',
|
|
@@ -107,12 +110,14 @@ const SECTION_BUILDERS = {
|
|
|
107
110
|
' min-width: 300px;',
|
|
108
111
|
' max-width: 480px;',
|
|
109
112
|
' padding: 13px 14px 13px 16px;',
|
|
110
|
-
' border: 1px solid var(--line);',
|
|
111
113
|
' border-radius: 14px;',
|
|
112
|
-
' background:
|
|
113
|
-
'
|
|
114
|
-
'
|
|
115
|
-
'
|
|
114
|
+
' background: rgba(28, 28, 30, .94);',
|
|
115
|
+
' -webkit-backdrop-filter: blur(20px) saturate(180%);',
|
|
116
|
+
' backdrop-filter: blur(20px) saturate(180%);',
|
|
117
|
+
' color: #f0f0f0;',
|
|
118
|
+
' box-shadow: 0 10px 32px rgba(0, 0, 0, .32), 0 0 0 .5px rgba(255, 255, 255, .08) inset;',
|
|
119
|
+
// #567 J4(§5.2 正文 13 吸收 13/12.5)。
|
|
120
|
+
' font-size: 13px;',
|
|
116
121
|
' line-height: 1.4;',
|
|
117
122
|
' font-feature-settings: "tnum";',
|
|
118
123
|
' pointer-events: auto;',
|
|
@@ -131,13 +136,16 @@ const SECTION_BUILDERS = {
|
|
|
131
136
|
' transform: none;',
|
|
132
137
|
' }',
|
|
133
138
|
'}',
|
|
139
|
+
// 失败态:老仓没有卡面描边,失败由「❌ 图标 + danger 徽章」承担;深色面上改由
|
|
140
|
+
// **内影那条 0.5px 细线换成功色系的红**来点一句(不新增描边、不改底色)。
|
|
134
141
|
'.' + p + 'toast-danger {',
|
|
135
|
-
'
|
|
142
|
+
' box-shadow: 0 10px 32px rgba(0, 0, 0, .32), 0 0 0 .5px rgba(255, 59, 48, .45) inset;',
|
|
136
143
|
'}',
|
|
137
144
|
'.' + p + 'toast-icon {',
|
|
138
145
|
' flex: 0 0 auto;',
|
|
139
146
|
' padding-top: 1px;',
|
|
140
|
-
|
|
147
|
+
// #567 J4(§5.2 标题 18 吸收 17/18/20/22):装饰字形 20→18。
|
|
148
|
+
' font-size: 18px;',
|
|
141
149
|
' line-height: 1;',
|
|
142
150
|
'}',
|
|
143
151
|
// body 是 toast 的**唯一**内容列(静态产出器与 helpers 运行时同构,见 `controls.ts`
|
|
@@ -155,15 +163,16 @@ const SECTION_BUILDERS = {
|
|
|
155
163
|
'}',
|
|
156
164
|
'.' + p + 'toast-title {',
|
|
157
165
|
' margin-bottom: 2px;',
|
|
158
|
-
' color:
|
|
159
|
-
|
|
166
|
+
' color: #fff;',
|
|
167
|
+
// #567 J4(§5.2 正文 13 吸收 13/12.5)。
|
|
168
|
+
' font-size: 13px;',
|
|
160
169
|
' font-weight: 600;',
|
|
161
170
|
' line-height: 1.4;',
|
|
162
171
|
'}',
|
|
163
172
|
// 运行时详情(helpers 产出 `.ilife-toast-title-detail`,在 `.ilife-toast-body` 内):
|
|
164
173
|
// 与静态侧 `.ilife-toast-detail` **同排版**;此前的 `flex: 1 1 100%` 权宜补丁已随结构对齐删除。
|
|
165
174
|
'.' + p + 'toast-title-detail {',
|
|
166
|
-
' color:
|
|
175
|
+
' color: #c8c8cc;',
|
|
167
176
|
' font-size: 11px;',
|
|
168
177
|
' font-weight: 400;',
|
|
169
178
|
' line-height: 1.5;',
|
|
@@ -172,41 +181,44 @@ const SECTION_BUILDERS = {
|
|
|
172
181
|
' flex-shrink: 0;',
|
|
173
182
|
' padding: 2px 8px;',
|
|
174
183
|
' border-radius: 999px;',
|
|
175
|
-
' background:
|
|
176
|
-
' color:
|
|
177
|
-
|
|
184
|
+
' background: rgba(255, 255, 255, .12);',
|
|
185
|
+
' color: #c8c8cc;',
|
|
186
|
+
// #567 J4(§5.2 下限 11:10/10.5/11 一律抬到 11)。
|
|
187
|
+
' font-size: 11px;',
|
|
178
188
|
' font-weight: 700;',
|
|
179
189
|
' letter-spacing: .02em;',
|
|
180
190
|
' line-height: 1.6;',
|
|
181
191
|
'}',
|
|
182
192
|
'.' + p + 'toast-chip-ok {',
|
|
183
|
-
' background: rgba(52, 199, 89, .
|
|
184
|
-
' color: #
|
|
193
|
+
' background: rgba(52, 199, 89, .18);',
|
|
194
|
+
' color: #4dd96b;',
|
|
185
195
|
'}',
|
|
186
196
|
'.' + p + 'toast-chip-warn {',
|
|
187
|
-
' background: rgba(255, 149, 0, .
|
|
188
|
-
' color: #
|
|
197
|
+
' background: rgba(255, 149, 0, .18);',
|
|
198
|
+
' color: #ffb340;',
|
|
189
199
|
'}',
|
|
190
200
|
'.' + p + 'toast-chip-danger {',
|
|
191
|
-
' background: rgba(255, 59, 48, .
|
|
192
|
-
' color: #
|
|
201
|
+
' background: rgba(255, 59, 48, .18);',
|
|
202
|
+
' color: #ff6961;',
|
|
193
203
|
'}',
|
|
194
204
|
'.' + p + 'toast-count {',
|
|
195
205
|
' flex-shrink: 0;',
|
|
196
206
|
' padding: 2px 8px;',
|
|
197
207
|
' border-radius: 8px;',
|
|
198
|
-
'
|
|
199
|
-
'
|
|
208
|
+
' background: rgba(255, 255, 255, .08);',
|
|
209
|
+
' color: #c8c8cc;',
|
|
210
|
+
// #567 J4(§5.2 下限 11)。
|
|
211
|
+
' font-size: 11px;',
|
|
200
212
|
' font-weight: 700;',
|
|
201
213
|
' font-variant-numeric: tabular-nums;',
|
|
202
214
|
'}',
|
|
203
215
|
'.' + p + 'toast-detail {',
|
|
204
|
-
' color:
|
|
216
|
+
' color: #c8c8cc;',
|
|
205
217
|
' font-size: 11px;',
|
|
206
218
|
' line-height: 1.5;',
|
|
207
219
|
'}',
|
|
208
220
|
'.' + p + 'toast-lines {',
|
|
209
|
-
' color:
|
|
221
|
+
' color: #c8c8cc;',
|
|
210
222
|
' font-size: 11px;',
|
|
211
223
|
' line-height: 1.55;',
|
|
212
224
|
' white-space: pre-wrap;',
|
|
@@ -215,10 +227,11 @@ const SECTION_BUILDERS = {
|
|
|
215
227
|
' margin: 6px 0 0;',
|
|
216
228
|
' padding: 8px 10px;',
|
|
217
229
|
' border-radius: 8px;',
|
|
218
|
-
' background:
|
|
219
|
-
' color:
|
|
230
|
+
' background: rgba(0, 0, 0, .32);',
|
|
231
|
+
' color: #aeb0b8;',
|
|
220
232
|
' font-family: "SF Mono", monospace;',
|
|
221
|
-
|
|
233
|
+
// #567 J4(§5.2 下限 11)。
|
|
234
|
+
' font-size: 11px;',
|
|
222
235
|
' line-height: 1.5;',
|
|
223
236
|
' white-space: pre-wrap;',
|
|
224
237
|
' max-height: 140px;',
|
|
@@ -229,11 +242,13 @@ const SECTION_BUILDERS = {
|
|
|
229
242
|
' padding: 2px 4px;',
|
|
230
243
|
' border: 0;',
|
|
231
244
|
' background: none;',
|
|
232
|
-
' color:
|
|
245
|
+
' color: #4dd96b;',
|
|
233
246
|
' font-family: inherit;',
|
|
234
247
|
' font-size: 11px;',
|
|
235
248
|
' font-weight: 600;',
|
|
236
249
|
' cursor: pointer;',
|
|
250
|
+
' -webkit-tap-highlight-color: transparent;',
|
|
251
|
+
' touch-action: manipulation;',
|
|
237
252
|
'}',
|
|
238
253
|
'.' + p + 'toast-act:active {',
|
|
239
254
|
' opacity: .7;',
|
|
@@ -244,13 +259,16 @@ const SECTION_BUILDERS = {
|
|
|
244
259
|
' padding: 5px 9px;',
|
|
245
260
|
' border: 0;',
|
|
246
261
|
' border-radius: 8px;',
|
|
247
|
-
' background:
|
|
248
|
-
' color:
|
|
262
|
+
' background: rgba(255, 255, 255, .10);',
|
|
263
|
+
' color: #34c759;',
|
|
249
264
|
' font-family: inherit;',
|
|
250
|
-
|
|
265
|
+
// #567 J4(§5.2 下限 11)。
|
|
266
|
+
' font-size: 11px;',
|
|
251
267
|
' font-weight: 500;',
|
|
252
268
|
' white-space: nowrap;',
|
|
253
269
|
' cursor: pointer;',
|
|
270
|
+
' -webkit-tap-highlight-color: transparent;',
|
|
271
|
+
' touch-action: manipulation;',
|
|
254
272
|
'}',
|
|
255
273
|
focusRing('.' + p + 'toast-act'),
|
|
256
274
|
focusRing('.' + p + 'toast-close'),
|
|
@@ -276,9 +294,18 @@ const SECTION_BUILDERS = {
|
|
|
276
294
|
' gap: 8px;',
|
|
277
295
|
' box-sizing: border-box;',
|
|
278
296
|
' margin: 12px 0;',
|
|
297
|
+
// 旧层冻结值(旧 `base.css:81-91`)。它只在**窄档**用得上:窄屏内容列本来就不到 520px,这条不生效;
|
|
298
|
+
// 桌面档由下方那条媒体查询放开到内容列宽(#238 用户 2026-09-13 二次裁定)。
|
|
279
299
|
' max-width: 520px;',
|
|
280
|
-
'
|
|
281
|
-
|
|
300
|
+
'}',
|
|
301
|
+
// #238(用户 2026-09-13 二次裁定「两个按钮平分宽度」):桌面档**铺满内容列**,动作条里的整行
|
|
302
|
+
// (`.action-row-ghost` 的 `repeat(2, minmax(0, 1fr))`)随之按内容列平分——两颗按钮各占一半。
|
|
303
|
+
// 断点用样式表里既有的移动档分界 `TOAST_DEFAULTS.mobileMaxPx`(与 #249 那两处同源),
|
|
304
|
+
// 故 ≤820 的窄档逐像素不动。
|
|
305
|
+
'@media (min-width: ' + (TOAST_DEFAULTS.mobileMaxPx + 1) + 'px) {',
|
|
306
|
+
' .' + p + 'action-bar {',
|
|
307
|
+
' max-width: none;',
|
|
308
|
+
' }',
|
|
282
309
|
'}',
|
|
283
310
|
'.' + p + 'action-row {',
|
|
284
311
|
' display: grid;',
|
|
@@ -286,7 +313,18 @@ const SECTION_BUILDERS = {
|
|
|
286
313
|
' gap: 8px;',
|
|
287
314
|
'}',
|
|
288
315
|
'.' + p + 'action-row-ghost {',
|
|
289
|
-
|
|
316
|
+
// 复制按钮那一行**平分整行**(#247 用户 2026-09-12 返修):两列而不是单列——单列只在「一行一颗」时
|
|
317
|
+
// 才好看,一旦有第二颗(复制数据 + 复制日志)就变成「一颗铺满、一颗缩成内容宽」。列数取冻结
|
|
318
|
+
// `ACTION_BAR_DEFAULTS.evenRowPairs`(既有「偶数一行 2 个」的口径,不是新拍的数字)。
|
|
319
|
+
' grid-template-columns: repeat(' + ACTION_BAR_DEFAULTS.evenRowPairs + ', minmax(0, 1fr));',
|
|
320
|
+
'}',
|
|
321
|
+
// #249:窄屏那档菜单**以整行做锚点**(同档 `copyButton` 区把包裹层改成 `position: static`)——
|
|
322
|
+
// 行盒=内容宽,菜单 `left:0; right:0` 落进去就恒在视口内,与那颗按钮落在左格还是右格无关。
|
|
323
|
+
// 只在窄屏挂,桌面档的锚点仍是包裹层(菜单贴按钮右缘,用户已验收的样子不动)。
|
|
324
|
+
'@media (max-width: ' + TOAST_DEFAULTS.mobileMaxPx + 'px) {',
|
|
325
|
+
' .' + p + 'action-row-ghost {',
|
|
326
|
+
' position: relative;',
|
|
327
|
+
' }',
|
|
290
328
|
'}',
|
|
291
329
|
'.' + p + 'action-btn {',
|
|
292
330
|
' display: inline-flex;',
|
|
@@ -303,6 +341,8 @@ const SECTION_BUILDERS = {
|
|
|
303
341
|
' font-weight: ' + ACTION_BAR_DEFAULTS.fontWeight + ';',
|
|
304
342
|
' line-height: 1;',
|
|
305
343
|
' cursor: pointer;',
|
|
344
|
+
' -webkit-tap-highlight-color: transparent;',
|
|
345
|
+
' touch-action: manipulation;',
|
|
306
346
|
'}',
|
|
307
347
|
'.' + p + 'action-btn-primary {',
|
|
308
348
|
' background: var(--blue);',
|
|
@@ -315,7 +355,14 @@ const SECTION_BUILDERS = {
|
|
|
315
355
|
'.' + p + 'action-btn-ghost {',
|
|
316
356
|
' border-color: rgba(' + BLUE_RGB + ', ' + ACTION_BAR_DEFAULTS.ghostBorderAlpha + ');',
|
|
317
357
|
' background: var(--card);',
|
|
318
|
-
' color: var(--
|
|
358
|
+
' color: var(--blue2);',
|
|
359
|
+
'}',
|
|
360
|
+
// #179 触控目标:窄屏按钮抬到 44px。**#525 起两个宽档同值**(`minHeightPx` 40 → 44,见
|
|
361
|
+
// `spec/controls.ts`);本条留在这里只为不动既有选择器与既有媒体查询。
|
|
362
|
+
'@media (max-width: ' + TOAST_DEFAULTS.mobileMaxPx + 'px) {',
|
|
363
|
+
' .' + p + 'action-btn {',
|
|
364
|
+
' min-height: 44px;',
|
|
365
|
+
' }',
|
|
319
366
|
'}',
|
|
320
367
|
focusRing('.' + p + 'action-btn'),
|
|
321
368
|
].join(LF),
|
|
@@ -336,6 +383,8 @@ const SECTION_BUILDERS = {
|
|
|
336
383
|
' font-weight: ' + ACTION_BAR_DEFAULTS.fontWeight + ';',
|
|
337
384
|
' line-height: 1;',
|
|
338
385
|
' cursor: pointer;',
|
|
386
|
+
' -webkit-tap-highlight-color: transparent;',
|
|
387
|
+
' touch-action: manipulation;',
|
|
339
388
|
' transition: transform .45s cubic-bezier(.34, 1.56, .64, 1), background-color .2s ease;',
|
|
340
389
|
'}',
|
|
341
390
|
'.' + p + 'copy-btn-primary {',
|
|
@@ -345,7 +394,9 @@ const SECTION_BUILDERS = {
|
|
|
345
394
|
'.' + p + 'copy-btn-ghost {',
|
|
346
395
|
' border-color: rgba(' + BLUE_RGB + ', ' + ACTION_BAR_DEFAULTS.ghostBorderAlpha + ');',
|
|
347
396
|
' background: var(--card);',
|
|
348
|
-
|
|
397
|
+
// #179 对比度:ghost 按钮是 12px 小字,`--blue` 在白底上 4.02:1 不到 AA 的 4.5:1
|
|
398
|
+
// → 换同族深一档的 `--blue2`(5.6:1)。实心按钮(白字压 `--blue`)不在本页,另账见交付报告。
|
|
399
|
+
' color: var(--blue2);',
|
|
349
400
|
'}',
|
|
350
401
|
'.' + p + 'copy-btn-wide {',
|
|
351
402
|
' width: 100%;',
|
|
@@ -354,7 +405,7 @@ const SECTION_BUILDERS = {
|
|
|
354
405
|
' transform: scale(.96);',
|
|
355
406
|
'}',
|
|
356
407
|
// W3(H-16 双反馈的 CSS 侧):复制成功态变绿。规格 `docs/visual-spec-help.md:195,197`
|
|
357
|
-
// 「按钮变绿进入 `copied` 态并跑 450ms 弹簧动画」;弹簧 =
|
|
408
|
+
// 「按钮变绿进入 `copied` 态并跑 450ms 弹簧动画」;弹簧 = 基础 `transition: transform .45s
|
|
358
409
|
// cubic-bezier(.34, 1.56, .64, 1)`(B1 `benchmark-visual-spec.md:279,645`),本节只补**变绿**。
|
|
359
410
|
// 类名由**运行时**添加(`copied`,非 `ilife-` 前缀 → 不占样式区命名空间);
|
|
360
411
|
// 本票**不改** helpers 的复制反馈行为,移交落点见契约 §8.11.1 FX-75-11。
|
|
@@ -363,6 +414,172 @@ const SECTION_BUILDERS = {
|
|
|
363
414
|
' background: var(--ok);',
|
|
364
415
|
' color: var(--card);',
|
|
365
416
|
'}',
|
|
417
|
+
// **禁用态必须看得出来**(#525 收口 · 两处公共债之一):读页面没有写库日志,复制区按 #336
|
|
418
|
+
// 自动补的那颗「复制日志」带 `disabled` 属性、可**从 #336 起就没有任何置灰规则**——看着与
|
|
419
|
+
// 旁边那颗能点的按钮一模一样(`t524-改前读数.md` §7.1 第 3 条只核了属性、没核观感)。
|
|
420
|
+
//
|
|
421
|
+
// **#525 第二轮返修(禁用态只看得见、读不清)**:上一版照 HELP 页 `button.copy:disabled`
|
|
422
|
+
// 取 `opacity:.45` 压**整颗**按钮,实测有效文字色被混成 `#91b9e9` 压白底,对比度只有
|
|
423
|
+
// **2.03:1**(`.scratch/t525c/before.json`;读法=把 opacity 混进底色后按 WCAG 相对亮度算)——
|
|
424
|
+
// 连 AA 大字的 3:1 都不到,等于把「禁用」写成了「看不清」。
|
|
425
|
+
// 改法=**不压整颗**,改三处、各自都是一个信号:① 文字色换 `--fg3`;② 底压成 `--soft`;
|
|
426
|
+
// ③ 描边降到 `--line`(「蓝=可点」这条信号只留在可点态)。`opacity` 恒 1(不继承、不叠乘)。
|
|
427
|
+
// 2.03 → 3.47 的两行读数落 `.scratch/t525c/disabled-contrast.json`,探针 `.scratch/t525c/probe.mjs` 可复跑。
|
|
428
|
+
'.' + p + 'copy-btn[disabled],',
|
|
429
|
+
'.' + p + 'copy-btn:disabled {',
|
|
430
|
+
' opacity: 1;',
|
|
431
|
+
' border-color: var(--line);',
|
|
432
|
+
' background: var(--soft);',
|
|
433
|
+
' color: var(--fg3);',
|
|
434
|
+
' cursor: not-allowed;',
|
|
435
|
+
'}',
|
|
436
|
+
'.' + p + 'copy-btn[disabled]:active,',
|
|
437
|
+
'.' + p + 'copy-btn:disabled:active {',
|
|
438
|
+
' transform: none;',
|
|
439
|
+
'}',
|
|
440
|
+
// #179 触控目标:窄屏按钮抬到 44px。**#525 起这条在两个宽档上是同一个值**(`minHeightPx`
|
|
441
|
+
// 由 40 提到 44,见 `spec/controls.ts`)——留在这里是为了不动既有选择器与既有媒体查询;
|
|
442
|
+
// 桌面档不再是 40px。
|
|
443
|
+
'@media (max-width: ' + TOAST_DEFAULTS.mobileMaxPx + 'px) {',
|
|
444
|
+
' .' + p + 'copy-btn {',
|
|
445
|
+
' min-height: 44px;',
|
|
446
|
+
' }',
|
|
447
|
+
'}',
|
|
448
|
+
// ── 复制数据的三格式菜单(#247,2026-09-12 用户裁定「恢复老仓原样」)───────────────
|
|
449
|
+
// 逐值取自老仓 `卡路里/templates/crud_receipt.html`(可点版本 `2262fee1~1`)的 `.fmt-menu`/
|
|
450
|
+
// `.fmt-item`/`.fmt-item:hover`/`.fmt-item span` 四串;老仓的 `--border`/`--soft` 分别
|
|
451
|
+
// 对到本仓的 `--line`/`--soft`。**复用本区命名空间**(`CONTROL_STYLE_SECTIONS` 是冻结闭集,
|
|
452
|
+
// 不新增第 9 个区);类名不对 `copy-btn` 用前缀相似的名字(`.copy-menu-btn` 会被
|
|
453
|
+
// `.copy-btn` 的规则一并命中,多出一圈胶囊底),故开合器只带 `copy-btn copy-btn-ghost` 两颗类。
|
|
454
|
+
// **偏离 1 处(记账)**:菜单圆角取 **14px**(老仓是 12px)——#89 R-9 的 H-10 把
|
|
455
|
+
// 全部非图表 CSS 的 `border-radius` 钉在 `{8px,14px,20px,999px,50%}`,12px 会让你越出闭集;
|
|
456
|
+
// 14px 是本仓既有卡片圆角(toast 同值),几何其余逐值不动(`bottom`/`right`/`min-width`/
|
|
457
|
+
// `max-width`/`padding`/投影/项内距与字号全取老仓)。
|
|
458
|
+
'.' + p + 'copy-menu-wrap {',
|
|
459
|
+
// 宽度**跟着轨道走**(#247 用户 2026-09-12 返修):复制数据与复制日志在 ghost 行里**平分整行**
|
|
460
|
+
// (各占一格,见 `.action-row-ghost` 的两列),两颗宽高一致——不再出现「一颗铺满一行、一颗缩成
|
|
461
|
+
// 内容宽」的一胖一瘦。故这里**不写** `justify-self: start`(那会让本层缩成内容宽、连带按钮也缩)。
|
|
462
|
+
' position: relative;',
|
|
463
|
+
' display: flex;',
|
|
464
|
+
' align-items: center;',
|
|
465
|
+
' width: 100%;',
|
|
466
|
+
'}',
|
|
467
|
+
// 开合器按钮铺满自己那一格:菜单的 `right: 0` 才贴着按钮右缘(== 格子右缘),两格时居中偏右。
|
|
468
|
+
'.' + p + 'copy-menu-wrap > .' + p + 'copy-btn {',
|
|
469
|
+
' width: 100%;',
|
|
470
|
+
'}',
|
|
471
|
+
// **#525 第二轮·三角用 CSS 画**(用户裁定第 5 条:符号顶替了设计):
|
|
472
|
+
// 可见文字里的 `▾` 已从 `controls.ts` 的 `copyMenuHtml` 删掉(那句「可以选格式」改住 `aria-label`),
|
|
473
|
+
// 这里用 `border` 拼一个向下的小三角 + `rotate(180deg)` 做开合态——**一个字符都不打**,
|
|
474
|
+
// 也就不会被字体/读屏/抓取器当成内容。画的规矩:零宽零高的盒子靠 `border-top` 出形,
|
|
475
|
+
// `margin-left: 6px` 与基础的 `gap: 6px` 同值(文字与三角的间距连两处取值都不新造)。
|
|
476
|
+
// 开合态由运行时加的 `.copy-menu-open` 落色(与菜单同一个类,不新增第二个开关)。
|
|
477
|
+
'.' + p + 'copy-menu-wrap > .' + p + 'copy-btn::after {',
|
|
478
|
+
' content: "";',
|
|
479
|
+
' width: 0;',
|
|
480
|
+
' height: 0;',
|
|
481
|
+
' margin-left: 6px;',
|
|
482
|
+
' border-left: 4px solid transparent;',
|
|
483
|
+
' border-right: 4px solid transparent;',
|
|
484
|
+
' border-top: 5px solid currentColor;',
|
|
485
|
+
' transition: transform .16s ease-out;',
|
|
486
|
+
'}',
|
|
487
|
+
'.copy-menu-open.' + p + 'copy-menu-wrap > .' + p + 'copy-btn::after {',
|
|
488
|
+
' transform: rotate(180deg);',
|
|
489
|
+
'}',
|
|
490
|
+
'.' + p + 'copy-menu {',
|
|
491
|
+
' position: absolute;',
|
|
492
|
+
' bottom: calc(100% + 8px);',
|
|
493
|
+
' right: 0;',
|
|
494
|
+
' z-index: 20;',
|
|
495
|
+
' min-width: 200px;',
|
|
496
|
+
// 浮层开合走 opacity(不是 `display`/`hidden`):一是 CSS 过渡不被跳过,二是开合不重排整页。
|
|
497
|
+
// 关着时同时收掉命中,免得看不见的菜单项还能被点到;`visibility` 可过渡 ⇒ 收起仍有淡出。
|
|
498
|
+
' box-sizing: border-box;',
|
|
499
|
+
' max-width: calc(100vw - 32px);',
|
|
500
|
+
' padding: 6px;',
|
|
501
|
+
' border: 1px solid var(--line);',
|
|
502
|
+
' border-radius: 14px;',
|
|
503
|
+
' background: var(--card);',
|
|
504
|
+
' box-shadow: 0 8px 24px rgba(0, 0, 0, .14);',
|
|
505
|
+
' opacity: 0;',
|
|
506
|
+
' visibility: hidden;',
|
|
507
|
+
' pointer-events: none;',
|
|
508
|
+
' transition: opacity .16s ease-out, visibility .16s ease-out;',
|
|
509
|
+
'}',
|
|
510
|
+
// 开着的那条:`copy-menu-open` 是**运行时**加的类(与 #121 的 `copied` 同口径——类名不加
|
|
511
|
+
// `ilife-` 前缀,故不占样式区命名空间,也不作为 `ilife-` 类名进跨文件检查);选择器把裸类
|
|
512
|
+
// 排在**前**面,这样从 CSS 里扫出来的 `ilife-` 类名仍只有 `ilife-copy-menu`(T10 ② 认得出产出者)。
|
|
513
|
+
'.copy-menu-open.' + p + 'copy-menu {',
|
|
514
|
+
' opacity: 1;',
|
|
515
|
+
' visibility: visible;',
|
|
516
|
+
' pointer-events: auto;',
|
|
517
|
+
'}',
|
|
518
|
+
'.' + p + 'copy-menu-item {',
|
|
519
|
+
// #152 返修:补最小高——老仓 `.fmt-item` 只写 `padding:10px 12px` + 13px 字,算出来 37px,
|
|
520
|
+
// 低于本仓同区复制按钮的冻结最小值(`spec/controls.ts:297` 的 40px)。40 不另写一个数,
|
|
521
|
+
// 引用同一个定义地;窄屏那档仍由下面的 `min-height:44px` 抬起(老仓 `.fmt-item` 是 36px)。
|
|
522
|
+
' min-height: ' + ACTION_BAR_DEFAULTS.minHeightPx + 'px;',
|
|
523
|
+
' display: flex;',
|
|
524
|
+
' justify-content: space-between;',
|
|
525
|
+
' gap: 14px;',
|
|
526
|
+
' width: 100%;',
|
|
527
|
+
' padding: 10px 12px;',
|
|
528
|
+
' border: none;',
|
|
529
|
+
' border-radius: 8px;',
|
|
530
|
+
' background: none;',
|
|
531
|
+
' color: var(--fg);',
|
|
532
|
+
' font-family: inherit;',
|
|
533
|
+
' font-size: 13px;',
|
|
534
|
+
' text-align: left;',
|
|
535
|
+
' cursor: pointer;',
|
|
536
|
+
' -webkit-tap-highlight-color: transparent;',
|
|
537
|
+
' touch-action: manipulation;',
|
|
538
|
+
'}',
|
|
539
|
+
'.' + p + 'copy-menu-item:hover {',
|
|
540
|
+
' background: var(--soft);',
|
|
541
|
+
'}',
|
|
542
|
+
// 标签(格式键):显式一条——省得继承菜单项的既有值,也让「CSS 里每个类名都有产出者、
|
|
543
|
+
// 每个产出类名都有 CSS」这条跨文件检查两面都成立(`style.test.mjs` T10)。
|
|
544
|
+
'.' + p + 'copy-menu-item > .' + p + 'copy-menu-label {',
|
|
545
|
+
' color: var(--fg);',
|
|
546
|
+
' font-size: 13px;',
|
|
547
|
+
'}',
|
|
548
|
+
// 用途提示:老仓是 `.fmt-item span`(后代选择器,两项 span 都染 11px 灰);本仓显式给类名,
|
|
549
|
+
// 标签那半仍取 13px/`--fg`(上一条)。选择器用 `>` ——本仓跨文件交叉检查按**整段选择器**比对。
|
|
550
|
+
// **返修**:字色由 `--fg3`(#86868b)改为 `--fg2`(#6e6e73)——11px 属正文,AA 要 4.5:1,
|
|
551
|
+
// 前者对白卡片仅 3.62:1、后者 5.07:1;与同批「12px + `--fg3`」那 7 处改用的是同一个做法(#152)。
|
|
552
|
+
'.' + p + 'copy-menu-item > .' + p + 'copy-menu-hint {',
|
|
553
|
+
' color: var(--fg2);',
|
|
554
|
+
' font-size: 11px;',
|
|
555
|
+
' white-space: nowrap;',
|
|
556
|
+
'}',
|
|
557
|
+
// #179 触控目标:窄屏菜单项抬到 44px(与复制按钮同一口径;老仓 `.fmt-item` 是 36px 上下)。
|
|
558
|
+
'@media (max-width: ' + TOAST_DEFAULTS.mobileMaxPx + 'px) {',
|
|
559
|
+
' .' + p + 'copy-menu-item {',
|
|
560
|
+
' min-height: 44px;',
|
|
561
|
+
' }',
|
|
562
|
+
// 窄屏改**贴按钮算**(老仓那句「右对齐视口内,手机不超界」的落法):桌面档按钮靠左,200px 的菜单
|
|
563
|
+
// 贴按钮会有一半越到屏幕左外;窄屏按钮在右半格,故改成
|
|
564
|
+
// 「宽 = 视口 − 左右各 16px、右缘贴按钮右缘」——既恒在视口内,又跟着按钮(滚动时不漂、不挡按钮),
|
|
565
|
+
// 也不会像 `position: fixed` 那样把浮层钉在视口底、压住别的正文。
|
|
566
|
+
//
|
|
567
|
+
// **#249 修正**:原先「宽 = 视口 − 32px + 右缘贴按钮」只在按钮位于**右格**时成立;复制数据排在
|
|
568
|
+
// 复制日志前头(`renderActionBar` 的 ghost 行顺序),窄屏上它在**左格**,菜单右缘贴左格右缘 ⇒
|
|
569
|
+
// 菜单左缘跑到视口外 167px(390 实测 x=-167,三项的格式名全看不见)。修法:窄屏把锚点从**包裹层**
|
|
570
|
+
// 换成**整行**(行在这一档挂 `position: relative`,见 `actionBar` 区);菜单 `left:0; right:0`
|
|
571
|
+
// 就落在行盒(=内容宽 358)里,按钮在哪一格都在视口内,且仍是「跟着按钮走」的绝对定位浮层。
|
|
572
|
+
' .' + p + 'copy-menu-wrap {',
|
|
573
|
+
' position: static;',
|
|
574
|
+
' }',
|
|
575
|
+
' .' + p + 'copy-menu {',
|
|
576
|
+
' left: 0;',
|
|
577
|
+
' right: 0;',
|
|
578
|
+
' width: auto;',
|
|
579
|
+
' min-width: 0;',
|
|
580
|
+
' max-width: none;',
|
|
581
|
+
' }',
|
|
582
|
+
'}',
|
|
366
583
|
focusRing('.' + p + 'copy-btn'),
|
|
367
584
|
].join(LF),
|
|
368
585
|
/** statusBadge —— 类名产出者 `controls.ts:702-707`。
|
|
@@ -372,7 +589,7 @@ const SECTION_BUILDERS = {
|
|
|
372
589
|
* ok `#e6f7ec`/`#1f8c3d`、warn `#fff5e0`/`#a25b00`、danger `#fff0ee`/`#a83228`、
|
|
373
590
|
* empty `#f0f0f3`/`var(--fg2)`(empty 字色旧层 `base.css:228` 为 `#6e6e73`=`--fg2` 解析值,底色为实色 `#f0f0f3`)。
|
|
374
591
|
* **返修 W2**:上一轮误用 `#1f8f3d`/`#b25000`(全仓无出处)+ 12% alpha 底色,且注释谎称「沿用旧值」
|
|
375
|
-
* → 已改回旧逐值,注释与实现一致(非 token 硬编码色按 D-5 以 CSS
|
|
592
|
+
* → 已改回旧逐值,注释与实现一致(非 token 硬编码色按 D-5 以 CSS 常量实施,不新增 token 名)。 */
|
|
376
593
|
statusBadge: (p) => [
|
|
377
594
|
'.' + p + 'status-badge {',
|
|
378
595
|
' display: inline-flex;',
|
|
@@ -414,14 +631,16 @@ const SECTION_BUILDERS = {
|
|
|
414
631
|
' color: var(--fg2);',
|
|
415
632
|
'}',
|
|
416
633
|
'.' + p + 'empty-icon {',
|
|
417
|
-
|
|
634
|
+
// #567 J4(§5.2 大数 28 吸收 26/28/32/40):装饰图标 40→28。
|
|
635
|
+
' font-size: 28px;',
|
|
418
636
|
' line-height: 1.2;',
|
|
419
637
|
' opacity: .5;',
|
|
420
638
|
'}',
|
|
421
639
|
'.' + p + 'empty-text {',
|
|
422
640
|
' margin-top: 8px;',
|
|
423
641
|
' color: var(--fg);',
|
|
424
|
-
|
|
642
|
+
// #567 J4(§5.2 标题 18 吸收 17/18/20/22)。
|
|
643
|
+
' font-size: 18px;',
|
|
425
644
|
' font-weight: 600;',
|
|
426
645
|
'}',
|
|
427
646
|
'.' + p + 'empty-hint {',
|
|
@@ -493,7 +712,7 @@ const SECTION_BUILDERS = {
|
|
|
493
712
|
' margin: 0 auto;',
|
|
494
713
|
' padding: 32px 20px 80px;',
|
|
495
714
|
' color: var(--fg);',
|
|
496
|
-
// H-06
|
|
715
|
+
// H-06 正文栈(唯一真相源 `src/font.ts` 的 BODY_FONT_STACK,首位 "SF Pro Display";不新增 token 名,等宽栈不动)。
|
|
497
716
|
' font-family: ' + BODY_FONT_STACK + ';',
|
|
498
717
|
' font-feature-settings: "tnum";',
|
|
499
718
|
'}',
|
|
@@ -580,6 +799,7 @@ const SECTION_BUILDERS = {
|
|
|
580
799
|
' font-size: 13px;',
|
|
581
800
|
' font-weight: 600;',
|
|
582
801
|
' cursor: pointer;',
|
|
802
|
+
' touch-action: manipulation;',
|
|
583
803
|
'}',
|
|
584
804
|
'.' + p + 'help-shell-tab-icon {',
|
|
585
805
|
' font-size: 14px;',
|
|
@@ -702,6 +922,7 @@ const SECTION_BUILDERS = {
|
|
|
702
922
|
' font-size: 13px;',
|
|
703
923
|
' font-weight: 600;',
|
|
704
924
|
' cursor: pointer;',
|
|
925
|
+
' touch-action: manipulation;',
|
|
705
926
|
' list-style: none;',
|
|
706
927
|
'}',
|
|
707
928
|
'.' + p + 'help-shell-sheet-summary::-webkit-details-marker {',
|
|
@@ -751,11 +972,13 @@ const SECTION_BUILDERS = {
|
|
|
751
972
|
' font-size: ' + ACTION_BAR_DEFAULTS.fontSizePx + 'px;',
|
|
752
973
|
' font-weight: ' + ACTION_BAR_DEFAULTS.fontWeight + ';',
|
|
753
974
|
' line-height: 1;',
|
|
754
|
-
// #121:H-16「跑 450ms 弹簧动画」——弹簧口径**逐字复用** `copyButton`
|
|
975
|
+
// #121:H-16「跑 450ms 弹簧动画」——弹簧口径**逐字复用** `copyButton` 基础(B1
|
|
755
976
|
// `benchmark-visual-spec.md:279,645`:`transform .45s cubic-bezier(.34,1.56,.64,1)`),
|
|
756
977
|
// 不新增机制、不新增关键帧;按下态同 `.ilife-copy-btn:active`(scale .96)。
|
|
757
978
|
' transition: transform .45s cubic-bezier(.34, 1.56, .64, 1), background-color .2s ease;',
|
|
758
979
|
' cursor: pointer;',
|
|
980
|
+
' -webkit-tap-highlight-color: transparent;',
|
|
981
|
+
' touch-action: manipulation;',
|
|
759
982
|
'}',
|
|
760
983
|
'.' + p + 'help-shell-btn:active {',
|
|
761
984
|
' transform: scale(.96);',
|
|
@@ -791,6 +1014,7 @@ const SECTION_BUILDERS = {
|
|
|
791
1014
|
' font-size: 14px;',
|
|
792
1015
|
' font-weight: 600;',
|
|
793
1016
|
' cursor: pointer;',
|
|
1017
|
+
' touch-action: manipulation;',
|
|
794
1018
|
'}',
|
|
795
1019
|
'.' + p + 'help-shell-count {',
|
|
796
1020
|
' color: var(--fg3);',
|
|
@@ -889,6 +1113,7 @@ const SECTION_BUILDERS = {
|
|
|
889
1113
|
' font-size: 12px;',
|
|
890
1114
|
' line-height: 1;',
|
|
891
1115
|
' cursor: pointer;',
|
|
1116
|
+
' touch-action: manipulation;',
|
|
892
1117
|
'}',
|
|
893
1118
|
focusRing('.' + p + 'help-shell-tab-search-clear'),
|
|
894
1119
|
'.' + p + 'help-shell-page-hitcount {',
|
|
@@ -911,9 +1136,11 @@ const SECTION_BUILDERS = {
|
|
|
911
1136
|
' font-size: 12px;',
|
|
912
1137
|
' font-weight: 600;',
|
|
913
1138
|
' line-height: 1;',
|
|
914
|
-
// #121:弹簧口径同 `copyButton`
|
|
1139
|
+
// #121:弹簧口径同 `copyButton` 基础(H-16「450ms 弹簧」),成功态 `.copied` 见上方 helpShell 区。
|
|
915
1140
|
' transition: transform .45s cubic-bezier(.34, 1.56, .64, 1), background-color .2s ease;',
|
|
916
1141
|
' cursor: pointer;',
|
|
1142
|
+
' -webkit-tap-highlight-color: transparent;',
|
|
1143
|
+
' touch-action: manipulation;',
|
|
917
1144
|
'}',
|
|
918
1145
|
'.' + p + 'help-shell-card-copy:active {',
|
|
919
1146
|
' transform: scale(.96);',
|
|
@@ -974,6 +1201,7 @@ const SECTION_BUILDERS = {
|
|
|
974
1201
|
' transition: opacity .2s ease;',
|
|
975
1202
|
' z-index: 9998;',
|
|
976
1203
|
' cursor: pointer;',
|
|
1204
|
+
' touch-action: manipulation;',
|
|
977
1205
|
'}',
|
|
978
1206
|
'.' + p + 'help-shell-btn-backtop-show {',
|
|
979
1207
|
' opacity: 1;',
|
|
@@ -1038,7 +1266,7 @@ function normalizePrefix(input) {
|
|
|
1038
1266
|
/** `extraCss` 违规错误:**不导出**(与 #74 `TemplateError`/#76 `bad-input` 同口径——
|
|
1039
1267
|
* 冻结面 `SPEC_FROZEN_SURFACE` 无该运行时条目,调用方按 `name`/`code` 判定)。
|
|
1040
1268
|
* code 三值 = 契约 doc:299-300 三条「不得」的落点:
|
|
1041
|
-
* `extra-css-root
|
|
1269
|
+
* `extra-css-root`(改写基础 `:root`)/`extra-css-forbidden-token`(Q14 禁入项)/
|
|
1042
1270
|
* `extra-css-dark-scheme`(深色区选择器,doc:292)。 */
|
|
1043
1271
|
class StyleSheetExtraCssError extends Error {
|
|
1044
1272
|
code;
|
|
@@ -1049,7 +1277,7 @@ class StyleSheetExtraCssError extends Error {
|
|
|
1049
1277
|
}
|
|
1050
1278
|
}
|
|
1051
1279
|
/** CSS 块注释剥除(`/* … *\/` → 空格):**判定前先剥注释**——注释里的 `:root`/`--pink` 只是说明文字,
|
|
1052
|
-
*
|
|
1280
|
+
* 不是「改写基础/引入禁入项」;反之注释**不能**藏住真实声明(`/*c*\/:root{}` 剥后仍命中)。 */
|
|
1053
1281
|
function stripCssComments(css) {
|
|
1054
1282
|
return css.replace(/\/\*[\s\S]*?\*\//g, ' ');
|
|
1055
1283
|
}
|
|
@@ -1062,9 +1290,9 @@ function hasBoundedToken(text, token) {
|
|
|
1062
1290
|
}
|
|
1063
1291
|
/** `extraCss` 三禁强制(**编排者返修裁定:D3 修订**,见契约 §8.11)。
|
|
1064
1292
|
*
|
|
1065
|
-
* 理由:契约 doc:299-300
|
|
1293
|
+
* 理由:契约 doc:299-300 的三条「不得」(不得改写基础值/不得引入 Q14 禁入项/不得引入深色区)
|
|
1066
1294
|
* 此前**无任何落点**(D3 原裁定「不校验、纯调用方责任」)→ 本票补最小强制:
|
|
1067
|
-
* - (a) 含 `:root` 选择器 →
|
|
1295
|
+
* - (a) 含 `:root` 选择器 → 改写基础;
|
|
1068
1296
|
* - (b) 含 `STYLE_FORBIDDEN_TOKENS`(`--r-xl`/`--pink`);
|
|
1069
1297
|
* - (c) 含深色区选择器(`[data-theme`/`prefers-color-scheme: dark`)。
|
|
1070
1298
|
* 命中**任一**即抛错;**合法技能作用域覆盖块**(`.ilife-<skill>{--blue:…}`)照常通过。
|
|
@@ -1078,7 +1306,7 @@ function assertExtraCss(extraCss) {
|
|
|
1078
1306
|
const code = stripCssComments(extraCss);
|
|
1079
1307
|
// `:root` 是伪类名(CSS 伪类名大小写不敏感)→ 用 `/i` 拦住 `:ROOT` 之类的等价写法。
|
|
1080
1308
|
if (/:root(?![A-Za-z0-9_-])/i.test(code)) {
|
|
1081
|
-
throw new StyleSheetExtraCssError('extra-css-root', 'buildStyleSheet: extraCss
|
|
1309
|
+
throw new StyleSheetExtraCssError('extra-css-root', 'buildStyleSheet: extraCss 不得改写基础(命中 `:root` 选择器);技能主题只许用 `.ilife-<skill>` 作用域覆盖块(契约 doc:299)');
|
|
1082
1310
|
}
|
|
1083
1311
|
for (const forbidden of STYLE_FORBIDDEN_TOKENS) {
|
|
1084
1312
|
if (hasBoundedToken(code, forbidden)) {
|