ilha 0.12.1 → 0.13.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 +7 -25
- package/dist/{index-BETRqz-0.d.ts → index-CVOjC94p.d.ts} +31 -13
- package/dist/index.d.ts +2 -2
- package/dist/index.js +494 -255
- package/dist/internal.d.ts +10 -2
- package/dist/internal.js +14 -1
- package/dist/jsx-dev-runtime.d.ts +1 -1
- package/dist/jsx-dev-runtime.js +1 -1
- package/dist/{jsx-runtime-qnxoD2YJ.d.ts → jsx-runtime-CzU-60tX.d.ts} +1 -1
- package/dist/jsx-runtime-DreKruAt.js +124 -0
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +1 -235
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, serializeServerManifest, setJsxRuntimeBridge, setServerActionBinder } from "./internal.js";
|
|
1
|
+
import { ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, __ilhaJsxEvent, serializeServerManifest, setJsxRuntimeBridge, setServerActionBinder, setTemplateRenderer } from "./internal.js";
|
|
2
2
|
import { effect as effect$1, endBatch, setActiveSub, signal, startBatch } from "alien-signals";
|
|
3
3
|
|
|
4
4
|
//#region src/index.ts
|
|
@@ -511,15 +511,6 @@ function serializeScriptJson(value) {
|
|
|
511
511
|
function escapeStyleText(text) {
|
|
512
512
|
return text.replace(/</g, "\\3C ");
|
|
513
513
|
}
|
|
514
|
-
function dedentString(str) {
|
|
515
|
-
if (str.length === 0 || str[0] !== "\n") return str;
|
|
516
|
-
const lines = str.split("\n");
|
|
517
|
-
while (lines.length && lines[0].trim() === "") lines.shift();
|
|
518
|
-
while (lines.length && lines[lines.length - 1].trim() === "") lines.pop();
|
|
519
|
-
if (!lines.length) return "";
|
|
520
|
-
const indent = Math.min(...lines.filter((l) => l.trim() !== "").map((l) => l.match(/^(\s*)/)[1].length));
|
|
521
|
-
return lines.map((l) => l.slice(indent)).join("\n");
|
|
522
|
-
}
|
|
523
514
|
const RAW = Symbol.for("ilha.raw");
|
|
524
515
|
const SIGNAL_ACCESSOR = Symbol.for("ilha.signalAccessor");
|
|
525
516
|
const ISLAND = Symbol.for("ilha.island");
|
|
@@ -773,18 +764,18 @@ async function resolveAsyncChildren(html, pending) {
|
|
|
773
764
|
}
|
|
774
765
|
return html;
|
|
775
766
|
}
|
|
776
|
-
function
|
|
777
|
-
|
|
778
|
-
const
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
767
|
+
function markSignalAccessor(read, write) {
|
|
768
|
+
read[SIGNAL_ACCESSOR] = true;
|
|
769
|
+
const accessor = read;
|
|
770
|
+
accessor.set = (value) => write(value);
|
|
771
|
+
accessor.update = (fn) => {
|
|
772
|
+
const prevSub = setActiveSub(void 0);
|
|
773
|
+
try {
|
|
774
|
+
write(fn(read()));
|
|
775
|
+
} finally {
|
|
776
|
+
setActiveSub(prevSub);
|
|
777
|
+
}
|
|
778
|
+
};
|
|
788
779
|
accessor.select = ((...args) => createSelectAccessor(accessor, args));
|
|
789
780
|
return accessor;
|
|
790
781
|
}
|
|
@@ -870,17 +861,14 @@ function createSelectAccessor(root, input) {
|
|
|
870
861
|
if (!Object.is(selected, resolved)) throw new Error("select(): selector must only traverse nested properties or array indexes — derived or transformed values are not supported.");
|
|
871
862
|
} else path = input;
|
|
872
863
|
const read = (from) => selector ? path.length === 0 ? selector(from) : getAtPath(from, path) : getAtPath(from, path);
|
|
873
|
-
return markSignalAccessor((
|
|
874
|
-
if (args.length === 0) return read(root());
|
|
864
|
+
return markSignalAccessor(() => read(root()), (value) => {
|
|
875
865
|
const previousRoot = root();
|
|
876
|
-
const previousSelected = read(previousRoot);
|
|
877
|
-
const value = resolveSignalSetter(() => previousSelected, args[0]);
|
|
878
866
|
const next = path.length === 0 && selector ? value : setAtPath({
|
|
879
867
|
object: previousRoot,
|
|
880
868
|
path,
|
|
881
869
|
value
|
|
882
870
|
});
|
|
883
|
-
if (!Object.is(previousRoot, next)) root(
|
|
871
|
+
if (!Object.is(previousRoot, next)) root.set(next);
|
|
884
872
|
});
|
|
885
873
|
}
|
|
886
874
|
function ilhaRaw(value) {
|
|
@@ -950,70 +938,18 @@ const BIND_VALID_KINDS = /* @__PURE__ */ new Set([
|
|
|
950
938
|
"group",
|
|
951
939
|
"this"
|
|
952
940
|
]);
|
|
953
|
-
const BIND_PREFIX_RE = /\bbind:([a-zA-Z]+)\s*=\s*("|')?$/;
|
|
954
|
-
const EVENT_PREFIX_RE = /(?:^|\s)on([a-zA-Z][a-zA-Z0-9-]*)(?::([a-zA-Z][a-zA-Z0-9-]*))?\s*=\s*("|')?$/;
|
|
955
941
|
const NATIVE_EVENT_MODIFIERS = /* @__PURE__ */ new Set([
|
|
956
942
|
"abortable",
|
|
957
943
|
"once",
|
|
958
944
|
"capture",
|
|
959
945
|
"passive"
|
|
960
946
|
]);
|
|
961
|
-
const FULL_VALUE_ATTR_RE = /(?:^|\s)([a-zA-Z_:][a-zA-Z0-9:._-]*)\s*=\s*("|')?$/;
|
|
962
|
-
const UNQUOTED_HAZARD_RE = /[\s=]|`/;
|
|
963
947
|
function resolveTemplateValue(v) {
|
|
964
948
|
if (isSignalAccessor(v)) return v();
|
|
965
949
|
if (typeof v === "function") return v();
|
|
966
950
|
return v;
|
|
967
951
|
}
|
|
968
|
-
function
|
|
969
|
-
const open = source.lastIndexOf("<", index);
|
|
970
|
-
if (open === -1) return "element";
|
|
971
|
-
return (source.slice(open).match(/^<\s*([a-zA-Z][a-zA-Z0-9:._-]*)/)?.[1] ?? "element").toLowerCase();
|
|
972
|
-
}
|
|
973
|
-
function isEventAttributePosition(source, index) {
|
|
974
|
-
let open = -1;
|
|
975
|
-
let quote = null;
|
|
976
|
-
for (let i = 0; i < index; i++) {
|
|
977
|
-
const char = source[i];
|
|
978
|
-
if (open === -1) {
|
|
979
|
-
if (char === "<") open = i;
|
|
980
|
-
continue;
|
|
981
|
-
}
|
|
982
|
-
if (quote) {
|
|
983
|
-
if (char === quote) quote = null;
|
|
984
|
-
} else if (char === "\"" || char === "'") quote = char;
|
|
985
|
-
else if (char === ">") open = -1;
|
|
986
|
-
}
|
|
987
|
-
if (open === -1 || quote !== null) return false;
|
|
988
|
-
return !/^\s*[!/?]/.test(source.slice(open + 1, index));
|
|
989
|
-
}
|
|
990
|
-
function findTagCloseIndex(chunk, initialQuote) {
|
|
991
|
-
let quote = initialQuote;
|
|
992
|
-
for (let i = 0; i < chunk.length; i++) {
|
|
993
|
-
const ch = chunk[i];
|
|
994
|
-
if (quote !== null) {
|
|
995
|
-
if (ch === quote) quote = null;
|
|
996
|
-
} else if (ch === "\"" || ch === "'") quote = ch;
|
|
997
|
-
else if (ch === ">") return {
|
|
998
|
-
index: i,
|
|
999
|
-
quote
|
|
1000
|
-
};
|
|
1001
|
-
}
|
|
1002
|
-
return {
|
|
1003
|
-
index: -1,
|
|
1004
|
-
quote
|
|
1005
|
-
};
|
|
1006
|
-
}
|
|
1007
|
-
function extractElementStaticValue(prefix) {
|
|
1008
|
-
const lastOpen = prefix.lastIndexOf("<");
|
|
1009
|
-
if (lastOpen === -1) return null;
|
|
1010
|
-
const tagPrefix = prefix.slice(lastOpen);
|
|
1011
|
-
if (tagPrefix.includes(">")) return null;
|
|
1012
|
-
const m = tagPrefix.match(/\bvalue\s*=\s*("([^"]*)"|'([^']*)'|([^\s>]+))/);
|
|
1013
|
-
if (!m) return null;
|
|
1014
|
-
return m[2] ?? m[3] ?? m[4] ?? null;
|
|
1015
|
-
}
|
|
1016
|
-
function emitBindSSR({ kind, index, accessor, prefixForStaticPeek }) {
|
|
952
|
+
function emitBindSSR({ kind, index, accessor, optionValue }) {
|
|
1017
953
|
const spec = `${kind}:${index}`;
|
|
1018
954
|
let v;
|
|
1019
955
|
try {
|
|
@@ -1027,183 +963,494 @@ function emitBindSSR({ kind, index, accessor, prefixForStaticPeek }) {
|
|
|
1027
963
|
case "open": return [v ? ` open` : ``, spec];
|
|
1028
964
|
case "files": return [``, spec];
|
|
1029
965
|
case "this": return [``, spec];
|
|
1030
|
-
case "group":
|
|
1031
|
-
const optionValue = extractElementStaticValue(prefixForStaticPeek);
|
|
966
|
+
case "group":
|
|
1032
967
|
if (optionValue == null) return [``, spec];
|
|
1033
968
|
return [(Array.isArray(v) ? v.map(String).includes(optionValue) : v != null && String(v) === optionValue) ? ` checked` : ``, spec];
|
|
1034
|
-
}
|
|
1035
969
|
}
|
|
1036
970
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
971
|
+
const TEMPLATE_ATTRIBUTE = Symbol.for("ilha.templateAttribute");
|
|
972
|
+
const TEMPLATE_PARTS = Symbol.for("ilha.templateParts");
|
|
973
|
+
const TEMPLATE_SLOT_START = "ilha:";
|
|
974
|
+
const TEMPLATE_SLOT_END = ":";
|
|
975
|
+
const TEMPLATE_SLOT_RE = /\uE000ilha:(\d+):\uE001/g;
|
|
976
|
+
const templateBlueprintCache = /* @__PURE__ */ new WeakMap();
|
|
977
|
+
const TEMPLATE_PARSE_VOID_TAGS = /* @__PURE__ */ new Set([
|
|
978
|
+
"area",
|
|
979
|
+
"base",
|
|
980
|
+
"br",
|
|
981
|
+
"col",
|
|
982
|
+
"embed",
|
|
983
|
+
"hr",
|
|
984
|
+
"img",
|
|
985
|
+
"input",
|
|
986
|
+
"link",
|
|
987
|
+
"meta",
|
|
988
|
+
"param",
|
|
989
|
+
"source",
|
|
990
|
+
"track",
|
|
991
|
+
"wbr"
|
|
992
|
+
]);
|
|
993
|
+
const TEMPLATE_PARSE_RAW_TEXT_TAGS = /* @__PURE__ */ new Set([
|
|
994
|
+
"script",
|
|
995
|
+
"style",
|
|
996
|
+
"textarea",
|
|
997
|
+
"title"
|
|
998
|
+
]);
|
|
999
|
+
function templateSkipWs(s, i) {
|
|
1000
|
+
while (i < s.length && /[\t\n\f\r ]/.test(s[i])) i++;
|
|
1001
|
+
return i;
|
|
1002
|
+
}
|
|
1003
|
+
function templateAsciiLower(source) {
|
|
1004
|
+
return source.replace(/[A-Z]/g, (char) => String.fromCharCode(char.charCodeAt(0) + 32));
|
|
1005
|
+
}
|
|
1006
|
+
function templateClosingTagAt(lower, index, tag) {
|
|
1007
|
+
const prefix = `</${tag}`;
|
|
1008
|
+
if (!lower.startsWith(prefix, index)) return false;
|
|
1009
|
+
const boundary = lower[index + prefix.length];
|
|
1010
|
+
return boundary === ">" || boundary === "/" || /[\t\n\f\r ]/.test(boundary ?? "");
|
|
1011
|
+
}
|
|
1012
|
+
function templateFindClosingTag(lower, tag, from) {
|
|
1013
|
+
const needle = `</${tag}`;
|
|
1014
|
+
let index = lower.indexOf(needle, from);
|
|
1015
|
+
while (index !== -1) {
|
|
1016
|
+
if (templateClosingTagAt(lower, index, tag)) return index;
|
|
1017
|
+
index = lower.indexOf(needle, index + 1);
|
|
1018
|
+
}
|
|
1019
|
+
return -1;
|
|
1020
|
+
}
|
|
1021
|
+
function templateParseFragment(source) {
|
|
1022
|
+
const children = [];
|
|
1023
|
+
templateParseNodes(source, templateAsciiLower(source), 0, null, children);
|
|
1024
|
+
return {
|
|
1025
|
+
nodeName: "#document-fragment",
|
|
1026
|
+
childNodes: children
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
function templateParseNodes(s, lower, i, stop, out) {
|
|
1030
|
+
while (i < s.length) {
|
|
1031
|
+
if (stop && templateClosingTagAt(lower, i, stop)) {
|
|
1032
|
+
const gt = s.indexOf(">", i);
|
|
1033
|
+
return gt === -1 ? s.length : gt + 1;
|
|
1062
1034
|
}
|
|
1063
|
-
if (i
|
|
1064
|
-
|
|
1035
|
+
if (s.startsWith("<!--", i)) {
|
|
1036
|
+
const end = s.indexOf("-->", i + 4);
|
|
1037
|
+
const close = end === -1 ? s.length : end + 3;
|
|
1038
|
+
out.push({
|
|
1039
|
+
nodeName: "#comment",
|
|
1040
|
+
data: s.slice(i + 4, end === -1 ? s.length : end)
|
|
1041
|
+
});
|
|
1042
|
+
i = close;
|
|
1065
1043
|
continue;
|
|
1066
1044
|
}
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
const ambiguous = chunk.match(/(?:^|\s)on([a-zA-Z][a-zA-Z0-9-]*)(?::[a-zA-Z][a-zA-Z0-9-]*)?\s*=\s*(?:(?:"[^"]*)|(?:'[^']*)|(?:[^\s"'=<>`]+))$/);
|
|
1072
|
-
const start = ambiguous ? chunk.length - ambiguous[0].length : -1;
|
|
1073
|
-
if (ambiguous && isEventAttributePosition(result + chunk, result.length + start)) throw new Error(`[ilha] on${ambiguous[1]} handler must occupy the entire attribute value. Write on${ambiguous[1]}=\${handler}.`);
|
|
1045
|
+
if (stop === null && s[i] === "<" && s[i + 1] === "/") {
|
|
1046
|
+
const gt = s.indexOf(">", i);
|
|
1047
|
+
i = gt === -1 ? s.length : gt + 1;
|
|
1048
|
+
continue;
|
|
1074
1049
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1080
|
-
const
|
|
1081
|
-
const
|
|
1082
|
-
|
|
1083
|
-
const
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1050
|
+
if (s[i] === "<" && /[A-Za-z]/.test(s[i + 1] ?? "")) {
|
|
1051
|
+
const start = i;
|
|
1052
|
+
i++;
|
|
1053
|
+
const tagStart = i;
|
|
1054
|
+
while (i < s.length && /[A-Za-z0-9:-]/.test(s[i])) i++;
|
|
1055
|
+
const tagOrig = s.slice(tagStart, i);
|
|
1056
|
+
const tag = tagOrig.toLowerCase();
|
|
1057
|
+
const attrs = [];
|
|
1058
|
+
const attrLocs = {};
|
|
1059
|
+
i = templateSkipWs(s, i);
|
|
1060
|
+
while (i < s.length && s[i] !== ">" && s[i] !== "/") {
|
|
1061
|
+
const attrStart = i;
|
|
1062
|
+
while (i < s.length && /[^\s=>/]/.test(s[i])) i++;
|
|
1063
|
+
const rawName = s.slice(attrStart, i);
|
|
1064
|
+
if (!rawName) break;
|
|
1065
|
+
const name = rawName;
|
|
1066
|
+
i = templateSkipWs(s, i);
|
|
1067
|
+
let value = "";
|
|
1068
|
+
if (s[i] === "=") {
|
|
1069
|
+
i++;
|
|
1070
|
+
i = templateSkipWs(s, i);
|
|
1071
|
+
if (s[i] === "\"" || s[i] === "'") {
|
|
1072
|
+
const q = s[i];
|
|
1073
|
+
i++;
|
|
1074
|
+
const vs = i;
|
|
1075
|
+
while (i < s.length && s[i] !== q) i++;
|
|
1076
|
+
value = s.slice(vs, i);
|
|
1077
|
+
if (s[i] === q) i++;
|
|
1078
|
+
} else {
|
|
1079
|
+
const vs = i;
|
|
1080
|
+
while (i < s.length && /[^\s>]/.test(s[i])) {
|
|
1081
|
+
if (s[i] === "/") {
|
|
1082
|
+
let j = i + 1;
|
|
1083
|
+
while (j < s.length && /\s/.test(s[j])) j++;
|
|
1084
|
+
if (j >= s.length || s[j] === ">") break;
|
|
1085
|
+
}
|
|
1086
|
+
i++;
|
|
1087
|
+
}
|
|
1088
|
+
value = s.slice(vs, i);
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
attrs.push({
|
|
1092
|
+
name,
|
|
1093
|
+
value
|
|
1094
|
+
});
|
|
1095
|
+
attrLocs[name] = {
|
|
1096
|
+
startOffset: attrStart,
|
|
1097
|
+
endOffset: i
|
|
1098
|
+
};
|
|
1099
|
+
i = templateSkipWs(s, i);
|
|
1100
|
+
}
|
|
1101
|
+
if (s[i] === "/") {
|
|
1102
|
+
i++;
|
|
1103
|
+
i = templateSkipWs(s, i);
|
|
1104
|
+
}
|
|
1105
|
+
if (s[i] === ">") i++;
|
|
1106
|
+
const el = {
|
|
1107
|
+
nodeName: tagOrig,
|
|
1108
|
+
tagName: tagOrig,
|
|
1109
|
+
attrs,
|
|
1110
|
+
childNodes: [],
|
|
1111
|
+
sourceCodeLocation: {
|
|
1112
|
+
attrs: attrLocs,
|
|
1113
|
+
startTag: {
|
|
1114
|
+
startOffset: start,
|
|
1115
|
+
endOffset: i
|
|
1116
|
+
}
|
|
1095
1117
|
}
|
|
1118
|
+
};
|
|
1119
|
+
if (!TEMPLATE_PARSE_VOID_TAGS.has(tag)) {
|
|
1120
|
+
if (TEMPLATE_PARSE_RAW_TEXT_TAGS.has(tag)) {
|
|
1121
|
+
const ci = templateFindClosingTag(lower, tag, i);
|
|
1122
|
+
const textEnd = ci === -1 ? s.length : ci;
|
|
1123
|
+
if (textEnd > i) el.childNodes.push({
|
|
1124
|
+
nodeName: "#text",
|
|
1125
|
+
value: s.slice(i, textEnd)
|
|
1126
|
+
});
|
|
1127
|
+
i = ci === -1 ? s.length : s.indexOf(">", ci) === -1 ? s.length : s.indexOf(">", ci) + 1;
|
|
1128
|
+
} else i = templateParseNodes(s, lower, i, tag, el.childNodes);
|
|
1096
1129
|
}
|
|
1097
|
-
|
|
1130
|
+
out.push(el);
|
|
1098
1131
|
continue;
|
|
1099
1132
|
}
|
|
1100
|
-
const
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1133
|
+
const next = s.indexOf("<", i);
|
|
1134
|
+
const end = next === -1 ? s.length : next;
|
|
1135
|
+
if (end > i) {
|
|
1136
|
+
out.push({
|
|
1137
|
+
nodeName: "#text",
|
|
1138
|
+
value: s.slice(i, end)
|
|
1139
|
+
});
|
|
1140
|
+
i = end;
|
|
1141
|
+
continue;
|
|
1142
|
+
}
|
|
1143
|
+
out.push({
|
|
1144
|
+
nodeName: "#text",
|
|
1145
|
+
value: s[i]
|
|
1146
|
+
});
|
|
1147
|
+
i++;
|
|
1148
|
+
}
|
|
1149
|
+
return i;
|
|
1150
|
+
}
|
|
1151
|
+
function templateSegments(value) {
|
|
1152
|
+
const out = [];
|
|
1153
|
+
let offset = 0;
|
|
1154
|
+
for (const match of value.matchAll(TEMPLATE_SLOT_RE)) {
|
|
1155
|
+
if (match.index > offset) out.push(value.slice(offset, match.index));
|
|
1156
|
+
out.push({ slot: Number(match[1]) });
|
|
1157
|
+
offset = match.index + match[0].length;
|
|
1158
|
+
}
|
|
1159
|
+
if (offset < value.length) out.push(value.slice(offset));
|
|
1160
|
+
return out;
|
|
1161
|
+
}
|
|
1162
|
+
function templateBlueprint(node, source) {
|
|
1163
|
+
if (node.nodeName === "#text") return {
|
|
1164
|
+
kind: "text",
|
|
1165
|
+
value: templateSegments(node.value)
|
|
1166
|
+
};
|
|
1167
|
+
if (node.nodeName === "#comment") return {
|
|
1168
|
+
kind: "comment",
|
|
1169
|
+
value: templateSegments(node.data)
|
|
1170
|
+
};
|
|
1171
|
+
if (node.nodeName === "#document-fragment") return {
|
|
1172
|
+
kind: "fragment",
|
|
1173
|
+
children: node.childNodes.map((child) => templateBlueprint(child, source)).filter(Boolean)
|
|
1174
|
+
};
|
|
1175
|
+
if (typeof node.tagName === "string") {
|
|
1176
|
+
const props = {};
|
|
1177
|
+
for (const attr of node.attrs ?? []) {
|
|
1178
|
+
const location = node.sourceCodeLocation?.attrs?.[attr.name];
|
|
1179
|
+
const sourceAttr = location ? source.slice(location.startOffset, location.endOffset) : attr.name;
|
|
1180
|
+
const parts = templateSegments(attr.value);
|
|
1181
|
+
parts.quoted = /=\s*["']/.test(sourceAttr);
|
|
1182
|
+
parts.bare = !sourceAttr.includes("=");
|
|
1183
|
+
props[attr.name] = parts;
|
|
1184
|
+
}
|
|
1185
|
+
return {
|
|
1186
|
+
kind: "element",
|
|
1187
|
+
tag: node.tagName,
|
|
1188
|
+
props,
|
|
1189
|
+
children: (node.childNodes ?? []).map((child) => templateBlueprint(child, source)).filter(Boolean),
|
|
1190
|
+
selfClosing: node.sourceCodeLocation?.startTag ? /\/\s*>$/.test(source.slice(node.sourceCodeLocation.startTag.startOffset, node.sourceCodeLocation.startTag.endOffset)) : false
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
return null;
|
|
1194
|
+
}
|
|
1195
|
+
function templateCompile(strings) {
|
|
1196
|
+
let source = strings[0] ?? "";
|
|
1197
|
+
for (let i = 0; i < strings.length - 1; i++) source += `${TEMPLATE_SLOT_START}${i}${TEMPLATE_SLOT_END}${strings[i + 1] ?? ""}`;
|
|
1198
|
+
return templateBlueprint(templateParseFragment(source), source) ?? {
|
|
1199
|
+
kind: "fragment",
|
|
1200
|
+
children: []
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
function templateBindSegments(parts, values) {
|
|
1204
|
+
let value;
|
|
1205
|
+
if (parts.length === 1 && typeof parts[0] !== "string") value = values[parts[0].slot];
|
|
1206
|
+
else if (parts.some((part) => typeof part !== "string")) value = {
|
|
1207
|
+
[TEMPLATE_PARTS]: true,
|
|
1208
|
+
values: parts.map((part) => typeof part === "string" ? part : values[part.slot])
|
|
1209
|
+
};
|
|
1210
|
+
else value = parts.join("");
|
|
1211
|
+
return {
|
|
1212
|
+
[TEMPLATE_ATTRIBUTE]: true,
|
|
1213
|
+
value,
|
|
1214
|
+
quoted: parts.quoted ?? true,
|
|
1215
|
+
bare: parts.bare ?? false
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
function templateBind(node, values) {
|
|
1219
|
+
if (node.kind === "text") {
|
|
1220
|
+
const out = [];
|
|
1221
|
+
for (const part of node.value) if (typeof part === "string") {
|
|
1222
|
+
if (part) out.push({
|
|
1223
|
+
kind: "text",
|
|
1224
|
+
value: part
|
|
1225
|
+
});
|
|
1226
|
+
} else out.push({
|
|
1227
|
+
kind: "dynamic",
|
|
1228
|
+
value: values[part.slot]
|
|
1229
|
+
});
|
|
1230
|
+
return out;
|
|
1231
|
+
}
|
|
1232
|
+
if (node.kind === "comment") {
|
|
1233
|
+
const parts = node.value;
|
|
1234
|
+
if (parts.length === 1 && typeof parts[0] === "string") return {
|
|
1235
|
+
kind: "comment",
|
|
1236
|
+
value: parts[0]
|
|
1237
|
+
};
|
|
1238
|
+
if (parts.every((part) => typeof part === "string")) return {
|
|
1239
|
+
kind: "comment",
|
|
1240
|
+
value: parts.join("")
|
|
1241
|
+
};
|
|
1242
|
+
return {
|
|
1243
|
+
kind: "comment",
|
|
1244
|
+
value: {
|
|
1245
|
+
[TEMPLATE_PARTS]: true,
|
|
1246
|
+
values: parts.map((part) => typeof part === "string" ? part : values[part.slot])
|
|
1107
1247
|
}
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
if (node.kind === "element") {
|
|
1251
|
+
const props = {};
|
|
1252
|
+
for (const [name, parts] of Object.entries(node.props)) props[name] = templateBindSegments(parts, values);
|
|
1253
|
+
return {
|
|
1254
|
+
kind: "element",
|
|
1255
|
+
tag: node.tag,
|
|
1256
|
+
props,
|
|
1257
|
+
children: node.children.flatMap((child) => templateBind(child, values)),
|
|
1258
|
+
selfClosing: node.selfClosing
|
|
1259
|
+
};
|
|
1260
|
+
}
|
|
1261
|
+
return {
|
|
1262
|
+
kind: "fragment",
|
|
1263
|
+
children: node.children.flatMap((child) => templateBind(child, values))
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
function htmlTemplate(strings, values) {
|
|
1267
|
+
let compiled = templateBlueprintCache.get(strings);
|
|
1268
|
+
if (!compiled) {
|
|
1269
|
+
compiled = templateCompile(strings);
|
|
1270
|
+
templateBlueprintCache.set(strings, compiled);
|
|
1271
|
+
}
|
|
1272
|
+
const result = templateBind(compiled, values);
|
|
1273
|
+
return Array.isArray(result) ? {
|
|
1274
|
+
kind: "fragment",
|
|
1275
|
+
children: result
|
|
1276
|
+
} : result;
|
|
1277
|
+
}
|
|
1278
|
+
function templateAttribute(value) {
|
|
1279
|
+
return value && typeof value === "object" && TEMPLATE_ATTRIBUTE in value ? value : null;
|
|
1280
|
+
}
|
|
1281
|
+
function templateParts(value) {
|
|
1282
|
+
return value && typeof value === "object" && TEMPLATE_PARTS in value ? value.values : null;
|
|
1283
|
+
}
|
|
1284
|
+
const TEMPLATE_ATTRIBUTE_ALIASES = {
|
|
1285
|
+
className: "class",
|
|
1286
|
+
htmlFor: "for",
|
|
1287
|
+
acceptCharset: "accept-charset",
|
|
1288
|
+
httpEquiv: "http-equiv",
|
|
1289
|
+
accentHeight: "accent-height",
|
|
1290
|
+
alignmentBaseline: "alignment-baseline",
|
|
1291
|
+
baselineShift: "baseline-shift",
|
|
1292
|
+
clipPath: "clip-path",
|
|
1293
|
+
clipRule: "clip-rule",
|
|
1294
|
+
dominantBaseline: "dominant-baseline",
|
|
1295
|
+
fillOpacity: "fill-opacity",
|
|
1296
|
+
fillRule: "fill-rule",
|
|
1297
|
+
floodColor: "flood-color",
|
|
1298
|
+
floodOpacity: "flood-opacity",
|
|
1299
|
+
fontFamily: "font-family",
|
|
1300
|
+
fontSize: "font-size",
|
|
1301
|
+
fontStyle: "font-style",
|
|
1302
|
+
fontWeight: "font-weight",
|
|
1303
|
+
markerEnd: "marker-end",
|
|
1304
|
+
markerMid: "marker-mid",
|
|
1305
|
+
markerStart: "marker-start",
|
|
1306
|
+
stopColor: "stop-color",
|
|
1307
|
+
stopOpacity: "stop-opacity",
|
|
1308
|
+
strokeDasharray: "stroke-dasharray",
|
|
1309
|
+
strokeDashoffset: "stroke-dashoffset",
|
|
1310
|
+
strokeLinecap: "stroke-linecap",
|
|
1311
|
+
strokeLinejoin: "stroke-linejoin",
|
|
1312
|
+
strokeMiterlimit: "stroke-miterlimit",
|
|
1313
|
+
strokeOpacity: "stroke-opacity",
|
|
1314
|
+
strokeWidth: "stroke-width",
|
|
1315
|
+
textAnchor: "text-anchor",
|
|
1316
|
+
vectorEffect: "vector-effect",
|
|
1317
|
+
xlinkHref: "xlink:href"
|
|
1318
|
+
};
|
|
1319
|
+
const TEMPLATE_VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
1320
|
+
"area",
|
|
1321
|
+
"base",
|
|
1322
|
+
"br",
|
|
1323
|
+
"col",
|
|
1324
|
+
"embed",
|
|
1325
|
+
"hr",
|
|
1326
|
+
"img",
|
|
1327
|
+
"input",
|
|
1328
|
+
"link",
|
|
1329
|
+
"meta",
|
|
1330
|
+
"param",
|
|
1331
|
+
"source",
|
|
1332
|
+
"track",
|
|
1333
|
+
"wbr"
|
|
1334
|
+
]);
|
|
1335
|
+
const TEMPLATE_STRING_BOOLEANS = /* @__PURE__ */ new Set([
|
|
1336
|
+
"contenteditable",
|
|
1337
|
+
"draggable",
|
|
1338
|
+
"spellcheck"
|
|
1339
|
+
]);
|
|
1340
|
+
const TEMPLATE_SAFE_NAME = /^[A-Za-z_:][A-Za-z0-9:._-]*$/;
|
|
1341
|
+
const TEMPLATE_EVENT = /^on([a-z][a-z0-9-]*)(?::([a-z][a-z0-9-]*))?$/;
|
|
1342
|
+
function normalizeTemplateClass(value) {
|
|
1343
|
+
if (Array.isArray(value)) return value.filter(Boolean).join(" ");
|
|
1344
|
+
if (isPlainObject(value)) return Object.entries(value).filter(([, enabled]) => Boolean(enabled)).map(([name]) => name).join(" ");
|
|
1345
|
+
return String(value);
|
|
1346
|
+
}
|
|
1347
|
+
function resolvedAttrText(rawSourceValue) {
|
|
1348
|
+
const attribute = templateAttribute(rawSourceValue);
|
|
1349
|
+
const sourceValue = attribute ? attribute.value : rawSourceValue;
|
|
1350
|
+
if (sourceValue == null) return null;
|
|
1351
|
+
const parts = templateParts(sourceValue);
|
|
1352
|
+
const value = parts ? parts.map((part) => resolveTemplateValue(part) ?? "").join("") : resolveTemplateValue(sourceValue);
|
|
1353
|
+
if (value == null || value === false) return null;
|
|
1354
|
+
return String(value);
|
|
1355
|
+
}
|
|
1356
|
+
function renderTemplateElement(node) {
|
|
1357
|
+
const ctx = currentRenderCtx();
|
|
1358
|
+
let attrs = "";
|
|
1359
|
+
const eventSpecs = [];
|
|
1360
|
+
const bindSpecs = [];
|
|
1361
|
+
for (const [sourceName, rawSourceValue] of Object.entries(node.props)) {
|
|
1362
|
+
const attribute = templateAttribute(rawSourceValue);
|
|
1363
|
+
const sourceValue = attribute ? attribute.value : rawSourceValue;
|
|
1364
|
+
if (sourceName === "children" || sourceName === "key" || sourceValue == null) continue;
|
|
1365
|
+
if (sourceName === "__proto__" || sourceName === "constructor" || sourceName === "prototype") continue;
|
|
1366
|
+
const name = TEMPLATE_ATTRIBUTE_ALIASES[sourceName] ?? (/^on[A-Z]/.test(sourceName) ? sourceName.toLowerCase() : sourceName);
|
|
1367
|
+
if (!TEMPLATE_SAFE_NAME.test(name)) continue;
|
|
1368
|
+
if (name.startsWith("bind:")) {
|
|
1369
|
+
const kind = name.slice(5);
|
|
1370
|
+
if (!BIND_VALID_KINDS.has(kind) || !isSignalAccessor(sourceValue)) continue;
|
|
1108
1371
|
if (!ctx) {
|
|
1109
|
-
const
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
if (openQuote) stripLeadingQuote = openQuote;
|
|
1372
|
+
const value = sourceValue();
|
|
1373
|
+
if (kind === "value") attrs += ` value="${escapeHtml(value ?? "")}"`;
|
|
1374
|
+
else if ((kind === "checked" || kind === "open") && value) attrs += ` ${kind}`;
|
|
1113
1375
|
continue;
|
|
1114
1376
|
}
|
|
1115
|
-
const matchStart = chunk.length - m[0].length;
|
|
1116
|
-
const cleanPrefix = chunk.slice(0, matchStart).replace(/\s+$/, "");
|
|
1117
1377
|
const index = ctx.binds.length;
|
|
1118
1378
|
ctx.binds.push({
|
|
1119
|
-
kind
|
|
1120
|
-
accessor:
|
|
1379
|
+
kind,
|
|
1380
|
+
accessor: sourceValue
|
|
1121
1381
|
});
|
|
1122
|
-
const [
|
|
1123
|
-
kind
|
|
1382
|
+
const [reflected, spec] = emitBindSSR({
|
|
1383
|
+
kind,
|
|
1124
1384
|
index,
|
|
1125
|
-
accessor:
|
|
1126
|
-
|
|
1385
|
+
accessor: sourceValue,
|
|
1386
|
+
optionValue: resolvedAttrText(node.props.value)
|
|
1127
1387
|
});
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
if (openQuote) stripLeadingQuote = openQuote;
|
|
1388
|
+
attrs += reflected;
|
|
1389
|
+
bindSpecs.push(spec);
|
|
1131
1390
|
continue;
|
|
1132
1391
|
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
const
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
}
|
|
1162
|
-
const url = String(resolved);
|
|
1163
|
-
if (!isSafeUrlAttrValue(openTagName(result + chunk, result.length + attrMatch.index), attrName, url)) {
|
|
1164
|
-
result += cleanPrefix;
|
|
1165
|
-
continue;
|
|
1166
|
-
}
|
|
1167
|
-
const quotedUrl = openQuote !== null || UNQUOTED_HAZARD_RE.test(url);
|
|
1168
|
-
result += cleanPrefix + ` ${attrName}=` + (quotedUrl ? `"${escapeHtml(url)}"` : escapeHtml(url));
|
|
1169
|
-
continue;
|
|
1170
|
-
}
|
|
1171
|
-
if (attrName.toLowerCase() === "style") {
|
|
1172
|
-
if (!isRawHtml(value)) {
|
|
1173
|
-
const resolved = resolveTemplateValue(value);
|
|
1174
|
-
if (isPlainObject(resolved)) {
|
|
1175
|
-
result += cleanPrefix + ` style="${escapeHtml(serializeStyle(resolved))}"`;
|
|
1176
|
-
continue;
|
|
1177
|
-
}
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
if (isRawHtml(value)) {
|
|
1181
|
-
stripLeadingQuote = null;
|
|
1182
|
-
result += chunk + interpolateValue(value);
|
|
1183
|
-
continue;
|
|
1184
|
-
}
|
|
1185
|
-
const resolved = resolveTemplateValue(value);
|
|
1186
|
-
if (resolved == null || resolved === false) {
|
|
1187
|
-
result += cleanPrefix;
|
|
1188
|
-
continue;
|
|
1189
|
-
}
|
|
1190
|
-
if (resolved === true) {
|
|
1191
|
-
result += cleanPrefix + ` ${attrName}`;
|
|
1192
|
-
continue;
|
|
1193
|
-
}
|
|
1194
|
-
const generic = String(resolved);
|
|
1195
|
-
if (openQuote !== null || UNQUOTED_HAZARD_RE.test(generic)) result += cleanPrefix + ` ${attrName}="${escapeHtml(generic)}"`;
|
|
1196
|
-
else result += cleanPrefix + ` ${attrName}=${escapeHtml(generic)}`;
|
|
1392
|
+
if (/^on/i.test(name)) {
|
|
1393
|
+
const match = TEMPLATE_EVENT.exec(name.toLowerCase());
|
|
1394
|
+
if (templateParts(sourceValue)?.some((part) => typeof part === "function")) throw new Error(`[ilha] ${name} handler must occupy the entire attribute value. Write ${name}=\${handler}.`);
|
|
1395
|
+
if (!match || typeof sourceValue !== "function") continue;
|
|
1396
|
+
const eventName = match[1];
|
|
1397
|
+
const rawModifier = match[2];
|
|
1398
|
+
const modifier = rawModifier !== void 0 && NATIVE_EVENT_MODIFIERS.has(rawModifier) ? rawModifier : void 0;
|
|
1399
|
+
if (rawModifier && !modifier) continue;
|
|
1400
|
+
const index = __ilhaJsxEvent({
|
|
1401
|
+
type: eventName,
|
|
1402
|
+
handler: sourceValue,
|
|
1403
|
+
modifier
|
|
1404
|
+
});
|
|
1405
|
+
if (index !== void 0) eventSpecs.push(`${eventName}:${index}`);
|
|
1406
|
+
continue;
|
|
1407
|
+
}
|
|
1408
|
+
const lower = name.toLowerCase();
|
|
1409
|
+
if (lower === "srcdoc") continue;
|
|
1410
|
+
const parts = templateParts(sourceValue);
|
|
1411
|
+
let value = parts ? parts.map((part) => resolveTemplateValue(part) ?? "").join("") : resolveTemplateValue(sourceValue);
|
|
1412
|
+
if ((lower.startsWith("aria-") || TEMPLATE_STRING_BOOLEANS.has(lower)) && typeof value === "boolean") value = String(value);
|
|
1413
|
+
if (lower === "class" && !isRawHtml(value)) value = normalizeTemplateClass(value);
|
|
1414
|
+
const structuredStyle = lower === "style" && isPlainObject(value) && !isRawHtml(value);
|
|
1415
|
+
if (structuredStyle) value = serializeStyle(value);
|
|
1416
|
+
if (isUrlAttributeName(lower) && !isRawHtml(value) && !isSafeUrlAttrValue(node.tag, lower, String(value))) continue;
|
|
1417
|
+
if (value === false || value == null) continue;
|
|
1418
|
+
if (attribute?.bare && value === "" || value === true && !TEMPLATE_STRING_BOOLEANS.has(lower) && !lower.startsWith("aria-")) {
|
|
1419
|
+
attrs += ` ${name}`;
|
|
1197
1420
|
continue;
|
|
1198
1421
|
}
|
|
1199
|
-
|
|
1422
|
+
const text = isRawHtml(value) ? value.value : String(value);
|
|
1423
|
+
const escaped = isRawHtml(value) ? text : escapeHtml(text);
|
|
1424
|
+
attrs += attribute && !attribute.quoted && !structuredStyle && !/[\s"'`=<>]/.test(text) ? ` ${name}=${escaped}` : ` ${name}="${escaped}"`;
|
|
1425
|
+
}
|
|
1426
|
+
const key = node.props.key;
|
|
1427
|
+
if (key != null && node.props["data-key"] == null) attrs += ` data-key="${escapeHtml(key)}"`;
|
|
1428
|
+
if (bindSpecs.length) attrs += ` data-ilha-bind="${bindSpecs.join(",")}"`;
|
|
1429
|
+
if (eventSpecs.length) attrs += ` data-ilha-on="${eventSpecs.join(",")}"`;
|
|
1430
|
+
if (TEMPLATE_VOID_ELEMENTS.has(node.tag.toLowerCase())) return `<${node.tag}${attrs}${node.selfClosing ? " /" : ""}>`;
|
|
1431
|
+
return `<${node.tag}${attrs}>${node.children.map((child) => renderTemplateNode(child, node.tag)).join("")}</${node.tag}>`;
|
|
1432
|
+
}
|
|
1433
|
+
function renderTemplateNode(node, parentTag) {
|
|
1434
|
+
switch (node.kind) {
|
|
1435
|
+
case "fragment": return node.children.map((child) => renderTemplateNode(child, parentTag)).join("");
|
|
1436
|
+
case "element": return renderTemplateElement(node);
|
|
1437
|
+
case "dynamic": return interpolateValue(node.value);
|
|
1438
|
+
case "comment": {
|
|
1439
|
+
const parts = templateParts(node.value);
|
|
1440
|
+
return `<!--${(parts ? parts.map((part) => resolveTemplateValue(part) ?? "").join("") : String(node.value)).replace(/--/g, "- -")}-->`;
|
|
1441
|
+
}
|
|
1442
|
+
case "text": {
|
|
1443
|
+
const parent = parentTag?.toLowerCase();
|
|
1444
|
+
return parent === "script" || parent === "style" ? node.value : escapeHtml(node.value);
|
|
1445
|
+
}
|
|
1200
1446
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
return
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1447
|
+
}
|
|
1448
|
+
function renderTemplate(node) {
|
|
1449
|
+
return ilhaRaw(renderTemplateNode(node));
|
|
1450
|
+
}
|
|
1451
|
+
setTemplateRenderer(renderTemplate);
|
|
1452
|
+
function ilhaHtml(strings, ...values) {
|
|
1453
|
+
return renderTemplate(htmlTemplate(strings, values));
|
|
1207
1454
|
}
|
|
1208
1455
|
function isRawHtml(v) {
|
|
1209
1456
|
if (typeof v !== "object" || v === null) return false;
|
|
@@ -1216,9 +1463,8 @@ const contextRegistry = /* @__PURE__ */ new Map();
|
|
|
1216
1463
|
function ilhaContextFn(key, initial) {
|
|
1217
1464
|
if (contextRegistry.has(key)) return contextRegistry.get(key);
|
|
1218
1465
|
const s = signal(initial);
|
|
1219
|
-
const accessor = markSignalAccessor((
|
|
1220
|
-
|
|
1221
|
-
s(resolveSignalSetter(() => s(), args[0]));
|
|
1466
|
+
const accessor = markSignalAccessor(() => s(), (next) => {
|
|
1467
|
+
s(next);
|
|
1222
1468
|
});
|
|
1223
1469
|
contextRegistry.set(key, accessor);
|
|
1224
1470
|
return accessor;
|
|
@@ -1241,9 +1487,8 @@ const ilhaContext = Object.assign(ilhaContextFn, {
|
|
|
1241
1487
|
function ilhaSignal(initial) {
|
|
1242
1488
|
if (currentFrame()?.creating && __DEV__);
|
|
1243
1489
|
const s = signal(initial);
|
|
1244
|
-
return markSignalAccessor((
|
|
1245
|
-
|
|
1246
|
-
s(resolveSignalSetter(() => s(), args[0]));
|
|
1490
|
+
return markSignalAccessor(() => s(), (next) => {
|
|
1491
|
+
s(next);
|
|
1247
1492
|
});
|
|
1248
1493
|
}
|
|
1249
1494
|
/**
|
|
@@ -1353,7 +1598,7 @@ function persist(accessor, key, options = {}) {
|
|
|
1353
1598
|
if (value !== null) {
|
|
1354
1599
|
const prevSub = setActiveSub(void 0);
|
|
1355
1600
|
try {
|
|
1356
|
-
accessor(
|
|
1601
|
+
accessor.set(value);
|
|
1357
1602
|
} finally {
|
|
1358
1603
|
setActiveSub(prevSub);
|
|
1359
1604
|
}
|
|
@@ -1388,12 +1633,8 @@ function persist(accessor, key, options = {}) {
|
|
|
1388
1633
|
};
|
|
1389
1634
|
}
|
|
1390
1635
|
function createDerivedAccessor(read, write) {
|
|
1391
|
-
const accessor = markSignalAccessor((
|
|
1392
|
-
if (
|
|
1393
|
-
if (write) write(args[0]);
|
|
1394
|
-
return;
|
|
1395
|
-
}
|
|
1396
|
-
return read().value;
|
|
1636
|
+
const accessor = markSignalAccessor(() => read().value, (value) => {
|
|
1637
|
+
if (write) write(value);
|
|
1397
1638
|
});
|
|
1398
1639
|
return new Proxy(accessor, { get(target, prop, receiver) {
|
|
1399
1640
|
if (prop === "loading" || prop === "value" || prop === "error") return read()[prop];
|
|
@@ -1563,8 +1804,8 @@ function applyTemplateBindings(host, binds, phase = "all") {
|
|
|
1563
1804
|
const accessor = record.accessor;
|
|
1564
1805
|
if (spec.kind === "this") {
|
|
1565
1806
|
if (phase !== "listen") {
|
|
1566
|
-
accessor(el);
|
|
1567
|
-
cleanups.push(() => accessor(null));
|
|
1807
|
+
accessor.set(el);
|
|
1808
|
+
cleanups.push(() => accessor.set(null));
|
|
1568
1809
|
}
|
|
1569
1810
|
continue;
|
|
1570
1811
|
}
|
|
@@ -1592,7 +1833,7 @@ function applyTemplateBindings(host, binds, phase = "all") {
|
|
|
1592
1833
|
}
|
|
1593
1834
|
arr.push(coercedVal);
|
|
1594
1835
|
} else if (!groupRead.checked && idx !== -1) arr.splice(idx, 1);
|
|
1595
|
-
accessor(arr);
|
|
1836
|
+
accessor.set(arr);
|
|
1596
1837
|
return;
|
|
1597
1838
|
}
|
|
1598
1839
|
const currentVal = accessor();
|
|
@@ -1601,7 +1842,7 @@ function applyTemplateBindings(host, binds, phase = "all") {
|
|
|
1601
1842
|
const n = Number(groupRead);
|
|
1602
1843
|
coerced = Number.isNaN(n) ? 0 : n;
|
|
1603
1844
|
} else if (typeof currentVal === "boolean") coerced = Boolean(groupRead);
|
|
1604
|
-
accessor(coerced);
|
|
1845
|
+
accessor.set(coerced);
|
|
1605
1846
|
return;
|
|
1606
1847
|
}
|
|
1607
1848
|
const currentVal = accessor();
|
|
@@ -1610,7 +1851,7 @@ function applyTemplateBindings(host, binds, phase = "all") {
|
|
|
1610
1851
|
const n = Number(raw);
|
|
1611
1852
|
value = Number.isNaN(n) ? 0 : n;
|
|
1612
1853
|
} else if (typeof currentVal === "boolean") value = Boolean(raw);
|
|
1613
|
-
accessor(value);
|
|
1854
|
+
accessor.set(value);
|
|
1614
1855
|
};
|
|
1615
1856
|
el.addEventListener(event, listener);
|
|
1616
1857
|
cleanups.push(() => el.removeEventListener(event, listener));
|
|
@@ -1694,8 +1935,8 @@ function acquireSlot(kind) {
|
|
|
1694
1935
|
*
|
|
1695
1936
|
* A function argument is treated as a lazy initializer:
|
|
1696
1937
|
* const count = state(() => expensiveInitialValue());
|
|
1697
|
-
* To store a function VALUE,
|
|
1698
|
-
*
|
|
1938
|
+
* To store a function VALUE, pass it to `.set`:
|
|
1939
|
+
* onSave.set(nextCallback);
|
|
1699
1940
|
*/
|
|
1700
1941
|
function state(init) {
|
|
1701
1942
|
const frame = currentFrame();
|
|
@@ -1707,9 +1948,7 @@ function state(init) {
|
|
|
1707
1948
|
const snap = f.ssr ? void 0 : f.instance?.stateSnapshot?.s?.[index];
|
|
1708
1949
|
const initial = snap === void 0 ? typeof init === "function" ? init() : init : snap;
|
|
1709
1950
|
const s = signal(initial);
|
|
1710
|
-
const acc = markSignalAccessor((
|
|
1711
|
-
if (args.length === 0) return s();
|
|
1712
|
-
const next = resolveSignalSetter(() => s(), args[0]);
|
|
1951
|
+
const acc = markSignalAccessor(() => s(), (next) => {
|
|
1713
1952
|
s(next);
|
|
1714
1953
|
});
|
|
1715
1954
|
f.slots[f.cursor - 1] = {
|
|
@@ -2981,4 +3220,4 @@ const mount = mountAll;
|
|
|
2981
3220
|
const context = ilhaContext;
|
|
2982
3221
|
|
|
2983
3222
|
//#endregion
|
|
2984
|
-
export { action, batch, context, css, derived, each, effect, html, ilha,
|
|
3223
|
+
export { action, batch, context, css, derived, each, effect, html, ilha, isSafeUrl, isSafeUrlAttrValue, isUrlAttributeName, json, morph, mount, onError, onUncaughtError, persist, raw, serializeStyle, state, untrack };
|