marko 6.3.34 → 6.3.36
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/cheatsheet.md +2 -2
- package/dist/common/constants/accessor-prefix.d.ts +1 -0
- package/dist/common/constants/accessor-prefix.debug.d.ts +1 -0
- package/dist/common/errors.d.ts +1 -0
- package/dist/common/meta.d.ts +1 -0
- package/dist/common/types.d.ts +10 -0
- package/dist/debug/dom/catch.feat.js +1 -1
- package/dist/debug/dom/catch.feat.mjs +1 -1
- package/dist/debug/dom/controllable-input.feat.js +1 -1
- package/dist/debug/dom/controllable-input.feat.mjs +1 -1
- package/dist/debug/dom/controllable-open.feat.js +1 -1
- package/dist/debug/dom/controllable-open.feat.mjs +1 -1
- package/dist/debug/dom/controllable-select.feat.js +1 -1
- package/dist/debug/dom/controllable-select.feat.mjs +1 -1
- package/dist/debug/dom/controllable-textarea.feat.js +1 -1
- package/dist/debug/dom/controllable-textarea.feat.mjs +1 -1
- package/dist/debug/dom/controllable.feat.js +1 -1
- package/dist/debug/dom/controllable.feat.mjs +1 -1
- package/dist/debug/dom/dynamic-tag-var.feat.js +7 -0
- package/dist/debug/dom/dynamic-tag-var.feat.mjs +6 -0
- package/dist/debug/{dom-Bj58jt8y.js → dom-BbFAdZEB.js} +54 -17
- package/dist/debug/{dom-klf8Ec_o.mjs → dom-ClMc0GK9.mjs} +43 -18
- package/dist/debug/dom.js +1 -1
- package/dist/debug/dom.mjs +1 -1
- package/dist/debug/html.js +94 -25
- package/dist/debug/html.mjs +94 -25
- package/dist/dom/catch.feat.js +4 -4
- package/dist/dom/catch.feat.mjs +1 -1
- package/dist/dom/control-flow.d.ts +3 -0
- package/dist/dom/controllable-input.feat.js +2 -2
- package/dist/dom/controllable-input.feat.mjs +1 -1
- package/dist/dom/controllable-open.feat.js +2 -2
- package/dist/dom/controllable-open.feat.mjs +1 -1
- package/dist/dom/controllable-select.feat.js +2 -2
- package/dist/dom/controllable-select.feat.mjs +1 -1
- package/dist/dom/controllable-textarea.feat.js +2 -2
- package/dist/dom/controllable-textarea.feat.mjs +1 -1
- package/dist/dom/controllable.feat.js +2 -2
- package/dist/dom/controllable.feat.mjs +1 -1
- package/dist/dom/dynamic-tag-var.feat.d.ts +1 -0
- package/dist/dom/dynamic-tag-var.feat.js +3 -0
- package/dist/dom/dynamic-tag-var.feat.mjs +4 -0
- package/dist/dom/signals.d.ts +3 -3
- package/dist/{dom-B-XpL2_H.js → dom-59H9kVUF.js} +133 -118
- package/dist/{dom-6hBvZW7X.mjs → dom-BKDjlXIl.mjs} +25 -15
- package/dist/dom.js +34 -34
- package/dist/dom.mjs +1 -1
- package/dist/html/dynamic-tag.d.ts +1 -1
- package/dist/html/serializer.d.ts +9 -1
- package/dist/html/template.d.ts +1 -0
- package/dist/html/writer.d.ts +1 -0
- package/dist/html.js +19 -13
- package/dist/html.mjs +19 -13
- package/dist/translator/index.js +287 -101
- package/dist/translator/util/references.d.ts +1 -0
- package/dist/translator/util/runtime.d.ts +1 -1
- package/dist/translator/util/signals.d.ts +2 -0
- package/dist/translator/util/translate-var.d.ts +1 -1
- package/dist/translator/util/traverse.d.ts +2 -0
- package/dist/translator/visitors/export-declaration.d.ts +8 -0
- package/package.json +4 -4
- package/tags/let.d.marko +3 -4
package/cheatsheet.md
CHANGED
|
@@ -13,8 +13,8 @@ Marko 6 = HTML superset, not JSX and not Marko 4/5 syntax. `.marko` files are co
|
|
|
13
13
|
- remove: `items = items.toSpliced(i, 1)`
|
|
14
14
|
- update: `items = items.toSpliced(i, 1, { ...item, done: true })`
|
|
15
15
|
- object: `user = { ...user, name }`
|
|
16
|
-
6. Events: method shorthand `onClick() { ... }` or `onClick=fn`. Handlers receive `(event, element)`; delegation means the element is the second parameter, not `event.currentTarget`: `onSubmit(e) { e.preventDefault(); save() }`, `onClick(e, el) { el.focus() }`. Don't sync input values through `onInput`/`onChange`; that's what the change handlers below are for.
|
|
17
|
-
7. Native inputs are uncontrolled by default: `value=`
|
|
16
|
+
6. Events: method shorthand `onClick() { ... }` or `onClick=fn`. Handlers receive `(event, element)`; delegation means the element is the second parameter, not `event.currentTarget`: `onSubmit(e) { e.preventDefault(); save() }`, `onClick(e, el) { el.focus() }`. Don't sync input values through `onInput`/`onChange`; that's what the change handlers below are for. Prefix with `async` to `await` in the body: `async onClick() { await save() }`.
|
|
17
|
+
7. Native inputs are uncontrolled by default: `value=` sets the default value — later writes update what `form.reset()` restores, never a dirty field's display. Adding the matching `*Change` handler is what makes them controlled: `valueChange` on `<input>`/`<textarea>`/`<select>`, `checkedChange` on checkboxes/radios, `openChange` on `<details>`/`<dialog>`. `value:=text` is the shorthand for `value=text valueChange(v) { text = v }`. (`<textarea value:=text/>`: value attribute, not body.)
|
|
18
18
|
8. Transform in the handler when needed; number inputs give strings: `<input type="number" value=n valueChange(v) { n = +v }>`, or `value:parseFloat:=n`.
|
|
19
19
|
9. Radio/checkbox groups: `checkedValue:=picked` on each input (shared var, distinct `value=`); the match is checked; array var for multi-checkbox. Dropdown: `<select value:=picked>`.
|
|
20
20
|
10. Module-level values and helpers need `static`: `static const LIMIT = 10`, `static function fmt(n) {…}`. Without it `function fmt(n) {` parses as a tag: ``Unable to find entry point for custom tag `<function>` ``, an error that never says `static`. Prefer it to `<const>` for anything that never changes: `<const/LIMIT=10>` emits a per-instance signal plus a `$setup` call.
|
|
@@ -8,6 +8,7 @@ export declare const ControlledType = "F";
|
|
|
8
8
|
export declare const ControlledValue = "G";
|
|
9
9
|
export declare const DynamicHTMLLastChild = "H";
|
|
10
10
|
export declare const EventAttributes = "I";
|
|
11
|
+
export declare const IdFallback = "J";
|
|
11
12
|
export declare const KeyedScopes = "O";
|
|
12
13
|
export declare const Lifecycle = "K";
|
|
13
14
|
export declare const Promise = "L";
|
|
@@ -8,6 +8,7 @@ export declare const ControlledType = "ControlledType:";
|
|
|
8
8
|
export declare const ControlledValue = "ControlledValue:";
|
|
9
9
|
export declare const DynamicHTMLLastChild = "DynamicHTMLLastChild:";
|
|
10
10
|
export declare const EventAttributes = "EventAttributes:";
|
|
11
|
+
export declare const IdFallback = "IdFallback:";
|
|
11
12
|
export declare const KeyedScopes = "KeyedScopes:";
|
|
12
13
|
export declare const Lifecycle = "Lifecycle:";
|
|
13
14
|
export declare const Promise = "Promise:";
|
package/dist/common/errors.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare function _el_read_error(): void;
|
|
|
9
9
|
export declare function _hoist_read_error(): void;
|
|
10
10
|
export declare function _assert_hoist(value: unknown): void;
|
|
11
11
|
export declare function assertExclusiveAttrs(attrs: Record<string, unknown> | undefined, onError?: typeof throwErr): void;
|
|
12
|
+
export declare function assertNoValueBindingOnCheckable(type: unknown, valueChange: unknown): void;
|
|
12
13
|
export declare function assertHandlerIsFunction(name: string, value: unknown): void;
|
|
13
14
|
export declare function assertValidTagName(tagName: string): void;
|
|
14
15
|
declare function throwErr(msg: string): void;
|
package/dist/common/meta.d.ts
CHANGED
package/dist/common/types.d.ts
CHANGED
|
@@ -73,6 +73,16 @@ export interface MountedTemplate {
|
|
|
73
73
|
}
|
|
74
74
|
export type RenderedTemplate = PromiseLike<string> & AsyncIterable<string> & {
|
|
75
75
|
toReadable(): ReadableStream<Uint8Array<ArrayBufferLike>>;
|
|
76
|
+
pipe(stream: {
|
|
77
|
+
write(chunk: string): unknown;
|
|
78
|
+
end(): unknown;
|
|
79
|
+
flush?(): void;
|
|
80
|
+
destroy?(): void;
|
|
81
|
+
emit?(name: PropertyKey, ...args: unknown[]): unknown;
|
|
82
|
+
}): void;
|
|
83
|
+
toString(): string;
|
|
84
|
+
catch<T = never>(onrejected?: ((reason: unknown) => T | PromiseLike<T>) | undefined | null): Promise<string | T>;
|
|
85
|
+
finally(onfinally?: (() => void) | undefined | null): Promise<string>;
|
|
76
86
|
};
|
|
77
87
|
type ControlledType = ControlledType.Value;
|
|
78
88
|
export { ControlledType };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Cn as
|
|
1
|
+
import { Cn as ParentBranch, Qt as placeholderShown, Tn as PendingRenders, Xt as caughtError, Zt as installCatch, g as renderCatch, gn as Scope, hn as Pending, vn as ClosestBranch, wn as PendingEffects } from "../dom-ClMc0GK9.mjs";
|
|
2
2
|
//#region src/dom/catch.feat.ts
|
|
3
3
|
const handlePendingTry = (fn, scope, branch) => {
|
|
4
4
|
while (branch) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const require_control_flow = require("../dom-
|
|
2
|
+
const require_control_flow = require("../dom-BbFAdZEB.js");
|
|
3
3
|
//#region src/dom/controllable-input.feat.ts
|
|
4
4
|
require_control_flow.controllableScripts[0] = require_control_flow._attr_input_checked_script;
|
|
5
5
|
require_control_flow.controllableScripts[1] = require_control_flow._attr_input_checkedValue_script;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as _attr_input_value_script, C as _attr_input_checkedValue_script, T as _attr_input_checked_script, z as controllableScripts } from "../dom-ClMc0GK9.mjs";
|
|
2
2
|
//#region src/dom/controllable-input.feat.ts
|
|
3
3
|
controllableScripts[0] = _attr_input_checked_script;
|
|
4
4
|
controllableScripts[1] = _attr_input_checkedValue_script;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const require_control_flow = require("../dom-
|
|
2
|
+
const require_control_flow = require("../dom-BbFAdZEB.js");
|
|
3
3
|
//#region src/dom/controllable-open.feat.ts
|
|
4
4
|
require_control_flow.controllableScripts[4] = require_control_flow._attr_details_or_dialog_open_script;
|
|
5
5
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { y as _attr_details_or_dialog_open_script, z as controllableScripts } from "../dom-ClMc0GK9.mjs";
|
|
2
2
|
//#region src/dom/controllable-open.feat.ts
|
|
3
3
|
controllableScripts[4] = _attr_details_or_dialog_open_script;
|
|
4
4
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const require_control_flow = require("../dom-
|
|
2
|
+
const require_control_flow = require("../dom-BbFAdZEB.js");
|
|
3
3
|
//#region src/dom/controllable-select.feat.ts
|
|
4
4
|
require_control_flow.controllableScripts[3] = require_control_flow._attr_select_value_script;
|
|
5
5
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { N as _attr_select_value_script, z as controllableScripts } from "../dom-ClMc0GK9.mjs";
|
|
2
2
|
//#region src/dom/controllable-select.feat.ts
|
|
3
3
|
controllableScripts[3] = _attr_select_value_script;
|
|
4
4
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
const require_control_flow = require("../dom-
|
|
2
|
+
const require_control_flow = require("../dom-BbFAdZEB.js");
|
|
3
3
|
//#region src/dom/controllable-textarea.feat.ts
|
|
4
4
|
require_control_flow.controllableScripts[2] = require_control_flow._attr_input_value_script;
|
|
5
5
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as _attr_input_value_script, z as controllableScripts } from "../dom-ClMc0GK9.mjs";
|
|
2
2
|
//#region src/dom/controllable-textarea.feat.ts
|
|
3
3
|
controllableScripts[2] = _attr_input_value_script;
|
|
4
4
|
//#endregion
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as
|
|
1
|
+
import { F as _controllable_open, I as _controllable_select, L as _controllable_textarea, P as _controllable_input, R as controllableRenders } from "../dom-ClMc0GK9.mjs";
|
|
2
2
|
import "./controllable-input.feat.mjs";
|
|
3
3
|
import "./controllable-open.feat.mjs";
|
|
4
4
|
import "./controllable-select.feat.mjs";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const require_control_flow = require("../dom-BbFAdZEB.js");
|
|
3
|
+
//#region src/dom/dynamic-tag-var.feat.ts
|
|
4
|
+
const elementGetter = (branch) => () => require_control_flow._el_read(branch[require_control_flow.StartNode]);
|
|
5
|
+
require_control_flow.installDynamicTagVar((branch) => branch[require_control_flow.TagVariable](elementGetter(branch)));
|
|
6
|
+
require_control_flow._resume(require_control_flow.DYNAMIC_TAG_VAR_REGISTER_ID, elementGetter);
|
|
7
|
+
//#endregion
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Dn as TagVariable, En as StartNode, Et as _el_read, gt as _resume, m as installDynamicTagVar, qt as DYNAMIC_TAG_VAR_REGISTER_ID } from "../dom-ClMc0GK9.mjs";
|
|
2
|
+
//#region src/dom/dynamic-tag-var.feat.ts
|
|
3
|
+
const elementGetter = (branch) => () => _el_read(branch[StartNode]);
|
|
4
|
+
installDynamicTagVar((branch) => branch[TagVariable](elementGetter(branch)));
|
|
5
|
+
_resume(DYNAMIC_TAG_VAR_REGISTER_ID, elementGetter);
|
|
6
|
+
//#endregion
|
|
@@ -254,10 +254,16 @@ function assertExclusiveAttrs(attrs, onError = throwErr) {
|
|
|
254
254
|
(exclusiveAttrs ||= []).push("checkedValueChange");
|
|
255
255
|
if ("checked" in attrs) exclusiveAttrs.push("checked");
|
|
256
256
|
}
|
|
257
|
-
if (attrs.valueChange)
|
|
257
|
+
if (attrs.valueChange) {
|
|
258
|
+
(exclusiveAttrs ||= []).push("valueChange");
|
|
259
|
+
if ("checked" in attrs && !exclusiveAttrs.includes("checked")) exclusiveAttrs.push("checked");
|
|
260
|
+
}
|
|
258
261
|
if (exclusiveAttrs && exclusiveAttrs.length > 1) onError(`The attributes ${joinWithAnd(exclusiveAttrs)} are mutually exclusive.`);
|
|
259
262
|
}
|
|
260
263
|
}
|
|
264
|
+
function assertNoValueBindingOnCheckable(type, valueChange) {
|
|
265
|
+
if (valueChange && /^(?:button|checkbox|hidden|image|radio|reset|submit)$/i.test(type)) console.error(`\`valueChange\` cannot be used on a \`type="${type}"\` \`<input>\` — user interaction can never change its \`value\`.` + (/^[cr]/i.test(type) ? " Bind `checked` or `checkedValue` instead." : ""));
|
|
266
|
+
}
|
|
261
267
|
function assertHandlerIsFunction(name, value) {
|
|
262
268
|
if (value && typeof value !== "function") throw new Error(`The \`${name}\` handler must be a function or a falsey value (\`null\`, \`undefined\`, \`false\`, \`0\`, …), but received type "${typeof value}".`);
|
|
263
269
|
}
|
|
@@ -440,6 +446,7 @@ function abort(ctrl) {
|
|
|
440
446
|
//#endregion
|
|
441
447
|
//#region src/common/meta.ts
|
|
442
448
|
const DYNAMIC_TAG_SCRIPT_REGISTER_ID = "_dynamicTagScript";
|
|
449
|
+
const DYNAMIC_TAG_VAR_REGISTER_ID = "_dynamicTagVar";
|
|
443
450
|
//#endregion
|
|
444
451
|
//#region src/common/opt.ts
|
|
445
452
|
function toArray(opt) {
|
|
@@ -742,10 +749,16 @@ const _var_change = (scope, value, name = "This") => {
|
|
|
742
749
|
scope[TagVariableChange](value);
|
|
743
750
|
};
|
|
744
751
|
const tagIdsByGlobal = /* @__PURE__ */ new WeakMap();
|
|
745
|
-
function _id(
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
752
|
+
function _id(scope, accessor) {
|
|
753
|
+
let id = accessor !== void 0 && scope[accessor];
|
|
754
|
+
if (!id) {
|
|
755
|
+
const $global = scope[Global];
|
|
756
|
+
const n = tagIdsByGlobal.get($global) || 0;
|
|
757
|
+
tagIdsByGlobal.set($global, n + 1);
|
|
758
|
+
id = "c" + $global.runtimeId + $global.renderId + n.toString(36);
|
|
759
|
+
if (accessor !== void 0) scope[accessor] = id;
|
|
760
|
+
}
|
|
761
|
+
return id;
|
|
749
762
|
}
|
|
750
763
|
function _script(id, fn) {
|
|
751
764
|
_resume(id, fn);
|
|
@@ -757,19 +770,19 @@ function _el_read(value) {
|
|
|
757
770
|
if (rendering) _el_read_error();
|
|
758
771
|
return value;
|
|
759
772
|
}
|
|
760
|
-
function* traverse(scope, path, i = path.length - 1) {
|
|
773
|
+
function* traverse(scope, path, args, i = path.length - 1) {
|
|
761
774
|
if (rendering) _hoist_read_error();
|
|
762
|
-
if (scope) if (Symbol.iterator in scope) for (const childScope of scope.values()) yield* traverse(childScope, path, i);
|
|
775
|
+
if (scope) if (Symbol.iterator in scope) for (const childScope of scope.values()) yield* traverse(childScope, path, args, i);
|
|
763
776
|
else {
|
|
764
777
|
const item = scope[path[i]];
|
|
765
|
-
if (i) yield* traverse(item, path, i - 1);
|
|
766
|
-
else yield typeof item === "function" ? item() : item;
|
|
778
|
+
if (i) yield* traverse(item, path, args, i - 1);
|
|
779
|
+
else yield typeof item === "function" ? item(...args) : item;
|
|
767
780
|
}
|
|
768
781
|
}
|
|
769
782
|
function _hoist(...path) {
|
|
770
783
|
return (scope) => {
|
|
771
|
-
const fn = () => traverse(scope, path).next().value;
|
|
772
|
-
fn[Symbol.iterator] = () => traverse(scope, path);
|
|
784
|
+
const fn = (...args) => traverse(scope, path, args).next().value;
|
|
785
|
+
fn[Symbol.iterator] = () => traverse(scope, path, []);
|
|
773
786
|
return fn;
|
|
774
787
|
};
|
|
775
788
|
}
|
|
@@ -1149,7 +1162,7 @@ function _style_shell(scope, nodeAccessor) {
|
|
|
1149
1162
|
const element = scope[nodeAccessor];
|
|
1150
1163
|
const id = _id(scope);
|
|
1151
1164
|
_attr_nonce(scope, nodeAccessor);
|
|
1152
|
-
element
|
|
1165
|
+
_attr(element, "class", id);
|
|
1153
1166
|
_text_content(element, "." + id + "~*{}");
|
|
1154
1167
|
}
|
|
1155
1168
|
function _style_rule_item(element, name, value) {
|
|
@@ -1236,7 +1249,7 @@ function attrsInternal(scope, nodeAccessor, nextAttrs, controllable) {
|
|
|
1236
1249
|
}
|
|
1237
1250
|
function _attr_content(scope, nodeAccessor, value) {
|
|
1238
1251
|
const content = normalizeClientRender(value);
|
|
1239
|
-
if (scope["ConditionalRenderer:" + nodeAccessor] !== (scope["ConditionalRenderer:" + nodeAccessor] = content
|
|
1252
|
+
if (scope["ConditionalRenderer:" + nodeAccessor] !== (scope["ConditionalRenderer:" + nodeAccessor] = rendererKey(content))) {
|
|
1240
1253
|
setConditionalRenderer(scope, nodeAccessor, content, createAndSetupBranch);
|
|
1241
1254
|
if (content?.["accessor"]) subscribeToScopeSet(content[Owner], content[Accessor], scope[BranchScopes$1 + nodeAccessor]);
|
|
1242
1255
|
}
|
|
@@ -1416,17 +1429,19 @@ function _attr_input_value(scope, nodeAccessor, value, valueChange, setDefault =
|
|
|
1416
1429
|
const el = scope[nodeAccessor];
|
|
1417
1430
|
const normalizedValue = normalizeAttrValue(value) || "";
|
|
1418
1431
|
assertHandlerIsFunction("valueChange", valueChange);
|
|
1432
|
+
assertNoValueBindingOnCheckable(el.type, valueChange);
|
|
1419
1433
|
scope[ControlledHandler + nodeAccessor] = valueChange;
|
|
1420
1434
|
scope[ControlledValue + nodeAccessor] = normalizedValue;
|
|
1421
1435
|
scope[ControlledType + nodeAccessor] = valueChange ? 2 : 5;
|
|
1422
1436
|
if (valueChange && scope["#Gen"] < runId) setInputValue(el, normalizedValue);
|
|
1423
|
-
else setDefault(scope, nodeAccessor,
|
|
1437
|
+
else setDefault(scope, nodeAccessor, value);
|
|
1424
1438
|
}
|
|
1425
1439
|
function _attr_input_value_attribute_default(scope, nodeAccessor, value) {
|
|
1426
1440
|
_attr(scope[nodeAccessor], "value", value);
|
|
1427
1441
|
}
|
|
1428
1442
|
function _attr_input_value_script(scope, nodeAccessor) {
|
|
1429
1443
|
const el = scope[nodeAccessor];
|
|
1444
|
+
assertNoValueBindingOnCheckable(el.type, scope[ControlledHandler + nodeAccessor]);
|
|
1430
1445
|
if (isResuming) scope[ControlledValue + nodeAccessor] = el.defaultValue;
|
|
1431
1446
|
syncControllableFormInput(el, hasValueChanged, (ev) => {
|
|
1432
1447
|
const valueChange = scope[ControlledHandler + nodeAccessor];
|
|
@@ -1834,6 +1849,9 @@ const _show = /*@__PURE__*/ withBranches((nodeAccessor, startNodeAccessor, endNo
|
|
|
1834
1849
|
}
|
|
1835
1850
|
};
|
|
1836
1851
|
});
|
|
1852
|
+
function rendererKey(renderer) {
|
|
1853
|
+
return renderer?.["owner"] ? renderer["id"] + " " + renderer[Owner]["#Id"] : renderer?.["id"] || renderer;
|
|
1854
|
+
}
|
|
1837
1855
|
function patchDynamicTag(fn) {
|
|
1838
1856
|
_dynamic_tag = fn(_dynamic_tag);
|
|
1839
1857
|
}
|
|
@@ -1842,9 +1860,12 @@ let _dynamic_tag = /*@__PURE__*/ withBranches((nodeAccessor, getContent, getTagV
|
|
|
1842
1860
|
const rendererAccessor = ConditionalRenderer + nodeAccessor;
|
|
1843
1861
|
return (scope, newRenderer, getInput) => {
|
|
1844
1862
|
const normalizedRenderer = normalizeDynamicRenderer(newRenderer);
|
|
1845
|
-
if (scope[rendererAccessor] !== (scope[rendererAccessor] = normalizedRenderer
|
|
1863
|
+
if (scope[rendererAccessor] !== (scope[rendererAccessor] = rendererKey(normalizedRenderer)) || getContent && !(normalizedRenderer || scope[childScopeAccessor])) {
|
|
1846
1864
|
setConditionalRenderer(scope, nodeAccessor, normalizedRenderer || (getContent ? getContent(scope) : void 0), createBranchWithTagNameOrRenderer);
|
|
1847
|
-
if (getTagVar) scope[childScopeAccessor]
|
|
1865
|
+
if (getTagVar) if (scope[childScopeAccessor]) {
|
|
1866
|
+
scope[childScopeAccessor][TagVariable] = (value) => getTagVar()(scope, value);
|
|
1867
|
+
if (typeof normalizedRenderer === "string") bindNativeTagVar?.(scope[childScopeAccessor]);
|
|
1868
|
+
} else getTagVar()(scope, void 0);
|
|
1848
1869
|
if (typeof normalizedRenderer === "string") {
|
|
1849
1870
|
if (getContent) {
|
|
1850
1871
|
const content = getContent(scope);
|
|
@@ -1878,13 +1899,17 @@ const _dynamic_tag_content = /*@__PURE__*/ withBranches((nodeAccessor) => {
|
|
|
1878
1899
|
const childScopeAccessor = BranchScopes$1 + nodeAccessor;
|
|
1879
1900
|
const rendererAccessor = ConditionalRenderer + nodeAccessor;
|
|
1880
1901
|
return (scope, renderer) => {
|
|
1881
|
-
if (scope[rendererAccessor] !== (scope[rendererAccessor] = renderer
|
|
1902
|
+
if (scope[rendererAccessor] !== (scope[rendererAccessor] = rendererKey(renderer))) {
|
|
1882
1903
|
setConditionalRenderer(scope, nodeAccessor, renderer, createAndSetupBranch);
|
|
1883
1904
|
if (renderer?.["accessor"]) subscribeToScopeSet(renderer[Owner], renderer[Accessor], scope[childScopeAccessor]);
|
|
1884
1905
|
}
|
|
1885
1906
|
if (renderer) for (const accessor in renderer[LocalClosures]) renderer[LocalClosures][accessor](scope[childScopeAccessor], renderer[LocalClosureValues][accessor]);
|
|
1886
1907
|
};
|
|
1887
1908
|
});
|
|
1909
|
+
let bindNativeTagVar;
|
|
1910
|
+
function installDynamicTagVar(bind) {
|
|
1911
|
+
bindNativeTagVar = bind;
|
|
1912
|
+
}
|
|
1888
1913
|
const _resume_dynamic_tag = /*@__PURE__*/ withBranches(() => _resume(DYNAMIC_TAG_SCRIPT_REGISTER_ID, dynamicTagScript));
|
|
1889
1914
|
function dynamicTagScript(branch) {
|
|
1890
1915
|
_attrs_script(branch, `#${branch[Renderer].toLowerCase()}/0`);
|
|
@@ -2069,6 +2094,12 @@ Object.defineProperty(exports, "ClosestBranch", {
|
|
|
2069
2094
|
return ClosestBranch;
|
|
2070
2095
|
}
|
|
2071
2096
|
});
|
|
2097
|
+
Object.defineProperty(exports, "DYNAMIC_TAG_VAR_REGISTER_ID", {
|
|
2098
|
+
enumerable: true,
|
|
2099
|
+
get: function() {
|
|
2100
|
+
return DYNAMIC_TAG_VAR_REGISTER_ID;
|
|
2101
|
+
}
|
|
2102
|
+
});
|
|
2072
2103
|
Object.defineProperty(exports, "EndNode", {
|
|
2073
2104
|
enumerable: true,
|
|
2074
2105
|
get: function() {
|
|
@@ -2753,6 +2784,12 @@ Object.defineProperty(exports, "installCatch", {
|
|
|
2753
2784
|
return installCatch;
|
|
2754
2785
|
}
|
|
2755
2786
|
});
|
|
2787
|
+
Object.defineProperty(exports, "installDynamicTagVar", {
|
|
2788
|
+
enumerable: true,
|
|
2789
|
+
get: function() {
|
|
2790
|
+
return installDynamicTagVar;
|
|
2791
|
+
}
|
|
2792
|
+
});
|
|
2756
2793
|
Object.defineProperty(exports, "patchDynamicTag", {
|
|
2757
2794
|
enumerable: true,
|
|
2758
2795
|
get: function() {
|
|
@@ -253,10 +253,16 @@ function assertExclusiveAttrs(attrs, onError = throwErr) {
|
|
|
253
253
|
(exclusiveAttrs ||= []).push("checkedValueChange");
|
|
254
254
|
if ("checked" in attrs) exclusiveAttrs.push("checked");
|
|
255
255
|
}
|
|
256
|
-
if (attrs.valueChange)
|
|
256
|
+
if (attrs.valueChange) {
|
|
257
|
+
(exclusiveAttrs ||= []).push("valueChange");
|
|
258
|
+
if ("checked" in attrs && !exclusiveAttrs.includes("checked")) exclusiveAttrs.push("checked");
|
|
259
|
+
}
|
|
257
260
|
if (exclusiveAttrs && exclusiveAttrs.length > 1) onError(`The attributes ${joinWithAnd(exclusiveAttrs)} are mutually exclusive.`);
|
|
258
261
|
}
|
|
259
262
|
}
|
|
263
|
+
function assertNoValueBindingOnCheckable(type, valueChange) {
|
|
264
|
+
if (valueChange && /^(?:button|checkbox|hidden|image|radio|reset|submit)$/i.test(type)) console.error(`\`valueChange\` cannot be used on a \`type="${type}"\` \`<input>\` — user interaction can never change its \`value\`.` + (/^[cr]/i.test(type) ? " Bind `checked` or `checkedValue` instead." : ""));
|
|
265
|
+
}
|
|
260
266
|
function assertHandlerIsFunction(name, value) {
|
|
261
267
|
if (value && typeof value !== "function") throw new Error(`The \`${name}\` handler must be a function or a falsey value (\`null\`, \`undefined\`, \`false\`, \`0\`, …), but received type "${typeof value}".`);
|
|
262
268
|
}
|
|
@@ -439,6 +445,7 @@ function abort(ctrl) {
|
|
|
439
445
|
//#endregion
|
|
440
446
|
//#region src/common/meta.ts
|
|
441
447
|
const DYNAMIC_TAG_SCRIPT_REGISTER_ID = "_dynamicTagScript";
|
|
448
|
+
const DYNAMIC_TAG_VAR_REGISTER_ID = "_dynamicTagVar";
|
|
442
449
|
//#endregion
|
|
443
450
|
//#region src/common/opt.ts
|
|
444
451
|
function toArray(opt) {
|
|
@@ -741,10 +748,16 @@ const _var_change = (scope, value, name = "This") => {
|
|
|
741
748
|
scope[TagVariableChange](value);
|
|
742
749
|
};
|
|
743
750
|
const tagIdsByGlobal = /* @__PURE__ */ new WeakMap();
|
|
744
|
-
function _id(
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
751
|
+
function _id(scope, accessor) {
|
|
752
|
+
let id = accessor !== void 0 && scope[accessor];
|
|
753
|
+
if (!id) {
|
|
754
|
+
const $global = scope[Global];
|
|
755
|
+
const n = tagIdsByGlobal.get($global) || 0;
|
|
756
|
+
tagIdsByGlobal.set($global, n + 1);
|
|
757
|
+
id = "c" + $global.runtimeId + $global.renderId + n.toString(36);
|
|
758
|
+
if (accessor !== void 0) scope[accessor] = id;
|
|
759
|
+
}
|
|
760
|
+
return id;
|
|
748
761
|
}
|
|
749
762
|
function _script(id, fn) {
|
|
750
763
|
_resume(id, fn);
|
|
@@ -756,19 +769,19 @@ function _el_read(value) {
|
|
|
756
769
|
if (rendering) _el_read_error();
|
|
757
770
|
return value;
|
|
758
771
|
}
|
|
759
|
-
function* traverse(scope, path, i = path.length - 1) {
|
|
772
|
+
function* traverse(scope, path, args, i = path.length - 1) {
|
|
760
773
|
if (rendering) _hoist_read_error();
|
|
761
|
-
if (scope) if (Symbol.iterator in scope) for (const childScope of scope.values()) yield* traverse(childScope, path, i);
|
|
774
|
+
if (scope) if (Symbol.iterator in scope) for (const childScope of scope.values()) yield* traverse(childScope, path, args, i);
|
|
762
775
|
else {
|
|
763
776
|
const item = scope[path[i]];
|
|
764
|
-
if (i) yield* traverse(item, path, i - 1);
|
|
765
|
-
else yield typeof item === "function" ? item() : item;
|
|
777
|
+
if (i) yield* traverse(item, path, args, i - 1);
|
|
778
|
+
else yield typeof item === "function" ? item(...args) : item;
|
|
766
779
|
}
|
|
767
780
|
}
|
|
768
781
|
function _hoist(...path) {
|
|
769
782
|
return (scope) => {
|
|
770
|
-
const fn = () => traverse(scope, path).next().value;
|
|
771
|
-
fn[Symbol.iterator] = () => traverse(scope, path);
|
|
783
|
+
const fn = (...args) => traverse(scope, path, args).next().value;
|
|
784
|
+
fn[Symbol.iterator] = () => traverse(scope, path, []);
|
|
772
785
|
return fn;
|
|
773
786
|
};
|
|
774
787
|
}
|
|
@@ -1148,7 +1161,7 @@ function _style_shell(scope, nodeAccessor) {
|
|
|
1148
1161
|
const element = scope[nodeAccessor];
|
|
1149
1162
|
const id = _id(scope);
|
|
1150
1163
|
_attr_nonce(scope, nodeAccessor);
|
|
1151
|
-
element
|
|
1164
|
+
_attr(element, "class", id);
|
|
1152
1165
|
_text_content(element, "." + id + "~*{}");
|
|
1153
1166
|
}
|
|
1154
1167
|
function _style_rule_item(element, name, value) {
|
|
@@ -1235,7 +1248,7 @@ function attrsInternal(scope, nodeAccessor, nextAttrs, controllable) {
|
|
|
1235
1248
|
}
|
|
1236
1249
|
function _attr_content(scope, nodeAccessor, value) {
|
|
1237
1250
|
const content = normalizeClientRender(value);
|
|
1238
|
-
if (scope["ConditionalRenderer:" + nodeAccessor] !== (scope["ConditionalRenderer:" + nodeAccessor] = content
|
|
1251
|
+
if (scope["ConditionalRenderer:" + nodeAccessor] !== (scope["ConditionalRenderer:" + nodeAccessor] = rendererKey(content))) {
|
|
1239
1252
|
setConditionalRenderer(scope, nodeAccessor, content, createAndSetupBranch);
|
|
1240
1253
|
if (content?.["accessor"]) subscribeToScopeSet(content[Owner], content[Accessor], scope[BranchScopes$1 + nodeAccessor]);
|
|
1241
1254
|
}
|
|
@@ -1415,17 +1428,19 @@ function _attr_input_value(scope, nodeAccessor, value, valueChange, setDefault =
|
|
|
1415
1428
|
const el = scope[nodeAccessor];
|
|
1416
1429
|
const normalizedValue = normalizeAttrValue(value) || "";
|
|
1417
1430
|
assertHandlerIsFunction("valueChange", valueChange);
|
|
1431
|
+
assertNoValueBindingOnCheckable(el.type, valueChange);
|
|
1418
1432
|
scope[ControlledHandler + nodeAccessor] = valueChange;
|
|
1419
1433
|
scope[ControlledValue + nodeAccessor] = normalizedValue;
|
|
1420
1434
|
scope[ControlledType + nodeAccessor] = valueChange ? 2 : 5;
|
|
1421
1435
|
if (valueChange && scope["#Gen"] < runId) setInputValue(el, normalizedValue);
|
|
1422
|
-
else setDefault(scope, nodeAccessor,
|
|
1436
|
+
else setDefault(scope, nodeAccessor, value);
|
|
1423
1437
|
}
|
|
1424
1438
|
function _attr_input_value_attribute_default(scope, nodeAccessor, value) {
|
|
1425
1439
|
_attr(scope[nodeAccessor], "value", value);
|
|
1426
1440
|
}
|
|
1427
1441
|
function _attr_input_value_script(scope, nodeAccessor) {
|
|
1428
1442
|
const el = scope[nodeAccessor];
|
|
1443
|
+
assertNoValueBindingOnCheckable(el.type, scope[ControlledHandler + nodeAccessor]);
|
|
1429
1444
|
if (isResuming) scope[ControlledValue + nodeAccessor] = el.defaultValue;
|
|
1430
1445
|
syncControllableFormInput(el, hasValueChanged, (ev) => {
|
|
1431
1446
|
const valueChange = scope[ControlledHandler + nodeAccessor];
|
|
@@ -1833,6 +1848,9 @@ const _show = /*@__PURE__*/ withBranches((nodeAccessor, startNodeAccessor, endNo
|
|
|
1833
1848
|
}
|
|
1834
1849
|
};
|
|
1835
1850
|
});
|
|
1851
|
+
function rendererKey(renderer) {
|
|
1852
|
+
return renderer?.["owner"] ? renderer["id"] + " " + renderer[Owner]["#Id"] : renderer?.["id"] || renderer;
|
|
1853
|
+
}
|
|
1836
1854
|
function patchDynamicTag(fn) {
|
|
1837
1855
|
_dynamic_tag = fn(_dynamic_tag);
|
|
1838
1856
|
}
|
|
@@ -1841,9 +1859,12 @@ let _dynamic_tag = /*@__PURE__*/ withBranches((nodeAccessor, getContent, getTagV
|
|
|
1841
1859
|
const rendererAccessor = ConditionalRenderer + nodeAccessor;
|
|
1842
1860
|
return (scope, newRenderer, getInput) => {
|
|
1843
1861
|
const normalizedRenderer = normalizeDynamicRenderer(newRenderer);
|
|
1844
|
-
if (scope[rendererAccessor] !== (scope[rendererAccessor] = normalizedRenderer
|
|
1862
|
+
if (scope[rendererAccessor] !== (scope[rendererAccessor] = rendererKey(normalizedRenderer)) || getContent && !(normalizedRenderer || scope[childScopeAccessor])) {
|
|
1845
1863
|
setConditionalRenderer(scope, nodeAccessor, normalizedRenderer || (getContent ? getContent(scope) : void 0), createBranchWithTagNameOrRenderer);
|
|
1846
|
-
if (getTagVar) scope[childScopeAccessor]
|
|
1864
|
+
if (getTagVar) if (scope[childScopeAccessor]) {
|
|
1865
|
+
scope[childScopeAccessor][TagVariable] = (value) => getTagVar()(scope, value);
|
|
1866
|
+
if (typeof normalizedRenderer === "string") bindNativeTagVar?.(scope[childScopeAccessor]);
|
|
1867
|
+
} else getTagVar()(scope, void 0);
|
|
1847
1868
|
if (typeof normalizedRenderer === "string") {
|
|
1848
1869
|
if (getContent) {
|
|
1849
1870
|
const content = getContent(scope);
|
|
@@ -1877,13 +1898,17 @@ const _dynamic_tag_content = /*@__PURE__*/ withBranches((nodeAccessor) => {
|
|
|
1877
1898
|
const childScopeAccessor = BranchScopes$1 + nodeAccessor;
|
|
1878
1899
|
const rendererAccessor = ConditionalRenderer + nodeAccessor;
|
|
1879
1900
|
return (scope, renderer) => {
|
|
1880
|
-
if (scope[rendererAccessor] !== (scope[rendererAccessor] = renderer
|
|
1901
|
+
if (scope[rendererAccessor] !== (scope[rendererAccessor] = rendererKey(renderer))) {
|
|
1881
1902
|
setConditionalRenderer(scope, nodeAccessor, renderer, createAndSetupBranch);
|
|
1882
1903
|
if (renderer?.["accessor"]) subscribeToScopeSet(renderer[Owner], renderer[Accessor], scope[childScopeAccessor]);
|
|
1883
1904
|
}
|
|
1884
1905
|
if (renderer) for (const accessor in renderer[LocalClosures]) renderer[LocalClosures][accessor](scope[childScopeAccessor], renderer[LocalClosureValues][accessor]);
|
|
1885
1906
|
};
|
|
1886
1907
|
});
|
|
1908
|
+
let bindNativeTagVar;
|
|
1909
|
+
function installDynamicTagVar(bind) {
|
|
1910
|
+
bindNativeTagVar = bind;
|
|
1911
|
+
}
|
|
1887
1912
|
const _resume_dynamic_tag = /*@__PURE__*/ withBranches(() => _resume(DYNAMIC_TAG_SCRIPT_REGISTER_ID, dynamicTagScript));
|
|
1888
1913
|
function dynamicTagScript(branch) {
|
|
1889
1914
|
_attrs_script(branch, `#${branch[Renderer].toLowerCase()}/0`);
|
|
@@ -2038,4 +2063,4 @@ function byFirstArg(name) {
|
|
|
2038
2063
|
return name;
|
|
2039
2064
|
}
|
|
2040
2065
|
//#endregion
|
|
2041
|
-
export {
|
|
2066
|
+
export { _attrs_script as $, prepareEffects as $t, _attr_input_value_script as A, _hoist_resume as At, _attr as B, _var_change as Bt, _attr_input_checkedValue_script as C, ParentBranch as Cn, _closure as Ct, _attr_input_value_attribute_default as D, TagVariable as Dn, _for_closure as Dt, _attr_input_value as E, StartNode as En, _el_read as Et, _controllable_open as F, _or as Ft, _attr_nonce as G, syncGen as Gt, _attr_class_item as H, destroyBranch as Ht, _controllable_select as I, _return as It, _attr_style_items as J, $signal as Jt, _attr_style as K, _on as Kt, _controllable_textarea as L, _return_change as Lt, _attr_select_value_default as M, _if_closure as Mt, _attr_select_value_script as N, _let as Nt, _attr_input_value_default as O, _for_selector as Ot, _controllable_input as P, _let_change as Pt, _attrs_partial_content as Q, placeholderShown as Qt, controllableRenders as R, _script as Rt, _attr_input_checkedValue_default as S, Load as Sn, _child_setup as St, _attr_input_checked_script as T, PendingRenders as Tn, _const as Tt, _attr_class_items as U, insertBranchBefore as Ut, _attr_class as V, _assert_init as Vt, _attr_content as W, removeAndDestroyBranch as Wt, _attrs_content as X, caughtError as Xt, _attrs as Y, $signalReset as Yt, _attrs_partial as Z, installCatch as Zt, _attr_details_or_dialog_open as _, AwaitCounter as _n, _var_resume as _t, _for_in as a, forIn as an, _text_content as at, _attr_input_checked as b, Gen$1 as bn, initEmbedded as bt, _for_until as c, forUntil as cn, toInsertNode as ct, _show as d, Clone as dn, _content_resume as dt, queueAsyncRender as en, _html as et, _try as f, Owner as fn, createAndSetupBranch as ft, renderCatch as g, Scope as gn, _resume as gt, patchDynamicTag as h, Pending as hn, _el as ht, _dynamic_tag_content as i, runId as in, _text as it, _attr_select_value as j, _id as jt, _attr_input_value_dynamic_default as k, _hoist as kt, _if as l, _assert_hoist as ln, _content as lt, installDynamicTagVar as m, Setup as mn, setupBranch as mt, _await_promise as n, run as nn, _style_rule_item as nt, _for_of as o, forOf as on, _to_text as ot, addAwaitCounter as p, Params as pn, createBranch as pt, _attr_style_item as q, DYNAMIC_TAG_VAR_REGISTER_ID as qt, _dynamic_tag as r, runEffects as rn, _style_shell as rt, _for_to as s, forTo as sn, insertChildNodes as st, _await_content as t, queueEffect as tn, _lifecycle as tt, _resume_dynamic_tag as u, _call as un, _content_closures as ut, _attr_details_or_dialog_open_default as v, ClosestBranch as vn, getRegisteredWithScope as vt, _attr_input_checked_default as w, PendingEffects as wn, _closure_get as wt, _attr_input_checkedValue as x, Global as xn, ready as xt, _attr_details_or_dialog_open_script as y, EndNode as yn, init as yt, controllableScripts as z, _var as zt };
|
package/dist/debug/dom.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const require_control_flow = require("./dom-
|
|
3
|
+
const require_control_flow = require("./dom-BbFAdZEB.js");
|
|
4
4
|
//#region src/common/attr-tag.ts
|
|
5
5
|
const empty = [];
|
|
6
6
|
const rest = Symbol("Attribute Tag");
|
package/dist/debug/dom.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as
|
|
1
|
+
import { $ as _attrs_script, $t as prepareEffects, A as _attr_input_value_script, At as _hoist_resume, B as _attr, Bt as _var_change, C as _attr_input_checkedValue_script, Ct as _closure, D as _attr_input_value_attribute_default, Dn as TagVariable, Dt as _for_closure, E as _attr_input_value, En as StartNode, Et as _el_read, F as _controllable_open, Ft as _or, G as _attr_nonce, Gt as syncGen, H as _attr_class_item, Ht as destroyBranch, I as _controllable_select, It as _return, J as _attr_style_items, Jt as $signal, K as _attr_style, Kt as _on, L as _controllable_textarea, Lt as _return_change, M as _attr_select_value_default, Mt as _if_closure, N as _attr_select_value_script, Nt as _let, O as _attr_input_value_default, Ot as _for_selector, P as _controllable_input, Pt as _let_change, Q as _attrs_partial_content, Rt as _script, S as _attr_input_checkedValue_default, Sn as Load, St as _child_setup, T as _attr_input_checked_script, Tt as _const, U as _attr_class_items, Ut as insertBranchBefore, V as _attr_class, Vt as _assert_init, W as _attr_content, Wt as removeAndDestroyBranch, X as _attrs_content, Y as _attrs, Yt as $signalReset, Z as _attrs_partial, _ as _attr_details_or_dialog_open, _t as _var_resume, a as _for_in, an as forIn, at as _text_content, b as _attr_input_checked, bt as initEmbedded, c as _for_until, cn as forUntil, ct as toInsertNode, d as _show, dn as Clone, dt as _content_resume, en as queueAsyncRender, et as _html, f as _try, fn as Owner, ft as createAndSetupBranch, g as renderCatch, gt as _resume, h as patchDynamicTag, ht as _el, i as _dynamic_tag_content, in as runId, it as _text, j as _attr_select_value, jt as _id, k as _attr_input_value_dynamic_default, kt as _hoist, l as _if, ln as _assert_hoist, lt as _content, mn as Setup, mt as setupBranch, n as _await_promise, nn as run, nt as _style_rule_item, o as _for_of, on as forOf, ot as _to_text, p as addAwaitCounter, pn as Params, pt as createBranch, q as _attr_style_item, r as _dynamic_tag, rn as runEffects, rt as _style_shell, s as _for_to, sn as forTo, st as insertChildNodes, t as _await_content, tn as queueEffect, tt as _lifecycle, u as _resume_dynamic_tag, un as _call, ut as _content_closures, v as _attr_details_or_dialog_open_default, vt as getRegisteredWithScope, w as _attr_input_checked_default, wt as _closure_get, x as _attr_input_checkedValue, xn as Global, xt as ready, y as _attr_details_or_dialog_open_script, yn as EndNode, yt as init, zt as _var } from "./dom-ClMc0GK9.mjs";
|
|
2
2
|
//#region src/common/attr-tag.ts
|
|
3
3
|
const empty = [];
|
|
4
4
|
const rest = Symbol("Attribute Tag");
|