@marvalt/wparser 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1504,63 +1504,338 @@ function renderTextWithShortcodes(text, registry) {
1504
1504
  return parts;
1505
1505
  }
1506
1506
 
1507
+ /**
1508
+ * Content extraction utilities for WordPress blocks
1509
+ * Extracts text content from various block formats
1510
+ */
1511
+ /**
1512
+ * Extract text content from a block's innerHTML by stripping HTML tags
1513
+ */
1514
+ function extractTextFromHTML(html) {
1515
+ if (!html)
1516
+ return '';
1517
+ // Remove HTML tags and decode entities
1518
+ let text = html
1519
+ .replace(/<[^>]*>/g, '') // Remove HTML tags
1520
+ .replace(/&nbsp;/g, ' ') // Replace &nbsp; with space
1521
+ .replace(/&#8217;/g, "'") // Replace apostrophe entity
1522
+ .replace(/&#8220;/g, '"') // Replace left double quote
1523
+ .replace(/&#8221;/g, '"') // Replace right double quote
1524
+ .replace(/&#8230;/g, '...') // Replace ellipsis
1525
+ .replace(/&amp;/g, '&') // Replace &amp;
1526
+ .replace(/&lt;/g, '<') // Replace &lt;
1527
+ .replace(/&gt;/g, '>') // Replace &gt;
1528
+ .replace(/&quot;/g, '"') // Replace &quot;
1529
+ .replace(/&#8211;/g, '–') // Replace en dash
1530
+ .replace(/&#8212;/g, '—') // Replace em dash
1531
+ .trim();
1532
+ // Clean up extra whitespace
1533
+ text = text.replace(/\s+/g, ' ');
1534
+ return text;
1535
+ }
1536
+ /**
1537
+ * Extract text content from block attributes or innerHTML
1538
+ */
1539
+ function getBlockTextContent(block) {
1540
+ const attrs = block.attributes || {};
1541
+ // Try various attribute keys
1542
+ const content = attrs['content'] || attrs['text'] || attrs['value'] || '';
1543
+ if (typeof content === 'string' && content.trim()) {
1544
+ return content.trim();
1545
+ }
1546
+ // Fall back to innerHTML
1547
+ if (block.innerHTML) {
1548
+ return extractTextFromHTML(block.innerHTML);
1549
+ }
1550
+ return '';
1551
+ }
1552
+ /**
1553
+ * Extract image URL from block attributes
1554
+ * Checks for Cloudflare URLs first, then falls back to regular URLs
1555
+ * Also extracts from innerHTML if needed
1556
+ */
1557
+ function getImageUrl(block) {
1558
+ const attrs = block.attributes || {};
1559
+ // Check various possible URL attributes
1560
+ let url = attrs['url'] ||
1561
+ attrs['src'] ||
1562
+ attrs['imageUrl'] ||
1563
+ attrs['mediaUrl'] ||
1564
+ attrs['backgroundImage'];
1565
+ if (typeof url === 'string' && url.trim()) {
1566
+ return url.trim();
1567
+ }
1568
+ // Try to extract from innerHTML if it's an img tag
1569
+ if (block.innerHTML) {
1570
+ // Try img src first
1571
+ const imgMatch = block.innerHTML.match(/<img[^>]+src=["']([^"']+)["']/i);
1572
+ if (imgMatch && imgMatch[1]) {
1573
+ return imgMatch[1];
1574
+ }
1575
+ // Try background-image in style attribute
1576
+ const bgMatch = block.innerHTML.match(/background-image:\s*url\(["']?([^"')]+)["']?\)/i);
1577
+ if (bgMatch && bgMatch[1]) {
1578
+ return bgMatch[1];
1579
+ }
1580
+ }
1581
+ return null;
1582
+ }
1583
+ /**
1584
+ * Extract image attributes (alt, width, height) from block
1585
+ */
1586
+ function getImageAttributes(block) {
1587
+ const attrs = block.attributes || {};
1588
+ const url = getImageUrl(block);
1589
+ return {
1590
+ url,
1591
+ alt: attrs['alt'] || '',
1592
+ width: attrs['width'] ? Number(attrs['width']) : undefined,
1593
+ height: attrs['height'] ? Number(attrs['height']) : undefined,
1594
+ };
1595
+ }
1596
+
1597
+ /**
1598
+ * Style mapping utilities
1599
+ * Maps WordPress block attributes to Tailwind CSS classes
1600
+ */
1601
+ /**
1602
+ * Map WordPress alignment to Tailwind classes
1603
+ */
1604
+ function getAlignmentClasses(align) {
1605
+ if (!align)
1606
+ return '';
1607
+ switch (align) {
1608
+ case 'full':
1609
+ return 'w-full';
1610
+ case 'wide':
1611
+ return 'max-w-7xl mx-auto';
1612
+ case 'center':
1613
+ return 'mx-auto';
1614
+ case 'left':
1615
+ return 'mr-auto';
1616
+ case 'right':
1617
+ return 'ml-auto';
1618
+ default:
1619
+ return '';
1620
+ }
1621
+ }
1622
+ /**
1623
+ * Map WordPress text alignment to Tailwind classes
1624
+ */
1625
+ function getTextAlignClasses(textAlign) {
1626
+ if (!textAlign)
1627
+ return '';
1628
+ switch (textAlign) {
1629
+ case 'center':
1630
+ return 'text-center';
1631
+ case 'left':
1632
+ return 'text-left';
1633
+ case 'right':
1634
+ return 'text-right';
1635
+ default:
1636
+ return '';
1637
+ }
1638
+ }
1639
+ /**
1640
+ * Map WordPress font size to Tailwind classes
1641
+ */
1642
+ function getFontSizeClasses(fontSize) {
1643
+ if (!fontSize)
1644
+ return '';
1645
+ // Map WordPress font sizes to Tailwind
1646
+ const sizeMap = {
1647
+ 'small': 'text-sm',
1648
+ 'medium': 'text-base',
1649
+ 'large': 'text-lg',
1650
+ 'x-large': 'text-xl',
1651
+ 'xx-large': 'text-3xl',
1652
+ 'xxx-large': 'text-4xl',
1653
+ };
1654
+ return sizeMap[fontSize] || '';
1655
+ }
1656
+ /**
1657
+ * Get container classes based on layout and alignment
1658
+ */
1659
+ function getContainerClasses(align, layout) {
1660
+ const alignClass = getAlignmentClasses(align);
1661
+ // If layout is constrained, use container
1662
+ if (layout?.type === 'constrained') {
1663
+ return align === 'full' ? 'w-full' : 'container';
1664
+ }
1665
+ return alignClass || 'container';
1666
+ }
1667
+ /**
1668
+ * Get spacing classes for sections
1669
+ */
1670
+ function getSectionSpacingClasses() {
1671
+ return 'py-16 md:py-24';
1672
+ }
1673
+ /**
1674
+ * Get content spacing classes
1675
+ */
1676
+ function getContentSpacingClasses() {
1677
+ return 'space-y-6';
1678
+ }
1679
+ /**
1680
+ * Build className string from multiple class sources
1681
+ */
1682
+ function buildClassName(...classes) {
1683
+ return classes
1684
+ .filter((cls) => Boolean(cls && cls.trim()))
1685
+ .join(' ')
1686
+ .trim();
1687
+ }
1688
+
1689
+ /**
1690
+ * Cloudflare Images URL helpers for wparser package
1691
+ * Formats Cloudflare image URLs with variants for optimal performance
1692
+ */
1693
+ /**
1694
+ * Check if a URL is a Cloudflare Images URL
1695
+ */
1696
+ const isCloudflareImageUrl = (url) => {
1697
+ if (!url)
1698
+ return false;
1699
+ try {
1700
+ const u = new URL(url);
1701
+ return u.hostname.toLowerCase().includes('imagedelivery.net');
1702
+ }
1703
+ catch {
1704
+ return false;
1705
+ }
1706
+ };
1707
+ /**
1708
+ * Append Cloudflare Images variant to the base URL if not already present.
1709
+ * Example output: https://imagedelivery.net/<account>/<id>/w=1024,h=600
1710
+ */
1711
+ const getCloudflareVariantUrl = (url, options) => {
1712
+ if (!isCloudflareImageUrl(url))
1713
+ return url;
1714
+ // If a transform already exists, return as-is
1715
+ if (/\/w=\d+/.test(url) || /\/(public|thumbnail|banner|avatar)/.test(url)) {
1716
+ return url;
1717
+ }
1718
+ const { width, height } = options;
1719
+ const hasTrailingSlash = url.endsWith('/');
1720
+ const base = hasTrailingSlash ? url.slice(0, -1) : url;
1721
+ const variant = `w=${Math.max(1, Math.floor(width))}` + (height ? `,h=${Math.max(1, Math.floor(height))}` : '');
1722
+ return `${base}/${variant}`;
1723
+ };
1724
+
1507
1725
  const Paragraph = ({ block, context }) => {
1508
- const content = getString(block);
1726
+ const content = getBlockTextContent(block);
1727
+ const attrs = block.attributes || {};
1728
+ const textAlign = getTextAlignClasses(attrs['align']);
1509
1729
  // Check if content contains shortcodes
1510
1730
  const hasShortcodes = /\[(\w+)/.test(content);
1511
1731
  if (hasShortcodes && context.registry.shortcodes) {
1512
1732
  const parts = renderTextWithShortcodes(content, context.registry);
1513
- return jsxRuntimeExports.jsx("p", { className: "prose-p", children: parts });
1733
+ return jsxRuntimeExports.jsx("p", { className: buildClassName('text-gray-700', textAlign), children: parts });
1514
1734
  }
1515
- return jsxRuntimeExports.jsx("p", { className: "prose-p", children: content });
1735
+ return jsxRuntimeExports.jsx("p", { className: buildClassName('text-gray-700', textAlign), children: content });
1516
1736
  };
1517
1737
  const Heading = ({ block, children }) => {
1518
- const { level = 2 } = block.attributes || {};
1519
- const content = getString(block);
1738
+ const attrs = block.attributes || {};
1739
+ const { level = 2 } = attrs;
1740
+ const content = getBlockTextContent(block);
1741
+ const textAlign = getTextAlignClasses(attrs['textAlign']);
1742
+ const fontSize = getFontSizeClasses(attrs['fontSize']);
1520
1743
  const Tag = `h${Math.min(Math.max(Number(level) || 2, 1), 6)}`;
1521
- return jsxRuntimeExports.jsx(Tag, { className: "prose-headings font-semibold", children: children ?? content });
1744
+ // Default heading sizes if fontSize not specified
1745
+ const sizeClass = fontSize || (level === 1 ? 'text-4xl' : level === 2 ? 'text-3xl' : level === 3 ? 'text-2xl' : 'text-xl');
1746
+ return (jsxRuntimeExports.jsx(Tag, { className: buildClassName('font-bold text-gray-900', sizeClass, textAlign), children: children ?? content }));
1522
1747
  };
1523
1748
  const Image = ({ block }) => {
1524
- const { url, alt, width, height } = block.attributes || {};
1525
- if (!url)
1749
+ const imageAttrs = getImageAttributes(block);
1750
+ if (!imageAttrs.url)
1526
1751
  return null;
1527
- return (jsxRuntimeExports.jsx("img", { src: url, alt: alt || '', width: width, height: height, className: "w-full h-auto object-cover", loading: "lazy" }));
1752
+ // Use Cloudflare variant URL if it's a Cloudflare image
1753
+ let imageUrl = imageAttrs.url;
1754
+ if (isCloudflareImageUrl(imageUrl)) {
1755
+ const width = imageAttrs.width || 1024;
1756
+ const height = imageAttrs.height;
1757
+ imageUrl = getCloudflareVariantUrl(imageUrl, { width, height });
1758
+ }
1759
+ return (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: imageAttrs.alt, width: imageAttrs.width, height: imageAttrs.height, className: "w-full h-auto object-cover rounded-lg", loading: "lazy" }));
1528
1760
  };
1529
1761
  const List = ({ block, children }) => {
1530
- const { ordered } = block.attributes || {};
1762
+ const attrs = block.attributes || {};
1763
+ const { ordered } = attrs;
1531
1764
  const Tag = ordered ? 'ol' : 'ul';
1532
- return React.createElement(Tag, { className: 'list-disc pl-6 space-y-1' }, children);
1765
+ return React.createElement(Tag, { className: 'list-disc pl-6 space-y-2 text-gray-700' }, children);
1533
1766
  };
1534
1767
  const ListItem = ({ children }) => {
1535
- return jsxRuntimeExports.jsx("li", { children: children });
1768
+ return jsxRuntimeExports.jsx("li", { className: "text-gray-700", children: children });
1536
1769
  };
1537
- const Group = ({ children }) => {
1538
- return jsxRuntimeExports.jsx("div", { className: "space-y-4", children: children });
1770
+ const Group = ({ block, children }) => {
1771
+ const attrs = block.attributes || {};
1772
+ const align = attrs['align'];
1773
+ const layout = attrs['layout'];
1774
+ // Determine if this is a section-level group (has alignment) or content-level
1775
+ const isSection = align === 'full' || align === 'wide';
1776
+ const containerClass = getContainerClasses(align, layout);
1777
+ const spacingClass = isSection ? getSectionSpacingClasses() : getContentSpacingClasses();
1778
+ return (jsxRuntimeExports.jsx("div", { className: buildClassName(containerClass, spacingClass), children: children }));
1539
1779
  };
1540
- const Columns = ({ children }) => {
1541
- return jsxRuntimeExports.jsx("div", { className: "grid gap-6 md:grid-cols-2", children: children });
1780
+ const Columns = ({ block, children }) => {
1781
+ const attrs = block.attributes || {};
1782
+ const align = attrs['align'];
1783
+ const alignClass = getAlignmentClasses(align);
1784
+ return (jsxRuntimeExports.jsx("div", { className: buildClassName('grid grid-cols-1 md:grid-cols-2 gap-6 lg:gap-12', alignClass), children: children }));
1542
1785
  };
1543
- const Column = ({ children }) => {
1544
- return jsxRuntimeExports.jsx("div", { className: "space-y-4", children: children });
1786
+ const Column = ({ block, children }) => {
1787
+ const attrs = block.attributes || {};
1788
+ const width = attrs['width'];
1789
+ // Handle column width (e.g., "50%" becomes flex-basis)
1790
+ const style = width ? { flexBasis: width } : undefined;
1791
+ return (jsxRuntimeExports.jsx("div", { className: "space-y-4", style: style, children: children }));
1545
1792
  };
1546
1793
  const Separator = () => jsxRuntimeExports.jsx("hr", { className: "border-gray-200 my-8" });
1547
1794
  const ButtonBlock = ({ block }) => {
1548
- const { url, text } = block.attributes || {};
1549
- if (!url)
1795
+ const attrs = block.attributes || {};
1796
+ const url = attrs['url'];
1797
+ const text = attrs['text'];
1798
+ attrs['linkDestination'];
1799
+ if (!url && !text)
1550
1800
  return null;
1551
- return (jsxRuntimeExports.jsx("a", { href: url, className: "inline-flex items-center rounded-md bg-primary px-4 py-2 text-white", children: text || 'Learn more' }));
1801
+ const buttonText = text || getBlockTextContent(block) || 'Learn more';
1802
+ // Handle internal vs external links
1803
+ const isExternal = url && (url.startsWith('http://') || url.startsWith('https://'));
1804
+ const linkProps = isExternal ? { target: '_blank', rel: 'noopener noreferrer' } : {};
1805
+ return (jsxRuntimeExports.jsx("a", { href: url || '#', className: "inline-flex items-center justify-center rounded-md bg-primary px-6 py-3 text-white font-medium hover:bg-primary/90 transition-colors", ...linkProps, children: buttonText }));
1552
1806
  };
1553
1807
  const Cover = ({ block, children }) => {
1554
1808
  const attrs = block.attributes || {};
1555
- const { url, backgroundImage, overlayColor, dimRatio = 0, align = 'full', minHeight, hasParallax, } = attrs;
1809
+ const { url, id, backgroundImage, overlayColor, dimRatio = 0, align = 'full', minHeight, minHeightUnit = 'vh', hasParallax, } = attrs;
1556
1810
  // Get background image URL from various possible sources
1557
- const bgImageUrl = url || backgroundImage || (typeof backgroundImage === 'object' && backgroundImage?.url);
1811
+ let bgImageUrl = url || backgroundImage || (typeof backgroundImage === 'object' && backgroundImage?.url);
1812
+ // If not found in attributes, try to extract from innerHTML
1813
+ if (!bgImageUrl && block.innerHTML) {
1814
+ // Try to extract img src from innerHTML
1815
+ const imgMatch = block.innerHTML.match(/<img[^>]+src=["']([^"']+)["']/i);
1816
+ if (imgMatch && imgMatch[1]) {
1817
+ bgImageUrl = imgMatch[1];
1818
+ }
1819
+ // Try background-image in style attribute
1820
+ if (!bgImageUrl) {
1821
+ const bgMatch = block.innerHTML.match(/background-image:\s*url\(["']?([^"')]+)["']?\)/i);
1822
+ if (bgMatch && bgMatch[1]) {
1823
+ bgImageUrl = bgMatch[1];
1824
+ }
1825
+ }
1826
+ }
1827
+ // Convert to Cloudflare URL if it's a Cloudflare image, otherwise use as-is
1828
+ if (bgImageUrl && isCloudflareImageUrl(bgImageUrl)) {
1829
+ // Use full width for cover images
1830
+ bgImageUrl = getCloudflareVariantUrl(bgImageUrl, { width: 1920 });
1831
+ }
1558
1832
  // Build alignment classes
1559
- const alignClass = align === 'full' ? 'w-full' : align === 'wide' ? 'max-w-7xl mx-auto' : '';
1833
+ const alignClass = getAlignmentClasses(align);
1560
1834
  // Build style object
1561
1835
  const style = {};
1562
1836
  if (minHeight) {
1563
- style.minHeight = typeof minHeight === 'number' ? `${minHeight}px` : minHeight;
1837
+ const minHeightValue = typeof minHeight === 'number' ? minHeight : parseFloat(String(minHeight));
1838
+ style.minHeight = minHeightUnit === 'vh' ? `${minHeightValue}vh` : `${minHeightValue}px`;
1564
1839
  }
1565
1840
  if (bgImageUrl) {
1566
1841
  style.backgroundImage = `url(${bgImageUrl})`;
@@ -1571,11 +1846,11 @@ const Cover = ({ block, children }) => {
1571
1846
  }
1572
1847
  }
1573
1848
  // Calculate overlay opacity
1574
- const overlayOpacity = dimRatio / 100;
1575
- return (jsxRuntimeExports.jsxs("div", { className: `relative ${alignClass}`, style: style, children: [overlayOpacity > 0 && (jsxRuntimeExports.jsx("span", { className: "absolute inset-0", style: {
1576
- backgroundColor: overlayColor || '#000000',
1849
+ const overlayOpacity = typeof dimRatio === 'number' ? dimRatio / 100 : 0;
1850
+ return (jsxRuntimeExports.jsxs("div", { className: buildClassName('relative w-full', alignClass), style: style, children: [overlayOpacity > 0 && (jsxRuntimeExports.jsx("span", { className: "absolute inset-0 z-0", style: {
1851
+ backgroundColor: overlayColor === 'contrast' ? '#000000' : (overlayColor || '#000000'),
1577
1852
  opacity: overlayOpacity,
1578
- }, "aria-hidden": "true" })), jsxRuntimeExports.jsx("div", { className: "relative z-10 container mx-auto px-4 py-12", children: children })] }));
1853
+ }, "aria-hidden": "true" })), jsxRuntimeExports.jsx("div", { className: buildClassName('relative z-10', align === 'full' ? 'w-full' : 'container mx-auto px-4'), children: children })] }));
1579
1854
  };
1580
1855
  const MediaText = ({ block, children, context }) => {
1581
1856
  const attrs = block.attributes || {};
@@ -1592,7 +1867,7 @@ const MediaText = ({ block, children, context }) => {
1592
1867
  // Content is all other children
1593
1868
  const contentElements = childrenArray.filter((_, index) => index !== mediaBlockIndex);
1594
1869
  // Build alignment classes
1595
- const alignClass = align === 'full' ? 'w-full' : align === 'wide' ? 'max-w-7xl mx-auto' : 'max-w-6xl mx-auto';
1870
+ const alignClass = getAlignmentClasses(align) || 'max-w-7xl mx-auto';
1596
1871
  // Vertical alignment classes
1597
1872
  const verticalAlignClass = verticalAlignment === 'top' ? 'items-start' :
1598
1873
  verticalAlignment === 'bottom' ? 'items-end' :
@@ -1601,7 +1876,7 @@ const MediaText = ({ block, children, context }) => {
1601
1876
  const stackClass = 'flex-col md:flex-row';
1602
1877
  // Media position determines order
1603
1878
  const isMediaRight = mediaPosition === 'right';
1604
- return (jsxRuntimeExports.jsx("div", { className: `${alignClass} px-4`, children: jsxRuntimeExports.jsxs("div", { className: `flex ${stackClass} ${verticalAlignClass} gap-6`, children: [jsxRuntimeExports.jsx("div", { className: `${isMediaRight ? 'order-2' : 'order-1'} ${imageFill ? 'w-full md:w-1/2' : 'flex-shrink-0'}`, children: mediaElement || jsxRuntimeExports.jsx("div", { className: "bg-gray-200 h-64 rounded" }) }), jsxRuntimeExports.jsx("div", { className: `${isMediaRight ? 'order-1' : 'order-2'} ${imageFill ? 'w-full md:w-1/2' : 'flex-1'} space-y-4`, children: contentElements.length > 0 ? contentElements : children })] }) }));
1879
+ return (jsxRuntimeExports.jsx("div", { className: buildClassName(alignClass, 'px-4'), children: jsxRuntimeExports.jsxs("div", { className: buildClassName('flex', stackClass, verticalAlignClass, 'gap-6 lg:gap-12'), children: [jsxRuntimeExports.jsx("div", { className: buildClassName(isMediaRight ? 'order-2' : 'order-1', imageFill ? 'w-full md:w-1/2' : 'flex-shrink-0'), children: mediaElement || jsxRuntimeExports.jsx("div", { className: "bg-gray-200 h-64 rounded-lg" }) }), jsxRuntimeExports.jsx("div", { className: buildClassName(isMediaRight ? 'order-1' : 'order-2', imageFill ? 'w-full md:w-1/2' : 'flex-1', 'space-y-4'), children: contentElements.length > 0 ? contentElements : children })] }) }));
1605
1880
  };
1606
1881
  const Fallback = ({ block, children }) => {
1607
1882
  // Minimal fallback; do not render innerHTML directly in v1 for safety
@@ -1619,7 +1894,15 @@ function createDefaultRegistry() {
1619
1894
  'core/column': Column,
1620
1895
  'core/separator': Separator,
1621
1896
  'core/button': ButtonBlock,
1622
- 'core/buttons': ({ children }) => jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-3", children: children }),
1897
+ 'core/buttons': ({ block, children }) => {
1898
+ const attrs = block.attributes || {};
1899
+ const layout = attrs['layout'];
1900
+ const justifyContent = layout?.justifyContent || 'left';
1901
+ const justifyClass = justifyContent === 'center' ? 'justify-center' :
1902
+ justifyContent === 'right' ? 'justify-end' :
1903
+ 'justify-start';
1904
+ return jsxRuntimeExports.jsx("div", { className: buildClassName('flex flex-wrap gap-3', justifyClass), children: children });
1905
+ },
1623
1906
  'core/quote': ({ children }) => jsxRuntimeExports.jsx("blockquote", { className: "border-l-4 pl-4 italic", children: children }),
1624
1907
  'core/code': ({ block }) => (jsxRuntimeExports.jsx("pre", { className: "bg-gray-100 p-3 rounded text-sm overflow-auto", children: jsxRuntimeExports.jsx("code", { children: getString(block) }) })),
1625
1908
  'core/preformatted': ({ block }) => jsxRuntimeExports.jsx("pre", { children: getString(block) }),
@@ -1643,12 +1926,9 @@ function createDefaultRegistry() {
1643
1926
  fallback: Fallback,
1644
1927
  };
1645
1928
  }
1929
+ // Legacy function for backward compatibility - use getBlockTextContent instead
1646
1930
  function getString(block) {
1647
- const attrs = (block.attributes || {});
1648
- const content = attrs['content'];
1649
- const text = attrs['text'];
1650
- const value = (typeof content === 'string' ? content : typeof text === 'string' ? text : block.innerHTML || '');
1651
- return String(value);
1931
+ return getBlockTextContent(block);
1652
1932
  }
1653
1933
 
1654
1934
  const WPContent = ({ blocks, registry, className }) => {
@@ -1684,7 +1964,7 @@ const WPPage = ({ page, registry, className }) => {
1684
1964
  }
1685
1965
  const hasHeroShortcode = useMemo(() => detectHeroShortcode(page.blocks), [page.blocks]);
1686
1966
  const featured = getFeaturedImage(page);
1687
- return (jsxRuntimeExports.jsxs("article", { className: className, children: [!hasHeroShortcode && featured && (jsxRuntimeExports.jsx(HeroFromFeatured, { featured: featured, title: page.title?.rendered })), jsxRuntimeExports.jsxs("div", { className: "container mx-auto px-4 py-8 prose max-w-none", children: [jsxRuntimeExports.jsx("header", { className: "mb-8", children: page.title?.rendered && (jsxRuntimeExports.jsx("h1", { className: "text-3xl font-bold", children: page.title.rendered })) }), jsxRuntimeExports.jsx(WPContent, { blocks: page.blocks, registry: registry })] })] }));
1967
+ return (jsxRuntimeExports.jsxs("article", { className: className, children: [!hasHeroShortcode && featured && (jsxRuntimeExports.jsx(HeroFromFeatured, { featured: featured, title: page.title?.rendered })), jsxRuntimeExports.jsx(WPContent, { blocks: page.blocks, registry: registry })] }));
1688
1968
  };
1689
1969
  function detectHeroShortcode(blocks) {
1690
1970
  for (const block of blocks) {
@@ -1731,5 +2011,5 @@ class WPErrorBoundary extends React.Component {
1731
2011
  }
1732
2012
  }
1733
2013
 
1734
- export { WPContent, WPErrorBoundary, WPPage, createDefaultRegistry, findShortcodes, parseGutenbergBlocks, parseShortcodeAttrs, renderNodes, renderTextWithShortcodes };
2014
+ export { WPContent, WPErrorBoundary, WPPage, buildClassName, createDefaultRegistry, extractTextFromHTML, findShortcodes, getAlignmentClasses, getBlockTextContent, getCloudflareVariantUrl, getContainerClasses, getContentSpacingClasses, getFontSizeClasses, getImageAttributes, getImageUrl, getSectionSpacingClasses, getTextAlignClasses, isCloudflareImageUrl, parseGutenbergBlocks, parseShortcodeAttrs, renderNodes, renderTextWithShortcodes };
1735
2015
  //# sourceMappingURL=index.esm.js.map