cf-pagetree-parser 1.0.0 → 1.0.3
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 +8 -8
- package/dist/cf-pagetree-parser.js +44 -432
- package/package.json +2 -2
- package/src/index.js +13 -304
- package/src/parsers/button.js +18 -75
- package/src/parsers/layout.js +0 -24
- package/src/parsers/list.js +0 -1
- package/src/parsers/placeholders.js +0 -2
- package/src/parsers/text.js +4 -17
- package/src/utils.js +3 -17
|
@@ -30,11 +30,12 @@ function sanitizeHtml(html) {
|
|
|
30
30
|
* ============================================================================
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Sanitize HTML - passthrough for trusted FunnelWind source content
|
|
35
|
+
*/
|
|
36
|
+
function sanitizeHtml(html) {
|
|
37
|
+
if (!html) return '';
|
|
38
|
+
return html;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
/**
|
|
@@ -280,7 +281,7 @@ function extractTextContent(element) {
|
|
|
280
281
|
/**
|
|
281
282
|
* Parse HTML content to ContentEditableNode children
|
|
282
283
|
* @param {string} html - The HTML content to parse
|
|
283
|
-
* @param {string|null} defaultLinkColor - Default color for links (from
|
|
284
|
+
* @param {string|null} defaultLinkColor - Default color for links (from data attribute)
|
|
284
285
|
*/
|
|
285
286
|
function parseHtmlToTextNodes(html, defaultLinkColor = null) {
|
|
286
287
|
const temp = document.createElement('div');
|
|
@@ -922,7 +923,6 @@ function parseSectionContainer(element, parentId, index, parseChildren) {
|
|
|
922
923
|
marginTop: spacing.marginTop || parseValueWithUnit('0px'),
|
|
923
924
|
};
|
|
924
925
|
const overlay = element.getAttribute('data-overlay');
|
|
925
|
-
const paintColors = element.getAttribute('data-paint-colors');
|
|
926
926
|
|
|
927
927
|
// Video background attributes
|
|
928
928
|
const videoBgUrl = element.getAttribute('data-video-bg-url');
|
|
@@ -966,11 +966,6 @@ function parseSectionContainer(element, parentId, index, parseChildren) {
|
|
|
966
966
|
node.attrs.id = elementId;
|
|
967
967
|
}
|
|
968
968
|
|
|
969
|
-
// Add paint colors if present
|
|
970
|
-
if (paintColors) {
|
|
971
|
-
node.attrs['data-paint-colors'] = paintColors;
|
|
972
|
-
}
|
|
973
|
-
|
|
974
969
|
// Apply spacing
|
|
975
970
|
const { attrs: spacingAttrs, params: spacingParams } = spacingToAttrsAndParams(rowSpacingWithDefaults);
|
|
976
971
|
Object.assign(node.attrs.style, spacingAttrs.style);
|
|
@@ -1099,7 +1094,6 @@ function parseRowContainer(element, parentId, index, parseChildren) {
|
|
|
1099
1094
|
marginTop: spacing.marginTop || parseValueWithUnit('0px'),
|
|
1100
1095
|
};
|
|
1101
1096
|
const overlay = element.getAttribute('data-overlay');
|
|
1102
|
-
const paintColors = element.getAttribute('data-paint-colors');
|
|
1103
1097
|
|
|
1104
1098
|
const width = parseValueWithUnit(styles.width || '1170px');
|
|
1105
1099
|
|
|
@@ -1154,11 +1148,6 @@ function parseRowContainer(element, parentId, index, parseChildren) {
|
|
|
1154
1148
|
node.attrs.id = elementId;
|
|
1155
1149
|
}
|
|
1156
1150
|
|
|
1157
|
-
// Add paint colors if present
|
|
1158
|
-
if (paintColors) {
|
|
1159
|
-
node.attrs['data-paint-colors'] = paintColors;
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
1151
|
// Add className if set
|
|
1163
1152
|
if (className) {
|
|
1164
1153
|
node.attrs.className = className;
|
|
@@ -1302,7 +1291,6 @@ function parseColContainer(element, parentId, index, parseChildren) {
|
|
|
1302
1291
|
const overlay = colInner.getAttribute('data-overlay');
|
|
1303
1292
|
const separateCorners = colInner.getAttribute('data-separate-corners') === 'true';
|
|
1304
1293
|
const borderRadius = parseBorderRadius(innerStyles);
|
|
1305
|
-
const paintColors = colInner.getAttribute('data-paint-colors');
|
|
1306
1294
|
|
|
1307
1295
|
const colInnerSelector = node.selectors['& > .col-inner'];
|
|
1308
1296
|
|
|
@@ -1418,11 +1406,6 @@ function parseColContainer(element, parentId, index, parseChildren) {
|
|
|
1418
1406
|
colInnerSelector.attrs['data-skip-background-settings'] =
|
|
1419
1407
|
(hasBackground || overlay) ? 'false' : 'true';
|
|
1420
1408
|
|
|
1421
|
-
// Add paint colors if present
|
|
1422
|
-
if (paintColors) {
|
|
1423
|
-
colInnerSelector.attrs['data-paint-colors'] = paintColors;
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
1409
|
// Parse children from col-inner, skipping overlay and content wrapper
|
|
1427
1410
|
let childIdx = 0;
|
|
1428
1411
|
const parseColInnerChildren = (container) => {
|
|
@@ -1482,7 +1465,6 @@ function parseFlexContainer(element, parentId, index, parseChildren) {
|
|
|
1482
1465
|
marginTop: spacing.marginTop || parseValueWithUnit('0px'),
|
|
1483
1466
|
};
|
|
1484
1467
|
const overlay = element.getAttribute('data-overlay');
|
|
1485
|
-
const paintColors = element.getAttribute('data-paint-colors');
|
|
1486
1468
|
|
|
1487
1469
|
const width = parseValueWithUnit(styles.width || '100%', '%');
|
|
1488
1470
|
const height = styles.height ? parseValueWithUnit(styles.height, 'px') : null;
|
|
@@ -1524,11 +1506,6 @@ function parseFlexContainer(element, parentId, index, parseChildren) {
|
|
|
1524
1506
|
node.attrs.id = elementId;
|
|
1525
1507
|
}
|
|
1526
1508
|
|
|
1527
|
-
// Add paint colors if present
|
|
1528
|
-
if (paintColors) {
|
|
1529
|
-
node.attrs['data-paint-colors'] = paintColors;
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1532
1509
|
// Add width
|
|
1533
1510
|
node.attrs.style.width = width.value;
|
|
1534
1511
|
node.params['width--unit'] = width.unit;
|
|
@@ -1640,8 +1617,7 @@ function parseTextElement(
|
|
|
1640
1617
|
parentId,
|
|
1641
1618
|
index,
|
|
1642
1619
|
type,
|
|
1643
|
-
selector
|
|
1644
|
-
_styleGuideAttr
|
|
1620
|
+
selector
|
|
1645
1621
|
) {
|
|
1646
1622
|
const id = generateId();
|
|
1647
1623
|
const contentEditableId = generateId();
|
|
@@ -1730,14 +1706,6 @@ function parseTextElement(
|
|
|
1730
1706
|
selectorStyle["font-family"] = fontFamily;
|
|
1731
1707
|
}
|
|
1732
1708
|
|
|
1733
|
-
// Determine the style-guide-override param name based on type
|
|
1734
|
-
const styleGuideOverrideMap = {
|
|
1735
|
-
"Headline/V1": "style-guide-override-headline",
|
|
1736
|
-
"SubHeadline/V1": "style-guide-override-subheadline",
|
|
1737
|
-
"Paragraph/V1": "style-guide-override-content",
|
|
1738
|
-
};
|
|
1739
|
-
const styleGuideOverrideParam = styleGuideOverrideMap[type];
|
|
1740
|
-
|
|
1741
1709
|
// Parse animation attributes
|
|
1742
1710
|
const { attrs: animationAttrs, params: animationParams } = parseAnimationAttrs(element);
|
|
1743
1711
|
|
|
@@ -1764,7 +1732,6 @@ function parseTextElement(
|
|
|
1764
1732
|
style: selectorStyle,
|
|
1765
1733
|
},
|
|
1766
1734
|
params: {
|
|
1767
|
-
[styleGuideOverrideParam]: true,
|
|
1768
1735
|
"font-size--unit": fontSize ? fontSize.unit : "px",
|
|
1769
1736
|
"line-height--unit": "%",
|
|
1770
1737
|
"letter-spacing--unit": "rem",
|
|
@@ -1847,8 +1814,7 @@ function parseHeadline(element, parentId, index) {
|
|
|
1847
1814
|
parentId,
|
|
1848
1815
|
index,
|
|
1849
1816
|
"Headline/V1",
|
|
1850
|
-
".elHeadline"
|
|
1851
|
-
"data-style-guide-headline"
|
|
1817
|
+
".elHeadline"
|
|
1852
1818
|
);
|
|
1853
1819
|
}
|
|
1854
1820
|
|
|
@@ -1861,8 +1827,7 @@ function parseSubHeadline(element, parentId, index) {
|
|
|
1861
1827
|
parentId,
|
|
1862
1828
|
index,
|
|
1863
1829
|
"SubHeadline/V1",
|
|
1864
|
-
".elSubheadline"
|
|
1865
|
-
"data-style-guide-subheadline"
|
|
1830
|
+
".elSubheadline"
|
|
1866
1831
|
);
|
|
1867
1832
|
}
|
|
1868
1833
|
|
|
@@ -1875,8 +1840,7 @@ function parseParagraph(element, parentId, index) {
|
|
|
1875
1840
|
parentId,
|
|
1876
1841
|
index,
|
|
1877
1842
|
"Paragraph/V1",
|
|
1878
|
-
".elParagraph"
|
|
1879
|
-
"data-style-guide-content"
|
|
1843
|
+
".elParagraph"
|
|
1880
1844
|
);
|
|
1881
1845
|
}
|
|
1882
1846
|
|
|
@@ -1898,9 +1862,8 @@ function parseParagraph(element, parentId, index) {
|
|
|
1898
1862
|
* @param {HTMLElement} element - The button element
|
|
1899
1863
|
* @param {string} parentId - Parent element ID
|
|
1900
1864
|
* @param {number} index - Child index
|
|
1901
|
-
* @param {Object} styleguideData - Optional styleguide data for looking up button styles
|
|
1902
1865
|
*/
|
|
1903
|
-
function parseButton(element, parentId, index
|
|
1866
|
+
function parseButton(element, parentId, index) {
|
|
1904
1867
|
const id = generateId();
|
|
1905
1868
|
const mainTextId = generateId();
|
|
1906
1869
|
const subTextId = generateId();
|
|
@@ -1917,15 +1880,6 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
1917
1880
|
const hideIds = element.getAttribute('data-hide-ids');
|
|
1918
1881
|
const elButtonType = element.getAttribute('data-elbuttontype');
|
|
1919
1882
|
|
|
1920
|
-
// Check for styleguide button
|
|
1921
|
-
const styleGuideButton = element.getAttribute('data-style-guide-button');
|
|
1922
|
-
|
|
1923
|
-
// Look up button style from styleguide if available
|
|
1924
|
-
let styleguideButtonStyle = null;
|
|
1925
|
-
if (styleGuideButton && styleguideData?.buttons) {
|
|
1926
|
-
styleguideButtonStyle = styleguideData.buttons.find(btn => btn.id === styleGuideButton);
|
|
1927
|
-
}
|
|
1928
|
-
|
|
1929
1883
|
// Find the anchor element for fallback parsing
|
|
1930
1884
|
const anchor = element.querySelector('a');
|
|
1931
1885
|
const anchorStyles = anchor ? parseInlineStyle(anchor.getAttribute('style') || '') : {};
|
|
@@ -1934,21 +1888,16 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
1934
1888
|
const textSpan = anchor ? anchor.querySelector('span') : null;
|
|
1935
1889
|
const textStyles = textSpan ? parseInlineStyle(textSpan.getAttribute('style') || '') : {};
|
|
1936
1890
|
|
|
1937
|
-
// Read from
|
|
1938
|
-
// Styleguide button structure: { regular: { bg, color }, hover: { bg, color }, borderRadius, borderWidth, borderColor }
|
|
1891
|
+
// Read from data attributes first, then inline styles
|
|
1939
1892
|
const bgAttr = element.getAttribute('data-bg');
|
|
1940
|
-
const bgColor =
|
|
1941
|
-
? normalizeColor(
|
|
1942
|
-
:
|
|
1943
|
-
? normalizeColor(bgAttr)
|
|
1944
|
-
: (normalizeColor(anchorStyles['background-color']) || '#3b82f6');
|
|
1893
|
+
const bgColor = bgAttr
|
|
1894
|
+
? normalizeColor(bgAttr)
|
|
1895
|
+
: (normalizeColor(anchorStyles['background-color']) || '#3b82f6');
|
|
1945
1896
|
|
|
1946
1897
|
const textColorAttr = element.getAttribute('data-color');
|
|
1947
|
-
const textColor =
|
|
1948
|
-
? normalizeColor(
|
|
1949
|
-
:
|
|
1950
|
-
? normalizeColor(textColorAttr)
|
|
1951
|
-
: (normalizeColor(textStyles.color) || '#ffffff');
|
|
1898
|
+
const textColor = textColorAttr
|
|
1899
|
+
? normalizeColor(textColorAttr)
|
|
1900
|
+
: (normalizeColor(textStyles.color) || '#ffffff');
|
|
1952
1901
|
|
|
1953
1902
|
// Font styling - prefer data attributes
|
|
1954
1903
|
const fontSizeAttr = element.getAttribute('data-size');
|
|
@@ -1962,40 +1911,26 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
1962
1911
|
const paddingHorizontal = pxAttr ? parseValueWithUnit(pxAttr) : parseValueWithUnit(anchorStyles['padding-right'] || '32px');
|
|
1963
1912
|
const paddingVertical = pyAttr ? parseValueWithUnit(pyAttr) : parseValueWithUnit(anchorStyles['padding-top'] || '16px');
|
|
1964
1913
|
|
|
1965
|
-
// Border and corners -
|
|
1914
|
+
// Border and corners - data attributes first, then inline styles
|
|
1966
1915
|
const roundedAttr = element.getAttribute('data-rounded');
|
|
1967
|
-
const borderRadius =
|
|
1968
|
-
?
|
|
1969
|
-
:
|
|
1970
|
-
? parseValueWithUnit(roundedAttr)
|
|
1971
|
-
: parseBorderRadius(anchorStyles);
|
|
1916
|
+
const borderRadius = roundedAttr
|
|
1917
|
+
? parseValueWithUnit(roundedAttr)
|
|
1918
|
+
: parseBorderRadius(anchorStyles);
|
|
1972
1919
|
|
|
1973
1920
|
const borderColorAttr = element.getAttribute('data-border-color');
|
|
1974
|
-
const borderColor =
|
|
1975
|
-
? normalizeColor(
|
|
1976
|
-
:
|
|
1977
|
-
? normalizeColor(borderColorAttr)
|
|
1978
|
-
: normalizeColor(anchorStyles['border-color']);
|
|
1921
|
+
const borderColor = borderColorAttr
|
|
1922
|
+
? normalizeColor(borderColorAttr)
|
|
1923
|
+
: normalizeColor(anchorStyles['border-color']);
|
|
1979
1924
|
|
|
1980
1925
|
const borderWidthAttr = element.getAttribute('data-border-width');
|
|
1981
|
-
const borderWidth =
|
|
1982
|
-
?
|
|
1983
|
-
:
|
|
1984
|
-
? parseValueWithUnit(borderWidthAttr)
|
|
1985
|
-
: parseValueWithUnit(anchorStyles['border-width'] || '0');
|
|
1926
|
+
const borderWidth = borderWidthAttr
|
|
1927
|
+
? parseValueWithUnit(borderWidthAttr)
|
|
1928
|
+
: parseValueWithUnit(anchorStyles['border-width'] || '0');
|
|
1986
1929
|
|
|
1987
1930
|
// Shadow
|
|
1988
1931
|
const shadowAttr = element.getAttribute('data-shadow');
|
|
1989
1932
|
const shadow = shadowAttr ? parseShadow(shadowAttr) : parseShadow(anchorStyles['box-shadow']);
|
|
1990
1933
|
|
|
1991
|
-
// Hover state from styleguide
|
|
1992
|
-
const hoverBgColor = styleguideButtonStyle?.hover?.bg
|
|
1993
|
-
? normalizeColor(styleguideButtonStyle.hover.bg)
|
|
1994
|
-
: null;
|
|
1995
|
-
const hoverTextColor = styleguideButtonStyle?.hover?.color
|
|
1996
|
-
? normalizeColor(styleguideButtonStyle.hover.color)
|
|
1997
|
-
: null;
|
|
1998
|
-
|
|
1999
1934
|
// Alignment
|
|
2000
1935
|
const textAlign = element.getAttribute('data-align') || parseTextAlign(wrapperStyles['text-align']);
|
|
2001
1936
|
|
|
@@ -2029,7 +1964,6 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
2029
1964
|
const fullWidth = element.getAttribute('data-full-width') === 'true';
|
|
2030
1965
|
|
|
2031
1966
|
// Build button selector - always include padding params
|
|
2032
|
-
// When using styleguide button, also include data-style-guide-button attribute
|
|
2033
1967
|
const buttonSelector = {
|
|
2034
1968
|
attrs: {
|
|
2035
1969
|
style: {},
|
|
@@ -2039,7 +1973,6 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
2039
1973
|
'--style-padding-horizontal--unit': paddingHorizontal ? paddingHorizontal.unit : 'px',
|
|
2040
1974
|
'--style-padding-vertical': paddingVertical ? paddingVertical.value : 16,
|
|
2041
1975
|
'--style-padding-vertical--unit': paddingVertical ? paddingVertical.unit : 'px',
|
|
2042
|
-
'style-guide-override-button': true,
|
|
2043
1976
|
'--style-background-color': bgColor,
|
|
2044
1977
|
'--style-border-color': borderColor || 'transparent',
|
|
2045
1978
|
'--style-border-width': borderWidth ? borderWidth.value : 0,
|
|
@@ -2047,11 +1980,6 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
2047
1980
|
},
|
|
2048
1981
|
};
|
|
2049
1982
|
|
|
2050
|
-
// Add styleguide button reference if present
|
|
2051
|
-
if (styleGuideButton) {
|
|
2052
|
-
buttonSelector.attrs['data-style-guide-button'] = styleGuideButton;
|
|
2053
|
-
}
|
|
2054
|
-
|
|
2055
1983
|
// Parse animation attributes
|
|
2056
1984
|
const { attrs: animationAttrs, params: animationParams } = parseAnimationAttrs(element);
|
|
2057
1985
|
|
|
@@ -2218,27 +2146,6 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
2218
2146
|
node.selectors['.elButton .elButtonSub'].attrs.style.color = subTextColor;
|
|
2219
2147
|
}
|
|
2220
2148
|
|
|
2221
|
-
// Add hover state selectors if available from styleguide
|
|
2222
|
-
if (hoverBgColor) {
|
|
2223
|
-
node.selectors['.elButton:hover'] = {
|
|
2224
|
-
attrs: {
|
|
2225
|
-
style: {},
|
|
2226
|
-
},
|
|
2227
|
-
params: {
|
|
2228
|
-
'--style-background-color': hoverBgColor,
|
|
2229
|
-
},
|
|
2230
|
-
};
|
|
2231
|
-
}
|
|
2232
|
-
if (hoverTextColor) {
|
|
2233
|
-
node.selectors['.elButton:hover .elButtonText'] = {
|
|
2234
|
-
attrs: {
|
|
2235
|
-
style: {
|
|
2236
|
-
color: hoverTextColor,
|
|
2237
|
-
},
|
|
2238
|
-
},
|
|
2239
|
-
};
|
|
2240
|
-
}
|
|
2241
|
-
|
|
2242
2149
|
return node;
|
|
2243
2150
|
}
|
|
2244
2151
|
|
|
@@ -3394,7 +3301,6 @@ function parseBulletList(element, parentId, index) {
|
|
|
3394
3301
|
selectors: {
|
|
3395
3302
|
'.elBulletList': {
|
|
3396
3303
|
attrs: {
|
|
3397
|
-
'data-style-guide-content': 'm',
|
|
3398
3304
|
'data-skip-text-shadow-settings': 'true',
|
|
3399
3305
|
style: {
|
|
3400
3306
|
color: textColor,
|
|
@@ -4216,8 +4122,6 @@ function parseCheckoutPlaceholder(element, parentId, index) {
|
|
|
4216
4122
|
fractionalIndex: generateFractionalIndex(index),
|
|
4217
4123
|
attrs: {
|
|
4218
4124
|
style: {
|
|
4219
|
-
'--container-font-family': 'var(--style-guide-font-family-content)',
|
|
4220
|
-
'--input-headline-font-family': 'var(--style-guide-font-family-subheadline)',
|
|
4221
4125
|
'--multiple-payments-font-family': 'sans-serif',
|
|
4222
4126
|
'--input-background-color': '#FFFFFF',
|
|
4223
4127
|
},
|
|
@@ -4391,276 +4295,6 @@ function parseConfirmationPlaceholder(element, parentId, index) {
|
|
|
4391
4295
|
* ============================================================================
|
|
4392
4296
|
*/
|
|
4393
4297
|
|
|
4394
|
-
/**
|
|
4395
|
-
* Get typescale sizes calculated from baseSize and scaleRatio.
|
|
4396
|
-
* Matches StyleguideEditor.tsx and cf-elements.js getTypescale() for consistency.
|
|
4397
|
-
* Returns element-specific scales because headlines, subheadlines, and paragraphs
|
|
4398
|
-
* have different sizes at the same preset (e.g., "s" for headline = 20px, "s" for paragraph = 13px).
|
|
4399
|
-
*
|
|
4400
|
-
* @param {Object} typography - Typography settings with baseSize and scaleRatio
|
|
4401
|
-
* @returns {Object|null} - Map of element types to their size preset maps
|
|
4402
|
-
*/
|
|
4403
|
-
function getTypescale(typography) {
|
|
4404
|
-
if (!typography) return null;
|
|
4405
|
-
|
|
4406
|
-
const { baseSize = 16, scaleRatio = 1.25 } = typography;
|
|
4407
|
-
const r = scaleRatio;
|
|
4408
|
-
const b = baseSize;
|
|
4409
|
-
|
|
4410
|
-
// Build the base scale points (negative = smaller, positive = larger)
|
|
4411
|
-
const scale = {
|
|
4412
|
-
n3: Math.round(b / Math.pow(r, 3)), // ~8
|
|
4413
|
-
n2: Math.round(b / Math.pow(r, 2)), // ~10
|
|
4414
|
-
n1: Math.round(b / r), // ~13
|
|
4415
|
-
base: b, // 16
|
|
4416
|
-
p1: Math.round(b * r), // ~20
|
|
4417
|
-
p2: Math.round(b * Math.pow(r, 2)), // ~25
|
|
4418
|
-
p3: Math.round(b * Math.pow(r, 3)), // ~31
|
|
4419
|
-
p4: Math.round(b * Math.pow(r, 4)), // ~39
|
|
4420
|
-
p5: Math.round(b * Math.pow(r, 5)), // ~49
|
|
4421
|
-
p6: Math.round(b * Math.pow(r, 6)), // ~61
|
|
4422
|
-
p7: Math.round(b * Math.pow(r, 7)), // ~76
|
|
4423
|
-
p8: Math.round(b * Math.pow(r, 8)), // ~95
|
|
4424
|
-
};
|
|
4425
|
-
|
|
4426
|
-
// Return element-specific scales (each element type maps presets to different scale points)
|
|
4427
|
-
return {
|
|
4428
|
-
headline: {
|
|
4429
|
-
"5xl": scale.p8,
|
|
4430
|
-
"4xl": scale.p7,
|
|
4431
|
-
"3xl": scale.p6,
|
|
4432
|
-
"2xl": scale.p5,
|
|
4433
|
-
xl: scale.p4,
|
|
4434
|
-
l: scale.p3,
|
|
4435
|
-
lg: scale.p3,
|
|
4436
|
-
m: scale.p2,
|
|
4437
|
-
md: scale.p2,
|
|
4438
|
-
s: scale.p1,
|
|
4439
|
-
sm: scale.p1,
|
|
4440
|
-
xs: scale.base,
|
|
4441
|
-
},
|
|
4442
|
-
subheadline: {
|
|
4443
|
-
"5xl": scale.p7,
|
|
4444
|
-
"4xl": scale.p6,
|
|
4445
|
-
"3xl": scale.p5,
|
|
4446
|
-
"2xl": scale.p4,
|
|
4447
|
-
xl: scale.p3,
|
|
4448
|
-
l: scale.p2,
|
|
4449
|
-
lg: scale.p2,
|
|
4450
|
-
m: scale.p1,
|
|
4451
|
-
md: scale.p1,
|
|
4452
|
-
s: scale.base,
|
|
4453
|
-
sm: scale.base,
|
|
4454
|
-
xs: scale.n1,
|
|
4455
|
-
},
|
|
4456
|
-
paragraph: {
|
|
4457
|
-
"5xl": scale.p6,
|
|
4458
|
-
"4xl": scale.p5,
|
|
4459
|
-
"3xl": scale.p4,
|
|
4460
|
-
"2xl": scale.p3,
|
|
4461
|
-
xl: scale.p2,
|
|
4462
|
-
l: scale.p1,
|
|
4463
|
-
lg: scale.p1,
|
|
4464
|
-
m: scale.base,
|
|
4465
|
-
md: scale.base,
|
|
4466
|
-
s: scale.n1,
|
|
4467
|
-
sm: scale.n1,
|
|
4468
|
-
xs: scale.n2,
|
|
4469
|
-
},
|
|
4470
|
-
};
|
|
4471
|
-
}
|
|
4472
|
-
|
|
4473
|
-
/**
|
|
4474
|
-
* Apply styleguide fonts and colors as data attributes before parsing.
|
|
4475
|
-
* This ensures the parser captures styleguide-applied values.
|
|
4476
|
-
*
|
|
4477
|
-
* @param {Document|HTMLElement} root - The root element or document to process
|
|
4478
|
-
* @param {Object} styleguideData - Optional styleguide data (will try to read from embedded JSON if not provided)
|
|
4479
|
-
*/
|
|
4480
|
-
function applyStyleguideDataAttributes(root, styleguideData = null) {
|
|
4481
|
-
// Try to get styleguide from embedded JSON if not provided
|
|
4482
|
-
if (!styleguideData) {
|
|
4483
|
-
const scriptEl = root.querySelector
|
|
4484
|
-
? root.querySelector("#cf-styleguide-data")
|
|
4485
|
-
: root.getElementById
|
|
4486
|
-
? root.getElementById("cf-styleguide-data")
|
|
4487
|
-
: null;
|
|
4488
|
-
if (scriptEl) {
|
|
4489
|
-
try {
|
|
4490
|
-
styleguideData = JSON.parse(scriptEl.textContent);
|
|
4491
|
-
} catch (e) {
|
|
4492
|
-
console.warn("PageTree Parser: Failed to parse styleguide data:", e);
|
|
4493
|
-
return;
|
|
4494
|
-
}
|
|
4495
|
-
}
|
|
4496
|
-
}
|
|
4497
|
-
|
|
4498
|
-
if (!styleguideData) return;
|
|
4499
|
-
|
|
4500
|
-
const { typography, paintThemes, colors } = styleguideData;
|
|
4501
|
-
|
|
4502
|
-
// Helper to get color hex by ID
|
|
4503
|
-
const getColorHex = (colorId) => {
|
|
4504
|
-
if (!colors) return "#000000";
|
|
4505
|
-
const color = colors.find((c) => c.id === colorId);
|
|
4506
|
-
return color ? color.hex : "#000000";
|
|
4507
|
-
};
|
|
4508
|
-
|
|
4509
|
-
// Apply typography fonts to elements without explicit fonts
|
|
4510
|
-
if (typography) {
|
|
4511
|
-
const { headlineFont, subheadlineFont, contentFont } = typography;
|
|
4512
|
-
|
|
4513
|
-
if (headlineFont) {
|
|
4514
|
-
root
|
|
4515
|
-
.querySelectorAll('[data-type="Headline/V1"]:not([data-font])')
|
|
4516
|
-
.forEach((el) => {
|
|
4517
|
-
el.setAttribute("data-font", headlineFont);
|
|
4518
|
-
});
|
|
4519
|
-
}
|
|
4520
|
-
|
|
4521
|
-
if (subheadlineFont) {
|
|
4522
|
-
root
|
|
4523
|
-
.querySelectorAll('[data-type="SubHeadline/V1"]:not([data-font])')
|
|
4524
|
-
.forEach((el) => {
|
|
4525
|
-
el.setAttribute("data-font", subheadlineFont);
|
|
4526
|
-
});
|
|
4527
|
-
}
|
|
4528
|
-
|
|
4529
|
-
if (contentFont) {
|
|
4530
|
-
root
|
|
4531
|
-
.querySelectorAll('[data-type="Paragraph/V1"]:not([data-font])')
|
|
4532
|
-
.forEach((el) => {
|
|
4533
|
-
el.setAttribute("data-font", contentFont);
|
|
4534
|
-
});
|
|
4535
|
-
}
|
|
4536
|
-
}
|
|
4537
|
-
|
|
4538
|
-
// Helper to check if element's closest paint-themed ancestor is the given container
|
|
4539
|
-
// This prevents applying colors to elements inside nested non-paint containers
|
|
4540
|
-
const isDirectPaintDescendant = (el, paintContainer) => {
|
|
4541
|
-
// Find the closest ancestor with data-paint-colors attribute
|
|
4542
|
-
const closestPaint = el.closest("[data-paint-colors]");
|
|
4543
|
-
// Element should only get colors if its closest paint ancestor is this container
|
|
4544
|
-
return closestPaint === paintContainer;
|
|
4545
|
-
};
|
|
4546
|
-
|
|
4547
|
-
// Apply paint theme colors - OVERRIDE existing (paint themes take precedence)
|
|
4548
|
-
// Only apply to elements that are direct descendants (no intervening non-paint containers)
|
|
4549
|
-
if (paintThemes?.length) {
|
|
4550
|
-
paintThemes.forEach((theme) => {
|
|
4551
|
-
const containers = root.querySelectorAll(
|
|
4552
|
-
`[data-paint-colors="${theme.id}"]`
|
|
4553
|
-
);
|
|
4554
|
-
containers.forEach((container) => {
|
|
4555
|
-
const headlineColor = getColorHex(theme.headlineColorId);
|
|
4556
|
-
const subheadlineColor = getColorHex(theme.subheadlineColorId);
|
|
4557
|
-
const contentColor = getColorHex(theme.contentColorId);
|
|
4558
|
-
const iconColor = getColorHex(theme.iconColorId);
|
|
4559
|
-
const linkColor = theme.linkColorId
|
|
4560
|
-
? getColorHex(theme.linkColorId)
|
|
4561
|
-
: null;
|
|
4562
|
-
|
|
4563
|
-
// Apply headline color (only to direct paint descendants)
|
|
4564
|
-
container
|
|
4565
|
-
.querySelectorAll('[data-type="Headline/V1"]')
|
|
4566
|
-
.forEach((el) => {
|
|
4567
|
-
if (isDirectPaintDescendant(el, container)) {
|
|
4568
|
-
if (!el.hasAttribute("data-color-explicit")) {
|
|
4569
|
-
el.setAttribute("data-color", headlineColor);
|
|
4570
|
-
}
|
|
4571
|
-
if (linkColor) el.setAttribute("data-link-color", linkColor);
|
|
4572
|
-
}
|
|
4573
|
-
});
|
|
4574
|
-
|
|
4575
|
-
// Apply subheadline color (only to direct paint descendants)
|
|
4576
|
-
container
|
|
4577
|
-
.querySelectorAll('[data-type="SubHeadline/V1"]')
|
|
4578
|
-
.forEach((el) => {
|
|
4579
|
-
if (isDirectPaintDescendant(el, container)) {
|
|
4580
|
-
if (!el.hasAttribute("data-color-explicit")) {
|
|
4581
|
-
el.setAttribute("data-color", subheadlineColor);
|
|
4582
|
-
}
|
|
4583
|
-
if (linkColor) el.setAttribute("data-link-color", linkColor);
|
|
4584
|
-
}
|
|
4585
|
-
});
|
|
4586
|
-
|
|
4587
|
-
// Apply content/paragraph color (only to direct paint descendants)
|
|
4588
|
-
container
|
|
4589
|
-
.querySelectorAll('[data-type="Paragraph/V1"]')
|
|
4590
|
-
.forEach((el) => {
|
|
4591
|
-
if (isDirectPaintDescendant(el, container)) {
|
|
4592
|
-
if (!el.hasAttribute("data-color-explicit")) {
|
|
4593
|
-
el.setAttribute("data-color", contentColor);
|
|
4594
|
-
}
|
|
4595
|
-
if (linkColor) el.setAttribute("data-link-color", linkColor);
|
|
4596
|
-
}
|
|
4597
|
-
});
|
|
4598
|
-
|
|
4599
|
-
// Apply icon color (only to direct paint descendants)
|
|
4600
|
-
container.querySelectorAll('[data-type="Icon/V1"]').forEach((el) => {
|
|
4601
|
-
if (isDirectPaintDescendant(el, container)) {
|
|
4602
|
-
if (!el.hasAttribute("data-color-explicit")) {
|
|
4603
|
-
el.setAttribute("data-color", iconColor);
|
|
4604
|
-
}
|
|
4605
|
-
}
|
|
4606
|
-
});
|
|
4607
|
-
|
|
4608
|
-
// Apply colors to bullet lists (only to direct paint descendants)
|
|
4609
|
-
container
|
|
4610
|
-
.querySelectorAll('[data-type="BulletList/V1"]')
|
|
4611
|
-
.forEach((el) => {
|
|
4612
|
-
if (isDirectPaintDescendant(el, container)) {
|
|
4613
|
-
if (!el.hasAttribute("data-text-color-explicit")) {
|
|
4614
|
-
el.setAttribute("data-text-color", contentColor);
|
|
4615
|
-
}
|
|
4616
|
-
if (!el.hasAttribute("data-icon-color-explicit")) {
|
|
4617
|
-
el.setAttribute("data-icon-color", iconColor);
|
|
4618
|
-
}
|
|
4619
|
-
if (linkColor) el.setAttribute("data-link-color", linkColor);
|
|
4620
|
-
}
|
|
4621
|
-
});
|
|
4622
|
-
});
|
|
4623
|
-
});
|
|
4624
|
-
}
|
|
4625
|
-
|
|
4626
|
-
// Resolve size presets (xl, l, m, s) to pixel values for text elements
|
|
4627
|
-
// This allows the parser to capture correct font sizes even when using presets
|
|
4628
|
-
if (typography) {
|
|
4629
|
-
const typescale = getTypescale(typography);
|
|
4630
|
-
|
|
4631
|
-
if (typescale) {
|
|
4632
|
-
// Map data-type to element scale key
|
|
4633
|
-
const elementTypeMap = {
|
|
4634
|
-
"Headline/V1": "headline",
|
|
4635
|
-
"SubHeadline/V1": "subheadline",
|
|
4636
|
-
"Paragraph/V1": "paragraph",
|
|
4637
|
-
"BulletList/V1": "paragraph", // Bullet lists use paragraph scale
|
|
4638
|
-
};
|
|
4639
|
-
|
|
4640
|
-
// Find all text elements with a size attribute
|
|
4641
|
-
const textElements = root.querySelectorAll(
|
|
4642
|
-
'[data-type="Headline/V1"][data-size], ' +
|
|
4643
|
-
'[data-type="SubHeadline/V1"][data-size], ' +
|
|
4644
|
-
'[data-type="Paragraph/V1"][data-size], ' +
|
|
4645
|
-
'[data-type="BulletList/V1"][data-size]'
|
|
4646
|
-
);
|
|
4647
|
-
|
|
4648
|
-
textElements.forEach((el) => {
|
|
4649
|
-
const sizeAttr = el.getAttribute("data-size");
|
|
4650
|
-
const dataType = el.getAttribute("data-type");
|
|
4651
|
-
const elementKey = elementTypeMap[dataType] || "headline";
|
|
4652
|
-
const elementScale = typescale[elementKey];
|
|
4653
|
-
|
|
4654
|
-
// Check if it's a preset (not already a px value)
|
|
4655
|
-
if (sizeAttr && elementScale && elementScale[sizeAttr] !== undefined) {
|
|
4656
|
-
// Set the resolved pixel value as a separate attribute
|
|
4657
|
-
el.setAttribute("data-size-resolved", `${elementScale[sizeAttr]}px`);
|
|
4658
|
-
}
|
|
4659
|
-
});
|
|
4660
|
-
}
|
|
4661
|
-
}
|
|
4662
|
-
}
|
|
4663
|
-
|
|
4664
4298
|
/**
|
|
4665
4299
|
* Map of data-type to parser function
|
|
4666
4300
|
*/
|
|
@@ -4696,10 +4330,10 @@ const PARSER_MAP = {
|
|
|
4696
4330
|
};
|
|
4697
4331
|
|
|
4698
4332
|
/**
|
|
4699
|
-
* Create parseElement function
|
|
4700
|
-
*
|
|
4333
|
+
* Create parseElement function
|
|
4334
|
+
* Tracks element-id to internal-id mappings for scroll/show-hide resolution
|
|
4701
4335
|
*/
|
|
4702
|
-
function createParseElement(
|
|
4336
|
+
function createParseElement(elementIdMap) {
|
|
4703
4337
|
function parseElement(element, parentId, index) {
|
|
4704
4338
|
const dataType = getDataType(element);
|
|
4705
4339
|
|
|
@@ -4726,9 +4360,6 @@ function createParseElement(styleguideData, elementIdMap) {
|
|
|
4726
4360
|
let node;
|
|
4727
4361
|
if (containerTypes.includes(dataType)) {
|
|
4728
4362
|
node = parser(element, parentId, index, parseElement);
|
|
4729
|
-
} else if (dataType === "Button/V1") {
|
|
4730
|
-
// Button needs styleguide data to look up button styles
|
|
4731
|
-
node = parser(element, parentId, index, styleguideData);
|
|
4732
4363
|
} else {
|
|
4733
4364
|
node = parser(element, parentId, index);
|
|
4734
4365
|
}
|
|
@@ -4793,10 +4424,9 @@ function resolveButtonReferences(node, elementIdMap) {
|
|
|
4793
4424
|
* Parse the entire page tree starting from a root element
|
|
4794
4425
|
*
|
|
4795
4426
|
* @param {HTMLElement} rootElement - The root element to parse (default: find ContentNode)
|
|
4796
|
-
* @param {Object} styleguideData - Optional styleguide data for applying fonts/colors
|
|
4797
4427
|
* @returns {Object} The pagetree JSON object
|
|
4798
4428
|
*/
|
|
4799
|
-
function parsePageTree(rootElement = null
|
|
4429
|
+
function parsePageTree(rootElement = null) {
|
|
4800
4430
|
// Find the root ContentNode if not provided
|
|
4801
4431
|
if (!rootElement) {
|
|
4802
4432
|
rootElement = document.querySelector('[data-type="ContentNode"]');
|
|
@@ -4807,16 +4437,14 @@ function parsePageTree(rootElement = null, styleguideData = null) {
|
|
|
4807
4437
|
return null;
|
|
4808
4438
|
}
|
|
4809
4439
|
|
|
4810
|
-
//
|
|
4811
|
-
// This ensures the parser captures styleguide-applied values (fonts, paint theme colors)
|
|
4440
|
+
// Get document root for popup detection
|
|
4812
4441
|
const docRoot = rootElement.ownerDocument || document;
|
|
4813
|
-
applyStyleguideDataAttributes(docRoot, styleguideData);
|
|
4814
4442
|
|
|
4815
4443
|
// Create element ID map for scroll/show-hide reference resolution
|
|
4816
4444
|
const elementIdMap = {};
|
|
4817
4445
|
|
|
4818
|
-
// Create parseElement
|
|
4819
|
-
const parseElement = createParseElement(
|
|
4446
|
+
// Create parseElement function
|
|
4447
|
+
const parseElement = createParseElement(elementIdMap);
|
|
4820
4448
|
|
|
4821
4449
|
// Parse the content node
|
|
4822
4450
|
const content = parseContentNode(rootElement, parseElement);
|
|
@@ -4935,7 +4563,6 @@ function parsePageTree(rootElement = null, styleguideData = null) {
|
|
|
4935
4563
|
".containerModal": {
|
|
4936
4564
|
attrs: {
|
|
4937
4565
|
"data-skip-corners-settings": "false",
|
|
4938
|
-
"data-style-guide-corner": "style1",
|
|
4939
4566
|
style: { "margin-bottom": 0 },
|
|
4940
4567
|
},
|
|
4941
4568
|
},
|
|
@@ -4951,15 +4578,10 @@ function parsePageTree(rootElement = null, styleguideData = null) {
|
|
|
4951
4578
|
*
|
|
4952
4579
|
* @param {HTMLElement} rootElement - The root element to parse
|
|
4953
4580
|
* @param {boolean} pretty - Whether to pretty-print the JSON
|
|
4954
|
-
* @param {Object} styleguideData - Optional styleguide data for applying fonts/colors
|
|
4955
4581
|
* @returns {string} The pagetree as JSON string
|
|
4956
4582
|
*/
|
|
4957
|
-
function exportPageTreeJSON(
|
|
4958
|
-
|
|
4959
|
-
pretty = true,
|
|
4960
|
-
styleguideData = null
|
|
4961
|
-
) {
|
|
4962
|
-
const pageTree = parsePageTree(rootElement, styleguideData);
|
|
4583
|
+
function exportPageTreeJSON(rootElement = null, pretty = true) {
|
|
4584
|
+
const pageTree = parsePageTree(rootElement);
|
|
4963
4585
|
if (!pageTree) return null;
|
|
4964
4586
|
|
|
4965
4587
|
return pretty ? JSON.stringify(pageTree, null, 2) : JSON.stringify(pageTree);
|
|
@@ -4970,14 +4592,9 @@ function exportPageTreeJSON(
|
|
|
4970
4592
|
*
|
|
4971
4593
|
* @param {string} filename - The filename (default: 'pagetree.json')
|
|
4972
4594
|
* @param {HTMLElement} rootElement - The root element to parse
|
|
4973
|
-
* @param {Object} styleguideData - Optional styleguide data for applying fonts/colors
|
|
4974
4595
|
*/
|
|
4975
|
-
function downloadPageTree(
|
|
4976
|
-
|
|
4977
|
-
rootElement = null,
|
|
4978
|
-
styleguideData = null
|
|
4979
|
-
) {
|
|
4980
|
-
const json = exportPageTreeJSON(rootElement, true, styleguideData);
|
|
4596
|
+
function downloadPageTree(filename = "pagetree.json", rootElement = null) {
|
|
4597
|
+
const json = exportPageTreeJSON(rootElement, true);
|
|
4981
4598
|
if (!json) return;
|
|
4982
4599
|
|
|
4983
4600
|
const blob = new Blob([json], { type: "application/json" });
|
|
@@ -4996,14 +4613,10 @@ function downloadPageTree(
|
|
|
4996
4613
|
* Copy pagetree JSON to clipboard
|
|
4997
4614
|
*
|
|
4998
4615
|
* @param {HTMLElement} rootElement - The root element to parse
|
|
4999
|
-
* @param {Object} styleguideData - Optional styleguide data for applying fonts/colors
|
|
5000
4616
|
* @returns {Promise<boolean>} Whether the copy was successful
|
|
5001
4617
|
*/
|
|
5002
|
-
async function copyPageTreeToClipboard(
|
|
5003
|
-
|
|
5004
|
-
styleguideData = null
|
|
5005
|
-
) {
|
|
5006
|
-
const json = exportPageTreeJSON(rootElement, true, styleguideData);
|
|
4618
|
+
async function copyPageTreeToClipboard(rootElement = null) {
|
|
4619
|
+
const json = exportPageTreeJSON(rootElement, true);
|
|
5007
4620
|
if (!json) return false;
|
|
5008
4621
|
|
|
5009
4622
|
try {
|
|
@@ -5021,10 +4634,9 @@ async function copyPageTreeToClipboard(
|
|
|
5021
4634
|
// Expose API
|
|
5022
4635
|
global.CFPageTreeParser = {
|
|
5023
4636
|
parsePageTree,
|
|
5024
|
-
|
|
5025
|
-
extractPageSettings,
|
|
4637
|
+
createParseElement,
|
|
5026
4638
|
exportPageTreeJSON,
|
|
5027
|
-
|
|
4639
|
+
downloadPageTree,
|
|
5028
4640
|
copyPageTreeToClipboard,
|
|
5029
4641
|
// Utils
|
|
5030
4642
|
generateId,
|