micra.js 2.3.2 → 2.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/CHANGELOG.md +57 -0
- package/README.md +7 -4
- package/dist/index.d.ts +1 -1
- package/dist/micra.cjs.js +296 -48
- package/dist/micra.cjs.js.map +3 -3
- package/dist/micra.esm.js +296 -48
- package/dist/micra.esm.js.map +3 -3
- package/dist/micra.js +296 -48
- package/dist/micra.js.map +3 -3
- package/dist/micra.min.js +3 -2
- package/dist/types.d.ts +1 -0
- package/dist/utils/expr.d.ts +29 -22
- package/llms-full.txt +19 -19
- package/llms.txt +3 -3
- package/package.json +2 -2
- package/src/core/mount.ts +4 -0
- package/src/dom/events.ts +37 -10
- package/src/index.ts +1 -1
- package/src/types.ts +1 -0
- package/src/utils/expr.ts +278 -121
package/dist/micra.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Micra.js v2.
|
|
1
|
+
/* Micra.js v2.4.0 — https://github.com/micra-js/micra — MIT */
|
|
2
2
|
"use strict";
|
|
3
3
|
var Micra = (() => {
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -116,42 +116,196 @@ var Micra = (() => {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
// src/utils/expr.ts
|
|
119
|
-
var exprCache = /* @__PURE__ */ new Map();
|
|
120
|
-
var warnedRuntime = /* @__PURE__ */ new Set();
|
|
121
|
-
var SIMPLE_PATH = /^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/;
|
|
122
119
|
var ALLOWED_GLOBALS = new Set(
|
|
123
120
|
"Math,JSON,Date,String,Number,Boolean,Array,Object,parseInt,parseFloat,isNaN,isFinite,NaN,Infinity,undefined".split(",")
|
|
124
121
|
);
|
|
125
|
-
var
|
|
126
|
-
var PARAM_SAFE = "$safe";
|
|
127
|
-
var SAFE_OUTER = new Proxy(/* @__PURE__ */ Object.create(null), {
|
|
128
|
-
has(_target, key) {
|
|
129
|
-
if (typeof key !== "string") return false;
|
|
130
|
-
if (key === PARAM_S || key === PARAM_SAFE) return false;
|
|
131
|
-
return !ALLOWED_GLOBALS.has(key);
|
|
132
|
-
},
|
|
133
|
-
get() {
|
|
134
|
-
return void 0;
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
var safeWrapCache = /* @__PURE__ */ new WeakMap();
|
|
122
|
+
var BLOCKED_PROPS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
138
123
|
var OBJ_PROTO_KEYS = new Set(Object.getOwnPropertyNames(Object.prototype));
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
124
|
+
var PUNCT = [
|
|
125
|
+
"===",
|
|
126
|
+
"!==",
|
|
127
|
+
"==",
|
|
128
|
+
"!=",
|
|
129
|
+
"<=",
|
|
130
|
+
">=",
|
|
131
|
+
"&&",
|
|
132
|
+
"||",
|
|
133
|
+
"(",
|
|
134
|
+
")",
|
|
135
|
+
".",
|
|
136
|
+
",",
|
|
137
|
+
"?",
|
|
138
|
+
":",
|
|
139
|
+
"!",
|
|
140
|
+
"<",
|
|
141
|
+
">",
|
|
142
|
+
"+",
|
|
143
|
+
"-",
|
|
144
|
+
"*",
|
|
145
|
+
"/",
|
|
146
|
+
"%"
|
|
147
|
+
];
|
|
148
|
+
function tokenize(src) {
|
|
149
|
+
var _a;
|
|
150
|
+
const toks = [];
|
|
151
|
+
let i = 0;
|
|
152
|
+
const n = src.length;
|
|
153
|
+
while (i < n) {
|
|
154
|
+
const c = src[i];
|
|
155
|
+
if (c === " " || c === " " || c === "\n" || c === "\r" || c === "\f") {
|
|
156
|
+
i++;
|
|
157
|
+
continue;
|
|
148
158
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
159
|
+
if (c === '"' || c === "'") {
|
|
160
|
+
let s = "";
|
|
161
|
+
i++;
|
|
162
|
+
while (i < n && src[i] !== c) {
|
|
163
|
+
if (src[i] === "\\") {
|
|
164
|
+
s += (_a = src[i + 1]) != null ? _a : "";
|
|
165
|
+
i += 2;
|
|
166
|
+
} else {
|
|
167
|
+
s += src[i];
|
|
168
|
+
i++;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (src[i] !== c) throw 0;
|
|
172
|
+
i++;
|
|
173
|
+
toks.push({ t: "str", v: s });
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (c >= "0" && c <= "9") {
|
|
177
|
+
let s = "";
|
|
178
|
+
while (i < n && (src[i] >= "0" && src[i] <= "9" || src[i] === ".")) {
|
|
179
|
+
s += src[i];
|
|
180
|
+
i++;
|
|
181
|
+
}
|
|
182
|
+
toks.push({ t: "num", v: s });
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (/[A-Za-z_$]/.test(c)) {
|
|
186
|
+
let s = "";
|
|
187
|
+
while (i < n && /[A-Za-z0-9_$]/.test(src[i])) {
|
|
188
|
+
s += src[i];
|
|
189
|
+
i++;
|
|
190
|
+
}
|
|
191
|
+
toks.push({ t: "id", v: s });
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const m = PUNCT.find((p) => src.startsWith(p, i));
|
|
195
|
+
if (!m) throw 0;
|
|
196
|
+
toks.push({ t: "p", v: m });
|
|
197
|
+
i += m.length;
|
|
198
|
+
}
|
|
199
|
+
return toks;
|
|
200
|
+
}
|
|
201
|
+
var BIN_PREC = {
|
|
202
|
+
"||": 1,
|
|
203
|
+
"&&": 2,
|
|
204
|
+
"==": 3,
|
|
205
|
+
"!=": 3,
|
|
206
|
+
"===": 3,
|
|
207
|
+
"!==": 3,
|
|
208
|
+
"<": 4,
|
|
209
|
+
"<=": 4,
|
|
210
|
+
">": 4,
|
|
211
|
+
">=": 4,
|
|
212
|
+
"+": 5,
|
|
213
|
+
"-": 5,
|
|
214
|
+
"*": 6,
|
|
215
|
+
"/": 6,
|
|
216
|
+
"%": 6
|
|
217
|
+
};
|
|
218
|
+
function parse(toks) {
|
|
219
|
+
let pos = 0;
|
|
220
|
+
const peek = () => toks[pos];
|
|
221
|
+
const next = () => toks[pos++];
|
|
222
|
+
const eat = (v) => {
|
|
223
|
+
var _a;
|
|
224
|
+
if (((_a = peek()) == null ? void 0 : _a.v) !== v) throw 0;
|
|
225
|
+
pos++;
|
|
226
|
+
};
|
|
227
|
+
function parseExpr() {
|
|
228
|
+
var _a;
|
|
229
|
+
const c = parseBin(1);
|
|
230
|
+
if (((_a = peek()) == null ? void 0 : _a.v) === "?") {
|
|
231
|
+
next();
|
|
232
|
+
const a = parseExpr();
|
|
233
|
+
eat(":");
|
|
234
|
+
const b = parseExpr();
|
|
235
|
+
return { k: "tern", c, a, b };
|
|
236
|
+
}
|
|
237
|
+
return c;
|
|
238
|
+
}
|
|
239
|
+
function parseBin(minPrec) {
|
|
240
|
+
let left = parseUnary();
|
|
241
|
+
for (; ; ) {
|
|
242
|
+
const t = peek();
|
|
243
|
+
const prec = t && t.t === "p" ? BIN_PREC[t.v] : void 0;
|
|
244
|
+
if (prec === void 0 || prec < minPrec) break;
|
|
245
|
+
next();
|
|
246
|
+
const right = parseBin(prec + 1);
|
|
247
|
+
left = { k: "bin", op: t.v, l: left, r: right };
|
|
248
|
+
}
|
|
249
|
+
return left;
|
|
250
|
+
}
|
|
251
|
+
function parseUnary() {
|
|
252
|
+
const t = peek();
|
|
253
|
+
if (t && t.t === "p" && (t.v === "!" || t.v === "-")) {
|
|
254
|
+
next();
|
|
255
|
+
return { k: "un", op: t.v, x: parseUnary() };
|
|
256
|
+
}
|
|
257
|
+
return parsePostfix();
|
|
258
|
+
}
|
|
259
|
+
function parsePostfix() {
|
|
260
|
+
var _a, _b;
|
|
261
|
+
let node = parsePrimary();
|
|
262
|
+
for (; ; ) {
|
|
263
|
+
const t = peek();
|
|
264
|
+
if ((t == null ? void 0 : t.v) === ".") {
|
|
265
|
+
next();
|
|
266
|
+
const id = next();
|
|
267
|
+
if (!id || id.t !== "id") throw 0;
|
|
268
|
+
node = { k: "mem", o: node, p: id.v };
|
|
269
|
+
} else if ((t == null ? void 0 : t.v) === "(") {
|
|
270
|
+
next();
|
|
271
|
+
const args = [];
|
|
272
|
+
if (((_a = peek()) == null ? void 0 : _a.v) !== ")") {
|
|
273
|
+
args.push(parseExpr());
|
|
274
|
+
while (((_b = peek()) == null ? void 0 : _b.v) === ",") {
|
|
275
|
+
next();
|
|
276
|
+
args.push(parseExpr());
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
eat(")");
|
|
280
|
+
node = { k: "call", c: node, a: args };
|
|
281
|
+
} else break;
|
|
282
|
+
}
|
|
283
|
+
return node;
|
|
284
|
+
}
|
|
285
|
+
function parsePrimary() {
|
|
286
|
+
const t = next();
|
|
287
|
+
if (!t) throw 0;
|
|
288
|
+
if (t.t === "num") return { k: "lit", v: Number(t.v) };
|
|
289
|
+
if (t.t === "str") return { k: "lit", v: t.v };
|
|
290
|
+
if (t.v === "(") {
|
|
291
|
+
const e = parseExpr();
|
|
292
|
+
eat(")");
|
|
293
|
+
return e;
|
|
294
|
+
}
|
|
295
|
+
if (t.t === "id") {
|
|
296
|
+
if (t.v === "true") return { k: "lit", v: true };
|
|
297
|
+
if (t.v === "false") return { k: "lit", v: false };
|
|
298
|
+
if (t.v === "null") return { k: "lit", v: null };
|
|
299
|
+
if (t.v === "undefined") return { k: "lit", v: void 0 };
|
|
300
|
+
return { k: "id", n: t.v };
|
|
301
|
+
}
|
|
302
|
+
throw 0;
|
|
303
|
+
}
|
|
304
|
+
const ast = parseExpr();
|
|
305
|
+
if (pos !== toks.length) throw 0;
|
|
306
|
+
return ast;
|
|
152
307
|
}
|
|
153
308
|
function safeStateHas(state, key) {
|
|
154
|
-
if (typeof key !== "string") return false;
|
|
155
309
|
if (!Reflect.has(state, key)) return false;
|
|
156
310
|
if (!OBJ_PROTO_KEYS.has(key)) return true;
|
|
157
311
|
let obj = state;
|
|
@@ -161,6 +315,87 @@ var Micra = (() => {
|
|
|
161
315
|
}
|
|
162
316
|
return false;
|
|
163
317
|
}
|
|
318
|
+
function resolveIdent(name, scope) {
|
|
319
|
+
if (safeStateHas(scope, name)) return scope[name];
|
|
320
|
+
if (ALLOWED_GLOBALS.has(name)) return globalThis[name];
|
|
321
|
+
return void 0;
|
|
322
|
+
}
|
|
323
|
+
function evalNode(node, scope) {
|
|
324
|
+
switch (node.k) {
|
|
325
|
+
case "lit":
|
|
326
|
+
return node.v;
|
|
327
|
+
case "id":
|
|
328
|
+
return resolveIdent(node.n, scope);
|
|
329
|
+
case "mem": {
|
|
330
|
+
const o = evalNode(node.o, scope);
|
|
331
|
+
if (o == null || BLOCKED_PROPS.has(node.p)) return void 0;
|
|
332
|
+
return o[node.p];
|
|
333
|
+
}
|
|
334
|
+
case "un": {
|
|
335
|
+
const x = evalNode(node.x, scope);
|
|
336
|
+
return node.op === "!" ? !x : -x;
|
|
337
|
+
}
|
|
338
|
+
case "tern":
|
|
339
|
+
return evalNode(node.c, scope) ? evalNode(node.a, scope) : evalNode(node.b, scope);
|
|
340
|
+
case "bin": {
|
|
341
|
+
const op = node.op;
|
|
342
|
+
if (op === "&&") {
|
|
343
|
+
const l2 = evalNode(node.l, scope);
|
|
344
|
+
return l2 ? evalNode(node.r, scope) : l2;
|
|
345
|
+
}
|
|
346
|
+
if (op === "||") {
|
|
347
|
+
const l2 = evalNode(node.l, scope);
|
|
348
|
+
return l2 ? l2 : evalNode(node.r, scope);
|
|
349
|
+
}
|
|
350
|
+
const l = evalNode(node.l, scope);
|
|
351
|
+
const r = evalNode(node.r, scope);
|
|
352
|
+
switch (op) {
|
|
353
|
+
case "+":
|
|
354
|
+
return l + r;
|
|
355
|
+
case "-":
|
|
356
|
+
return l - r;
|
|
357
|
+
case "*":
|
|
358
|
+
return l * r;
|
|
359
|
+
case "/":
|
|
360
|
+
return l / r;
|
|
361
|
+
case "%":
|
|
362
|
+
return l % r;
|
|
363
|
+
case "<":
|
|
364
|
+
return l < r;
|
|
365
|
+
case "<=":
|
|
366
|
+
return l <= r;
|
|
367
|
+
case ">":
|
|
368
|
+
return l > r;
|
|
369
|
+
case ">=":
|
|
370
|
+
return l >= r;
|
|
371
|
+
case "==":
|
|
372
|
+
return l == r;
|
|
373
|
+
case "!=":
|
|
374
|
+
return l != r;
|
|
375
|
+
case "===":
|
|
376
|
+
return l === r;
|
|
377
|
+
case "!==":
|
|
378
|
+
return l !== r;
|
|
379
|
+
}
|
|
380
|
+
return void 0;
|
|
381
|
+
}
|
|
382
|
+
case "call": {
|
|
383
|
+
let fn;
|
|
384
|
+
let self;
|
|
385
|
+
if (node.c.k === "mem") {
|
|
386
|
+
self = evalNode(node.c.o, scope);
|
|
387
|
+
fn = self == null || BLOCKED_PROPS.has(node.c.p) ? void 0 : self[node.c.p];
|
|
388
|
+
} else {
|
|
389
|
+
fn = evalNode(node.c, scope);
|
|
390
|
+
}
|
|
391
|
+
if (typeof fn !== "function") throw new TypeError("not a function");
|
|
392
|
+
return fn.apply(self, node.a.map((x) => evalNode(x, scope)));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
var exprCache = /* @__PURE__ */ new Map();
|
|
397
|
+
var warnedRuntime = /* @__PURE__ */ new Set();
|
|
398
|
+
var SIMPLE_PATH = /^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/;
|
|
164
399
|
function evalExpr(expr, state) {
|
|
165
400
|
let cached = exprCache.get(expr);
|
|
166
401
|
if (!cached) {
|
|
@@ -168,26 +403,24 @@ var Micra = (() => {
|
|
|
168
403
|
cached = { kind: "path", parts: expr.split(".") };
|
|
169
404
|
} else {
|
|
170
405
|
try {
|
|
171
|
-
cached = {
|
|
172
|
-
kind: "fn",
|
|
173
|
-
fn: new Function("$s", "$safe", `with($safe){with($s){return (${expr})}}`)
|
|
174
|
-
};
|
|
406
|
+
cached = { kind: "ast", ast: parse(tokenize(expr)) };
|
|
175
407
|
} catch {
|
|
176
408
|
warn(`invalid expression "${expr}"`);
|
|
177
|
-
cached = { kind: "
|
|
409
|
+
cached = { kind: "err" };
|
|
178
410
|
}
|
|
179
411
|
}
|
|
180
412
|
exprCache.set(expr, cached);
|
|
181
413
|
}
|
|
182
414
|
if (cached.kind === "path") {
|
|
183
|
-
|
|
184
|
-
return
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
415
|
+
const parts = cached.parts;
|
|
416
|
+
if (!safeStateHas(state, parts[0])) return void 0;
|
|
417
|
+
let obj = state;
|
|
418
|
+
for (const key of parts) obj = obj != null ? obj[key] : void 0;
|
|
419
|
+
return obj;
|
|
188
420
|
}
|
|
421
|
+
if (cached.kind === "err") return void 0;
|
|
189
422
|
try {
|
|
190
|
-
return cached.
|
|
423
|
+
return evalNode(cached.ast, state);
|
|
191
424
|
} catch (e) {
|
|
192
425
|
if (!warnedRuntime.has(expr)) {
|
|
193
426
|
warnedRuntime.add(expr);
|
|
@@ -347,6 +580,23 @@ var Micra = (() => {
|
|
|
347
580
|
el.addEventListener(type, fn);
|
|
348
581
|
((_a = instance.__micraListeners) != null ? _a : instance.__micraListeners = []).push({ el, type, fn });
|
|
349
582
|
}
|
|
583
|
+
function runHandler(instance, el, value, e) {
|
|
584
|
+
var _a;
|
|
585
|
+
if (value.includes("(")) {
|
|
586
|
+
let base;
|
|
587
|
+
for (let n = el; n && !base; n = n.parentElement) {
|
|
588
|
+
base = n._itemState;
|
|
589
|
+
}
|
|
590
|
+
const scope = Object.create((_a = base != null ? base : instance.__micraExpr) != null ? _a : null);
|
|
591
|
+
scope["$event"] = e;
|
|
592
|
+
scope["event"] = e;
|
|
593
|
+
evalExpr(value, scope);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
const fn = instance[value];
|
|
597
|
+
if (typeof fn === "function") fn.call(instance, e);
|
|
598
|
+
else warn(`method "${value}" not found`);
|
|
599
|
+
}
|
|
350
600
|
function bindDataOn(els, instance) {
|
|
351
601
|
var _a;
|
|
352
602
|
for (const el of els) {
|
|
@@ -358,13 +608,12 @@ var Micra = (() => {
|
|
|
358
608
|
const [evSpec, method] = part.trim().split(":");
|
|
359
609
|
if (!evSpec || !method) continue;
|
|
360
610
|
const [evName, ...mods] = evSpec.split(".");
|
|
611
|
+
const handler = method.trim();
|
|
361
612
|
track(instance, el, evName, (e) => {
|
|
362
613
|
if (mods.includes("prevent")) e.preventDefault();
|
|
363
614
|
if (mods.includes("stop")) e.stopPropagation();
|
|
364
615
|
if (mods.includes("self") && e.target !== el) return;
|
|
365
|
-
|
|
366
|
-
if (typeof fn === "function") fn.call(instance, e);
|
|
367
|
-
else warn(`method "${method.trim()}" not found`);
|
|
616
|
+
runHandler(instance, el, handler, e);
|
|
368
617
|
});
|
|
369
618
|
}
|
|
370
619
|
}
|
|
@@ -377,14 +626,12 @@ var Micra = (() => {
|
|
|
377
626
|
for (const attr of Array.from(el.attributes)) {
|
|
378
627
|
if (!attr.name.startsWith("@")) continue;
|
|
379
628
|
const [evSpec, ...rest] = attr.name.slice(1).split(".");
|
|
380
|
-
const
|
|
629
|
+
const handler = attr.value.trim();
|
|
381
630
|
track(instance, el, evSpec, (e) => {
|
|
382
631
|
if (rest.includes("prevent")) e.preventDefault();
|
|
383
632
|
if (rest.includes("stop")) e.stopPropagation();
|
|
384
633
|
if (rest.includes("self") && e.target !== el) return;
|
|
385
|
-
|
|
386
|
-
if (typeof fn === "function") fn.call(instance, e);
|
|
387
|
-
else warn(`method "${method}" not found`);
|
|
634
|
+
runHandler(instance, el, handler, e);
|
|
388
635
|
});
|
|
389
636
|
bound = true;
|
|
390
637
|
}
|
|
@@ -794,6 +1041,7 @@ var Micra = (() => {
|
|
|
794
1041
|
return Object.prototype.hasOwnProperty.call(instance, key) && typeof instance[key] === "function";
|
|
795
1042
|
}
|
|
796
1043
|
});
|
|
1044
|
+
instance.__micraExpr = exprState;
|
|
797
1045
|
let warnedReentry = false;
|
|
798
1046
|
instance.render = function() {
|
|
799
1047
|
var _a2;
|