@marvalt/wparser 0.1.34 → 0.1.38

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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAClH,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,EAC9B,6BAA6B,EAC7B,iCAAiC,EACjC,+BAA+B,EAC/B,+BAA+B,EAC/B,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,2BAA2B,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACtI,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,OAAO,EACL,2BAA2B,EAC3B,8BAA8B,EAC9B,6BAA6B,EAC7B,iCAAiC,EACjC,+BAA+B,EAC/B,+BAA+B,EAC/B,oBAAoB,EACpB,sBAAsB,EACtB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,yBAAyB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC"}
package/dist/index.esm.js CHANGED
@@ -1590,16 +1590,41 @@ function getImageUrl(block) {
1590
1590
  return null;
1591
1591
  }
1592
1592
  /**
1593
- * Extract image attributes (alt, width, height) from block
1593
+ * Extract image attributes (alt, width, height, alignment) from block
1594
1594
  */
1595
1595
  function getImageAttributes(block) {
1596
1596
  const attrs = block.attributes || {};
1597
1597
  const url = getImageUrl(block);
1598
+ // Extract width - can be number or string like "640px"
1599
+ let width;
1600
+ const widthAttr = attrs['width'];
1601
+ if (widthAttr) {
1602
+ if (typeof widthAttr === 'number') {
1603
+ width = widthAttr;
1604
+ }
1605
+ else if (typeof widthAttr === 'string') {
1606
+ // Try to parse number from string like "640px" or "640"
1607
+ const numMatch = widthAttr.match(/^(\d+)/);
1608
+ if (numMatch) {
1609
+ width = parseInt(numMatch[1], 10);
1610
+ }
1611
+ else {
1612
+ // Keep as string if it's not a simple number
1613
+ width = widthAttr;
1614
+ }
1615
+ }
1616
+ }
1617
+ // Extract alignment
1618
+ const align = attrs['align'];
1619
+ const alignValue = align === 'left' || align === 'center' || align === 'right'
1620
+ ? align
1621
+ : undefined;
1598
1622
  return {
1599
1623
  url,
1600
1624
  alt: attrs['alt'] || '',
1601
- width: attrs['width'] ? Number(attrs['width']) : undefined,
1625
+ width,
1602
1626
  height: attrs['height'] ? Number(attrs['height']) : undefined,
1627
+ align: alignValue,
1603
1628
  };
1604
1629
  }
1605
1630
  /**
@@ -1731,7 +1756,17 @@ function extractImageUrl(block) {
1731
1756
  * Extract image attributes (url, alt, width, height)
1732
1757
  */
1733
1758
  function extractImageAttributes(block) {
1734
- return getImageAttributes(block);
1759
+ const attrs = getImageAttributes(block);
1760
+ // Convert width to number if it's a string
1761
+ const width = typeof attrs.width === 'string'
1762
+ ? (parseInt(attrs.width, 10) || undefined)
1763
+ : attrs.width;
1764
+ return {
1765
+ url: attrs.url,
1766
+ alt: attrs.alt,
1767
+ width,
1768
+ height: attrs.height,
1769
+ };
1735
1770
  }
1736
1771
  /**
1737
1772
  * Extract title/heading text from a block
@@ -2235,16 +2270,63 @@ function getHeadingSpacing(spacingConfig, level) {
2235
2270
  return headingConfig?.h3 || 'mt-6 mb-4';
2236
2271
  }
2237
2272
  const Paragraph = ({ block, context }) => {
2238
- const content = getBlockTextContent(block);
2239
2273
  const attrs = block.attributes || {};
2240
2274
  const textAlign = getTextAlignClasses(attrs['align']);
2241
2275
  const spacing = getSpacing(context.spacingConfig || context.registry.spacingConfig, 'paragraph', 'my-6');
2242
- // Check if content contains shortcodes
2276
+ // Check if innerHTML contains HTML elements (like links, strong, em, etc.)
2277
+ const hasHTML = block.innerHTML && /<[a-z][\s\S]*>/i.test(block.innerHTML);
2278
+ // If innerHTML contains HTML elements, render it directly (preserves links, formatting, etc.)
2279
+ if (hasHTML && block.innerHTML) {
2280
+ const htmlContent = block.innerHTML;
2281
+ // Check if HTML contains shortcodes
2282
+ const hasShortcodes = /\[(\w+)/.test(htmlContent);
2283
+ if (hasShortcodes && context.registry.shortcodes) {
2284
+ // For HTML with shortcodes, we need to process shortcodes first
2285
+ // Extract text content to process shortcodes, then reconstruct
2286
+ const textContent = getBlockTextContent(block);
2287
+ const parts = renderTextWithShortcodes(textContent, context.registry);
2288
+ // Check if any part is a block-level element (section, div, etc.)
2289
+ const isBlockLevelElement = (element) => {
2290
+ if (!React.isValidElement(element)) {
2291
+ return false;
2292
+ }
2293
+ const type = element.type;
2294
+ // Check for block-level HTML elements
2295
+ if (typeof type === 'string' && ['section', 'div', 'article', 'header', 'footer', 'aside', 'nav'].includes(type)) {
2296
+ return true;
2297
+ }
2298
+ // Check if it's React.Fragment - recursively check its children
2299
+ if (type === React.Fragment) {
2300
+ const fragmentProps = element.props;
2301
+ const children = React.Children.toArray(fragmentProps.children);
2302
+ return children.some((child) => isBlockLevelElement(child));
2303
+ }
2304
+ // Check if it's a React component (likely block-level)
2305
+ if (typeof type === 'function' || (typeof type === 'object' && type !== null && type !== React.Fragment)) {
2306
+ return true;
2307
+ }
2308
+ return false;
2309
+ };
2310
+ const hasBlockLevelContent = React.Children.toArray(parts).some((part) => isBlockLevelElement(part));
2311
+ if (hasBlockLevelContent) {
2312
+ // Render block-level content without <p> wrapper, but add spacing wrapper
2313
+ return jsxRuntimeExports.jsx("div", { className: spacing, children: parts });
2314
+ }
2315
+ // For mixed HTML and shortcodes, render shortcode parts but this is complex
2316
+ // For now, fall back to rendering HTML with shortcodes processed in text
2317
+ // This is a limitation - shortcodes in HTML paragraphs with links won't work perfectly
2318
+ // But links will be preserved
2319
+ return jsxRuntimeExports.jsx("p", { className: buildClassName(spacing, textAlign), dangerouslySetInnerHTML: { __html: htmlContent } });
2320
+ }
2321
+ // No shortcodes, just render HTML directly (preserves links, formatting, etc.)
2322
+ return jsxRuntimeExports.jsx("p", { className: buildClassName(spacing, textAlign), dangerouslySetInnerHTML: { __html: htmlContent } });
2323
+ }
2324
+ // No HTML, use text content (existing logic for shortcodes)
2325
+ const content = getBlockTextContent(block);
2243
2326
  const hasShortcodes = /\[(\w+)/.test(content);
2244
2327
  if (hasShortcodes && context.registry.shortcodes) {
2245
2328
  const parts = renderTextWithShortcodes(content, context.registry);
2246
2329
  // Check if any part is a block-level element (section, div, etc.)
2247
- // If so, render without wrapping in <p> to avoid DOM nesting violations
2248
2330
  const isBlockLevelElement = (element) => {
2249
2331
  if (!React.isValidElement(element)) {
2250
2332
  return false;
@@ -2261,7 +2343,6 @@ const Paragraph = ({ block, context }) => {
2261
2343
  return children.some((child) => isBlockLevelElement(child));
2262
2344
  }
2263
2345
  // Check if it's a React component (likely block-level)
2264
- // Most custom components render block-level content
2265
2346
  if (typeof type === 'function' || (typeof type === 'object' && type !== null && type !== React.Fragment)) {
2266
2347
  return true;
2267
2348
  }
@@ -2298,15 +2379,48 @@ const Image = ({ block, context }) => {
2298
2379
  const imageAttrs = getImageAttributes(block);
2299
2380
  if (!imageAttrs.url)
2300
2381
  return null;
2382
+ // Extract width for Cloudflare variant (use numeric value)
2383
+ const numericWidth = typeof imageAttrs.width === 'number'
2384
+ ? imageAttrs.width
2385
+ : (typeof imageAttrs.width === 'string' ? parseInt(imageAttrs.width, 10) || 1024 : 1024);
2301
2386
  // Use Cloudflare variant URL if it's a Cloudflare image
2302
2387
  let imageUrl = imageAttrs.url;
2303
2388
  if (isCloudflareImageUrl(imageUrl)) {
2304
- const width = imageAttrs.width || 1024;
2305
2389
  const height = imageAttrs.height;
2306
- imageUrl = getCloudflareVariantUrl(imageUrl, { width, height });
2390
+ imageUrl = getCloudflareVariantUrl(imageUrl, { width: numericWidth, height });
2307
2391
  }
2308
2392
  const spacing = getSpacing(context.spacingConfig || context.registry.spacingConfig, 'image', 'my-6');
2309
- return (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: imageAttrs.alt, width: imageAttrs.width, height: imageAttrs.height, className: buildClassName('w-full h-auto rounded-lg object-cover', spacing), style: { maxWidth: '100%', height: 'auto' }, loading: "lazy" }));
2393
+ // Handle alignment (left, center, right)
2394
+ let alignClass = '';
2395
+ if (imageAttrs.align === 'left') {
2396
+ alignClass = 'mr-auto';
2397
+ }
2398
+ else if (imageAttrs.align === 'center') {
2399
+ alignClass = 'mx-auto';
2400
+ }
2401
+ else if (imageAttrs.align === 'right') {
2402
+ alignClass = 'ml-auto';
2403
+ }
2404
+ // Handle width - if specified, use it; otherwise use w-full
2405
+ let widthClass = 'w-full';
2406
+ let widthStyle = {};
2407
+ if (imageAttrs.width) {
2408
+ if (typeof imageAttrs.width === 'string' && imageAttrs.width.includes('px')) {
2409
+ // Use inline style for pixel values
2410
+ widthStyle.width = imageAttrs.width;
2411
+ widthClass = ''; // Don't use w-full if we have explicit width
2412
+ }
2413
+ else if (typeof imageAttrs.width === 'number') {
2414
+ // Use inline style for numeric pixel values
2415
+ widthStyle.width = `${imageAttrs.width}px`;
2416
+ widthClass = ''; // Don't use w-full if we have explicit width
2417
+ }
2418
+ }
2419
+ // Build image classes - include shadow (app can override via registry)
2420
+ // Default shadow is shadow-md, but app can customize
2421
+ const imageClasses = buildClassName('h-auto rounded-lg object-cover shadow-md', // shadow-md is default, app can override
2422
+ widthClass, alignClass, spacing);
2423
+ return (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: imageAttrs.alt, width: typeof imageAttrs.width === 'number' ? imageAttrs.width : undefined, height: imageAttrs.height, className: imageClasses, style: { maxWidth: '100%', height: 'auto', ...widthStyle }, loading: "lazy" }));
2310
2424
  };
2311
2425
  const List = ({ block, children, context }) => {
2312
2426
  const attrs = block.attributes || {};