@marvalt/wparser 0.1.24 → 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', 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', 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,9 +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
- return (jsxRuntimeExports.jsx(Tag, { className: buildClassName('font-bold text-gray-900', sizeClass, textAlign), children: children ?? content }));
2218
+ // Get spacing from config with improved defaults
2219
+ const spacingClass = getHeadingSpacing(context.spacingConfig || context.registry.spacingConfig, level);
2220
+ return (jsxRuntimeExports.jsx(Tag, { className: buildClassName('font-bold text-gray-900', sizeClass, textAlign, spacingClass), children: children ?? content }));
2195
2221
  };
2196
- const Image = ({ block }) => {
2222
+ const Image = ({ block, context }) => {
2197
2223
  const imageAttrs = getImageAttributes(block);
2198
2224
  if (!imageAttrs.url)
2199
2225
  return null;
@@ -2204,13 +2230,15 @@ const Image = ({ block }) => {
2204
2230
  const height = imageAttrs.height;
2205
2231
  imageUrl = getCloudflareVariantUrl(imageUrl, { width, height });
2206
2232
  }
2207
- return (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: imageAttrs.alt, width: imageAttrs.width, height: imageAttrs.height, className: "w-full h-auto rounded-lg object-cover", 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" }));
2208
2235
  };
2209
- const List = ({ block, children }) => {
2236
+ const List = ({ block, children, context }) => {
2210
2237
  const attrs = block.attributes || {};
2211
2238
  const { ordered } = attrs;
2212
2239
  const Tag = ordered ? 'ol' : 'ul';
2213
- return React.createElement(Tag, { className: 'list-disc pl-6 space-y-2 text-gray-700' }, 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);
2214
2242
  };
2215
2243
  const ListItem = ({ children }) => {
2216
2244
  return jsxRuntimeExports.jsx("li", { className: "text-gray-700", children: children });
@@ -2225,7 +2253,11 @@ const Group = ({ block, children, context }) => {
2225
2253
  // Determine if this is a section-level group (has alignment) or content-level
2226
2254
  const isSection = align === 'full' || align === 'wide';
2227
2255
  const containerClass = getContainerClasses(align, layout);
2228
- 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());
2229
2261
  // Ensure container class is always applied for constrained groups
2230
2262
  const finalContainerClass = layout?.type === 'constrained' && align === 'wide'
2231
2263
  ? 'container'
@@ -2389,7 +2421,7 @@ const Fallback = ({ block, children }) => {
2389
2421
  // Minimal fallback; do not render innerHTML directly in v1 for safety
2390
2422
  return jsxRuntimeExports.jsx("div", { "data-unknown-block": block.name, children: children });
2391
2423
  };
2392
- function createDefaultRegistry(colorMapper) {
2424
+ function createDefaultRegistry(colorMapper, spacingConfig) {
2393
2425
  const renderers = {
2394
2426
  'core/paragraph': Paragraph,
2395
2427
  'core/heading': Heading,
@@ -2432,6 +2464,7 @@ function createDefaultRegistry(colorMapper) {
2432
2464
  shortcodes: {}, // Empty by default - apps extend this
2433
2465
  fallback: Fallback,
2434
2466
  colorMapper,
2467
+ spacingConfig,
2435
2468
  };
2436
2469
  }
2437
2470
  // Legacy function for backward compatibility - use getBlockTextContent instead
@@ -2521,8 +2554,8 @@ function findMatchingMapping(block, mappings) {
2521
2554
  * const registry = createEnhancedRegistry(mappings);
2522
2555
  * ```
2523
2556
  */
2524
- function createEnhancedRegistry(mappings = [], baseRegistry, colorMapper) {
2525
- const base = baseRegistry || createDefaultRegistry(colorMapper);
2557
+ function createEnhancedRegistry(mappings = [], baseRegistry, colorMapper, spacingConfig) {
2558
+ const base = baseRegistry || createDefaultRegistry(colorMapper, spacingConfig);
2526
2559
  // Create enhanced renderers that check patterns first
2527
2560
  const enhancedRenderers = {
2528
2561
  ...base.renderers,
@@ -2570,6 +2603,8 @@ function createEnhancedRegistry(mappings = [], baseRegistry, colorMapper) {
2570
2603
  matchBlock,
2571
2604
  // Use provided colorMapper or inherit from base registry
2572
2605
  colorMapper: colorMapper || base.colorMapper,
2606
+ // Use provided spacingConfig or inherit from base registry
2607
+ spacingConfig: spacingConfig || base.spacingConfig,
2573
2608
  };
2574
2609
  }
2575
2610