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