@optionfactory/fml 8.0.0 → 8.0.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/dist/client-errors.iife.js +11 -8
- package/dist/client-errors.iife.js.map +1 -1
- package/dist/client-errors.iife.min.js +1 -1
- package/dist/client-errors.iife.min.js.map +1 -1
- package/dist/custom-elements.json +1210 -0
- package/dist/fml.css +10 -1
- package/dist/fml.css.map +1 -1
- package/dist/fml.d.mts +73 -13
- package/dist/fml.iife.js +628 -209
- package/dist/fml.iife.js.map +1 -1
- package/dist/fml.iife.min.js +1 -1
- package/dist/fml.iife.min.js.map +1 -1
- package/dist/fml.min.mjs +1 -1
- package/dist/fml.min.mjs.map +1 -1
- package/dist/fml.mjs +628 -209
- package/dist/fml.mjs.map +1 -1
- package/dist/ftl.d.mts +2 -1
- package/dist/ftl.iife.js +90 -34
- package/dist/ftl.iife.js.map +1 -1
- package/dist/ftl.iife.min.js +1 -1
- package/dist/ftl.iife.min.js.map +1 -1
- package/dist/ftl.min.mjs +1 -1
- package/dist/ftl.min.mjs.map +1 -1
- package/dist/ftl.mjs +90 -34
- package/dist/ftl.mjs.map +1 -1
- package/dist/ful.css +10 -1
- package/dist/ful.css.map +1 -1
- package/dist/ful.d.mts +22 -6
- package/dist/ful.iife.js +496 -166
- package/dist/ful.iife.js.map +1 -1
- package/dist/ful.iife.min.js +1 -1
- package/dist/ful.iife.min.js.map +1 -1
- package/dist/ful.min.mjs +1 -1
- package/dist/ful.min.mjs.map +1 -1
- package/dist/ful.mjs +496 -166
- package/dist/ful.mjs.map +1 -1
- package/dist/httpc.d.mts +49 -6
- package/dist/httpc.iife.js +40 -9
- package/dist/httpc.iife.js.map +1 -1
- package/dist/httpc.iife.min.js +1 -1
- package/dist/httpc.iife.min.js.map +1 -1
- package/dist/httpc.min.mjs +1 -1
- package/dist/httpc.min.mjs.map +1 -1
- package/dist/httpc.mjs +40 -9
- package/dist/httpc.mjs.map +1 -1
- package/dist/vscode.html-custom-data.json +357 -0
- package/dist/web-types.json +1006 -0
- package/package.json +11 -9
package/dist/ftl.d.mts
CHANGED
|
@@ -252,8 +252,9 @@ declare class Template {
|
|
|
252
252
|
* @param {string} expression
|
|
253
253
|
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode]
|
|
254
254
|
* @param {...*} data
|
|
255
|
+
* @returns the evaluated expression result
|
|
255
256
|
*/
|
|
256
|
-
evaluate(expression: string, mode?: (typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED) | null, ...data: any[]):
|
|
257
|
+
evaluate(expression: string, mode?: (typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED) | null, ...data: any[]): any;
|
|
257
258
|
/**
|
|
258
259
|
* Returns an expression evaluator with bound modules and dataStack.
|
|
259
260
|
*/
|
package/dist/ftl.iife.js
CHANGED
|
@@ -3460,7 +3460,7 @@ var ftl = (function (exports) {
|
|
|
3460
3460
|
case '<=':
|
|
3461
3461
|
return lhs <= rhs;
|
|
3462
3462
|
default:
|
|
3463
|
-
throw new Error(
|
|
3463
|
+
throw new Error(`unknown cmp op ${node.op}`);
|
|
3464
3464
|
}
|
|
3465
3465
|
}
|
|
3466
3466
|
[nodes.call](node) {
|
|
@@ -3471,7 +3471,7 @@ var ftl = (function (exports) {
|
|
|
3471
3471
|
}
|
|
3472
3472
|
const fn = module[fnRef.value];
|
|
3473
3473
|
if (!fn) {
|
|
3474
|
-
throw new Error(`Function "#${fnRef.module === null ? '' : fnRef.module
|
|
3474
|
+
throw new Error(`Function "#${fnRef.module === null ? '' : `${fnRef.module}:`}${fnRef.value}" not found`);
|
|
3475
3475
|
}
|
|
3476
3476
|
const args = node.args.map((arg) => this.visit(arg));
|
|
3477
3477
|
return fn.apply(this.#resolve_proxy(), args);
|
|
@@ -3507,14 +3507,14 @@ var ftl = (function (exports) {
|
|
|
3507
3507
|
return cond ? cond : this.visit(node.ifFalse);
|
|
3508
3508
|
}
|
|
3509
3509
|
[nodes.access](node) {
|
|
3510
|
-
let prev
|
|
3510
|
+
let prev ;
|
|
3511
3511
|
let cur = this.visit(node.lhs);
|
|
3512
3512
|
for (let i = 0; i !== node.rhs.length; ++i) {
|
|
3513
3513
|
const rhs = node.rhs[i];
|
|
3514
3514
|
if (rhs.ns && cur == null) {
|
|
3515
3515
|
return undefined;
|
|
3516
3516
|
}
|
|
3517
|
-
let value
|
|
3517
|
+
let value ;
|
|
3518
3518
|
switch (rhs.type) {
|
|
3519
3519
|
case nodes.member: {
|
|
3520
3520
|
value = cur[rhs.rhs];
|
|
@@ -3555,7 +3555,7 @@ var ftl = (function (exports) {
|
|
|
3555
3555
|
case nodes.templated.ten:
|
|
3556
3556
|
return { type: nodes.dom.n, value: this.visit(node.value) };
|
|
3557
3557
|
default:
|
|
3558
|
-
throw new Error(
|
|
3558
|
+
throw new Error(`unknown node type ${node.type.toString()}`);
|
|
3559
3559
|
}
|
|
3560
3560
|
});
|
|
3561
3561
|
}
|
|
@@ -3731,7 +3731,7 @@ var ftl = (function (exports) {
|
|
|
3731
3731
|
.forEach((a) => {
|
|
3732
3732
|
const target = a.substring(prefix.length);
|
|
3733
3733
|
if (target === 'class') {
|
|
3734
|
-
const classes = from.getAttribute(prefix
|
|
3734
|
+
const classes = from.getAttribute(`${prefix}class`)?.split(/\s+/).filter((a) => a.length) ?? [];
|
|
3735
3735
|
to.classList.add(...classes);
|
|
3736
3736
|
return;
|
|
3737
3737
|
}
|
|
@@ -3823,8 +3823,7 @@ var ftl = (function (exports) {
|
|
|
3823
3823
|
* @returns
|
|
3824
3824
|
*/
|
|
3825
3825
|
static isParsed(el) {
|
|
3826
|
-
|
|
3827
|
-
for (let c = el; c; c = c.parentNode) {
|
|
3826
|
+
for (let c = /** @type {Node | null} */ (el); c; c = c.parentNode) {
|
|
3828
3827
|
if (c.nextSibling) {
|
|
3829
3828
|
return true;
|
|
3830
3829
|
}
|
|
@@ -3887,19 +3886,18 @@ var ftl = (function (exports) {
|
|
|
3887
3886
|
}
|
|
3888
3887
|
|
|
3889
3888
|
class NodeOperations {
|
|
3890
|
-
#forRemoval;
|
|
3891
|
-
constructor() {
|
|
3892
|
-
this.#forRemoval = [];
|
|
3893
|
-
}
|
|
3889
|
+
#forRemoval = new Set();
|
|
3894
3890
|
removed(node) {
|
|
3895
|
-
return this.#forRemoval.
|
|
3891
|
+
return this.#forRemoval.has(node);
|
|
3896
3892
|
}
|
|
3897
3893
|
remove(node) {
|
|
3898
3894
|
node.replaceChildren?.();
|
|
3899
3895
|
Object.keys(node.dataset || {})
|
|
3900
3896
|
.filter((k) => k.startsWith('tpl'))
|
|
3901
|
-
.forEach((k) =>
|
|
3902
|
-
|
|
3897
|
+
.forEach((k) => {
|
|
3898
|
+
delete node.dataset[k];
|
|
3899
|
+
});
|
|
3900
|
+
this.#forRemoval.add(node);
|
|
3903
3901
|
}
|
|
3904
3902
|
popData(node, key) {
|
|
3905
3903
|
const v = node.dataset[key];
|
|
@@ -3917,9 +3915,10 @@ var ftl = (function (exports) {
|
|
|
3917
3915
|
this.remove(ref);
|
|
3918
3916
|
}
|
|
3919
3917
|
cleanup() {
|
|
3920
|
-
|
|
3921
|
-
|
|
3918
|
+
for (const node of this.#forRemoval) {
|
|
3919
|
+
node.remove();
|
|
3922
3920
|
}
|
|
3921
|
+
this.#forRemoval.clear();
|
|
3923
3922
|
}
|
|
3924
3923
|
}
|
|
3925
3924
|
|
|
@@ -3974,7 +3973,7 @@ var ftl = (function (exports) {
|
|
|
3974
3973
|
}
|
|
3975
3974
|
static tplRemove(node, value, ops, modules, dataStack) {
|
|
3976
3975
|
switch (value.toLowerCase()) {
|
|
3977
|
-
case 'tag':
|
|
3976
|
+
case 'tag': {
|
|
3978
3977
|
const fragment = new DocumentFragment();
|
|
3979
3978
|
while (node.firstChild) {
|
|
3980
3979
|
fragment.appendChild(node.firstChild);
|
|
@@ -3988,6 +3987,7 @@ var ftl = (function (exports) {
|
|
|
3988
3987
|
ops.remove(node);
|
|
3989
3988
|
}
|
|
3990
3989
|
break;
|
|
3990
|
+
}
|
|
3991
3991
|
case 'body':
|
|
3992
3992
|
node.replaceChildren();
|
|
3993
3993
|
break;
|
|
@@ -4053,8 +4053,10 @@ var ftl = (function (exports) {
|
|
|
4053
4053
|
}
|
|
4054
4054
|
}
|
|
4055
4055
|
|
|
4056
|
-
// Module-isolated string cache for dataset-to-attribute conversions
|
|
4056
|
+
// Module-isolated string cache for dataset-to-attribute conversions, bounded with
|
|
4057
|
+
// FIFO eviction like the expression ast cache
|
|
4057
4058
|
const attributeCache = new Map();
|
|
4059
|
+
const ATTRIBUTE_CACHE_MAX_SIZE = 1000;
|
|
4058
4060
|
|
|
4059
4061
|
/**
|
|
4060
4062
|
* Converts a tpl camelCase dataset key into a kebab-case attribute name.
|
|
@@ -4065,6 +4067,9 @@ var ftl = (function (exports) {
|
|
|
4065
4067
|
function toAttr(dataSetKey) {
|
|
4066
4068
|
let cached = attributeCache.get(dataSetKey);
|
|
4067
4069
|
if (!cached) {
|
|
4070
|
+
if (attributeCache.size >= ATTRIBUTE_CACHE_MAX_SIZE) {
|
|
4071
|
+
attributeCache.delete(attributeCache.keys().next().value);
|
|
4072
|
+
}
|
|
4068
4073
|
cached = dataSetKey
|
|
4069
4074
|
.substring(3)
|
|
4070
4075
|
.split(/(?=[A-Z])/)
|
|
@@ -4199,9 +4204,10 @@ var ftl = (function (exports) {
|
|
|
4199
4204
|
* @param {string} expression
|
|
4200
4205
|
* @param {(typeof Expressions.MODE_EXPRESSION | typeof Expressions.MODE_TEMPLATED)?} [mode]
|
|
4201
4206
|
* @param {...*} data
|
|
4207
|
+
* @returns the evaluated expression result
|
|
4202
4208
|
*/
|
|
4203
4209
|
evaluate(expression, mode, ...data) {
|
|
4204
|
-
new ExpressionEvaluator(this.#modules, this.#dataStack).withOverlay(...data).evaluate(expression, mode);
|
|
4210
|
+
return new ExpressionEvaluator(this.#modules, this.#dataStack).withOverlay(...data).evaluate(expression, mode);
|
|
4205
4211
|
}
|
|
4206
4212
|
/**
|
|
4207
4213
|
* Returns an expression evaluator with bound modules and dataStack.
|
|
@@ -4346,8 +4352,8 @@ var ftl = (function (exports) {
|
|
|
4346
4352
|
if (node.nodeType === Node.TEXT_NODE) {
|
|
4347
4353
|
node.nodeValue = node.nodeValue.trim();
|
|
4348
4354
|
}
|
|
4349
|
-
for (
|
|
4350
|
-
|
|
4355
|
+
for (let n = 0; n < node.childNodes.length; n++) {
|
|
4356
|
+
const child = node.childNodes[n];
|
|
4351
4357
|
if (child.nodeType === Node.TEXT_NODE) {
|
|
4352
4358
|
child.nodeValue = child.nodeValue.trim();
|
|
4353
4359
|
if (child.nodeValue.length === 0) {
|
|
@@ -4366,8 +4372,7 @@ var ftl = (function (exports) {
|
|
|
4366
4372
|
#q = new Map();
|
|
4367
4373
|
constructor() {
|
|
4368
4374
|
document.addEventListener('DOMContentLoaded', async () => {
|
|
4369
|
-
|
|
4370
|
-
await Promise.all(pending);
|
|
4375
|
+
await this.settle();
|
|
4371
4376
|
document.dispatchEvent(
|
|
4372
4377
|
new CustomEvent('ftl:ready', {
|
|
4373
4378
|
bubbles: false,
|
|
@@ -4376,16 +4381,39 @@ var ftl = (function (exports) {
|
|
|
4376
4381
|
);
|
|
4377
4382
|
});
|
|
4378
4383
|
}
|
|
4384
|
+
#finished = new Map();
|
|
4379
4385
|
enqueue(el) {
|
|
4380
4386
|
if (this.#q.has(el)) {
|
|
4381
4387
|
//already upgrading, can happen when disconnecting an element
|
|
4382
4388
|
//while it's already queued for upgrade (e.g.: ful-form)
|
|
4383
4389
|
return;
|
|
4384
4390
|
}
|
|
4391
|
+
//settling waits on a signal that only ever resolves, so nothing here attaches a
|
|
4392
|
+
//rejection handler to the upgrade itself: a component that fails is still
|
|
4393
|
+
//reported the way it always was
|
|
4394
|
+
const { promise: finished, resolve: markFinished } = /** @type {PromiseWithResolvers<void>} */ (
|
|
4395
|
+
Promise.withResolvers()
|
|
4396
|
+
);
|
|
4385
4397
|
const promise = Nodes.waitParsed(el)
|
|
4386
4398
|
.then(() => el.upgrade())
|
|
4387
|
-
.finally(() =>
|
|
4399
|
+
.finally(() => {
|
|
4400
|
+
this.#q.delete(el);
|
|
4401
|
+
this.#finished.delete(el);
|
|
4402
|
+
markFinished();
|
|
4403
|
+
});
|
|
4388
4404
|
this.#q.set(el, promise);
|
|
4405
|
+
this.#finished.set(el, finished);
|
|
4406
|
+
}
|
|
4407
|
+
/**
|
|
4408
|
+
* Waits for every queued upgrade to settle, including the ones enqueued while
|
|
4409
|
+
* waiting: a component is only queued once its parent connects it, so a single pass
|
|
4410
|
+
* would miss everything nested. A component that fails to upgrade does not hold the
|
|
4411
|
+
* others back, readiness means the queue drained rather than that everything worked.
|
|
4412
|
+
*/
|
|
4413
|
+
async settle() {
|
|
4414
|
+
while (this.#finished.size !== 0) {
|
|
4415
|
+
await Promise.all(Array.from(this.#finished.values()));
|
|
4416
|
+
}
|
|
4389
4417
|
}
|
|
4390
4418
|
get entries() {
|
|
4391
4419
|
return this.#q.entries();
|
|
@@ -4581,18 +4609,30 @@ var ftl = (function (exports) {
|
|
|
4581
4609
|
}
|
|
4582
4610
|
}
|
|
4583
4611
|
|
|
4584
|
-
|
|
4585
|
-
|
|
4612
|
+
/**
|
|
4613
|
+
* Waits for the queued upgrades matching the filter, including the ones enqueued while
|
|
4614
|
+
* waiting: a component is only queued once its parent connects it, so a single pass
|
|
4615
|
+
* would miss everything nested.
|
|
4616
|
+
* @param {(el: Element) => boolean} accept
|
|
4617
|
+
*/
|
|
4618
|
+
const settle = async (accept) => {
|
|
4619
|
+
for (;;) {
|
|
4586
4620
|
const pending = Array.from(registry.upgrades)
|
|
4587
|
-
.filter(([child
|
|
4588
|
-
.map(([
|
|
4621
|
+
.filter(([child]) => accept(child))
|
|
4622
|
+
.map(([, promise]) => promise);
|
|
4623
|
+
if (pending.length === 0) {
|
|
4624
|
+
return;
|
|
4625
|
+
}
|
|
4589
4626
|
await Promise.all(pending);
|
|
4590
4627
|
}
|
|
4628
|
+
};
|
|
4629
|
+
|
|
4630
|
+
class Rendering {
|
|
4631
|
+
static async waitFor(el) {
|
|
4632
|
+
await settle((child) => el.contains(child));
|
|
4633
|
+
}
|
|
4591
4634
|
static async waitForChildren(el) {
|
|
4592
|
-
|
|
4593
|
-
.filter(([child, promise]) => el !== child && el.contains(child))
|
|
4594
|
-
.map(([child, promise]) => promise);
|
|
4595
|
-
await Promise.all(pending);
|
|
4635
|
+
await settle((child) => el !== child && el.contains(child));
|
|
4596
4636
|
}
|
|
4597
4637
|
}
|
|
4598
4638
|
|
|
@@ -4634,7 +4674,7 @@ var ftl = (function (exports) {
|
|
|
4634
4674
|
template(name) {
|
|
4635
4675
|
const { modules, data } = registry.context();
|
|
4636
4676
|
let t = this.#bits().TEMPLATES[name ?? 'default'].withData(data).withModules(modules);
|
|
4637
|
-
for (
|
|
4677
|
+
for (const k of ['l10n', 'config']) {
|
|
4638
4678
|
const v = this.constructor[k];
|
|
4639
4679
|
if (v) {
|
|
4640
4680
|
t = t.withOverlay({ [k]: v });
|
|
@@ -4664,6 +4704,19 @@ var ftl = (function (exports) {
|
|
|
4664
4704
|
return;
|
|
4665
4705
|
}
|
|
4666
4706
|
Reflect.set(this, 'disabled', disabled);
|
|
4707
|
+
if (disabled) {
|
|
4708
|
+
this.#unclaimFormDisabled();
|
|
4709
|
+
}
|
|
4710
|
+
}
|
|
4711
|
+
//a disabled ancestor fieldset already matches the element through :disabled, and
|
|
4712
|
+
//an attribute of its own would keep the element disabled once the fieldset is
|
|
4713
|
+
//re-enabled, as formDisabledCallback(false) is only delivered on an actual state
|
|
4714
|
+
//change. a claim of its own made while already disabled by ancestry is safe: the
|
|
4715
|
+
//platform fires no callback for it, so it survives the fieldset being re-enabled
|
|
4716
|
+
#unclaimFormDisabled() {
|
|
4717
|
+
if (this.closest('fieldset:disabled')) {
|
|
4718
|
+
this.removeAttribute('disabled');
|
|
4719
|
+
}
|
|
4667
4720
|
}
|
|
4668
4721
|
async upgrade() {
|
|
4669
4722
|
if (this.#parsed) {
|
|
@@ -4679,6 +4732,9 @@ var ftl = (function (exports) {
|
|
|
4679
4732
|
);
|
|
4680
4733
|
const disabled = this.#disabledBeforeParsed ?? false;
|
|
4681
4734
|
await this.render({ slots, observed, disabled });
|
|
4735
|
+
if (disabled) {
|
|
4736
|
+
this.#unclaimFormDisabled();
|
|
4737
|
+
}
|
|
4682
4738
|
}
|
|
4683
4739
|
render(c) {}
|
|
4684
4740
|
reflect(fn) {
|