@tamagui/static 1.0.0-beta.179 → 1.0.0-beta.207
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/cjs/extractor/createExtractor.js +117 -51
- package/dist/cjs/extractor/createExtractor.js.map +2 -2
- package/dist/cjs/extractor/loadTamagui.js.map +1 -1
- package/dist/esm/extractor/createExtractor.js +117 -51
- package/dist/esm/extractor/createExtractor.js.map +2 -2
- package/dist/esm/extractor/loadTamagui.js.map +1 -1
- package/dist/jsx/extractor/createExtractor.js +117 -51
- package/package.json +8 -8
- package/types/extractor/createExtractor.d.ts.map +1 -1
- package/types/extractor/loadTamagui.d.ts +2 -2
- package/types/extractor/loadTamagui.d.ts.map +1 -1
|
@@ -26,6 +26,15 @@ const UNTOUCHED_PROPS = {
|
|
|
26
26
|
style: true,
|
|
27
27
|
className: true
|
|
28
28
|
};
|
|
29
|
+
const INLINE_EXTRACTABLE = {
|
|
30
|
+
ref: "ref",
|
|
31
|
+
key: "key",
|
|
32
|
+
onPress: "onClick",
|
|
33
|
+
onHoverIn: "onMouseEnter",
|
|
34
|
+
onHoverOut: "onMouseLeave",
|
|
35
|
+
onPressIn: "onMouseDown",
|
|
36
|
+
onPressOut: "onMouseUp"
|
|
37
|
+
};
|
|
29
38
|
const isAttr = /* @__PURE__ */ __name((x) => x.type === "attr", "isAttr");
|
|
30
39
|
const validHooks = {
|
|
31
40
|
useMedia: true,
|
|
@@ -33,6 +42,10 @@ const validHooks = {
|
|
|
33
42
|
};
|
|
34
43
|
const createTernary = /* @__PURE__ */ __name((x) => x, "createTernary");
|
|
35
44
|
function createExtractor() {
|
|
45
|
+
if (!process.env.TAMAGUI_TARGET) {
|
|
46
|
+
console.log('\u26A0\uFE0F Please set process.env.TAMAGUI_TARGET to either "web" or "native"');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
36
49
|
const shouldAddDebugProp = !process.env.npm_package_dependencies_next && process.env.TAMAGUI_TARGET !== "native" && process.env.IDENTIFY_TAGS !== "false" && (process.env.NODE_ENV === "development" || process.env.DEBUG || process.env.IDENTIFY_TAGS);
|
|
37
50
|
require("esbuild-register/dist/node").register({
|
|
38
51
|
target: "es2019",
|
|
@@ -88,6 +101,7 @@ function createExtractor() {
|
|
|
88
101
|
return obj;
|
|
89
102
|
}, {});
|
|
90
103
|
let doesUseValidImport = false;
|
|
104
|
+
let hasImportedTheme = false;
|
|
91
105
|
for (const bodyPath of body) {
|
|
92
106
|
if (bodyPath.type !== "ImportDeclaration")
|
|
93
107
|
continue;
|
|
@@ -156,16 +170,17 @@ function createExtractor() {
|
|
|
156
170
|
}
|
|
157
171
|
const originalNodeName = node.name.name;
|
|
158
172
|
res.found++;
|
|
173
|
+
const filePath = sourcePath.replace(process.cwd(), ".");
|
|
174
|
+
const lineNumbers = node.loc ? node.loc.start.line + (node.loc.start.line !== node.loc.end.line ? `-${node.loc.end.line}` : "") : "";
|
|
175
|
+
const preName = componentName ? `${componentName}.` : "";
|
|
176
|
+
const tagId = `${preName}${node.name.name}@${filePath.replace("./", "")}:${lineNumbers}`;
|
|
159
177
|
if (shouldPrintDebug) {
|
|
160
178
|
console.log(`
|
|
161
|
-
<${originalNodeName}
|
|
179
|
+
<${originalNodeName} /> (${tagId})`);
|
|
162
180
|
}
|
|
163
|
-
const filePath = sourcePath.replace(process.cwd(), ".");
|
|
164
|
-
const lineNumbers = node.loc ? node.loc.start.line + (node.loc.start.line !== node.loc.end.line ? `-${node.loc.end.line}` : "") : "";
|
|
165
181
|
if (shouldAddDebugProp && !disableDebugAttr) {
|
|
166
|
-
const preName = componentName ? `${componentName}.` : "";
|
|
167
182
|
res.modified++;
|
|
168
|
-
node.attributes.unshift(t.jsxAttribute(t.jsxIdentifier("data-is"), t.stringLiteral(
|
|
183
|
+
node.attributes.unshift(t.jsxAttribute(t.jsxIdentifier("data-is"), t.stringLiteral(tagId)));
|
|
169
184
|
}
|
|
170
185
|
const shouldLog = !hasLogged;
|
|
171
186
|
if (shouldLog) {
|
|
@@ -202,6 +217,7 @@ function createExtractor() {
|
|
|
202
217
|
...staticConfig.inlineProps || []
|
|
203
218
|
]);
|
|
204
219
|
const deoptProps = /* @__PURE__ */ new Set([
|
|
220
|
+
"animation",
|
|
205
221
|
...props.deoptProps || [],
|
|
206
222
|
...staticConfig.deoptProps || []
|
|
207
223
|
]);
|
|
@@ -280,7 +296,7 @@ function createExtractor() {
|
|
|
280
296
|
}
|
|
281
297
|
let attrs = [];
|
|
282
298
|
let shouldDeopt = false;
|
|
283
|
-
|
|
299
|
+
const inlined = /* @__PURE__ */ new Map();
|
|
284
300
|
let hasSetOptimized = false;
|
|
285
301
|
attrs = traversePath.get("openingElement").get("attributes").flatMap((path) => {
|
|
286
302
|
try {
|
|
@@ -332,7 +348,7 @@ function createExtractor() {
|
|
|
332
348
|
if (shouldPrintDebug) {
|
|
333
349
|
console.log(" ! inlining, spread attr");
|
|
334
350
|
}
|
|
335
|
-
|
|
351
|
+
inlined.set(`${Math.random()}`, "spread");
|
|
336
352
|
return attr;
|
|
337
353
|
}
|
|
338
354
|
const name = attribute.name.name;
|
|
@@ -343,7 +359,7 @@ function createExtractor() {
|
|
|
343
359
|
return null;
|
|
344
360
|
}
|
|
345
361
|
if (inlineProps.has(name)) {
|
|
346
|
-
|
|
362
|
+
inlined.set(name, name);
|
|
347
363
|
if (shouldPrintDebug) {
|
|
348
364
|
console.log(" ! inlining, inline prop", name);
|
|
349
365
|
}
|
|
@@ -351,7 +367,7 @@ function createExtractor() {
|
|
|
351
367
|
}
|
|
352
368
|
if (deoptProps.has(name)) {
|
|
353
369
|
shouldDeopt = true;
|
|
354
|
-
|
|
370
|
+
inlined.set(name, name);
|
|
355
371
|
if (shouldPrintDebug) {
|
|
356
372
|
console.log(" ! inlining, deopted prop", name);
|
|
357
373
|
}
|
|
@@ -360,6 +376,10 @@ function createExtractor() {
|
|
|
360
376
|
if (UNTOUCHED_PROPS[name]) {
|
|
361
377
|
return attr;
|
|
362
378
|
}
|
|
379
|
+
if (INLINE_EXTRACTABLE[name]) {
|
|
380
|
+
inlined.set(name, INLINE_EXTRACTABLE[name]);
|
|
381
|
+
return attr;
|
|
382
|
+
}
|
|
363
383
|
if (name.startsWith("data-")) {
|
|
364
384
|
return attr;
|
|
365
385
|
}
|
|
@@ -397,7 +417,7 @@ function createExtractor() {
|
|
|
397
417
|
if (shouldPrintDebug) {
|
|
398
418
|
console.log(" ! inlining, ref", name);
|
|
399
419
|
}
|
|
400
|
-
|
|
420
|
+
inlined.set("ref", "ref");
|
|
401
421
|
return attr;
|
|
402
422
|
}
|
|
403
423
|
if (name === "tag") {
|
|
@@ -412,7 +432,7 @@ function createExtractor() {
|
|
|
412
432
|
if (shouldPrintDebug) {
|
|
413
433
|
console.log(` ! inlining, native disable extract: ${name} =`, value.value);
|
|
414
434
|
}
|
|
415
|
-
|
|
435
|
+
inlined.set(name, true);
|
|
416
436
|
return attr;
|
|
417
437
|
}
|
|
418
438
|
}
|
|
@@ -429,19 +449,49 @@ function createExtractor() {
|
|
|
429
449
|
keys = Object.keys(out);
|
|
430
450
|
}
|
|
431
451
|
}
|
|
452
|
+
let didInline = false;
|
|
432
453
|
const attributes = keys.map((key) => {
|
|
433
454
|
const val = out[key];
|
|
434
|
-
if (
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
455
|
+
if (key === "theme") {
|
|
456
|
+
inlined.set(key, val);
|
|
457
|
+
return attr;
|
|
458
|
+
}
|
|
459
|
+
if (isValidStyleKey(key)) {
|
|
460
|
+
return {
|
|
461
|
+
type: "style",
|
|
462
|
+
value: { [name]: styleValue },
|
|
463
|
+
name,
|
|
464
|
+
attr: path.node
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
if (validHTMLAttributes[key]) {
|
|
468
|
+
return attr;
|
|
469
|
+
}
|
|
470
|
+
if (shouldPrintDebug) {
|
|
471
|
+
console.log(" ! inlining, non-static", key);
|
|
472
|
+
}
|
|
473
|
+
didInline = true;
|
|
474
|
+
inlined.set(key, val);
|
|
475
|
+
return val;
|
|
476
|
+
});
|
|
477
|
+
if (didInline) {
|
|
478
|
+
if (shouldPrintDebug) {
|
|
479
|
+
console.log(" bailing flattening due to attributes", attributes);
|
|
480
|
+
}
|
|
481
|
+
return attr;
|
|
482
|
+
}
|
|
483
|
+
return attributes;
|
|
484
|
+
}
|
|
485
|
+
if (styleValue !== FAILED_EVAL) {
|
|
486
|
+
if (isValidStyleKey(name)) {
|
|
487
|
+
if (shouldPrintDebug) {
|
|
488
|
+
console.log(` style: ${name} =`, styleValue);
|
|
489
|
+
}
|
|
490
|
+
if (!(name in staticConfig.defaultProps)) {
|
|
491
|
+
if (!hasSetOptimized) {
|
|
492
|
+
res.optimized++;
|
|
493
|
+
hasSetOptimized = true;
|
|
443
494
|
}
|
|
444
|
-
inlinePropCount++;
|
|
445
495
|
}
|
|
446
496
|
return {
|
|
447
497
|
type: "style",
|
|
@@ -449,28 +499,10 @@ function createExtractor() {
|
|
|
449
499
|
name,
|
|
450
500
|
attr: path.node
|
|
451
501
|
};
|
|
452
|
-
}
|
|
453
|
-
|
|
502
|
+
} else {
|
|
503
|
+
inlined.set(name, true);
|
|
454
504
|
return attr;
|
|
455
505
|
}
|
|
456
|
-
return attributes;
|
|
457
|
-
}
|
|
458
|
-
if (styleValue !== FAILED_EVAL) {
|
|
459
|
-
if (shouldPrintDebug) {
|
|
460
|
-
console.log(` style: ${name} =`, styleValue);
|
|
461
|
-
}
|
|
462
|
-
if (!(name in staticConfig.defaultProps)) {
|
|
463
|
-
if (!hasSetOptimized) {
|
|
464
|
-
res.optimized++;
|
|
465
|
-
hasSetOptimized = true;
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
return {
|
|
469
|
-
type: "style",
|
|
470
|
-
value: { [name]: styleValue },
|
|
471
|
-
name,
|
|
472
|
-
attr: path.node
|
|
473
|
-
};
|
|
474
506
|
}
|
|
475
507
|
if (t.isBinaryExpression(value)) {
|
|
476
508
|
if (shouldPrintDebug) {
|
|
@@ -495,7 +527,7 @@ function createExtractor() {
|
|
|
495
527
|
if (shouldPrintDebug) {
|
|
496
528
|
console.log(` evalBinaryExpression cant extract`);
|
|
497
529
|
}
|
|
498
|
-
|
|
530
|
+
inlined.set(name, true);
|
|
499
531
|
return attr;
|
|
500
532
|
}
|
|
501
533
|
const staticConditional = getStaticConditional(value);
|
|
@@ -512,12 +544,9 @@ function createExtractor() {
|
|
|
512
544
|
}
|
|
513
545
|
return { type: "ternary", value: staticLogical };
|
|
514
546
|
}
|
|
547
|
+
inlined.set(name, true);
|
|
515
548
|
if (shouldPrintDebug) {
|
|
516
|
-
console.log(
|
|
517
|
-
}
|
|
518
|
-
inlinePropCount++;
|
|
519
|
-
if (shouldPrintDebug) {
|
|
520
|
-
console.log(` inlining ${name} = `, value);
|
|
549
|
+
console.log(` ! inline no match ${name}`, value);
|
|
521
550
|
}
|
|
522
551
|
return attr;
|
|
523
552
|
function addBinaryConditional(operator, staticExpr, cond) {
|
|
@@ -750,7 +779,28 @@ function createExtractor() {
|
|
|
750
779
|
};
|
|
751
780
|
const hasSpread = node.attributes.some((x) => t.isJSXSpreadAttribute(x));
|
|
752
781
|
const hasOnlyStringChildren = !hasSpread && (node.selfClosing || traversePath.node.children && traversePath.node.children.every((x) => x.type === "JSXText"));
|
|
753
|
-
const
|
|
782
|
+
const themeVal = inlined.get("theme");
|
|
783
|
+
inlined.delete("theme");
|
|
784
|
+
const allOtherPropsExtractable = [...inlined].every(([k, v]) => INLINE_EXTRACTABLE[k]);
|
|
785
|
+
const shouldWrapInnerTheme = allOtherPropsExtractable && !!(hasOnlyStringChildren && themeVal);
|
|
786
|
+
const canFlattenProps = inlined.size === 0 || shouldWrapInnerTheme || allOtherPropsExtractable;
|
|
787
|
+
let shouldFlatten = !shouldDeopt && canFlattenProps && !hasSpread && staticConfig.neverFlatten !== true && (staticConfig.neverFlatten === "jsx" ? hasOnlyStringChildren : true);
|
|
788
|
+
if (shouldFlatten && shouldWrapInnerTheme) {
|
|
789
|
+
if (typeof themeVal !== "string") {
|
|
790
|
+
console.warn("??");
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
if (shouldPrintDebug) {
|
|
794
|
+
console.log(" - wrapping theme", allOtherPropsExtractable, themeVal);
|
|
795
|
+
}
|
|
796
|
+
if (!hasImportedTheme) {
|
|
797
|
+
hasImportedTheme = true;
|
|
798
|
+
programPath.node.body.push(t.importDeclaration([t.importSpecifier(t.identifier("_TamaguiTheme"), t.identifier("Theme"))], t.stringLiteral("@tamagui/core")));
|
|
799
|
+
}
|
|
800
|
+
traversePath.replaceWith(t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier("_TamaguiTheme"), [
|
|
801
|
+
t.jsxAttribute(t.jsxIdentifier("name"), t.stringLiteral(`${themeVal}`))
|
|
802
|
+
]), t.jsxClosingElement(t.jsxIdentifier("_TamaguiTheme")), [traversePath.node]));
|
|
803
|
+
}
|
|
754
804
|
if (shouldFlatten && staticConfig.defaultProps) {
|
|
755
805
|
const defaultStyleAttrs = Object.keys(staticConfig.defaultProps).flatMap((key) => {
|
|
756
806
|
if (!isValidStyleKey(key)) {
|
|
@@ -805,8 +855,12 @@ function createExtractor() {
|
|
|
805
855
|
if (!cur) {
|
|
806
856
|
return acc;
|
|
807
857
|
}
|
|
808
|
-
if (
|
|
809
|
-
|
|
858
|
+
if (cur.type === "attr" && !t.isJSXSpreadAttribute(cur.value)) {
|
|
859
|
+
if (shouldFlatten) {
|
|
860
|
+
if (cur.value.name.name === "tag") {
|
|
861
|
+
return acc;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
810
864
|
}
|
|
811
865
|
if (cur.type !== "style") {
|
|
812
866
|
acc.push(cur);
|
|
@@ -982,6 +1036,18 @@ function createExtractor() {
|
|
|
982
1036
|
const existingStyleKeys = /* @__PURE__ */ new Set();
|
|
983
1037
|
for (let i = attrs.length - 1; i >= 0; i--) {
|
|
984
1038
|
const attr = attrs[i];
|
|
1039
|
+
if (shouldFlatten && canFlattenProps) {
|
|
1040
|
+
if (attr.type === "attr") {
|
|
1041
|
+
if (t.isJSXAttribute(attr.value)) {
|
|
1042
|
+
if (t.isJSXIdentifier(attr.value.name)) {
|
|
1043
|
+
const name = attr.value.name.name;
|
|
1044
|
+
if (INLINE_EXTRACTABLE[name]) {
|
|
1045
|
+
attr.value.name.name = INLINE_EXTRACTABLE[name];
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
985
1051
|
if (attr.type === "style") {
|
|
986
1052
|
for (const key in attr.value) {
|
|
987
1053
|
if (existingStyleKeys.has(key)) {
|
|
@@ -1006,7 +1072,7 @@ function createExtractor() {
|
|
|
1006
1072
|
}
|
|
1007
1073
|
}
|
|
1008
1074
|
if (shouldPrintDebug) {
|
|
1009
|
-
console.log(` \u274A\u274A inline props (${
|
|
1075
|
+
console.log(` \u274A\u274A inline props (${inlined.size}):`, shouldDeopt ? " deopted" : "", hasSpread ? " has spread" : "", staticConfig.neverFlatten ? "neverFlatten" : "");
|
|
1010
1076
|
console.log(" - attrs (end):\n", logLines(attrs.map(attrStr).join(", ")));
|
|
1011
1077
|
}
|
|
1012
1078
|
onExtractTag({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/static",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.207+3fd10ea6",
|
|
4
4
|
"source": "src/index.ts",
|
|
5
5
|
"typings": "types",
|
|
6
6
|
"main": "dist/cjs",
|
|
@@ -57,21 +57,21 @@
|
|
|
57
57
|
"@babel/parser": "^7.15.7",
|
|
58
58
|
"@babel/traverse": "^7.15.4",
|
|
59
59
|
"@expo/match-media": "^0.1.0",
|
|
60
|
-
"@tamagui/build": "^1.0.0-beta.
|
|
61
|
-
"@tamagui/core-node": "^1.0.0-beta.
|
|
62
|
-
"@tamagui/fake-react-native": "^1.0.0-beta.
|
|
63
|
-
"@tamagui/helpers": "^1.0.0-beta.
|
|
60
|
+
"@tamagui/build": "^1.0.0-beta.207+3fd10ea6",
|
|
61
|
+
"@tamagui/core-node": "^1.0.0-beta.207+3fd10ea6",
|
|
62
|
+
"@tamagui/fake-react-native": "^1.0.0-beta.207+3fd10ea6",
|
|
63
|
+
"@tamagui/helpers": "^1.0.0-beta.207+3fd10ea6",
|
|
64
64
|
"babel-literal-to-ast": "^2.1.0",
|
|
65
65
|
"esbuild": "^0.14.36",
|
|
66
66
|
"esbuild-register": "^3.1.2",
|
|
67
|
-
"find-cache-dir": "^3.3.
|
|
67
|
+
"find-cache-dir": "^3.3.2",
|
|
68
68
|
"fs-extra": "^9.1.0",
|
|
69
69
|
"invariant": "^2.2.4",
|
|
70
70
|
"lodash": "^4.17.21",
|
|
71
|
-
"tamagui": "^1.0.0-beta.
|
|
71
|
+
"tamagui": "^1.0.0-beta.207+3fd10ea6"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
74
|
"react-native-web": "*"
|
|
75
75
|
},
|
|
76
|
-
"gitHead": "
|
|
76
|
+
"gitHead": "3fd10ea6d026fac0339fbc1a501ee304f4985b05"
|
|
77
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createExtractor.d.ts","sourceRoot":"","sources":["../../src/extractor/createExtractor.ts"],"names":[],"mappings":"AAAA,OAAiB,EAAE,QAAQ,EAAW,MAAM,iBAAiB,CAAA;AAC7D,OAAO,KAAK,CAAC,MAAM,cAAc,CAAA;AACjC,OAAO,EAGL,qBAAqB,EAKtB,MAAM,oBAAoB,CAAA;AAK3B,OAAO,EAIL,mBAAmB,EAEpB,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"createExtractor.d.ts","sourceRoot":"","sources":["../../src/extractor/createExtractor.ts"],"names":[],"mappings":"AAAA,OAAiB,EAAE,QAAQ,EAAW,MAAM,iBAAiB,CAAA;AAC7D,OAAO,KAAK,CAAC,MAAM,cAAc,CAAA;AACjC,OAAO,EAGL,qBAAqB,EAKtB,MAAM,oBAAoB,CAAA;AAK3B,OAAO,EAIL,mBAAmB,EAEpB,MAAM,UAAU,CAAA;AAoCjB,oBAAY,SAAS,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAA;AAI1D,wBAAgB,eAAe;;;;;;;;;;;;;;wBA2Bb,SAAS,EAAE,OAAO,CAAC,GAAG,MAAM,kPAiBrC,mBAAmB;;;;;;EAu6C3B"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { TamaguiComponent, TamaguiInternalConfig } from '@tamagui/core';
|
|
2
2
|
export declare function loadTamagui(props: {
|
|
3
3
|
components: string[];
|
|
4
4
|
config: string;
|
|
5
5
|
}): {
|
|
6
|
-
components: Record<string,
|
|
6
|
+
components: Record<string, TamaguiComponent>;
|
|
7
7
|
tamaguiConfig: TamaguiInternalConfig;
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=loadTamagui.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadTamagui.d.ts","sourceRoot":"","sources":["../../src/extractor/loadTamagui.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"loadTamagui.d.ts","sourceRoot":"","sources":["../../src/extractor/loadTamagui.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AAK5E,wBAAgB,WAAW,CAAC,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG;IAC5E,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;IAC5C,aAAa,EAAE,qBAAqB,CAAA;CACrC,CA0EA"}
|