@jbpark/live-editor 3.0.1 → 3.1.0
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.ko.md +3 -2
- package/README.md +3 -2
- package/dist/{ast-D6R-dsk0.js → ast-CIe-mhh_.js} +416 -177
- package/dist/ast-CIe-mhh_.js.map +1 -0
- package/dist/{boundary-BF7iZp6e.js → boundary-BTP1nfG6.js} +2 -2
- package/dist/{boundary-BF7iZp6e.js.map → boundary-BTP1nfG6.js.map} +1 -1
- package/dist/{context-DH70wj9d.js → context-649REFsj.js} +2 -2
- package/dist/{context-DH70wj9d.js.map → context-649REFsj.js.map} +1 -1
- package/dist/core-D3q5rpuz.js +77 -0
- package/dist/core-D3q5rpuz.js.map +1 -0
- package/dist/dnd/index.d.ts +2 -2
- package/dist/dnd/index.js +2 -2
- package/dist/{dnd-CZJjzuTC.js → dnd-BnXoytb5.js} +385 -398
- package/dist/dnd-BnXoytb5.js.map +1 -0
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/index.js +2 -2
- package/dist/{editor-Ct9wuhLm.js → editor-DQSoTCe8.js} +2 -2
- package/dist/{editor-Ct9wuhLm.js.map → editor-DQSoTCe8.js.map} +1 -1
- package/dist/error/index.js +2 -2
- package/dist/{error-lsJey-it.js → error-CO0EbMlA.js} +2 -2
- package/dist/{error-lsJey-it.js.map → error-CO0EbMlA.js.map} +1 -1
- package/dist/{index-C4TBkJBG.d.ts → index-Ck3akHag.d.ts} +2 -2
- package/dist/{index-Bqc5kUAG.d.ts → index-DswWDEXZ.d.ts} +27 -3
- package/dist/{index-GuEiafMN.d.ts → index-DxbG789f.d.ts} +25 -2
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -5
- package/dist/preview/index.js +1 -1
- package/dist/{preview-CNVXyDgY.js → preview-DFH-z_JL.js} +4 -4
- package/dist/{preview-CNVXyDgY.js.map → preview-DFH-z_JL.js.map} +1 -1
- package/dist/provider/index.js +1 -1
- package/dist/style.css +105 -123
- package/dist/{use-dynamic-tailwind-C0Onss1A.js → use-dynamic-tailwind-DqqQu2de.js} +2 -2
- package/dist/{use-dynamic-tailwind-C0Onss1A.js.map → use-dynamic-tailwind-DqqQu2de.js.map} +1 -1
- package/dist/utils/ast/index.d.ts +2 -2
- package/dist/utils/ast/index.js +2 -2
- package/dist/utils/index.js +1 -1
- package/dist/{utils-BwEgY5pe.js → utils-WyxPYZGh.js} +12 -10
- package/dist/{utils-BwEgY5pe.js.map → utils-WyxPYZGh.js.map} +1 -1
- package/package.json +2 -2
- package/dist/ast-D6R-dsk0.js.map +0 -1
- package/dist/core-CbuS_p_d.js +0 -123
- package/dist/core-CbuS_p_d.js.map +0 -1
- package/dist/dnd-CZJjzuTC.js.map +0 -1
|
@@ -453,42 +453,164 @@ const moveSelectedIndices = (items, indices, direction) => {
|
|
|
453
453
|
};
|
|
454
454
|
};
|
|
455
455
|
//#endregion
|
|
456
|
-
//#region src/utils/ast/
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
456
|
+
//#region src/utils/ast/patch.ts
|
|
457
|
+
const hasOnlyLayoutNewlines = (content) => {
|
|
458
|
+
let index = 0;
|
|
459
|
+
while (index < content.length) {
|
|
460
|
+
const char = content[index];
|
|
461
|
+
if (char === "`" || char === "<") return false;
|
|
462
|
+
if (char === "\"" || char === "'") {
|
|
463
|
+
const next = skipStringLiteral(content, index);
|
|
464
|
+
if (next === -1) return false;
|
|
465
|
+
index = next;
|
|
466
|
+
continue;
|
|
467
|
+
}
|
|
468
|
+
if (char === "/") {
|
|
469
|
+
const following = content[index + 1];
|
|
470
|
+
if (following === "/") {
|
|
471
|
+
const lineEnd = content.indexOf("\n", index + 2);
|
|
472
|
+
index = lineEnd === -1 ? content.length : lineEnd;
|
|
473
|
+
continue;
|
|
474
|
+
}
|
|
475
|
+
if (following === "*") {
|
|
476
|
+
const commentEnd = content.indexOf("*/", index + 2);
|
|
477
|
+
if (commentEnd === -1) return false;
|
|
478
|
+
index = commentEnd + 2;
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
return false;
|
|
482
|
+
}
|
|
483
|
+
index++;
|
|
484
|
+
}
|
|
485
|
+
return true;
|
|
461
486
|
};
|
|
462
|
-
const
|
|
463
|
-
|
|
464
|
-
|
|
487
|
+
const skipStringLiteral = (content, start) => {
|
|
488
|
+
const quote = content[start];
|
|
489
|
+
for (let index = start + 1; index < content.length; index++) {
|
|
490
|
+
const char = content[index];
|
|
491
|
+
if (char === "\\") {
|
|
492
|
+
const escaped = content[index + 1];
|
|
493
|
+
if (escaped === "\n" || escaped === "\r") return -1;
|
|
494
|
+
index++;
|
|
495
|
+
continue;
|
|
496
|
+
}
|
|
497
|
+
if (char === quote) return index + 1;
|
|
498
|
+
if (char === "\n") return -1;
|
|
499
|
+
}
|
|
500
|
+
return -1;
|
|
501
|
+
};
|
|
502
|
+
const lineIndentAt = (source, offset) => {
|
|
503
|
+
const lineStart = source.lastIndexOf("\n", offset - 1) + 1;
|
|
504
|
+
return /^[ \t]*/.exec(source.slice(lineStart, offset))?.[0] ?? "";
|
|
505
|
+
};
|
|
506
|
+
const lineTerminatorOf = (source) => {
|
|
507
|
+
return source.includes("\r\n") ? "\r\n" : "\n";
|
|
508
|
+
};
|
|
509
|
+
const applyEdits = (source, edits) => {
|
|
510
|
+
if (edits.length === 0) return source;
|
|
511
|
+
const ordered = [...edits].sort((a, b) => a.start - b.start || a.end - b.end);
|
|
512
|
+
for (const edit of ordered) if (!Number.isInteger(edit.start) || !Number.isInteger(edit.end) || edit.start < 0 || edit.end > source.length || edit.start > edit.end) throw new Error(`Invalid source edit [${edit.start}, ${edit.end}) for a source of length ${source.length}`);
|
|
513
|
+
for (let i = 1; i < ordered.length; i++) {
|
|
514
|
+
const previous = ordered[i - 1];
|
|
515
|
+
const current = ordered[i];
|
|
516
|
+
if (current.start < previous.end) throw new Error(`Overlapping source edits: [${previous.start}, ${previous.end}) and [${current.start}, ${current.end})`);
|
|
517
|
+
}
|
|
518
|
+
let result = "";
|
|
519
|
+
let cursor = 0;
|
|
520
|
+
const terminator = lineTerminatorOf(source);
|
|
521
|
+
for (const edit of ordered) {
|
|
522
|
+
const content = edit.indent && edit.content.includes("\n") && hasOnlyLayoutNewlines(edit.content) ? edit.content.replace(/\n/g, `${terminator}${lineIndentAt(source, edit.start)}`) : edit.content;
|
|
523
|
+
result += source.slice(cursor, edit.start) + content;
|
|
524
|
+
cursor = edit.end;
|
|
525
|
+
}
|
|
526
|
+
return result + source.slice(cursor);
|
|
527
|
+
};
|
|
528
|
+
//#endregion
|
|
529
|
+
//#region src/utils/ast/array-source.ts
|
|
530
|
+
const commaIn = (source, start, end) => {
|
|
531
|
+
let comma = null;
|
|
532
|
+
for (let at = start; at < end; at++) {
|
|
533
|
+
if (/\s/.test(source[at])) continue;
|
|
534
|
+
if (source.startsWith("/*", at)) {
|
|
535
|
+
const close = source.indexOf("*/", at + 2);
|
|
536
|
+
if (close < 0 || close + 2 > end) return null;
|
|
537
|
+
at = close + 1;
|
|
538
|
+
} else if (source.startsWith("//", at)) {
|
|
539
|
+
const newline = source.indexOf("\n", at + 2);
|
|
540
|
+
at = newline < 0 ? end : newline;
|
|
541
|
+
} else if (source[at] === "," && comma === null) comma = at;
|
|
542
|
+
else return null;
|
|
543
|
+
}
|
|
544
|
+
return comma;
|
|
545
|
+
};
|
|
546
|
+
const denseArraySource = (source) => {
|
|
547
|
+
const array = parseArrayExpression(source);
|
|
548
|
+
if (!array || array.elements.some((node) => !import_lib$2.isExpression(node) || node.extra?.parenthesized)) return null;
|
|
549
|
+
const elements = array.elements;
|
|
550
|
+
const commas = elements.slice(0, -1).map((node, index) => commaIn(source, node.end, elements[index + 1].start));
|
|
551
|
+
if (commas.some((comma) => comma === null)) return null;
|
|
552
|
+
const last = elements.at(-1);
|
|
553
|
+
return {
|
|
554
|
+
array,
|
|
555
|
+
elements,
|
|
556
|
+
commas,
|
|
557
|
+
trailing: last ? commaIn(source, last.end, array.end - 1) : null
|
|
558
|
+
};
|
|
559
|
+
};
|
|
560
|
+
const validArrayIndices = (indices, length) => [...indices].every((index) => Number.isInteger(index) && index >= 0 && index < length);
|
|
561
|
+
const reorderArraySource = (source, elements, next) => applyEdits(source, elements.map((node, index) => ({
|
|
562
|
+
start: node.start,
|
|
563
|
+
end: node.end,
|
|
564
|
+
content: source.slice(next[index].start, next[index].end)
|
|
565
|
+
})));
|
|
566
|
+
const removeArraySource = (source, data, indices) => {
|
|
567
|
+
const edits = [];
|
|
568
|
+
const removedCommas = /* @__PURE__ */ new Set();
|
|
569
|
+
const { elements, commas, trailing } = data;
|
|
570
|
+
for (let index = 0; index < elements.length; index++) {
|
|
571
|
+
if (!indices.has(index)) continue;
|
|
572
|
+
const start = index;
|
|
573
|
+
while (index + 1 < elements.length && indices.has(index + 1)) index++;
|
|
574
|
+
for (let current = start; current <= index; current++) {
|
|
575
|
+
const node = elements[current];
|
|
576
|
+
edits.push({
|
|
577
|
+
start: node.start,
|
|
578
|
+
end: node.end,
|
|
579
|
+
content: ""
|
|
580
|
+
});
|
|
581
|
+
if (current < elements.length - 1) removedCommas.add(commas[current]);
|
|
582
|
+
}
|
|
583
|
+
if (index === elements.length - 1) {
|
|
584
|
+
if (trailing !== null) removedCommas.add(trailing);
|
|
585
|
+
else if (start > 0) removedCommas.add(commas[start - 1]);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
for (const comma of removedCommas) edits.push({
|
|
589
|
+
start: comma,
|
|
590
|
+
end: comma + 1,
|
|
591
|
+
content: ""
|
|
465
592
|
});
|
|
593
|
+
return applyEdits(source, edits);
|
|
466
594
|
};
|
|
467
|
-
const
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
595
|
+
const appendArraySource = (source, data, copies) => {
|
|
596
|
+
const last = data.elements.at(-1);
|
|
597
|
+
if (!last || copies.length === 0) return source;
|
|
598
|
+
return applyEdits(source, [{
|
|
599
|
+
start: last.end,
|
|
600
|
+
end: last.end,
|
|
601
|
+
content: `, ${copies.join(", ")}`
|
|
602
|
+
}]);
|
|
472
603
|
};
|
|
473
604
|
//#endregion
|
|
474
605
|
//#region src/utils/ast/items.ts
|
|
475
|
-
const elementsOf = (code) =>
|
|
476
|
-
const ast = parseArrayExpression(code);
|
|
477
|
-
if (!ast) return null;
|
|
478
|
-
return ast.elements.filter((element) => Boolean(element));
|
|
479
|
-
};
|
|
606
|
+
const elementsOf = (code) => parseArrayExpression(code)?.elements ?? null;
|
|
480
607
|
const kindOf = (element) => import_lib$2.isObjectExpression(element) ? "object" : "primitive";
|
|
481
|
-
const toCode = (elements) => {
|
|
482
|
-
return generateCode(import_lib$2.arrayExpression(elements));
|
|
483
|
-
};
|
|
484
608
|
const parseItems = (code) => {
|
|
485
|
-
|
|
486
|
-
if (!elements) return null;
|
|
487
|
-
return elements.map((node, index) => ({
|
|
609
|
+
return elementsOf(code)?.flatMap((node, index) => import_lib$2.isExpression(node) ? [{
|
|
488
610
|
index,
|
|
489
611
|
kind: kindOf(node),
|
|
490
612
|
node
|
|
491
|
-
})
|
|
613
|
+
}] : []) ?? null;
|
|
492
614
|
};
|
|
493
615
|
const resolveRenderLeaf = (render, key) => {
|
|
494
616
|
const leaf = render?.[key];
|
|
@@ -542,79 +664,104 @@ const updateArrayItemProperty = (code, index, key, value, render) => {
|
|
|
542
664
|
const declaredType = extractObjectProperties(element)[key]?.type ?? "string";
|
|
543
665
|
const nextValue = buildPropertyValue(value, declaredType, resolveRenderLeaf(render, key), target.value);
|
|
544
666
|
if (!nextValue) return null;
|
|
545
|
-
|
|
546
|
-
|
|
667
|
+
let serialized = typeof value === "string" && (declaredType === "array" || declaredType === "object" || import_lib$2.isJSXElement(nextValue) || import_lib$2.isJSXFragment(nextValue)) ? value.trim() : generateCode(nextValue);
|
|
668
|
+
if (nextValue.trailingComments?.some((comment) => comment.type === "CommentLine")) serialized += "\n";
|
|
669
|
+
const content = target.shorthand ? `${key}: ${serialized}` : serialized;
|
|
670
|
+
return applyEdits(code, [{
|
|
671
|
+
start: target.value.start,
|
|
672
|
+
end: target.value.end,
|
|
673
|
+
content
|
|
674
|
+
}]);
|
|
547
675
|
};
|
|
548
676
|
const updateArrayItemValue = (code, index, value) => {
|
|
549
677
|
const elements = elementsOf(code);
|
|
550
678
|
const element = elements?.[index];
|
|
551
|
-
if (!elements || !element) return null;
|
|
679
|
+
if (!elements || !import_lib$2.isExpression(element)) return null;
|
|
552
680
|
const nextValue = createNodeFromValue(extractNodeValue(element).type, parseValue(value));
|
|
553
681
|
if (!nextValue) return null;
|
|
554
|
-
|
|
555
|
-
|
|
682
|
+
return applyEdits(code, [{
|
|
683
|
+
start: element.start,
|
|
684
|
+
end: element.end,
|
|
685
|
+
content: generateCode(nextValue)
|
|
686
|
+
}]);
|
|
556
687
|
};
|
|
557
688
|
const moveArrayItem = (code, from, to) => {
|
|
558
|
-
const
|
|
559
|
-
if (!
|
|
560
|
-
const next = [...elements];
|
|
689
|
+
const data = denseArraySource(code);
|
|
690
|
+
if (!data || !validArrayIndices([from], data.elements.length) || !Number.isInteger(to)) return null;
|
|
691
|
+
const next = [...data.elements];
|
|
561
692
|
const [moved] = next.splice(from, 1);
|
|
562
693
|
next.splice(to, 0, moved);
|
|
563
|
-
return
|
|
694
|
+
return reorderArraySource(code, data.elements, next);
|
|
564
695
|
};
|
|
565
696
|
const moveArrayItems = (code, indices, direction) => {
|
|
566
|
-
const
|
|
567
|
-
if (!elements) return null;
|
|
568
|
-
const
|
|
697
|
+
const data = denseArraySource(code);
|
|
698
|
+
if (!data || !validArrayIndices(indices, data.elements.length) || !["up", "down"].includes(direction)) return null;
|
|
699
|
+
const next = moveSelectedIndices(data.elements, indices, direction);
|
|
569
700
|
return {
|
|
570
|
-
code:
|
|
571
|
-
indices:
|
|
701
|
+
code: reorderArraySource(code, data.elements, next.items),
|
|
702
|
+
indices: next.indices
|
|
572
703
|
};
|
|
573
704
|
};
|
|
574
705
|
const removeArrayItems = (code, indices, kind) => {
|
|
575
|
-
const
|
|
576
|
-
if (!elements) return null;
|
|
577
|
-
const remaining = removeIndices(elements, indices);
|
|
578
|
-
if ((kind === void 0 ? remaining : remaining.filter((
|
|
579
|
-
return
|
|
580
|
-
};
|
|
581
|
-
const
|
|
582
|
-
const
|
|
583
|
-
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
706
|
+
const data = denseArraySource(code);
|
|
707
|
+
if (!data || !validArrayIndices(indices, data.elements.length)) return null;
|
|
708
|
+
const remaining = removeIndices(data.elements, indices);
|
|
709
|
+
if (!(kind === void 0 ? remaining : remaining.filter((node) => kindOf(node) === kind)).length) return null;
|
|
710
|
+
return removeArraySource(code, data, indices);
|
|
711
|
+
};
|
|
712
|
+
const copyItem = (code, element, generateId, usedIds) => {
|
|
713
|
+
const edits = [];
|
|
714
|
+
let unsupported = false;
|
|
715
|
+
const reserveId = (id) => {
|
|
716
|
+
if (usedIds.has(id)) unsupported = true;
|
|
717
|
+
usedIds.add(id);
|
|
718
|
+
return JSON.stringify(id);
|
|
719
|
+
};
|
|
720
|
+
import_lib$2.traverseFast(element, (node) => {
|
|
721
|
+
if (!import_lib$2.isJSXOpeningElement(node)) return;
|
|
722
|
+
const ids = node.attributes.filter((attr) => import_lib$2.isJSXAttribute(attr) && import_lib$2.isJSXIdentifier(attr.name, { name: "data-id" }));
|
|
723
|
+
const attr = ids[0];
|
|
724
|
+
if (ids.length > 1 || attr && (!import_lib$2.isStringLiteral(attr.value) || node.attributes.slice(node.attributes.indexOf(attr) + 1).some((a) => import_lib$2.isJSXSpreadAttribute(a)))) {
|
|
725
|
+
unsupported = true;
|
|
590
726
|
return;
|
|
591
727
|
}
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
}
|
|
728
|
+
if (attr && import_lib$2.isStringLiteral(attr.value)) edits.push({
|
|
729
|
+
start: attr.value.start,
|
|
730
|
+
end: attr.value.end,
|
|
731
|
+
content: reserveId(generateId())
|
|
732
|
+
});
|
|
597
733
|
});
|
|
598
|
-
|
|
734
|
+
if (import_lib$2.isObjectExpression(element)) {
|
|
735
|
+
const keys = element.properties.filter((prop) => import_lib$2.isObjectProperty(prop) && !prop.computed && (import_lib$2.isIdentifier(prop.key, { name: "key" }) || import_lib$2.isStringLiteral(prop.key, { value: "key" })));
|
|
736
|
+
const key = keys[0];
|
|
737
|
+
if (keys.length > 1 || key && (!import_lib$2.isStringLiteral(key.value) || element.properties.slice(element.properties.indexOf(key) + 1).some((prop) => import_lib$2.isSpreadElement(prop) || "computed" in prop && prop.computed))) return null;
|
|
738
|
+
if (key && import_lib$2.isStringLiteral(key.value)) edits.push({
|
|
739
|
+
start: key.value.start,
|
|
740
|
+
end: key.value.end,
|
|
741
|
+
content: reserveId(`${key.value.value}-${generateId()}`)
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
if (unsupported) return null;
|
|
745
|
+
return applyEdits(code.slice(element.start, element.end), edits.map((edit) => ({
|
|
746
|
+
...edit,
|
|
747
|
+
start: edit.start - element.start,
|
|
748
|
+
end: edit.end - element.start
|
|
749
|
+
})));
|
|
599
750
|
};
|
|
600
751
|
const duplicateArrayItems = (code, indices, generateId = () => nanoid(6)) => {
|
|
601
|
-
const
|
|
602
|
-
if (!elements) return null;
|
|
603
|
-
const
|
|
604
|
-
|
|
605
|
-
|
|
752
|
+
const data = denseArraySource(code);
|
|
753
|
+
if (!data || !indices.size || !validArrayIndices(indices, data.elements.length)) return null;
|
|
754
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
755
|
+
import_lib$2.traverseFast(data.array, (node) => {
|
|
756
|
+
if (import_lib$2.isJSXAttribute(node) && import_lib$2.isJSXIdentifier(node.name, { name: "data-id" }) && import_lib$2.isStringLiteral(node.value)) usedIds.add(node.value.value);
|
|
757
|
+
else if (import_lib$2.isObjectProperty(node) && !node.computed && (import_lib$2.isIdentifier(node.key, { name: "key" }) || import_lib$2.isStringLiteral(node.key, { value: "key" })) && import_lib$2.isStringLiteral(node.value)) usedIds.add(node.value.value);
|
|
758
|
+
});
|
|
759
|
+
const copies = [...indices].sort((a, b) => a - b).map((index) => copyItem(code, data.elements[index], generateId, usedIds));
|
|
760
|
+
return copies.every((copy) => copy !== null) ? appendArraySource(code, data, copies) : null;
|
|
606
761
|
};
|
|
607
762
|
const appendArrayItem = (code, kind, generateId = () => nanoid(6)) => {
|
|
608
|
-
const
|
|
609
|
-
|
|
610
|
-
const template = elements.find((element) => kindOf(element) === kind);
|
|
611
|
-
if (!template) return null;
|
|
612
|
-
if (kind === "primitive") {
|
|
613
|
-
const { type, value } = extractNodeValue(template);
|
|
614
|
-
const next = createNodeFromValue(type, value);
|
|
615
|
-
return next ? toCode([...elements, next]) : null;
|
|
616
|
-
}
|
|
617
|
-
return toCode([...elements, cloneItem(template, generateId)]);
|
|
763
|
+
const index = denseArraySource(code)?.elements.findIndex((node) => kindOf(node) === kind) ?? -1;
|
|
764
|
+
return index < 0 ? null : duplicateArrayItems(code, /* @__PURE__ */ new Set([index]), generateId);
|
|
618
765
|
};
|
|
619
766
|
//#endregion
|
|
620
767
|
//#region src/utils/ast/extract.ts
|
|
@@ -647,7 +794,7 @@ const parseJSXName = (tagName) => {
|
|
|
647
794
|
return expr;
|
|
648
795
|
};
|
|
649
796
|
const extractCache = createBoundedCache(CONFIG.CACHE_LIMIT);
|
|
650
|
-
const extractAttributes = (attributes) => {
|
|
797
|
+
const extractAttributes = (attributes, source) => {
|
|
651
798
|
const allAttrs = [];
|
|
652
799
|
const dataAttrs = [];
|
|
653
800
|
for (const attr of attributes) {
|
|
@@ -660,7 +807,9 @@ const extractAttributes = (attributes) => {
|
|
|
660
807
|
value = attr.value.value;
|
|
661
808
|
isStringLiteral = true;
|
|
662
809
|
} else if (import_lib$2.isJSXExpressionContainer(attr.value)) try {
|
|
663
|
-
|
|
810
|
+
const expression = attr.value.expression;
|
|
811
|
+
const structural = import_lib$2.isArrayExpression(unwrapExpression(expression)) || import_lib$2.isObjectExpression(unwrapExpression(expression));
|
|
812
|
+
value = source && structural && expression.start != null && expression.end != null ? source.slice(expression.start, expression.end) : generateCode(expression);
|
|
664
813
|
isStringLiteral = false;
|
|
665
814
|
} catch {
|
|
666
815
|
value = null;
|
|
@@ -736,15 +885,18 @@ const createFragmentNode = (textContent, children) => ({
|
|
|
736
885
|
children,
|
|
737
886
|
isFragment: true
|
|
738
887
|
});
|
|
739
|
-
const processChildrenBinding = (jsxElement, processedNodes, shouldWrap = true) => {
|
|
888
|
+
const processChildrenBinding = (jsxElement, processedNodes, shouldWrap = true, source) => {
|
|
740
889
|
const jsxChildren = jsxElement.children.filter((child) => import_lib$2.isJSXElement(child) || import_lib$2.isJSXFragment(child));
|
|
741
890
|
if (!jsxChildren.length) return;
|
|
742
891
|
const childrenNodes = [];
|
|
743
892
|
jsxChildren.forEach((child) => {
|
|
744
893
|
if (import_lib$2.isJSXElement(child)) {
|
|
745
|
-
const childResults = extractFromNode(child, processedNodes);
|
|
894
|
+
const childResults = extractFromNode(child, processedNodes, source);
|
|
746
895
|
if (shouldWrap) {
|
|
747
896
|
const wrapperNode = createWrapperNode(collectText(child.children), childResults);
|
|
897
|
+
wrapperNode.source = source?.slice(child.start, child.end);
|
|
898
|
+
const dataId = childResults[0]?.dataAttributes.find((attr) => attr.name === DATA_ATTR.ID)?.value;
|
|
899
|
+
if (dataId) wrapperNode.id = `child:${dataId}`;
|
|
748
900
|
childrenNodes.push(wrapperNode);
|
|
749
901
|
} else childrenNodes.push(...childResults);
|
|
750
902
|
} else if (import_lib$2.isJSXFragment(child)) {
|
|
@@ -752,12 +904,13 @@ const processChildrenBinding = (jsxElement, processedNodes, shouldWrap = true) =
|
|
|
752
904
|
const fragmentChildren = [];
|
|
753
905
|
child.children.forEach((fragmentChild) => {
|
|
754
906
|
if (import_lib$2.isJSXElement(fragmentChild)) {
|
|
755
|
-
const childResults = extractFromNode(fragmentChild, processedNodes);
|
|
907
|
+
const childResults = extractFromNode(fragmentChild, processedNodes, source);
|
|
756
908
|
fragmentChildren.push(...childResults);
|
|
757
909
|
}
|
|
758
910
|
});
|
|
759
911
|
if (fragmentChildren.length) {
|
|
760
912
|
const fragmentNode = createFragmentNode(collectText(child.children), fragmentChildren);
|
|
913
|
+
fragmentNode.source = source?.slice(child.start, child.end);
|
|
761
914
|
childrenNodes.push(fragmentNode);
|
|
762
915
|
}
|
|
763
916
|
}
|
|
@@ -788,10 +941,10 @@ const getBindingExpression = (opening) => {
|
|
|
788
941
|
}
|
|
789
942
|
return null;
|
|
790
943
|
};
|
|
791
|
-
const readNodeBindingInfo = (node) => {
|
|
944
|
+
const readNodeBindingInfo = (node, source) => {
|
|
792
945
|
const opening = node.openingElement;
|
|
793
946
|
const tagName = getTagName(opening);
|
|
794
|
-
const { allAttrs, dataAttrs } = extractAttributes(opening.attributes);
|
|
947
|
+
const { allAttrs, dataAttrs } = extractAttributes(opening.attributes, source);
|
|
795
948
|
const bindingAttr = dataAttrs.find((attr) => attr.name === DATA_ATTR.BINDING);
|
|
796
949
|
const bindingExpr = getBindingExpression(opening);
|
|
797
950
|
const bindings = bindingExpr ? parseBindingExpression(bindingExpr) : bindingAttr?.value ? parseBinding(bindingAttr.value) : [];
|
|
@@ -821,10 +974,10 @@ const parseToNodes = (raw) => {
|
|
|
821
974
|
const processedNodes = /* @__PURE__ */ new WeakSet();
|
|
822
975
|
traverse(ast, { JSXElement(path) {
|
|
823
976
|
if (processedNodes.has(path.node)) return;
|
|
824
|
-
const { tagName, allAttrs, dataAttrs, bindings, childrenBinding, arrayBindings, rawChildren } = readNodeBindingInfo(path.node);
|
|
977
|
+
const { tagName, allAttrs, dataAttrs, bindings, childrenBinding, arrayBindings, rawChildren } = readNodeBindingInfo(path.node, wrapped);
|
|
825
978
|
if (!tagName || !dataAttrs.length) return;
|
|
826
979
|
let childrenNodes;
|
|
827
|
-
if (childrenBinding) childrenNodes = processChildrenBinding(path.node, processedNodes);
|
|
980
|
+
if (childrenBinding) childrenNodes = processChildrenBinding(path.node, processedNodes, true, wrapped);
|
|
828
981
|
for (const arrayBinding of arrayBindings) skipItemsChildren(path.node, processedNodes, arrayBinding.property);
|
|
829
982
|
results.push({
|
|
830
983
|
tagName,
|
|
@@ -854,12 +1007,12 @@ function extract(raw) {
|
|
|
854
1007
|
extractCache.set(raw, results);
|
|
855
1008
|
return results;
|
|
856
1009
|
}
|
|
857
|
-
function extractFromNode(node, processedNodes) {
|
|
1010
|
+
function extractFromNode(node, processedNodes, source) {
|
|
858
1011
|
processedNodes?.add(node);
|
|
859
|
-
const { tagName, allAttrs, dataAttrs, bindings, childrenBinding, rawChildren } = readNodeBindingInfo(node);
|
|
1012
|
+
const { tagName, allAttrs, dataAttrs, bindings, childrenBinding, rawChildren } = readNodeBindingInfo(node, source);
|
|
860
1013
|
let childrenNodes;
|
|
861
|
-
if (childrenBinding) childrenNodes = processChildrenBinding(node, processedNodes);
|
|
862
|
-
if (!childrenNodes) childrenNodes = processChildrenBinding(node, processedNodes, false);
|
|
1014
|
+
if (childrenBinding) childrenNodes = processChildrenBinding(node, processedNodes, true, source);
|
|
1015
|
+
if (!childrenNodes) childrenNodes = processChildrenBinding(node, processedNodes, false, source);
|
|
863
1016
|
return [{
|
|
864
1017
|
tagName,
|
|
865
1018
|
attributes: allAttrs,
|
|
@@ -874,77 +1027,150 @@ function clearExtractCache() {
|
|
|
874
1027
|
extractCache.clear();
|
|
875
1028
|
}
|
|
876
1029
|
//#endregion
|
|
877
|
-
//#region src/utils/ast/
|
|
878
|
-
const
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
1030
|
+
//#region src/utils/ast/children.ts
|
|
1031
|
+
const modeledSignatures = (nodes) => nodes.map((node) => {
|
|
1032
|
+
const jsx = nodeToJSX(node);
|
|
1033
|
+
if (!jsx) throw new Error("Invalid child node");
|
|
1034
|
+
return generateCode(jsx);
|
|
1035
|
+
});
|
|
1036
|
+
const getChildrenSignatures = (nodes) => {
|
|
1037
|
+
const modeled = modeledSignatures(nodes);
|
|
1038
|
+
return nodes.map((node, index) => JSON.stringify([node.source ?? null, modeled[index]]));
|
|
1039
|
+
};
|
|
1040
|
+
const indicesAreValid = (indices, count) => Array.isArray(indices) && new Set(indices).size === indices.length && indices.every((index) => Number.isInteger(index) && index >= 0 && index < count);
|
|
1041
|
+
const copySource = (source, usedIds) => {
|
|
1042
|
+
const node = (0, import_lib$1.parseExpression)(source, { plugins: ["jsx", "typescript"] });
|
|
1043
|
+
const edits = [];
|
|
1044
|
+
const newId = () => {
|
|
1045
|
+
let id = nanoid(12);
|
|
1046
|
+
while (usedIds.has(id)) id = nanoid(12);
|
|
1047
|
+
usedIds.add(id);
|
|
1048
|
+
return id;
|
|
1049
|
+
};
|
|
1050
|
+
import_lib$2.traverseFast(node, (child) => {
|
|
1051
|
+
if (!import_lib$2.isJSXOpeningElement(child)) return;
|
|
1052
|
+
const ids = child.attributes.filter((attr) => import_lib$2.isJSXAttribute(attr) && import_lib$2.isJSXIdentifier(attr.name, { name: "data-id" }));
|
|
1053
|
+
if (ids.length > 1) throw new Error("Duplicate data-id attributes");
|
|
1054
|
+
const attr = ids[0];
|
|
1055
|
+
if (attr && child.attributes.slice(child.attributes.indexOf(attr) + 1).some((attribute) => import_lib$2.isJSXSpreadAttribute(attribute))) throw new Error("A spread may override the copied data-id");
|
|
1056
|
+
if (attr) {
|
|
1057
|
+
const value = attr.value;
|
|
1058
|
+
if (!import_lib$2.isStringLiteral(value) || value.start == null || value.end == null) throw new Error("Cannot copy a dynamic data-id");
|
|
1059
|
+
edits.push({
|
|
1060
|
+
start: value.start,
|
|
1061
|
+
end: value.end,
|
|
1062
|
+
content: JSON.stringify(newId())
|
|
1063
|
+
});
|
|
1064
|
+
} else {
|
|
1065
|
+
const at = child.attributes.at(-1)?.end ?? child.name.end;
|
|
1066
|
+
if (at == null) throw new Error("Missing opening element span");
|
|
1067
|
+
edits.push({
|
|
1068
|
+
start: at,
|
|
1069
|
+
end: at,
|
|
1070
|
+
content: ` data-id="${newId()}"`
|
|
1071
|
+
});
|
|
888
1072
|
}
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1073
|
+
});
|
|
1074
|
+
return applyEdits(source, edits);
|
|
1075
|
+
};
|
|
1076
|
+
const editChildrenSource = (source, parent, input) => {
|
|
1077
|
+
try {
|
|
1078
|
+
if (!parent.closingElement || parent.start == null || parent.end == null) return null;
|
|
1079
|
+
const value = typeof input === "string" ? JSON.parse(input) : input;
|
|
1080
|
+
const children = parent.children.filter((child) => import_lib$2.isJSXElement(child) || import_lib$2.isJSXFragment(child));
|
|
1081
|
+
const raw = children.map((child) => source.slice(child.start, child.end));
|
|
1082
|
+
const models = extract(source.slice(parent.start, parent.end))[0]?.children ?? [];
|
|
1083
|
+
if (models.length !== children.length) return null;
|
|
1084
|
+
const signatures = modeledSignatures(models);
|
|
1085
|
+
const replaceSlots = (next) => {
|
|
1086
|
+
const edits = children.map((child, index) => ({
|
|
1087
|
+
start: child.start,
|
|
1088
|
+
end: child.end,
|
|
1089
|
+
content: next[index] ?? ""
|
|
1090
|
+
}));
|
|
1091
|
+
if (next.length > children.length) {
|
|
1092
|
+
const at = parent.closingElement.start;
|
|
1093
|
+
edits.push({
|
|
1094
|
+
start: at,
|
|
1095
|
+
end: at,
|
|
1096
|
+
content: next.slice(children.length).join("")
|
|
1097
|
+
});
|
|
901
1098
|
}
|
|
902
|
-
return
|
|
1099
|
+
return edits;
|
|
1100
|
+
};
|
|
1101
|
+
if (Array.isArray(value)) {
|
|
1102
|
+
const desired = modeledSignatures(value);
|
|
1103
|
+
const lossless = raw.every((text, index) => generateCode((0, import_lib$1.parseExpression)(text, { plugins: ["jsx", "typescript"] })) === signatures[index]);
|
|
1104
|
+
const consumed = /* @__PURE__ */ new Set();
|
|
1105
|
+
const next = desired.map((signature, position) => {
|
|
1106
|
+
const index = signatures.findIndex((candidate, i) => candidate === signature && !consumed.has(i) && (value[position].source === void 0 || value[position].source === raw[i]));
|
|
1107
|
+
if (index >= 0) {
|
|
1108
|
+
consumed.add(index);
|
|
1109
|
+
return raw[index];
|
|
1110
|
+
}
|
|
1111
|
+
if (!lossless || value[position].source !== void 0 && !raw.includes(value[position].source)) throw new Error("Use children commands to copy or edit unsupported source");
|
|
1112
|
+
return signature;
|
|
1113
|
+
});
|
|
1114
|
+
const countIds = (text) => {
|
|
1115
|
+
const counts = /* @__PURE__ */ new Map();
|
|
1116
|
+
import_lib$2.traverseFast((0, import_lib$1.parseExpression)(text, { plugins: ["jsx", "typescript"] }), (node) => {
|
|
1117
|
+
if (import_lib$2.isJSXAttribute(node) && import_lib$2.isJSXIdentifier(node.name, { name: "data-id" }) && import_lib$2.isStringLiteral(node.value)) counts.set(node.value.value, (counts.get(node.value.value) ?? 0) + 1);
|
|
1118
|
+
});
|
|
1119
|
+
return counts;
|
|
1120
|
+
};
|
|
1121
|
+
const previousIds = countIds(source);
|
|
1122
|
+
if ([...countIds(applyEdits(source, replaceSlots(next)))].some(([id, count]) => count > 1 && count > (previousIds.get(id) ?? 0))) return null;
|
|
1123
|
+
return replaceSlots(next);
|
|
903
1124
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
1125
|
+
const request = value;
|
|
1126
|
+
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;
|
|
1127
|
+
const { action } = request;
|
|
1128
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
1129
|
+
import_lib$2.traverseFast(parent, (node) => {
|
|
1130
|
+
if (import_lib$2.isJSXAttribute(node) && import_lib$2.isJSXIdentifier(node.name, { name: "data-id" }) && import_lib$2.isStringLiteral(node.value)) usedIds.add(node.value.value);
|
|
1131
|
+
});
|
|
1132
|
+
switch (action.type) {
|
|
1133
|
+
case "move": {
|
|
1134
|
+
if (!indicesAreValid([action.from], raw.length) || !indicesAreValid([action.to], raw.length)) return null;
|
|
1135
|
+
const next = [...raw];
|
|
1136
|
+
const [moved] = next.splice(action.from, 1);
|
|
1137
|
+
next.splice(action.to, 0, moved);
|
|
1138
|
+
return replaceSlots(next);
|
|
1139
|
+
}
|
|
1140
|
+
case "move-selected":
|
|
1141
|
+
if (!indicesAreValid(action.indices, raw.length) || !["up", "down"].includes(action.direction)) return null;
|
|
1142
|
+
return replaceSlots(moveSelectedIndices(raw, new Set(action.indices), action.direction).items);
|
|
1143
|
+
case "remove":
|
|
1144
|
+
if (!indicesAreValid(action.indices, raw.length)) return null;
|
|
1145
|
+
return action.indices.map((index) => ({
|
|
1146
|
+
start: children[index].start,
|
|
1147
|
+
end: children[index].end,
|
|
1148
|
+
content: ""
|
|
1149
|
+
}));
|
|
1150
|
+
case "duplicate": {
|
|
1151
|
+
if (!indicesAreValid(action.indices, raw.length)) return null;
|
|
1152
|
+
const content = [...action.indices].sort((a, b) => a - b).map((index) => copySource(raw[index], usedIds)).join("");
|
|
1153
|
+
const at = parent.closingElement.start;
|
|
1154
|
+
return [{
|
|
1155
|
+
start: at,
|
|
1156
|
+
end: at,
|
|
1157
|
+
content
|
|
1158
|
+
}];
|
|
1159
|
+
}
|
|
1160
|
+
case "append": {
|
|
1161
|
+
const content = copySource(raw[0] ?? "<div></div>", usedIds);
|
|
1162
|
+
const at = parent.closingElement.start;
|
|
1163
|
+
return [{
|
|
1164
|
+
start: at,
|
|
1165
|
+
end: at,
|
|
1166
|
+
content
|
|
1167
|
+
}];
|
|
1168
|
+
}
|
|
1169
|
+
default: return null;
|
|
917
1170
|
}
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
}
|
|
921
|
-
return -1;
|
|
922
|
-
};
|
|
923
|
-
const lineIndentAt = (source, offset) => {
|
|
924
|
-
const lineStart = source.lastIndexOf("\n", offset - 1) + 1;
|
|
925
|
-
return /^[ \t]*/.exec(source.slice(lineStart, offset))?.[0] ?? "";
|
|
926
|
-
};
|
|
927
|
-
const lineTerminatorOf = (source) => {
|
|
928
|
-
return source.includes("\r\n") ? "\r\n" : "\n";
|
|
929
|
-
};
|
|
930
|
-
const applyEdits = (source, edits) => {
|
|
931
|
-
if (edits.length === 0) return source;
|
|
932
|
-
const ordered = [...edits].sort((a, b) => a.start - b.start || a.end - b.end);
|
|
933
|
-
for (const edit of ordered) if (!Number.isInteger(edit.start) || !Number.isInteger(edit.end) || edit.start < 0 || edit.end > source.length || edit.start > edit.end) throw new Error(`Invalid source edit [${edit.start}, ${edit.end}) for a source of length ${source.length}`);
|
|
934
|
-
for (let i = 1; i < ordered.length; i++) {
|
|
935
|
-
const previous = ordered[i - 1];
|
|
936
|
-
const current = ordered[i];
|
|
937
|
-
if (current.start < previous.end) throw new Error(`Overlapping source edits: [${previous.start}, ${previous.end}) and [${current.start}, ${current.end})`);
|
|
938
|
-
}
|
|
939
|
-
let result = "";
|
|
940
|
-
let cursor = 0;
|
|
941
|
-
const terminator = lineTerminatorOf(source);
|
|
942
|
-
for (const edit of ordered) {
|
|
943
|
-
const content = edit.indent && edit.content.includes("\n") && hasOnlyLayoutNewlines(edit.content) ? edit.content.replace(/\n/g, `${terminator}${lineIndentAt(source, edit.start)}`) : edit.content;
|
|
944
|
-
result += source.slice(cursor, edit.start) + content;
|
|
945
|
-
cursor = edit.end;
|
|
1171
|
+
} catch {
|
|
1172
|
+
return null;
|
|
946
1173
|
}
|
|
947
|
-
return result + source.slice(cursor);
|
|
948
1174
|
};
|
|
949
1175
|
//#endregion
|
|
950
1176
|
//#region src/utils/ast/update.ts
|
|
@@ -1000,23 +1226,6 @@ const editInnerHTML = (element, value) => {
|
|
|
1000
1226
|
content: value
|
|
1001
1227
|
}];
|
|
1002
1228
|
};
|
|
1003
|
-
const editChildren = (element, value) => {
|
|
1004
|
-
try {
|
|
1005
|
-
const childrenData = typeof value === "string" ? JSON.parse(value) : value;
|
|
1006
|
-
const range = childrenRange(element);
|
|
1007
|
-
if (!range) return [];
|
|
1008
|
-
const content = childrenData.map((childData) => nodeToJSX(childData)).filter((node) => node !== null).map((node) => generateCode(node)).join("");
|
|
1009
|
-
return [{
|
|
1010
|
-
start: range.start,
|
|
1011
|
-
end: range.end,
|
|
1012
|
-
content,
|
|
1013
|
-
indent: true
|
|
1014
|
-
}];
|
|
1015
|
-
} catch (error) {
|
|
1016
|
-
console.error("❌ Children update error:", error);
|
|
1017
|
-
return null;
|
|
1018
|
-
}
|
|
1019
|
-
};
|
|
1020
1229
|
const editRichtext = (element, value) => {
|
|
1021
1230
|
const edits = [];
|
|
1022
1231
|
const range = childrenRange(element);
|
|
@@ -1065,11 +1274,11 @@ const editJsxAttribute = (opening, propertyName, value) => {
|
|
|
1065
1274
|
content: `=${content}`
|
|
1066
1275
|
}];
|
|
1067
1276
|
};
|
|
1068
|
-
const holdsStructuralExpression = (value) => import_lib$2.isJSXExpressionContainer(value) && (import_lib$2.isArrayExpression(value.expression) || import_lib$2.isObjectExpression(value.expression));
|
|
1277
|
+
const holdsStructuralExpression = (value) => import_lib$2.isJSXExpressionContainer(value) && (import_lib$2.isArrayExpression(unwrapExpression(value.expression)) || import_lib$2.isObjectExpression(unwrapExpression(value.expression)));
|
|
1069
1278
|
const structuralSource = (value) => {
|
|
1070
1279
|
try {
|
|
1071
1280
|
const expression = (0, import_lib$1.parseExpression)(value.trim(), { plugins: ["jsx", "typescript"] });
|
|
1072
|
-
return import_lib$2.isArrayExpression(expression) || import_lib$2.isObjectExpression(expression) ? expression : null;
|
|
1281
|
+
return import_lib$2.isArrayExpression(unwrapExpression(expression)) || import_lib$2.isObjectExpression(unwrapExpression(expression)) ? expression : null;
|
|
1073
1282
|
} catch {
|
|
1074
1283
|
return null;
|
|
1075
1284
|
}
|
|
@@ -1097,6 +1306,18 @@ const buildAttributeValue = (value, type, current) => {
|
|
|
1097
1306
|
const editAttribute = (opening, propertyName, value, type) => {
|
|
1098
1307
|
const attribute = findAttribute(opening, propertyName);
|
|
1099
1308
|
if (!attribute || attribute.start == null || attribute.end == null) return null;
|
|
1309
|
+
if (typeof value === "string" && (type === "array" || type === "object" || holdsStructuralExpression(attribute.value) && !(type && STRING_VALUED_TYPES.has(type)))) {
|
|
1310
|
+
const expression = structuralSource(value);
|
|
1311
|
+
if (expression && import_lib$2.isJSXExpressionContainer(attribute.value)) {
|
|
1312
|
+
const text = value.trim();
|
|
1313
|
+
const lineComment = expression.trailingComments?.some((comment) => comment.type === "CommentLine");
|
|
1314
|
+
return [{
|
|
1315
|
+
start: attribute.value.expression.start,
|
|
1316
|
+
end: attribute.value.expression.end,
|
|
1317
|
+
content: `${text}${lineComment ? "\n" : ""}`
|
|
1318
|
+
}];
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1100
1321
|
const content = generateCode(import_lib$2.jsxAttribute(attribute.name, buildAttributeValue(value, type, attribute.value)));
|
|
1101
1322
|
return [{
|
|
1102
1323
|
start: attribute.start,
|
|
@@ -1183,9 +1404,9 @@ const update = (code, dataId, label, value, property) => {
|
|
|
1183
1404
|
}));
|
|
1184
1405
|
break;
|
|
1185
1406
|
case BINDING_PROP.CHILDREN:
|
|
1186
|
-
collect(
|
|
1407
|
+
collect(editChildrenSource(wrapped, path.node, value), () => ({
|
|
1187
1408
|
reason: "parse-error",
|
|
1188
|
-
error: /* @__PURE__ */ new Error(
|
|
1409
|
+
error: /* @__PURE__ */ new Error("Unsupported or stale children edit; source was preserved")
|
|
1189
1410
|
}));
|
|
1190
1411
|
break;
|
|
1191
1412
|
default: collect(propertyBinding.type === "jsx" ? editJsxAttribute(opening, prop, value) : editAttribute(opening, prop, value, propertyBinding.type), () => ({
|
|
@@ -1237,6 +1458,24 @@ const bulkUpdate = (raw, entries) => {
|
|
|
1237
1458
|
};
|
|
1238
1459
|
};
|
|
1239
1460
|
//#endregion
|
|
1461
|
+
//#region src/utils/ast/tree.ts
|
|
1462
|
+
const replaceIds = (code, generateId = () => nanoid(6)) => {
|
|
1463
|
+
return code.replace(new RegExp(`${DATA_ATTR.ID}="[^"]*"`, "g"), () => {
|
|
1464
|
+
return `${DATA_ATTR.ID}="${generateId()}"`;
|
|
1465
|
+
});
|
|
1466
|
+
};
|
|
1467
|
+
const fillIds = (code, generateId = () => nanoid(6)) => {
|
|
1468
|
+
return code.replace(new RegExp(`${DATA_ATTR.ID}=""`, "g"), () => {
|
|
1469
|
+
return `${DATA_ATTR.ID}="${generateId()}"`;
|
|
1470
|
+
});
|
|
1471
|
+
};
|
|
1472
|
+
const clone = (element, generateId = () => nanoid(6)) => {
|
|
1473
|
+
const cloned = import_lib$2.cloneNode(element, true);
|
|
1474
|
+
const generatedCode = generateCode(cloned);
|
|
1475
|
+
const code = replaceIds(generatedCode, generateId);
|
|
1476
|
+
return (0, import_lib$1.parseExpression)(code, { plugins: ["jsx", "typescript"] });
|
|
1477
|
+
};
|
|
1478
|
+
//#endregion
|
|
1240
1479
|
//#region src/utils/ast/validate.ts
|
|
1241
1480
|
const VALID = { valid: true };
|
|
1242
1481
|
const validateBindingValue = (binding, value) => {
|
|
@@ -1286,6 +1525,6 @@ const validateBindingValue = (binding, value) => {
|
|
|
1286
1525
|
return VALID;
|
|
1287
1526
|
};
|
|
1288
1527
|
//#endregion
|
|
1289
|
-
export {
|
|
1528
|
+
export { setEditableValue as A, arrayExpressionToCode as C, flattenEditableValue as D, extractObjectProperties as E, parseArrayExpression as O, parseBindingExpression as S, extractNodeValue as T, updateArrayItemValue as _, bulkUpdate as a, getStructuredValue as b, clearExtractCache as c, duplicateArrayItems as d, moveArrayItem as f, updateArrayItemProperty as g, removeArrayItems as h, replaceIds as i, generateCode as j, parseValue as k, extract as l, parseItems as m, clone as n, update as o, moveArrayItems as p, fillIds as r, getChildrenSignatures as s, validateBindingValue as t, appendArrayItem as u, findEditableChildren as v, createNodeFromValue as w, parseBinding as x, getCurrentValue as y };
|
|
1290
1529
|
|
|
1291
|
-
//# sourceMappingURL=ast-
|
|
1530
|
+
//# sourceMappingURL=ast-CIe-mhh_.js.map
|