@dooboostore/simple-web-component 1.0.30 → 1.0.32
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 +220 -1
- package/dist/cjs/decorators/applyStyle.js +1 -1
- package/dist/cjs/decorators/applyStyle.js.map +2 -2
- package/dist/cjs/decorators/attribute.js +17 -1
- package/dist/cjs/decorators/attribute.js.map +2 -2
- package/dist/cjs/decorators/elementDefine.js +29 -12
- package/dist/cjs/decorators/elementDefine.js.map +3 -3
- package/dist/cjs/elements/SwcAppEngine.js +3 -3
- package/dist/cjs/elements/SwcAppEngine.js.map +2 -2
- package/dist/cjs/elements/SwcAppMixin.js +1 -8
- package/dist/cjs/elements/SwcAppMixin.js.map +2 -2
- package/dist/cjs/elements/SwcAsync.js +71 -78
- package/dist/cjs/elements/SwcAsync.js.map +2 -2
- package/dist/cjs/elements/SwcChoose.js +66 -81
- package/dist/cjs/elements/SwcChoose.js.map +2 -2
- package/dist/cjs/elements/SwcIf.js +52 -96
- package/dist/cjs/elements/SwcIf.js.map +2 -2
- package/dist/cjs/elements/SwcLoop.js +60 -103
- package/dist/cjs/elements/SwcLoop.js.map +2 -2
- package/dist/cjs/elements/SwcSubTemplates.js +0 -27
- package/dist/cjs/elements/SwcSubTemplates.js.map +2 -2
- package/dist/cjs/elements/register.js +314 -343
- package/dist/cjs/elements/register.js.map +2 -2
- package/dist/cjs/router/ElementRouter.js +1 -8
- package/dist/cjs/router/ElementRouter.js.map +2 -2
- package/dist/cjs/types.js.map +1 -1
- package/dist/cjs/utils/Utils.js +31 -24
- package/dist/cjs/utils/Utils.js.map +2 -2
- package/dist/esm/decorators/applyStyle.js +1 -1
- package/dist/esm/decorators/applyStyle.js.map +2 -2
- package/dist/esm/decorators/attribute.js +18 -2
- package/dist/esm/decorators/attribute.js.map +2 -2
- package/dist/esm/decorators/elementDefine.js +27 -10
- package/dist/esm/decorators/elementDefine.js.map +3 -3
- package/dist/esm/elements/SwcAppEngine.js +3 -3
- package/dist/esm/elements/SwcAppEngine.js.map +2 -2
- package/dist/esm/elements/SwcAppMixin.js +1 -8
- package/dist/esm/elements/SwcAppMixin.js.map +2 -2
- package/dist/esm/elements/SwcAsync.js +72 -60
- package/dist/esm/elements/SwcAsync.js.map +2 -2
- package/dist/esm/elements/SwcChoose.js +67 -63
- package/dist/esm/elements/SwcChoose.js.map +2 -2
- package/dist/esm/elements/SwcIf.js +53 -78
- package/dist/esm/elements/SwcIf.js.map +2 -2
- package/dist/esm/elements/SwcLoop.js +61 -85
- package/dist/esm/elements/SwcLoop.js.map +2 -2
- package/dist/esm/elements/SwcSubTemplates.js +0 -8
- package/dist/esm/elements/SwcSubTemplates.js.map +2 -2
- package/dist/esm/elements/register.js +246 -275
- package/dist/esm/elements/register.js.map +2 -2
- package/dist/esm/router/ElementRouter.js +1 -8
- package/dist/esm/router/ElementRouter.js.map +2 -2
- package/dist/esm/types.js.map +1 -1
- package/dist/esm/utils/Utils.js +31 -24
- package/dist/esm/utils/Utils.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js +2223 -2009
- package/dist/esm-bundle/dooboostore-simple-web-component.esm.js.map +4 -4
- package/dist/types/decorators/attribute.d.ts.map +1 -1
- package/dist/types/decorators/elementDefine.d.ts.map +1 -1
- package/dist/types/elements/SwcAppMixin.d.ts.map +1 -1
- package/dist/types/elements/SwcAsync.d.ts +1 -11
- package/dist/types/elements/SwcAsync.d.ts.map +1 -1
- package/dist/types/elements/SwcChoose.d.ts +1 -13
- package/dist/types/elements/SwcChoose.d.ts.map +1 -1
- package/dist/types/elements/SwcIf.d.ts +1 -13
- package/dist/types/elements/SwcIf.d.ts.map +1 -1
- package/dist/types/elements/SwcLoop.d.ts +1 -13
- package/dist/types/elements/SwcLoop.d.ts.map +1 -1
- package/dist/types/elements/SwcSubTemplates.d.ts +6 -6
- package/dist/types/elements/SwcSubTemplates.d.ts.map +1 -1
- package/dist/types/elements/register.d.ts.map +1 -1
- package/dist/types/router/ElementRouter.d.ts.map +1 -1
- package/dist/types/types.d.ts +11 -1
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/utils/Utils.d.ts +10 -0
- package/dist/types/utils/Utils.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js +2223 -2009
- package/dist/umd-bundle/dooboostore-simple-web-component.umd.js.map +4 -4
- package/package.json +3 -3
- package/src/decorators/applyStyle.ts +1 -1
- package/src/decorators/attribute.ts +35 -30
- package/src/decorators/elementDefine.ts +32 -10
- package/src/elements/SwcAppEngine.ts +3 -3
- package/src/elements/SwcAppMixin.ts +6 -27
- package/src/elements/SwcAsync.ts +75 -57
- package/src/elements/SwcChoose.ts +69 -77
- package/src/elements/SwcIf.ts +50 -75
- package/src/elements/SwcLoop.ts +56 -82
- package/src/elements/SwcSubTemplates.ts +6 -6
- package/src/elements/register.ts +234 -285
- package/src/router/ElementRouter.ts +1 -12
- package/src/types.ts +9 -2
- package/src/utils/Utils.ts +48 -37
package/src/elements/register.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { elementDefine } from '../decorators
|
|
1
|
+
import { elementDefine, attributeHost, changedAttributeHost } from '../decorators';
|
|
2
2
|
import { SwcAppMixin } from './SwcAppMixin';
|
|
3
3
|
import { SwcUtils } from '../utils/Utils';
|
|
4
|
-
import { FunctionUtils } from '@dooboostore/core';
|
|
5
|
-
import {
|
|
4
|
+
import { FunctionUtils,ActionExpression } from '@dooboostore/core';
|
|
5
|
+
import { ConvertUtils } from '@dooboostore/core-web';
|
|
6
6
|
|
|
7
7
|
type Constructor<T> = new (...args: any[]) => T;
|
|
8
8
|
|
|
@@ -148,99 +148,74 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
148
148
|
|
|
149
149
|
@elementDefine('swc-if', { extends: 'template', window: w })
|
|
150
150
|
class SwcIf extends HTMLTemplateElement {
|
|
151
|
-
|
|
151
|
+
@attributeHost('value')
|
|
152
|
+
_value: any;
|
|
153
|
+
|
|
154
|
+
@attributeHost('replace-wrap')
|
|
155
|
+
_replaceWrap: string | null;
|
|
156
|
+
|
|
152
157
|
private _nodes: Node[] = [];
|
|
153
158
|
|
|
154
159
|
get value(): boolean {
|
|
155
160
|
return this._value;
|
|
156
161
|
}
|
|
162
|
+
|
|
157
163
|
set value(nv: any) {
|
|
158
|
-
this._value =
|
|
159
|
-
this.
|
|
164
|
+
// this._value = nv;
|
|
165
|
+
this.refresh(nv);
|
|
160
166
|
}
|
|
161
167
|
|
|
162
|
-
private
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
168
|
+
private replaceExpressions(html: string, groupArgs: any, context: any, wrap?: string | null): string {
|
|
169
|
+
const config = wrap ? { wrapExpression: wrap } : undefined;
|
|
170
|
+
const ae = new ActionExpression(html, config);
|
|
171
|
+
const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';
|
|
166
172
|
const win = this.ownerDocument?.defaultView || window;
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
|
|
174
|
+
// @ts-ignore
|
|
175
|
+
for (const expr of ae.getExpressions(filterOptions)) {
|
|
176
|
+
try {
|
|
177
|
+
const value = FunctionUtils.executeReturn({
|
|
178
|
+
script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),
|
|
179
|
+
context,
|
|
180
|
+
args: groupArgs
|
|
181
|
+
});
|
|
182
|
+
ae.replace(expr, String(value));
|
|
183
|
+
} catch (e) {
|
|
184
|
+
console.error(`[SWC] Failed to execute ${expr.original}:`, e);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return ae.getUnprocessedTemplate();
|
|
176
188
|
}
|
|
177
189
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
FunctionUtils.execute({ script, context: this, args });
|
|
190
|
+
@changedAttributeHost('value')
|
|
191
|
+
private setValue(valueAttr?: string | null) {
|
|
192
|
+
this.refresh();
|
|
182
193
|
}
|
|
183
194
|
|
|
184
|
-
@changedAttributeHost('
|
|
185
|
-
private
|
|
186
|
-
|
|
187
|
-
if (!script) {
|
|
188
|
-
this.value = false;
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
const win = this.ownerDocument?.defaultView || window;
|
|
192
|
-
const res = FunctionUtils.executeReturn({
|
|
193
|
-
script,
|
|
194
|
-
context: this,
|
|
195
|
-
args: SwcUtils.getHelperAndHostSet(win, this)
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
if (res instanceof Promise) {
|
|
199
|
-
res.then(v => (this.value = v)).catch(() => (this.value = false));
|
|
200
|
-
} else {
|
|
201
|
-
this.value = res;
|
|
202
|
-
}
|
|
195
|
+
@changedAttributeHost('replace-wrap')
|
|
196
|
+
private setReplaceWrap(replaceWrapAttr?: string | null) {
|
|
197
|
+
this.refresh();
|
|
203
198
|
}
|
|
204
199
|
|
|
205
|
-
|
|
200
|
+
refresh(value = this._value) {
|
|
206
201
|
this.cleanup();
|
|
207
|
-
const portal = this.
|
|
208
|
-
if (!portal) return;
|
|
202
|
+
const portal = this.parentElement;
|
|
203
|
+
if (!portal || !value) return;
|
|
209
204
|
|
|
210
205
|
const win = this.ownerDocument?.defaultView || window;
|
|
211
206
|
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
212
207
|
|
|
213
|
-
let
|
|
214
|
-
|
|
215
|
-
targetTpl = this;
|
|
216
|
-
} else {
|
|
217
|
-
targetTpl = this.content.querySelector('template[is="swc-default"]') as HTMLTemplateElement;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (targetTpl) {
|
|
221
|
-
const clone = targetTpl.content.cloneNode(true) as DocumentFragment;
|
|
222
|
-
// If it's the host template, remove sub-templates from clone
|
|
223
|
-
if (targetTpl === this) {
|
|
224
|
-
clone.querySelectorAll('template[is^="swc-"]').forEach(t => t.remove());
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
this._nodes = Array.from(clone.childNodes);
|
|
228
|
-
const elements = this._nodes.filter(n => n.nodeType === 1) as HTMLElement[];
|
|
229
|
-
const groupArgs = { ...helperSet, $value: this._value, $nodes: this._nodes, $elements: elements, $firstElement: elements[0] };
|
|
208
|
+
let htmlString = this.innerHTML;
|
|
209
|
+
const groupArgs = { ...helperSet, $value: value };
|
|
230
210
|
|
|
231
|
-
|
|
232
|
-
if (node instanceof HTMLElement) (node as any).__swc_host = this;
|
|
233
|
-
this._executeCloneCallback('on-clone-node', { ...groupArgs, $node: node, $nodeIndex: nodeIdx, $isElement: node.nodeType === 1 });
|
|
234
|
-
});
|
|
211
|
+
htmlString = this.replaceExpressions(htmlString, groupArgs, this, this._replaceWrap);
|
|
235
212
|
|
|
236
|
-
|
|
213
|
+
const result = this.ownerDocument?.createElement('template') || document.createElement('template');
|
|
214
|
+
result.innerHTML = htmlString;
|
|
215
|
+
const processedFragment = result.content;
|
|
237
216
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
} else {
|
|
241
|
-
portal.appendChild(clone);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
217
|
+
this._nodes = Array.from(processedFragment.childNodes);
|
|
218
|
+
portal.insertBefore(processedFragment, this.nextSibling);
|
|
244
219
|
}
|
|
245
220
|
|
|
246
221
|
private cleanup() {
|
|
@@ -248,9 +223,6 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
248
223
|
this._nodes = [];
|
|
249
224
|
}
|
|
250
225
|
|
|
251
|
-
connectedCallback() {
|
|
252
|
-
this.refreshValue();
|
|
253
|
-
}
|
|
254
226
|
disconnectedCallback() {
|
|
255
227
|
this.cleanup();
|
|
256
228
|
}
|
|
@@ -258,184 +230,173 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
258
230
|
|
|
259
231
|
@elementDefine('swc-loop', { extends: 'template', window: w })
|
|
260
232
|
class SwcLoop extends HTMLTemplateElement {
|
|
261
|
-
|
|
233
|
+
@attributeHost('value')
|
|
234
|
+
_value: any[];
|
|
235
|
+
|
|
236
|
+
@attributeHost('replace-wrap')
|
|
237
|
+
_replaceWrap: string | null;
|
|
238
|
+
|
|
262
239
|
private _nodeGroups: Node[][] = [];
|
|
263
240
|
|
|
264
241
|
get value(): any[] {
|
|
265
242
|
return this._value;
|
|
266
243
|
}
|
|
267
244
|
set value(nv: any[]) {
|
|
268
|
-
this._value = Array.isArray(nv) ? [...nv] : [];
|
|
269
|
-
this.
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
private _resolvePortal(): Element | null {
|
|
273
|
-
const portalScript = this.getAttribute('on-get-portal');
|
|
274
|
-
if (!portalScript) return this.parentElement;
|
|
275
|
-
|
|
276
|
-
const win = this.ownerDocument?.defaultView || window;
|
|
277
|
-
const res = FunctionUtils.executeReturn({
|
|
278
|
-
script: portalScript,
|
|
279
|
-
context: this,
|
|
280
|
-
args: SwcUtils.getHelperAndHostSet(win, this)
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
if (res instanceof HTMLElement) return res;
|
|
284
|
-
if (typeof res === 'string') return win.document.querySelector(res);
|
|
285
|
-
return this.parentElement;
|
|
245
|
+
// this._value = Array.isArray(nv) ? [...nv] : [];
|
|
246
|
+
this.refresh(nv);
|
|
286
247
|
}
|
|
287
248
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
FunctionUtils.execute({ script, context: this, args });
|
|
249
|
+
@changedAttributeHost('value')
|
|
250
|
+
private setValue() {
|
|
251
|
+
this.refresh();
|
|
292
252
|
}
|
|
293
253
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
this.
|
|
254
|
+
@changedAttributeHost('replace-wrap')
|
|
255
|
+
private setReplaceWrap() {
|
|
256
|
+
this.refresh();
|
|
297
257
|
}
|
|
298
258
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
this.value = [];
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
259
|
+
private replaceExpressions(html: string, groupArgs: any, context: any, wrap?: string | null): string {
|
|
260
|
+
const config = wrap ? { wrapExpression: wrap } : undefined;
|
|
261
|
+
const ae = new ActionExpression(html, config);
|
|
262
|
+
const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';
|
|
306
263
|
const win = this.ownerDocument?.defaultView || window;
|
|
307
|
-
const res = FunctionUtils.executeReturn({
|
|
308
|
-
script,
|
|
309
|
-
context: this,
|
|
310
|
-
args: SwcUtils.getHelperAndHostSet(win, this)
|
|
311
|
-
});
|
|
312
264
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
265
|
+
// @ts-ignore
|
|
266
|
+
for (const expr of ae.getExpressions(filterOptions)) {
|
|
267
|
+
try {
|
|
268
|
+
const value = FunctionUtils.executeReturn({
|
|
269
|
+
script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),
|
|
270
|
+
context,
|
|
271
|
+
args: groupArgs
|
|
272
|
+
});
|
|
273
|
+
ae.replace(expr, String(value));
|
|
274
|
+
} catch (e) {
|
|
275
|
+
console.error(`[SWC] Failed to execute ${expr.original}:`, e);
|
|
276
|
+
}
|
|
317
277
|
}
|
|
278
|
+
return ae.getUnprocessedTemplate();
|
|
318
279
|
}
|
|
319
280
|
|
|
320
|
-
|
|
321
|
-
this.
|
|
322
|
-
|
|
281
|
+
refresh(value = this._value) {
|
|
282
|
+
this.cleanup();
|
|
283
|
+
if (value?.length<=0) return;
|
|
284
|
+
const portal = this.parentElement;
|
|
323
285
|
if (!portal) return;
|
|
324
286
|
|
|
325
287
|
const win = this.ownerDocument?.defaultView || window;
|
|
326
288
|
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
327
289
|
const fragment = win.document.createDocumentFragment();
|
|
328
290
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
const clone = defaultTpl.content.cloneNode(true);
|
|
333
|
-
const nodes = Array.from(clone.childNodes);
|
|
334
|
-
this._nodeGroups.push(nodes);
|
|
335
|
-
fragment.appendChild(clone);
|
|
336
|
-
}
|
|
337
|
-
} else {
|
|
338
|
-
this._value.forEach((item, index) => {
|
|
339
|
-
const clone = this.content.cloneNode(true) as DocumentFragment;
|
|
340
|
-
// Filter out sub-templates
|
|
341
|
-
const subTemplates = clone.querySelectorAll('template[is^="swc-"]');
|
|
342
|
-
subTemplates.forEach(t => t.remove());
|
|
343
|
-
|
|
344
|
-
const nodes = Array.from(clone.childNodes);
|
|
345
|
-
const elements = nodes.filter(n => n.nodeType === 1) as HTMLElement[];
|
|
291
|
+
value.forEach((item, index) => {
|
|
292
|
+
let htmlString = this.innerHTML;
|
|
293
|
+
const groupArgs = { ...helperSet, $item: item, $index: index, $value: this._value };
|
|
346
294
|
|
|
347
|
-
|
|
295
|
+
htmlString = this.replaceExpressions(htmlString, groupArgs, this, this._replaceWrap);
|
|
348
296
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
this._executeCloneCallback('on-clone-node', { ...groupArgs, $node: node, $nodeIndex: nodeIdx, $isElement: node.nodeType === 1 });
|
|
352
|
-
});
|
|
297
|
+
const temp = this.ownerDocument?.createElement('template') || document.createElement('template');
|
|
298
|
+
temp.innerHTML = htmlString;
|
|
353
299
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
}
|
|
300
|
+
const content = temp.content;
|
|
301
|
+
const nodes = Array.from(content.childNodes);
|
|
302
|
+
this._nodeGroups.push(nodes);
|
|
303
|
+
fragment.appendChild(content);
|
|
304
|
+
});
|
|
359
305
|
|
|
360
|
-
|
|
361
|
-
portal.insertBefore(fragment, this.nextSibling);
|
|
362
|
-
} else {
|
|
363
|
-
portal.appendChild(fragment);
|
|
364
|
-
}
|
|
306
|
+
portal.insertBefore(fragment, this.nextSibling);
|
|
365
307
|
}
|
|
366
308
|
|
|
367
|
-
|
|
368
|
-
this.
|
|
309
|
+
private cleanup() {
|
|
310
|
+
this._nodeGroups.forEach(nodes => nodes.forEach(n => n.parentElement?.removeChild(n)));
|
|
311
|
+
this._nodeGroups = [];
|
|
369
312
|
}
|
|
313
|
+
|
|
370
314
|
disconnectedCallback() {
|
|
371
|
-
this.
|
|
315
|
+
this.cleanup();
|
|
372
316
|
}
|
|
373
317
|
}
|
|
374
318
|
|
|
375
319
|
@elementDefine('swc-choose', { extends: 'template', window: w })
|
|
376
320
|
class SwcChoose extends HTMLTemplateElement {
|
|
321
|
+
@attributeHost('value')
|
|
322
|
+
_value: any;
|
|
323
|
+
|
|
324
|
+
@attributeHost('replace-wrap')
|
|
325
|
+
_replaceWrap: string | null;
|
|
326
|
+
|
|
377
327
|
private _nodes: Node[] = [];
|
|
378
|
-
private _value: any = null;
|
|
379
328
|
private _previousTemplate: HTMLTemplateElement | null = null;
|
|
380
329
|
|
|
381
330
|
get value(): any {
|
|
382
331
|
return this._value;
|
|
383
332
|
}
|
|
333
|
+
|
|
384
334
|
set value(nv: any) {
|
|
385
|
-
this.
|
|
386
|
-
this.render();
|
|
335
|
+
this.refresh(nv);
|
|
387
336
|
}
|
|
388
337
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
FunctionUtils.execute({ script, context: this, args });
|
|
338
|
+
@changedAttributeHost('value')
|
|
339
|
+
private setValue() {
|
|
340
|
+
this.refresh();
|
|
393
341
|
}
|
|
394
342
|
|
|
395
|
-
@changedAttributeHost('
|
|
396
|
-
private
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
this.value = null;
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
343
|
+
@changedAttributeHost('replace-wrap')
|
|
344
|
+
private setReplaceWrap(replaceWrapAttr?: string | null) {
|
|
345
|
+
this.refresh();
|
|
346
|
+
}
|
|
402
347
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
348
|
+
private replaceExpressions(html: string, groupArgs: any, context: any, wrap?: string | null): string {
|
|
349
|
+
const config = wrap ? { wrapExpression: wrap } : undefined;
|
|
350
|
+
const ae = new ActionExpression(html, config);
|
|
351
|
+
const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';
|
|
352
|
+
const win = this.ownerDocument?.defaultView || window;
|
|
353
|
+
|
|
354
|
+
// @ts-ignore
|
|
355
|
+
for (const expr of ae.getExpressions(filterOptions)) {
|
|
356
|
+
try {
|
|
357
|
+
const value = FunctionUtils.executeReturn({
|
|
358
|
+
script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),
|
|
359
|
+
context,
|
|
360
|
+
args: groupArgs
|
|
361
|
+
});
|
|
362
|
+
ae.replace(expr, String(value));
|
|
363
|
+
} catch (e) {
|
|
364
|
+
console.error(`[SWC] Failed to execute ${expr.original}:`, e);
|
|
365
|
+
}
|
|
412
366
|
}
|
|
367
|
+
return ae.getUnprocessedTemplate();
|
|
413
368
|
}
|
|
414
369
|
|
|
415
|
-
|
|
370
|
+
refresh(value = this._value) {
|
|
371
|
+
const portal = this.parentElement;
|
|
372
|
+
if (!portal) return;
|
|
373
|
+
|
|
416
374
|
const win = this.ownerDocument?.defaultView || window;
|
|
417
375
|
const helperSet = SwcUtils.getHelperAndHostSet(win, this);
|
|
376
|
+
const groupArgs = { ...helperSet, $value: value };
|
|
377
|
+
|
|
418
378
|
const templates = Array.from(this.content.querySelectorAll('template'));
|
|
419
379
|
let selected: HTMLTemplateElement | null = null;
|
|
420
380
|
|
|
421
381
|
for (const t of templates) {
|
|
422
382
|
if (t.getAttribute('is') === 'swc-when') {
|
|
383
|
+
const attrVal = t.getAttribute('value') || '';
|
|
423
384
|
let matches = false;
|
|
424
|
-
const value = t.getAttribute('value') || '';
|
|
425
385
|
|
|
426
|
-
//
|
|
427
|
-
|
|
428
|
-
|
|
386
|
+
// Use ActionExpression to parse and extract script from value attribute
|
|
387
|
+
const ae = new ActionExpression(attrVal);
|
|
388
|
+
const expr = ae.getFirstExpression('replace');
|
|
389
|
+
|
|
390
|
+
if (expr) {
|
|
391
|
+
const decodedScript = ConvertUtils.decodeHtmlEntity(expr.script, win.document);
|
|
429
392
|
const result = FunctionUtils.executeReturn({
|
|
430
|
-
script,
|
|
393
|
+
script: decodedScript,
|
|
431
394
|
context: t,
|
|
432
|
-
args:
|
|
395
|
+
args: groupArgs
|
|
433
396
|
});
|
|
434
|
-
|
|
435
|
-
matches = result === true;
|
|
397
|
+
matches = !!result;
|
|
436
398
|
} else {
|
|
437
|
-
|
|
438
|
-
matches = String(value) === String(this._value);
|
|
399
|
+
matches = String(attrVal) === String(value);
|
|
439
400
|
}
|
|
440
401
|
|
|
441
402
|
if (matches) {
|
|
@@ -447,11 +408,12 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
447
408
|
|
|
448
409
|
const target = selected || (this.content.querySelector('template[is="swc-otherwise"]') as HTMLTemplateElement);
|
|
449
410
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
const
|
|
453
|
-
const
|
|
454
|
-
|
|
411
|
+
const skipValue = target?.getAttribute?.('skip-if-same');
|
|
412
|
+
const skipValue2 = this._previousTemplate?.getAttribute?.('skip-if-same');
|
|
413
|
+
const hasSkipIfSame = target?.hasAttribute?.('skip-if-same');
|
|
414
|
+
const isSame = this._previousTemplate === target;
|
|
415
|
+
// console.log('---rrrr---', this._previousTemplate, target, hasSkipIfSame, isSame, skipValue, skipValue2);
|
|
416
|
+
if (hasSkipIfSame && isSame) {
|
|
455
417
|
return;
|
|
456
418
|
}
|
|
457
419
|
|
|
@@ -459,41 +421,15 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
459
421
|
this._previousTemplate = target;
|
|
460
422
|
|
|
461
423
|
if (target) {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
const elements = this._nodes.filter(n => n.nodeType === 1) as HTMLElement[];
|
|
465
|
-
const groupArgs = { ...helperSet, $value: this._value, $nodes: this._nodes, $elements: elements, $firstElement: elements[0] };
|
|
466
|
-
|
|
467
|
-
// 복제된 최상위 요소들은 SwcChoose의 직접 자식이 될 것이므로 __swc_host 설정 안 함
|
|
468
|
-
this._nodes.forEach((n, nodeIdx) => {
|
|
469
|
-
// if (n instanceof HTMLElement) (n as any).__swc_host = this; // 제거: 부모 체인 유지
|
|
470
|
-
this._executeCloneCallback('on-clone-node', { ...groupArgs, $node: n, $nodeIndex: nodeIdx, $isElement: n.nodeType === 1 });
|
|
471
|
-
|
|
472
|
-
// Attribute {{ }} 치환 - HTML string 차원에서 동적 치환
|
|
473
|
-
if (n instanceof HTMLElement) {
|
|
474
|
-
Array.from(n.attributes).forEach(attr => {
|
|
475
|
-
const value = attr.value || '';
|
|
476
|
-
if (value.startsWith('{{') && value.endsWith('}}')) {
|
|
477
|
-
const script = value.slice(2, -2).trim();
|
|
478
|
-
const result = FunctionUtils.executeReturn({
|
|
479
|
-
script,
|
|
480
|
-
context: n,
|
|
481
|
-
args: { ...groupArgs, $value: this._value }
|
|
482
|
-
});
|
|
483
|
-
n.setAttribute(attr.name, String(result));
|
|
484
|
-
}
|
|
485
|
-
});
|
|
486
|
-
}
|
|
487
|
-
});
|
|
424
|
+
let htmlString = target.innerHTML;
|
|
425
|
+
htmlString = this.replaceExpressions(htmlString, groupArgs, this, this._replaceWrap);
|
|
488
426
|
|
|
489
|
-
this.
|
|
427
|
+
const result = this.ownerDocument?.createElement('template') || document.createElement('template');
|
|
428
|
+
result.innerHTML = htmlString;
|
|
429
|
+
const processedFragment = result.content;
|
|
490
430
|
|
|
491
|
-
this.
|
|
492
|
-
|
|
493
|
-
// portal.insertBefore(clone, this.nextSibling);
|
|
494
|
-
// } else {
|
|
495
|
-
// portal.appendChild(clone);
|
|
496
|
-
// }
|
|
431
|
+
this._nodes = Array.from(processedFragment.childNodes);
|
|
432
|
+
portal.insertBefore(processedFragment, this.nextSibling);
|
|
497
433
|
}
|
|
498
434
|
}
|
|
499
435
|
|
|
@@ -502,9 +438,6 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
502
438
|
this._nodes = [];
|
|
503
439
|
}
|
|
504
440
|
|
|
505
|
-
connectedCallback() {
|
|
506
|
-
this.refresh();
|
|
507
|
-
}
|
|
508
441
|
disconnectedCallback() {
|
|
509
442
|
this.cleanup();
|
|
510
443
|
}
|
|
@@ -512,58 +445,84 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
512
445
|
|
|
513
446
|
@elementDefine('swc-async', { extends: 'template', window: w })
|
|
514
447
|
class SwcAsync extends HTMLTemplateElement {
|
|
515
|
-
|
|
516
|
-
|
|
448
|
+
@attributeHost('value')
|
|
449
|
+
_value: any;
|
|
517
450
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
if (!portalScript) return this.parentElement;
|
|
451
|
+
@attributeHost('replace-wrap')
|
|
452
|
+
_replaceWrap: string | null;
|
|
521
453
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
});
|
|
454
|
+
resultValue?: any;
|
|
455
|
+
|
|
456
|
+
get value(): boolean {
|
|
457
|
+
return this._value;
|
|
458
|
+
}
|
|
528
459
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
return this.parentElement;
|
|
460
|
+
set value(nv: any) {
|
|
461
|
+
this.executeAsync(nv);
|
|
532
462
|
}
|
|
533
463
|
|
|
534
|
-
private
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
464
|
+
private _nodes: Node[] = [];
|
|
465
|
+
|
|
466
|
+
@changedAttributeHost('value')
|
|
467
|
+
private setValue(valueAttr?: string | null) {
|
|
468
|
+
this.executeAsync(this._value);
|
|
538
469
|
}
|
|
539
470
|
|
|
540
|
-
@changedAttributeHost('
|
|
541
|
-
private
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
471
|
+
@changedAttributeHost('replace-wrap')
|
|
472
|
+
private setReplaceWrap() {
|
|
473
|
+
this.executeAsync(this._value);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
private executeAsync(result: any = this._value) {
|
|
477
|
+
if (result === undefined || result === null) {
|
|
478
|
+
this.refresh('default');
|
|
545
479
|
return;
|
|
546
480
|
}
|
|
547
|
-
const win = this.ownerDocument?.defaultView || window;
|
|
548
|
-
const result = FunctionUtils.executeReturn({ script, context: this, args: SwcUtils.getHelperAndHostSet(win, this) });
|
|
549
481
|
|
|
550
482
|
if (result instanceof Promise) {
|
|
551
|
-
this.
|
|
483
|
+
this.refresh('loading');
|
|
552
484
|
result
|
|
553
485
|
.then(v => {
|
|
554
|
-
this.
|
|
555
|
-
this.
|
|
486
|
+
this.resultValue = v;
|
|
487
|
+
this.refresh('success');
|
|
556
488
|
})
|
|
557
|
-
.catch(e =>
|
|
489
|
+
.catch(e => {
|
|
490
|
+
console.error('[SWC-ASYNC] Promise rejected:', e);
|
|
491
|
+
this.resultValue = e;
|
|
492
|
+
this.refresh('error');
|
|
493
|
+
});
|
|
558
494
|
} else {
|
|
559
|
-
this.
|
|
560
|
-
this.
|
|
495
|
+
this.resultValue = result;
|
|
496
|
+
this.refresh('success');
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
private replaceExpressions(html: string, groupArgs: any, context: any, wrap?: string | null): string {
|
|
501
|
+
const config = wrap ? { wrapExpression: wrap } : undefined;
|
|
502
|
+
const ae = new ActionExpression(html, config);
|
|
503
|
+
const filterOptions = wrap ? { type: 'replace' as const, wrap } : 'replace';
|
|
504
|
+
const win = this.ownerDocument?.defaultView || window;
|
|
505
|
+
|
|
506
|
+
// @ts-ignore
|
|
507
|
+
for (const expr of ae.getExpressions(filterOptions)) {
|
|
508
|
+
try {
|
|
509
|
+
const value = FunctionUtils.executeReturn({
|
|
510
|
+
script: ConvertUtils.decodeHtmlEntity(expr.script, win.document),
|
|
511
|
+
context,
|
|
512
|
+
args: groupArgs
|
|
513
|
+
});
|
|
514
|
+
ae.replace(expr, String(value));
|
|
515
|
+
} catch (e) {
|
|
516
|
+
console.error(`[SWC] Failed to execute ${expr.original}:`, e);
|
|
517
|
+
}
|
|
561
518
|
}
|
|
519
|
+
return ae.getUnprocessedTemplate();
|
|
562
520
|
}
|
|
563
521
|
|
|
564
|
-
|
|
522
|
+
refresh(state: string = 'default') {
|
|
523
|
+
console.log('rrrrrrrrrrrrrrrrr', state);
|
|
565
524
|
this.cleanup();
|
|
566
|
-
const portal = this.
|
|
525
|
+
const portal = this.parentElement;
|
|
567
526
|
if (!portal) return;
|
|
568
527
|
|
|
569
528
|
const win = this.ownerDocument?.defaultView || window;
|
|
@@ -571,23 +530,17 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
571
530
|
|
|
572
531
|
const t = this.content.querySelector(`template[is="swc-${state}"]`) as HTMLTemplateElement;
|
|
573
532
|
if (t) {
|
|
574
|
-
|
|
575
|
-
this.
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
this.
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
if (portal === this.parentElement) {
|
|
587
|
-
portal.insertBefore(clone, this.nextSibling);
|
|
588
|
-
} else {
|
|
589
|
-
portal.appendChild(clone);
|
|
590
|
-
}
|
|
533
|
+
let htmlString = t.innerHTML;
|
|
534
|
+
const groupArgs = { ...helperSet, $value: this._value, $state: state };
|
|
535
|
+
|
|
536
|
+
htmlString = this.replaceExpressions(htmlString, groupArgs, this, this._replaceWrap);
|
|
537
|
+
|
|
538
|
+
const temp = this.ownerDocument?.createElement('template') || document.createElement('template');
|
|
539
|
+
temp.innerHTML = htmlString;
|
|
540
|
+
const content = temp.content;
|
|
541
|
+
|
|
542
|
+
this._nodes = Array.from(content.childNodes);
|
|
543
|
+
portal.insertBefore(content, this.nextSibling);
|
|
591
544
|
}
|
|
592
545
|
}
|
|
593
546
|
|
|
@@ -596,10 +549,6 @@ export const registerAllElements = (w: any): Record<string, Constructor<HTMLElem
|
|
|
596
549
|
this._nodes = [];
|
|
597
550
|
}
|
|
598
551
|
|
|
599
|
-
connectedCallback() {
|
|
600
|
-
console.log('[SwcAsync] connectedCallback called');
|
|
601
|
-
this.refresh();
|
|
602
|
-
}
|
|
603
552
|
disconnectedCallback() {
|
|
604
553
|
this.cleanup();
|
|
605
554
|
}
|