cf-pagetree-parser 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,6 +65,23 @@ The `dist/cf-pagetree-parser.js` bundle can be used in sandboxed extension conte
65
65
  - `parseBackground(styles)` - Parse background styles
66
66
  - `backgroundToParams(background)` - Convert background to CF params
67
67
 
68
+ ## Page Settings
69
+
70
+ The parser extracts page-level settings from cf-page attributes:
71
+
72
+ | Attribute | Description |
73
+ |-----------|-------------|
74
+ | `font` | Page font family (e.g., "Poppins"). Applied to body-level styles. |
75
+ | `font-family` | Alias for `font` |
76
+ | `text-color` | Default text color (default: #334155) |
77
+ | `link-color` | Default link color (default: #3b82f6) |
78
+ | `font-weight` | Default font weight |
79
+ | `css` | Custom CSS (URL-encoded) |
80
+ | `header-code` | Custom header HTML/scripts (URL-encoded) |
81
+ | `footer-code` | Custom footer HTML/scripts (URL-encoded) |
82
+
83
+ Font values are normalized to ClickFunnels format (e.g., `"Poppins", sans-serif`).
84
+
68
85
  ## Development
69
86
 
70
87
  ```bash
@@ -1622,6 +1622,9 @@ function parseTextElement(
1622
1622
  const id = generateId();
1623
1623
  const contentEditableId = generateId();
1624
1624
 
1625
+ // Get element-id for scroll-to/show-hide targeting
1626
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
1627
+
1625
1628
  const wrapperStyles = parseInlineStyle(element.getAttribute("style") || "");
1626
1629
  const spacing = parseSpacing(wrapperStyles);
1627
1630
 
@@ -1716,6 +1719,7 @@ function parseTextElement(
1716
1719
  parentId,
1717
1720
  fractionalIndex: generateFractionalIndex(index),
1718
1721
  attrs: {
1722
+ ...(elementId ? { id: elementId } : {}),
1719
1723
  style: {},
1720
1724
  ...animationAttrs,
1721
1725
  },
@@ -1868,6 +1872,9 @@ function parseButton(element, parentId, index) {
1868
1872
  const mainTextId = generateId();
1869
1873
  const subTextId = generateId();
1870
1874
 
1875
+ // Get element-id for scroll-to/show-hide targeting
1876
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
1877
+
1871
1878
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
1872
1879
  const spacing = parseSpacing(wrapperStyles);
1873
1880
 
@@ -1990,6 +1997,7 @@ function parseButton(element, parentId, index) {
1990
1997
  parentId,
1991
1998
  fractionalIndex: generateFractionalIndex(index),
1992
1999
  attrs: {
2000
+ ...(elementId ? { id: elementId } : {}),
1993
2001
  style: {
1994
2002
  'text-align': textAlign,
1995
2003
  },
@@ -2166,6 +2174,9 @@ function parseButton(element, parentId, index) {
2166
2174
  function parseImage(element, parentId, index) {
2167
2175
  const id = generateId();
2168
2176
 
2177
+ // Get element-id for scroll-to/show-hide targeting
2178
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
2179
+
2169
2180
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
2170
2181
  const spacing = parseSpacing(wrapperStyles);
2171
2182
  const textAlign = parseTextAlign(wrapperStyles['text-align']);
@@ -2194,6 +2205,7 @@ function parseImage(element, parentId, index) {
2194
2205
  parentId,
2195
2206
  fractionalIndex: generateFractionalIndex(index),
2196
2207
  attrs: {
2208
+ ...(elementId ? { id: elementId } : {}),
2197
2209
  alt,
2198
2210
  style: {
2199
2211
  'text-align': textAlign,
@@ -2262,6 +2274,9 @@ function parseImage(element, parentId, index) {
2262
2274
  function parseIcon(element, parentId, index) {
2263
2275
  const id = generateId();
2264
2276
 
2277
+ // Get element-id for scroll-to/show-hide targeting
2278
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
2279
+
2265
2280
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
2266
2281
  const spacing = parseSpacing(wrapperStyles);
2267
2282
  const textAlign = parseTextAlign(wrapperStyles['text-align']);
@@ -2297,6 +2312,7 @@ function parseIcon(element, parentId, index) {
2297
2312
  parentId,
2298
2313
  fractionalIndex: generateFractionalIndex(index),
2299
2314
  attrs: {
2315
+ ...(elementId ? { id: elementId } : {}),
2300
2316
  style: {},
2301
2317
  ...animationAttrs,
2302
2318
  },
@@ -2345,6 +2361,9 @@ function parseIcon(element, parentId, index) {
2345
2361
  function parseVideo(element, parentId, index) {
2346
2362
  const id = generateId();
2347
2363
 
2364
+ // Get element-id for scroll-to/show-hide targeting
2365
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
2366
+
2348
2367
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
2349
2368
  const spacing = parseSpacing(wrapperStyles);
2350
2369
 
@@ -2368,6 +2387,7 @@ function parseVideo(element, parentId, index) {
2368
2387
  parentId,
2369
2388
  fractionalIndex: generateFractionalIndex(index),
2370
2389
  attrs: {
2390
+ ...(elementId ? { id: elementId } : {}),
2371
2391
  'data-video-type': videoType,
2372
2392
  'data-skip-background-settings': background.color ? 'false' : 'true',
2373
2393
  'data-skip-shadow-settings': shadow ? 'false' : 'true',
@@ -2419,6 +2439,9 @@ function parseVideo(element, parentId, index) {
2419
2439
  function parseDivider(element, parentId, index) {
2420
2440
  const id = generateId();
2421
2441
 
2442
+ // Get element-id for scroll-to/show-hide targeting
2443
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
2444
+
2422
2445
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
2423
2446
  const spacing = parseSpacing(wrapperStyles);
2424
2447
 
@@ -2464,6 +2487,7 @@ function parseDivider(element, parentId, index) {
2464
2487
  parentId,
2465
2488
  fractionalIndex: generateFractionalIndex(index),
2466
2489
  attrs: {
2490
+ ...(elementId ? { id: elementId } : {}),
2467
2491
  style: {},
2468
2492
  },
2469
2493
  params: {
@@ -2523,6 +2547,9 @@ function parseDivider(element, parentId, index) {
2523
2547
  function parseInput(element, parentId, index) {
2524
2548
  const id = generateId();
2525
2549
 
2550
+ // Get element-id for scroll-to/show-hide targeting
2551
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
2552
+
2526
2553
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
2527
2554
  const spacing = parseSpacing(wrapperStyles);
2528
2555
 
@@ -2565,6 +2592,7 @@ function parseInput(element, parentId, index) {
2565
2592
  parentId,
2566
2593
  fractionalIndex: generateFractionalIndex(index),
2567
2594
  attrs: {
2595
+ ...(elementId ? { id: elementId } : {}),
2568
2596
  'data-skip-shadow-settings': shadow ? 'false' : 'true',
2569
2597
  type: inputType === 'phone_number' ? 'tel' : (inputType === 'email' ? 'email' : 'text'),
2570
2598
  style: {
@@ -2683,6 +2711,9 @@ function parseInput(element, parentId, index) {
2683
2711
  function parseTextArea(element, parentId, index) {
2684
2712
  const id = generateId();
2685
2713
 
2714
+ // Get element-id for scroll-to/show-hide targeting
2715
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
2716
+
2686
2717
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
2687
2718
  const spacing = parseSpacing(wrapperStyles);
2688
2719
 
@@ -2724,6 +2755,7 @@ function parseTextArea(element, parentId, index) {
2724
2755
  parentId,
2725
2756
  fractionalIndex: generateFractionalIndex(index),
2726
2757
  attrs: {
2758
+ ...(elementId ? { id: elementId } : {}),
2727
2759
  'data-skip-shadow-settings': shadow ? 'false' : 'true',
2728
2760
  style: {
2729
2761
  width,
@@ -2840,6 +2872,9 @@ function parseTextArea(element, parentId, index) {
2840
2872
  function parseSelectBox(element, parentId, index) {
2841
2873
  const id = generateId();
2842
2874
 
2875
+ // Get element-id for scroll-to/show-hide targeting
2876
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
2877
+
2843
2878
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
2844
2879
  const spacing = parseSpacing(wrapperStyles);
2845
2880
 
@@ -2908,6 +2943,7 @@ function parseSelectBox(element, parentId, index) {
2908
2943
  parentId,
2909
2944
  fractionalIndex: generateFractionalIndex(index),
2910
2945
  attrs: {
2946
+ ...(elementId ? { id: elementId } : {}),
2911
2947
  style: {
2912
2948
  width,
2913
2949
  'margin-top': marginTop.value,
@@ -3013,6 +3049,9 @@ function parseSelectBox(element, parentId, index) {
3013
3049
  function parseCheckbox(element, parentId, index) {
3014
3050
  const id = generateId();
3015
3051
 
3052
+ // Get element-id for scroll-to/show-hide targeting
3053
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
3054
+
3016
3055
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
3017
3056
  const spacing = parseSpacing(wrapperStyles);
3018
3057
 
@@ -3052,6 +3091,7 @@ function parseCheckbox(element, parentId, index) {
3052
3091
  parentId,
3053
3092
  fractionalIndex: generateFractionalIndex(index),
3054
3093
  attrs: {
3094
+ ...(elementId ? { id: elementId } : {}),
3055
3095
  style: {},
3056
3096
  },
3057
3097
  params: {
@@ -3164,6 +3204,9 @@ function parseBulletList(element, parentId, index) {
3164
3204
  const id = generateId();
3165
3205
  const contentEditableId = generateId();
3166
3206
 
3207
+ // Get element-id for scroll-to/show-hide targeting
3208
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
3209
+
3167
3210
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
3168
3211
  const spacing = parseSpacing(wrapperStyles);
3169
3212
 
@@ -3291,6 +3334,7 @@ function parseBulletList(element, parentId, index) {
3291
3334
  parentId,
3292
3335
  fractionalIndex: generateFractionalIndex(index),
3293
3336
  attrs: {
3337
+ ...(elementId ? { id: elementId } : {}),
3294
3338
  style: {},
3295
3339
  },
3296
3340
  params: {
@@ -3509,6 +3553,9 @@ function parseBulletList(element, parentId, index) {
3509
3553
  function parseProgressBar(element, parentId, index) {
3510
3554
  const id = generateId();
3511
3555
 
3556
+ // Get element-id for scroll-to/show-hide targeting
3557
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
3558
+
3512
3559
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
3513
3560
  const spacing = parseSpacing(wrapperStyles);
3514
3561
 
@@ -3552,6 +3599,7 @@ function parseProgressBar(element, parentId, index) {
3552
3599
  parentId,
3553
3600
  fractionalIndex: generateFractionalIndex(index),
3554
3601
  attrs: {
3602
+ ...(elementId ? { id: elementId } : {}),
3555
3603
  style: {},
3556
3604
  },
3557
3605
  params: {
@@ -3631,6 +3679,9 @@ function parseProgressBar(element, parentId, index) {
3631
3679
  function parseVideoPopup(element, parentId, index) {
3632
3680
  const id = generateId();
3633
3681
 
3682
+ // Get element-id for scroll-to/show-hide targeting
3683
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
3684
+
3634
3685
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
3635
3686
  const spacing = parseSpacing(wrapperStyles);
3636
3687
  const textAlign = parseTextAlign(wrapperStyles['text-align']);
@@ -3669,6 +3720,7 @@ function parseVideoPopup(element, parentId, index) {
3669
3720
  parentId,
3670
3721
  fractionalIndex: generateFractionalIndex(index),
3671
3722
  attrs: {
3723
+ ...(elementId ? { id: elementId } : {}),
3672
3724
  alt: alt || 'Video thumbnail',
3673
3725
  },
3674
3726
  params: {
@@ -3746,6 +3798,9 @@ function parseVideoPopup(element, parentId, index) {
3746
3798
  function parseCountdown(element, parentId, index) {
3747
3799
  const id = generateId();
3748
3800
 
3801
+ // Get element-id for scroll-to/show-hide targeting
3802
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
3803
+
3749
3804
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
3750
3805
  const spacing = parseSpacing(wrapperStyles);
3751
3806
 
@@ -3819,6 +3874,10 @@ function parseCountdown(element, parentId, index) {
3819
3874
  version: 0,
3820
3875
  parentId,
3821
3876
  fractionalIndex: generateFractionalIndex(index),
3877
+ attrs: {
3878
+ ...(elementId ? { id: elementId } : {}),
3879
+ style: {},
3880
+ },
3822
3881
  params: {
3823
3882
  type: 'countdown',
3824
3883
  countdown_opts: {
@@ -3943,7 +4002,7 @@ function parseCountdown(element, parentId, index) {
3943
4002
 
3944
4003
  // Apply spacing
3945
4004
  const { attrs: spacingAttrs, params: spacingParams } = spacingToAttrsAndParams(spacing);
3946
- Object.assign(node.attrs || (node.attrs = {}), { style: spacingAttrs.style });
4005
+ Object.assign(node.attrs.style, spacingAttrs.style);
3947
4006
  Object.assign(node.params, spacingParams);
3948
4007
 
3949
4008
  // Apply border to amount container
@@ -4463,11 +4522,13 @@ function parsePageTree(rootElement = null) {
4463
4522
  }
4464
4523
 
4465
4524
  // Extract page settings from data attributes
4466
- const textColorRaw = rootElement.getAttribute("data-text-color") || "#334155";
4525
+ // Support both 'color' (simple) and 'text-color' (explicit) for page text color
4526
+ const textColorRaw = rootElement.getAttribute("data-color") || rootElement.getAttribute("data-text-color") || "#334155";
4467
4527
  const linkColorRaw = rootElement.getAttribute("data-link-color") || "#3b82f6";
4468
4528
  const textColor = normalizeColor(textColorRaw);
4469
4529
  const linkColor = normalizeColor(linkColorRaw);
4470
- const fontFamily = rootElement.getAttribute("data-font-family") || "";
4530
+ // Support both 'font' (simple) and 'font-family' attributes
4531
+ const fontFamily = rootElement.getAttribute("data-font") || rootElement.getAttribute("data-font-family") || "";
4471
4532
  const fontWeight = rootElement.getAttribute("data-font-weight") || "";
4472
4533
  // Decode URL-encoded values
4473
4534
  const headerCodeRaw = rootElement.getAttribute("data-header-code") || "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cf-pagetree-parser",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Parse FunnelWind HTML to ClickFunnels PageTree JSON",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/index.js CHANGED
@@ -221,11 +221,13 @@ export function parsePageTree(rootElement = null) {
221
221
  }
222
222
 
223
223
  // Extract page settings from data attributes
224
- const textColorRaw = rootElement.getAttribute("data-text-color") || "#334155";
224
+ // Support both 'color' (simple) and 'text-color' (explicit) for page text color
225
+ const textColorRaw = rootElement.getAttribute("data-color") || rootElement.getAttribute("data-text-color") || "#334155";
225
226
  const linkColorRaw = rootElement.getAttribute("data-link-color") || "#3b82f6";
226
227
  const textColor = normalizeColor(textColorRaw);
227
228
  const linkColor = normalizeColor(linkColorRaw);
228
- const fontFamily = rootElement.getAttribute("data-font-family") || "";
229
+ // Support both 'font' (simple) and 'font-family' attributes
230
+ const fontFamily = rootElement.getAttribute("data-font") || rootElement.getAttribute("data-font-family") || "";
229
231
  const fontWeight = rootElement.getAttribute("data-font-weight") || "";
230
232
  // Decode URL-encoded values
231
233
  const headerCodeRaw = rootElement.getAttribute("data-header-code") || "";
@@ -40,6 +40,9 @@ export function parseButton(element, parentId, index) {
40
40
  const mainTextId = generateId();
41
41
  const subTextId = generateId();
42
42
 
43
+ // Get element-id for scroll-to/show-hide targeting
44
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
45
+
43
46
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
44
47
  const spacing = parseSpacing(wrapperStyles);
45
48
 
@@ -162,6 +165,7 @@ export function parseButton(element, parentId, index) {
162
165
  parentId,
163
166
  fractionalIndex: generateFractionalIndex(index),
164
167
  attrs: {
168
+ ...(elementId ? { id: elementId } : {}),
165
169
  style: {
166
170
  'text-align': textAlign,
167
171
  },
@@ -34,6 +34,9 @@ import {
34
34
  export function parseInput(element, parentId, index) {
35
35
  const id = generateId();
36
36
 
37
+ // Get element-id for scroll-to/show-hide targeting
38
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
39
+
37
40
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
38
41
  const spacing = parseSpacing(wrapperStyles);
39
42
 
@@ -76,6 +79,7 @@ export function parseInput(element, parentId, index) {
76
79
  parentId,
77
80
  fractionalIndex: generateFractionalIndex(index),
78
81
  attrs: {
82
+ ...(elementId ? { id: elementId } : {}),
79
83
  'data-skip-shadow-settings': shadow ? 'false' : 'true',
80
84
  type: inputType === 'phone_number' ? 'tel' : (inputType === 'email' ? 'email' : 'text'),
81
85
  style: {
@@ -194,6 +198,9 @@ export function parseInput(element, parentId, index) {
194
198
  export function parseTextArea(element, parentId, index) {
195
199
  const id = generateId();
196
200
 
201
+ // Get element-id for scroll-to/show-hide targeting
202
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
203
+
197
204
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
198
205
  const spacing = parseSpacing(wrapperStyles);
199
206
 
@@ -235,6 +242,7 @@ export function parseTextArea(element, parentId, index) {
235
242
  parentId,
236
243
  fractionalIndex: generateFractionalIndex(index),
237
244
  attrs: {
245
+ ...(elementId ? { id: elementId } : {}),
238
246
  'data-skip-shadow-settings': shadow ? 'false' : 'true',
239
247
  style: {
240
248
  width,
@@ -351,6 +359,9 @@ export function parseTextArea(element, parentId, index) {
351
359
  export function parseSelectBox(element, parentId, index) {
352
360
  const id = generateId();
353
361
 
362
+ // Get element-id for scroll-to/show-hide targeting
363
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
364
+
354
365
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
355
366
  const spacing = parseSpacing(wrapperStyles);
356
367
 
@@ -419,6 +430,7 @@ export function parseSelectBox(element, parentId, index) {
419
430
  parentId,
420
431
  fractionalIndex: generateFractionalIndex(index),
421
432
  attrs: {
433
+ ...(elementId ? { id: elementId } : {}),
422
434
  style: {
423
435
  width,
424
436
  'margin-top': marginTop.value,
@@ -524,6 +536,9 @@ export function parseSelectBox(element, parentId, index) {
524
536
  export function parseCheckbox(element, parentId, index) {
525
537
  const id = generateId();
526
538
 
539
+ // Get element-id for scroll-to/show-hide targeting
540
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
541
+
527
542
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
528
543
  const spacing = parseSpacing(wrapperStyles);
529
544
 
@@ -563,6 +578,7 @@ export function parseCheckbox(element, parentId, index) {
563
578
  parentId,
564
579
  fractionalIndex: generateFractionalIndex(index),
565
580
  attrs: {
581
+ ...(elementId ? { id: elementId } : {}),
566
582
  style: {},
567
583
  },
568
584
  params: {
@@ -33,6 +33,9 @@ import {
33
33
  export function parseProgressBar(element, parentId, index) {
34
34
  const id = generateId();
35
35
 
36
+ // Get element-id for scroll-to/show-hide targeting
37
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
38
+
36
39
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
37
40
  const spacing = parseSpacing(wrapperStyles);
38
41
 
@@ -76,6 +79,7 @@ export function parseProgressBar(element, parentId, index) {
76
79
  parentId,
77
80
  fractionalIndex: generateFractionalIndex(index),
78
81
  attrs: {
82
+ ...(elementId ? { id: elementId } : {}),
79
83
  style: {},
80
84
  },
81
85
  params: {
@@ -155,6 +159,9 @@ export function parseProgressBar(element, parentId, index) {
155
159
  export function parseVideoPopup(element, parentId, index) {
156
160
  const id = generateId();
157
161
 
162
+ // Get element-id for scroll-to/show-hide targeting
163
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
164
+
158
165
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
159
166
  const spacing = parseSpacing(wrapperStyles);
160
167
  const textAlign = parseTextAlign(wrapperStyles['text-align']);
@@ -193,6 +200,7 @@ export function parseVideoPopup(element, parentId, index) {
193
200
  parentId,
194
201
  fractionalIndex: generateFractionalIndex(index),
195
202
  attrs: {
203
+ ...(elementId ? { id: elementId } : {}),
196
204
  alt: alt || 'Video thumbnail',
197
205
  },
198
206
  params: {
@@ -270,6 +278,9 @@ export function parseVideoPopup(element, parentId, index) {
270
278
  export function parseCountdown(element, parentId, index) {
271
279
  const id = generateId();
272
280
 
281
+ // Get element-id for scroll-to/show-hide targeting
282
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
283
+
273
284
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
274
285
  const spacing = parseSpacing(wrapperStyles);
275
286
 
@@ -343,6 +354,10 @@ export function parseCountdown(element, parentId, index) {
343
354
  version: 0,
344
355
  parentId,
345
356
  fractionalIndex: generateFractionalIndex(index),
357
+ attrs: {
358
+ ...(elementId ? { id: elementId } : {}),
359
+ style: {},
360
+ },
346
361
  params: {
347
362
  type: 'countdown',
348
363
  countdown_opts: {
@@ -467,7 +482,7 @@ export function parseCountdown(element, parentId, index) {
467
482
 
468
483
  // Apply spacing
469
484
  const { attrs: spacingAttrs, params: spacingParams } = spacingToAttrsAndParams(spacing);
470
- Object.assign(node.attrs || (node.attrs = {}), { style: spacingAttrs.style });
485
+ Object.assign(node.attrs.style, spacingAttrs.style);
471
486
  Object.assign(node.params, spacingParams);
472
487
 
473
488
  // Apply border to amount container
@@ -29,6 +29,9 @@ export function parseBulletList(element, parentId, index) {
29
29
  const id = generateId();
30
30
  const contentEditableId = generateId();
31
31
 
32
+ // Get element-id for scroll-to/show-hide targeting
33
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
34
+
32
35
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
33
36
  const spacing = parseSpacing(wrapperStyles);
34
37
 
@@ -156,6 +159,7 @@ export function parseBulletList(element, parentId, index) {
156
159
  parentId,
157
160
  fractionalIndex: generateFractionalIndex(index),
158
161
  attrs: {
162
+ ...(elementId ? { id: elementId } : {}),
159
163
  style: {},
160
164
  },
161
165
  params: {
@@ -35,6 +35,9 @@ import {
35
35
  export function parseImage(element, parentId, index) {
36
36
  const id = generateId();
37
37
 
38
+ // Get element-id for scroll-to/show-hide targeting
39
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
40
+
38
41
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
39
42
  const spacing = parseSpacing(wrapperStyles);
40
43
  const textAlign = parseTextAlign(wrapperStyles['text-align']);
@@ -63,6 +66,7 @@ export function parseImage(element, parentId, index) {
63
66
  parentId,
64
67
  fractionalIndex: generateFractionalIndex(index),
65
68
  attrs: {
69
+ ...(elementId ? { id: elementId } : {}),
66
70
  alt,
67
71
  style: {
68
72
  'text-align': textAlign,
@@ -131,6 +135,9 @@ export function parseImage(element, parentId, index) {
131
135
  export function parseIcon(element, parentId, index) {
132
136
  const id = generateId();
133
137
 
138
+ // Get element-id for scroll-to/show-hide targeting
139
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
140
+
134
141
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
135
142
  const spacing = parseSpacing(wrapperStyles);
136
143
  const textAlign = parseTextAlign(wrapperStyles['text-align']);
@@ -166,6 +173,7 @@ export function parseIcon(element, parentId, index) {
166
173
  parentId,
167
174
  fractionalIndex: generateFractionalIndex(index),
168
175
  attrs: {
176
+ ...(elementId ? { id: elementId } : {}),
169
177
  style: {},
170
178
  ...animationAttrs,
171
179
  },
@@ -214,6 +222,9 @@ export function parseIcon(element, parentId, index) {
214
222
  export function parseVideo(element, parentId, index) {
215
223
  const id = generateId();
216
224
 
225
+ // Get element-id for scroll-to/show-hide targeting
226
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
227
+
217
228
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
218
229
  const spacing = parseSpacing(wrapperStyles);
219
230
 
@@ -237,6 +248,7 @@ export function parseVideo(element, parentId, index) {
237
248
  parentId,
238
249
  fractionalIndex: generateFractionalIndex(index),
239
250
  attrs: {
251
+ ...(elementId ? { id: elementId } : {}),
240
252
  'data-video-type': videoType,
241
253
  'data-skip-background-settings': background.color ? 'false' : 'true',
242
254
  'data-skip-shadow-settings': shadow ? 'false' : 'true',
@@ -288,6 +300,9 @@ export function parseVideo(element, parentId, index) {
288
300
  export function parseDivider(element, parentId, index) {
289
301
  const id = generateId();
290
302
 
303
+ // Get element-id for scroll-to/show-hide targeting
304
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
305
+
291
306
  const wrapperStyles = parseInlineStyle(element.getAttribute('style') || '');
292
307
  const spacing = parseSpacing(wrapperStyles);
293
308
 
@@ -333,6 +348,7 @@ export function parseDivider(element, parentId, index) {
333
348
  parentId,
334
349
  fractionalIndex: generateFractionalIndex(index),
335
350
  attrs: {
351
+ ...(elementId ? { id: elementId } : {}),
336
352
  style: {},
337
353
  },
338
354
  params: {
@@ -42,6 +42,9 @@ function parseTextElement(
42
42
  const id = generateId();
43
43
  const contentEditableId = generateId();
44
44
 
45
+ // Get element-id for scroll-to/show-hide targeting
46
+ const elementId = element.getAttribute('id') || element.getAttribute('data-element-id');
47
+
45
48
  const wrapperStyles = parseInlineStyle(element.getAttribute("style") || "");
46
49
  const spacing = parseSpacing(wrapperStyles);
47
50
 
@@ -136,6 +139,7 @@ function parseTextElement(
136
139
  parentId,
137
140
  fractionalIndex: generateFractionalIndex(index),
138
141
  attrs: {
142
+ ...(elementId ? { id: elementId } : {}),
139
143
  style: {},
140
144
  ...animationAttrs,
141
145
  },