@yaoxiu/marketing-dsl 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -1
- package/dist/chunk-FKZKLCVV.js +968 -0
- package/dist/docs/index.cjs +3726 -0
- package/dist/docs/index.d.cts +170 -0
- package/dist/docs/index.d.ts +170 -0
- package/dist/docs/index.js +3624 -0
- package/dist/index.cjs +118 -15
- package/dist/index.d.cts +17 -283
- package/dist/index.d.ts +17 -283
- package/dist/index.js +86 -949
- package/dist/types-BgUaJUAu.d.cts +293 -0
- package/dist/types-BgUaJUAu.d.ts +293 -0
- package/package.json +6 -1
package/dist/index.js
CHANGED
|
@@ -1,308 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
true: true,
|
|
4
|
-
false: false,
|
|
5
|
-
null: null,
|
|
6
|
-
undefined: void 0
|
|
7
|
-
};
|
|
8
|
-
var PUNCTUATORS = [
|
|
9
|
-
"===",
|
|
10
|
-
"!==",
|
|
11
|
-
"<=",
|
|
12
|
-
">=",
|
|
13
|
-
"==",
|
|
14
|
-
"!=",
|
|
15
|
-
"&&",
|
|
16
|
-
"||",
|
|
17
|
-
"(",
|
|
18
|
-
")",
|
|
19
|
-
"[",
|
|
20
|
-
"]",
|
|
21
|
-
".",
|
|
22
|
-
"?",
|
|
23
|
-
":",
|
|
24
|
-
"<",
|
|
25
|
-
">",
|
|
26
|
-
"!",
|
|
27
|
-
"+",
|
|
28
|
-
"-",
|
|
29
|
-
"*",
|
|
30
|
-
"/",
|
|
31
|
-
"%"
|
|
32
|
-
];
|
|
33
|
-
function tokenize(input) {
|
|
34
|
-
const tokens = [];
|
|
35
|
-
let i = 0;
|
|
36
|
-
while (i < input.length) {
|
|
37
|
-
const ch = input[i];
|
|
38
|
-
if (/\s/.test(ch)) {
|
|
39
|
-
i++;
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
if (ch === '"' || ch === "'") {
|
|
43
|
-
const quote = ch;
|
|
44
|
-
let value = "";
|
|
45
|
-
i++;
|
|
46
|
-
while (i < input.length && input[i] !== quote) {
|
|
47
|
-
if (input[i] === "\\") {
|
|
48
|
-
value += input[i + 1] || "";
|
|
49
|
-
i += 2;
|
|
50
|
-
} else {
|
|
51
|
-
value += input[i];
|
|
52
|
-
i++;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
if (i >= input.length) throw new Error("\u5B57\u7B26\u4E32\u6CA1\u6709\u95ED\u5408");
|
|
56
|
-
i++;
|
|
57
|
-
tokens.push({ type: "string", value });
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
if (/[0-9]/.test(ch) || ch === "." && /[0-9]/.test(input[i + 1] || "")) {
|
|
61
|
-
let raw = "";
|
|
62
|
-
while (i < input.length && /[0-9.]/.test(input[i])) {
|
|
63
|
-
raw += input[i];
|
|
64
|
-
i++;
|
|
65
|
-
}
|
|
66
|
-
tokens.push({ type: "number", value: Number(raw) });
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
if (/[A-Za-z_$]/.test(ch)) {
|
|
70
|
-
let name = "";
|
|
71
|
-
while (i < input.length && /[A-Za-z0-9_$]/.test(input[i])) {
|
|
72
|
-
name += input[i];
|
|
73
|
-
i++;
|
|
74
|
-
}
|
|
75
|
-
tokens.push({ type: "ident", value: name });
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
const punctuator = PUNCTUATORS.find((p) => input.startsWith(p, i));
|
|
79
|
-
if (!punctuator) throw new Error(`\u65E0\u6CD5\u8BC6\u522B\u7684\u5B57\u7B26 "${ch}"`);
|
|
80
|
-
tokens.push({ type: "punc", value: punctuator });
|
|
81
|
-
i += punctuator.length;
|
|
82
|
-
}
|
|
83
|
-
return tokens;
|
|
84
|
-
}
|
|
85
|
-
function createParser(tokens) {
|
|
86
|
-
let pos = 0;
|
|
87
|
-
const peek = () => tokens[pos];
|
|
88
|
-
const isPunc = (v) => {
|
|
89
|
-
const token = peek();
|
|
90
|
-
return !!token && token.type === "punc" && token.value === v;
|
|
91
|
-
};
|
|
92
|
-
const eat = (v) => {
|
|
93
|
-
if (!isPunc(v)) throw new Error(`\u7F3A\u5C11 "${v}"`);
|
|
94
|
-
pos++;
|
|
95
|
-
};
|
|
96
|
-
const binaryLevels = [
|
|
97
|
-
["||"],
|
|
98
|
-
["&&"],
|
|
99
|
-
["===", "!==", "==", "!="],
|
|
100
|
-
["<", ">", "<=", ">="],
|
|
101
|
-
["+", "-"],
|
|
102
|
-
["*", "/", "%"]
|
|
103
|
-
];
|
|
104
|
-
function parseExpression() {
|
|
105
|
-
return parseTernary();
|
|
106
|
-
}
|
|
107
|
-
function parseTernary() {
|
|
108
|
-
const test = parseBinary(0);
|
|
109
|
-
if (!isPunc("?")) return test;
|
|
110
|
-
eat("?");
|
|
111
|
-
const consequent = parseTernary();
|
|
112
|
-
eat(":");
|
|
113
|
-
const alternate = parseTernary();
|
|
114
|
-
return { kind: "ternary", test, consequent, alternate };
|
|
115
|
-
}
|
|
116
|
-
function parseBinary(level) {
|
|
117
|
-
if (level >= binaryLevels.length) return parseUnary();
|
|
118
|
-
let left = parseBinary(level + 1);
|
|
119
|
-
for (; ; ) {
|
|
120
|
-
const token = peek();
|
|
121
|
-
if (!token || token.type !== "punc") break;
|
|
122
|
-
if (binaryLevels[level].indexOf(String(token.value)) === -1) break;
|
|
123
|
-
const operator = String(token.value);
|
|
124
|
-
pos++;
|
|
125
|
-
const right = parseBinary(level + 1);
|
|
126
|
-
left = { kind: "binary", operator, left, right };
|
|
127
|
-
}
|
|
128
|
-
return left;
|
|
129
|
-
}
|
|
130
|
-
function parseUnary() {
|
|
131
|
-
if (isPunc("!") || isPunc("-")) {
|
|
132
|
-
const operator = String(peek().value);
|
|
133
|
-
pos++;
|
|
134
|
-
return { kind: "unary", operator, argument: parseUnary() };
|
|
135
|
-
}
|
|
136
|
-
return parseMember();
|
|
137
|
-
}
|
|
138
|
-
function parseMember() {
|
|
139
|
-
let object = parsePrimary();
|
|
140
|
-
for (; ; ) {
|
|
141
|
-
if (isPunc(".")) {
|
|
142
|
-
eat(".");
|
|
143
|
-
const token = peek();
|
|
144
|
-
if (!token || token.type !== "ident") throw new Error('"." \u540E\u9762\u9700\u8981\u5C5E\u6027\u540D');
|
|
145
|
-
pos++;
|
|
146
|
-
object = {
|
|
147
|
-
kind: "member",
|
|
148
|
-
object,
|
|
149
|
-
property: { kind: "literal", value: token.value }
|
|
150
|
-
};
|
|
151
|
-
} else if (isPunc("[")) {
|
|
152
|
-
eat("[");
|
|
153
|
-
const property = parseExpression();
|
|
154
|
-
eat("]");
|
|
155
|
-
object = { kind: "member", object, property };
|
|
156
|
-
} else {
|
|
157
|
-
return object;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
function parsePrimary() {
|
|
162
|
-
const token = peek();
|
|
163
|
-
if (!token) throw new Error("\u8868\u8FBE\u5F0F\u4E0D\u5B8C\u6574");
|
|
164
|
-
if (isPunc("(")) {
|
|
165
|
-
eat("(");
|
|
166
|
-
const node = parseExpression();
|
|
167
|
-
eat(")");
|
|
168
|
-
return node;
|
|
169
|
-
}
|
|
170
|
-
if (token.type === "number" || token.type === "string") {
|
|
171
|
-
pos++;
|
|
172
|
-
return { kind: "literal", value: token.value };
|
|
173
|
-
}
|
|
174
|
-
if (token.type === "ident") {
|
|
175
|
-
pos++;
|
|
176
|
-
const name = String(token.value);
|
|
177
|
-
if (Object.prototype.hasOwnProperty.call(KEYWORD_LITERALS, name)) {
|
|
178
|
-
return { kind: "literal", value: KEYWORD_LITERALS[name] };
|
|
179
|
-
}
|
|
180
|
-
return { kind: "identifier", name };
|
|
181
|
-
}
|
|
182
|
-
throw new Error(`\u610F\u5916\u7684\u7B26\u53F7 "${token.value}"`);
|
|
183
|
-
}
|
|
184
|
-
const ast = parseExpression();
|
|
185
|
-
if (pos < tokens.length) throw new Error(`\u8868\u8FBE\u5F0F\u7ED3\u5C3E\u6709\u591A\u4F59\u5185\u5BB9 "${tokens[pos].value}"`);
|
|
186
|
-
return ast;
|
|
187
|
-
}
|
|
188
|
-
var astCache = /* @__PURE__ */ new Map();
|
|
189
|
-
function parse(source) {
|
|
190
|
-
const cached = astCache.get(source);
|
|
191
|
-
if (cached) return cached;
|
|
192
|
-
const ast = createParser(tokenize(source));
|
|
193
|
-
astCache.set(source, ast);
|
|
194
|
-
return ast;
|
|
195
|
-
}
|
|
196
|
-
var BLOCKED_KEYS = ["__proto__", "constructor", "prototype"];
|
|
197
|
-
function readProperty(object, key) {
|
|
198
|
-
if (object === null || object === void 0) return void 0;
|
|
199
|
-
if (BLOCKED_KEYS.indexOf(String(key)) > -1) return void 0;
|
|
200
|
-
const value = object[String(key)];
|
|
201
|
-
return typeof value === "function" ? void 0 : value;
|
|
202
|
-
}
|
|
203
|
-
function evaluateNode(node, context) {
|
|
204
|
-
switch (node.kind) {
|
|
205
|
-
case "literal":
|
|
206
|
-
return node.value;
|
|
207
|
-
case "identifier":
|
|
208
|
-
return readProperty(context, node.name);
|
|
209
|
-
case "member":
|
|
210
|
-
return readProperty(
|
|
211
|
-
evaluateNode(node.object, context),
|
|
212
|
-
evaluateNode(node.property, context)
|
|
213
|
-
);
|
|
214
|
-
case "unary": {
|
|
215
|
-
const value = evaluateNode(node.argument, context);
|
|
216
|
-
return node.operator === "!" ? !value : -value;
|
|
217
|
-
}
|
|
218
|
-
case "ternary":
|
|
219
|
-
return evaluateNode(node.test, context) ? evaluateNode(node.consequent, context) : evaluateNode(node.alternate, context);
|
|
220
|
-
case "binary": {
|
|
221
|
-
if (node.operator === "&&") {
|
|
222
|
-
return evaluateNode(node.left, context) && evaluateNode(node.right, context);
|
|
223
|
-
}
|
|
224
|
-
if (node.operator === "||") {
|
|
225
|
-
return evaluateNode(node.left, context) || evaluateNode(node.right, context);
|
|
226
|
-
}
|
|
227
|
-
const left = evaluateNode(node.left, context);
|
|
228
|
-
const right = evaluateNode(node.right, context);
|
|
229
|
-
switch (node.operator) {
|
|
230
|
-
case "===":
|
|
231
|
-
return left === right;
|
|
232
|
-
case "!==":
|
|
233
|
-
return left !== right;
|
|
234
|
-
case "==":
|
|
235
|
-
return left == right;
|
|
236
|
-
case "!=":
|
|
237
|
-
return left != right;
|
|
238
|
-
case "<":
|
|
239
|
-
return left < right;
|
|
240
|
-
case ">":
|
|
241
|
-
return left > right;
|
|
242
|
-
case "<=":
|
|
243
|
-
return left <= right;
|
|
244
|
-
case ">=":
|
|
245
|
-
return left >= right;
|
|
246
|
-
case "+":
|
|
247
|
-
return left + right;
|
|
248
|
-
case "-":
|
|
249
|
-
return left - right;
|
|
250
|
-
case "*":
|
|
251
|
-
return left * right;
|
|
252
|
-
case "/":
|
|
253
|
-
return left / right;
|
|
254
|
-
case "%":
|
|
255
|
-
return left % right;
|
|
256
|
-
default:
|
|
257
|
-
throw new Error(`\u4E0D\u652F\u6301\u7684\u8FD0\u7B97\u7B26 "${node.operator}"`);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
default:
|
|
261
|
-
throw new Error("\u4E0D\u652F\u6301\u7684\u8282\u70B9\u7C7B\u578B");
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
function evaluate(source, context) {
|
|
265
|
-
try {
|
|
266
|
-
return evaluateNode(parse(source), context);
|
|
267
|
-
} catch (e) {
|
|
268
|
-
return void 0;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
function check(source) {
|
|
272
|
-
try {
|
|
273
|
-
parse(source);
|
|
274
|
-
return "";
|
|
275
|
-
} catch (error) {
|
|
276
|
-
return error.message;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
var INTERPOLATION_RE = /\{\{([\s\S]+?)\}\}/g;
|
|
280
|
-
function interpolate(input, context) {
|
|
281
|
-
if (typeof input !== "string" || input.indexOf("{{") === -1) return input;
|
|
282
|
-
const trimmed = input.trim();
|
|
283
|
-
const tokens = trimmed.match(INTERPOLATION_RE) || [];
|
|
284
|
-
if (tokens.length === 1 && tokens[0] === trimmed) {
|
|
285
|
-
return evaluate(trimmed.slice(2, -2).trim(), context);
|
|
286
|
-
}
|
|
287
|
-
return input.replace(INTERPOLATION_RE, (_, expr) => {
|
|
288
|
-
const value = evaluate(expr.trim(), context);
|
|
289
|
-
return value === void 0 || value === null ? "" : String(value);
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
function interpolateDeep(input, context) {
|
|
293
|
-
if (typeof input === "string") return interpolate(input, context);
|
|
294
|
-
if (Array.isArray(input)) {
|
|
295
|
-
return input.map((item) => interpolateDeep(item, context));
|
|
296
|
-
}
|
|
297
|
-
if (input && typeof input === "object") {
|
|
298
|
-
const result = {};
|
|
299
|
-
Object.keys(input).forEach((key) => {
|
|
300
|
-
result[key] = interpolateDeep(input[key], context);
|
|
301
|
-
});
|
|
302
|
-
return result;
|
|
303
|
-
}
|
|
304
|
-
return input;
|
|
305
|
-
}
|
|
1
|
+
import { normalizeViews, createTicker, interpolateDeep, interpolate, evaluate, resolveNodeStyle, toLength, toCssStyle, parseEndTime, computeParts, formatParts } from './chunk-FKZKLCVV.js';
|
|
2
|
+
export { ACTION_TYPES, ALLOWED_STYLE_KEYS, CLOSE_POSITIONS, DSL_VERSION, NODE_TYPES, SINGLE_VIEW_NAME, TRACK_EVENT_PATTERN, check, computeParts, evaluate, formatIssues, formatParts, interpolate, interpolateDeep, isLength, isValidEndTime, normalizeViews, parseEndTime, toCssStyle, toLength, validate } from './chunk-FKZKLCVV.js';
|
|
306
3
|
|
|
307
4
|
// src/url.ts
|
|
308
5
|
var SAFE_PROTOCOLS = ["http:", "https:", "mailto:", "tel:"];
|
|
@@ -390,215 +87,6 @@ function createDispatcher(options) {
|
|
|
390
87
|
return dispatch;
|
|
391
88
|
}
|
|
392
89
|
|
|
393
|
-
// src/countdown.ts
|
|
394
|
-
function pad(value, len = 2) {
|
|
395
|
-
return String(value).padStart(len, "0");
|
|
396
|
-
}
|
|
397
|
-
function parseEndTime(to) {
|
|
398
|
-
if (typeof to === "number") return to;
|
|
399
|
-
if (to === void 0 || to === null || to === "") return 0;
|
|
400
|
-
const raw = String(to).trim();
|
|
401
|
-
if (/^\d+$/.test(raw)) return Number(raw);
|
|
402
|
-
const time = new Date(raw.replace(/-/g, "/")).getTime();
|
|
403
|
-
return isNaN(time) ? 0 : time;
|
|
404
|
-
}
|
|
405
|
-
function computeParts(endTime, now = Date.now()) {
|
|
406
|
-
const raw = endTime - now;
|
|
407
|
-
const remain = raw > 0 ? raw : 0;
|
|
408
|
-
const cs = Math.floor(remain / 10);
|
|
409
|
-
const sec = Math.floor(cs / 100);
|
|
410
|
-
return {
|
|
411
|
-
d: String(Math.floor(sec / 86400)),
|
|
412
|
-
// h 是 0~23;跨天还想连着数小时的用 hAll(如 143:58:07)
|
|
413
|
-
h: pad(Math.floor(sec % 86400 / 3600)),
|
|
414
|
-
hAll: pad(Math.floor(sec / 3600)),
|
|
415
|
-
m: pad(Math.floor(sec % 3600 / 60)),
|
|
416
|
-
s: pad(sec % 60),
|
|
417
|
-
cs: pad(cs % 100),
|
|
418
|
-
ended: !endTime || remain <= 0
|
|
419
|
-
};
|
|
420
|
-
}
|
|
421
|
-
function formatParts(parts, format) {
|
|
422
|
-
return (format || "{d}\u5929 {h}:{m}:{s}").replace("{d}", parts.d).replace("{hAll}", parts.hAll).replace("{h}", parts.h).replace("{m}", parts.m).replace("{s}", parts.s).replace("{cs}", parts.cs);
|
|
423
|
-
}
|
|
424
|
-
function createTicker(options) {
|
|
425
|
-
let timer = null;
|
|
426
|
-
let raf = 0;
|
|
427
|
-
let running = false;
|
|
428
|
-
let precision = "s";
|
|
429
|
-
let endTimes = [];
|
|
430
|
-
const hasRaf = typeof requestAnimationFrame === "function";
|
|
431
|
-
function allEnded() {
|
|
432
|
-
const now = Date.now();
|
|
433
|
-
return endTimes.every((end) => !end || end - now <= 0);
|
|
434
|
-
}
|
|
435
|
-
function tick() {
|
|
436
|
-
options.onTick();
|
|
437
|
-
if (allEnded()) {
|
|
438
|
-
stop();
|
|
439
|
-
if (options.onAllEnded) options.onAllEnded();
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
function stop() {
|
|
443
|
-
running = false;
|
|
444
|
-
if (timer) {
|
|
445
|
-
clearInterval(timer);
|
|
446
|
-
timer = null;
|
|
447
|
-
}
|
|
448
|
-
if (raf) {
|
|
449
|
-
cancelAnimationFrame(raf);
|
|
450
|
-
raf = 0;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
function sync(nextEndTimes, nextPrecision) {
|
|
454
|
-
const changed = nextPrecision !== precision || nextEndTimes.length !== endTimes.length || nextEndTimes.some((end, i) => end !== endTimes[i]);
|
|
455
|
-
endTimes = nextEndTimes;
|
|
456
|
-
precision = nextPrecision;
|
|
457
|
-
if (!changed && running) return;
|
|
458
|
-
stop();
|
|
459
|
-
if (!endTimes.length || allEnded()) return;
|
|
460
|
-
running = true;
|
|
461
|
-
if (precision === "cs" && hasRaf) {
|
|
462
|
-
const loop = () => {
|
|
463
|
-
tick();
|
|
464
|
-
if (running) raf = requestAnimationFrame(loop);
|
|
465
|
-
};
|
|
466
|
-
raf = requestAnimationFrame(loop);
|
|
467
|
-
} else {
|
|
468
|
-
timer = setInterval(tick, 1e3);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
return { sync, stop };
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// src/views.ts
|
|
475
|
-
var SINGLE_VIEW_NAME = "main";
|
|
476
|
-
function normalizeViews(dsl) {
|
|
477
|
-
if (!dsl || typeof dsl !== "object") {
|
|
478
|
-
return { entry: SINGLE_VIEW_NAME, views: {}, isMulti: false };
|
|
479
|
-
}
|
|
480
|
-
if (dsl.views && typeof dsl.views === "object" && !Array.isArray(dsl.views)) {
|
|
481
|
-
const names = Object.keys(dsl.views);
|
|
482
|
-
return {
|
|
483
|
-
entry: dsl.entry && dsl.views[dsl.entry] ? dsl.entry : names[0],
|
|
484
|
-
views: dsl.views,
|
|
485
|
-
isMulti: true
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
return {
|
|
489
|
-
entry: SINGLE_VIEW_NAME,
|
|
490
|
-
views: {
|
|
491
|
-
[SINGLE_VIEW_NAME]: {
|
|
492
|
-
type: dsl.type,
|
|
493
|
-
stage: dsl.stage,
|
|
494
|
-
nodes: dsl.nodes
|
|
495
|
-
}
|
|
496
|
-
},
|
|
497
|
-
isMulti: false
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
// src/style.ts
|
|
502
|
-
function toLength(value) {
|
|
503
|
-
return typeof value === "number" ? `${value}px` : String(value);
|
|
504
|
-
}
|
|
505
|
-
var px = toLength;
|
|
506
|
-
var LENGTH_RE = /^-?(\d+(\.\d+)?)(px|%|em|rem|vw|vh)$/;
|
|
507
|
-
function isLength(value) {
|
|
508
|
-
if (typeof value === "number") return isFinite(value);
|
|
509
|
-
if (typeof value !== "string") return false;
|
|
510
|
-
const trimmed = value.trim();
|
|
511
|
-
if (trimmed === "auto" || trimmed === "0") return true;
|
|
512
|
-
if (/^calc\([^;{}]*\)$/.test(trimmed)) return true;
|
|
513
|
-
return LENGTH_RE.test(trimmed);
|
|
514
|
-
}
|
|
515
|
-
var STYLE_MAP = {
|
|
516
|
-
// 文字
|
|
517
|
-
color: ["color", String],
|
|
518
|
-
fontSize: ["fontSize", px],
|
|
519
|
-
fontWeight: ["fontWeight", String],
|
|
520
|
-
fontFamily: ["fontFamily", String],
|
|
521
|
-
lineHeight: ["lineHeight", (v) => typeof v === "number" && v > 4 ? px(v) : String(v)],
|
|
522
|
-
letterSpacing: ["letterSpacing", px],
|
|
523
|
-
textAlign: ["textAlign", String],
|
|
524
|
-
textDecoration: ["textDecoration", String],
|
|
525
|
-
whiteSpace: ["whiteSpace", String],
|
|
526
|
-
// 倒计时这类逐帧变化的数字必须等宽,否则数字会左右抖动
|
|
527
|
-
fontVariantNumeric: ["fontVariantNumeric", String],
|
|
528
|
-
// 背景
|
|
529
|
-
background: ["background", String],
|
|
530
|
-
backgroundImage: ["backgroundImage", (v) => `url(${JSON.stringify(String(v))})`],
|
|
531
|
-
backgroundSize: ["backgroundSize", String],
|
|
532
|
-
backgroundPosition: ["backgroundPosition", String],
|
|
533
|
-
backgroundRepeat: ["backgroundRepeat", String],
|
|
534
|
-
// 边框与圆角
|
|
535
|
-
border: ["border", String],
|
|
536
|
-
borderColor: ["borderColor", String],
|
|
537
|
-
borderWidth: ["borderWidth", px],
|
|
538
|
-
borderStyle: ["borderStyle", String],
|
|
539
|
-
radius: ["borderRadius", px],
|
|
540
|
-
// 盒模型
|
|
541
|
-
padding: ["padding", px],
|
|
542
|
-
margin: ["margin", px],
|
|
543
|
-
marginTop: ["marginTop", px],
|
|
544
|
-
marginBottom: ["marginBottom", px],
|
|
545
|
-
marginLeft: ["marginLeft", px],
|
|
546
|
-
marginRight: ["marginRight", px],
|
|
547
|
-
overflow: ["overflow", String],
|
|
548
|
-
opacity: ["opacity", String],
|
|
549
|
-
shadow: ["boxShadow", String],
|
|
550
|
-
cursor: ["cursor", String],
|
|
551
|
-
// flex 容器
|
|
552
|
-
direction: ["flexDirection", (v) => v === "column" ? "column" : "row"],
|
|
553
|
-
gap: ["gap", px],
|
|
554
|
-
wrap: ["flexWrap", (v) => v ? "wrap" : "nowrap"],
|
|
555
|
-
align: ["alignItems", String],
|
|
556
|
-
justify: ["justifyContent", String],
|
|
557
|
-
// flex 子项
|
|
558
|
-
flex: ["flex", String],
|
|
559
|
-
// 不写时子项会被拉满父级交叉轴,标签这类「按内容宽度」的元素要显式声明
|
|
560
|
-
alignSelf: ["alignSelf", String],
|
|
561
|
-
width: ["width", px],
|
|
562
|
-
height: ["height", px],
|
|
563
|
-
minWidth: ["minWidth", px],
|
|
564
|
-
minHeight: ["minHeight", px],
|
|
565
|
-
maxWidth: ["maxWidth", px],
|
|
566
|
-
maxHeight: ["maxHeight", px],
|
|
567
|
-
// 图片
|
|
568
|
-
objectFit: ["objectFit", String],
|
|
569
|
-
// 宽度给百分比、高度按比例算。整图 banner 的热区必须靠它才能用百分比定位:
|
|
570
|
-
// 容器没有真实高度时,子节点的百分比 rect 算出来全是 0。
|
|
571
|
-
aspectRatio: ["aspectRatio", String]
|
|
572
|
-
};
|
|
573
|
-
var ALLOWED_STYLE_KEYS = Object.keys(STYLE_MAP);
|
|
574
|
-
function toCssStyle(style) {
|
|
575
|
-
const css = {};
|
|
576
|
-
if (!style) return css;
|
|
577
|
-
Object.keys(style).forEach((key) => {
|
|
578
|
-
const rule = STYLE_MAP[key];
|
|
579
|
-
if (!rule) return;
|
|
580
|
-
const value = style[key];
|
|
581
|
-
if (value === void 0 || value === null || value === "") return;
|
|
582
|
-
css[rule[0]] = rule[1](value);
|
|
583
|
-
});
|
|
584
|
-
return css;
|
|
585
|
-
}
|
|
586
|
-
function toRectStyle(rect) {
|
|
587
|
-
if (!Array.isArray(rect)) return {};
|
|
588
|
-
const [x, y, w, h] = rect;
|
|
589
|
-
const css = { position: "absolute", left: px(x || 0), top: px(y || 0) };
|
|
590
|
-
if (w !== void 0 && w !== null && w !== "auto") css.width = px(w);
|
|
591
|
-
if (h !== void 0 && h !== null && h !== "auto") css.height = px(h);
|
|
592
|
-
return css;
|
|
593
|
-
}
|
|
594
|
-
function resolveNodeStyle(node, layout) {
|
|
595
|
-
return Object.assign(
|
|
596
|
-
{},
|
|
597
|
-
layout === "absolute" ? toRectStyle(node.rect) : {},
|
|
598
|
-
toCssStyle(node.style)
|
|
599
|
-
);
|
|
600
|
-
}
|
|
601
|
-
|
|
602
90
|
// src/resolve.ts
|
|
603
91
|
function resolveTree(input) {
|
|
604
92
|
const { normalized, viewStack, ready } = input;
|
|
@@ -714,11 +202,12 @@ function resolveCloseButton(config, layerName, closeTop) {
|
|
|
714
202
|
const offset = config.offset || [8, 8];
|
|
715
203
|
const size = config.size === void 0 ? 26 : config.size;
|
|
716
204
|
const position = config.position || "top-right";
|
|
205
|
+
const image = config.image ? safeImageUrl(config.image) : "";
|
|
206
|
+
const iconMode = image ? "image" : config.icon ? "text" : "svg";
|
|
717
207
|
const style = {
|
|
718
208
|
position: "absolute",
|
|
719
209
|
width: toLength(size),
|
|
720
210
|
height: toLength(size),
|
|
721
|
-
lineHeight: toLength(size),
|
|
722
211
|
display: "flex",
|
|
723
212
|
alignItems: "center",
|
|
724
213
|
justifyContent: "center",
|
|
@@ -726,12 +215,15 @@ function resolveCloseButton(config, layerName, closeTop) {
|
|
|
726
215
|
borderRadius: "50%",
|
|
727
216
|
background: "rgba(0, 0, 0, 0.35)",
|
|
728
217
|
color: "#fff",
|
|
729
|
-
fontSize: "18px",
|
|
730
|
-
textAlign: "center",
|
|
731
218
|
cursor: "pointer",
|
|
732
219
|
userSelect: "none",
|
|
733
220
|
zIndex: "1"
|
|
734
221
|
};
|
|
222
|
+
if (iconMode !== "svg") {
|
|
223
|
+
style.lineHeight = toLength(size);
|
|
224
|
+
style.fontSize = "18px";
|
|
225
|
+
style.textAlign = "center";
|
|
226
|
+
}
|
|
735
227
|
if (position.indexOf("bottom") === 0) style.bottom = toLength(offset[1]);
|
|
736
228
|
else style.top = toLength(offset[1]);
|
|
737
229
|
if (position.indexOf("center") > -1) {
|
|
@@ -744,8 +236,7 @@ function resolveCloseButton(config, layerName, closeTop) {
|
|
|
744
236
|
}
|
|
745
237
|
Object.assign(style, toCssStyle(config.style));
|
|
746
238
|
const onClick = () => closeTop("close-button");
|
|
747
|
-
|
|
748
|
-
if (image) {
|
|
239
|
+
if (iconMode === "image") {
|
|
749
240
|
return {
|
|
750
241
|
key: `${layerName}-close`,
|
|
751
242
|
tag: "div",
|
|
@@ -768,15 +259,81 @@ function resolveCloseButton(config, layerName, closeTop) {
|
|
|
768
259
|
]
|
|
769
260
|
};
|
|
770
261
|
}
|
|
262
|
+
if (iconMode === "text") {
|
|
263
|
+
return {
|
|
264
|
+
key: `${layerName}-close`,
|
|
265
|
+
tag: "div",
|
|
266
|
+
className: "dsl-close",
|
|
267
|
+
style,
|
|
268
|
+
onClick,
|
|
269
|
+
text: config.icon
|
|
270
|
+
};
|
|
271
|
+
}
|
|
771
272
|
return {
|
|
772
273
|
key: `${layerName}-close`,
|
|
773
274
|
tag: "div",
|
|
774
275
|
className: "dsl-close",
|
|
775
276
|
style,
|
|
776
277
|
onClick,
|
|
777
|
-
|
|
278
|
+
children: [closeIcon(`${layerName}-close-icon`, size)]
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
function closeIcon(key, size) {
|
|
282
|
+
const box = clamp(Math.round(toPx(size, 26) * 0.42), 8, 18);
|
|
283
|
+
const stroke = Math.max(1.2, round2(box * 0.15));
|
|
284
|
+
const a = round2(stroke / 2);
|
|
285
|
+
const b = round2(box - stroke / 2);
|
|
286
|
+
const lineAttrs = {
|
|
287
|
+
stroke: "currentColor",
|
|
288
|
+
"stroke-width": String(stroke),
|
|
289
|
+
"stroke-linecap": "round"
|
|
290
|
+
};
|
|
291
|
+
return {
|
|
292
|
+
key,
|
|
293
|
+
tag: "svg",
|
|
294
|
+
className: "dsl-close-icon",
|
|
295
|
+
style: { display: "block" },
|
|
296
|
+
attrs: {
|
|
297
|
+
width: String(box),
|
|
298
|
+
height: String(box),
|
|
299
|
+
viewBox: `0 0 ${box} ${box}`,
|
|
300
|
+
fill: "none",
|
|
301
|
+
"aria-hidden": "true"
|
|
302
|
+
},
|
|
303
|
+
children: [
|
|
304
|
+
{
|
|
305
|
+
key: `${key}-1`,
|
|
306
|
+
tag: "line",
|
|
307
|
+
className: "dsl-close-icon-line",
|
|
308
|
+
style: {},
|
|
309
|
+
attrs: Object.assign(
|
|
310
|
+
{ x1: String(a), y1: String(a), x2: String(b), y2: String(b) },
|
|
311
|
+
lineAttrs
|
|
312
|
+
)
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
key: `${key}-2`,
|
|
316
|
+
tag: "line",
|
|
317
|
+
className: "dsl-close-icon-line",
|
|
318
|
+
style: {},
|
|
319
|
+
attrs: Object.assign(
|
|
320
|
+
{ x1: String(b), y1: String(a), x2: String(a), y2: String(b) },
|
|
321
|
+
lineAttrs
|
|
322
|
+
)
|
|
323
|
+
}
|
|
324
|
+
]
|
|
778
325
|
};
|
|
779
326
|
}
|
|
327
|
+
function toPx(value, fallback) {
|
|
328
|
+
const num = typeof value === "number" ? value : parseFloat(String(value));
|
|
329
|
+
return isFinite(num) && num > 0 ? num : fallback;
|
|
330
|
+
}
|
|
331
|
+
function clamp(value, min, max) {
|
|
332
|
+
return Math.min(max, Math.max(min, value));
|
|
333
|
+
}
|
|
334
|
+
function round2(value) {
|
|
335
|
+
return Math.round(value * 100) / 100;
|
|
336
|
+
}
|
|
780
337
|
var BASE_STYLE = { boxSizing: "border-box" };
|
|
781
338
|
var NODE_CLASS = {
|
|
782
339
|
box: "dsl-box",
|
|
@@ -954,10 +511,13 @@ function resolveCountdown(node, key, style, context, input, countdowns) {
|
|
|
954
511
|
const parts = computeParts(endTime);
|
|
955
512
|
countdowns.endTimes.push(endTime);
|
|
956
513
|
if (node.precision === "cs") countdowns.precision = "cs";
|
|
957
|
-
if (
|
|
514
|
+
if (endTime && node.onEnd) {
|
|
958
515
|
const token = `${key}@${endTime}`;
|
|
959
|
-
|
|
960
|
-
|
|
516
|
+
const status = input.countdownEnds.get(token);
|
|
517
|
+
if (status === void 0) {
|
|
518
|
+
input.countdownEnds.set(token, parts.ended ? "done" : "waiting");
|
|
519
|
+
} else if (status === "waiting" && parts.ended) {
|
|
520
|
+
input.countdownEnds.set(token, "done");
|
|
961
521
|
input.dispatch(node.onEnd, context);
|
|
962
522
|
}
|
|
963
523
|
}
|
|
@@ -1017,7 +577,7 @@ function createRuntime(dsl, options = {}) {
|
|
|
1017
577
|
let loadFailed = false;
|
|
1018
578
|
let destroyed = false;
|
|
1019
579
|
const listeners = /* @__PURE__ */ new Set();
|
|
1020
|
-
const
|
|
580
|
+
const countdownEnds = /* @__PURE__ */ new Map();
|
|
1021
581
|
const notify = () => {
|
|
1022
582
|
if (destroyed) return;
|
|
1023
583
|
listeners.forEach((fn) => fn());
|
|
@@ -1151,7 +711,7 @@ function createRuntime(dsl, options = {}) {
|
|
|
1151
711
|
dispatch,
|
|
1152
712
|
setState,
|
|
1153
713
|
closeTop,
|
|
1154
|
-
|
|
714
|
+
countdownEnds
|
|
1155
715
|
});
|
|
1156
716
|
ticker.sync(tree.countdownEndTimes, tree.countdownPrecision);
|
|
1157
717
|
return tree;
|
|
@@ -1178,427 +738,4 @@ function createRuntime(dsl, options = {}) {
|
|
|
1178
738
|
};
|
|
1179
739
|
}
|
|
1180
740
|
|
|
1181
|
-
|
|
1182
|
-
var LENGTH_STYLE_KEYS = [
|
|
1183
|
-
"width",
|
|
1184
|
-
"height",
|
|
1185
|
-
"minWidth",
|
|
1186
|
-
"minHeight",
|
|
1187
|
-
"maxWidth",
|
|
1188
|
-
"maxHeight",
|
|
1189
|
-
"radius",
|
|
1190
|
-
"padding",
|
|
1191
|
-
"margin",
|
|
1192
|
-
"marginTop",
|
|
1193
|
-
"marginBottom",
|
|
1194
|
-
"marginLeft",
|
|
1195
|
-
"marginRight",
|
|
1196
|
-
"gap",
|
|
1197
|
-
"fontSize",
|
|
1198
|
-
"letterSpacing",
|
|
1199
|
-
"borderWidth"
|
|
1200
|
-
];
|
|
1201
|
-
var DSL_VERSION = 1;
|
|
1202
|
-
var NODE_TYPES = [
|
|
1203
|
-
"box",
|
|
1204
|
-
"flex",
|
|
1205
|
-
"repeat",
|
|
1206
|
-
"image",
|
|
1207
|
-
"text",
|
|
1208
|
-
"button",
|
|
1209
|
-
"tabs",
|
|
1210
|
-
"countdown"
|
|
1211
|
-
];
|
|
1212
|
-
var ACTION_TYPES = [
|
|
1213
|
-
"navigate",
|
|
1214
|
-
"close",
|
|
1215
|
-
"closeAll",
|
|
1216
|
-
"open",
|
|
1217
|
-
"setState",
|
|
1218
|
-
"track",
|
|
1219
|
-
"call",
|
|
1220
|
-
"sequence"
|
|
1221
|
-
];
|
|
1222
|
-
var CLOSE_POSITIONS = [
|
|
1223
|
-
"top-right",
|
|
1224
|
-
"top-left",
|
|
1225
|
-
"top-center",
|
|
1226
|
-
"bottom-right",
|
|
1227
|
-
"bottom-left",
|
|
1228
|
-
"bottom-center"
|
|
1229
|
-
];
|
|
1230
|
-
var CONTAINER_TYPES = ["box", "flex"];
|
|
1231
|
-
function validate(dsl) {
|
|
1232
|
-
const errors = [];
|
|
1233
|
-
const warnings = [];
|
|
1234
|
-
const add = (path, message) => errors.push({ path, message });
|
|
1235
|
-
const warn = (path, message) => warnings.push({ path, message });
|
|
1236
|
-
if (!dsl || typeof dsl !== "object" || Array.isArray(dsl)) {
|
|
1237
|
-
return {
|
|
1238
|
-
valid: false,
|
|
1239
|
-
errors: [{ path: "", message: "\u6839\u8282\u70B9\u5FC5\u987B\u662F\u4E00\u4E2A\u5BF9\u8C61" }],
|
|
1240
|
-
warnings
|
|
1241
|
-
};
|
|
1242
|
-
}
|
|
1243
|
-
const doc = dsl;
|
|
1244
|
-
if (doc.version !== DSL_VERSION) {
|
|
1245
|
-
add(
|
|
1246
|
-
"version",
|
|
1247
|
-
`version \u5FC5\u987B\u662F ${DSL_VERSION}\uFF0C\u5F53\u524D\u4E3A ${JSON.stringify(doc.version)}`
|
|
1248
|
-
);
|
|
1249
|
-
}
|
|
1250
|
-
const dataKeys = validateData(doc.data, add);
|
|
1251
|
-
const stateKeys = validateState(doc.state, add);
|
|
1252
|
-
validateDerived(doc.derived, dataKeys, stateKeys, add);
|
|
1253
|
-
const isMulti = doc.views !== void 0;
|
|
1254
|
-
if (isMulti) validateMultiView(doc, add);
|
|
1255
|
-
const { views } = normalizeViews(doc);
|
|
1256
|
-
const viewNames = Object.keys(views);
|
|
1257
|
-
const ctx = { add, warn, viewNames };
|
|
1258
|
-
viewNames.forEach((name) => {
|
|
1259
|
-
validateView(views[name], isMulti ? `views.${name}` : "", ctx);
|
|
1260
|
-
});
|
|
1261
|
-
return { valid: errors.length === 0, errors, warnings };
|
|
1262
|
-
}
|
|
1263
|
-
function validateMultiView(dsl, add) {
|
|
1264
|
-
if (typeof dsl.views !== "object" || dsl.views === null || Array.isArray(dsl.views)) {
|
|
1265
|
-
add("views", 'views \u5FC5\u987B\u662F\u5BF9\u8C61\uFF0C\u5F62\u5982 { "main": { type, stage, nodes } }');
|
|
1266
|
-
return;
|
|
1267
|
-
}
|
|
1268
|
-
if (!Object.keys(dsl.views).length) {
|
|
1269
|
-
add("views", "views \u81F3\u5C11\u8981\u6709\u4E00\u4E2A\u89C6\u56FE");
|
|
1270
|
-
return;
|
|
1271
|
-
}
|
|
1272
|
-
if (dsl.entry === void 0) {
|
|
1273
|
-
add("entry", "\u591A\u89C6\u56FE\u5FC5\u987B\u6307\u5B9A entry\uFF08\u9996\u4E2A\u5C55\u793A\u7684\u89C6\u56FE\u540D\uFF09");
|
|
1274
|
-
} else if (!dsl.views[dsl.entry]) {
|
|
1275
|
-
add("entry", `entry "${dsl.entry}" \u5728 views \u91CC\u4E0D\u5B58\u5728`);
|
|
1276
|
-
}
|
|
1277
|
-
["stage", "nodes"].forEach((key) => {
|
|
1278
|
-
if (dsl[key] !== void 0) {
|
|
1279
|
-
add(key, `\u7528\u4E86 views \u4E4B\u540E\uFF0C${key} \u8981\u5199\u5728\u6BCF\u4E2A\u89C6\u56FE\u91CC\uFF0C\u4E0D\u80FD\u7559\u5728\u9876\u5C42`);
|
|
1280
|
-
}
|
|
1281
|
-
});
|
|
1282
|
-
}
|
|
1283
|
-
function validateView(view, prefix, ctx) {
|
|
1284
|
-
const { add, warn } = ctx;
|
|
1285
|
-
const at = (key) => prefix ? `${prefix}.${key}` : key;
|
|
1286
|
-
if (!view || typeof view !== "object" || Array.isArray(view)) {
|
|
1287
|
-
add(prefix || "view", "\u89C6\u56FE\u5FC5\u987B\u662F\u5BF9\u8C61\uFF0C\u5305\u542B type / stage / nodes");
|
|
1288
|
-
return;
|
|
1289
|
-
}
|
|
1290
|
-
if (["popup", "banner", "notice"].indexOf(view.type) === -1) {
|
|
1291
|
-
add(at("type"), "type \u5FC5\u987B\u662F popup / banner / notice \u4E4B\u4E00");
|
|
1292
|
-
}
|
|
1293
|
-
validateStage(
|
|
1294
|
-
view.stage,
|
|
1295
|
-
(path, message) => add(prefix ? `${prefix}.${path}` : path, message),
|
|
1296
|
-
warn,
|
|
1297
|
-
ctx,
|
|
1298
|
-
prefix
|
|
1299
|
-
);
|
|
1300
|
-
if (!Array.isArray(view.nodes) || view.nodes.length === 0) {
|
|
1301
|
-
add(at("nodes"), "nodes \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4");
|
|
1302
|
-
return;
|
|
1303
|
-
}
|
|
1304
|
-
const rootLayout = (view.stage || {}).layout === "flow" ? "flow" : "absolute";
|
|
1305
|
-
view.nodes.forEach((node, index) => {
|
|
1306
|
-
validateNode(node, at(`nodes[${index}]`), rootLayout, ctx);
|
|
1307
|
-
});
|
|
1308
|
-
}
|
|
1309
|
-
function checkLength(value) {
|
|
1310
|
-
if (typeof value === "string" && value.indexOf("{{") > -1) return true;
|
|
1311
|
-
if (typeof value === "number") return isLength(value);
|
|
1312
|
-
if (typeof value !== "string") return false;
|
|
1313
|
-
if (isLength(value)) return true;
|
|
1314
|
-
return value.trim().split(/\s+/).every(isLength);
|
|
1315
|
-
}
|
|
1316
|
-
function checkAspectRatio(value) {
|
|
1317
|
-
if (typeof value === "string" && value.indexOf("{{") > -1) return true;
|
|
1318
|
-
if (typeof value === "number") return isFinite(value) && value > 0;
|
|
1319
|
-
if (typeof value !== "string") return false;
|
|
1320
|
-
return /^\s*\d+(\.\d+)?\s*(\/\s*\d+(\.\d+)?\s*)?$/.test(value);
|
|
1321
|
-
}
|
|
1322
|
-
function validateStage(stage, add, warn, ctx, prefix) {
|
|
1323
|
-
if (stage === void 0) {
|
|
1324
|
-
add("stage", "\u7F3A\u5C11 stage");
|
|
1325
|
-
return;
|
|
1326
|
-
}
|
|
1327
|
-
if (typeof stage !== "object" || stage === null) {
|
|
1328
|
-
add("stage", "stage \u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
1329
|
-
return;
|
|
1330
|
-
}
|
|
1331
|
-
if (!checkLength(stage.width)) {
|
|
1332
|
-
add(
|
|
1333
|
-
"stage.width",
|
|
1334
|
-
"stage.width \u5FC5\u987B\u662F\u6570\u5B57(px)\u6216\u957F\u5EA6\u5B57\u7B26\u4E32\uFF0C\u5982 460 / '100%' / 'calc(100% - 32px)'"
|
|
1335
|
-
);
|
|
1336
|
-
}
|
|
1337
|
-
if (!checkLength(stage.height)) {
|
|
1338
|
-
add("stage.height", "stage.height \u5FC5\u987B\u662F\u6570\u5B57(px)\u6216\u957F\u5EA6\u5B57\u7B26\u4E32\uFF0C\u5982 520 / 'auto'");
|
|
1339
|
-
}
|
|
1340
|
-
if (stage.layout !== void 0 && ["absolute", "flow"].indexOf(stage.layout) === -1) {
|
|
1341
|
-
add("stage.layout", "stage.layout \u53EA\u80FD\u662F 'absolute'\uFF08\u9ED8\u8BA4\uFF09\u6216 'flow'");
|
|
1342
|
-
}
|
|
1343
|
-
validateCloseButton(stage.closeButton, add, warn);
|
|
1344
|
-
const at = (key) => prefix ? `${prefix}.stage.${key}` : `stage.${key}`;
|
|
1345
|
-
if (stage.onShow !== void 0) validateAction(stage.onShow, at("onShow"), ctx);
|
|
1346
|
-
if (stage.onClose !== void 0) validateAction(stage.onClose, at("onClose"), ctx);
|
|
1347
|
-
if (stage.height === "auto" && stage.layout !== "flow") {
|
|
1348
|
-
add(
|
|
1349
|
-
"stage.height",
|
|
1350
|
-
"height: 'auto' \u9700\u8981\u540C\u65F6\u8BBE\u7F6E stage.layout: 'flow'\uFF0C\u5426\u5219\u9AD8\u5EA6\u4F1A\u584C\u6210 0"
|
|
1351
|
-
);
|
|
1352
|
-
}
|
|
1353
|
-
}
|
|
1354
|
-
function validateCloseButton(config, add, warn) {
|
|
1355
|
-
if (config === void 0) return;
|
|
1356
|
-
if (typeof config !== "object" || config === null || Array.isArray(config)) {
|
|
1357
|
-
add("stage.closeButton", "closeButton \u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
1358
|
-
return;
|
|
1359
|
-
}
|
|
1360
|
-
if (config.position !== void 0 && CLOSE_POSITIONS.indexOf(config.position) === -1) {
|
|
1361
|
-
add("stage.closeButton.position", `position \u53EA\u80FD\u662F ${CLOSE_POSITIONS.join(" / ")}`);
|
|
1362
|
-
}
|
|
1363
|
-
if (config.offset !== void 0) {
|
|
1364
|
-
if (!Array.isArray(config.offset) || config.offset.length !== 2) {
|
|
1365
|
-
add(
|
|
1366
|
-
"stage.closeButton.offset",
|
|
1367
|
-
"offset \u5FC5\u987B\u662F [x, y] \u4E24\u9879\u6570\u7EC4\uFF0C\u8D1F\u503C\u4F1A\u628A\u6309\u94AE\u79FB\u5230\u5F39\u7A97\u5916\u9762"
|
|
1368
|
-
);
|
|
1369
|
-
} else {
|
|
1370
|
-
config.offset.forEach((value, index) => {
|
|
1371
|
-
if (!checkLength(value)) {
|
|
1372
|
-
add(`stage.closeButton.offset[${index}]`, `"${value}" \u4E0D\u662F\u5408\u6CD5\u957F\u5EA6`);
|
|
1373
|
-
}
|
|
1374
|
-
});
|
|
1375
|
-
}
|
|
1376
|
-
}
|
|
1377
|
-
if (config.size !== void 0 && !checkLength(config.size)) {
|
|
1378
|
-
add("stage.closeButton.size", `"${config.size}" \u4E0D\u662F\u5408\u6CD5\u957F\u5EA6`);
|
|
1379
|
-
}
|
|
1380
|
-
if (config.icon !== void 0 && typeof config.icon !== "string") {
|
|
1381
|
-
add("stage.closeButton.icon", "icon \u5FC5\u987B\u662F\u5B57\u7B26\u4E32");
|
|
1382
|
-
}
|
|
1383
|
-
if (config.image !== void 0 && typeof config.image !== "string") {
|
|
1384
|
-
add("stage.closeButton.image", "image \u5FC5\u987B\u662F\u56FE\u7247\u94FE\u63A5\u5B57\u7B26\u4E32");
|
|
1385
|
-
}
|
|
1386
|
-
if (config.style) {
|
|
1387
|
-
Object.keys(config.style).forEach((key) => {
|
|
1388
|
-
if (ALLOWED_STYLE_KEYS.indexOf(key) === -1) {
|
|
1389
|
-
warn(
|
|
1390
|
-
`stage.closeButton.style.${key}`,
|
|
1391
|
-
`\u6837\u5F0F\u5C5E\u6027 "${key}" \u4E0D\u5728\u767D\u540D\u5355\u5185\uFF0C\u6E32\u67D3\u65F6\u4F1A\u88AB\u5FFD\u7565`
|
|
1392
|
-
);
|
|
1393
|
-
}
|
|
1394
|
-
});
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
function validateData(data, add) {
|
|
1398
|
-
if (data === void 0) return [];
|
|
1399
|
-
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
1400
|
-
add("data", "data \u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
1401
|
-
return [];
|
|
1402
|
-
}
|
|
1403
|
-
Object.keys(data).forEach((key) => {
|
|
1404
|
-
const value = data[key];
|
|
1405
|
-
if (value && typeof value === "object" && !Array.isArray(value) && value.$source) {
|
|
1406
|
-
if (typeof value.$source !== "string") {
|
|
1407
|
-
add(`data.${key}.$source`, "$source \u5FC5\u987B\u662F\u6570\u636E\u6E90\u540D\u79F0\u5B57\u7B26\u4E32");
|
|
1408
|
-
}
|
|
1409
|
-
if (value.params !== void 0 && (typeof value.params !== "object" || value.params === null)) {
|
|
1410
|
-
add(`data.${key}.params`, "params \u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
});
|
|
1414
|
-
return Object.keys(data);
|
|
1415
|
-
}
|
|
1416
|
-
function validateState(state, add) {
|
|
1417
|
-
if (state === void 0) return [];
|
|
1418
|
-
if (typeof state !== "object" || state === null || Array.isArray(state)) {
|
|
1419
|
-
add("state", "state \u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
1420
|
-
return [];
|
|
1421
|
-
}
|
|
1422
|
-
return Object.keys(state);
|
|
1423
|
-
}
|
|
1424
|
-
function validateDerived(derived, dataKeys, stateKeys, add) {
|
|
1425
|
-
if (derived === void 0) return;
|
|
1426
|
-
if (typeof derived !== "object" || derived === null || Array.isArray(derived)) {
|
|
1427
|
-
add("derived", "derived \u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
1428
|
-
return;
|
|
1429
|
-
}
|
|
1430
|
-
Object.keys(derived).forEach((key) => {
|
|
1431
|
-
const item = derived[key] || {};
|
|
1432
|
-
if (typeof item.list !== "string") {
|
|
1433
|
-
add(`derived.${key}.list`, "list \u5FC5\u987B\u662F data \u4E2D\u7684\u6570\u7EC4\u5B57\u6BB5\u540D");
|
|
1434
|
-
} else if (dataKeys.indexOf(item.list) === -1) {
|
|
1435
|
-
add(`derived.${key}.list`, `data \u4E2D\u4E0D\u5B58\u5728 "${item.list}"`);
|
|
1436
|
-
}
|
|
1437
|
-
if (typeof item.indexBy !== "string") {
|
|
1438
|
-
add(`derived.${key}.indexBy`, "indexBy \u5FC5\u987B\u662F state \u4E2D\u7684\u5B57\u6BB5\u540D");
|
|
1439
|
-
} else if (stateKeys.indexOf(item.indexBy) === -1) {
|
|
1440
|
-
add(`derived.${key}.indexBy`, `state \u4E2D\u4E0D\u5B58\u5728 "${item.indexBy}"`);
|
|
1441
|
-
}
|
|
1442
|
-
});
|
|
1443
|
-
}
|
|
1444
|
-
function validateNode(node, path, layout, ctx) {
|
|
1445
|
-
const { add, warn } = ctx;
|
|
1446
|
-
if (!node || typeof node !== "object" || Array.isArray(node)) {
|
|
1447
|
-
add(path, "\u8282\u70B9\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
1448
|
-
return;
|
|
1449
|
-
}
|
|
1450
|
-
if (NODE_TYPES.indexOf(node.type) === -1) {
|
|
1451
|
-
add(`${path}.type`, `\u672A\u77E5\u8282\u70B9\u7C7B\u578B "${node.type}"\uFF0C\u53EF\u7528\uFF1A${NODE_TYPES.join(" / ")}`);
|
|
1452
|
-
return;
|
|
1453
|
-
}
|
|
1454
|
-
if (layout === "absolute" && !Array.isArray(node.rect)) {
|
|
1455
|
-
add(`${path}.rect`, "\u5904\u4E8E\u7EDD\u5BF9\u5B9A\u4F4D\u5BB9\u5668\u4E2D\uFF0C\u5FC5\u987B\u63D0\u4F9B rect: [x, y, w, h]");
|
|
1456
|
-
}
|
|
1457
|
-
if (node.rect !== void 0) {
|
|
1458
|
-
if (!Array.isArray(node.rect)) {
|
|
1459
|
-
add(`${path}.rect`, "rect \u5FC5\u987B\u662F [x, y, w, h] \u6570\u7EC4");
|
|
1460
|
-
} else {
|
|
1461
|
-
node.rect.forEach((value, index) => {
|
|
1462
|
-
if (value !== void 0 && value !== null && !checkLength(value)) {
|
|
1463
|
-
add(
|
|
1464
|
-
`${path}.rect[${index}]`,
|
|
1465
|
-
`"${value}" \u4E0D\u662F\u5408\u6CD5\u957F\u5EA6\uFF0C\u652F\u6301\u6570\u5B57(px) / '100%' / 'auto' \u7B49`
|
|
1466
|
-
);
|
|
1467
|
-
}
|
|
1468
|
-
});
|
|
1469
|
-
}
|
|
1470
|
-
}
|
|
1471
|
-
if (node.style) {
|
|
1472
|
-
Object.keys(node.style).forEach((key) => {
|
|
1473
|
-
if (ALLOWED_STYLE_KEYS.indexOf(key) === -1) {
|
|
1474
|
-
warn(`${path}.style.${key}`, `\u6837\u5F0F\u5C5E\u6027 "${key}" \u4E0D\u5728\u767D\u540D\u5355\u5185\uFF0C\u6E32\u67D3\u65F6\u4F1A\u88AB\u5FFD\u7565`);
|
|
1475
|
-
return;
|
|
1476
|
-
}
|
|
1477
|
-
if (LENGTH_STYLE_KEYS.indexOf(key) > -1 && !checkLength(node.style[key])) {
|
|
1478
|
-
add(
|
|
1479
|
-
`${path}.style.${key}`,
|
|
1480
|
-
`"${node.style[key]}" \u4E0D\u662F\u5408\u6CD5\u957F\u5EA6\uFF0C\u652F\u6301\u6570\u5B57(px) / '100%' / 'auto' \u7B49`
|
|
1481
|
-
);
|
|
1482
|
-
}
|
|
1483
|
-
if (key === "aspectRatio" && !checkAspectRatio(node.style[key])) {
|
|
1484
|
-
add(
|
|
1485
|
-
`${path}.style.aspectRatio`,
|
|
1486
|
-
"aspectRatio \u8981\u5199\u6210 '750 / 200' \u6216 1.5 \u8FD9\u6837\u7684\u5BBD\u9AD8\u6BD4"
|
|
1487
|
-
);
|
|
1488
|
-
}
|
|
1489
|
-
});
|
|
1490
|
-
}
|
|
1491
|
-
if (node.visibleWhen !== void 0) {
|
|
1492
|
-
if (typeof node.visibleWhen !== "string") {
|
|
1493
|
-
add(`${path}.visibleWhen`, "visibleWhen \u5FC5\u987B\u662F\u8868\u8FBE\u5F0F\u5B57\u7B26\u4E32");
|
|
1494
|
-
} else {
|
|
1495
|
-
const error = check(node.visibleWhen);
|
|
1496
|
-
if (error) add(`${path}.visibleWhen`, `\u8868\u8FBE\u5F0F\u6709\u8BEF\uFF1A${error}`);
|
|
1497
|
-
}
|
|
1498
|
-
}
|
|
1499
|
-
if (node.action !== void 0) validateAction(node.action, `${path}.action`, ctx);
|
|
1500
|
-
validateNodeByType(node, path, ctx);
|
|
1501
|
-
}
|
|
1502
|
-
function validateNodeByType(node, path, ctx) {
|
|
1503
|
-
const { add } = ctx;
|
|
1504
|
-
if (node.type === "image" && !node.src) {
|
|
1505
|
-
add(`${path}.src`, "image \u5FC5\u987B\u63D0\u4F9B src");
|
|
1506
|
-
}
|
|
1507
|
-
if (node.type === "text" && node.content === void 0) {
|
|
1508
|
-
add(`${path}.content`, "text \u5FC5\u987B\u63D0\u4F9B content");
|
|
1509
|
-
}
|
|
1510
|
-
if (node.type === "button" && node.text === void 0) {
|
|
1511
|
-
add(`${path}.text`, "button \u5FC5\u987B\u63D0\u4F9B text");
|
|
1512
|
-
}
|
|
1513
|
-
if (node.type === "tabs") {
|
|
1514
|
-
if (typeof node.bind !== "string") {
|
|
1515
|
-
add(`${path}.bind`, "tabs \u5FC5\u987B\u63D0\u4F9B bind\uFF08data \u4E2D\u7684\u6570\u7EC4\u5B57\u6BB5\u540D\uFF09");
|
|
1516
|
-
}
|
|
1517
|
-
if (typeof node.stateKey !== "string")
|
|
1518
|
-
add(`${path}.stateKey`, "tabs \u5FC5\u987B\u63D0\u4F9B stateKey");
|
|
1519
|
-
if (node.labelField !== void 0 && typeof node.labelField !== "string") {
|
|
1520
|
-
add(`${path}.labelField`, "labelField \u5FC5\u987B\u662F\u5B57\u7B26\u4E32");
|
|
1521
|
-
}
|
|
1522
|
-
}
|
|
1523
|
-
if (node.type === "countdown") {
|
|
1524
|
-
if (!node.to) add(`${path}.to`, "countdown \u5FC5\u987B\u63D0\u4F9B to\uFF08\u7ED3\u675F\u65F6\u95F4\uFF09");
|
|
1525
|
-
if (node.precision !== void 0 && ["s", "cs"].indexOf(node.precision) === -1) {
|
|
1526
|
-
add(`${path}.precision`, "precision \u53EA\u80FD\u662F 's'\uFF08\u6BCF\u79D2\uFF09\u6216 'cs'\uFF08\u5398\u79D2\uFF0C\u9010\u5E27\u5237\u65B0\uFF09");
|
|
1527
|
-
}
|
|
1528
|
-
if (node.children !== void 0 && !Array.isArray(node.children)) {
|
|
1529
|
-
add(`${path}.children`, "children \u5FC5\u987B\u662F\u6570\u7EC4");
|
|
1530
|
-
} else {
|
|
1531
|
-
(node.children || []).forEach((child, index) => {
|
|
1532
|
-
validateNode(child, `${path}.children[${index}]`, "flow", ctx);
|
|
1533
|
-
});
|
|
1534
|
-
}
|
|
1535
|
-
}
|
|
1536
|
-
if (node.type === "repeat") {
|
|
1537
|
-
if (typeof node.bind !== "string") add(`${path}.bind`, "repeat \u5FC5\u987B\u63D0\u4F9B bind");
|
|
1538
|
-
if (!node.template) {
|
|
1539
|
-
add(`${path}.template`, "repeat \u5FC5\u987B\u63D0\u4F9B template");
|
|
1540
|
-
} else {
|
|
1541
|
-
validateNode(node.template, `${path}.template`, "flow", ctx);
|
|
1542
|
-
}
|
|
1543
|
-
}
|
|
1544
|
-
if (CONTAINER_TYPES.indexOf(node.type) > -1) {
|
|
1545
|
-
const childLayout = node.type === "box" ? "absolute" : "flow";
|
|
1546
|
-
if (node.children !== void 0 && !Array.isArray(node.children)) {
|
|
1547
|
-
add(`${path}.children`, "children \u5FC5\u987B\u662F\u6570\u7EC4");
|
|
1548
|
-
} else {
|
|
1549
|
-
(node.children || []).forEach((child, index) => {
|
|
1550
|
-
validateNode(child, `${path}.children[${index}]`, childLayout, ctx);
|
|
1551
|
-
});
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
}
|
|
1555
|
-
function validateAction(action, path, ctx) {
|
|
1556
|
-
const { add } = ctx;
|
|
1557
|
-
if (!action || typeof action !== "object" || Array.isArray(action)) {
|
|
1558
|
-
add(path, "action \u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
1559
|
-
return;
|
|
1560
|
-
}
|
|
1561
|
-
if (ACTION_TYPES.indexOf(action.type) === -1) {
|
|
1562
|
-
add(`${path}.type`, `\u672A\u77E5\u52A8\u4F5C "${action.type}"\uFF0C\u53EF\u7528\uFF1A${ACTION_TYPES.join(" / ")}`);
|
|
1563
|
-
return;
|
|
1564
|
-
}
|
|
1565
|
-
if (action.type === "navigate" && !action.url) {
|
|
1566
|
-
add(`${path}.url`, "navigate \u5FC5\u987B\u63D0\u4F9B url");
|
|
1567
|
-
}
|
|
1568
|
-
if (action.type === "setState" && typeof action.key !== "string") {
|
|
1569
|
-
add(`${path}.key`, "setState \u5FC5\u987B\u63D0\u4F9B key");
|
|
1570
|
-
}
|
|
1571
|
-
if (action.type === "track" && !action.event) {
|
|
1572
|
-
add(`${path}.event`, "track \u5FC5\u987B\u63D0\u4F9B event");
|
|
1573
|
-
}
|
|
1574
|
-
if (action.type === "call" && !action.name) {
|
|
1575
|
-
add(`${path}.name`, "call \u5FC5\u987B\u63D0\u4F9B name\uFF08\u5BBF\u4E3B\u6CE8\u518C\u7684\u65B9\u6CD5\u540D\uFF09");
|
|
1576
|
-
}
|
|
1577
|
-
if (action.type === "open") {
|
|
1578
|
-
if (!action.view) {
|
|
1579
|
-
add(`${path}.view`, "open \u5FC5\u987B\u63D0\u4F9B view\uFF08\u8981\u6253\u5F00\u7684\u89C6\u56FE\u540D\uFF09");
|
|
1580
|
-
} else if (ctx.viewNames && ctx.viewNames.indexOf(action.view) === -1) {
|
|
1581
|
-
add(`${path}.view`, `views \u91CC\u4E0D\u5B58\u5728\u89C6\u56FE "${action.view}"`);
|
|
1582
|
-
}
|
|
1583
|
-
if (action.mode !== void 0 && ["stack", "replace"].indexOf(action.mode) === -1) {
|
|
1584
|
-
add(
|
|
1585
|
-
`${path}.mode`,
|
|
1586
|
-
"mode \u53EA\u80FD\u662F 'stack'\uFF08\u9ED8\u8BA4\uFF0C\u53E0\u4E00\u5C42\uFF09\u6216 'replace'\uFF08\u6362\u6389\u5F53\u524D\u5C42\uFF09"
|
|
1587
|
-
);
|
|
1588
|
-
}
|
|
1589
|
-
}
|
|
1590
|
-
if (action.type === "sequence") {
|
|
1591
|
-
if (!Array.isArray(action.actions)) {
|
|
1592
|
-
add(`${path}.actions`, "sequence \u5FC5\u987B\u63D0\u4F9B actions \u6570\u7EC4");
|
|
1593
|
-
} else {
|
|
1594
|
-
action.actions.forEach(
|
|
1595
|
-
(item, index) => validateAction(item, `${path}.actions[${index}]`, ctx)
|
|
1596
|
-
);
|
|
1597
|
-
}
|
|
1598
|
-
}
|
|
1599
|
-
}
|
|
1600
|
-
function formatIssues(issues) {
|
|
1601
|
-
return issues.map((item) => item.path ? `${item.path}: ${item.message}` : item.message).join("\n");
|
|
1602
|
-
}
|
|
1603
|
-
|
|
1604
|
-
export { ACTION_TYPES, ALLOWED_STYLE_KEYS, CLOSE_POSITIONS, DSL_VERSION, NODE_TYPES, SINGLE_VIEW_NAME, check, computeParts, createRuntime, evaluate, formatIssues, formatParts, interpolate, interpolateDeep, isLength, normalizeViews, parseEndTime, safeImageUrl, safeUrl, toCssStyle, toLength, validate };
|
|
741
|
+
export { createRuntime, safeImageUrl, safeUrl };
|