@jbpark/live-editor 4.6.0 → 4.6.1
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/dnd/index.d.ts +1 -1
- package/dist/dnd/index.js +1 -1
- package/dist/{dnd-UoJILA75.js → dnd-V8NAxd_R.js} +8 -9
- package/dist/dnd-V8NAxd_R.js.map +1 -0
- package/dist/document-CHO215iP.js +33992 -0
- package/dist/document-CHO215iP.js.map +1 -0
- package/dist/{document-Ct4jW78J.d.ts → document-DqRSCtsx.d.ts} +496 -435
- package/dist/index-C_PfR4X9.d.ts +734 -0
- package/dist/{index-C69Lv-jR.d.ts → index-CiWB0zFb.d.ts} +3 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/{items-B6OXxcLG.js → items-BXXtMUNI.js} +148 -150
- package/dist/items-BXXtMUNI.js.map +1 -0
- package/dist/{sections-BYWOBISr.js → sections-jYuqS4KB.js} +2 -2
- package/dist/{sections-BYWOBISr.js.map → sections-jYuqS4KB.js.map} +1 -1
- package/dist/utils/ast/index.d.ts +2 -2
- package/dist/utils/ast/index.js +13 -15
- package/dist/utils/ast/index.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +2 -2
- package/package.json +5 -7
- package/dist/dnd-UoJILA75.js.map +0 -1
- package/dist/document-CGbe6bSV.js +0 -38667
- package/dist/document-CGbe6bSV.js.map +0 -1
- package/dist/index-DKYUxi-E.d.ts +0 -227
- package/dist/items-B6OXxcLG.js.map +0 -1
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { C as
|
|
1
|
+
import { $ as jsxClosingFragment, A as isJSXElement, B as isObjectExpression, C as booleanLiteral, D as isExpression, E as isBooleanLiteral, F as isJSXOpeningElement, G as isTSAsExpression, H as isParenthesizedExpression, I as isJSXSpreadAttribute, J as isTSTypeAssertion, K as isTSNonNullExpression, L as isJSXText, M as isJSXExpressionContainer, N as isJSXFragment, O as isIdentifier, P as isJSXIdentifier, Q as jsxClosingElement, R as isNullLiteral, S as arrayExpression, T as isArrayExpression, U as isSpreadElement, V as isObjectProperty, W as isStringLiteral, X as isUnaryExpression, Y as isTemplateLiteral, Z as jsxAttribute, _ as generateCode, _t as parse, at as jsxOpeningElement, b as getJSXTagName, ct as nullLiteral, d as traverse, dt as objectProperty, et as jsxElement, ft as stringLiteral, g as attrValue, gt as unaryExpression, ht as traverseFast, it as jsxMemberExpression, j as isJSXEmptyExpression, k as isJSXAttribute, lt as numericLiteral, mt as templateLiteral, nt as jsxFragment, ot as jsxOpeningFragment, pt as templateElement, q as isTSSatisfiesExpression, rt as jsxIdentifier, st as jsxText, tt as jsxExpressionContainer, ut as objectExpression, v as unwrap, vt as parseExpression, w as identifier, x as nanoid, y as wrap, z as isNumericLiteral } from "./document-CHO215iP.js";
|
|
2
2
|
import { c as RESERVED_BINDING_PROPERTIES, n as CONFIG, r as DATA_ATTR, s as REGEX, t as BINDING_PROP } from "./constants-DU17Tdwo.js";
|
|
3
3
|
import { n as registerEditorCache } from "./editor-caches-ClMvdcQF.js";
|
|
4
4
|
import { t as createBoundedCache } from "./cache-B0-XcIxJ.js";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
//#region src/utils/ast/types.ts
|
|
7
|
-
var import_lib = require_lib();
|
|
8
|
-
var import_lib$1 = /* @__PURE__ */ __toESM(require_lib$1(), 1);
|
|
9
7
|
const BINDING_TYPES = [
|
|
10
8
|
"array",
|
|
11
9
|
"object",
|
|
@@ -31,44 +29,44 @@ const dedent = (str) => {
|
|
|
31
29
|
};
|
|
32
30
|
const unwrapExpression = (node) => {
|
|
33
31
|
let current = node;
|
|
34
|
-
while (
|
|
32
|
+
while (isTSAsExpression(current) || isTSSatisfiesExpression(current) || isTSNonNullExpression(current) || isTSTypeAssertion(current) || isParenthesizedExpression(current)) current = current.expression;
|
|
35
33
|
return current;
|
|
36
34
|
};
|
|
37
35
|
const isLosslesslyEvaluable = (node) => {
|
|
38
36
|
const value = unwrapExpression(node);
|
|
39
|
-
if (
|
|
40
|
-
if (
|
|
41
|
-
if (
|
|
42
|
-
if (
|
|
43
|
-
if (
|
|
37
|
+
if (isStringLiteral(value) || isNumericLiteral(value) || isBooleanLiteral(value) || isNullLiteral(value)) return true;
|
|
38
|
+
if (isUnaryExpression(value) && value.operator === "-" && isNumericLiteral(value.argument)) return true;
|
|
39
|
+
if (isTemplateLiteral(value)) return value.expressions.length === 0;
|
|
40
|
+
if (isArrayExpression(value)) return value.elements.every((element) => element !== null && isLosslesslyEvaluable(element));
|
|
41
|
+
if (isObjectExpression(value)) return value.properties.every((property) => isObjectProperty(property) && !property.computed && (isIdentifier(property.key) || isStringLiteral(property.key) || isNumericLiteral(property.key)) && isLosslesslyEvaluable(property.value));
|
|
44
42
|
return false;
|
|
45
43
|
};
|
|
46
44
|
const canLosslesslyEvaluateSource = (source) => {
|
|
47
45
|
try {
|
|
48
|
-
return isLosslesslyEvaluable(
|
|
46
|
+
return isLosslesslyEvaluable(parseExpression(source, { plugins: ["jsx", "typescript"] }));
|
|
49
47
|
} catch {
|
|
50
48
|
return false;
|
|
51
49
|
}
|
|
52
50
|
};
|
|
53
51
|
const evaluateLiteral = (rawNode) => {
|
|
54
52
|
const node = unwrapExpression(rawNode);
|
|
55
|
-
if (
|
|
56
|
-
if (
|
|
57
|
-
if (
|
|
58
|
-
if (
|
|
59
|
-
if (
|
|
60
|
-
if (
|
|
61
|
-
if (
|
|
62
|
-
if (
|
|
63
|
-
if (
|
|
64
|
-
if (
|
|
53
|
+
if (isStringLiteral(node)) return node.value;
|
|
54
|
+
if (isNumericLiteral(node)) return node.value;
|
|
55
|
+
if (isBooleanLiteral(node)) return node.value;
|
|
56
|
+
if (isNullLiteral(node)) return null;
|
|
57
|
+
if (isIdentifier(node) && node.name === "undefined") return;
|
|
58
|
+
if (isUnaryExpression(node) && node.operator === "-" && isNumericLiteral(node.argument)) return -node.argument.value;
|
|
59
|
+
if (isTemplateLiteral(node) && node.expressions.length === 0) return node.quasis[0]?.value.cooked ?? node.quasis[0]?.value.raw ?? "";
|
|
60
|
+
if (isJSXElement(node) || isJSXFragment(node)) return generateCode(node);
|
|
61
|
+
if (isArrayExpression(node)) return node.elements.map((element) => element ? evaluateLiteral(element) : null);
|
|
62
|
+
if (isObjectExpression(node)) {
|
|
65
63
|
const result = {};
|
|
66
64
|
for (const prop of node.properties) {
|
|
67
|
-
if (!
|
|
65
|
+
if (!isObjectProperty(prop)) continue;
|
|
68
66
|
let key = null;
|
|
69
|
-
if (
|
|
70
|
-
else if (
|
|
71
|
-
else if (
|
|
67
|
+
if (isIdentifier(prop.key)) key = prop.key.name;
|
|
68
|
+
else if (isStringLiteral(prop.key)) key = prop.key.value;
|
|
69
|
+
else if (isNumericLiteral(prop.key)) key = String(prop.key.value);
|
|
72
70
|
if (key === null) continue;
|
|
73
71
|
result[key] = evaluateLiteral(prop.value);
|
|
74
72
|
}
|
|
@@ -88,31 +86,31 @@ const parseValue = (value) => {
|
|
|
88
86
|
}
|
|
89
87
|
if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
90
88
|
try {
|
|
91
|
-
const ast =
|
|
92
|
-
if (
|
|
89
|
+
const ast = parseExpression(trimmed, { plugins: ["jsx", "typescript"] });
|
|
90
|
+
if (isObjectExpression(ast) || isArrayExpression(ast)) return evaluateLiteral(ast);
|
|
93
91
|
} catch {}
|
|
94
92
|
return value;
|
|
95
93
|
}
|
|
96
94
|
return value;
|
|
97
95
|
};
|
|
98
96
|
const extractNodeValue = (node) => {
|
|
99
|
-
if (
|
|
97
|
+
if (isBooleanLiteral(node)) return {
|
|
100
98
|
type: "boolean",
|
|
101
99
|
value: node.value
|
|
102
100
|
};
|
|
103
|
-
if (
|
|
101
|
+
if (isNumericLiteral(node)) return {
|
|
104
102
|
type: "number",
|
|
105
103
|
value: node.value
|
|
106
104
|
};
|
|
107
|
-
if (
|
|
105
|
+
if (isUnaryExpression(node) && node.operator === "-" && isNumericLiteral(node.argument)) return {
|
|
108
106
|
type: "number",
|
|
109
107
|
value: -node.argument.value
|
|
110
108
|
};
|
|
111
|
-
if (
|
|
109
|
+
if (isStringLiteral(node)) return {
|
|
112
110
|
type: "string",
|
|
113
111
|
value: node.value
|
|
114
112
|
};
|
|
115
|
-
if (
|
|
113
|
+
if (isTemplateLiteral(node)) {
|
|
116
114
|
if (node.expressions.length === 0 && node.quasis.length === 1) return {
|
|
117
115
|
type: "string",
|
|
118
116
|
value: dedent(node.quasis[0].value.cooked ?? node.quasis[0].value.raw)
|
|
@@ -122,19 +120,19 @@ const extractNodeValue = (node) => {
|
|
|
122
120
|
value: generateCode(node)
|
|
123
121
|
};
|
|
124
122
|
}
|
|
125
|
-
if (
|
|
123
|
+
if (isNullLiteral(node)) return {
|
|
126
124
|
type: "null",
|
|
127
125
|
value: null
|
|
128
126
|
};
|
|
129
|
-
if (
|
|
127
|
+
if (isArrayExpression(node)) return {
|
|
130
128
|
type: "array",
|
|
131
129
|
value: generateCode(node)
|
|
132
130
|
};
|
|
133
|
-
if (
|
|
131
|
+
if (isObjectExpression(node)) return {
|
|
134
132
|
type: "object",
|
|
135
133
|
value: generateCode(node)
|
|
136
134
|
};
|
|
137
|
-
if (
|
|
135
|
+
if (isJSXElement(node) || isJSXFragment(node)) return {
|
|
138
136
|
type: "string",
|
|
139
137
|
value: generateCode(node)
|
|
140
138
|
};
|
|
@@ -145,8 +143,8 @@ const extractNodeValue = (node) => {
|
|
|
145
143
|
};
|
|
146
144
|
const parseArrayExpression = (value) => {
|
|
147
145
|
try {
|
|
148
|
-
const ast = unwrapExpression(
|
|
149
|
-
if (!
|
|
146
|
+
const ast = unwrapExpression(parseExpression(value, { plugins: ["jsx", "typescript"] }));
|
|
147
|
+
if (!isArrayExpression(ast)) return null;
|
|
150
148
|
return ast;
|
|
151
149
|
} catch (error) {
|
|
152
150
|
console.error("❌ Array parsing error:", error);
|
|
@@ -156,9 +154,9 @@ const parseArrayExpression = (value) => {
|
|
|
156
154
|
const extractObjectProperties = (element) => {
|
|
157
155
|
const properties = {};
|
|
158
156
|
element.properties.forEach((prop) => {
|
|
159
|
-
if (
|
|
157
|
+
if (isObjectProperty(prop) && isIdentifier(prop.key)) {
|
|
160
158
|
const key = prop.key.name;
|
|
161
|
-
if (key === "children" ||
|
|
159
|
+
if (key === "children" || isJSXElement(prop.value) || isJSXFragment(prop.value)) return;
|
|
162
160
|
const extracted = extractNodeValue(prop.value);
|
|
163
161
|
properties[key] = {
|
|
164
162
|
...extracted,
|
|
@@ -329,12 +327,12 @@ const getCurrentValue = (node, property) => {
|
|
|
329
327
|
case BINDING_PROP.INNER_HTML: {
|
|
330
328
|
const dsiAttr = node.attributes.find((a) => a.name === "dangerouslySetInnerHTML");
|
|
331
329
|
if (dsiAttr?.value) try {
|
|
332
|
-
const expr =
|
|
333
|
-
if (
|
|
334
|
-
const htmlProp = expr.properties.find((p) =>
|
|
330
|
+
const expr = parseExpression(dsiAttr.value, { plugins: ["jsx", "typescript"] });
|
|
331
|
+
if (isObjectExpression(expr)) {
|
|
332
|
+
const htmlProp = expr.properties.find((p) => isObjectProperty(p) && isIdentifier(p.key) && p.key.name === "__html");
|
|
335
333
|
if (htmlProp) {
|
|
336
|
-
if (
|
|
337
|
-
if (
|
|
334
|
+
if (isStringLiteral(htmlProp.value)) return htmlProp.value.value;
|
|
335
|
+
if (isTemplateLiteral(htmlProp.value) && htmlProp.value.expressions.length === 0) return htmlProp.value.quasis[0]?.value.cooked ?? htmlProp.value.quasis[0]?.value.raw ?? "";
|
|
338
336
|
}
|
|
339
337
|
}
|
|
340
338
|
} catch {}
|
|
@@ -385,13 +383,13 @@ const findEditableChildren = (node) => {
|
|
|
385
383
|
//#endregion
|
|
386
384
|
//#region src/utils/ast/extract.ts
|
|
387
385
|
const collectText = (children) => {
|
|
388
|
-
return children.filter((c) =>
|
|
386
|
+
return children.filter((c) => isJSXText(c)).map((c) => c.value.trim()).filter((v) => v.length).join(" ");
|
|
389
387
|
};
|
|
390
388
|
const parseJSXName = (tagName) => {
|
|
391
389
|
const parts = tagName.split(".");
|
|
392
|
-
if (parts.length === 1) return
|
|
393
|
-
let expr =
|
|
394
|
-
for (let i = 1; i < parts.length; i++) expr =
|
|
390
|
+
if (parts.length === 1) return jsxIdentifier(parts[0]);
|
|
391
|
+
let expr = jsxIdentifier(parts[0]);
|
|
392
|
+
for (let i = 1; i < parts.length; i++) expr = jsxMemberExpression(expr, jsxIdentifier(parts[i]));
|
|
395
393
|
return expr;
|
|
396
394
|
};
|
|
397
395
|
const extractCache = createBoundedCache(CONFIG.CACHE_LIMIT);
|
|
@@ -415,19 +413,19 @@ const extractAttributes = (attributes, source) => {
|
|
|
415
413
|
const allAttrs = [];
|
|
416
414
|
const dataAttrs = [];
|
|
417
415
|
for (const attr of attributes) {
|
|
418
|
-
if (!
|
|
416
|
+
if (!isJSXAttribute(attr) || !isJSXIdentifier(attr.name)) continue;
|
|
419
417
|
const name = attr.name.name;
|
|
420
418
|
let value = null;
|
|
421
|
-
let isStringLiteral = false;
|
|
419
|
+
let isStringLiteral$1 = false;
|
|
422
420
|
if (attr.value) {
|
|
423
|
-
if (
|
|
421
|
+
if (isStringLiteral(attr.value)) {
|
|
424
422
|
value = attr.value.value;
|
|
425
|
-
isStringLiteral = true;
|
|
426
|
-
} else if (
|
|
423
|
+
isStringLiteral$1 = true;
|
|
424
|
+
} else if (isJSXExpressionContainer(attr.value)) try {
|
|
427
425
|
const expression = attr.value.expression;
|
|
428
|
-
const structural =
|
|
426
|
+
const structural = isArrayExpression(unwrapExpression(expression)) || isObjectExpression(unwrapExpression(expression));
|
|
429
427
|
value = source && structural && expression.start != null && expression.end != null ? source.slice(expression.start, expression.end) : generateCode(expression);
|
|
430
|
-
isStringLiteral = false;
|
|
428
|
+
isStringLiteral$1 = false;
|
|
431
429
|
} catch {
|
|
432
430
|
value = null;
|
|
433
431
|
}
|
|
@@ -435,7 +433,7 @@ const extractAttributes = (attributes, source) => {
|
|
|
435
433
|
const entry = {
|
|
436
434
|
name,
|
|
437
435
|
value,
|
|
438
|
-
isStringLiteral
|
|
436
|
+
isStringLiteral: isStringLiteral$1
|
|
439
437
|
};
|
|
440
438
|
allAttrs.push(entry);
|
|
441
439
|
if (name.startsWith("data-")) dataAttrs.push(entry);
|
|
@@ -447,7 +445,7 @@ const extractAttributes = (attributes, source) => {
|
|
|
447
445
|
};
|
|
448
446
|
const buildChildElements = (node) => {
|
|
449
447
|
const childElements = [];
|
|
450
|
-
if (node.textContent) childElements.push(
|
|
448
|
+
if (node.textContent) childElements.push(jsxText(node.textContent));
|
|
451
449
|
node.children?.forEach((child) => {
|
|
452
450
|
const childJSX = nodeToJSX(child);
|
|
453
451
|
if (childJSX) childElements.push(childJSX);
|
|
@@ -458,22 +456,22 @@ const nodeToJSX = (node) => {
|
|
|
458
456
|
try {
|
|
459
457
|
if (node.isFragment) {
|
|
460
458
|
const childElements = buildChildElements(node);
|
|
461
|
-
return
|
|
459
|
+
return jsxFragment(jsxOpeningFragment(), jsxClosingFragment(), childElements);
|
|
462
460
|
}
|
|
463
461
|
if (node.tagName === "div" && node.dataAttributes.some((attr) => attr.name === "data-item")) {
|
|
464
462
|
if (node.children) return nodeToJSX(node.children[0]);
|
|
465
463
|
return null;
|
|
466
464
|
}
|
|
467
465
|
const attributes = node.attributes.map((attr) => {
|
|
468
|
-
const attrName =
|
|
469
|
-
if (!attr.value) return
|
|
470
|
-
return
|
|
466
|
+
const attrName = jsxIdentifier(attr.name);
|
|
467
|
+
if (!attr.value) return jsxAttribute(attrName, null);
|
|
468
|
+
return jsxAttribute(attrName, attrValue(attr));
|
|
471
469
|
});
|
|
472
470
|
const elementName = parseJSXName(node.tagName);
|
|
473
|
-
const openingElement =
|
|
474
|
-
const closingElement =
|
|
471
|
+
const openingElement = jsxOpeningElement(elementName, attributes);
|
|
472
|
+
const closingElement = jsxClosingElement(elementName);
|
|
475
473
|
const children = buildChildElements(node);
|
|
476
|
-
return
|
|
474
|
+
return jsxElement(openingElement, closingElement, children);
|
|
477
475
|
} catch (error) {
|
|
478
476
|
console.error("❌ DataAttrNode to JSX conversion error:", error);
|
|
479
477
|
return null;
|
|
@@ -503,11 +501,11 @@ const createFragmentNode = (textContent, children) => ({
|
|
|
503
501
|
isFragment: true
|
|
504
502
|
});
|
|
505
503
|
const processChildrenBinding = (jsxElement, processedNodes, shouldWrap = true, source, options) => {
|
|
506
|
-
const jsxChildren = jsxElement.children.filter((child) =>
|
|
504
|
+
const jsxChildren = jsxElement.children.filter((child) => isJSXElement(child) || isJSXFragment(child));
|
|
507
505
|
if (!jsxChildren.length) return;
|
|
508
506
|
const childrenNodes = [];
|
|
509
507
|
jsxChildren.forEach((child) => {
|
|
510
|
-
if (
|
|
508
|
+
if (isJSXElement(child)) {
|
|
511
509
|
const childResults = extractFromNode(child, processedNodes, source, options);
|
|
512
510
|
if (shouldWrap) {
|
|
513
511
|
const wrapperNode = createWrapperNode(collectText(child.children), childResults);
|
|
@@ -516,11 +514,11 @@ const processChildrenBinding = (jsxElement, processedNodes, shouldWrap = true, s
|
|
|
516
514
|
if (dataId) wrapperNode.id = `child:${dataId}`;
|
|
517
515
|
childrenNodes.push(wrapperNode);
|
|
518
516
|
} else childrenNodes.push(...childResults);
|
|
519
|
-
} else if (
|
|
517
|
+
} else if (isJSXFragment(child)) {
|
|
520
518
|
processedNodes?.add(child);
|
|
521
519
|
const fragmentChildren = [];
|
|
522
520
|
child.children.forEach((fragmentChild) => {
|
|
523
|
-
if (
|
|
521
|
+
if (isJSXElement(fragmentChild)) {
|
|
524
522
|
const childResults = extractFromNode(fragmentChild, processedNodes, source, options);
|
|
525
523
|
fragmentChildren.push(...childResults);
|
|
526
524
|
}
|
|
@@ -535,26 +533,26 @@ const processChildrenBinding = (jsxElement, processedNodes, shouldWrap = true, s
|
|
|
535
533
|
return childrenNodes.length ? childrenNodes : void 0;
|
|
536
534
|
};
|
|
537
535
|
const skipItemsChildren = (jsxElement, processedNodes, propertyName = "items") => {
|
|
538
|
-
const itemsAttr = jsxElement.openingElement.attributes.find((attr) =>
|
|
539
|
-
if (!itemsAttr || !
|
|
540
|
-
if (itemsAttr.value &&
|
|
541
|
-
if (
|
|
542
|
-
if (
|
|
536
|
+
const itemsAttr = jsxElement.openingElement.attributes.find((attr) => isJSXAttribute(attr) && isJSXIdentifier(attr.name) && attr.name.name === propertyName);
|
|
537
|
+
if (!itemsAttr || !isJSXAttribute(itemsAttr)) return;
|
|
538
|
+
if (itemsAttr.value && isJSXExpressionContainer(itemsAttr.value) && isArrayExpression(itemsAttr.value.expression)) itemsAttr.value.expression.elements.forEach((element) => {
|
|
539
|
+
if (isObjectExpression(element)) element.properties.forEach((prop) => {
|
|
540
|
+
if (isObjectProperty(prop) && isIdentifier(prop.key) && isJSXElement(prop.value)) markProcessedJSX(prop.value, processedNodes);
|
|
543
541
|
});
|
|
544
542
|
});
|
|
545
543
|
};
|
|
546
544
|
const markProcessedJSX = (node, processedNodes) => {
|
|
547
|
-
if (
|
|
545
|
+
if (isJSXElement(node) || isJSXFragment(node)) {
|
|
548
546
|
processedNodes.add(node);
|
|
549
547
|
node.children.forEach((child) => markProcessedJSX(child, processedNodes));
|
|
550
548
|
return;
|
|
551
549
|
}
|
|
552
|
-
if (
|
|
550
|
+
if (isJSXExpressionContainer(node) || isParenthesizedExpression(node)) markProcessedJSX(node.expression, processedNodes);
|
|
553
551
|
};
|
|
554
552
|
const getBindingExpression = (opening) => {
|
|
555
|
-
for (const attr of opening.attributes) if (
|
|
553
|
+
for (const attr of opening.attributes) if (isJSXAttribute(attr) && isJSXIdentifier(attr.name) && attr.name.name === DATA_ATTR.BINDING && attr.value && isJSXExpressionContainer(attr.value)) {
|
|
556
554
|
const expression = unwrapExpression(attr.value.expression);
|
|
557
|
-
if (
|
|
555
|
+
if (isArrayExpression(expression)) return expression;
|
|
558
556
|
}
|
|
559
557
|
return null;
|
|
560
558
|
};
|
|
@@ -583,7 +581,7 @@ const readNodeBindingInfo = (node, source, options) => {
|
|
|
583
581
|
};
|
|
584
582
|
const parseToNodes = (raw, options) => {
|
|
585
583
|
const wrapped = wrap(raw);
|
|
586
|
-
const ast =
|
|
584
|
+
const ast = parse(wrapped, {
|
|
587
585
|
sourceType: "module",
|
|
588
586
|
plugins: ["jsx", "typescript"],
|
|
589
587
|
errorRecovery: true
|
|
@@ -760,7 +758,7 @@ const getChildrenSignatures = (nodes) => {
|
|
|
760
758
|
};
|
|
761
759
|
const indicesAreValid = (indices, count) => Array.isArray(indices) && new Set(indices).size === indices.length && indices.every((index) => Number.isInteger(index) && index >= 0 && index < count);
|
|
762
760
|
const copySource = (source, usedIds) => {
|
|
763
|
-
const node =
|
|
761
|
+
const node = parseExpression(source, { plugins: ["jsx", "typescript"] });
|
|
764
762
|
const edits = [];
|
|
765
763
|
const newId = () => {
|
|
766
764
|
let id = nanoid(12);
|
|
@@ -768,15 +766,15 @@ const copySource = (source, usedIds) => {
|
|
|
768
766
|
usedIds.add(id);
|
|
769
767
|
return id;
|
|
770
768
|
};
|
|
771
|
-
|
|
772
|
-
if (!
|
|
773
|
-
const ids = child.attributes.filter((attr) =>
|
|
769
|
+
traverseFast(node, (child) => {
|
|
770
|
+
if (!isJSXOpeningElement(child)) return;
|
|
771
|
+
const ids = child.attributes.filter((attr) => isJSXAttribute(attr) && isJSXIdentifier(attr.name, { name: "data-id" }));
|
|
774
772
|
if (ids.length > 1) throw new Error("Duplicate data-id attributes");
|
|
775
773
|
const attr = ids[0];
|
|
776
|
-
if (attr && child.attributes.slice(child.attributes.indexOf(attr) + 1).some((attribute) =>
|
|
774
|
+
if (attr && child.attributes.slice(child.attributes.indexOf(attr) + 1).some((attribute) => isJSXSpreadAttribute(attribute))) throw new Error("A spread may override the copied data-id");
|
|
777
775
|
if (attr) {
|
|
778
776
|
const value = attr.value;
|
|
779
|
-
if (!
|
|
777
|
+
if (!isStringLiteral(value) || value.start == null || value.end == null) throw new Error("Cannot copy a dynamic data-id");
|
|
780
778
|
edits.push({
|
|
781
779
|
start: value.start,
|
|
782
780
|
end: value.end,
|
|
@@ -798,7 +796,7 @@ const editChildrenSource = (source, parent, input, options) => {
|
|
|
798
796
|
try {
|
|
799
797
|
if (!parent.closingElement || parent.start == null || parent.end == null) return null;
|
|
800
798
|
const value = typeof input === "string" ? JSON.parse(input) : input;
|
|
801
|
-
const children = parent.children.filter((child) =>
|
|
799
|
+
const children = parent.children.filter((child) => isJSXElement(child) || isJSXFragment(child));
|
|
802
800
|
const raw = children.map((child) => source.slice(child.start, child.end));
|
|
803
801
|
const models = extract(source.slice(parent.start, parent.end), options)[0]?.children ?? [];
|
|
804
802
|
if (models.length !== children.length) return null;
|
|
@@ -821,7 +819,7 @@ const editChildrenSource = (source, parent, input, options) => {
|
|
|
821
819
|
};
|
|
822
820
|
if (Array.isArray(value)) {
|
|
823
821
|
const desired = modeledSignatures(value);
|
|
824
|
-
const lossless = raw.every((text, index) => generateCode(
|
|
822
|
+
const lossless = raw.every((text, index) => generateCode(parseExpression(text, { plugins: ["jsx", "typescript"] })) === signatures[index]);
|
|
825
823
|
const consumed = /* @__PURE__ */ new Set();
|
|
826
824
|
const next = desired.map((signature, position) => {
|
|
827
825
|
const index = signatures.findIndex((candidate, i) => candidate === signature && !consumed.has(i) && (value[position].source === void 0 || value[position].source === raw[i]));
|
|
@@ -834,8 +832,8 @@ const editChildrenSource = (source, parent, input, options) => {
|
|
|
834
832
|
});
|
|
835
833
|
const countIds = (text) => {
|
|
836
834
|
const counts = /* @__PURE__ */ new Map();
|
|
837
|
-
|
|
838
|
-
if (
|
|
835
|
+
traverseFast(parseExpression(text, { plugins: ["jsx", "typescript"] }), (node) => {
|
|
836
|
+
if (isJSXAttribute(node) && isJSXIdentifier(node.name, { name: "data-id" }) && isStringLiteral(node.value)) counts.set(node.value.value, (counts.get(node.value.value) ?? 0) + 1);
|
|
839
837
|
});
|
|
840
838
|
return counts;
|
|
841
839
|
};
|
|
@@ -847,8 +845,8 @@ const editChildrenSource = (source, parent, input, options) => {
|
|
|
847
845
|
if (request?.kind !== "children-edit" || !Array.isArray(request.expected) || request.expected.length !== signatures.length || !getChildrenSignatures(models).every((signature, index) => signature === request.expected[index]) || !request.action) return null;
|
|
848
846
|
const { action } = request;
|
|
849
847
|
const usedIds = /* @__PURE__ */ new Set();
|
|
850
|
-
|
|
851
|
-
if (
|
|
848
|
+
traverseFast(parent, (node) => {
|
|
849
|
+
if (isJSXAttribute(node) && isJSXIdentifier(node.name, { name: "data-id" }) && isStringLiteral(node.value)) usedIds.add(node.value.value);
|
|
852
850
|
});
|
|
853
851
|
switch (action.type) {
|
|
854
852
|
case "move": {
|
|
@@ -897,10 +895,10 @@ const editChildrenSource = (source, parent, input, options) => {
|
|
|
897
895
|
//#region src/utils/ast/value-expression.ts
|
|
898
896
|
const createNodeFromValue = (type, value) => {
|
|
899
897
|
switch (type) {
|
|
900
|
-
case "boolean": return
|
|
901
|
-
case "number": return
|
|
902
|
-
case "string": return
|
|
903
|
-
case "null": return
|
|
898
|
+
case "boolean": return booleanLiteral(value === true);
|
|
899
|
+
case "number": return numericLiteral(Number(value));
|
|
900
|
+
case "string": return stringLiteral(String(value));
|
|
901
|
+
case "null": return nullLiteral();
|
|
904
902
|
case "array":
|
|
905
903
|
case "object":
|
|
906
904
|
case "unknown": return null;
|
|
@@ -908,24 +906,24 @@ const createNodeFromValue = (type, value) => {
|
|
|
908
906
|
}
|
|
909
907
|
};
|
|
910
908
|
const valueToExpression = (value) => {
|
|
911
|
-
if (typeof value === "string") return
|
|
912
|
-
if (typeof value === "number") return value < 0 ?
|
|
913
|
-
if (typeof value === "boolean") return
|
|
914
|
-
if (value === null) return
|
|
915
|
-
if (Array.isArray(value)) return
|
|
909
|
+
if (typeof value === "string") return stringLiteral(value);
|
|
910
|
+
if (typeof value === "number") return value < 0 ? unaryExpression("-", numericLiteral(-value)) : numericLiteral(value);
|
|
911
|
+
if (typeof value === "boolean") return booleanLiteral(value);
|
|
912
|
+
if (value === null) return nullLiteral();
|
|
913
|
+
if (Array.isArray(value)) return arrayExpression(value.map((item) => valueToExpression(item) ?? nullLiteral()));
|
|
916
914
|
if (typeof value === "object") {
|
|
917
915
|
const properties = [];
|
|
918
916
|
for (const [key, item] of Object.entries(value)) {
|
|
919
917
|
const expr = valueToExpression(item);
|
|
920
918
|
if (expr === null) continue;
|
|
921
|
-
properties.push(
|
|
919
|
+
properties.push(objectProperty(stringLiteral(key), expr));
|
|
922
920
|
}
|
|
923
|
-
return
|
|
921
|
+
return objectExpression(properties);
|
|
924
922
|
}
|
|
925
923
|
return null;
|
|
926
924
|
};
|
|
927
925
|
const arrayExpressionToCode = (elements) => {
|
|
928
|
-
const nextAst =
|
|
926
|
+
const nextAst = arrayExpression(elements);
|
|
929
927
|
return generateCode(nextAst);
|
|
930
928
|
};
|
|
931
929
|
//#endregion
|
|
@@ -939,7 +937,7 @@ const childrenRange = (element) => {
|
|
|
939
937
|
};
|
|
940
938
|
};
|
|
941
939
|
const findAttribute = (opening, propertyName) => {
|
|
942
|
-
return opening.attributes.find((attr) =>
|
|
940
|
+
return opening.attributes.find((attr) => isJSXAttribute(attr) && isJSXIdentifier(attr.name) && attr.name.name === propertyName);
|
|
943
941
|
};
|
|
944
942
|
const attributeInsertPoint = (opening) => {
|
|
945
943
|
return opening.attributes[opening.attributes.length - 1]?.end ?? opening.name.end ?? null;
|
|
@@ -948,7 +946,7 @@ const editInnerText = (source, element, value) => {
|
|
|
948
946
|
const range = childrenRange(element);
|
|
949
947
|
if (!range) return [];
|
|
950
948
|
const [only] = element.children;
|
|
951
|
-
if (element.children.length === 1 &&
|
|
949
|
+
if (element.children.length === 1 && isJSXText(only) && only.start != null && only.end != null) {
|
|
952
950
|
const raw = source.slice(only.start, only.end);
|
|
953
951
|
if (raw.trim() !== "") {
|
|
954
952
|
const leading = raw.length - raw.trimStart().length;
|
|
@@ -961,7 +959,7 @@ const editInnerText = (source, element, value) => {
|
|
|
961
959
|
}
|
|
962
960
|
}
|
|
963
961
|
const edits = [];
|
|
964
|
-
for (const child of element.children) if (
|
|
962
|
+
for (const child of element.children) if (isJSXText(child) && child.start != null && child.end != null) edits.push({
|
|
965
963
|
start: child.start,
|
|
966
964
|
end: child.end,
|
|
967
965
|
content: ""
|
|
@@ -991,7 +989,7 @@ const editRichtext = (element, value) => {
|
|
|
991
989
|
content: ""
|
|
992
990
|
});
|
|
993
991
|
const opening = element.openingElement;
|
|
994
|
-
const attribute =
|
|
992
|
+
const attribute = jsxAttribute(jsxIdentifier("dangerouslySetInnerHTML"), jsxExpressionContainer(objectExpression([objectProperty(identifier("__html"), stringLiteral(value))])));
|
|
995
993
|
const content = generateCode(attribute);
|
|
996
994
|
const existing = findAttribute(opening, "dangerouslySetInnerHTML");
|
|
997
995
|
if (existing && existing.start != null && existing.end != null) {
|
|
@@ -1030,11 +1028,11 @@ const editJsxAttribute = (opening, propertyName, value) => {
|
|
|
1030
1028
|
content: `=${content}`
|
|
1031
1029
|
}];
|
|
1032
1030
|
};
|
|
1033
|
-
const holdsStructuralExpression = (value) =>
|
|
1031
|
+
const holdsStructuralExpression = (value) => isJSXExpressionContainer(value) && (isArrayExpression(unwrapExpression(value.expression)) || isObjectExpression(unwrapExpression(value.expression)));
|
|
1034
1032
|
const structuralSource = (value) => {
|
|
1035
1033
|
try {
|
|
1036
|
-
const expression =
|
|
1037
|
-
return
|
|
1034
|
+
const expression = parseExpression(value.trim(), { plugins: ["jsx", "typescript"] });
|
|
1035
|
+
return isArrayExpression(unwrapExpression(expression)) || isObjectExpression(unwrapExpression(expression)) ? expression : null;
|
|
1038
1036
|
} catch {
|
|
1039
1037
|
return null;
|
|
1040
1038
|
}
|
|
@@ -1042,29 +1040,29 @@ const structuralSource = (value) => {
|
|
|
1042
1040
|
const buildAttributeValue = (value, type, current) => {
|
|
1043
1041
|
if (type === "array" || type === "object") {
|
|
1044
1042
|
if (typeof value === "string") try {
|
|
1045
|
-
return
|
|
1043
|
+
return jsxExpressionContainer(parseExpression(value.trim(), { plugins: ["jsx", "typescript"] }));
|
|
1046
1044
|
} catch {
|
|
1047
|
-
return
|
|
1045
|
+
return stringLiteral(value);
|
|
1048
1046
|
}
|
|
1049
1047
|
const expr = valueToExpression(value);
|
|
1050
|
-
return expr ?
|
|
1048
|
+
return expr ? jsxExpressionContainer(expr) : stringLiteral("");
|
|
1051
1049
|
}
|
|
1052
1050
|
if (typeof value === "string") {
|
|
1053
1051
|
if (holdsStructuralExpression(current) && !(type && STRING_VALUED_TYPES.has(type))) {
|
|
1054
1052
|
const structural = structuralSource(value);
|
|
1055
|
-
if (structural) return
|
|
1053
|
+
if (structural) return jsxExpressionContainer(structural);
|
|
1056
1054
|
}
|
|
1057
|
-
return
|
|
1055
|
+
return stringLiteral(value);
|
|
1058
1056
|
}
|
|
1059
1057
|
const expr = valueToExpression(value);
|
|
1060
|
-
return expr ?
|
|
1058
|
+
return expr ? jsxExpressionContainer(expr) : stringLiteral(String(value));
|
|
1061
1059
|
};
|
|
1062
1060
|
const editAttribute = (opening, propertyName, value, type) => {
|
|
1063
1061
|
const attribute = findAttribute(opening, propertyName);
|
|
1064
1062
|
if (!attribute || attribute.start == null || attribute.end == null) return null;
|
|
1065
1063
|
if (typeof value === "string" && (type === "array" || type === "object" || holdsStructuralExpression(attribute.value) && !(type && STRING_VALUED_TYPES.has(type)))) {
|
|
1066
1064
|
const expression = structuralSource(value);
|
|
1067
|
-
if (expression &&
|
|
1065
|
+
if (expression && isJSXExpressionContainer(attribute.value)) {
|
|
1068
1066
|
const text = value.trim();
|
|
1069
1067
|
const lineComment = expression.trailingComments?.some((comment) => comment.type === "CommentLine");
|
|
1070
1068
|
return [{
|
|
@@ -1074,7 +1072,7 @@ const editAttribute = (opening, propertyName, value, type) => {
|
|
|
1074
1072
|
}];
|
|
1075
1073
|
}
|
|
1076
1074
|
}
|
|
1077
|
-
const content = generateCode(
|
|
1075
|
+
const content = generateCode(jsxAttribute(attribute.name, buildAttributeValue(value, type, attribute.value)));
|
|
1078
1076
|
return [{
|
|
1079
1077
|
start: attribute.start,
|
|
1080
1078
|
end: attribute.end,
|
|
@@ -1100,18 +1098,18 @@ const addAttribute = (source, opening, propertyName, value, type) => {
|
|
|
1100
1098
|
return [{
|
|
1101
1099
|
start: insertAt,
|
|
1102
1100
|
end: insertAt,
|
|
1103
|
-
content: `${lastStart != null && lineStart > 0 && /^\s*$/.test(source.slice(lineStart, lastStart)) ? "\n" : " "}${type === "jsx" ? `${propertyName}={${String(value).trim()}}` : generateCode(
|
|
1101
|
+
content: `${lastStart != null && lineStart > 0 && /^\s*$/.test(source.slice(lineStart, lastStart)) ? "\n" : " "}${type === "jsx" ? `${propertyName}={${String(value).trim()}}` : generateCode(jsxAttribute(jsxIdentifier(propertyName), buildAttributeValue(value, type)))}`,
|
|
1104
1102
|
indent: true
|
|
1105
1103
|
}];
|
|
1106
1104
|
};
|
|
1107
1105
|
const canEditAttributeValue = (attribute, value, type) => {
|
|
1108
|
-
if (!
|
|
1106
|
+
if (!isJSXExpressionContainer(attribute.value) || isJSXEmptyExpression(attribute.value.expression) || isLosslesslyEvaluable(attribute.value.expression)) return true;
|
|
1109
1107
|
return typeof value === "string" && holdsStructuralExpression(attribute.value) && !(type && STRING_VALUED_TYPES.has(type)) && structuralSource(value) !== null;
|
|
1110
1108
|
};
|
|
1111
1109
|
//#endregion
|
|
1112
1110
|
//#region src/utils/ast/update.ts
|
|
1113
|
-
const hasDataId = (opening, dataId) => opening.attributes.some((attr) =>
|
|
1114
|
-
const findJSXAttribute = (opening, name) => opening.attributes.find((attr) =>
|
|
1111
|
+
const hasDataId = (opening, dataId) => opening.attributes.some((attr) => isJSXAttribute(attr) && isJSXIdentifier(attr.name) && attr.name.name === DATA_ATTR.ID && attr.value && isStringLiteral(attr.value) && attr.value.value === dataId);
|
|
1112
|
+
const findJSXAttribute = (opening, name) => opening.attributes.find((attr) => isJSXAttribute(attr) && isJSXIdentifier(attr.name) && attr.name.name === name);
|
|
1115
1113
|
const findBinding = (opening, { dataId, label, property, options }) => {
|
|
1116
1114
|
const bindingAttr = findJSXAttribute(opening, DATA_ATTR.BINDING);
|
|
1117
1115
|
if (bindingAttr && !bindingAttr.value) return { failure: {
|
|
@@ -1121,8 +1119,8 @@ const findBinding = (opening, { dataId, label, property, options }) => {
|
|
|
1121
1119
|
let own;
|
|
1122
1120
|
if (bindingAttr?.value) {
|
|
1123
1121
|
let bindingValue = "";
|
|
1124
|
-
if (
|
|
1125
|
-
else if (
|
|
1122
|
+
if (isStringLiteral(bindingAttr.value)) bindingValue = bindingAttr.value.value;
|
|
1123
|
+
else if (isJSXExpressionContainer(bindingAttr.value)) try {
|
|
1126
1124
|
bindingValue = generateCode(bindingAttr.value.expression);
|
|
1127
1125
|
} catch (error) {
|
|
1128
1126
|
return { failure: {
|
|
@@ -1133,7 +1131,7 @@ const findBinding = (opening, { dataId, label, property, options }) => {
|
|
|
1133
1131
|
own = parseBinding(bindingValue);
|
|
1134
1132
|
}
|
|
1135
1133
|
const keyAttr = findJSXAttribute(opening, DATA_ATTR.BINDING_KEY);
|
|
1136
|
-
const bindings = resolveBindings(own, keyAttr && (keyAttr.value &&
|
|
1134
|
+
const bindings = resolveBindings(own, keyAttr && (keyAttr.value && isStringLiteral(keyAttr.value) ? keyAttr.value.value : null), getJSXTagName(opening), options);
|
|
1137
1135
|
if (!own && bindings.length === 0) return { failure: {
|
|
1138
1136
|
reason: "no-binding",
|
|
1139
1137
|
dataId
|
|
@@ -1243,7 +1241,7 @@ const update = (code, dataId, label, value, property, options = {}) => {
|
|
|
1243
1241
|
};
|
|
1244
1242
|
try {
|
|
1245
1243
|
const wrapped = wrap(code);
|
|
1246
|
-
const ast =
|
|
1244
|
+
const ast = parse(wrapped, {
|
|
1247
1245
|
sourceType: "module",
|
|
1248
1246
|
plugins: ["jsx", "typescript"]
|
|
1249
1247
|
});
|
|
@@ -1346,7 +1344,7 @@ const commaIn = (source, start, end) => {
|
|
|
1346
1344
|
};
|
|
1347
1345
|
const denseArraySource = (source) => {
|
|
1348
1346
|
const array = parseArrayExpression(source);
|
|
1349
|
-
if (!array || array.elements.some((node) => !
|
|
1347
|
+
if (!array || array.elements.some((node) => !isExpression(node) || node.extra?.parenthesized)) return null;
|
|
1350
1348
|
const elements = array.elements;
|
|
1351
1349
|
const commas = elements.slice(0, -1).map((node, index) => commaIn(source, node.end, elements[index + 1].start));
|
|
1352
1350
|
if (commas.some((comma) => comma === null)) return null;
|
|
@@ -1406,9 +1404,9 @@ const appendArraySource = (source, data, copies) => {
|
|
|
1406
1404
|
//#endregion
|
|
1407
1405
|
//#region src/utils/ast/items.ts
|
|
1408
1406
|
const elementsOf = (code) => parseArrayExpression(code)?.elements ?? null;
|
|
1409
|
-
const kindOf = (element) =>
|
|
1407
|
+
const kindOf = (element) => isObjectExpression(element) ? "object" : "primitive";
|
|
1410
1408
|
const parseItems = (code) => {
|
|
1411
|
-
return elementsOf(code)?.flatMap((node, index) =>
|
|
1409
|
+
return elementsOf(code)?.flatMap((node, index) => isExpression(node) ? [{
|
|
1412
1410
|
index,
|
|
1413
1411
|
kind: kindOf(node),
|
|
1414
1412
|
node
|
|
@@ -1424,23 +1422,23 @@ const toTemplateRaw = (value) => {
|
|
|
1424
1422
|
const buildPropertyValue = (value, declaredType, renderLeaf, current) => {
|
|
1425
1423
|
if (renderLeaf?.property === BINDING_PROP.INNER_HTML) {
|
|
1426
1424
|
const raw = String(value);
|
|
1427
|
-
return
|
|
1425
|
+
return templateLiteral([templateElement({
|
|
1428
1426
|
raw: toTemplateRaw(raw),
|
|
1429
1427
|
cooked: raw
|
|
1430
1428
|
}, true)], []);
|
|
1431
1429
|
}
|
|
1432
|
-
if (renderLeaf?.type === "jsx" ||
|
|
1430
|
+
if (renderLeaf?.type === "jsx" || isJSXElement(current) || isJSXFragment(current)) {
|
|
1433
1431
|
const trimmed = String(value).trim();
|
|
1434
|
-
if (!trimmed.startsWith("<")) return
|
|
1432
|
+
if (!trimmed.startsWith("<")) return stringLiteral(trimmed);
|
|
1435
1433
|
try {
|
|
1436
|
-
return
|
|
1434
|
+
return parseExpression(trimmed, { plugins: ["jsx", "typescript"] });
|
|
1437
1435
|
} catch {
|
|
1438
1436
|
return;
|
|
1439
1437
|
}
|
|
1440
1438
|
}
|
|
1441
1439
|
if (declaredType === "array" || declaredType === "object") {
|
|
1442
1440
|
if (typeof value === "string") try {
|
|
1443
|
-
return
|
|
1441
|
+
return parseExpression(value, { plugins: ["jsx", "typescript"] });
|
|
1444
1442
|
} catch {
|
|
1445
1443
|
return;
|
|
1446
1444
|
}
|
|
@@ -1452,13 +1450,13 @@ const buildPropertyValue = (value, declaredType, renderLeaf, current) => {
|
|
|
1452
1450
|
const updateArrayItemProperty = (code, index, key, value, render) => {
|
|
1453
1451
|
const elements = elementsOf(code);
|
|
1454
1452
|
const element = elements?.[index];
|
|
1455
|
-
if (!elements || !
|
|
1456
|
-
const target = element.properties.find((property) =>
|
|
1453
|
+
if (!elements || !isObjectExpression(element)) return null;
|
|
1454
|
+
const target = element.properties.find((property) => isObjectProperty(property) && isIdentifier(property.key) && property.key.name === key);
|
|
1457
1455
|
if (!target) return null;
|
|
1458
1456
|
const declaredType = extractObjectProperties(element)[key]?.type ?? "string";
|
|
1459
1457
|
const nextValue = buildPropertyValue(value, declaredType, resolveRenderLeaf(render, key), target.value);
|
|
1460
1458
|
if (!nextValue) return null;
|
|
1461
|
-
let serialized = typeof value === "string" && (declaredType === "array" || declaredType === "object" ||
|
|
1459
|
+
let serialized = typeof value === "string" && (declaredType === "array" || declaredType === "object" || isJSXElement(nextValue) || isJSXFragment(nextValue)) ? value.trim() : generateCode(nextValue);
|
|
1462
1460
|
if (nextValue.trailingComments?.some((comment) => comment.type === "CommentLine")) serialized += "\n";
|
|
1463
1461
|
const content = target.shorthand ? `${key}: ${serialized}` : serialized;
|
|
1464
1462
|
return applyEdits(code, [{
|
|
@@ -1470,7 +1468,7 @@ const updateArrayItemProperty = (code, index, key, value, render) => {
|
|
|
1470
1468
|
const updateArrayItemValue = (code, index, value) => {
|
|
1471
1469
|
const elements = elementsOf(code);
|
|
1472
1470
|
const element = elements?.[index];
|
|
1473
|
-
if (!elements || !
|
|
1471
|
+
if (!elements || !isExpression(element)) return null;
|
|
1474
1472
|
const nextValue = createNodeFromValue(extractNodeValue(element).type, parseValue(value));
|
|
1475
1473
|
if (!nextValue) return null;
|
|
1476
1474
|
return applyEdits(code, [{
|
|
@@ -1511,25 +1509,25 @@ const copyItem = (code, element, generateId, usedIds) => {
|
|
|
1511
1509
|
usedIds.add(id);
|
|
1512
1510
|
return JSON.stringify(id);
|
|
1513
1511
|
};
|
|
1514
|
-
|
|
1515
|
-
if (!
|
|
1516
|
-
const ids = node.attributes.filter((attr) =>
|
|
1512
|
+
traverseFast(element, (node) => {
|
|
1513
|
+
if (!isJSXOpeningElement(node)) return;
|
|
1514
|
+
const ids = node.attributes.filter((attr) => isJSXAttribute(attr) && isJSXIdentifier(attr.name, { name: "data-id" }));
|
|
1517
1515
|
const attr = ids[0];
|
|
1518
|
-
if (ids.length > 1 || attr && (!
|
|
1516
|
+
if (ids.length > 1 || attr && (!isStringLiteral(attr.value) || node.attributes.slice(node.attributes.indexOf(attr) + 1).some((a) => isJSXSpreadAttribute(a)))) {
|
|
1519
1517
|
unsupported = true;
|
|
1520
1518
|
return;
|
|
1521
1519
|
}
|
|
1522
|
-
if (attr &&
|
|
1520
|
+
if (attr && isStringLiteral(attr.value)) edits.push({
|
|
1523
1521
|
start: attr.value.start,
|
|
1524
1522
|
end: attr.value.end,
|
|
1525
1523
|
content: reserveId(generateId())
|
|
1526
1524
|
});
|
|
1527
1525
|
});
|
|
1528
|
-
if (
|
|
1529
|
-
const keys = element.properties.filter((prop) =>
|
|
1526
|
+
if (isObjectExpression(element)) {
|
|
1527
|
+
const keys = element.properties.filter((prop) => isObjectProperty(prop) && !prop.computed && (isIdentifier(prop.key, { name: "key" }) || isStringLiteral(prop.key, { value: "key" })));
|
|
1530
1528
|
const key = keys[0];
|
|
1531
|
-
if (keys.length > 1 || key && (!
|
|
1532
|
-
if (key &&
|
|
1529
|
+
if (keys.length > 1 || key && (!isStringLiteral(key.value) || element.properties.slice(element.properties.indexOf(key) + 1).some((prop) => isSpreadElement(prop) || "computed" in prop && prop.computed))) return null;
|
|
1530
|
+
if (key && isStringLiteral(key.value)) edits.push({
|
|
1533
1531
|
start: key.value.start,
|
|
1534
1532
|
end: key.value.end,
|
|
1535
1533
|
content: reserveId(`${key.value.value}-${generateId()}`)
|
|
@@ -1546,9 +1544,9 @@ const duplicateArrayItems = (code, indices, generateId = () => nanoid(6)) => {
|
|
|
1546
1544
|
const data = denseArraySource(code);
|
|
1547
1545
|
if (!data || !indices.size || !validArrayIndices(indices, data.elements.length)) return null;
|
|
1548
1546
|
const usedIds = /* @__PURE__ */ new Set();
|
|
1549
|
-
|
|
1550
|
-
if (
|
|
1551
|
-
else if (
|
|
1547
|
+
traverseFast(data.array, (node) => {
|
|
1548
|
+
if (isJSXAttribute(node) && isJSXIdentifier(node.name, { name: "data-id" }) && isStringLiteral(node.value)) usedIds.add(node.value.value);
|
|
1549
|
+
else if (isObjectProperty(node) && !node.computed && (isIdentifier(node.key, { name: "key" }) || isStringLiteral(node.key, { value: "key" })) && isStringLiteral(node.value)) usedIds.add(node.value.value);
|
|
1552
1550
|
});
|
|
1553
1551
|
const copies = [...indices].sort((a, b) => a - b).map((index) => copyItem(code, data.elements[index], generateId, usedIds));
|
|
1554
1552
|
return copies.every((copy) => copy !== null) ? appendArraySource(code, data, copies) : null;
|
|
@@ -1560,4 +1558,4 @@ const appendArrayItem = (code, kind, generateId = () => nanoid(6)) => {
|
|
|
1560
1558
|
//#endregion
|
|
1561
1559
|
export { extractNodeValue as A, getStructuredValue as C, readNodeBindings as D, parseBindingExpression as E, parseArrayExpression as M, parseValue as N, resolveBindings as O, unwrapExpression as P, getRegistryBindings as S, parseBinding as T, clearExtractCache as _, parseItems as a, getCurrentValue as b, updateArrayItemValue as c, update as d, updateAll as f, moveSelectedIndices as g, getChildrenSignatures as h, moveArrayItems as i, extractObjectProperties as j, canLosslesslyEvaluateSource as k, canStructurallyEditArray as l, createNodeFromValue as m, duplicateArrayItems as n, removeArrayItems as o, arrayExpressionToCode as p, moveArrayItem as r, updateArrayItemProperty as s, appendArrayItem as t, bulkUpdate as u, extract as v, isComponentTagName as w, getKeyBindings as x, findEditableChildren as y };
|
|
1562
1560
|
|
|
1563
|
-
//# sourceMappingURL=items-
|
|
1561
|
+
//# sourceMappingURL=items-BXXtMUNI.js.map
|