@jbpark/live-editor 3.2.1 → 4.0.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.
Files changed (49) hide show
  1. package/dist/ast-CZwpVrJv.js +851 -0
  2. package/dist/ast-CZwpVrJv.js.map +1 -0
  3. package/dist/{boundary-BTP1nfG6.js → boundary-C90q3YsT.js} +8 -7
  4. package/dist/boundary-C90q3YsT.js.map +1 -0
  5. package/dist/{context-649REFsj.js → context-Y-M9fViD.js} +4 -8
  6. package/dist/context-Y-M9fViD.js.map +1 -0
  7. package/dist/{core-D3q5rpuz.js → core-Co8Nlq16.js} +2 -2
  8. package/dist/{core-D3q5rpuz.js.map → core-Co8Nlq16.js.map} +1 -1
  9. package/dist/dnd/index.d.ts +2 -2
  10. package/dist/dnd/index.js +2 -2
  11. package/dist/{dnd-D90jLjLH.js → dnd-ClnGRNaY.js} +353 -319
  12. package/dist/dnd-ClnGRNaY.js.map +1 -0
  13. package/dist/editor/index.js +2 -2
  14. package/dist/{editor-LzqHe_-F.js → editor-COKGtmfE.js} +3 -3
  15. package/dist/{editor-LzqHe_-F.js.map → editor-COKGtmfE.js.map} +1 -1
  16. package/dist/error/index.d.ts +1 -1
  17. package/dist/error/index.js +2 -2
  18. package/dist/{error-CO0EbMlA.js → error-o0SBwtTv.js} +2 -2
  19. package/dist/{error-CO0EbMlA.js.map → error-o0SBwtTv.js.map} +1 -1
  20. package/dist/{document-C6bNHl7l.js → extract-abHYmNsu.js} +927 -42
  21. package/dist/extract-abHYmNsu.js.map +1 -0
  22. package/dist/{index-DxbG789f.d.ts → index-B_p74BRM.d.ts} +29 -14
  23. package/dist/{index-CCynrS6c.d.ts → index-DNNj_0ba.d.ts} +3 -2
  24. package/dist/{index-lgHdCda5.d.ts → index-DQkL37eL.d.ts} +10 -2
  25. package/dist/{index-DswWDEXZ.d.ts → index-Doh4VTXr.d.ts} +65 -35
  26. package/dist/index.d.ts +6 -6
  27. package/dist/index.js +5 -5
  28. package/dist/index.js.map +1 -1
  29. package/dist/preview/index.d.ts +2 -2
  30. package/dist/preview/index.js +3 -2
  31. package/dist/{preview-CWT0lgwq.js → preview-DKyKKcu7.js} +4 -4
  32. package/dist/{preview-CWT0lgwq.js.map → preview-DKyKKcu7.js.map} +1 -1
  33. package/dist/provider/index.js +1 -1
  34. package/dist/{use-dynamic-tailwind-DAhKGsY4.js → use-dynamic-tailwind-BF8TQ3Yy.js} +83 -27
  35. package/dist/use-dynamic-tailwind-BF8TQ3Yy.js.map +1 -0
  36. package/dist/utils/ast/index.d.ts +2 -2
  37. package/dist/utils/ast/index.js +3 -3
  38. package/dist/utils/index.d.ts +4 -7
  39. package/dist/utils/index.js +3 -3
  40. package/dist/{utils-WyxPYZGh.js → utils-BQ7WL7Jh.js} +33 -16
  41. package/dist/{utils-WyxPYZGh.js.map → utils-BQ7WL7Jh.js.map} +1 -1
  42. package/package.json +3 -1
  43. package/dist/ast-Bx2Avo4d.js +0 -1530
  44. package/dist/ast-Bx2Avo4d.js.map +0 -1
  45. package/dist/boundary-BTP1nfG6.js.map +0 -1
  46. package/dist/context-649REFsj.js.map +0 -1
  47. package/dist/dnd-D90jLjLH.js.map +0 -1
  48. package/dist/document-C6bNHl7l.js.map +0 -1
  49. package/dist/use-dynamic-tailwind-DAhKGsY4.js.map +0 -1
@@ -1,3 +1,4 @@
1
+ import { z } from "zod";
1
2
  //#region \0rolldown/runtime.js
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
@@ -84,20 +85,26 @@ const DRAGGABLE_ITEMS = [
84
85
  {
85
86
  label: 'Background Style',
86
87
  property: 'style',
88
+ type: 'object',
89
+ // Types the keys inside the object value; a leaf takes the same
90
+ // fields as a top-level binding.
91
+ render: {
92
+ backgroundColor: { type: 'color', label: 'Background Color' },
93
+ },
94
+ // Not a library field, so it arrives as meta.group.
95
+ group: 'layout',
87
96
  },
88
97
  {
89
98
  label: 'Content Spacing',
90
99
  property: 'size',
91
100
  type: 'number',
92
- widget: 'slider',
101
+ // Constraints the library validates with or without a widget.
93
102
  min: 0,
94
103
  max: 40,
95
- // step/unit aren't fields this library knows about — they
96
- // survive parsing under binding.meta instead of being
97
- // stripped, so a custom panel can read its own
98
- // per-field configuration back out. See #234.
99
- step: 4,
100
- unit: 'px',
104
+ // Presentation only: the built-in panel ignores it and shows a
105
+ // number input; a custom panel can switch on widget.type.
106
+ widget: { type: 'slider', step: 4, unit: 'px' },
107
+ group: 'layout',
101
108
  },
102
109
  ]}
103
110
  style={{
@@ -117,6 +124,8 @@ const DRAGGABLE_ITEMS = [
117
124
  {
118
125
  label: 'Title',
119
126
  property: 'innerText',
127
+ type: 'string',
128
+ required: true,
120
129
  },
121
130
  ]}
122
131
  className={cn(
@@ -148,39 +157,31 @@ const DRAGGABLE_ITEMS = [
148
157
  label: 'Button Text',
149
158
  property: 'innerText',
150
159
  },
160
+ {
161
+ label: 'Button Icon',
162
+ property: 'icon',
163
+ type: 'jsx',
164
+ },
151
165
  {
152
166
  label: 'Button Size',
153
167
  property: 'size',
154
168
  options: [
155
- {
156
- label: 'small',
157
- value: 'small',
158
- },
159
- {
160
- label: 'middle',
161
- value: 'middle',
162
- },
163
- {
164
- label: 'large',
165
- value: 'large',
166
- },
169
+ { label: 'Small', value: 'small' },
170
+ { label: 'Middle', value: 'middle' },
171
+ { label: 'Large', value: 'large' },
167
172
  ],
168
173
  },
169
174
  {
170
175
  label: 'Button Variant',
171
176
  property: 'variant',
172
177
  options: [
173
- {
174
- label: 'default',
175
- value: 'default',
176
- },
177
- {
178
- label: 'outlined',
179
- value: 'outlined',
180
- },
178
+ { label: 'Solid', value: 'solid' },
179
+ { label: 'Outlined', value: 'outlined' },
180
+ { label: 'Filled', value: 'filled' },
181
181
  ],
182
182
  },
183
183
  ]}
184
+ icon={<span>🚀</span>}
184
185
  size="large"
185
186
  variant="solid"
186
187
  className={cn(
@@ -925,7 +926,19 @@ const DRAGGABLE_ITEMS = [
925
926
  >
926
927
  <ui.Marquees
927
928
  data-id=""
928
- data-binding={[{ label: 'Stats Items', property: 'items' }]}
929
+ data-binding={[
930
+ { label: 'Stats Items', property: 'items' },
931
+ {
932
+ label: 'Scroll Speed',
933
+ property: 'speed',
934
+ type: 'number',
935
+ min: 20,
936
+ max: 300,
937
+ // The bare-string form; it arrives as { type: 'slider' }.
938
+ widget: 'slider',
939
+ },
940
+ { label: 'Pause On Hover', property: 'pauseOnHover', type: 'boolean' },
941
+ ]}
929
942
  speed={100}
930
943
  pauseOnHover={true}
931
944
  autoFill={true}
@@ -1098,6 +1111,190 @@ const DRAGGABLE_ITEMS = [
1098
1111
  ]}
1099
1112
  />
1100
1113
  </section>
1114
+ `
1115
+ },
1116
+ {
1117
+ id: "roadmap",
1118
+ name: "Roadmap",
1119
+ code: `
1120
+ <section
1121
+ data-name="Roadmap"
1122
+ className={cn(
1123
+ 'px-5 py-16',
1124
+ //
1125
+ )}
1126
+ >
1127
+ <div
1128
+ className={cn(
1129
+ 'mx-auto max-w-3xl',
1130
+ //
1131
+ )}
1132
+ >
1133
+ <h2
1134
+ data-id=""
1135
+ data-binding={[
1136
+ { label: 'Title', property: 'innerText', required: true },
1137
+ ]}
1138
+ className={cn(
1139
+ 'mb-8 text-center text-4xl font-bold text-gray-800',
1140
+ //
1141
+ )}
1142
+ >
1143
+ Roadmap
1144
+ </h2>
1145
+ <ui.List
1146
+ data-id=""
1147
+ data-binding={[
1148
+ {
1149
+ label: 'Milestones',
1150
+ property: 'data',
1151
+ type: 'array',
1152
+ // One leaf per item key. Each leaf takes the same fields as a
1153
+ // top-level binding, and label falls back to the key.
1154
+ render: {
1155
+ title: {
1156
+ type: 'string',
1157
+ label: 'Title',
1158
+ required: true,
1159
+ },
1160
+ date: { type: 'date', label: 'Release Date', required: true },
1161
+ status: {
1162
+ type: 'string',
1163
+ label: 'Status',
1164
+ options: [
1165
+ { label: 'Planned', value: 'planned' },
1166
+ { label: 'In Progress', value: 'in-progress' },
1167
+ { label: 'Shipped', value: 'shipped' },
1168
+ ],
1169
+ },
1170
+ progress: {
1171
+ type: 'number',
1172
+ label: 'Progress',
1173
+ min: 0,
1174
+ max: 100,
1175
+ widget: { type: 'slider', step: 10, unit: '%' },
1176
+ },
1177
+ color: { type: 'color', label: 'Accent Color' },
1178
+ highlight: { type: 'boolean', label: 'Highlight' },
1179
+ // An object-valued key: its own render map types the keys
1180
+ // inside it, one level further down.
1181
+ link: {
1182
+ type: 'object',
1183
+ label: 'Link',
1184
+ render: {
1185
+ text: { type: 'string', label: 'Link Text' },
1186
+ href: {
1187
+ type: 'url',
1188
+ label: 'Link URL',
1189
+ pattern: '^https://',
1190
+ // Not a library field, so it arrives as meta.hint.
1191
+ hint: 'Must use https',
1192
+ },
1193
+ },
1194
+ },
1195
+ },
1196
+ },
1197
+ ]}
1198
+ data={[
1199
+ {
1200
+ title: 'Visual editing',
1201
+ date: '2026-03-02',
1202
+ status: 'shipped',
1203
+ progress: 100,
1204
+ color: '#22c55e',
1205
+ highlight: false,
1206
+ link: { text: 'Release notes', href: 'https://github.com' },
1207
+ },
1208
+ {
1209
+ title: 'Custom panels',
1210
+ date: '2026-09-26',
1211
+ status: 'in-progress',
1212
+ progress: 60,
1213
+ color: '#6366f1',
1214
+ highlight: true,
1215
+ link: { text: 'Guide', href: 'https://github.com' },
1216
+ },
1217
+ {
1218
+ title: 'Collaboration',
1219
+ date: '2027-01-15',
1220
+ status: 'planned',
1221
+ progress: 0,
1222
+ color: '#f59e0b',
1223
+ highlight: false,
1224
+ link: { text: 'Discussion', href: 'https://github.com' },
1225
+ },
1226
+ ]}
1227
+ itemKey={item => item.title}
1228
+ renderItem={item => (
1229
+ <div
1230
+ className={cn(
1231
+ 'flex items-center gap-4 border-b border-gray-100 py-4',
1232
+ item.highlight && 'rounded-lg bg-indigo-50 px-4',
1233
+ )}
1234
+ >
1235
+ <span
1236
+ className="size-3 shrink-0 rounded-full"
1237
+ style={{ backgroundColor: item.color }}
1238
+ />
1239
+ <div className="min-w-0 flex-1">
1240
+ <p className="font-semibold text-gray-800">{item.title}</p>
1241
+ <p className="text-sm text-gray-500">
1242
+ {item.date} · {item.status}
1243
+ </p>
1244
+ <ui.Progress value={item.progress} className="mt-2" />
1245
+ </div>
1246
+ <a
1247
+ href={item.link.href}
1248
+ className="text-sm text-indigo-500 hover:underline"
1249
+ >
1250
+ {item.link.text}
1251
+ </a>
1252
+ </div>
1253
+ )}
1254
+ />
1255
+ <p
1256
+ className={cn(
1257
+ 'mt-6 text-center text-sm text-gray-500',
1258
+ //
1259
+ )}
1260
+ >
1261
+ Last updated{' '}
1262
+ <time
1263
+ data-id=""
1264
+ data-binding={[
1265
+ {
1266
+ label: 'Updated On',
1267
+ property: 'dateTime',
1268
+ type: 'date',
1269
+ required: true,
1270
+ },
1271
+ { label: 'Updated Text', property: 'innerText' },
1272
+ ]}
1273
+ dateTime="2026-09-26"
1274
+ >
1275
+ September 26, 2026
1276
+ </time>
1277
+ {' · '}
1278
+ <a
1279
+ data-id=""
1280
+ data-binding={[
1281
+ { label: 'Link Text', property: 'innerText' },
1282
+ {
1283
+ label: 'Link URL',
1284
+ property: 'href',
1285
+ type: 'url',
1286
+ required: true,
1287
+ pattern: '^https://',
1288
+ },
1289
+ ]}
1290
+ href="https://github.com/pjb0811/live-editor/releases"
1291
+ className="text-indigo-500 hover:underline"
1292
+ >
1293
+ All releases
1294
+ </a>
1295
+ </p>
1296
+ </div>
1297
+ </section>
1101
1298
  `
1102
1299
  },
1103
1300
  {
@@ -39613,9 +39810,8 @@ var require_lib = /* @__PURE__ */ __commonJSMin(((exports) => {
39613
39810
  }));
39614
39811
  //#endregion
39615
39812
  //#region node_modules/.pnpm/nanoid@3.3.18/node_modules/nanoid/index.browser.js
39616
- var import_lib = require_lib$7();
39617
- var import_lib$2 = /* @__PURE__ */ __toESM(require_lib$4(), 1);
39618
- var import_lib$1 = /* @__PURE__ */ __toESM(require_lib(), 1);
39813
+ var import_lib$1 = require_lib$7();
39814
+ var import_lib$3 = /* @__PURE__ */ __toESM(require_lib$4(), 1);
39619
39815
  let nanoid = (size = 21) => crypto.getRandomValues(new Uint8Array(size)).reduce((id, byte) => {
39620
39816
  byte &= 63;
39621
39817
  if (byte < 36) id += byte.toString(36);
@@ -39674,20 +39870,22 @@ const createBoundedCache = (limit, onEvict) => {
39674
39870
  };
39675
39871
  //#endregion
39676
39872
  //#region src/utils/ast/document.ts
39677
- const traverse = typeof import_lib$1.default === "function" ? import_lib$1.default : import_lib$1.default.default;
39873
+ var import_lib = /* @__PURE__ */ __toESM(require_lib$3(), 1);
39874
+ var import_lib$2 = /* @__PURE__ */ __toESM(require_lib(), 1);
39875
+ const traverse = typeof import_lib$2.default === "function" ? import_lib$2.default : import_lib$2.default.default;
39678
39876
  const APP_CONTAINER_ID = "app-container";
39679
39877
  const SECTION_TAG = "section";
39680
39878
  const DATA_NAME_ATTR = "data-name";
39681
- const getTagName = (element) => {
39879
+ const getTagName$1 = (element) => {
39682
39880
  const name = element.openingElement.name;
39683
- return import_lib$2.isJSXIdentifier(name) ? name.name : "";
39881
+ return import_lib$3.isJSXIdentifier(name) ? name.name : "";
39684
39882
  };
39685
- const getAttr = (element, attrName) => element.openingElement.attributes.find((a) => import_lib$2.isJSXAttribute(a) && import_lib$2.isJSXIdentifier(a.name) && a.name.name === attrName);
39883
+ const getAttr = (element, attrName) => element.openingElement.attributes.find((a) => import_lib$3.isJSXAttribute(a) && import_lib$3.isJSXIdentifier(a.name) && a.name.name === attrName);
39686
39884
  const getAttrValue = (element, attrName) => {
39687
39885
  const attr = getAttr(element, attrName);
39688
- return attr && import_lib$2.isStringLiteral(attr.value) ? attr.value.value : void 0;
39886
+ return attr && import_lib$3.isStringLiteral(attr.value) ? attr.value.value : void 0;
39689
39887
  };
39690
- const isSectionElement = (node) => import_lib$2.isJSXElement(node) && getTagName(node) === SECTION_TAG;
39888
+ const isSectionElement = (node) => import_lib$3.isJSXElement(node) && getTagName$1(node) === SECTION_TAG;
39691
39889
  const findContainer = (ast) => {
39692
39890
  let container;
39693
39891
  traverse(ast, { JSXElement(path) {
@@ -39705,14 +39903,14 @@ const findOutermostSections = (children) => {
39705
39903
  sections.push(child);
39706
39904
  continue;
39707
39905
  }
39708
- if (import_lib$2.isJSXElement(child) || import_lib$2.isJSXFragment(child)) sections.push(...findOutermostSections(child.children));
39906
+ if (import_lib$3.isJSXElement(child) || import_lib$3.isJSXFragment(child)) sections.push(...findOutermostSections(child.children));
39709
39907
  }
39710
39908
  return sections;
39711
39909
  };
39712
39910
  const documentCache = createBoundedCache(CONFIG.DOCUMENT_CACHE_LIMIT);
39713
39911
  const buildDocument = (code) => {
39714
39912
  try {
39715
- const ast = (0, import_lib.parse)(code, {
39913
+ const ast = (0, import_lib$1.parse)(code, {
39716
39914
  sourceType: "module",
39717
39915
  plugins: ["jsx", "typescript"]
39718
39916
  });
@@ -39749,7 +39947,7 @@ const fillSectionIds = (code, generateId = () => nanoid(6)) => {
39749
39947
  const edits = [];
39750
39948
  findOutermostSections(doc.container.children).forEach((node) => {
39751
39949
  const attr = getAttr(node, DATA_ATTR.ID);
39752
- const id = attr && import_lib$2.isStringLiteral(attr.value) ? attr.value.value : void 0;
39950
+ const id = attr && import_lib$3.isStringLiteral(attr.value) ? attr.value.value : void 0;
39753
39951
  if (id && !seen.has(id)) {
39754
39952
  seen.add(id);
39755
39953
  return;
@@ -39861,6 +40059,693 @@ const createSectionPreviewCache = () => {
39861
40059
  return { compute };
39862
40060
  };
39863
40061
  //#endregion
39864
- export { __toESM as C, TS_PATTERNS as S, CONFIG as _, generateSectionPreview as a, DRAGGABLE_ITEMS as b, parseDocument as c, createBoundedCache as d, nanoid as f, BINDING_PROP as g, require_lib$7 as h, generateDocumentCode as i, replaceDocumentSections as l, require_lib$4 as m, createSectionPreviewCache as n, generateSectionPreviews as o, require_lib$3 as p, fillSectionIds as r, getSections as s, clearDocumentParseCache as t, traverse as u, DATA_ATTR as v, REGEX as x, DEFAULT_TEMPLATE as y };
40062
+ //#region src/utils/ast/types.ts
40063
+ const BINDING_TYPES = [
40064
+ "array",
40065
+ "object",
40066
+ "string",
40067
+ "number",
40068
+ "boolean",
40069
+ "color",
40070
+ "jsx",
40071
+ "richtext",
40072
+ "date",
40073
+ "url"
40074
+ ];
40075
+ //#endregion
40076
+ //#region src/utils/ast/helpers.ts
40077
+ const generate = typeof import_lib.default === "function" ? import_lib.default : import_lib.default.default;
40078
+ const wrap = (code) => {
40079
+ return `<>${code}</>`;
40080
+ };
40081
+ const unwrap = (generated) => {
40082
+ return generated.replace(/^<>\s*/g, "").replace(/\s*<\/>\s*;?\s*$/g, "").trim();
40083
+ };
40084
+ const attrValue = ({ value, isStringLiteral }) => {
40085
+ if (value === null) return null;
40086
+ if (isStringLiteral) return import_lib$3.stringLiteral(value);
40087
+ const trimmed = value.trim();
40088
+ if (REGEX.NUMBER.test(trimmed)) return import_lib$3.jsxExpressionContainer(import_lib$3.numericLiteral(parseFloat(trimmed)));
40089
+ if (REGEX.BOOLEAN_OR_NULL.test(trimmed)) {
40090
+ const expr = (0, import_lib$1.parseExpression)(trimmed, { plugins: ["jsx", "typescript"] });
40091
+ return import_lib$3.jsxExpressionContainer(expr);
40092
+ }
40093
+ try {
40094
+ const expr = (0, import_lib$1.parseExpression)(trimmed, { plugins: ["jsx", "typescript"] });
40095
+ return import_lib$3.jsxExpressionContainer(expr);
40096
+ } catch {
40097
+ return import_lib$3.stringLiteral(trimmed);
40098
+ }
40099
+ };
40100
+ const generateCode = (node) => {
40101
+ return generate(node, { jsescOption: { minimal: true } }).code;
40102
+ };
40103
+ //#endregion
40104
+ //#region src/utils/ast/value.ts
40105
+ const dedent = (str) => {
40106
+ const lines = str.replace(/^\n/, "").replace(/\n\s*$/, "").split("\n");
40107
+ const indent = lines.reduce((min, line) => {
40108
+ if (!line.trim()) return min;
40109
+ const match = line.match(/^(\s*)/);
40110
+ return Math.min(min, match?.[1]?.length ?? 0);
40111
+ }, Infinity);
40112
+ return indent === Infinity ? str.trim() : lines.map((line) => line.slice(indent)).join("\n");
40113
+ };
40114
+ const unwrapExpression = (node) => {
40115
+ let current = node;
40116
+ while (import_lib$3.isTSAsExpression(current) || import_lib$3.isTSSatisfiesExpression(current) || import_lib$3.isTSNonNullExpression(current) || import_lib$3.isTSTypeAssertion(current) || import_lib$3.isParenthesizedExpression(current)) current = current.expression;
40117
+ return current;
40118
+ };
40119
+ const isLosslesslyEvaluable = (node) => {
40120
+ const value = unwrapExpression(node);
40121
+ if (import_lib$3.isStringLiteral(value) || import_lib$3.isNumericLiteral(value) || import_lib$3.isBooleanLiteral(value) || import_lib$3.isNullLiteral(value)) return true;
40122
+ if (import_lib$3.isUnaryExpression(value) && value.operator === "-" && import_lib$3.isNumericLiteral(value.argument)) return true;
40123
+ if (import_lib$3.isTemplateLiteral(value)) return value.expressions.length === 0;
40124
+ if (import_lib$3.isArrayExpression(value)) return value.elements.every((element) => element !== null && isLosslesslyEvaluable(element));
40125
+ if (import_lib$3.isObjectExpression(value)) return value.properties.every((property) => import_lib$3.isObjectProperty(property) && !property.computed && (import_lib$3.isIdentifier(property.key) || import_lib$3.isStringLiteral(property.key) || import_lib$3.isNumericLiteral(property.key)) && isLosslesslyEvaluable(property.value));
40126
+ return false;
40127
+ };
40128
+ const canLosslesslyEvaluateSource = (source) => {
40129
+ try {
40130
+ return isLosslesslyEvaluable((0, import_lib$1.parseExpression)(source, { plugins: ["jsx", "typescript"] }));
40131
+ } catch {
40132
+ return false;
40133
+ }
40134
+ };
40135
+ const evaluateLiteral = (rawNode) => {
40136
+ const node = unwrapExpression(rawNode);
40137
+ if (import_lib$3.isStringLiteral(node)) return node.value;
40138
+ if (import_lib$3.isNumericLiteral(node)) return node.value;
40139
+ if (import_lib$3.isBooleanLiteral(node)) return node.value;
40140
+ if (import_lib$3.isNullLiteral(node)) return null;
40141
+ if (import_lib$3.isIdentifier(node) && node.name === "undefined") return;
40142
+ if (import_lib$3.isUnaryExpression(node) && node.operator === "-" && import_lib$3.isNumericLiteral(node.argument)) return -node.argument.value;
40143
+ if (import_lib$3.isTemplateLiteral(node) && node.expressions.length === 0) return node.quasis[0]?.value.cooked ?? node.quasis[0]?.value.raw ?? "";
40144
+ if (import_lib$3.isJSXElement(node) || import_lib$3.isJSXFragment(node)) return generateCode(node);
40145
+ if (import_lib$3.isArrayExpression(node)) return node.elements.map((element) => element ? evaluateLiteral(element) : null);
40146
+ if (import_lib$3.isObjectExpression(node)) {
40147
+ const result = {};
40148
+ for (const prop of node.properties) {
40149
+ if (!import_lib$3.isObjectProperty(prop)) continue;
40150
+ let key = null;
40151
+ if (import_lib$3.isIdentifier(prop.key)) key = prop.key.name;
40152
+ else if (import_lib$3.isStringLiteral(prop.key)) key = prop.key.value;
40153
+ else if (import_lib$3.isNumericLiteral(prop.key)) key = String(prop.key.value);
40154
+ if (key === null) continue;
40155
+ result[key] = evaluateLiteral(prop.value);
40156
+ }
40157
+ return result;
40158
+ }
40159
+ };
40160
+ const parseValue = (value) => {
40161
+ if (typeof value !== "string") return value;
40162
+ const trimmed = value.trim();
40163
+ if (!trimmed) return value;
40164
+ if (REGEX.NUMBER.test(trimmed)) return parseFloat(trimmed);
40165
+ if (REGEX.BOOLEAN_OR_NULL.test(trimmed)) {
40166
+ if (trimmed === "true") return true;
40167
+ if (trimmed === "false") return false;
40168
+ if (trimmed === "null") return null;
40169
+ if (trimmed === "undefined") return;
40170
+ }
40171
+ if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) {
40172
+ try {
40173
+ const ast = (0, import_lib$1.parseExpression)(trimmed, { plugins: ["jsx", "typescript"] });
40174
+ if (import_lib$3.isObjectExpression(ast) || import_lib$3.isArrayExpression(ast)) return evaluateLiteral(ast);
40175
+ } catch {}
40176
+ return value;
40177
+ }
40178
+ return value;
40179
+ };
40180
+ const MAX_FLATTEN_DEPTH = 20;
40181
+ const isEditablePrimitive = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean";
40182
+ const flattenEditableValue = (value) => {
40183
+ const parsed = parseValue(value);
40184
+ if (typeof parsed !== "object" || parsed === null || Object.keys(parsed).length === 0) return null;
40185
+ const entries = [];
40186
+ const walk = (node, path, depth) => {
40187
+ if (depth > MAX_FLATTEN_DEPTH) return;
40188
+ if (isEditablePrimitive(node)) {
40189
+ entries.push({
40190
+ path,
40191
+ value: node
40192
+ });
40193
+ return;
40194
+ }
40195
+ if (Array.isArray(node)) {
40196
+ node.forEach((item, index) => walk(item, [...path, index], depth + 1));
40197
+ return;
40198
+ }
40199
+ if (typeof node === "object" && node !== null) Object.entries(node).forEach(([key, item]) => walk(item, [...path, key], depth + 1));
40200
+ };
40201
+ walk(parsed, [], 0);
40202
+ return entries.length ? entries : null;
40203
+ };
40204
+ const setEditableValue = (value, path, next) => {
40205
+ if (!path.length) return value;
40206
+ const parsed = parseValue(value);
40207
+ if (typeof parsed !== "object" || parsed === null) return value;
40208
+ const root = Array.isArray(parsed) ? [...parsed] : { ...parsed };
40209
+ let cursor = root;
40210
+ for (let i = 0; i < path.length - 1; i++) {
40211
+ const key = path[i];
40212
+ const child = cursor[key];
40213
+ if (typeof child !== "object" || child === null) return value;
40214
+ const clonedChild = Array.isArray(child) ? [...child] : { ...child };
40215
+ cursor[key] = clonedChild;
40216
+ cursor = clonedChild;
40217
+ }
40218
+ const lastKey = path[path.length - 1];
40219
+ if (!(lastKey in cursor)) return value;
40220
+ cursor[lastKey] = next;
40221
+ return JSON.stringify(root);
40222
+ };
40223
+ const extractNodeValue = (node) => {
40224
+ if (import_lib$3.isBooleanLiteral(node)) return {
40225
+ type: "boolean",
40226
+ value: node.value
40227
+ };
40228
+ if (import_lib$3.isNumericLiteral(node)) return {
40229
+ type: "number",
40230
+ value: node.value
40231
+ };
40232
+ if (import_lib$3.isUnaryExpression(node) && node.operator === "-" && import_lib$3.isNumericLiteral(node.argument)) return {
40233
+ type: "number",
40234
+ value: -node.argument.value
40235
+ };
40236
+ if (import_lib$3.isStringLiteral(node)) return {
40237
+ type: "string",
40238
+ value: node.value
40239
+ };
40240
+ if (import_lib$3.isTemplateLiteral(node)) {
40241
+ if (node.expressions.length === 0 && node.quasis.length === 1) return {
40242
+ type: "string",
40243
+ value: dedent(node.quasis[0].value.cooked ?? node.quasis[0].value.raw)
40244
+ };
40245
+ return {
40246
+ type: "string",
40247
+ value: generateCode(node)
40248
+ };
40249
+ }
40250
+ if (import_lib$3.isNullLiteral(node)) return {
40251
+ type: "null",
40252
+ value: null
40253
+ };
40254
+ if (import_lib$3.isArrayExpression(node)) return {
40255
+ type: "array",
40256
+ value: generateCode(node)
40257
+ };
40258
+ if (import_lib$3.isObjectExpression(node)) return {
40259
+ type: "object",
40260
+ value: generateCode(node)
40261
+ };
40262
+ if (import_lib$3.isJSXElement(node) || import_lib$3.isJSXFragment(node)) return {
40263
+ type: "string",
40264
+ value: generateCode(node)
40265
+ };
40266
+ return {
40267
+ type: "unknown",
40268
+ value: null
40269
+ };
40270
+ };
40271
+ const createNodeFromValue = (type, value) => {
40272
+ switch (type) {
40273
+ case "boolean": return import_lib$3.booleanLiteral(value === true);
40274
+ case "number": return import_lib$3.numericLiteral(Number(value));
40275
+ case "string": return import_lib$3.stringLiteral(String(value));
40276
+ case "null": return import_lib$3.nullLiteral();
40277
+ case "array":
40278
+ case "object":
40279
+ case "unknown": return null;
40280
+ default: return null;
40281
+ }
40282
+ };
40283
+ const valueToExpression = (value) => {
40284
+ if (typeof value === "string") return import_lib$3.stringLiteral(value);
40285
+ if (typeof value === "number") return value < 0 ? import_lib$3.unaryExpression("-", import_lib$3.numericLiteral(-value)) : import_lib$3.numericLiteral(value);
40286
+ if (typeof value === "boolean") return import_lib$3.booleanLiteral(value);
40287
+ if (value === null) return import_lib$3.nullLiteral();
40288
+ if (Array.isArray(value)) return import_lib$3.arrayExpression(value.map((item) => valueToExpression(item) ?? import_lib$3.nullLiteral()));
40289
+ if (typeof value === "object") {
40290
+ const properties = [];
40291
+ for (const [key, item] of Object.entries(value)) {
40292
+ const expr = valueToExpression(item);
40293
+ if (expr === null) continue;
40294
+ properties.push(import_lib$3.objectProperty(import_lib$3.stringLiteral(key), expr));
40295
+ }
40296
+ return import_lib$3.objectExpression(properties);
40297
+ }
40298
+ return null;
40299
+ };
40300
+ const parseArrayExpression = (value) => {
40301
+ try {
40302
+ const ast = unwrapExpression((0, import_lib$1.parseExpression)(value, { plugins: ["jsx", "typescript"] }));
40303
+ if (!import_lib$3.isArrayExpression(ast)) return null;
40304
+ return ast;
40305
+ } catch (error) {
40306
+ console.error("❌ Array parsing error:", error);
40307
+ return null;
40308
+ }
40309
+ };
40310
+ const extractObjectProperties = (element) => {
40311
+ const properties = {};
40312
+ element.properties.forEach((prop) => {
40313
+ if (import_lib$3.isObjectProperty(prop) && import_lib$3.isIdentifier(prop.key)) {
40314
+ const key = prop.key.name;
40315
+ if (key === "children" || import_lib$3.isJSXElement(prop.value) || import_lib$3.isJSXFragment(prop.value)) return;
40316
+ const extracted = extractNodeValue(prop.value);
40317
+ properties[key] = {
40318
+ ...extracted,
40319
+ astNode: prop.value
40320
+ };
40321
+ }
40322
+ });
40323
+ return properties;
40324
+ };
40325
+ const arrayExpressionToCode = (elements) => {
40326
+ const nextAst = import_lib$3.arrayExpression(elements);
40327
+ return generateCode(nextAst);
40328
+ };
40329
+ //#endregion
40330
+ //#region src/utils/ast/binding.ts
40331
+ const bindingTypeSchema = z.enum(BINDING_TYPES);
40332
+ const bindingOptionSchema = z.object({
40333
+ label: z.string(),
40334
+ value: z.string()
40335
+ });
40336
+ const bindingWidgetSchema = z.object({
40337
+ type: z.string().min(1),
40338
+ step: z.number().optional(),
40339
+ unit: z.string().optional()
40340
+ }).passthrough();
40341
+ const pick = (schema, value) => {
40342
+ const parsed = schema.safeParse(value);
40343
+ return parsed.success ? parsed.data : void 0;
40344
+ };
40345
+ const sanitizeWidget = (value) => {
40346
+ if (typeof value === "string") return value ? { type: value } : void 0;
40347
+ return pick(bindingWidgetSchema, value);
40348
+ };
40349
+ const sanitizeOptions = (value) => {
40350
+ if (!Array.isArray(value)) return;
40351
+ const options = value.flatMap((option) => {
40352
+ const parsed = pick(bindingOptionSchema, option);
40353
+ return parsed ? [parsed] : [];
40354
+ });
40355
+ return options.length > 0 ? options : void 0;
40356
+ };
40357
+ const KNOWN_BINDING_KEYS = /* @__PURE__ */ new Set([
40358
+ "label",
40359
+ "property",
40360
+ "type",
40361
+ "widget",
40362
+ "options",
40363
+ "render",
40364
+ "min",
40365
+ "max",
40366
+ "pattern",
40367
+ "required"
40368
+ ]);
40369
+ const isPlainObject = (value) => {
40370
+ return typeof value === "object" && value !== null && !Array.isArray(value);
40371
+ };
40372
+ const sanitizeField = (raw) => {
40373
+ const metaEntries = Object.entries(raw).filter(([key]) => !KNOWN_BINDING_KEYS.has(key));
40374
+ const field = {
40375
+ label: pick(z.string(), raw.label),
40376
+ property: pick(z.string(), raw.property),
40377
+ type: pick(bindingTypeSchema, raw.type),
40378
+ widget: sanitizeWidget(raw.widget),
40379
+ options: sanitizeOptions(raw.options),
40380
+ render: sanitizeRenderMap(raw.render),
40381
+ min: pick(z.number(), raw.min),
40382
+ max: pick(z.number(), raw.max),
40383
+ pattern: pick(z.string(), raw.pattern),
40384
+ required: pick(z.boolean(), raw.required),
40385
+ meta: metaEntries.length > 0 ? Object.fromEntries(metaEntries) : void 0
40386
+ };
40387
+ return Object.fromEntries(Object.entries(field).filter(([, value]) => value !== void 0));
40388
+ };
40389
+ function sanitizeRenderMap(value) {
40390
+ if (!isPlainObject(value)) return;
40391
+ const map = {};
40392
+ for (const [key, raw] of Object.entries(value)) {
40393
+ if (!isPlainObject(raw)) continue;
40394
+ if ("type" in raw) {
40395
+ map[key] = {
40396
+ type: void 0,
40397
+ ...sanitizeField(raw)
40398
+ };
40399
+ continue;
40400
+ }
40401
+ const nested = sanitizeRenderMap(raw);
40402
+ if (nested) map[key] = nested;
40403
+ }
40404
+ return Object.keys(map).length > 0 ? map : void 0;
40405
+ }
40406
+ const buildBindingItems = (raw) => {
40407
+ if (!Array.isArray(raw)) return [];
40408
+ return raw.flatMap((rawItem) => {
40409
+ if (!isPlainObject(rawItem)) return [];
40410
+ const { label, property, ...field } = sanitizeField(rawItem);
40411
+ if (label === void 0) return [];
40412
+ if (property === void 0 && field.type !== "richtext") return [];
40413
+ return [{
40414
+ label,
40415
+ property: property ?? BINDING_PROP.INNER_HTML,
40416
+ ...field
40417
+ }];
40418
+ });
40419
+ };
40420
+ const parseBinding = (bindingValue) => {
40421
+ if (!bindingValue) return [];
40422
+ const ast = parseArrayExpression(bindingValue);
40423
+ if (!ast) return [];
40424
+ return buildBindingItems(evaluateLiteral(ast));
40425
+ };
40426
+ const parseBindingExpression = (expression) => buildBindingItems(evaluateLiteral(expression));
40427
+ const getCurrentValue = (node, property) => {
40428
+ switch (property) {
40429
+ case BINDING_PROP.INNER_TEXT: return node.textContent || "";
40430
+ case BINDING_PROP.INNER_HTML: {
40431
+ const dsiAttr = node.attributes.find((a) => a.name === "dangerouslySetInnerHTML");
40432
+ if (dsiAttr?.value) try {
40433
+ const expr = (0, import_lib$1.parseExpression)(dsiAttr.value, { plugins: ["jsx", "typescript"] });
40434
+ if (import_lib$3.isObjectExpression(expr)) {
40435
+ const htmlProp = expr.properties.find((p) => import_lib$3.isObjectProperty(p) && import_lib$3.isIdentifier(p.key) && p.key.name === "__html");
40436
+ if (htmlProp) {
40437
+ if (import_lib$3.isStringLiteral(htmlProp.value)) return htmlProp.value.value;
40438
+ if (import_lib$3.isTemplateLiteral(htmlProp.value) && htmlProp.value.expressions.length === 0) return htmlProp.value.quasis[0]?.value.cooked ?? htmlProp.value.quasis[0]?.value.raw ?? "";
40439
+ }
40440
+ }
40441
+ } catch {}
40442
+ return node.rawChildren || node.textContent || "";
40443
+ }
40444
+ case BINDING_PROP.CHILDREN: return JSON.stringify(node?.children || []);
40445
+ default: return node.attributes.find((attr) => attr.name === property)?.value || "";
40446
+ }
40447
+ };
40448
+ const STRING_VALUED_TYPES = /* @__PURE__ */ new Set([
40449
+ "string",
40450
+ "url",
40451
+ "date",
40452
+ "color",
40453
+ "jsx",
40454
+ "richtext"
40455
+ ]);
40456
+ const getStructuredValue = (node, property, type) => {
40457
+ switch (property) {
40458
+ case BINDING_PROP.INNER_TEXT:
40459
+ case BINDING_PROP.INNER_HTML: return getCurrentValue(node, property);
40460
+ case BINDING_PROP.CHILDREN: return node.children ?? [];
40461
+ default: {
40462
+ const raw = getCurrentValue(node, property);
40463
+ if (node.attributes.find((a) => a.name === property)?.isStringLiteral || type && STRING_VALUED_TYPES.has(type)) return raw;
40464
+ return parseValue(raw);
40465
+ }
40466
+ }
40467
+ };
40468
+ const hasEditableBindings = (node) => {
40469
+ const bindingAttr = node.dataAttributes.find((attr) => attr.name === DATA_ATTR.BINDING);
40470
+ if (!bindingAttr?.value) return false;
40471
+ return (node.bindings || parseBinding(bindingAttr.value)).length > 0;
40472
+ };
40473
+ const findEditableChildren = (node) => {
40474
+ const editableChildren = [];
40475
+ const traverse = (children) => {
40476
+ if (!children) return;
40477
+ for (const child of children) {
40478
+ if (hasEditableBindings(child)) editableChildren.push(child);
40479
+ traverse(child.children);
40480
+ }
40481
+ };
40482
+ traverse(node.children);
40483
+ return editableChildren;
40484
+ };
40485
+ //#endregion
40486
+ //#region src/utils/ast/extract.ts
40487
+ const collectText = (children) => {
40488
+ return children.filter((c) => import_lib$3.isJSXText(c)).map((c) => c.value.trim()).filter((v) => v.length).join(" ");
40489
+ };
40490
+ const getTagName = (opening) => {
40491
+ if (import_lib$3.isJSXIdentifier(opening.name)) return opening.name.name;
40492
+ if (import_lib$3.isJSXMemberExpression(opening.name)) return resolveMemberName(opening.name);
40493
+ return "";
40494
+ };
40495
+ const resolveMemberName = (expr) => {
40496
+ const parts = [];
40497
+ const collectMemberParts = (node) => {
40498
+ if (import_lib$3.isJSXIdentifier(node)) parts.push(node.name);
40499
+ else if (import_lib$3.isJSXMemberExpression(node)) {
40500
+ collectMemberParts(node.object);
40501
+ if (import_lib$3.isJSXIdentifier(node.property)) parts.push(node.property.name);
40502
+ }
40503
+ };
40504
+ collectMemberParts(expr.object);
40505
+ if (import_lib$3.isJSXIdentifier(expr.property)) parts.push(expr.property.name);
40506
+ return parts.join(".");
40507
+ };
40508
+ const parseJSXName = (tagName) => {
40509
+ const parts = tagName.split(".");
40510
+ if (parts.length === 1) return import_lib$3.jsxIdentifier(parts[0]);
40511
+ let expr = import_lib$3.jsxIdentifier(parts[0]);
40512
+ for (let i = 1; i < parts.length; i++) expr = import_lib$3.jsxMemberExpression(expr, import_lib$3.jsxIdentifier(parts[i]));
40513
+ return expr;
40514
+ };
40515
+ const extractCache = createBoundedCache(CONFIG.CACHE_LIMIT);
40516
+ const extractAttributes = (attributes, source) => {
40517
+ const allAttrs = [];
40518
+ const dataAttrs = [];
40519
+ for (const attr of attributes) {
40520
+ if (!import_lib$3.isJSXAttribute(attr) || !import_lib$3.isJSXIdentifier(attr.name)) continue;
40521
+ const name = attr.name.name;
40522
+ let value = null;
40523
+ let isStringLiteral = false;
40524
+ if (attr.value) {
40525
+ if (import_lib$3.isStringLiteral(attr.value)) {
40526
+ value = attr.value.value;
40527
+ isStringLiteral = true;
40528
+ } else if (import_lib$3.isJSXExpressionContainer(attr.value)) try {
40529
+ const expression = attr.value.expression;
40530
+ const structural = import_lib$3.isArrayExpression(unwrapExpression(expression)) || import_lib$3.isObjectExpression(unwrapExpression(expression));
40531
+ value = source && structural && expression.start != null && expression.end != null ? source.slice(expression.start, expression.end) : generateCode(expression);
40532
+ isStringLiteral = false;
40533
+ } catch {
40534
+ value = null;
40535
+ }
40536
+ }
40537
+ const entry = {
40538
+ name,
40539
+ value,
40540
+ isStringLiteral
40541
+ };
40542
+ allAttrs.push(entry);
40543
+ if (name.startsWith("data-")) dataAttrs.push(entry);
40544
+ }
40545
+ return {
40546
+ allAttrs,
40547
+ dataAttrs
40548
+ };
40549
+ };
40550
+ const buildChildElements = (node) => {
40551
+ const childElements = [];
40552
+ if (node.textContent) childElements.push(import_lib$3.jsxText(node.textContent));
40553
+ node.children?.forEach((child) => {
40554
+ const childJSX = nodeToJSX(child);
40555
+ if (childJSX) childElements.push(childJSX);
40556
+ });
40557
+ return childElements;
40558
+ };
40559
+ const nodeToJSX = (node) => {
40560
+ try {
40561
+ if (node.isFragment) {
40562
+ const childElements = buildChildElements(node);
40563
+ return import_lib$3.jsxFragment(import_lib$3.jsxOpeningFragment(), import_lib$3.jsxClosingFragment(), childElements);
40564
+ }
40565
+ if (node.tagName === "div" && node.dataAttributes.some((attr) => attr.name === "data-item")) {
40566
+ if (node.children) return nodeToJSX(node.children[0]);
40567
+ return null;
40568
+ }
40569
+ const attributes = node.attributes.map((attr) => {
40570
+ const attrName = import_lib$3.jsxIdentifier(attr.name);
40571
+ if (!attr.value) return import_lib$3.jsxAttribute(attrName, null);
40572
+ return import_lib$3.jsxAttribute(attrName, attrValue(attr));
40573
+ });
40574
+ const elementName = parseJSXName(node.tagName);
40575
+ const openingElement = import_lib$3.jsxOpeningElement(elementName, attributes);
40576
+ const closingElement = import_lib$3.jsxClosingElement(elementName);
40577
+ const children = buildChildElements(node);
40578
+ return import_lib$3.jsxElement(openingElement, closingElement, children, false);
40579
+ } catch (error) {
40580
+ console.error("❌ DataAttrNode to JSX conversion error:", error);
40581
+ return null;
40582
+ }
40583
+ };
40584
+ const createWrapperNode = (textContent, children) => ({
40585
+ tagName: "div",
40586
+ id: nanoid(6),
40587
+ attributes: [{
40588
+ name: DATA_ATTR.ITEM,
40589
+ value: "true"
40590
+ }],
40591
+ dataAttributes: [{
40592
+ name: DATA_ATTR.ITEM,
40593
+ value: "true"
40594
+ }],
40595
+ textContent,
40596
+ children
40597
+ });
40598
+ const createFragmentNode = (textContent, children) => ({
40599
+ tagName: "",
40600
+ id: nanoid(6),
40601
+ attributes: [],
40602
+ dataAttributes: [],
40603
+ textContent,
40604
+ children,
40605
+ isFragment: true
40606
+ });
40607
+ const processChildrenBinding = (jsxElement, processedNodes, shouldWrap = true, source) => {
40608
+ const jsxChildren = jsxElement.children.filter((child) => import_lib$3.isJSXElement(child) || import_lib$3.isJSXFragment(child));
40609
+ if (!jsxChildren.length) return;
40610
+ const childrenNodes = [];
40611
+ jsxChildren.forEach((child) => {
40612
+ if (import_lib$3.isJSXElement(child)) {
40613
+ const childResults = extractFromNode(child, processedNodes, source);
40614
+ if (shouldWrap) {
40615
+ const wrapperNode = createWrapperNode(collectText(child.children), childResults);
40616
+ wrapperNode.source = source?.slice(child.start, child.end);
40617
+ const dataId = childResults[0]?.dataAttributes.find((attr) => attr.name === DATA_ATTR.ID)?.value;
40618
+ if (dataId) wrapperNode.id = `child:${dataId}`;
40619
+ childrenNodes.push(wrapperNode);
40620
+ } else childrenNodes.push(...childResults);
40621
+ } else if (import_lib$3.isJSXFragment(child)) {
40622
+ processedNodes?.add(child);
40623
+ const fragmentChildren = [];
40624
+ child.children.forEach((fragmentChild) => {
40625
+ if (import_lib$3.isJSXElement(fragmentChild)) {
40626
+ const childResults = extractFromNode(fragmentChild, processedNodes, source);
40627
+ fragmentChildren.push(...childResults);
40628
+ }
40629
+ });
40630
+ if (fragmentChildren.length) {
40631
+ const fragmentNode = createFragmentNode(collectText(child.children), fragmentChildren);
40632
+ fragmentNode.source = source?.slice(child.start, child.end);
40633
+ childrenNodes.push(fragmentNode);
40634
+ }
40635
+ }
40636
+ });
40637
+ return childrenNodes.length ? childrenNodes : void 0;
40638
+ };
40639
+ const skipItemsChildren = (jsxElement, processedNodes, propertyName = "items") => {
40640
+ const itemsAttr = jsxElement.openingElement.attributes.find((attr) => import_lib$3.isJSXAttribute(attr) && import_lib$3.isJSXIdentifier(attr.name) && attr.name.name === propertyName);
40641
+ if (!itemsAttr || !import_lib$3.isJSXAttribute(itemsAttr)) return;
40642
+ if (itemsAttr.value && import_lib$3.isJSXExpressionContainer(itemsAttr.value) && import_lib$3.isArrayExpression(itemsAttr.value.expression)) itemsAttr.value.expression.elements.forEach((element) => {
40643
+ if (import_lib$3.isObjectExpression(element)) element.properties.forEach((prop) => {
40644
+ if (import_lib$3.isObjectProperty(prop) && import_lib$3.isIdentifier(prop.key) && import_lib$3.isJSXElement(prop.value)) markProcessedJSX(prop.value, processedNodes);
40645
+ });
40646
+ });
40647
+ };
40648
+ const markProcessedJSX = (node, processedNodes) => {
40649
+ if (import_lib$3.isJSXElement(node) || import_lib$3.isJSXFragment(node)) {
40650
+ processedNodes.add(node);
40651
+ node.children.forEach((child) => markProcessedJSX(child, processedNodes));
40652
+ return;
40653
+ }
40654
+ if (import_lib$3.isJSXExpressionContainer(node) || import_lib$3.isParenthesizedExpression(node)) markProcessedJSX(node.expression, processedNodes);
40655
+ };
40656
+ const getBindingExpression = (opening) => {
40657
+ for (const attr of opening.attributes) if (import_lib$3.isJSXAttribute(attr) && import_lib$3.isJSXIdentifier(attr.name) && attr.name.name === DATA_ATTR.BINDING && attr.value && import_lib$3.isJSXExpressionContainer(attr.value)) {
40658
+ const expression = unwrapExpression(attr.value.expression);
40659
+ if (import_lib$3.isArrayExpression(expression)) return expression;
40660
+ }
40661
+ return null;
40662
+ };
40663
+ const readNodeBindingInfo = (node, source) => {
40664
+ const opening = node.openingElement;
40665
+ const tagName = getTagName(opening);
40666
+ const { allAttrs, dataAttrs } = extractAttributes(opening.attributes, source);
40667
+ const bindingAttr = dataAttrs.find((attr) => attr.name === DATA_ATTR.BINDING);
40668
+ const bindingExpr = getBindingExpression(opening);
40669
+ const bindings = bindingExpr ? parseBindingExpression(bindingExpr) : bindingAttr?.value ? parseBinding(bindingAttr.value) : [];
40670
+ const childrenBinding = bindings.find((b) => b.property === BINDING_PROP.CHILDREN);
40671
+ const arrayBindings = bindings.filter((b) => b.property === BINDING_PROP.ITEMS || b.type === "array");
40672
+ const innerHtmlBinding = bindings.find((b) => b.property === BINDING_PROP.INNER_HTML);
40673
+ let rawChildren;
40674
+ if (innerHtmlBinding && node.children.length > 0) rawChildren = node.children.map((child) => generateCode(child)).join("").trim();
40675
+ return {
40676
+ tagName,
40677
+ allAttrs,
40678
+ dataAttrs,
40679
+ bindings,
40680
+ childrenBinding,
40681
+ arrayBindings,
40682
+ rawChildren
40683
+ };
40684
+ };
40685
+ const parseToNodes = (raw) => {
40686
+ const wrapped = wrap(raw);
40687
+ const ast = (0, import_lib$1.parse)(wrapped, {
40688
+ sourceType: "module",
40689
+ plugins: ["jsx", "typescript"],
40690
+ errorRecovery: true
40691
+ });
40692
+ const results = [];
40693
+ const processedNodes = /* @__PURE__ */ new WeakSet();
40694
+ traverse(ast, { JSXElement(path) {
40695
+ if (processedNodes.has(path.node)) return;
40696
+ const { tagName, allAttrs, dataAttrs, bindings, childrenBinding, arrayBindings, rawChildren } = readNodeBindingInfo(path.node, wrapped);
40697
+ if (!tagName || !dataAttrs.length) return;
40698
+ let childrenNodes;
40699
+ if (childrenBinding) childrenNodes = processChildrenBinding(path.node, processedNodes, true, wrapped);
40700
+ for (const arrayBinding of arrayBindings) skipItemsChildren(path.node, processedNodes, arrayBinding.property);
40701
+ results.push({
40702
+ tagName,
40703
+ attributes: allAttrs,
40704
+ dataAttributes: dataAttrs,
40705
+ textContent: collectText(path.node.children),
40706
+ rawChildren,
40707
+ children: childrenNodes,
40708
+ bindings,
40709
+ loc: path.node.loc ? {
40710
+ start: {
40711
+ line: path.node.loc.start.line,
40712
+ column: path.node.loc.start.column
40713
+ },
40714
+ end: {
40715
+ line: path.node.loc.end.line,
40716
+ column: path.node.loc.end.column
40717
+ }
40718
+ } : void 0
40719
+ });
40720
+ } });
40721
+ return results;
40722
+ };
40723
+ function extract(raw) {
40724
+ if (extractCache.has(raw)) return extractCache.get(raw);
40725
+ const results = parseToNodes(raw);
40726
+ extractCache.set(raw, results);
40727
+ return results;
40728
+ }
40729
+ function extractFromNode(node, processedNodes, source) {
40730
+ processedNodes?.add(node);
40731
+ const { tagName, allAttrs, dataAttrs, bindings, childrenBinding, rawChildren } = readNodeBindingInfo(node, source);
40732
+ let childrenNodes;
40733
+ if (childrenBinding) childrenNodes = processChildrenBinding(node, processedNodes, true, source);
40734
+ if (!childrenNodes) childrenNodes = processChildrenBinding(node, processedNodes, false, source);
40735
+ return [{
40736
+ tagName,
40737
+ attributes: allAttrs,
40738
+ dataAttributes: dataAttrs,
40739
+ textContent: collectText(node.children),
40740
+ rawChildren,
40741
+ children: childrenNodes,
40742
+ bindings
40743
+ }];
40744
+ }
40745
+ function clearExtractCache() {
40746
+ extractCache.clear();
40747
+ }
40748
+ //#endregion
40749
+ export { generateSectionPreviews as A, CONFIG as B, unwrap as C, fillSectionIds as D, createSectionPreviewCache as E, createBoundedCache as F, TS_PATTERNS as G, DEFAULT_TEMPLATE as H, nanoid as I, __toESM as K, require_lib$4 as L, parseDocument as M, replaceDocumentSections as N, generateDocumentCode as O, traverse as P, require_lib$7 as R, generateCode as S, clearDocumentParseCache as T, DRAGGABLE_ITEMS as U, DATA_ATTR as V, REGEX as W, parseArrayExpression as _, findEditableChildren as a, unwrapExpression as b, parseBinding as c, canLosslesslyEvaluateSource as d, createNodeFromValue as f, isLosslesslyEvaluable as g, flattenEditableValue as h, STRING_VALUED_TYPES as i, getSections as j, generateSectionPreview as k, parseBindingExpression as l, extractObjectProperties as m, extract as n, getCurrentValue as o, extractNodeValue as p, nodeToJSX as r, getStructuredValue as s, clearExtractCache as t, arrayExpressionToCode as u, parseValue as v, wrap as w, valueToExpression as x, setEditableValue as y, BINDING_PROP as z };
39865
40750
 
39866
- //# sourceMappingURL=document-C6bNHl7l.js.map
40751
+ //# sourceMappingURL=extract-abHYmNsu.js.map