@mintjamsinc/ichigojs 0.1.84 → 0.1.86
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/ichigo.cjs +105 -49
- package/dist/ichigo.cjs.map +1 -1
- package/dist/ichigo.esm.js +105 -49
- package/dist/ichigo.esm.js.map +1 -1
- package/dist/ichigo.esm.min.js +1 -1
- package/dist/ichigo.min.cjs +1 -1
- package/dist/ichigo.umd.js +105 -49
- package/dist/ichigo.umd.js.map +1 -1
- package/dist/ichigo.umd.min.js +1 -1
- package/dist/types/ichigo/util/ExpressionUtils.d.ts +7 -0
- package/dist/types/ichigo/util/ReactiveProxy.d.ts +17 -0
- package/package.json +1 -1
package/dist/ichigo.esm.js
CHANGED
|
@@ -6760,28 +6760,29 @@ class ExpressionUtils {
|
|
|
6760
6760
|
}
|
|
6761
6761
|
}
|
|
6762
6762
|
else if (node.type === 'MemberExpression') {
|
|
6763
|
-
// Reconstruct chain parts from a MemberExpression (e.g. a.b.c)
|
|
6763
|
+
// Reconstruct chain parts from a MemberExpression (e.g. a.b.c). Each part
|
|
6764
|
+
// carries its own separator so that the chain is spelled the way the reactive
|
|
6765
|
+
// proxy reports changes: array indices in brackets, properties after a dot
|
|
6766
|
+
// (e.g. "items[0].name").
|
|
6764
6767
|
const parts = [];
|
|
6765
6768
|
let cur = node;
|
|
6766
|
-
|
|
6767
|
-
while (cur && !stop) {
|
|
6769
|
+
while (cur) {
|
|
6768
6770
|
// property part (right side)
|
|
6769
6771
|
if (cur.property) {
|
|
6770
6772
|
if (!cur.computed && cur.property.type === 'Identifier') {
|
|
6771
|
-
parts.unshift(cur.property.name);
|
|
6773
|
+
parts.unshift(`.${cur.property.name}`);
|
|
6774
|
+
}
|
|
6775
|
+
else if (cur.computed && cur.property.type === 'Literal' && typeof cur.property.value === 'number') {
|
|
6776
|
+
parts.unshift(`[${cur.property.value}]`);
|
|
6772
6777
|
}
|
|
6773
6778
|
else if (cur.computed && cur.property.type === 'Literal') {
|
|
6774
|
-
parts.unshift(String(cur.property.value));
|
|
6779
|
+
parts.unshift(`.${String(cur.property.value)}`);
|
|
6775
6780
|
}
|
|
6776
|
-
else if (cur.computed
|
|
6777
|
-
// e.g.
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
// unknown property shape (e.g. expression) — stop adding chain here
|
|
6782
|
-
// inner expressions will be visited separately by walk.full
|
|
6783
|
-
stop = true;
|
|
6784
|
-
break;
|
|
6781
|
+
else if (cur.computed) {
|
|
6782
|
+
// e.g. items[i] or items[i + 1]: the index is only known when the
|
|
6783
|
+
// expression runs, so "[*]" stands for any index or key. Identifiers
|
|
6784
|
+
// inside the index expression are visited separately by walk.full.
|
|
6785
|
+
parts.unshift('[*]');
|
|
6785
6786
|
}
|
|
6786
6787
|
}
|
|
6787
6788
|
// object part (left side)
|
|
@@ -6801,7 +6802,6 @@ class ExpressionUtils {
|
|
|
6801
6802
|
}
|
|
6802
6803
|
else {
|
|
6803
6804
|
// other object types (CallExpression, etc.) — stop here
|
|
6804
|
-
stop = true;
|
|
6805
6805
|
break;
|
|
6806
6806
|
}
|
|
6807
6807
|
}
|
|
@@ -6809,10 +6809,15 @@ class ExpressionUtils {
|
|
|
6809
6809
|
break;
|
|
6810
6810
|
}
|
|
6811
6811
|
}
|
|
6812
|
-
|
|
6813
|
-
|
|
6812
|
+
// A chain that does not start at a name (e.g. `this.a.b` or `f().b`) begins
|
|
6813
|
+
// with its first property; one that begins with an index names no binding.
|
|
6814
|
+
if (parts.length > 0 && parts[0].startsWith('.')) {
|
|
6815
|
+
parts[0] = parts[0].substring(1);
|
|
6816
|
+
}
|
|
6817
|
+
if (parts.length > 0 && !parts[0].startsWith('[')) {
|
|
6818
|
+
// Add progressive chains: 'a', 'a.b', 'a.b[0]', 'a.b[0].c'
|
|
6814
6819
|
for (let i = 0; i < parts.length; i++) {
|
|
6815
|
-
const chain = parts.slice(0, i + 1).join('
|
|
6820
|
+
const chain = parts.slice(0, i + 1).join('');
|
|
6816
6821
|
identifiers.add(chain);
|
|
6817
6822
|
// Also apply functionDependencies lookup for the chain key
|
|
6818
6823
|
if (functionDependencies[chain]) {
|
|
@@ -6826,6 +6831,16 @@ class ExpressionUtils {
|
|
|
6826
6831
|
});
|
|
6827
6832
|
return Array.from(identifiers);
|
|
6828
6833
|
}
|
|
6834
|
+
/**
|
|
6835
|
+
* Returns the binding name an identifier chain starts with
|
|
6836
|
+
* (e.g. "items" for "items[0].name" or "user.name").
|
|
6837
|
+
* @param identifier An identifier or member chain returned by extractIdentifiers.
|
|
6838
|
+
* @returns The left-most name of the chain.
|
|
6839
|
+
*/
|
|
6840
|
+
static baseIdentifier(identifier) {
|
|
6841
|
+
const end = identifier.search(/[.[]/);
|
|
6842
|
+
return end === -1 ? identifier : identifier.substring(0, end);
|
|
6843
|
+
}
|
|
6829
6844
|
/**
|
|
6830
6845
|
* Analyzes the dependencies of functions in the provided dictionary.
|
|
6831
6846
|
* @param functions A dictionary mapping function names to their implementations.
|
|
@@ -7240,7 +7255,7 @@ class ExpressionEvaluator {
|
|
|
7240
7255
|
// Use the base (left-most) segment of member chains and preserve order.
|
|
7241
7256
|
const baseIdentifiers = [];
|
|
7242
7257
|
for (const id of extractedIdentifiers) {
|
|
7243
|
-
const base =
|
|
7258
|
+
const base = ExpressionUtils.baseIdentifier(id);
|
|
7244
7259
|
if (!baseIdentifiers.includes(base)) {
|
|
7245
7260
|
baseIdentifiers.push(base);
|
|
7246
7261
|
}
|
|
@@ -7781,13 +7796,20 @@ class VBindDirective {
|
|
|
7781
7796
|
}
|
|
7782
7797
|
/**
|
|
7783
7798
|
* Updates a regular attribute.
|
|
7799
|
+
* An attribute that already holds the value is left alone: setting `src` on
|
|
7800
|
+
* an <iframe>, even to the same URL, loads its page again.
|
|
7784
7801
|
*/
|
|
7785
7802
|
#updateAttribute(element, name, value) {
|
|
7786
7803
|
if (value == null || value === false) {
|
|
7787
|
-
element.
|
|
7804
|
+
if (element.hasAttribute(name)) {
|
|
7805
|
+
element.removeAttribute(name);
|
|
7806
|
+
}
|
|
7788
7807
|
}
|
|
7789
7808
|
else {
|
|
7790
|
-
|
|
7809
|
+
const text = String(value);
|
|
7810
|
+
if (element.getAttribute(name) !== text) {
|
|
7811
|
+
element.setAttribute(name, text);
|
|
7812
|
+
}
|
|
7791
7813
|
}
|
|
7792
7814
|
}
|
|
7793
7815
|
}
|
|
@@ -8027,6 +8049,11 @@ class ReactiveProxy {
|
|
|
8027
8049
|
* This allows mapping variable names to their actual source paths for dependency tracking.
|
|
8028
8050
|
*/
|
|
8029
8051
|
static pathAliases = new Map();
|
|
8052
|
+
/**
|
|
8053
|
+
* Compiled patterns for identifiers that contain a "[*]" index, keyed by the
|
|
8054
|
+
* identifier and whether descendants of the path also match.
|
|
8055
|
+
*/
|
|
8056
|
+
static pathPatterns = new Map();
|
|
8030
8057
|
/**
|
|
8031
8058
|
* The `Object.prototype.toString` tags of the *only* value types we deeply
|
|
8032
8059
|
* proxy. Everything else is returned untouched (raw).
|
|
@@ -8389,24 +8416,47 @@ class ReactiveProxy {
|
|
|
8389
8416
|
*/
|
|
8390
8417
|
static doesChangeMatchIdentifier(changePath, identifier) {
|
|
8391
8418
|
// Direct match
|
|
8392
|
-
if (changePath
|
|
8419
|
+
if (this.pathMatches(changePath, identifier)) {
|
|
8393
8420
|
return true;
|
|
8394
8421
|
}
|
|
8395
|
-
// Check if the identifier
|
|
8422
|
+
// Check if the change path is the resolved identifier or lies below it
|
|
8423
|
+
// (handles cases like array item changes)
|
|
8396
8424
|
const resolvedIdentifier = this.resolvePathAlias(identifier);
|
|
8397
|
-
if (resolvedIdentifier && changePath
|
|
8425
|
+
if (resolvedIdentifier && this.pathMatches(changePath, resolvedIdentifier, true)) {
|
|
8398
8426
|
return true;
|
|
8399
8427
|
}
|
|
8400
|
-
// Check if change path starts with the resolved identifier
|
|
8401
|
-
// (handles cases like array item changes)
|
|
8402
|
-
if (resolvedIdentifier) {
|
|
8403
|
-
if (changePath.startsWith(resolvedIdentifier + '.') ||
|
|
8404
|
-
changePath.startsWith(resolvedIdentifier + '[')) {
|
|
8405
|
-
return true;
|
|
8406
|
-
}
|
|
8407
|
-
}
|
|
8408
8428
|
return false;
|
|
8409
8429
|
}
|
|
8430
|
+
/**
|
|
8431
|
+
* Checks whether a change path names the location an identifier refers to.
|
|
8432
|
+
* A "[*]" index in the identifier (e.g. "items[*].name" for `items[i].name`)
|
|
8433
|
+
* stands for an index known only when the expression runs and matches any
|
|
8434
|
+
* one index or key.
|
|
8435
|
+
*
|
|
8436
|
+
* @param changePath The path that was changed (e.g., "items[2].name")
|
|
8437
|
+
* @param identifier The identifier to check (e.g., "items[*].name")
|
|
8438
|
+
* @param descendants Whether a change below the identifier also matches
|
|
8439
|
+
* @returns True if the change path matches the identifier
|
|
8440
|
+
*/
|
|
8441
|
+
static pathMatches(changePath, identifier, descendants = false) {
|
|
8442
|
+
if (changePath === identifier) {
|
|
8443
|
+
return true;
|
|
8444
|
+
}
|
|
8445
|
+
if (!identifier.includes('[*]')) {
|
|
8446
|
+
return descendants && (changePath.startsWith(identifier + '.') || changePath.startsWith(identifier + '['));
|
|
8447
|
+
}
|
|
8448
|
+
const cacheKey = descendants ? identifier + ' ' : identifier;
|
|
8449
|
+
let pattern = this.pathPatterns.get(cacheKey);
|
|
8450
|
+
if (!pattern) {
|
|
8451
|
+
const source = identifier
|
|
8452
|
+
.split('[*]')
|
|
8453
|
+
.map(part => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
8454
|
+
.join('(?:\\[[^\\]]*\\]|\\.[^.[]+)');
|
|
8455
|
+
pattern = new RegExp(`^${source}${descendants ? '(?:[.[].*)?' : ''}$`);
|
|
8456
|
+
this.pathPatterns.set(cacheKey, pattern);
|
|
8457
|
+
}
|
|
8458
|
+
return pattern.test(changePath);
|
|
8459
|
+
}
|
|
8410
8460
|
}
|
|
8411
8461
|
|
|
8412
8462
|
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
|
@@ -8902,18 +8952,15 @@ class VBindings {
|
|
|
8902
8952
|
* global aliases (computed properties etc.).
|
|
8903
8953
|
*/
|
|
8904
8954
|
doesChangeMatchIdentifier(changePath, identifier) {
|
|
8905
|
-
// Direct match
|
|
8906
|
-
if (changePath
|
|
8955
|
+
// Direct match (an index "[*]" in the identifier matches any index)
|
|
8956
|
+
if (ReactiveProxy.pathMatches(changePath, identifier)) {
|
|
8907
8957
|
return true;
|
|
8908
8958
|
}
|
|
8909
8959
|
// Resolve via local (scoped) alias chain
|
|
8910
8960
|
const resolved = this.resolveAlias(identifier);
|
|
8911
8961
|
if (resolved) {
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
}
|
|
8915
|
-
// changePath is a descendant of resolved (e.g. "files[0].isModified" for resolved "files[0]")
|
|
8916
|
-
if (changePath.startsWith(resolved + '.') || changePath.startsWith(resolved + '[')) {
|
|
8962
|
+
// changePath is resolved itself or a descendant of it (e.g. "files[0].isModified" for resolved "files[0]")
|
|
8963
|
+
if (ReactiveProxy.pathMatches(changePath, resolved, true)) {
|
|
8917
8964
|
return true;
|
|
8918
8965
|
}
|
|
8919
8966
|
// changePath is an ancestor of resolved (e.g. "files" for resolved "files[0].isModified")
|
|
@@ -9978,7 +10025,7 @@ class VTextEvaluator {
|
|
|
9978
10025
|
// Build base parameter names (no dots), preserving order of first appearance
|
|
9979
10026
|
const baseArgs = [];
|
|
9980
10027
|
for (const id of ids) {
|
|
9981
|
-
const base =
|
|
10028
|
+
const base = ExpressionUtils.baseIdentifier(id);
|
|
9982
10029
|
if (!baseArgs.includes(base)) {
|
|
9983
10030
|
baseArgs.push(base);
|
|
9984
10031
|
}
|
|
@@ -12054,6 +12101,11 @@ class VHtmlDirective {
|
|
|
12054
12101
|
* The expression evaluator for this directive.
|
|
12055
12102
|
*/
|
|
12056
12103
|
#evaluator;
|
|
12104
|
+
/**
|
|
12105
|
+
* The HTML last set on the element. The same HTML is not set again: that
|
|
12106
|
+
* would replace the elements inside, and load their frames and images again.
|
|
12107
|
+
*/
|
|
12108
|
+
#html;
|
|
12057
12109
|
/**
|
|
12058
12110
|
* @param context The context for parsing the directive.
|
|
12059
12111
|
*/
|
|
@@ -12104,10 +12156,14 @@ class VHtmlDirective {
|
|
|
12104
12156
|
get dependentIdentifiers() {
|
|
12105
12157
|
return identifiers;
|
|
12106
12158
|
},
|
|
12107
|
-
applyToDOM() {
|
|
12159
|
+
applyToDOM: () => {
|
|
12108
12160
|
const element = vNode.node;
|
|
12109
|
-
const htmlContent = evaluator.evaluate();
|
|
12110
|
-
|
|
12161
|
+
const htmlContent = evaluator.evaluate() ?? '';
|
|
12162
|
+
if (htmlContent === this.#html) {
|
|
12163
|
+
return;
|
|
12164
|
+
}
|
|
12165
|
+
this.#html = htmlContent;
|
|
12166
|
+
element.innerHTML = htmlContent;
|
|
12111
12167
|
}
|
|
12112
12168
|
};
|
|
12113
12169
|
return updater;
|
|
@@ -12314,7 +12370,7 @@ class VIntersectionDirective {
|
|
|
12314
12370
|
const identifiers = optionsDirective.dependentIdentifiers;
|
|
12315
12371
|
const baseArgs = [];
|
|
12316
12372
|
for (const id of identifiers) {
|
|
12317
|
-
const base =
|
|
12373
|
+
const base = ExpressionUtils.baseIdentifier(id);
|
|
12318
12374
|
if (!baseArgs.includes(base))
|
|
12319
12375
|
baseArgs.push(base);
|
|
12320
12376
|
}
|
|
@@ -12394,7 +12450,7 @@ class VIntersectionDirective {
|
|
|
12394
12450
|
// Note: inline expressions receive entries and $ctx as parameters
|
|
12395
12451
|
const baseArgs = [];
|
|
12396
12452
|
for (const id of identifiers) {
|
|
12397
|
-
const base =
|
|
12453
|
+
const base = ExpressionUtils.baseIdentifier(id);
|
|
12398
12454
|
if (!baseArgs.includes(base))
|
|
12399
12455
|
baseArgs.push(base);
|
|
12400
12456
|
}
|
|
@@ -13532,7 +13588,7 @@ class VPerformanceDirective {
|
|
|
13532
13588
|
const identifiers = optionsDirective.dependentIdentifiers;
|
|
13533
13589
|
const baseArgs = [];
|
|
13534
13590
|
for (const id of identifiers) {
|
|
13535
|
-
const base =
|
|
13591
|
+
const base = ExpressionUtils.baseIdentifier(id);
|
|
13536
13592
|
if (!baseArgs.includes(base))
|
|
13537
13593
|
baseArgs.push(base);
|
|
13538
13594
|
}
|
|
@@ -13620,7 +13676,7 @@ class VPerformanceDirective {
|
|
|
13620
13676
|
// Note: inline expressions receive entries, observer, options, and $ctx as parameters
|
|
13621
13677
|
const baseArgs = [];
|
|
13622
13678
|
for (const id of identifiers) {
|
|
13623
|
-
const base =
|
|
13679
|
+
const base = ExpressionUtils.baseIdentifier(id);
|
|
13624
13680
|
if (!baseArgs.includes(base))
|
|
13625
13681
|
baseArgs.push(base);
|
|
13626
13682
|
}
|
|
@@ -13753,7 +13809,7 @@ class VResizeDirective {
|
|
|
13753
13809
|
const identifiers = optionsDirective.dependentIdentifiers;
|
|
13754
13810
|
const baseArgs = [];
|
|
13755
13811
|
for (const id of identifiers) {
|
|
13756
|
-
const base =
|
|
13812
|
+
const base = ExpressionUtils.baseIdentifier(id);
|
|
13757
13813
|
if (!baseArgs.includes(base))
|
|
13758
13814
|
baseArgs.push(base);
|
|
13759
13815
|
}
|
|
@@ -13833,7 +13889,7 @@ class VResizeDirective {
|
|
|
13833
13889
|
// Note: inline expressions receive entries and $ctx as parameters
|
|
13834
13890
|
const baseArgs = [];
|
|
13835
13891
|
for (const id of identifiers) {
|
|
13836
|
-
const base =
|
|
13892
|
+
const base = ExpressionUtils.baseIdentifier(id);
|
|
13837
13893
|
if (!baseArgs.includes(base))
|
|
13838
13894
|
baseArgs.push(base);
|
|
13839
13895
|
}
|