cf-pagetree-parser 1.0.0 → 1.0.2
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 +36 -424
- 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 +1 -1
|
@@ -280,7 +280,7 @@ function extractTextContent(element) {
|
|
|
280
280
|
/**
|
|
281
281
|
* Parse HTML content to ContentEditableNode children
|
|
282
282
|
* @param {string} html - The HTML content to parse
|
|
283
|
-
* @param {string|null} defaultLinkColor - Default color for links (from
|
|
283
|
+
* @param {string|null} defaultLinkColor - Default color for links (from data attribute)
|
|
284
284
|
*/
|
|
285
285
|
function parseHtmlToTextNodes(html, defaultLinkColor = null) {
|
|
286
286
|
const temp = document.createElement('div');
|
|
@@ -922,7 +922,6 @@ function parseSectionContainer(element, parentId, index, parseChildren) {
|
|
|
922
922
|
marginTop: spacing.marginTop || parseValueWithUnit('0px'),
|
|
923
923
|
};
|
|
924
924
|
const overlay = element.getAttribute('data-overlay');
|
|
925
|
-
const paintColors = element.getAttribute('data-paint-colors');
|
|
926
925
|
|
|
927
926
|
// Video background attributes
|
|
928
927
|
const videoBgUrl = element.getAttribute('data-video-bg-url');
|
|
@@ -966,11 +965,6 @@ function parseSectionContainer(element, parentId, index, parseChildren) {
|
|
|
966
965
|
node.attrs.id = elementId;
|
|
967
966
|
}
|
|
968
967
|
|
|
969
|
-
// Add paint colors if present
|
|
970
|
-
if (paintColors) {
|
|
971
|
-
node.attrs['data-paint-colors'] = paintColors;
|
|
972
|
-
}
|
|
973
|
-
|
|
974
968
|
// Apply spacing
|
|
975
969
|
const { attrs: spacingAttrs, params: spacingParams } = spacingToAttrsAndParams(rowSpacingWithDefaults);
|
|
976
970
|
Object.assign(node.attrs.style, spacingAttrs.style);
|
|
@@ -1099,7 +1093,6 @@ function parseRowContainer(element, parentId, index, parseChildren) {
|
|
|
1099
1093
|
marginTop: spacing.marginTop || parseValueWithUnit('0px'),
|
|
1100
1094
|
};
|
|
1101
1095
|
const overlay = element.getAttribute('data-overlay');
|
|
1102
|
-
const paintColors = element.getAttribute('data-paint-colors');
|
|
1103
1096
|
|
|
1104
1097
|
const width = parseValueWithUnit(styles.width || '1170px');
|
|
1105
1098
|
|
|
@@ -1154,11 +1147,6 @@ function parseRowContainer(element, parentId, index, parseChildren) {
|
|
|
1154
1147
|
node.attrs.id = elementId;
|
|
1155
1148
|
}
|
|
1156
1149
|
|
|
1157
|
-
// Add paint colors if present
|
|
1158
|
-
if (paintColors) {
|
|
1159
|
-
node.attrs['data-paint-colors'] = paintColors;
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
1150
|
// Add className if set
|
|
1163
1151
|
if (className) {
|
|
1164
1152
|
node.attrs.className = className;
|
|
@@ -1302,7 +1290,6 @@ function parseColContainer(element, parentId, index, parseChildren) {
|
|
|
1302
1290
|
const overlay = colInner.getAttribute('data-overlay');
|
|
1303
1291
|
const separateCorners = colInner.getAttribute('data-separate-corners') === 'true';
|
|
1304
1292
|
const borderRadius = parseBorderRadius(innerStyles);
|
|
1305
|
-
const paintColors = colInner.getAttribute('data-paint-colors');
|
|
1306
1293
|
|
|
1307
1294
|
const colInnerSelector = node.selectors['& > .col-inner'];
|
|
1308
1295
|
|
|
@@ -1418,11 +1405,6 @@ function parseColContainer(element, parentId, index, parseChildren) {
|
|
|
1418
1405
|
colInnerSelector.attrs['data-skip-background-settings'] =
|
|
1419
1406
|
(hasBackground || overlay) ? 'false' : 'true';
|
|
1420
1407
|
|
|
1421
|
-
// Add paint colors if present
|
|
1422
|
-
if (paintColors) {
|
|
1423
|
-
colInnerSelector.attrs['data-paint-colors'] = paintColors;
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
1408
|
// Parse children from col-inner, skipping overlay and content wrapper
|
|
1427
1409
|
let childIdx = 0;
|
|
1428
1410
|
const parseColInnerChildren = (container) => {
|
|
@@ -1482,7 +1464,6 @@ function parseFlexContainer(element, parentId, index, parseChildren) {
|
|
|
1482
1464
|
marginTop: spacing.marginTop || parseValueWithUnit('0px'),
|
|
1483
1465
|
};
|
|
1484
1466
|
const overlay = element.getAttribute('data-overlay');
|
|
1485
|
-
const paintColors = element.getAttribute('data-paint-colors');
|
|
1486
1467
|
|
|
1487
1468
|
const width = parseValueWithUnit(styles.width || '100%', '%');
|
|
1488
1469
|
const height = styles.height ? parseValueWithUnit(styles.height, 'px') : null;
|
|
@@ -1524,11 +1505,6 @@ function parseFlexContainer(element, parentId, index, parseChildren) {
|
|
|
1524
1505
|
node.attrs.id = elementId;
|
|
1525
1506
|
}
|
|
1526
1507
|
|
|
1527
|
-
// Add paint colors if present
|
|
1528
|
-
if (paintColors) {
|
|
1529
|
-
node.attrs['data-paint-colors'] = paintColors;
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1532
1508
|
// Add width
|
|
1533
1509
|
node.attrs.style.width = width.value;
|
|
1534
1510
|
node.params['width--unit'] = width.unit;
|
|
@@ -1640,8 +1616,7 @@ function parseTextElement(
|
|
|
1640
1616
|
parentId,
|
|
1641
1617
|
index,
|
|
1642
1618
|
type,
|
|
1643
|
-
selector
|
|
1644
|
-
_styleGuideAttr
|
|
1619
|
+
selector
|
|
1645
1620
|
) {
|
|
1646
1621
|
const id = generateId();
|
|
1647
1622
|
const contentEditableId = generateId();
|
|
@@ -1730,14 +1705,6 @@ function parseTextElement(
|
|
|
1730
1705
|
selectorStyle["font-family"] = fontFamily;
|
|
1731
1706
|
}
|
|
1732
1707
|
|
|
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
1708
|
// Parse animation attributes
|
|
1742
1709
|
const { attrs: animationAttrs, params: animationParams } = parseAnimationAttrs(element);
|
|
1743
1710
|
|
|
@@ -1764,7 +1731,6 @@ function parseTextElement(
|
|
|
1764
1731
|
style: selectorStyle,
|
|
1765
1732
|
},
|
|
1766
1733
|
params: {
|
|
1767
|
-
[styleGuideOverrideParam]: true,
|
|
1768
1734
|
"font-size--unit": fontSize ? fontSize.unit : "px",
|
|
1769
1735
|
"line-height--unit": "%",
|
|
1770
1736
|
"letter-spacing--unit": "rem",
|
|
@@ -1847,8 +1813,7 @@ function parseHeadline(element, parentId, index) {
|
|
|
1847
1813
|
parentId,
|
|
1848
1814
|
index,
|
|
1849
1815
|
"Headline/V1",
|
|
1850
|
-
".elHeadline"
|
|
1851
|
-
"data-style-guide-headline"
|
|
1816
|
+
".elHeadline"
|
|
1852
1817
|
);
|
|
1853
1818
|
}
|
|
1854
1819
|
|
|
@@ -1861,8 +1826,7 @@ function parseSubHeadline(element, parentId, index) {
|
|
|
1861
1826
|
parentId,
|
|
1862
1827
|
index,
|
|
1863
1828
|
"SubHeadline/V1",
|
|
1864
|
-
".elSubheadline"
|
|
1865
|
-
"data-style-guide-subheadline"
|
|
1829
|
+
".elSubheadline"
|
|
1866
1830
|
);
|
|
1867
1831
|
}
|
|
1868
1832
|
|
|
@@ -1875,8 +1839,7 @@ function parseParagraph(element, parentId, index) {
|
|
|
1875
1839
|
parentId,
|
|
1876
1840
|
index,
|
|
1877
1841
|
"Paragraph/V1",
|
|
1878
|
-
".elParagraph"
|
|
1879
|
-
"data-style-guide-content"
|
|
1842
|
+
".elParagraph"
|
|
1880
1843
|
);
|
|
1881
1844
|
}
|
|
1882
1845
|
|
|
@@ -1898,9 +1861,8 @@ function parseParagraph(element, parentId, index) {
|
|
|
1898
1861
|
* @param {HTMLElement} element - The button element
|
|
1899
1862
|
* @param {string} parentId - Parent element ID
|
|
1900
1863
|
* @param {number} index - Child index
|
|
1901
|
-
* @param {Object} styleguideData - Optional styleguide data for looking up button styles
|
|
1902
1864
|
*/
|
|
1903
|
-
function parseButton(element, parentId, index
|
|
1865
|
+
function parseButton(element, parentId, index) {
|
|
1904
1866
|
const id = generateId();
|
|
1905
1867
|
const mainTextId = generateId();
|
|
1906
1868
|
const subTextId = generateId();
|
|
@@ -1917,15 +1879,6 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
1917
1879
|
const hideIds = element.getAttribute('data-hide-ids');
|
|
1918
1880
|
const elButtonType = element.getAttribute('data-elbuttontype');
|
|
1919
1881
|
|
|
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
1882
|
// Find the anchor element for fallback parsing
|
|
1930
1883
|
const anchor = element.querySelector('a');
|
|
1931
1884
|
const anchorStyles = anchor ? parseInlineStyle(anchor.getAttribute('style') || '') : {};
|
|
@@ -1934,21 +1887,16 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
1934
1887
|
const textSpan = anchor ? anchor.querySelector('span') : null;
|
|
1935
1888
|
const textStyles = textSpan ? parseInlineStyle(textSpan.getAttribute('style') || '') : {};
|
|
1936
1889
|
|
|
1937
|
-
// Read from
|
|
1938
|
-
// Styleguide button structure: { regular: { bg, color }, hover: { bg, color }, borderRadius, borderWidth, borderColor }
|
|
1890
|
+
// Read from data attributes first, then inline styles
|
|
1939
1891
|
const bgAttr = element.getAttribute('data-bg');
|
|
1940
|
-
const bgColor =
|
|
1941
|
-
? normalizeColor(
|
|
1942
|
-
:
|
|
1943
|
-
? normalizeColor(bgAttr)
|
|
1944
|
-
: (normalizeColor(anchorStyles['background-color']) || '#3b82f6');
|
|
1892
|
+
const bgColor = bgAttr
|
|
1893
|
+
? normalizeColor(bgAttr)
|
|
1894
|
+
: (normalizeColor(anchorStyles['background-color']) || '#3b82f6');
|
|
1945
1895
|
|
|
1946
1896
|
const textColorAttr = element.getAttribute('data-color');
|
|
1947
|
-
const textColor =
|
|
1948
|
-
? normalizeColor(
|
|
1949
|
-
:
|
|
1950
|
-
? normalizeColor(textColorAttr)
|
|
1951
|
-
: (normalizeColor(textStyles.color) || '#ffffff');
|
|
1897
|
+
const textColor = textColorAttr
|
|
1898
|
+
? normalizeColor(textColorAttr)
|
|
1899
|
+
: (normalizeColor(textStyles.color) || '#ffffff');
|
|
1952
1900
|
|
|
1953
1901
|
// Font styling - prefer data attributes
|
|
1954
1902
|
const fontSizeAttr = element.getAttribute('data-size');
|
|
@@ -1962,40 +1910,26 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
1962
1910
|
const paddingHorizontal = pxAttr ? parseValueWithUnit(pxAttr) : parseValueWithUnit(anchorStyles['padding-right'] || '32px');
|
|
1963
1911
|
const paddingVertical = pyAttr ? parseValueWithUnit(pyAttr) : parseValueWithUnit(anchorStyles['padding-top'] || '16px');
|
|
1964
1912
|
|
|
1965
|
-
// Border and corners -
|
|
1913
|
+
// Border and corners - data attributes first, then inline styles
|
|
1966
1914
|
const roundedAttr = element.getAttribute('data-rounded');
|
|
1967
|
-
const borderRadius =
|
|
1968
|
-
?
|
|
1969
|
-
:
|
|
1970
|
-
? parseValueWithUnit(roundedAttr)
|
|
1971
|
-
: parseBorderRadius(anchorStyles);
|
|
1915
|
+
const borderRadius = roundedAttr
|
|
1916
|
+
? parseValueWithUnit(roundedAttr)
|
|
1917
|
+
: parseBorderRadius(anchorStyles);
|
|
1972
1918
|
|
|
1973
1919
|
const borderColorAttr = element.getAttribute('data-border-color');
|
|
1974
|
-
const borderColor =
|
|
1975
|
-
? normalizeColor(
|
|
1976
|
-
:
|
|
1977
|
-
? normalizeColor(borderColorAttr)
|
|
1978
|
-
: normalizeColor(anchorStyles['border-color']);
|
|
1920
|
+
const borderColor = borderColorAttr
|
|
1921
|
+
? normalizeColor(borderColorAttr)
|
|
1922
|
+
: normalizeColor(anchorStyles['border-color']);
|
|
1979
1923
|
|
|
1980
1924
|
const borderWidthAttr = element.getAttribute('data-border-width');
|
|
1981
|
-
const borderWidth =
|
|
1982
|
-
?
|
|
1983
|
-
:
|
|
1984
|
-
? parseValueWithUnit(borderWidthAttr)
|
|
1985
|
-
: parseValueWithUnit(anchorStyles['border-width'] || '0');
|
|
1925
|
+
const borderWidth = borderWidthAttr
|
|
1926
|
+
? parseValueWithUnit(borderWidthAttr)
|
|
1927
|
+
: parseValueWithUnit(anchorStyles['border-width'] || '0');
|
|
1986
1928
|
|
|
1987
1929
|
// Shadow
|
|
1988
1930
|
const shadowAttr = element.getAttribute('data-shadow');
|
|
1989
1931
|
const shadow = shadowAttr ? parseShadow(shadowAttr) : parseShadow(anchorStyles['box-shadow']);
|
|
1990
1932
|
|
|
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
1933
|
// Alignment
|
|
2000
1934
|
const textAlign = element.getAttribute('data-align') || parseTextAlign(wrapperStyles['text-align']);
|
|
2001
1935
|
|
|
@@ -2029,7 +1963,6 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
2029
1963
|
const fullWidth = element.getAttribute('data-full-width') === 'true';
|
|
2030
1964
|
|
|
2031
1965
|
// Build button selector - always include padding params
|
|
2032
|
-
// When using styleguide button, also include data-style-guide-button attribute
|
|
2033
1966
|
const buttonSelector = {
|
|
2034
1967
|
attrs: {
|
|
2035
1968
|
style: {},
|
|
@@ -2039,7 +1972,6 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
2039
1972
|
'--style-padding-horizontal--unit': paddingHorizontal ? paddingHorizontal.unit : 'px',
|
|
2040
1973
|
'--style-padding-vertical': paddingVertical ? paddingVertical.value : 16,
|
|
2041
1974
|
'--style-padding-vertical--unit': paddingVertical ? paddingVertical.unit : 'px',
|
|
2042
|
-
'style-guide-override-button': true,
|
|
2043
1975
|
'--style-background-color': bgColor,
|
|
2044
1976
|
'--style-border-color': borderColor || 'transparent',
|
|
2045
1977
|
'--style-border-width': borderWidth ? borderWidth.value : 0,
|
|
@@ -2047,11 +1979,6 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
2047
1979
|
},
|
|
2048
1980
|
};
|
|
2049
1981
|
|
|
2050
|
-
// Add styleguide button reference if present
|
|
2051
|
-
if (styleGuideButton) {
|
|
2052
|
-
buttonSelector.attrs['data-style-guide-button'] = styleGuideButton;
|
|
2053
|
-
}
|
|
2054
|
-
|
|
2055
1982
|
// Parse animation attributes
|
|
2056
1983
|
const { attrs: animationAttrs, params: animationParams } = parseAnimationAttrs(element);
|
|
2057
1984
|
|
|
@@ -2218,27 +2145,6 @@ function parseButton(element, parentId, index, styleguideData = null) {
|
|
|
2218
2145
|
node.selectors['.elButton .elButtonSub'].attrs.style.color = subTextColor;
|
|
2219
2146
|
}
|
|
2220
2147
|
|
|
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
2148
|
return node;
|
|
2243
2149
|
}
|
|
2244
2150
|
|
|
@@ -3394,7 +3300,6 @@ function parseBulletList(element, parentId, index) {
|
|
|
3394
3300
|
selectors: {
|
|
3395
3301
|
'.elBulletList': {
|
|
3396
3302
|
attrs: {
|
|
3397
|
-
'data-style-guide-content': 'm',
|
|
3398
3303
|
'data-skip-text-shadow-settings': 'true',
|
|
3399
3304
|
style: {
|
|
3400
3305
|
color: textColor,
|
|
@@ -4216,8 +4121,6 @@ function parseCheckoutPlaceholder(element, parentId, index) {
|
|
|
4216
4121
|
fractionalIndex: generateFractionalIndex(index),
|
|
4217
4122
|
attrs: {
|
|
4218
4123
|
style: {
|
|
4219
|
-
'--container-font-family': 'var(--style-guide-font-family-content)',
|
|
4220
|
-
'--input-headline-font-family': 'var(--style-guide-font-family-subheadline)',
|
|
4221
4124
|
'--multiple-payments-font-family': 'sans-serif',
|
|
4222
4125
|
'--input-background-color': '#FFFFFF',
|
|
4223
4126
|
},
|
|
@@ -4391,276 +4294,6 @@ function parseConfirmationPlaceholder(element, parentId, index) {
|
|
|
4391
4294
|
* ============================================================================
|
|
4392
4295
|
*/
|
|
4393
4296
|
|
|
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
4297
|
/**
|
|
4665
4298
|
* Map of data-type to parser function
|
|
4666
4299
|
*/
|
|
@@ -4696,10 +4329,10 @@ const PARSER_MAP = {
|
|
|
4696
4329
|
};
|
|
4697
4330
|
|
|
4698
4331
|
/**
|
|
4699
|
-
* Create parseElement function
|
|
4700
|
-
*
|
|
4332
|
+
* Create parseElement function
|
|
4333
|
+
* Tracks element-id to internal-id mappings for scroll/show-hide resolution
|
|
4701
4334
|
*/
|
|
4702
|
-
function createParseElement(
|
|
4335
|
+
function createParseElement(elementIdMap) {
|
|
4703
4336
|
function parseElement(element, parentId, index) {
|
|
4704
4337
|
const dataType = getDataType(element);
|
|
4705
4338
|
|
|
@@ -4726,9 +4359,6 @@ function createParseElement(styleguideData, elementIdMap) {
|
|
|
4726
4359
|
let node;
|
|
4727
4360
|
if (containerTypes.includes(dataType)) {
|
|
4728
4361
|
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
4362
|
} else {
|
|
4733
4363
|
node = parser(element, parentId, index);
|
|
4734
4364
|
}
|
|
@@ -4793,10 +4423,9 @@ function resolveButtonReferences(node, elementIdMap) {
|
|
|
4793
4423
|
* Parse the entire page tree starting from a root element
|
|
4794
4424
|
*
|
|
4795
4425
|
* @param {HTMLElement} rootElement - The root element to parse (default: find ContentNode)
|
|
4796
|
-
* @param {Object} styleguideData - Optional styleguide data for applying fonts/colors
|
|
4797
4426
|
* @returns {Object} The pagetree JSON object
|
|
4798
4427
|
*/
|
|
4799
|
-
function parsePageTree(rootElement = null
|
|
4428
|
+
function parsePageTree(rootElement = null) {
|
|
4800
4429
|
// Find the root ContentNode if not provided
|
|
4801
4430
|
if (!rootElement) {
|
|
4802
4431
|
rootElement = document.querySelector('[data-type="ContentNode"]');
|
|
@@ -4807,16 +4436,14 @@ function parsePageTree(rootElement = null, styleguideData = null) {
|
|
|
4807
4436
|
return null;
|
|
4808
4437
|
}
|
|
4809
4438
|
|
|
4810
|
-
//
|
|
4811
|
-
// This ensures the parser captures styleguide-applied values (fonts, paint theme colors)
|
|
4439
|
+
// Get document root for popup detection
|
|
4812
4440
|
const docRoot = rootElement.ownerDocument || document;
|
|
4813
|
-
applyStyleguideDataAttributes(docRoot, styleguideData);
|
|
4814
4441
|
|
|
4815
4442
|
// Create element ID map for scroll/show-hide reference resolution
|
|
4816
4443
|
const elementIdMap = {};
|
|
4817
4444
|
|
|
4818
|
-
// Create parseElement
|
|
4819
|
-
const parseElement = createParseElement(
|
|
4445
|
+
// Create parseElement function
|
|
4446
|
+
const parseElement = createParseElement(elementIdMap);
|
|
4820
4447
|
|
|
4821
4448
|
// Parse the content node
|
|
4822
4449
|
const content = parseContentNode(rootElement, parseElement);
|
|
@@ -4935,7 +4562,6 @@ function parsePageTree(rootElement = null, styleguideData = null) {
|
|
|
4935
4562
|
".containerModal": {
|
|
4936
4563
|
attrs: {
|
|
4937
4564
|
"data-skip-corners-settings": "false",
|
|
4938
|
-
"data-style-guide-corner": "style1",
|
|
4939
4565
|
style: { "margin-bottom": 0 },
|
|
4940
4566
|
},
|
|
4941
4567
|
},
|
|
@@ -4951,15 +4577,10 @@ function parsePageTree(rootElement = null, styleguideData = null) {
|
|
|
4951
4577
|
*
|
|
4952
4578
|
* @param {HTMLElement} rootElement - The root element to parse
|
|
4953
4579
|
* @param {boolean} pretty - Whether to pretty-print the JSON
|
|
4954
|
-
* @param {Object} styleguideData - Optional styleguide data for applying fonts/colors
|
|
4955
4580
|
* @returns {string} The pagetree as JSON string
|
|
4956
4581
|
*/
|
|
4957
|
-
function exportPageTreeJSON(
|
|
4958
|
-
|
|
4959
|
-
pretty = true,
|
|
4960
|
-
styleguideData = null
|
|
4961
|
-
) {
|
|
4962
|
-
const pageTree = parsePageTree(rootElement, styleguideData);
|
|
4582
|
+
function exportPageTreeJSON(rootElement = null, pretty = true) {
|
|
4583
|
+
const pageTree = parsePageTree(rootElement);
|
|
4963
4584
|
if (!pageTree) return null;
|
|
4964
4585
|
|
|
4965
4586
|
return pretty ? JSON.stringify(pageTree, null, 2) : JSON.stringify(pageTree);
|
|
@@ -4970,14 +4591,9 @@ function exportPageTreeJSON(
|
|
|
4970
4591
|
*
|
|
4971
4592
|
* @param {string} filename - The filename (default: 'pagetree.json')
|
|
4972
4593
|
* @param {HTMLElement} rootElement - The root element to parse
|
|
4973
|
-
* @param {Object} styleguideData - Optional styleguide data for applying fonts/colors
|
|
4974
4594
|
*/
|
|
4975
|
-
function downloadPageTree(
|
|
4976
|
-
|
|
4977
|
-
rootElement = null,
|
|
4978
|
-
styleguideData = null
|
|
4979
|
-
) {
|
|
4980
|
-
const json = exportPageTreeJSON(rootElement, true, styleguideData);
|
|
4595
|
+
function downloadPageTree(filename = "pagetree.json", rootElement = null) {
|
|
4596
|
+
const json = exportPageTreeJSON(rootElement, true);
|
|
4981
4597
|
if (!json) return;
|
|
4982
4598
|
|
|
4983
4599
|
const blob = new Blob([json], { type: "application/json" });
|
|
@@ -4996,14 +4612,10 @@ function downloadPageTree(
|
|
|
4996
4612
|
* Copy pagetree JSON to clipboard
|
|
4997
4613
|
*
|
|
4998
4614
|
* @param {HTMLElement} rootElement - The root element to parse
|
|
4999
|
-
* @param {Object} styleguideData - Optional styleguide data for applying fonts/colors
|
|
5000
4615
|
* @returns {Promise<boolean>} Whether the copy was successful
|
|
5001
4616
|
*/
|
|
5002
|
-
async function copyPageTreeToClipboard(
|
|
5003
|
-
|
|
5004
|
-
styleguideData = null
|
|
5005
|
-
) {
|
|
5006
|
-
const json = exportPageTreeJSON(rootElement, true, styleguideData);
|
|
4617
|
+
async function copyPageTreeToClipboard(rootElement = null) {
|
|
4618
|
+
const json = exportPageTreeJSON(rootElement, true);
|
|
5007
4619
|
if (!json) return false;
|
|
5008
4620
|
|
|
5009
4621
|
try {
|