@marvalt/wparser 0.1.12 → 0.1.14

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
@@ -1382,15 +1382,15 @@ if (process.env.NODE_ENV === 'production') {
1382
1382
 
1383
1383
  var jsxRuntimeExports = jsxRuntime.exports;
1384
1384
 
1385
- function renderNodes(blocks, registry, options) {
1386
- return blocks.map((block, index) => renderBlock(block, registry, `b-${index}`, options));
1385
+ function renderNodes(blocks, registry, options, page) {
1386
+ return blocks.map((block, index) => renderBlock(block, registry, `b-${index}`, options, page));
1387
1387
  }
1388
- function renderBlock(block, registry, key, options) {
1388
+ function renderBlock(block, registry, key, options, page) {
1389
1389
  const Renderer = registry.renderers[block.name] || registry.fallback;
1390
1390
  const children = block.innerBlocks && block.innerBlocks.length
1391
- ? block.innerBlocks.map((child, i) => renderBlock(child, registry, `${key}-${i}`, options))
1391
+ ? block.innerBlocks.map((child, i) => renderBlock(child, registry, `${key}-${i}`, options, page))
1392
1392
  : undefined;
1393
- const node = Renderer({ block, children, context: { registry } });
1393
+ const node = Renderer({ block, children, context: { registry, page } });
1394
1394
  if (options?.debugWrappers) {
1395
1395
  return (jsxRuntimeExports.jsx("div", { "data-block": block.name, className: "wp-block", children: node }, key));
1396
1396
  }
@@ -1734,20 +1734,29 @@ const Paragraph = ({ block, context }) => {
1734
1734
  const parts = renderTextWithShortcodes(content, context.registry);
1735
1735
  // Check if any part is a block-level element (section, div, etc.)
1736
1736
  // If so, render without wrapping in <p> to avoid DOM nesting violations
1737
- const hasBlockLevelContent = React.Children.toArray(parts).some((part) => {
1738
- if (React.isValidElement(part)) {
1739
- const type = part.type;
1740
- // Check for block-level HTML elements
1741
- if (typeof type === 'string' && ['section', 'div', 'article', 'header', 'footer', 'aside', 'nav'].includes(type)) {
1742
- return true;
1743
- }
1744
- // Check if it's a React component (likely block-level)
1745
- if (typeof type === 'function' || (typeof type === 'object' && type !== null)) {
1746
- return true;
1747
- }
1737
+ const isBlockLevelElement = (element) => {
1738
+ if (!React.isValidElement(element)) {
1739
+ return false;
1740
+ }
1741
+ const type = element.type;
1742
+ // Check for block-level HTML elements
1743
+ if (typeof type === 'string' && ['section', 'div', 'article', 'header', 'footer', 'aside', 'nav'].includes(type)) {
1744
+ return true;
1745
+ }
1746
+ // Check if it's React.Fragment - recursively check its children
1747
+ if (type === React.Fragment) {
1748
+ const fragmentProps = element.props;
1749
+ const children = React.Children.toArray(fragmentProps.children);
1750
+ return children.some((child) => isBlockLevelElement(child));
1751
+ }
1752
+ // Check if it's a React component (likely block-level)
1753
+ // Most custom components render block-level content
1754
+ if (typeof type === 'function' || (typeof type === 'object' && type !== null && type !== React.Fragment)) {
1755
+ return true;
1748
1756
  }
1749
1757
  return false;
1750
- });
1758
+ };
1759
+ const hasBlockLevelContent = React.Children.toArray(parts).some((part) => isBlockLevelElement(part));
1751
1760
  if (hasBlockLevelContent) {
1752
1761
  // Render block-level content without <p> wrapper
1753
1762
  return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: parts });
@@ -2085,7 +2094,7 @@ function createEnhancedRegistry(mappings = [], baseRegistry) {
2085
2094
  };
2086
2095
  }
2087
2096
 
2088
- const WPContent = ({ blocks, registry, className }) => {
2097
+ const WPContent = ({ blocks, registry, className, page }) => {
2089
2098
  if (!Array.isArray(blocks)) {
2090
2099
  if (process.env.NODE_ENV !== 'production') {
2091
2100
  // eslint-disable-next-line no-console
@@ -2097,7 +2106,7 @@ const WPContent = ({ blocks, registry, className }) => {
2097
2106
  throw new Error('WPContent: registry is required');
2098
2107
  }
2099
2108
  const ast = parseGutenbergBlocks(blocks);
2100
- return (jsxRuntimeExports.jsx("div", { className: className, children: renderNodes(ast, registry) }));
2109
+ return (jsxRuntimeExports.jsx("div", { className: className, children: renderNodes(ast, registry, undefined, page) }));
2101
2110
  };
2102
2111
 
2103
2112
  /**
@@ -2118,13 +2127,16 @@ const WPPage = ({ page, registry, className }) => {
2118
2127
  }
2119
2128
  const hasHeroShortcode = React.useMemo(() => detectHeroShortcode(page.blocks), [page.blocks]);
2120
2129
  const featured = getFeaturedImage(page);
2121
- 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 })] }));
2130
+ 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, page: page })] }));
2122
2131
  };
2123
2132
  function detectHeroShortcode(blocks) {
2124
2133
  for (const block of blocks) {
2125
2134
  const html = (block.innerHTML || '').toLowerCase();
2126
2135
  if (html.includes('[herosection]'))
2127
2136
  return true;
2137
+ // Check if this is a cover block (which is a hero section)
2138
+ if (block.name === 'core/cover')
2139
+ return true;
2128
2140
  if (block.innerBlocks?.length && detectHeroShortcode(block.innerBlocks))
2129
2141
  return true;
2130
2142
  }
@@ -2167,10 +2179,14 @@ class WPErrorBoundary extends React.Component {
2167
2179
 
2168
2180
  /**
2169
2181
  * Extract background image URL from a block
2170
- * Checks various possible sources: url, backgroundImage, innerHTML
2182
+ * Checks various possible sources: url, backgroundImage, innerHTML, featured image
2171
2183
  */
2172
- function extractBackgroundImage(block) {
2184
+ function extractBackgroundImage(block, page) {
2173
2185
  const attrs = block.attributes || {};
2186
+ // Check if block uses featured image
2187
+ if (attrs['useFeaturedImage'] === true && page?._embedded?.['wp:featuredmedia']?.[0]?.source_url) {
2188
+ return page._embedded['wp:featuredmedia'][0].source_url;
2189
+ }
2174
2190
  // Try various attribute keys
2175
2191
  let url = attrs['url'] ||
2176
2192
  attrs['backgroundImage'] ||
@@ -2426,10 +2442,12 @@ function extractButtonsFromInnerBlocks(block) {
2426
2442
  * Extract text alignment from inner blocks
2427
2443
  * Recursively searches for heading or paragraph blocks with textAlign attribute
2428
2444
  * Also checks group blocks for justifyContent in layout
2445
+ * Priority: heading/paragraph textAlign takes precedence over group justifyContent
2429
2446
  */
2430
2447
  function extractTextAlignFromInnerBlocks(block) {
2431
2448
  const innerBlocks = block.innerBlocks || [];
2432
- // Recursively search for heading or paragraph blocks with textAlign
2449
+ // First, recursively search for heading or paragraph blocks with textAlign
2450
+ // (These take priority over group justifyContent)
2433
2451
  for (const innerBlock of innerBlocks) {
2434
2452
  if (innerBlock.name === 'core/heading' || innerBlock.name === 'core/paragraph') {
2435
2453
  const attrs = innerBlock.attributes || {};
@@ -2438,7 +2456,13 @@ function extractTextAlignFromInnerBlocks(block) {
2438
2456
  return textAlign;
2439
2457
  }
2440
2458
  }
2441
- // Check group blocks for justifyContent
2459
+ // Recursively search nested blocks for headings/paragraphs first
2460
+ const nestedAlign = extractTextAlignFromInnerBlocks(innerBlock);
2461
+ if (nestedAlign)
2462
+ return nestedAlign;
2463
+ }
2464
+ // Only check group blocks if no heading/paragraph alignment found
2465
+ for (const innerBlock of innerBlocks) {
2442
2466
  if (innerBlock.name === 'core/group') {
2443
2467
  const attrs = innerBlock.attributes || {};
2444
2468
  const layout = attrs['layout'];
@@ -2450,10 +2474,6 @@ function extractTextAlignFromInnerBlocks(block) {
2450
2474
  if (justifyContent === 'right')
2451
2475
  return 'right';
2452
2476
  }
2453
- // Recursively search nested blocks
2454
- const nestedAlign = extractTextAlignFromInnerBlocks(innerBlock);
2455
- if (nestedAlign)
2456
- return nestedAlign;
2457
2477
  }
2458
2478
  return null;
2459
2479
  }