assign-gingerly 0.0.64 → 0.0.66
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 +85 -26
- package/assignFrom.js +21 -19
- package/assignFrom.ts +28 -25
- package/assignFromAsync.js +10 -7
- package/assignFromAsync.ts +15 -98
- package/assignGingerly.js +54 -26
- package/assignGingerly.ts +62 -27
- package/assignTentatively.js +8 -0
- package/assignTentatively.ts +6 -0
- package/{builtInEmoji.ts → emojis.js} +46 -34
- package/emojis.ts +52 -0
- package/getValues.js +80 -25
- package/getValues.ts +85 -26
- package/handlers/addEventListener.js +153 -0
- package/handlers/addEventListener.ts +178 -0
- package/handlers/arr.js +13 -0
- package/handlers/arr.ts +13 -0
- package/handlers/lazyLoad.js +3 -3
- package/handlers/lazyLoad.ts +3 -3
- package/handlers/manageTemplateList.js +48 -21
- package/handlers/manageTemplateList.ts +51 -21
- package/handlers/nudge.js +23 -0
- package/handlers/nudge.ts +23 -0
- package/index.js +2 -0
- package/index.ts +2 -0
- package/inferencer/types/assign-gingerly/types.d.ts +327 -1
- package/inferencer/types/mount-observer/types.d.ts +10 -2
- package/inferencer/types/roundabout/types.d.ts +1 -1
- package/inferencer/types/three-peat/types.d.ts +18 -0
- package/object-extension.js +1 -1
- package/package.json +12 -4
- package/paths.ts +1 -1
- package/{withIdsCorrector.js → pinCorrector.js} +5 -5
- package/{withIdsCorrector.ts → pinCorrector.ts} +5 -5
- package/processHandlerCommands.js +4 -2
- package/processHandlerCommands.ts +4 -2
- package/resolveIdRef.js +8 -8
- package/resolveIdRef.ts +9 -9
- package/resolveValues.js +20 -88
- package/resolveValues.ts +17 -91
- package/types/assign-gingerly/types.d.ts +159 -3
- package/builtInEmoji.js +0 -26
package/handlers/lazyLoad.ts
CHANGED
|
@@ -317,10 +317,10 @@ export class LazyLoadHandler implements AssignFromHandler {
|
|
|
317
317
|
const len = Math.min(elements.length, assign.configs.length);
|
|
318
318
|
for (let j = 0; j < len; j++) {
|
|
319
319
|
const cfg = assign.configs[j];
|
|
320
|
-
assignFrom(elements[j], cfg.
|
|
320
|
+
assignFrom(elements[j], cfg.toClone ?? {}, { from, ...cfg.withOptions });
|
|
321
321
|
}
|
|
322
|
-
} else if (assign.
|
|
323
|
-
assignFrom(elements[0], assign.
|
|
322
|
+
} else if (assign.toClone) {
|
|
323
|
+
assignFrom(elements[0], assign.toClone, { from, ...assign.withOptions });
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* instantiate: 'globalThis://country-ranking',
|
|
18
18
|
* },
|
|
19
19
|
* fromEachItem: {
|
|
20
|
-
*
|
|
20
|
+
* '?.querySelector?.tr?.ish': '?.',
|
|
21
21
|
* withOptions: { withMethods: ['querySelector'], infer: true },
|
|
22
22
|
* resolve: { key: '?.rank' }
|
|
23
23
|
* }
|
|
@@ -28,6 +28,24 @@ import { findMarkers, createMarkers } from '../markerUtils.js';
|
|
|
28
28
|
import { resolveValue } from '../resolveValues.js';
|
|
29
29
|
import { assignFrom } from '../assignFrom.js';
|
|
30
30
|
import { processInferredAssignments } from '../inferredAssignments.js';
|
|
31
|
+
/**
|
|
32
|
+
* Reserved keys in fromEachItem config — not treated as shorthand patterns.
|
|
33
|
+
*/
|
|
34
|
+
const RESERVED_KEYS = new Set(['toClone', 'withOptions', 'resolve', 'get', 'configs']);
|
|
35
|
+
/**
|
|
36
|
+
* Extract shorthand patterns from fromEachItem config (non-reserved keys → toClone).
|
|
37
|
+
*/
|
|
38
|
+
function extractToClone(config) {
|
|
39
|
+
if (!config)
|
|
40
|
+
return {};
|
|
41
|
+
const result = {};
|
|
42
|
+
for (const key of Object.keys(config)) {
|
|
43
|
+
if (!RESERVED_KEYS.has(key)) {
|
|
44
|
+
result[key] = config[key];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
31
49
|
const listStateMap = new WeakMap();
|
|
32
50
|
/**
|
|
33
51
|
* ManageTemplateListHandler — clones a template per iterable item with keyed reconciliation.
|
|
@@ -46,20 +64,23 @@ export class ManageTemplateListHandler {
|
|
|
46
64
|
if (!items || typeof items[Symbol.iterator] !== 'function') {
|
|
47
65
|
return; // Nothing to iterate
|
|
48
66
|
}
|
|
49
|
-
const fromEachItem = this.config
|
|
67
|
+
const { fromEachItem, fromHost: fromHostConfig, fromTarget: fromTargetConfig } = this.config;
|
|
50
68
|
const configs = fromEachItem?.configs; // Array form for multi-element templates
|
|
51
|
-
const assignToFragment = fromEachItem?.assignToFragment ?? {};
|
|
52
69
|
const withOptions = fromEachItem?.withOptions ?? {};
|
|
53
|
-
const perItemResolve = fromEachItem?.resolve ?? {};
|
|
54
|
-
const keyPath = perItemResolve
|
|
55
|
-
//
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
70
|
+
const perItemResolve = fromEachItem?.resolve ?? fromEachItem?.get ?? {};
|
|
71
|
+
const { key: keyPath } = perItemResolve; // e.g., '?.rank'
|
|
72
|
+
// Resolve toClone patterns: explicit `toClone` key, or shorthand (non-reserved keys)
|
|
73
|
+
const toClone = fromEachItem?.toClone ?? extractToClone(fromEachItem);
|
|
74
|
+
// fromHost config — assigns from options.from (host/VM) to each clone
|
|
75
|
+
const hostToClone = fromHostConfig ? (fromHostConfig.toClone ?? extractToClone(fromHostConfig)) : undefined;
|
|
76
|
+
const hostWithOptions = fromHostConfig?.withOptions ?? {};
|
|
77
|
+
// fromTarget config — assigns from the target element to each clone
|
|
78
|
+
const targetToClone = fromTargetConfig ? (fromTargetConfig.toClone ?? extractToClone(fromTargetConfig)) : undefined;
|
|
79
|
+
const targetWithOptions = fromTargetConfig?.withOptions ?? {};
|
|
80
|
+
// Detect fast path: no toClone patterns, just infer (only for non-configs mode)
|
|
81
|
+
const hasAssignPatterns = !configs && Object.keys(toClone).length > 0;
|
|
61
82
|
const inferredConfig = !configs && withOptions.infer;
|
|
62
|
-
const useFastPath = !configs && !hasAssignPatterns && inferredConfig && !
|
|
83
|
+
const useFastPath = !configs && !hasAssignPatterns && inferredConfig && !hostToClone && !targetToClone;
|
|
63
84
|
const name = markerName ?? getMarkerName(instantiate) ?? 'templateList';
|
|
64
85
|
// Find or create markers
|
|
65
86
|
let [startMarker, endMarker] = findMarkers(lhsTarget, name);
|
|
@@ -122,7 +143,7 @@ export class ManageTemplateListHandler {
|
|
|
122
143
|
const len = Math.min(elements.length, configs.length);
|
|
123
144
|
for (let j = 0; j < len; j++) {
|
|
124
145
|
const cfg = configs[j];
|
|
125
|
-
assignFrom(elements[j], cfg.
|
|
146
|
+
assignFrom(elements[j], cfg.toClone ?? {}, { from: item, ...cfg.withOptions });
|
|
126
147
|
}
|
|
127
148
|
}
|
|
128
149
|
else {
|
|
@@ -132,10 +153,13 @@ export class ManageTemplateListHandler {
|
|
|
132
153
|
processInferred(rootEl, item, inferredConfig === true ? { byItemprop: true } : inferredConfig);
|
|
133
154
|
}
|
|
134
155
|
else {
|
|
135
|
-
assignFrom(rootEl,
|
|
156
|
+
assignFrom(rootEl, toClone, { from: item, ...withOptions });
|
|
136
157
|
}
|
|
137
|
-
if (
|
|
138
|
-
assignFrom(rootEl,
|
|
158
|
+
if (hostToClone && options?.from) {
|
|
159
|
+
assignFrom(rootEl, hostToClone, { from: options.from, ...hostWithOptions });
|
|
160
|
+
}
|
|
161
|
+
if (targetToClone) {
|
|
162
|
+
assignFrom(rootEl, targetToClone, { from: lhsTarget, ...targetWithOptions });
|
|
139
163
|
}
|
|
140
164
|
}
|
|
141
165
|
}
|
|
@@ -149,7 +173,7 @@ export class ManageTemplateListHandler {
|
|
|
149
173
|
// New item — clone template
|
|
150
174
|
let content;
|
|
151
175
|
if (instantiate instanceof HTMLTemplateElement) {
|
|
152
|
-
content = instantiate.content.cloneNode(true);
|
|
176
|
+
content = (instantiate.remoteContent || instantiate.content).cloneNode(true);
|
|
153
177
|
}
|
|
154
178
|
else if (instantiate instanceof DocumentFragment) {
|
|
155
179
|
content = instantiate.cloneNode(true);
|
|
@@ -168,7 +192,7 @@ export class ManageTemplateListHandler {
|
|
|
168
192
|
const len = Math.min(elements.length, configs.length);
|
|
169
193
|
for (let j = 0; j < len; j++) {
|
|
170
194
|
const cfg = configs[j];
|
|
171
|
-
assignFrom(elements[j], cfg.
|
|
195
|
+
assignFrom(elements[j], cfg.toClone ?? {}, { from: item, ...cfg.withOptions });
|
|
172
196
|
}
|
|
173
197
|
}
|
|
174
198
|
else {
|
|
@@ -180,10 +204,13 @@ export class ManageTemplateListHandler {
|
|
|
180
204
|
processInferred(rootEl, item, inferredConfig === true ? { byItemprop: true } : inferredConfig);
|
|
181
205
|
}
|
|
182
206
|
else {
|
|
183
|
-
assignFrom(rootEl,
|
|
207
|
+
assignFrom(rootEl, toClone, { from: item, ...withOptions });
|
|
208
|
+
}
|
|
209
|
+
if (hostToClone && options?.from) {
|
|
210
|
+
assignFrom(rootEl, hostToClone, { from: options.from, ...hostWithOptions });
|
|
184
211
|
}
|
|
185
|
-
if (
|
|
186
|
-
assignFrom(rootEl,
|
|
212
|
+
if (targetToClone) {
|
|
213
|
+
assignFrom(rootEl, targetToClone, { from: lhsTarget, ...targetWithOptions });
|
|
187
214
|
}
|
|
188
215
|
}
|
|
189
216
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* instantiate: 'globalThis://country-ranking',
|
|
18
18
|
* },
|
|
19
19
|
* fromEachItem: {
|
|
20
|
-
*
|
|
20
|
+
* '?.querySelector?.tr?.ish': '?.',
|
|
21
21
|
* withOptions: { withMethods: ['querySelector'], infer: true },
|
|
22
22
|
* resolve: { key: '?.rank' }
|
|
23
23
|
* }
|
|
@@ -32,6 +32,25 @@ import { resolveValue } from '../resolveValues.js';
|
|
|
32
32
|
import { assignFrom } from '../assignFrom.js';
|
|
33
33
|
import { processInferredAssignments } from '../inferredAssignments.js';
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Reserved keys in fromEachItem config — not treated as shorthand patterns.
|
|
37
|
+
*/
|
|
38
|
+
const RESERVED_KEYS = new Set(['toClone', 'withOptions', 'resolve', 'get', 'configs']);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Extract shorthand patterns from fromEachItem config (non-reserved keys → toClone).
|
|
42
|
+
*/
|
|
43
|
+
function extractToClone(config: any): Record<string, any> {
|
|
44
|
+
if (!config) return {};
|
|
45
|
+
const result: Record<string, any> = {};
|
|
46
|
+
for (const key of Object.keys(config)) {
|
|
47
|
+
if (!RESERVED_KEYS.has(key)) {
|
|
48
|
+
result[key] = config[key];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
|
|
35
54
|
/**
|
|
36
55
|
* State stored per list instance (keyed by start marker).
|
|
37
56
|
* Tracks the mapping of keys to their cloned DOM nodes.
|
|
@@ -74,22 +93,27 @@ export class ManageTemplateListHandler implements AssignFromHandler {
|
|
|
74
93
|
return; // Nothing to iterate
|
|
75
94
|
}
|
|
76
95
|
|
|
77
|
-
const fromEachItem = this.config
|
|
96
|
+
const { fromEachItem, fromHost: fromHostConfig, fromTarget: fromTargetConfig } = this.config;
|
|
78
97
|
const configs = fromEachItem?.configs; // Array form for multi-element templates
|
|
79
|
-
const assignToFragment = fromEachItem?.assignToFragment ?? {};
|
|
80
98
|
const withOptions = fromEachItem?.withOptions ?? {};
|
|
81
|
-
const perItemResolve = fromEachItem?.resolve ?? {};
|
|
82
|
-
const keyPath = perItemResolve
|
|
99
|
+
const perItemResolve = fromEachItem?.resolve ?? fromEachItem?.get ?? {};
|
|
100
|
+
const { key: keyPath } = perItemResolve; // e.g., '?.rank'
|
|
101
|
+
|
|
102
|
+
// Resolve toClone patterns: explicit `toClone` key, or shorthand (non-reserved keys)
|
|
103
|
+
const toClone = fromEachItem?.toClone ?? extractToClone(fromEachItem);
|
|
83
104
|
|
|
84
|
-
//
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
const sourceWithOptions = fromSource?.withOptions ?? {};
|
|
105
|
+
// fromHost config — assigns from options.from (host/VM) to each clone
|
|
106
|
+
const hostToClone = fromHostConfig ? (fromHostConfig.toClone ?? extractToClone(fromHostConfig)) : undefined;
|
|
107
|
+
const hostWithOptions = fromHostConfig?.withOptions ?? {};
|
|
88
108
|
|
|
89
|
-
//
|
|
90
|
-
const
|
|
109
|
+
// fromTarget config — assigns from the target element to each clone
|
|
110
|
+
const targetToClone = fromTargetConfig ? (fromTargetConfig.toClone ?? extractToClone(fromTargetConfig)) : undefined;
|
|
111
|
+
const targetWithOptions = fromTargetConfig?.withOptions ?? {};
|
|
112
|
+
|
|
113
|
+
// Detect fast path: no toClone patterns, just infer (only for non-configs mode)
|
|
114
|
+
const hasAssignPatterns = !configs && Object.keys(toClone).length > 0;
|
|
91
115
|
const inferredConfig = !configs && withOptions.infer;
|
|
92
|
-
const useFastPath = !configs && !hasAssignPatterns && inferredConfig && !
|
|
116
|
+
const useFastPath = !configs && !hasAssignPatterns && inferredConfig && !hostToClone && !targetToClone;
|
|
93
117
|
|
|
94
118
|
const name = markerName ?? getMarkerName(instantiate) ?? 'templateList';
|
|
95
119
|
|
|
@@ -159,7 +183,7 @@ export class ManageTemplateListHandler implements AssignFromHandler {
|
|
|
159
183
|
const len = Math.min(elements.length, configs.length);
|
|
160
184
|
for (let j = 0; j < len; j++) {
|
|
161
185
|
const cfg = configs[j];
|
|
162
|
-
assignFrom(elements[j], cfg.
|
|
186
|
+
assignFrom(elements[j], cfg.toClone ?? {}, { from: item, ...cfg.withOptions });
|
|
163
187
|
}
|
|
164
188
|
} else {
|
|
165
189
|
const rootEl = existingNodes.find(n => n instanceof Element) as Element | undefined;
|
|
@@ -167,10 +191,13 @@ export class ManageTemplateListHandler implements AssignFromHandler {
|
|
|
167
191
|
if (processInferred) {
|
|
168
192
|
processInferred(rootEl, item, inferredConfig === true ? { byItemprop: true } : inferredConfig);
|
|
169
193
|
} else {
|
|
170
|
-
assignFrom(rootEl,
|
|
194
|
+
assignFrom(rootEl, toClone, { from: item, ...withOptions });
|
|
195
|
+
}
|
|
196
|
+
if (hostToClone && options?.from) {
|
|
197
|
+
assignFrom(rootEl, hostToClone, { from: options.from, ...hostWithOptions });
|
|
171
198
|
}
|
|
172
|
-
if (
|
|
173
|
-
assignFrom(rootEl,
|
|
199
|
+
if (targetToClone) {
|
|
200
|
+
assignFrom(rootEl, targetToClone, { from: lhsTarget, ...targetWithOptions });
|
|
174
201
|
}
|
|
175
202
|
}
|
|
176
203
|
}
|
|
@@ -182,7 +209,7 @@ export class ManageTemplateListHandler implements AssignFromHandler {
|
|
|
182
209
|
// New item — clone template
|
|
183
210
|
let content: DocumentFragment;
|
|
184
211
|
if (instantiate instanceof HTMLTemplateElement) {
|
|
185
|
-
content = instantiate.content.cloneNode(true) as DocumentFragment;
|
|
212
|
+
content = (instantiate.remoteContent ||instantiate.content).cloneNode(true) as DocumentFragment;
|
|
186
213
|
} else if (instantiate instanceof DocumentFragment) {
|
|
187
214
|
content = instantiate.cloneNode(true) as DocumentFragment;
|
|
188
215
|
} else {
|
|
@@ -201,7 +228,7 @@ export class ManageTemplateListHandler implements AssignFromHandler {
|
|
|
201
228
|
const len = Math.min(elements.length, configs.length);
|
|
202
229
|
for (let j = 0; j < len; j++) {
|
|
203
230
|
const cfg = configs[j];
|
|
204
|
-
assignFrom(elements[j], cfg.
|
|
231
|
+
assignFrom(elements[j], cfg.toClone ?? {}, { from: item, ...cfg.withOptions });
|
|
205
232
|
}
|
|
206
233
|
} else {
|
|
207
234
|
const rootEl = clonedNodes.find(n => n instanceof Element) as Element | undefined;
|
|
@@ -212,11 +239,14 @@ export class ManageTemplateListHandler implements AssignFromHandler {
|
|
|
212
239
|
if (processInferred) {
|
|
213
240
|
processInferred(rootEl, item, inferredConfig === true ? { byItemprop: true } : inferredConfig);
|
|
214
241
|
} else {
|
|
215
|
-
assignFrom(rootEl,
|
|
242
|
+
assignFrom(rootEl, toClone, { from: item, ...withOptions });
|
|
216
243
|
}
|
|
217
244
|
|
|
218
|
-
if (
|
|
219
|
-
assignFrom(rootEl,
|
|
245
|
+
if (hostToClone && options?.from) {
|
|
246
|
+
assignFrom(rootEl, hostToClone, { from: options.from, ...hostWithOptions });
|
|
247
|
+
}
|
|
248
|
+
if (targetToClone) {
|
|
249
|
+
assignFrom(rootEl, targetToClone, { from: lhsTarget, ...targetWithOptions });
|
|
220
250
|
}
|
|
221
251
|
}
|
|
222
252
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { arr } from './arr.js';
|
|
2
|
+
/**
|
|
3
|
+
* Decrement "disabled" counter, remove when reaches 0
|
|
4
|
+
* @param el
|
|
5
|
+
* Optional select the attribute or attributes to remove or decrement
|
|
6
|
+
* @param attr
|
|
7
|
+
*/
|
|
8
|
+
export function nudge(el, attr = 'disabled') {
|
|
9
|
+
const attrs = arr(attr);
|
|
10
|
+
for (const attr of attrs) {
|
|
11
|
+
const da = el.getAttribute(attr);
|
|
12
|
+
if (da !== null) {
|
|
13
|
+
if (da.length === 0 || da === "1") {
|
|
14
|
+
el.removeAttribute(attr);
|
|
15
|
+
if (attr === 'disabled')
|
|
16
|
+
el.disabled = false;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
el.setAttribute(attr, (parseInt(da) - 1).toString());
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {arr} from './arr.js';
|
|
2
|
+
/**
|
|
3
|
+
* Decrement "disabled" counter, remove when reaches 0
|
|
4
|
+
* @param el
|
|
5
|
+
* Optional select the attribute or attributes to remove or decrement
|
|
6
|
+
* @param attr
|
|
7
|
+
*/
|
|
8
|
+
export function nudge(el: Element, attr: string | Array<string> = 'disabled') { //TODO: Share with be-observant
|
|
9
|
+
const attrs = arr(attr);
|
|
10
|
+
for(const attr of attrs){
|
|
11
|
+
const da = el.getAttribute(attr);
|
|
12
|
+
if (da !== null) {
|
|
13
|
+
if (da.length === 0 || da === "1") {
|
|
14
|
+
el.removeAttribute(attr);
|
|
15
|
+
if(attr === 'disabled') (<any>el).disabled = false;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
el.setAttribute(attr, (parseInt(da) - 1).toString());
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
}
|
package/index.js
CHANGED
|
@@ -14,4 +14,6 @@ export { assignFeatures, FeaturesRegistry, captureFeatureInitVals, PropertyBag,
|
|
|
14
14
|
export { installForwarding } from './installForwarding.js';
|
|
15
15
|
export { defineWithFeatures } from './defineWithFeatures.js';
|
|
16
16
|
export { resolveAndAssignFeatures } from './resolveAndAssignFeatures.js';
|
|
17
|
+
export { nudge } from './handlers/nudge.js';
|
|
18
|
+
export { arr } from './handlers/arr.js';
|
|
17
19
|
import './object-extension.js';
|
package/index.ts
CHANGED
|
@@ -14,5 +14,7 @@ export {assignFeatures, FeaturesRegistry, captureFeatureInitVals, PropertyBag, s
|
|
|
14
14
|
export {installForwarding} from './installForwarding.js';
|
|
15
15
|
export {defineWithFeatures} from './defineWithFeatures.js';
|
|
16
16
|
export {resolveAndAssignFeatures} from './resolveAndAssignFeatures.js';
|
|
17
|
+
export {nudge} from './handlers/nudge.js';
|
|
18
|
+
export {arr} from './handlers/arr.js';
|
|
17
19
|
export {} from './handlers/manageTemplateList.js';
|
|
18
20
|
import './object-extension.js';
|