@marvalt/wparser 0.1.42 → 0.1.45

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
@@ -2136,6 +2136,7 @@ function extractBackgroundColor(block, context) {
2136
2136
  */
2137
2137
  function extractTextColor(block, context) {
2138
2138
  const attrs = block.attributes || {};
2139
+ const mapper = context.colorMapper;
2139
2140
  // Try multiple possible attribute names for text color
2140
2141
  let wpColorName = attrs['textColor'] ||
2141
2142
  attrs['text'] ||
@@ -2152,31 +2153,42 @@ function extractTextColor(block, context) {
2152
2153
  if (colorMatch && colorMatch[1]) {
2153
2154
  wpColorName = colorMatch[1];
2154
2155
  }
2155
- // Debug logging
2156
- if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development' && !wpColorName) {
2157
- // Check if there are any color-related classes
2158
- const hasColorClass = className.includes('-color');
2159
- if (hasColorClass && context.colorMapper) {
2160
- console.log('🔍 extractTextColor - Found color class in className but no match:', {
2161
- blockName: block.name,
2162
- className: className,
2163
- colorClasses: className.split(' ').filter(c => c.includes('-color')),
2164
- });
2156
+ // Enhanced debug logging
2157
+ if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'development') {
2158
+ if (!wpColorName) {
2159
+ const hasColorClass = className.includes('-color');
2160
+ if (hasColorClass && context.colorMapper) {
2161
+ console.log('🔍 extractTextColor - Found color class in className but no match:', {
2162
+ blockName: block.name,
2163
+ className: className,
2164
+ colorClasses: className.split(' ').filter(c => c.includes('-color')),
2165
+ allAttrs: Object.keys(attrs),
2166
+ });
2167
+ }
2168
+ }
2169
+ else {
2170
+ console.log('✅ extractTextColor - Found color in className:', wpColorName);
2165
2171
  }
2166
2172
  }
2167
2173
  }
2168
2174
  if (!wpColorName || typeof wpColorName !== 'string') {
2169
- return null;
2175
+ wpColorName = null;
2170
2176
  }
2171
2177
  // Use colorMapper from context if available
2172
2178
  // Note: colorMapper returns combined classes like "bg-[#FBFAF3] text-gray-900"
2173
2179
  // We need to extract just the text color part
2174
- if (context.colorMapper) {
2175
- const mapped = context.colorMapper(wpColorName);
2180
+ if (mapper && wpColorName) {
2181
+ const mapped = mapper(wpColorName);
2176
2182
  if (mapped) {
2177
- // Extract text color classes (e.g., "text-white", "text-gray-900")
2178
- // Match text- classes but not text- in the middle of other classes
2179
- const textColorMatch = mapped.match(/\btext-[\w-]+/g);
2183
+ // If the mapper provided a background arbitrary value, derive a text color class directly from it
2184
+ const bgArbitrary = mapped.match(/\bbg-\[([^\]]+)\]/);
2185
+ if (bgArbitrary && bgArbitrary[1]) {
2186
+ const derivedText = `text-[${bgArbitrary[1]}]`;
2187
+ return derivedText;
2188
+ }
2189
+ // Extract text color classes (e.g., "text-white", "text-gray-900", "text-[#123456]")
2190
+ // Match text- classes including arbitrary values in brackets
2191
+ const textColorMatch = mapped.match(/\btext-(\[[^\]]+\]|[\w-]+)/g);
2180
2192
  if (textColorMatch && textColorMatch.length > 0) {
2181
2193
  // Return the last text color class (in case there are multiple)
2182
2194
  const result = textColorMatch[textColorMatch.length - 1];
@@ -2194,6 +2206,34 @@ function extractTextColor(block, context) {
2194
2206
  // Fallback: return null (no text color applied, will inherit from parent)
2195
2207
  return null;
2196
2208
  }
2209
+ /**
2210
+ * Infer a readable text color class based on a background class string.
2211
+ * Supports bg-[#hex] and bg-[rgb(...)].
2212
+ */
2213
+ function inferTextColorFromBackground(backgroundClass) {
2214
+ if (!backgroundClass)
2215
+ return null;
2216
+ // Try to extract hex color from arbitrary value class bg-[#xxxxxx]
2217
+ const hexMatch = backgroundClass.match(/bg-\[#?([0-9a-fA-F]{6})\]/);
2218
+ if (hexMatch) {
2219
+ const hex = hexMatch[1];
2220
+ const r = parseInt(hex.slice(0, 2), 16);
2221
+ const g = parseInt(hex.slice(2, 4), 16);
2222
+ const b = parseInt(hex.slice(4, 6), 16);
2223
+ const brightness = (r * 299 + g * 587 + b * 114) / 1000;
2224
+ return brightness < 140 ? 'text-white' : 'text-gray-900';
2225
+ }
2226
+ // Try rgb() form
2227
+ const rgbMatch = backgroundClass.match(/bg-\[rgb\((\d+),\s*(\d+),\s*(\d+)\)\]/i);
2228
+ if (rgbMatch) {
2229
+ const r = parseInt(rgbMatch[1], 10);
2230
+ const g = parseInt(rgbMatch[2], 10);
2231
+ const b = parseInt(rgbMatch[3], 10);
2232
+ const brightness = (r * 299 + g * 587 + b * 114) / 1000;
2233
+ return brightness < 140 ? 'text-white' : 'text-gray-900';
2234
+ }
2235
+ return null;
2236
+ }
2197
2237
  /**
2198
2238
  * Extract spacer height from block attributes or innerHTML
2199
2239
  * Returns height in pixels, or null if not found
@@ -2335,6 +2375,9 @@ const Paragraph = ({ block, context }) => {
2335
2375
  const attrs = block.attributes || {};
2336
2376
  const textAlign = getTextAlignClasses(attrs['align']);
2337
2377
  const spacing = getSpacing(context.spacingConfig || context.registry.spacingConfig, 'paragraph', 'my-6');
2378
+ // Extract text color if specified
2379
+ const textColor = extractTextColor(block, context);
2380
+ const textColorClass = textColor || '';
2338
2381
  // Check if innerHTML contains HTML elements (like links, strong, em, etc.)
2339
2382
  const hasHTML = block.innerHTML && /<[a-z][\s\S]*>/i.test(block.innerHTML);
2340
2383
  // Check if content contains shortcodes (check both HTML and text content)
@@ -2370,17 +2413,17 @@ const Paragraph = ({ block, context }) => {
2370
2413
  const hasBlockLevelContent = React.Children.toArray(parts).some((part) => isBlockLevelElement(part));
2371
2414
  if (hasBlockLevelContent) {
2372
2415
  // Render block-level content without <p> wrapper, but add spacing wrapper
2373
- return jsxRuntimeExports.jsx("div", { className: spacing, children: parts });
2416
+ return jsxRuntimeExports.jsx("div", { className: buildClassName(spacing, textColorClass), children: parts });
2374
2417
  }
2375
2418
  // Render shortcode parts inside paragraph (shortcodes are processed as React components)
2376
- return jsxRuntimeExports.jsx("p", { className: buildClassName(spacing, textAlign), children: parts });
2419
+ return jsxRuntimeExports.jsx("p", { className: buildClassName(spacing, textAlign, textColorClass), children: parts });
2377
2420
  }
2378
2421
  // If innerHTML contains HTML elements but no shortcodes, render it directly (preserves links, formatting, etc.)
2379
2422
  if (hasHTML && block.innerHTML) {
2380
- return jsxRuntimeExports.jsx("p", { className: buildClassName(spacing, textAlign), dangerouslySetInnerHTML: { __html: htmlContent } });
2423
+ return jsxRuntimeExports.jsx("p", { className: buildClassName(spacing, textAlign, textColorClass), dangerouslySetInnerHTML: { __html: htmlContent } });
2381
2424
  }
2382
2425
  // No HTML and no shortcodes, just render plain text content
2383
- return jsxRuntimeExports.jsx("p", { className: buildClassName(spacing, textAlign), children: textContent });
2426
+ return jsxRuntimeExports.jsx("p", { className: buildClassName(spacing, textAlign, textColorClass), children: textContent });
2384
2427
  };
2385
2428
  const Heading = ({ block, children, context }) => {
2386
2429
  const attrs = block.attributes || {};
@@ -2489,6 +2532,8 @@ const Group = ({ block, children, context }) => {
2489
2532
  const layout = attrs['layout'];
2490
2533
  // Extract background color using color mapper
2491
2534
  const backgroundColor = extractBackgroundColor(block, context);
2535
+ // Extract text color (apply on the wrapper so children inherit)
2536
+ const textColor = extractTextColor(block, context) || inferTextColorFromBackground(backgroundColor);
2492
2537
  // Determine if this is a section-level group (has alignment) or content-level
2493
2538
  const isSection = align === 'full' || align === 'wide';
2494
2539
  const containerClass = getContainerClasses(align, layout);
@@ -2502,8 +2547,8 @@ const Group = ({ block, children, context }) => {
2502
2547
  ? 'container'
2503
2548
  : containerClass;
2504
2549
  // Build className with background color if present
2505
- const className = buildClassName(finalContainerClass, spacingClass, backgroundColor // This will be null if no mapping, which is fine
2506
- );
2550
+ const className = buildClassName(finalContainerClass, spacingClass, backgroundColor, // This will be null if no mapping, which is fine
2551
+ textColor);
2507
2552
  return (jsxRuntimeExports.jsx("div", { className: className, children: children }));
2508
2553
  };
2509
2554
  const Columns = ({ block, children }) => {
@@ -2517,9 +2562,10 @@ const Column = ({ block, children, context }) => {
2517
2562
  const width = attrs['width'];
2518
2563
  // Extract background color using color mapper
2519
2564
  const backgroundColor = extractBackgroundColor(block, context);
2565
+ const textColor = extractTextColor(block, context) || inferTextColorFromBackground(backgroundColor);
2520
2566
  // Handle column width (e.g., "50%" becomes flex-basis)
2521
2567
  const style = width ? { flexBasis: width } : undefined;
2522
- return (jsxRuntimeExports.jsx("div", { className: buildClassName('space-y-4 p-6 rounded-lg', backgroundColor), style: style, children: children }));
2568
+ return (jsxRuntimeExports.jsx("div", { className: buildClassName('space-y-4 p-6 rounded-lg', backgroundColor, textColor), style: style, children: children }));
2523
2569
  };
2524
2570
  const Separator = () => jsxRuntimeExports.jsx("hr", { className: "border-gray-200 my-8" });
2525
2571
  const ButtonBlock = ({ block, context }) => {
@@ -3079,6 +3125,7 @@ exports.getImageAttributes = getImageAttributes;
3079
3125
  exports.getImageUrl = getImageUrl;
3080
3126
  exports.getSectionSpacingClasses = getSectionSpacingClasses;
3081
3127
  exports.getTextAlignClasses = getTextAlignClasses;
3128
+ exports.inferTextColorFromBackground = inferTextColorFromBackground;
3082
3129
  exports.isCloudflareImageUrl = isCloudflareImageUrl;
3083
3130
  exports.isValidCloudflareUrl = isValidCloudflareUrl;
3084
3131
  exports.matchesPattern = matchesPattern;