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