@jbpark/live-editor 3.2.0 → 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.
- package/dist/ast-CZwpVrJv.js +851 -0
- package/dist/ast-CZwpVrJv.js.map +1 -0
- package/dist/{boundary-BTP1nfG6.js → boundary-C90q3YsT.js} +8 -7
- package/dist/boundary-C90q3YsT.js.map +1 -0
- package/dist/{context-649REFsj.js → context-Y-M9fViD.js} +4 -8
- package/dist/context-Y-M9fViD.js.map +1 -0
- package/dist/{core-D3q5rpuz.js → core-Co8Nlq16.js} +2 -2
- package/dist/core-Co8Nlq16.js.map +1 -0
- package/dist/dnd/index.d.ts +2 -2
- package/dist/dnd/index.js +2 -2
- package/dist/{dnd-DTT37EbA.js → dnd-ClnGRNaY.js} +386 -324
- package/dist/dnd-ClnGRNaY.js.map +1 -0
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/index.js +2 -2
- package/dist/{editor-LzqHe_-F.js → editor-COKGtmfE.js} +3 -3
- package/dist/{editor-LzqHe_-F.js.map → editor-COKGtmfE.js.map} +1 -1
- package/dist/error/index.d.ts +1 -1
- package/dist/error/index.js +2 -2
- package/dist/{error-CO0EbMlA.js → error-o0SBwtTv.js} +2 -2
- package/dist/{error-CO0EbMlA.js.map → error-o0SBwtTv.js.map} +1 -1
- package/dist/{document-C6bNHl7l.js → extract-abHYmNsu.js} +927 -42
- package/dist/extract-abHYmNsu.js.map +1 -0
- package/dist/{index-Ba8jGXSM.d.ts → index-BQdZ6LrR.d.ts} +5 -1
- package/dist/{index-DxbG789f.d.ts → index-B_p74BRM.d.ts} +29 -14
- package/dist/{index-CCynrS6c.d.ts → index-DNNj_0ba.d.ts} +3 -2
- package/dist/{index-lgHdCda5.d.ts → index-DQkL37eL.d.ts} +10 -2
- package/dist/{index-DswWDEXZ.d.ts → index-Doh4VTXr.d.ts} +65 -35
- package/dist/index.d.ts +7 -7
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/preview/index.d.ts +2 -2
- package/dist/preview/index.js +3 -2
- package/dist/{preview-CWT0lgwq.js → preview-DKyKKcu7.js} +4 -4
- package/dist/{preview-CWT0lgwq.js.map → preview-DKyKKcu7.js.map} +1 -1
- package/dist/provider/index.js +1 -1
- package/dist/{use-dynamic-tailwind-DAhKGsY4.js → use-dynamic-tailwind-BF8TQ3Yy.js} +83 -27
- package/dist/use-dynamic-tailwind-BF8TQ3Yy.js.map +1 -0
- package/dist/utils/ast/index.d.ts +2 -2
- package/dist/utils/ast/index.js +3 -3
- package/dist/utils/index.d.ts +4 -7
- package/dist/utils/index.js +3 -3
- package/dist/{utils-WyxPYZGh.js → utils-BQ7WL7Jh.js} +33 -16
- package/dist/{utils-WyxPYZGh.js.map → utils-BQ7WL7Jh.js.map} +1 -1
- package/package.json +3 -1
- package/dist/ast-Bx2Avo4d.js +0 -1530
- package/dist/ast-Bx2Avo4d.js.map +0 -1
- package/dist/boundary-BTP1nfG6.js.map +0 -1
- package/dist/context-649REFsj.js.map +0 -1
- package/dist/core-D3q5rpuz.js.map +0 -1
- package/dist/dnd-DTT37EbA.js.map +0 -1
- package/dist/document-C6bNHl7l.js.map +0 -1
- 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
|
|
101
|
+
// Constraints the library validates with or without a widget.
|
|
93
102
|
min: 0,
|
|
94
103
|
max: 40,
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
157
|
-
|
|
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
|
-
|
|
175
|
-
|
|
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={[
|
|
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$
|
|
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
|
-
|
|
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$
|
|
39881
|
+
return import_lib$3.isJSXIdentifier(name) ? name.name : "";
|
|
39684
39882
|
};
|
|
39685
|
-
const getAttr = (element, attrName) => element.openingElement.attributes.find((a) => import_lib$
|
|
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$
|
|
39886
|
+
return attr && import_lib$3.isStringLiteral(attr.value) ? attr.value.value : void 0;
|
|
39689
39887
|
};
|
|
39690
|
-
const isSectionElement = (node) => import_lib$
|
|
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$
|
|
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$
|
|
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
|
-
|
|
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=
|
|
40751
|
+
//# sourceMappingURL=extract-abHYmNsu.js.map
|