@marvalt/wparser 0.1.25 → 0.1.27

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.d.ts CHANGED
@@ -50,6 +50,7 @@ interface RenderContext {
50
50
  registry: ComponentRegistry;
51
51
  page?: WordPressPageMinimal;
52
52
  colorMapper?: ColorMapper;
53
+ spacingConfig?: SpacingConfig;
53
54
  }
54
55
  interface BlockRendererProps {
55
56
  block: WordPressBlock;
@@ -70,6 +71,8 @@ interface ComponentRegistry {
70
71
  fallback: BlockRenderer;
71
72
  /** Optional color mapper for converting WordPress theme colors to CSS classes */
72
73
  colorMapper?: ColorMapper;
74
+ /** Optional spacing configuration for customizing element spacing */
75
+ spacingConfig?: SpacingConfig;
73
76
  }
74
77
  /**
75
78
  * Pattern matching for blocks - allows matching blocks by name and attributes
@@ -111,6 +114,31 @@ interface EnhancedRegistry extends ComponentRegistry {
111
114
  /** Find matching component mapping for a block */
112
115
  matchBlock: (block: WordPressBlock) => ComponentMapping | null;
113
116
  }
117
+ /**
118
+ * Spacing configuration for customizing element and section spacing
119
+ * Allows applications to control spacing values while maintaining consistency
120
+ */
121
+ interface SpacingConfig {
122
+ /** Spacing for paragraph elements (e.g., 'my-4', 'my-6') */
123
+ paragraph?: string;
124
+ /** Spacing for heading elements by level */
125
+ heading?: {
126
+ /** H1 spacing (e.g., 'mt-8 mb-6') */
127
+ h1?: string;
128
+ /** H2 spacing (e.g., 'mt-6 mb-4') */
129
+ h2?: string;
130
+ /** H3 and below spacing (e.g., 'mt-4 mb-3') */
131
+ h3?: string;
132
+ };
133
+ /** Spacing for image elements (e.g., 'my-4', 'my-6') */
134
+ image?: string;
135
+ /** Spacing for list elements (e.g., 'my-4', 'my-6') */
136
+ list?: string;
137
+ /** Section-level padding (for groups with align: 'full' or 'wide') */
138
+ section?: string;
139
+ /** Content-level spacing (for groups without alignment) */
140
+ content?: string;
141
+ }
114
142
 
115
143
  type WPNode = WordPressBlock;
116
144
  interface ParseOptions {
@@ -122,7 +150,7 @@ interface RenderOptions {
122
150
  }
123
151
  declare function renderNodes(blocks: WordPressBlock[], registry: ComponentRegistry, options?: RenderOptions, page?: WordPressPageMinimal): React$1.ReactNode;
124
152
 
125
- declare function createDefaultRegistry(colorMapper?: ColorMapper): ComponentRegistry;
153
+ declare function createDefaultRegistry(colorMapper?: ColorMapper, spacingConfig?: SpacingConfig): ComponentRegistry;
126
154
 
127
155
  /**
128
156
  * Create an enhanced registry that supports pattern-based component mapping
@@ -152,7 +180,7 @@ declare function createDefaultRegistry(colorMapper?: ColorMapper): ComponentRegi
152
180
  * const registry = createEnhancedRegistry(mappings);
153
181
  * ```
154
182
  */
155
- declare function createEnhancedRegistry(mappings?: ComponentMapping[], baseRegistry?: ComponentRegistry, colorMapper?: ColorMapper): EnhancedRegistry;
183
+ declare function createEnhancedRegistry(mappings?: ComponentMapping[], baseRegistry?: ComponentRegistry, colorMapper?: ColorMapper, spacingConfig?: SpacingConfig): EnhancedRegistry;
156
184
 
157
185
  interface WPContentProps {
158
186
  blocks: WordPressBlock[];
@@ -508,4 +536,4 @@ interface SectionWrapperProps {
508
536
  declare const SectionWrapper: React$1.FC<SectionWrapperProps>;
509
537
 
510
538
  export { SectionWrapper, WPContent, WPErrorBoundary, WPPage, buildClassName, convertImageToCloudflareVariant, convertImageUrl, convertImageUrls, createDefaultRegistry, createEnhancedRegistry, extractAlignment, extractBackgroundColor, extractBackgroundImage, extractButtonsFromInnerBlocks, extractContent, extractDimRatio, extractFontSize, extractHeadingLevel, extractImageAttributes, extractImageUrl, extractImageUrlWithFallback, extractMediaPosition, extractMinHeight, extractOverlayColor, extractSubtitleFromInnerBlocks, extractTextAlign, extractTextAlignFromInnerBlocks, extractTextFromHTML, extractTitle, extractTitleFromInnerBlocks, extractVerticalAlignment, extractVideoIframeFromInnerBlocks, findMatchingMapping, findShortcodes, getAlignmentClasses, getBlockTextContent, getCloudflareVariantUrl, getContainerClasses, getContentSpacingClasses, getFontSizeClasses, getImageAttributes, getImageUrl, getSectionSpacingClasses, getTextAlignClasses, isCloudflareImageUrl, isValidCloudflareUrl, matchesPattern, parseContentPosition, parseGutenbergBlocks, parseShortcodeAttrs, renderNodes, renderTextWithShortcodes };
511
- export type { AuthMode, BlockPattern, BlockRenderer, BlockRendererProps, CloudflareVariantOptions, ColorMapper, ComponentMapping, ComponentRegistry, EnhancedRegistry, ImageConversionOptions, ParseOptions, ParsedShortcode, RenderContext, RenderOptions, SectionWrapperProps, ShortcodeAttributes, ShortcodeRenderer, WPContentProps, WPNode, WPPageProps, WordPressBlock, WordPressEmbedded, WordPressFeaturedMedia, WordPressPageMinimal, WordPressTitleField };
539
+ export type { AuthMode, BlockPattern, BlockRenderer, BlockRendererProps, CloudflareVariantOptions, ColorMapper, ComponentMapping, ComponentRegistry, EnhancedRegistry, ImageConversionOptions, ParseOptions, ParsedShortcode, RenderContext, RenderOptions, SectionWrapperProps, ShortcodeAttributes, ShortcodeRenderer, SpacingConfig, WPContentProps, WPNode, WPPageProps, WordPressBlock, WordPressEmbedded, WordPressFeaturedMedia, WordPressPageMinimal, WordPressTitleField };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,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,GACvB,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,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,GACvB,MAAM,yBAAyB,CAAC;AACjC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC"}
package/dist/index.esm.js CHANGED
@@ -1388,7 +1388,16 @@ function renderBlock(block, registry, key, options, page) {
1388
1388
  const children = block.innerBlocks && block.innerBlocks.length
1389
1389
  ? block.innerBlocks.map((child, i) => renderBlock(child, registry, `${key}-${i}`, options, page))
1390
1390
  : undefined;
1391
- const node = Renderer({ block, children, context: { registry, page, colorMapper: registry.colorMapper } });
1391
+ const node = Renderer({
1392
+ block,
1393
+ children,
1394
+ context: {
1395
+ registry,
1396
+ page,
1397
+ colorMapper: registry.colorMapper,
1398
+ spacingConfig: registry.spacingConfig,
1399
+ }
1400
+ });
1392
1401
  if (options?.debugWrappers) {
1393
1402
  return (jsxRuntimeExports.jsx("div", { "data-block": block.name, className: "wp-block", children: node }, key));
1394
1403
  }
@@ -2141,10 +2150,25 @@ function buildClassName(...classes) {
2141
2150
  .trim();
2142
2151
  }
2143
2152
 
2153
+ // Helper function to get spacing value with fallback
2154
+ // Only accepts string keys (excludes 'heading' which is an object)
2155
+ function getSpacing(spacingConfig, key, fallback) {
2156
+ return spacingConfig?.[key] || fallback;
2157
+ }
2158
+ // Helper function to get heading spacing
2159
+ function getHeadingSpacing(spacingConfig, level) {
2160
+ const headingConfig = spacingConfig?.heading;
2161
+ if (level === 1)
2162
+ return headingConfig?.h1 || 'mt-10 mb-8';
2163
+ if (level === 2)
2164
+ return headingConfig?.h2 || 'mt-8 mb-6';
2165
+ return headingConfig?.h3 || 'mt-6 mb-4';
2166
+ }
2144
2167
  const Paragraph = ({ block, context }) => {
2145
2168
  const content = getBlockTextContent(block);
2146
2169
  const attrs = block.attributes || {};
2147
2170
  const textAlign = getTextAlignClasses(attrs['align']);
2171
+ const spacing = getSpacing(context.spacingConfig || context.registry.spacingConfig, 'paragraph', 'my-6');
2148
2172
  // Check if content contains shortcodes
2149
2173
  const hasShortcodes = /\[(\w+)/.test(content);
2150
2174
  if (hasShortcodes && context.registry.shortcodes) {
@@ -2175,14 +2199,14 @@ const Paragraph = ({ block, context }) => {
2175
2199
  };
2176
2200
  const hasBlockLevelContent = React.Children.toArray(parts).some((part) => isBlockLevelElement(part));
2177
2201
  if (hasBlockLevelContent) {
2178
- // Render block-level content without <p> wrapper
2179
- return jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: parts });
2202
+ // Render block-level content without <p> wrapper, but add spacing wrapper
2203
+ return jsxRuntimeExports.jsx("div", { className: spacing, children: parts });
2180
2204
  }
2181
- return jsxRuntimeExports.jsx("p", { className: buildClassName('text-gray-700 my-4', textAlign), children: parts });
2205
+ return jsxRuntimeExports.jsx("p", { className: buildClassName('text-gray-700', spacing, textAlign), children: parts });
2182
2206
  }
2183
- return jsxRuntimeExports.jsx("p", { className: buildClassName('text-gray-700 my-4', textAlign), children: content });
2207
+ return jsxRuntimeExports.jsx("p", { className: buildClassName('text-gray-700', spacing, textAlign), children: content });
2184
2208
  };
2185
- const Heading = ({ block, children }) => {
2209
+ const Heading = ({ block, children, context }) => {
2186
2210
  const attrs = block.attributes || {};
2187
2211
  const { level = 2 } = attrs;
2188
2212
  const content = getBlockTextContent(block);
@@ -2191,12 +2215,11 @@ const Heading = ({ block, children }) => {
2191
2215
  const Tag = `h${Math.min(Math.max(Number(level) || 2, 1), 6)}`;
2192
2216
  // Default heading sizes if fontSize not specified
2193
2217
  const sizeClass = fontSize || (level === 1 ? 'text-4xl' : level === 2 ? 'text-3xl' : level === 3 ? 'text-2xl' : 'text-xl');
2194
- // Add spacing: mt for top (except first heading), mb for bottom
2195
- // Use larger bottom margin for headings to create visual separation
2196
- const spacingClass = level === 1 ? 'mt-8 mb-6' : level === 2 ? 'mt-6 mb-4' : 'mt-4 mb-3';
2218
+ // Get spacing from config with improved defaults
2219
+ const spacingClass = getHeadingSpacing(context.spacingConfig || context.registry.spacingConfig, level);
2197
2220
  return (jsxRuntimeExports.jsx(Tag, { className: buildClassName('font-bold text-gray-900', sizeClass, textAlign, spacingClass), children: children ?? content }));
2198
2221
  };
2199
- const Image = ({ block }) => {
2222
+ const Image = ({ block, context }) => {
2200
2223
  const imageAttrs = getImageAttributes(block);
2201
2224
  if (!imageAttrs.url)
2202
2225
  return null;
@@ -2207,13 +2230,15 @@ const Image = ({ block }) => {
2207
2230
  const height = imageAttrs.height;
2208
2231
  imageUrl = getCloudflareVariantUrl(imageUrl, { width, height });
2209
2232
  }
2210
- return (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: imageAttrs.alt, width: imageAttrs.width, height: imageAttrs.height, className: "w-full h-auto rounded-lg object-cover my-4", style: { maxWidth: '100%', height: 'auto' }, loading: "lazy" }));
2233
+ const spacing = getSpacing(context.spacingConfig || context.registry.spacingConfig, 'image', 'my-6');
2234
+ 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" }));
2211
2235
  };
2212
- const List = ({ block, children }) => {
2236
+ const List = ({ block, children, context }) => {
2213
2237
  const attrs = block.attributes || {};
2214
2238
  const { ordered } = attrs;
2215
2239
  const Tag = ordered ? 'ol' : 'ul';
2216
- return React.createElement(Tag, { className: 'list-disc pl-6 space-y-2 text-gray-700 my-4' }, children);
2240
+ const spacing = getSpacing(context.spacingConfig || context.registry.spacingConfig, 'list', 'my-6');
2241
+ return React.createElement(Tag, { className: buildClassName('list-disc pl-6 space-y-2 text-gray-700', spacing) }, children);
2217
2242
  };
2218
2243
  const ListItem = ({ children }) => {
2219
2244
  return jsxRuntimeExports.jsx("li", { className: "text-gray-700", children: children });
@@ -2228,7 +2253,11 @@ const Group = ({ block, children, context }) => {
2228
2253
  // Determine if this is a section-level group (has alignment) or content-level
2229
2254
  const isSection = align === 'full' || align === 'wide';
2230
2255
  const containerClass = getContainerClasses(align, layout);
2231
- const spacingClass = isSection ? getSectionSpacingClasses() : getContentSpacingClasses();
2256
+ // Get spacing from config or use defaults
2257
+ const spacingConfig = context.spacingConfig || context.registry.spacingConfig;
2258
+ const spacingClass = isSection
2259
+ ? (spacingConfig?.section || getSectionSpacingClasses())
2260
+ : (spacingConfig?.content || getContentSpacingClasses());
2232
2261
  // Ensure container class is always applied for constrained groups
2233
2262
  const finalContainerClass = layout?.type === 'constrained' && align === 'wide'
2234
2263
  ? 'container'
@@ -2392,7 +2421,7 @@ const Fallback = ({ block, children }) => {
2392
2421
  // Minimal fallback; do not render innerHTML directly in v1 for safety
2393
2422
  return jsxRuntimeExports.jsx("div", { "data-unknown-block": block.name, children: children });
2394
2423
  };
2395
- function createDefaultRegistry(colorMapper) {
2424
+ function createDefaultRegistry(colorMapper, spacingConfig) {
2396
2425
  const renderers = {
2397
2426
  'core/paragraph': Paragraph,
2398
2427
  'core/heading': Heading,
@@ -2435,6 +2464,7 @@ function createDefaultRegistry(colorMapper) {
2435
2464
  shortcodes: {}, // Empty by default - apps extend this
2436
2465
  fallback: Fallback,
2437
2466
  colorMapper,
2467
+ spacingConfig,
2438
2468
  };
2439
2469
  }
2440
2470
  // Legacy function for backward compatibility - use getBlockTextContent instead
@@ -2524,8 +2554,8 @@ function findMatchingMapping(block, mappings) {
2524
2554
  * const registry = createEnhancedRegistry(mappings);
2525
2555
  * ```
2526
2556
  */
2527
- function createEnhancedRegistry(mappings = [], baseRegistry, colorMapper) {
2528
- const base = baseRegistry || createDefaultRegistry(colorMapper);
2557
+ function createEnhancedRegistry(mappings = [], baseRegistry, colorMapper, spacingConfig) {
2558
+ const base = baseRegistry || createDefaultRegistry(colorMapper, spacingConfig);
2529
2559
  // Create enhanced renderers that check patterns first
2530
2560
  const enhancedRenderers = {
2531
2561
  ...base.renderers,
@@ -2573,6 +2603,8 @@ function createEnhancedRegistry(mappings = [], baseRegistry, colorMapper) {
2573
2603
  matchBlock,
2574
2604
  // Use provided colorMapper or inherit from base registry
2575
2605
  colorMapper: colorMapper || base.colorMapper,
2606
+ // Use provided spacingConfig or inherit from base registry
2607
+ spacingConfig: spacingConfig || base.spacingConfig,
2576
2608
  };
2577
2609
  }
2578
2610