@marvalt/wparser 0.1.17 → 0.1.19

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
@@ -1605,15 +1605,30 @@ function isValidCloudflareUrl(url) {
1605
1605
  // Check if it's a Cloudflare URL
1606
1606
  if (!url.includes('imagedelivery.net'))
1607
1607
  return false;
1608
- // A complete URL should have at least 3 path segments: /account/image-id/
1609
- // Incomplete URLs might end with just /account/ or /account
1610
- const urlObj = new URL(url);
1611
- const pathSegments = urlObj.pathname.split('/').filter(Boolean);
1612
- // Should have at least account hash and image ID (2 segments minimum)
1613
- // But we also accept URLs that end with / (which means they might be complete)
1614
- // The issue is URLs like: https://imagedelivery.net/ZFArYcvsK9lQ3btUK-x2rA/
1615
- // This is incomplete - it's missing the image ID
1616
- return pathSegments.length >= 2;
1608
+ try {
1609
+ const urlObj = new URL(url);
1610
+ const pathSegments = urlObj.pathname.split('/').filter(Boolean);
1611
+ // A complete Cloudflare URL should have:
1612
+ // - Account hash (first segment)
1613
+ // - Image ID (second segment, typically a UUID)
1614
+ // Example: /ZFArYcvsK9lQ3btUK-x2rA/240f5739-ca22-4edb-5726-87fd1ad6c900/
1615
+ // Incomplete URLs like: /ZFArYcvsK9lQ3btUK-x2rA/ (only account hash)
1616
+ // Image IDs are typically UUIDs (36 chars with dashes) or similar long strings
1617
+ if (pathSegments.length < 2) {
1618
+ return false; // Missing image ID
1619
+ }
1620
+ // Check if the second segment looks like an image ID (UUID format or long alphanumeric)
1621
+ const imageId = pathSegments[1];
1622
+ // UUID format: 8-4-4-4-12 (e.g., 240f5739-ca22-4edb-5726-87fd1ad6c900)
1623
+ // Or long alphanumeric string
1624
+ const isUuidLike = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(imageId);
1625
+ const isLongId = imageId.length >= 20; // Long alphanumeric ID
1626
+ return isUuidLike || isLongId;
1627
+ }
1628
+ catch {
1629
+ // Invalid URL format
1630
+ return false;
1631
+ }
1617
1632
  }
1618
1633
  /**
1619
1634
  * Extract image URL from block with priority:
@@ -1875,12 +1890,24 @@ const Column = ({ block, children }) => {
1875
1890
  const Separator = () => jsxRuntimeExports.jsx("hr", { className: "border-gray-200 my-8" });
1876
1891
  const ButtonBlock = ({ block }) => {
1877
1892
  const attrs = block.attributes || {};
1878
- const url = attrs['url'];
1879
- const text = attrs['text'];
1893
+ let url = attrs['url'];
1894
+ let text = attrs['text'];
1880
1895
  attrs['linkDestination'];
1896
+ // Extract from innerHTML if not in attributes (buttons often store data in innerHTML)
1897
+ if (!url && block.innerHTML) {
1898
+ const linkMatch = block.innerHTML.match(/<a[^>]+href=["']([^"']+)["'][^>]*>([^<]+)<\/a>/i);
1899
+ if (linkMatch) {
1900
+ url = linkMatch[1];
1901
+ text = linkMatch[2] || text;
1902
+ }
1903
+ }
1904
+ // Get text from block content if still missing
1905
+ if (!text) {
1906
+ text = getBlockTextContent(block);
1907
+ }
1881
1908
  if (!url && !text)
1882
1909
  return null;
1883
- const buttonText = text || getBlockTextContent(block) || 'Learn more';
1910
+ const buttonText = text || 'Learn more';
1884
1911
  // Handle internal vs external links
1885
1912
  const isExternal = url && (url.startsWith('http://') || url.startsWith('https://'));
1886
1913
  const linkProps = isExternal ? { target: '_blank', rel: 'noopener noreferrer' } : {};
@@ -1954,19 +1981,34 @@ const MediaText = ({ block, children, context }) => {
1954
1981
  const finalImageUrl = isCloudflareImageUrl(imageUrl)
1955
1982
  ? getCloudflareVariantUrl(imageUrl, { width: 1024 })
1956
1983
  : imageUrl;
1957
- mediaElement = (jsxRuntimeExports.jsx("img", { src: finalImageUrl, alt: "", className: "w-full h-auto rounded-lg object-cover", loading: "lazy" }));
1984
+ mediaElement = (jsxRuntimeExports.jsx("img", { src: finalImageUrl, alt: "", className: "w-full h-auto rounded-lg shadow-lg object-cover", loading: "lazy" }));
1958
1985
  }
1959
1986
  }
1960
1987
  // Content is all other children
1961
1988
  const contentElements = childrenArray.filter((_, index) => index !== mediaBlockIndex);
1962
1989
  // Build alignment classes - ensure proper container width
1963
- // For 'wide', use max-w-7xl; for 'full', use w-full; default to contained
1990
+ // For 'wide', check if we're inside a constrained group context
1991
+ // If innerBlocks contain a group with constrained layout, the parent likely has constrained layout too
1992
+ // In that case, use w-full to fill the parent container (which is already boxed)
1993
+ // Otherwise, use max-w-7xl for standalone wide blocks
1964
1994
  let alignClass;
1965
1995
  if (align === 'full') {
1966
1996
  alignClass = 'w-full';
1967
1997
  }
1968
1998
  else if (align === 'wide') {
1969
- alignClass = 'max-w-7xl mx-auto';
1999
+ // Check if media-text content is wrapped in a constrained group
2000
+ // This indicates the block is in a constrained layout context
2001
+ // In that case, fill the parent container (which is already boxed) rather than applying another container
2002
+ const hasConstrainedGroup = innerBlocks.some((b) => {
2003
+ if (b.name === 'core/group') {
2004
+ const groupLayout = b.attributes?.layout;
2005
+ return groupLayout?.type === 'constrained';
2006
+ }
2007
+ return false;
2008
+ });
2009
+ // If we have a constrained group in innerBlocks, use w-full to fill parent container
2010
+ // Otherwise, use max-w-7xl for standalone wide blocks
2011
+ alignClass = hasConstrainedGroup ? 'w-full' : 'max-w-7xl mx-auto';
1970
2012
  }
1971
2013
  else {
1972
2014
  // Default to contained width (not full width)