@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/types.d.ts CHANGED
@@ -48,6 +48,7 @@ export interface RenderContext {
48
48
  registry: ComponentRegistry;
49
49
  page?: WordPressPageMinimal;
50
50
  colorMapper?: ColorMapper;
51
+ spacingConfig?: SpacingConfig;
51
52
  }
52
53
  export interface BlockRendererProps {
53
54
  block: WordPressBlock;
@@ -68,6 +69,8 @@ export interface ComponentRegistry {
68
69
  fallback: BlockRenderer;
69
70
  /** Optional color mapper for converting WordPress theme colors to CSS classes */
70
71
  colorMapper?: ColorMapper;
72
+ /** Optional spacing configuration for customizing element spacing */
73
+ spacingConfig?: SpacingConfig;
71
74
  }
72
75
  /**
73
76
  * Pattern matching for blocks - allows matching blocks by name and attributes
@@ -109,4 +112,29 @@ export interface EnhancedRegistry extends ComponentRegistry {
109
112
  /** Find matching component mapping for a block */
110
113
  matchBlock: (block: WordPressBlock) => ComponentMapping | null;
111
114
  }
115
+ /**
116
+ * Spacing configuration for customizing element and section spacing
117
+ * Allows applications to control spacing values while maintaining consistency
118
+ */
119
+ export interface SpacingConfig {
120
+ /** Spacing for paragraph elements (e.g., 'my-4', 'my-6') */
121
+ paragraph?: string;
122
+ /** Spacing for heading elements by level */
123
+ heading?: {
124
+ /** H1 spacing (e.g., 'mt-8 mb-6') */
125
+ h1?: string;
126
+ /** H2 spacing (e.g., 'mt-6 mb-4') */
127
+ h2?: string;
128
+ /** H3 and below spacing (e.g., 'mt-4 mb-3') */
129
+ h3?: string;
130
+ };
131
+ /** Spacing for image elements (e.g., 'my-4', 'my-6') */
132
+ image?: string;
133
+ /** Spacing for list elements (e.g., 'my-4', 'my-6') */
134
+ list?: string;
135
+ /** Section-level padding (for groups with align: 'full' or 'wide') */
136
+ section?: string;
137
+ /** Content-level spacing (for groups without alignment) */
138
+ content?: string;
139
+ }
112
140
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,82 @@
1
+ # Color Mapping System
2
+
3
+ ## Overview
4
+
5
+ The color mapping system allows WordPress theme colors to be converted to application-specific CSS classes. This maintains the separation where WordPress controls **which** color is used, while the app controls **what** it means.
6
+
7
+ ## Implementation
8
+
9
+ ### 1. Define Color Mapper
10
+
11
+ ```typescript
12
+ import { type ColorMapper } from '@marvalt/wparser';
13
+
14
+ const colorMapper: ColorMapper = (wpColorName) => {
15
+ const colorMap: Record<string, string> = {
16
+ 'accent-5': 'bg-gray-100', // Light gray background
17
+ 'base': 'bg-white', // White background
18
+ 'contrast': 'bg-gray-900 text-white', // Dark background with white text
19
+ 'transparent': 'bg-transparent', // Transparent
20
+ // Add more mappings as needed
21
+ };
22
+
23
+ return wpColorName ? colorMap[wpColorName] || null : null;
24
+ };
25
+ ```
26
+
27
+ ### 2. Pass to Registry
28
+
29
+ ```typescript
30
+ import { createEnhancedRegistry } from '@marvalt/wparser';
31
+
32
+ const registry = createEnhancedRegistry(mappings, undefined, colorMapper);
33
+ ```
34
+
35
+ ### 3. How It Works
36
+
37
+ When a block has `backgroundColor: "accent-5"`:
38
+ 1. `extractBackgroundColor()` extracts `"accent-5"` from block attributes
39
+ 2. Your `colorMapper` function is called with `"accent-5"`
40
+ 3. Returns `"bg-gray-100"` (or your app's equivalent)
41
+ 4. Class is applied to the rendered element
42
+
43
+ ## WordPress Theme Colors
44
+
45
+ Common WordPress theme color names:
46
+ - `base` - Base/background color
47
+ - `contrast` - Contrast/foreground color
48
+ - `accent-1` through `accent-5` - Theme accent colors
49
+ - `transparent` - Transparent background
50
+
51
+ Check your WordPress theme's color palette for exact names.
52
+
53
+ ## Best Practices
54
+
55
+ 1. **Map All Used Colors**: Ensure all WordPress colors have mappings
56
+ 2. **Use Design Tokens**: Map to your app's design system tokens
57
+ 3. **Handle Missing Colors**: Return `null` for unmapped colors (no background applied)
58
+ 4. **Consider Text Colors**: Include text color classes when needed (e.g., `bg-gray-900 text-white`)
59
+
60
+ ## Example: Full Implementation
61
+
62
+ ```typescript
63
+ // In your app's registry file
64
+ import { createEnhancedRegistry, type ColorMapper } from '@marvalt/wparser';
65
+
66
+ export function createAppRegistry() {
67
+ const colorMapper: ColorMapper = (wpColorName) => {
68
+ const colorMap: Record<string, string> = {
69
+ 'accent-5': 'bg-gray-100',
70
+ 'base': 'bg-white',
71
+ 'contrast': 'bg-gray-900 text-white',
72
+ 'transparent': 'bg-transparent',
73
+ };
74
+ return wpColorName ? colorMap[wpColorName] || null : null;
75
+ };
76
+
77
+ const registry = createEnhancedRegistry(mappings, undefined, colorMapper);
78
+ // ... rest of registry setup
79
+ return registry;
80
+ }
81
+ ```
82
+
@@ -0,0 +1,144 @@
1
+ # Customization Guide
2
+
3
+ ## Overview
4
+
5
+ The `@marvalt/wparser` package is designed to be highly customizable while maintaining a generic, reusable core. This guide covers how to customize block rendering, spacing, colors, and more.
6
+
7
+ ## Customizing Block Renderers
8
+
9
+ ### Override Default Renderers
10
+
11
+ ```typescript
12
+ import { createDefaultRegistry } from '@marvalt/wparser';
13
+
14
+ const registry = createDefaultRegistry();
15
+
16
+ // Override paragraph renderer
17
+ registry.renderers['core/paragraph'] = ({ block, context }) => {
18
+ const content = getBlockTextContent(block);
19
+ return <p className="my-6 text-lg text-gray-800">{content}</p>;
20
+ };
21
+
22
+ // Override heading renderer
23
+ registry.renderers['core/heading'] = ({ block, children }) => {
24
+ const level = block.attributes?.level || 2;
25
+ const Tag = `h${level}` as keyof JSX.IntrinsicElements;
26
+ return (
27
+ <Tag className="font-bold text-4xl mb-6">
28
+ {children}
29
+ </Tag>
30
+ );
31
+ };
32
+ ```
33
+
34
+ ### Using Enhanced Registry with Component Mappings
35
+
36
+ ```typescript
37
+ import { createEnhancedRegistry, type ComponentMapping } from '@marvalt/wparser';
38
+ import MyCustomHero from './components/MyCustomHero';
39
+
40
+ const mappings: ComponentMapping[] = [
41
+ {
42
+ pattern: { name: 'core/cover' },
43
+ component: MyCustomHero,
44
+ extractProps: (block, context) => ({
45
+ backgroundImage: extractBackgroundImage(block, context.page),
46
+ title: extractTitleFromInnerBlocks(block),
47
+ // ... other props
48
+ }),
49
+ },
50
+ ];
51
+
52
+ const registry = createEnhancedRegistry(mappings);
53
+ ```
54
+
55
+ ## Customizing Colors
56
+
57
+ See [COLOR_MAPPING.md](./COLOR_MAPPING.md) for detailed color mapping documentation.
58
+
59
+ ## Customizing Spacing
60
+
61
+ See [SPACING.md](./SPACING.md) for detailed spacing customization documentation.
62
+
63
+ ## Custom Shortcodes
64
+
65
+ ```typescript
66
+ registry.shortcodes = {
67
+ 'my_custom_shortcode': (attrs, content) => {
68
+ const id = attrs.id || '';
69
+ return <MyCustomComponent id={id}>{content}</MyCustomComponent>;
70
+ },
71
+ };
72
+ ```
73
+
74
+ ## Best Practices
75
+
76
+ 1. **Keep Package Generic**: Don't hardcode app-specific styles in package code
77
+ 2. **Use App Overrides**: Customize through registry overrides in your app
78
+ 3. **Leverage Extractors**: Use provided extractor functions for consistent data extraction
79
+ 4. **Type Safety**: Use TypeScript types for all customizations
80
+ 5. **Documentation**: Document your app-specific customizations
81
+
82
+ ## Example: Complete Custom Registry
83
+
84
+ ```typescript
85
+ import {
86
+ createEnhancedRegistry,
87
+ type ComponentMapping,
88
+ type ColorMapper,
89
+ type SpacingConfig,
90
+ extractBackgroundImage,
91
+ extractTitleFromInnerBlocks,
92
+ } from '@marvalt/wparser';
93
+ import MyHero from './components/MyHero';
94
+
95
+ export function createAppRegistry() {
96
+ // Color mapping
97
+ const colorMapper: ColorMapper = (wpColorName) => {
98
+ const colorMap: Record<string, string> = {
99
+ 'accent-5': 'bg-gray-100',
100
+ 'base': 'bg-white',
101
+ };
102
+ return wpColorName ? colorMap[wpColorName] || null : null;
103
+ };
104
+
105
+ // Spacing configuration
106
+ const spacingConfig: SpacingConfig = {
107
+ paragraph: 'my-6',
108
+ heading: {
109
+ h1: 'mt-10 mb-8',
110
+ h2: 'mt-8 mb-6',
111
+ h3: 'mt-6 mb-4',
112
+ },
113
+ };
114
+
115
+ // Component mappings
116
+ const mappings: ComponentMapping[] = [
117
+ {
118
+ pattern: { name: 'core/cover' },
119
+ component: MyHero,
120
+ extractProps: (block, context) => ({
121
+ backgroundImage: extractBackgroundImage(block, context.page),
122
+ title: extractTitleFromInnerBlocks(block),
123
+ }),
124
+ },
125
+ ];
126
+
127
+ // Create registry
128
+ const registry = createEnhancedRegistry(mappings, undefined, colorMapper);
129
+
130
+ // Override specific renderers
131
+ registry.renderers['core/paragraph'] = ({ block, context }) => {
132
+ const content = getBlockTextContent(block);
133
+ return <p className="my-6 text-gray-700">{content}</p>;
134
+ };
135
+
136
+ // Add custom shortcodes
137
+ registry.shortcodes = {
138
+ 'my_shortcode': (attrs) => <MyComponent {...attrs} />,
139
+ };
140
+
141
+ return registry;
142
+ }
143
+ ```
144
+
@@ -0,0 +1,136 @@
1
+ # Spacing System
2
+
3
+ ## Overview
4
+
5
+ The package applies consistent spacing to block elements to ensure proper visual hierarchy and readability. Spacing is configurable at the application level through the `spacingConfig` parameter.
6
+
7
+ ## Default Spacing
8
+
9
+ ### Section-Level Spacing
10
+ - **Groups with `align: "full"` or `"wide"`**: `py-16 md:py-24`
11
+ - These are treated as top-level sections
12
+ - Applied to the group container
13
+
14
+ ### Content-Level Spacing
15
+ - **Groups without alignment**: `space-y-6`
16
+ - These are treated as content containers
17
+ - Uses flexbox gap for child spacing
18
+
19
+ ### Element-Level Spacing (Default Values)
20
+
21
+ #### Headings
22
+ - **H1**: `mt-10 mb-8` (larger top margin, larger bottom for main headings)
23
+ - **H2**: `mt-8 mb-6` (medium top margin, medium bottom for section headings)
24
+ - **H3+**: `mt-6 mb-4` (smaller margins for subsections)
25
+
26
+ #### Paragraphs
27
+ - **All paragraphs**: `my-6` (equal top and bottom margin for better readability)
28
+
29
+ #### Images
30
+ - **All images**: `my-6` (equal top and bottom margin for better separation)
31
+
32
+ #### Lists
33
+ - **All lists**: `my-6` (equal top and bottom margin for better separation)
34
+ - **List items**: Internal spacing via `space-y-2` on parent
35
+
36
+ ### Shortcode Elements
37
+
38
+ Shortcode elements (like `[leadership_cards]`) that render block-level content automatically receive spacing when rendered within paragraphs. The paragraph renderer detects block-level shortcode output and wraps it in a div with the configured paragraph spacing (`my-6` by default).
39
+
40
+ ## Customizing Spacing
41
+
42
+ ### Using SpacingConfig
43
+
44
+ The package supports a `spacingConfig` object that allows apps to customize all spacing values:
45
+
46
+ ```typescript
47
+ import { createDefaultRegistry, type SpacingConfig } from '@marvalt/wparser';
48
+
49
+ const spacingConfig: SpacingConfig = {
50
+ // Element spacing
51
+ paragraph: 'my-8', // Custom paragraph spacing (larger)
52
+ heading: {
53
+ h1: 'mt-12 mb-10', // Custom H1 spacing (even larger)
54
+ h2: 'mt-10 mb-8', // Custom H2 spacing
55
+ h3: 'mt-8 mb-6', // Custom H3+ spacing
56
+ },
57
+ image: 'my-8', // Custom image spacing
58
+ list: 'my-8', // Custom list spacing
59
+
60
+ // Section spacing
61
+ section: 'py-20 md:py-32', // Custom section padding
62
+ content: 'space-y-8', // Custom content spacing
63
+ };
64
+
65
+ // Pass colorMapper (optional) and spacingConfig
66
+ const registry = createDefaultRegistry(undefined, spacingConfig);
67
+ ```
68
+
69
+ Or with `createEnhancedRegistry`:
70
+
71
+ ```typescript
72
+ import { createEnhancedRegistry, type SpacingConfig } from '@marvalt/wparser';
73
+
74
+ const spacingConfig: SpacingConfig = {
75
+ paragraph: 'my-8',
76
+ heading: {
77
+ h1: 'mt-12 mb-10',
78
+ h2: 'mt-10 mb-8',
79
+ h3: 'mt-8 mb-6',
80
+ },
81
+ };
82
+
83
+ // Pass mappings, baseRegistry (optional), colorMapper (optional), spacingConfig
84
+ const registry = createEnhancedRegistry(mappings, undefined, colorMapper, spacingConfig);
85
+ ```
86
+
87
+ ### Override Default Spacing
88
+
89
+ ```typescript
90
+ // In your app's registry override
91
+ registry.renderers['core/paragraph'] = ({ block, context }) => {
92
+ const content = getBlockTextContent(block);
93
+ // Use your own spacing classes
94
+ return <p className="my-6 text-gray-700">{content}</p>;
95
+ };
96
+ ```
97
+
98
+ ### Adjust Group Spacing
99
+
100
+ ```typescript
101
+ registry.renderers['core/group'] = ({ block, children, context }) => {
102
+ // Extract background color
103
+ const backgroundColor = extractBackgroundColor(block, context);
104
+
105
+ // Use custom spacing
106
+ const spacingClass = 'py-20 md:py-32'; // Larger spacing
107
+
108
+ return (
109
+ <div className={buildClassName('container', spacingClass, backgroundColor)}>
110
+ {children}
111
+ </div>
112
+ );
113
+ };
114
+ ```
115
+
116
+ ## Spacing Philosophy
117
+
118
+ 1. **Vertical Rhythm**: Consistent spacing creates visual flow
119
+ 2. **Responsive**: Spacing scales on larger screens (`md:` breakpoint)
120
+ 3. **Hierarchical**: Headings have more spacing than paragraphs
121
+ 4. **Contextual**: Section-level vs content-level spacing differs
122
+
123
+ ## WordPress Control
124
+
125
+ WordPress doesn't directly control spacing values. Instead:
126
+ - Content team uses group blocks with alignment to create sections
127
+ - Package applies appropriate spacing based on block structure
128
+ - Apps can customize spacing through `spacingConfig` or renderer overrides
129
+
130
+ ## Shortcode Elements
131
+
132
+ Shortcode elements (like `[leadership_cards]`) should be wrapped in containers with appropriate spacing. The package doesn't automatically add spacing to shortcode outputs, so apps should:
133
+
134
+ 1. Ensure shortcode components have their own spacing
135
+ 2. Or wrap shortcodes in group blocks in WordPress for automatic spacing
136
+
@@ -0,0 +1,96 @@
1
+ # Styling Control: WordPress vs Application
2
+
3
+ ## Overview
4
+
5
+ The `@marvalt/wparser` package implements a **separation of concerns** model where:
6
+ - **WordPress** controls **what** styling is applied (which colors, alignments, layouts)
7
+ - **Application** controls **how** it's implemented (actual CSS classes, design tokens)
8
+
9
+ This allows content teams to control styling from WordPress while developers maintain design system consistency.
10
+
11
+ ## Key Principles
12
+
13
+ 1. **WordPress = Content + Styling Intent**
14
+ - Content teams set background colors, alignments, spacing preferences
15
+ - WordPress stores theme color names (e.g., `"accent-5"`, `"base"`)
16
+
17
+ 2. **Application = Design System Implementation**
18
+ - Developers map WordPress colors to app-specific CSS classes
19
+ - Apps use their own design tokens (e.g., `bg-gray-100`, `bg-primary`)
20
+
21
+ 3. **Package = Generic Bridge**
22
+ - Package provides extraction utilities and generic renderers
23
+ - Package never hardcodes app-specific styles
24
+
25
+ ## How It Works
26
+
27
+ ### Background Colors
28
+
29
+ **WordPress Side:**
30
+ - Content team sets `backgroundColor: "accent-5"` on a group block
31
+ - WordPress stores this as a theme color name
32
+
33
+ **Package Side:**
34
+ - `extractBackgroundColor()` extracts the color name from block attributes
35
+ - Passes it to the app's `colorMapper` function
36
+
37
+ **Application Side:**
38
+ - `colorMapper` converts `"accent-5"` → `"bg-gray-100"` (or your app's equivalent)
39
+ - CSS class is applied to the rendered element
40
+
41
+ ### Alignment & Layout
42
+
43
+ **WordPress Side:**
44
+ - Content team sets `align: "wide"` or `align: "full"` on blocks
45
+ - Sets `layout.type: "constrained"` for container control
46
+
47
+ **Package Side:**
48
+ - Extracts alignment and layout attributes
49
+ - Maps to generic container classes (`container`, `w-full`, `max-w-7xl`)
50
+
51
+ **Application Side:**
52
+ - Can override renderers to customize container behavior
53
+ - Maintains consistent spacing and width constraints
54
+
55
+ ### Spacing
56
+
57
+ **WordPress Side:**
58
+ - Content team uses group blocks with alignment to create sections
59
+ - WordPress doesn't directly control spacing (handled by block structure)
60
+
61
+ **Package Side:**
62
+ - Applies spacing based on block type and alignment:
63
+ - Section-level groups (`align: "full"` or `"wide"`): `py-16 md:py-24`
64
+ - Content-level groups: `space-y-6`
65
+ - Individual elements: Configurable via spacing utilities
66
+
67
+ **Application Side:**
68
+ - Can customize spacing through `spacingConfig` in registry creation
69
+ - Can override spacing by customizing renderers
70
+ - Can adjust spacing classes in `createDefaultRegistry()` or app overrides
71
+
72
+ ## Example: Complete Flow
73
+
74
+ 1. **WordPress**: Content team creates a group block with:
75
+ - `align: "wide"`
76
+ - `layout.type: "constrained"`
77
+ - `backgroundColor: "accent-5"`
78
+
79
+ 2. **Package**: `Group` renderer:
80
+ - Extracts `backgroundColor: "accent-5"`
81
+ - Calls `extractBackgroundColor(block, context)`
82
+ - Gets `"bg-gray-100"` from app's `colorMapper`
83
+ - Applies classes: `container py-16 md:py-24 bg-gray-100`
84
+
85
+ 3. **Application**: Renders with app's design system:
86
+ - Container width matches app's design tokens
87
+ - Background color matches app's color palette
88
+ - Spacing matches app's section spacing standards
89
+
90
+ ## Benefits
91
+
92
+ ✅ **Content Team Autonomy**: Can change colors and layouts without code changes
93
+ ✅ **Design System Consistency**: App maintains control over actual CSS classes
94
+ ✅ **Package Reusability**: Same package works for different apps with different styles
95
+ ✅ **Type Safety**: TypeScript ensures correct usage of color mappers and extractors
96
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marvalt/wparser",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
4
4
  "description": "Static-only WordPress page parser and renderer (Gutenberg blocks → React) for Digivalt apps",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "main": "dist/index.cjs",
@@ -16,7 +16,8 @@
16
16
  "files": [
17
17
  "dist",
18
18
  "README.md",
19
- "LICENSE"
19
+ "LICENSE",
20
+ "docs"
20
21
  ],
21
22
  "type": "module",
22
23
  "sideEffects": false,