@marvalt/wparser 0.1.13 → 0.1.15

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.cjs CHANGED
@@ -1837,9 +1837,13 @@ const ButtonBlock = ({ block }) => {
1837
1837
  };
1838
1838
  const Cover = ({ block, children }) => {
1839
1839
  const attrs = block.attributes || {};
1840
- const { url, id, backgroundImage, overlayColor, dimRatio = 0, align = 'full', minHeight, minHeightUnit = 'vh', hasParallax, } = attrs;
1840
+ const { url, id, backgroundImage, cloudflareUrl, overlayColor, dimRatio = 0, align = 'full', minHeight, minHeightUnit = 'vh', hasParallax, } = attrs;
1841
1841
  // Get background image URL from various possible sources
1842
- let bgImageUrl = url || backgroundImage || (typeof backgroundImage === 'object' && backgroundImage?.url);
1842
+ // Priority: cloudflareUrl (from plugin) > url > backgroundImage > innerHTML extraction
1843
+ let bgImageUrl = cloudflareUrl;
1844
+ if (!bgImageUrl) {
1845
+ bgImageUrl = url || backgroundImage || (typeof backgroundImage === 'object' && backgroundImage?.url);
1846
+ }
1843
1847
  // If not found in attributes, try to extract from innerHTML
1844
1848
  if (!bgImageUrl && block.innerHTML) {
1845
1849
  // Try to extract img src from innerHTML
@@ -1855,10 +1859,16 @@ const Cover = ({ block, children }) => {
1855
1859
  }
1856
1860
  }
1857
1861
  }
1858
- // Convert to Cloudflare URL if it's a Cloudflare image, otherwise use as-is
1859
- if (bgImageUrl && isCloudflareImageUrl(bgImageUrl)) {
1860
- // Use full width for cover images
1861
- bgImageUrl = getCloudflareVariantUrl(bgImageUrl, { width: 1920 });
1862
+ // Convert to Cloudflare URL variant if it's a Cloudflare image, otherwise use as-is
1863
+ if (bgImageUrl) {
1864
+ if (isCloudflareImageUrl(bgImageUrl)) {
1865
+ // Use full width for cover images
1866
+ bgImageUrl = getCloudflareVariantUrl(bgImageUrl, { width: 1920 });
1867
+ }
1868
+ // If cloudflareUrl was provided, it's already a Cloudflare URL, just add variant
1869
+ else if (cloudflareUrl) {
1870
+ bgImageUrl = getCloudflareVariantUrl(cloudflareUrl, { width: 1920 });
1871
+ }
1862
1872
  }
1863
1873
  // Build alignment classes
1864
1874
  const alignClass = getAlignmentClasses(align);
@@ -1889,12 +1899,36 @@ const MediaText = ({ block, children, context }) => {
1889
1899
  // Access innerBlocks to identify media vs content
1890
1900
  const innerBlocks = block.innerBlocks || [];
1891
1901
  // Find media block (image or video)
1892
- const mediaBlockIndex = innerBlocks.findIndex((b) => b.name === 'core/image' || b.name === 'core/video');
1902
+ let mediaBlockIndex = innerBlocks.findIndex((b) => b.name === 'core/image' || b.name === 'core/video');
1903
+ // Check for cloudflareUrl in attributes first (provided by WordPress plugin)
1904
+ const cloudflareUrl = attrs['cloudflareUrl'];
1905
+ // If no media block found, try to extract from innerHTML
1906
+ let imageUrl = null;
1907
+ if (mediaBlockIndex === -1 && block.innerHTML) {
1908
+ // Extract img src from innerHTML
1909
+ const imgMatch = block.innerHTML.match(/<img[^>]+src=["']([^"']+)["']/i);
1910
+ if (imgMatch && imgMatch[1]) {
1911
+ imageUrl = imgMatch[1];
1912
+ }
1913
+ }
1893
1914
  // Render children - media-text typically has media as first child, then content
1894
1915
  const childrenArray = React.Children.toArray(children);
1895
- const mediaElement = mediaBlockIndex >= 0 && childrenArray[mediaBlockIndex]
1916
+ let mediaElement = mediaBlockIndex >= 0 && childrenArray[mediaBlockIndex]
1896
1917
  ? childrenArray[mediaBlockIndex]
1897
1918
  : null;
1919
+ // Use cloudflareUrl from attributes if available
1920
+ if (!mediaElement && cloudflareUrl) {
1921
+ const finalImageUrl = getCloudflareVariantUrl(cloudflareUrl, { width: 1024 });
1922
+ mediaElement = (jsxRuntimeExports.jsx("img", { src: finalImageUrl, alt: "", className: "w-full h-auto rounded-lg object-cover" }));
1923
+ }
1924
+ // If we extracted image URL from innerHTML, render it
1925
+ else if (!mediaElement && imageUrl) {
1926
+ // Convert to Cloudflare URL if applicable
1927
+ const finalImageUrl = isCloudflareImageUrl(imageUrl)
1928
+ ? getCloudflareVariantUrl(imageUrl, { width: 1024 })
1929
+ : imageUrl;
1930
+ mediaElement = (jsxRuntimeExports.jsx("img", { src: finalImageUrl, alt: "", className: "w-full h-auto rounded-lg object-cover" }));
1931
+ }
1898
1932
  // Content is all other children
1899
1933
  const contentElements = childrenArray.filter((_, index) => index !== mediaBlockIndex);
1900
1934
  // Build alignment classes
@@ -1907,7 +1941,9 @@ const MediaText = ({ block, children, context }) => {
1907
1941
  const stackClass = 'flex-col md:flex-row';
1908
1942
  // Media position determines order
1909
1943
  const isMediaRight = mediaPosition === 'right';
1910
- 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 })] }) }));
1944
+ // Add section spacing for consistent vertical rhythm
1945
+ const spacingClass = getSectionSpacingClasses();
1946
+ return (jsxRuntimeExports.jsx("div", { className: buildClassName(alignClass, spacingClass, '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 md:w-1/2'), children: mediaElement || jsxRuntimeExports.jsx("div", { className: "bg-gray-200 h-64 rounded-lg" }) }), jsxRuntimeExports.jsx("div", { className: buildClassName(isMediaRight ? 'order-1' : 'order-2', 'md:w-1/2', getContentSpacingClasses()), children: contentElements.length > 0 ? contentElements : children })] }) }));
1911
1947
  };
1912
1948
  const Fallback = ({ block, children }) => {
1913
1949
  // Minimal fallback; do not render innerHTML directly in v1 for safety
@@ -2134,6 +2170,9 @@ function detectHeroShortcode(blocks) {
2134
2170
  const html = (block.innerHTML || '').toLowerCase();
2135
2171
  if (html.includes('[herosection]'))
2136
2172
  return true;
2173
+ // Check if this is a cover block (which is a hero section)
2174
+ if (block.name === 'core/cover')
2175
+ return true;
2137
2176
  if (block.innerBlocks?.length && detectHeroShortcode(block.innerBlocks))
2138
2177
  return true;
2139
2178
  }
@@ -2439,10 +2478,12 @@ function extractButtonsFromInnerBlocks(block) {
2439
2478
  * Extract text alignment from inner blocks
2440
2479
  * Recursively searches for heading or paragraph blocks with textAlign attribute
2441
2480
  * Also checks group blocks for justifyContent in layout
2481
+ * Priority: heading/paragraph textAlign takes precedence over group justifyContent
2442
2482
  */
2443
2483
  function extractTextAlignFromInnerBlocks(block) {
2444
2484
  const innerBlocks = block.innerBlocks || [];
2445
- // Recursively search for heading or paragraph blocks with textAlign
2485
+ // First, recursively search for heading or paragraph blocks with textAlign
2486
+ // (These take priority over group justifyContent)
2446
2487
  for (const innerBlock of innerBlocks) {
2447
2488
  if (innerBlock.name === 'core/heading' || innerBlock.name === 'core/paragraph') {
2448
2489
  const attrs = innerBlock.attributes || {};
@@ -2451,7 +2492,13 @@ function extractTextAlignFromInnerBlocks(block) {
2451
2492
  return textAlign;
2452
2493
  }
2453
2494
  }
2454
- // Check group blocks for justifyContent
2495
+ // Recursively search nested blocks for headings/paragraphs first
2496
+ const nestedAlign = extractTextAlignFromInnerBlocks(innerBlock);
2497
+ if (nestedAlign)
2498
+ return nestedAlign;
2499
+ }
2500
+ // Only check group blocks if no heading/paragraph alignment found
2501
+ for (const innerBlock of innerBlocks) {
2455
2502
  if (innerBlock.name === 'core/group') {
2456
2503
  const attrs = innerBlock.attributes || {};
2457
2504
  const layout = attrs['layout'];
@@ -2463,10 +2510,6 @@ function extractTextAlignFromInnerBlocks(block) {
2463
2510
  if (justifyContent === 'right')
2464
2511
  return 'right';
2465
2512
  }
2466
- // Recursively search nested blocks
2467
- const nestedAlign = extractTextAlignFromInnerBlocks(innerBlock);
2468
- if (nestedAlign)
2469
- return nestedAlign;
2470
2513
  }
2471
2514
  return null;
2472
2515
  }