@marvalt/wparser 0.1.6 → 0.1.7
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/components/SectionWrapper.d.ts +30 -0
- package/dist/components/SectionWrapper.d.ts.map +1 -0
- package/dist/index.cjs +400 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +208 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +380 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/registry/enhancedRegistry.d.ts +31 -0
- package/dist/registry/enhancedRegistry.d.ts.map +1 -0
- package/dist/types.d.ts +40 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/blockExtractors.d.ts +77 -0
- package/dist/utils/blockExtractors.d.ts.map +1 -0
- package/dist/utils/imageUrlConverter.d.ts +23 -0
- package/dist/utils/imageUrlConverter.d.ts.map +1 -0
- package/dist/utils/patternMatcher.d.ts +11 -0
- package/dist/utils/patternMatcher.d.ts.map +1 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -47,6 +47,46 @@ interface ComponentRegistry {
|
|
|
47
47
|
/** Fallback renderer for unknown blocks */
|
|
48
48
|
fallback: BlockRenderer;
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Pattern matching for blocks - allows matching blocks by name and attributes
|
|
52
|
+
*/
|
|
53
|
+
interface BlockPattern {
|
|
54
|
+
/** Block name (e.g., 'core/cover', 'core/media-text') */
|
|
55
|
+
name: string;
|
|
56
|
+
/** Optional attribute matching - all specified attributes must match */
|
|
57
|
+
attributes?: Record<string, any>;
|
|
58
|
+
/** Optional nested block patterns for innerBlocks */
|
|
59
|
+
innerBlocks?: BlockPattern[];
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Component mapping configuration for enhanced registry
|
|
63
|
+
* Maps block patterns to React components with prop extraction
|
|
64
|
+
*/
|
|
65
|
+
interface ComponentMapping<TProps = any> {
|
|
66
|
+
/** Pattern to match against blocks */
|
|
67
|
+
pattern: BlockPattern;
|
|
68
|
+
/** React component to render when pattern matches */
|
|
69
|
+
component: React.ComponentType<TProps>;
|
|
70
|
+
/** Function to extract props from block data */
|
|
71
|
+
extractProps: (block: WordPressBlock, context: RenderContext) => TProps;
|
|
72
|
+
/** Optional wrapper component (e.g., for section spacing) */
|
|
73
|
+
wrapper?: React.ComponentType<{
|
|
74
|
+
children: React.ReactNode;
|
|
75
|
+
block?: WordPressBlock;
|
|
76
|
+
}>;
|
|
77
|
+
/** Priority for matching (higher = more specific, checked first) */
|
|
78
|
+
priority?: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Enhanced registry that supports pattern-based component mapping
|
|
82
|
+
* Extends the base ComponentRegistry with pattern matching capabilities
|
|
83
|
+
*/
|
|
84
|
+
interface EnhancedRegistry extends ComponentRegistry {
|
|
85
|
+
/** Array of component mappings with patterns */
|
|
86
|
+
mappings: ComponentMapping[];
|
|
87
|
+
/** Find matching component mapping for a block */
|
|
88
|
+
matchBlock: (block: WordPressBlock) => ComponentMapping | null;
|
|
89
|
+
}
|
|
50
90
|
|
|
51
91
|
type WPNode = WordPressBlock;
|
|
52
92
|
interface ParseOptions {
|
|
@@ -60,6 +100,36 @@ declare function renderNodes(blocks: WordPressBlock[], registry: ComponentRegist
|
|
|
60
100
|
|
|
61
101
|
declare function createDefaultRegistry(): ComponentRegistry;
|
|
62
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Create an enhanced registry that supports pattern-based component mapping
|
|
105
|
+
*
|
|
106
|
+
* This combines the default registry (for fallback) with app-specific component mappings.
|
|
107
|
+
* When a block matches a pattern, it uses the mapped component. Otherwise, it falls back
|
|
108
|
+
* to the default renderer.
|
|
109
|
+
*
|
|
110
|
+
* @param mappings - Array of component mappings with patterns
|
|
111
|
+
* @param baseRegistry - Optional base registry (defaults to createDefaultRegistry())
|
|
112
|
+
* @returns Enhanced registry with pattern matching capabilities
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* const mappings: ComponentMapping[] = [
|
|
117
|
+
* {
|
|
118
|
+
* pattern: { name: 'core/cover' },
|
|
119
|
+
* component: HomeHeroSection,
|
|
120
|
+
* extractProps: (block) => ({
|
|
121
|
+
* backgroundImage: extractBackgroundImage(block),
|
|
122
|
+
* title: extractTitle(block),
|
|
123
|
+
* }),
|
|
124
|
+
* wrapper: SectionWrapper,
|
|
125
|
+
* },
|
|
126
|
+
* ];
|
|
127
|
+
*
|
|
128
|
+
* const registry = createEnhancedRegistry(mappings);
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
declare function createEnhancedRegistry(mappings?: ComponentMapping[], baseRegistry?: ComponentRegistry): EnhancedRegistry;
|
|
132
|
+
|
|
63
133
|
interface WPContentProps {
|
|
64
134
|
blocks: WordPressBlock[];
|
|
65
135
|
registry: ComponentRegistry;
|
|
@@ -202,5 +272,141 @@ declare const isCloudflareImageUrl: (url: string | undefined | null) => boolean;
|
|
|
202
272
|
*/
|
|
203
273
|
declare const getCloudflareVariantUrl: (url: string, options: CloudflareVariantOptions) => string;
|
|
204
274
|
|
|
205
|
-
|
|
206
|
-
|
|
275
|
+
/**
|
|
276
|
+
* Check if a block matches a pattern
|
|
277
|
+
*/
|
|
278
|
+
declare function matchesPattern(block: WordPressBlock, pattern: BlockPattern): boolean;
|
|
279
|
+
/**
|
|
280
|
+
* Find the best matching component mapping for a block
|
|
281
|
+
* Returns the mapping with highest priority that matches, or null
|
|
282
|
+
*/
|
|
283
|
+
declare function findMatchingMapping(block: WordPressBlock, mappings: ComponentMapping[]): ComponentMapping | null;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Extract background image URL from a block
|
|
287
|
+
* Checks various possible sources: url, backgroundImage, innerHTML
|
|
288
|
+
*/
|
|
289
|
+
declare function extractBackgroundImage(block: WordPressBlock): string | null;
|
|
290
|
+
/**
|
|
291
|
+
* Extract image URL from a block
|
|
292
|
+
* Returns Cloudflare URL if available, otherwise WordPress URL
|
|
293
|
+
*/
|
|
294
|
+
declare function extractImageUrl(block: WordPressBlock): string | null;
|
|
295
|
+
/**
|
|
296
|
+
* Extract image attributes (url, alt, width, height)
|
|
297
|
+
*/
|
|
298
|
+
declare function extractImageAttributes(block: WordPressBlock): {
|
|
299
|
+
url: string | null;
|
|
300
|
+
alt: string;
|
|
301
|
+
width?: number;
|
|
302
|
+
height?: number;
|
|
303
|
+
};
|
|
304
|
+
/**
|
|
305
|
+
* Extract title/heading text from a block
|
|
306
|
+
*/
|
|
307
|
+
declare function extractTitle(block: WordPressBlock): string | null;
|
|
308
|
+
/**
|
|
309
|
+
* Extract content/text from a block
|
|
310
|
+
* Returns React node for rendering
|
|
311
|
+
*/
|
|
312
|
+
declare function extractContent(block: WordPressBlock, context: RenderContext): React$1.ReactNode;
|
|
313
|
+
/**
|
|
314
|
+
* Extract media position from media-text block
|
|
315
|
+
*/
|
|
316
|
+
declare function extractMediaPosition(block: WordPressBlock): 'left' | 'right';
|
|
317
|
+
/**
|
|
318
|
+
* Extract vertical alignment from block
|
|
319
|
+
*/
|
|
320
|
+
declare function extractVerticalAlignment(block: WordPressBlock): 'top' | 'center' | 'bottom';
|
|
321
|
+
/**
|
|
322
|
+
* Extract alignment (full, wide, contained) from block
|
|
323
|
+
*/
|
|
324
|
+
declare function extractAlignment(block: WordPressBlock): 'full' | 'wide' | 'contained';
|
|
325
|
+
/**
|
|
326
|
+
* Extract overlay color from cover block
|
|
327
|
+
*/
|
|
328
|
+
declare function extractOverlayColor(block: WordPressBlock): string | null;
|
|
329
|
+
/**
|
|
330
|
+
* Extract dim ratio (overlay opacity) from cover block
|
|
331
|
+
*/
|
|
332
|
+
declare function extractDimRatio(block: WordPressBlock): number;
|
|
333
|
+
/**
|
|
334
|
+
* Extract min height from block
|
|
335
|
+
*/
|
|
336
|
+
declare function extractMinHeight(block: WordPressBlock): {
|
|
337
|
+
value: number;
|
|
338
|
+
unit: string;
|
|
339
|
+
} | null;
|
|
340
|
+
/**
|
|
341
|
+
* Extract heading level from heading block
|
|
342
|
+
*/
|
|
343
|
+
declare function extractHeadingLevel(block: WordPressBlock): number;
|
|
344
|
+
/**
|
|
345
|
+
* Extract text alignment from block
|
|
346
|
+
*/
|
|
347
|
+
declare function extractTextAlign(block: WordPressBlock): 'left' | 'center' | 'right' | null;
|
|
348
|
+
/**
|
|
349
|
+
* Extract font size from block
|
|
350
|
+
*/
|
|
351
|
+
declare function extractFontSize(block: WordPressBlock): string | null;
|
|
352
|
+
/**
|
|
353
|
+
* Convert image URL to Cloudflare variant if it's a Cloudflare URL
|
|
354
|
+
*/
|
|
355
|
+
declare function convertImageToCloudflareVariant(url: string | null, options?: {
|
|
356
|
+
width?: number;
|
|
357
|
+
height?: number;
|
|
358
|
+
}): string | null;
|
|
359
|
+
|
|
360
|
+
interface ImageConversionOptions {
|
|
361
|
+
/** Convert to Cloudflare variant if URL is already Cloudflare */
|
|
362
|
+
convertToCloudflare?: boolean;
|
|
363
|
+
/** Default width for Cloudflare variant */
|
|
364
|
+
defaultWidth?: number;
|
|
365
|
+
/** Default height for Cloudflare variant */
|
|
366
|
+
defaultHeight?: number;
|
|
367
|
+
/** Force conversion even if URL is not Cloudflare (not recommended) */
|
|
368
|
+
forceCloudflare?: boolean;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Convert image URL with optional Cloudflare variant transformation
|
|
372
|
+
*
|
|
373
|
+
* @param url - Image URL (WordPress or Cloudflare)
|
|
374
|
+
* @param options - Conversion options
|
|
375
|
+
* @returns Converted URL or original if conversion not applicable
|
|
376
|
+
*/
|
|
377
|
+
declare function convertImageUrl(url: string | null | undefined, options?: ImageConversionOptions): string | null;
|
|
378
|
+
/**
|
|
379
|
+
* Batch convert multiple image URLs
|
|
380
|
+
*/
|
|
381
|
+
declare function convertImageUrls(urls: (string | null | undefined)[], options?: ImageConversionOptions): (string | null)[];
|
|
382
|
+
|
|
383
|
+
interface SectionWrapperProps {
|
|
384
|
+
children: React$1.ReactNode;
|
|
385
|
+
/** Background color variant */
|
|
386
|
+
background?: 'light' | 'dark' | 'transparent';
|
|
387
|
+
/** Vertical spacing between sections */
|
|
388
|
+
spacing?: 'none' | 'small' | 'medium' | 'large';
|
|
389
|
+
/** Container width */
|
|
390
|
+
container?: 'full' | 'wide' | 'contained';
|
|
391
|
+
/** Additional CSS classes */
|
|
392
|
+
className?: string;
|
|
393
|
+
/** Optional block reference for extracting additional props */
|
|
394
|
+
block?: WordPressBlock;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Generic section wrapper component for consistent spacing and layout
|
|
398
|
+
*
|
|
399
|
+
* Usage in component mappings:
|
|
400
|
+
* ```ts
|
|
401
|
+
* {
|
|
402
|
+
* pattern: { name: 'core/cover' },
|
|
403
|
+
* component: HeroSection,
|
|
404
|
+
* wrapper: SectionWrapper,
|
|
405
|
+
* extractProps: (block) => ({ ... })
|
|
406
|
+
* }
|
|
407
|
+
* ```
|
|
408
|
+
*/
|
|
409
|
+
declare const SectionWrapper: React$1.FC<SectionWrapperProps>;
|
|
410
|
+
|
|
411
|
+
export { SectionWrapper, WPContent, WPErrorBoundary, WPPage, buildClassName, convertImageToCloudflareVariant, convertImageUrl, convertImageUrls, createDefaultRegistry, createEnhancedRegistry, extractAlignment, extractBackgroundImage, extractContent, extractDimRatio, extractFontSize, extractHeadingLevel, extractImageAttributes, extractImageUrl, extractMediaPosition, extractMinHeight, extractOverlayColor, extractTextAlign, extractTextFromHTML, extractTitle, extractVerticalAlignment, findMatchingMapping, findShortcodes, getAlignmentClasses, getBlockTextContent, getCloudflareVariantUrl, getContainerClasses, getContentSpacingClasses, getFontSizeClasses, getImageAttributes, getImageUrl, getSectionSpacingClasses, getTextAlignClasses, isCloudflareImageUrl, matchesPattern, parseGutenbergBlocks, parseShortcodeAttrs, renderNodes, renderTextWithShortcodes };
|
|
412
|
+
export type { AuthMode, BlockPattern, BlockRenderer, BlockRendererProps, CloudflareVariantOptions, ComponentMapping, ComponentRegistry, EnhancedRegistry, ImageConversionOptions, ParseOptions, ParsedShortcode, RenderContext, RenderOptions, SectionWrapperProps, ShortcodeAttributes, ShortcodeRenderer, WPContentProps, WPNode, WPPageProps, WordPressBlock, WordPressEmbedded, WordPressFeaturedMedia, WordPressPageMinimal, WordPressTitleField };
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC"}
|
|
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,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC"}
|
package/dist/index.esm.js
CHANGED
|
@@ -1931,6 +1931,138 @@ function getString(block) {
|
|
|
1931
1931
|
return getBlockTextContent(block);
|
|
1932
1932
|
}
|
|
1933
1933
|
|
|
1934
|
+
/**
|
|
1935
|
+
* Check if a block matches a pattern
|
|
1936
|
+
*/
|
|
1937
|
+
function matchesPattern(block, pattern) {
|
|
1938
|
+
// Check block name
|
|
1939
|
+
if (block.name !== pattern.name) {
|
|
1940
|
+
return false;
|
|
1941
|
+
}
|
|
1942
|
+
// Check attributes if specified
|
|
1943
|
+
if (pattern.attributes) {
|
|
1944
|
+
const blockAttrs = block.attributes || {};
|
|
1945
|
+
for (const [key, value] of Object.entries(pattern.attributes)) {
|
|
1946
|
+
if (blockAttrs[key] !== value) {
|
|
1947
|
+
return false;
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
// Check innerBlocks patterns if specified
|
|
1952
|
+
if (pattern.innerBlocks && pattern.innerBlocks.length > 0) {
|
|
1953
|
+
const blockInnerBlocks = block.innerBlocks || [];
|
|
1954
|
+
// If pattern specifies innerBlocks, check if block has matching innerBlocks
|
|
1955
|
+
for (const innerPattern of pattern.innerBlocks) {
|
|
1956
|
+
// Find at least one matching innerBlock
|
|
1957
|
+
const hasMatch = blockInnerBlocks.some(innerBlock => matchesPattern(innerBlock, innerPattern));
|
|
1958
|
+
if (!hasMatch) {
|
|
1959
|
+
return false;
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
return true;
|
|
1964
|
+
}
|
|
1965
|
+
/**
|
|
1966
|
+
* Find the best matching component mapping for a block
|
|
1967
|
+
* Returns the mapping with highest priority that matches, or null
|
|
1968
|
+
*/
|
|
1969
|
+
function findMatchingMapping(block, mappings) {
|
|
1970
|
+
// Sort by priority (higher first), then by order in array
|
|
1971
|
+
const sortedMappings = [...mappings].sort((a, b) => {
|
|
1972
|
+
const priorityA = a.priority ?? 0;
|
|
1973
|
+
const priorityB = b.priority ?? 0;
|
|
1974
|
+
if (priorityA !== priorityB) {
|
|
1975
|
+
return priorityB - priorityA; // Higher priority first
|
|
1976
|
+
}
|
|
1977
|
+
return 0; // Keep original order for same priority
|
|
1978
|
+
});
|
|
1979
|
+
// Find first matching mapping
|
|
1980
|
+
for (const mapping of sortedMappings) {
|
|
1981
|
+
if (matchesPattern(block, mapping.pattern)) {
|
|
1982
|
+
return mapping;
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
return null;
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
/**
|
|
1989
|
+
* Create an enhanced registry that supports pattern-based component mapping
|
|
1990
|
+
*
|
|
1991
|
+
* This combines the default registry (for fallback) with app-specific component mappings.
|
|
1992
|
+
* When a block matches a pattern, it uses the mapped component. Otherwise, it falls back
|
|
1993
|
+
* to the default renderer.
|
|
1994
|
+
*
|
|
1995
|
+
* @param mappings - Array of component mappings with patterns
|
|
1996
|
+
* @param baseRegistry - Optional base registry (defaults to createDefaultRegistry())
|
|
1997
|
+
* @returns Enhanced registry with pattern matching capabilities
|
|
1998
|
+
*
|
|
1999
|
+
* @example
|
|
2000
|
+
* ```ts
|
|
2001
|
+
* const mappings: ComponentMapping[] = [
|
|
2002
|
+
* {
|
|
2003
|
+
* pattern: { name: 'core/cover' },
|
|
2004
|
+
* component: HomeHeroSection,
|
|
2005
|
+
* extractProps: (block) => ({
|
|
2006
|
+
* backgroundImage: extractBackgroundImage(block),
|
|
2007
|
+
* title: extractTitle(block),
|
|
2008
|
+
* }),
|
|
2009
|
+
* wrapper: SectionWrapper,
|
|
2010
|
+
* },
|
|
2011
|
+
* ];
|
|
2012
|
+
*
|
|
2013
|
+
* const registry = createEnhancedRegistry(mappings);
|
|
2014
|
+
* ```
|
|
2015
|
+
*/
|
|
2016
|
+
function createEnhancedRegistry(mappings = [], baseRegistry) {
|
|
2017
|
+
const base = baseRegistry || createDefaultRegistry();
|
|
2018
|
+
// Create enhanced renderers that check patterns first
|
|
2019
|
+
const enhancedRenderers = {
|
|
2020
|
+
...base.renderers,
|
|
2021
|
+
};
|
|
2022
|
+
// Override renderers for blocks that have mappings
|
|
2023
|
+
// We need to check patterns at render time, so we create a wrapper renderer
|
|
2024
|
+
const createPatternRenderer = (blockName) => {
|
|
2025
|
+
return (props) => {
|
|
2026
|
+
const { block, context } = props;
|
|
2027
|
+
// Find matching mapping
|
|
2028
|
+
const mapping = findMatchingMapping(block, mappings);
|
|
2029
|
+
if (mapping) {
|
|
2030
|
+
// Extract props from block
|
|
2031
|
+
const componentProps = mapping.extractProps(block, context);
|
|
2032
|
+
// Render component
|
|
2033
|
+
const Component = mapping.component;
|
|
2034
|
+
const content = jsxRuntimeExports.jsx(Component, { ...componentProps });
|
|
2035
|
+
// Wrap with wrapper if provided
|
|
2036
|
+
if (mapping.wrapper) {
|
|
2037
|
+
const Wrapper = mapping.wrapper;
|
|
2038
|
+
return jsxRuntimeExports.jsx(Wrapper, { block: block, children: content });
|
|
2039
|
+
}
|
|
2040
|
+
return content;
|
|
2041
|
+
}
|
|
2042
|
+
// Fall back to default renderer
|
|
2043
|
+
const defaultRenderer = base.renderers[blockName] || base.fallback;
|
|
2044
|
+
return defaultRenderer(props);
|
|
2045
|
+
};
|
|
2046
|
+
};
|
|
2047
|
+
// For each mapping, override the renderer for that block name
|
|
2048
|
+
for (const mapping of mappings) {
|
|
2049
|
+
const blockName = mapping.pattern.name;
|
|
2050
|
+
if (blockName) {
|
|
2051
|
+
enhancedRenderers[blockName] = createPatternRenderer(blockName);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
// Create matchBlock function
|
|
2055
|
+
const matchBlock = (block) => {
|
|
2056
|
+
return findMatchingMapping(block, mappings);
|
|
2057
|
+
};
|
|
2058
|
+
return {
|
|
2059
|
+
...base,
|
|
2060
|
+
renderers: enhancedRenderers,
|
|
2061
|
+
mappings,
|
|
2062
|
+
matchBlock,
|
|
2063
|
+
};
|
|
2064
|
+
}
|
|
2065
|
+
|
|
1934
2066
|
const WPContent = ({ blocks, registry, className }) => {
|
|
1935
2067
|
if (!Array.isArray(blocks)) {
|
|
1936
2068
|
if (process.env.NODE_ENV !== 'production') {
|
|
@@ -2011,5 +2143,252 @@ class WPErrorBoundary extends React.Component {
|
|
|
2011
2143
|
}
|
|
2012
2144
|
}
|
|
2013
2145
|
|
|
2014
|
-
|
|
2146
|
+
/**
|
|
2147
|
+
* Extract background image URL from a block
|
|
2148
|
+
* Checks various possible sources: url, backgroundImage, innerHTML
|
|
2149
|
+
*/
|
|
2150
|
+
function extractBackgroundImage(block) {
|
|
2151
|
+
const attrs = block.attributes || {};
|
|
2152
|
+
// Try various attribute keys
|
|
2153
|
+
let url = attrs['url'] ||
|
|
2154
|
+
attrs['backgroundImage'] ||
|
|
2155
|
+
(typeof attrs['backgroundImage'] === 'object' && attrs['backgroundImage']?.url);
|
|
2156
|
+
if (typeof url === 'string' && url.trim()) {
|
|
2157
|
+
return url.trim();
|
|
2158
|
+
}
|
|
2159
|
+
// Try to extract from innerHTML if not found in attributes
|
|
2160
|
+
if (block.innerHTML) {
|
|
2161
|
+
// Try img src from innerHTML
|
|
2162
|
+
const imgMatch = block.innerHTML.match(/<img[^>]+src=["']([^"']+)["']/i);
|
|
2163
|
+
if (imgMatch && imgMatch[1]) {
|
|
2164
|
+
return imgMatch[1];
|
|
2165
|
+
}
|
|
2166
|
+
// Try background-image in style attribute
|
|
2167
|
+
const bgMatch = block.innerHTML.match(/background-image:\s*url\(["']?([^"')]+)["']?\)/i);
|
|
2168
|
+
if (bgMatch && bgMatch[1]) {
|
|
2169
|
+
return bgMatch[1];
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
return null;
|
|
2173
|
+
}
|
|
2174
|
+
/**
|
|
2175
|
+
* Extract image URL from a block
|
|
2176
|
+
* Returns Cloudflare URL if available, otherwise WordPress URL
|
|
2177
|
+
*/
|
|
2178
|
+
function extractImageUrl(block) {
|
|
2179
|
+
return getImageUrl(block);
|
|
2180
|
+
}
|
|
2181
|
+
/**
|
|
2182
|
+
* Extract image attributes (url, alt, width, height)
|
|
2183
|
+
*/
|
|
2184
|
+
function extractImageAttributes(block) {
|
|
2185
|
+
return getImageAttributes(block);
|
|
2186
|
+
}
|
|
2187
|
+
/**
|
|
2188
|
+
* Extract title/heading text from a block
|
|
2189
|
+
*/
|
|
2190
|
+
function extractTitle(block) {
|
|
2191
|
+
const attrs = block.attributes || {};
|
|
2192
|
+
const title = attrs['title'] || attrs['content'] || getBlockTextContent(block);
|
|
2193
|
+
return typeof title === 'string' ? title.trim() : null;
|
|
2194
|
+
}
|
|
2195
|
+
/**
|
|
2196
|
+
* Extract content/text from a block
|
|
2197
|
+
* Returns React node for rendering
|
|
2198
|
+
*/
|
|
2199
|
+
function extractContent(block, context) {
|
|
2200
|
+
const text = getBlockTextContent(block);
|
|
2201
|
+
return text || null;
|
|
2202
|
+
}
|
|
2203
|
+
/**
|
|
2204
|
+
* Extract media position from media-text block
|
|
2205
|
+
*/
|
|
2206
|
+
function extractMediaPosition(block) {
|
|
2207
|
+
const attrs = block.attributes || {};
|
|
2208
|
+
const position = attrs['mediaPosition'] || 'left';
|
|
2209
|
+
return position === 'right' ? 'right' : 'left';
|
|
2210
|
+
}
|
|
2211
|
+
/**
|
|
2212
|
+
* Extract vertical alignment from block
|
|
2213
|
+
*/
|
|
2214
|
+
function extractVerticalAlignment(block) {
|
|
2215
|
+
const attrs = block.attributes || {};
|
|
2216
|
+
const alignment = attrs['verticalAlignment'] || 'center';
|
|
2217
|
+
if (alignment === 'top' || alignment === 'bottom') {
|
|
2218
|
+
return alignment;
|
|
2219
|
+
}
|
|
2220
|
+
return 'center';
|
|
2221
|
+
}
|
|
2222
|
+
/**
|
|
2223
|
+
* Extract alignment (full, wide, contained) from block
|
|
2224
|
+
*/
|
|
2225
|
+
function extractAlignment(block) {
|
|
2226
|
+
const attrs = block.attributes || {};
|
|
2227
|
+
const align = attrs['align'];
|
|
2228
|
+
if (align === 'full' || align === 'wide') {
|
|
2229
|
+
return align;
|
|
2230
|
+
}
|
|
2231
|
+
return 'contained';
|
|
2232
|
+
}
|
|
2233
|
+
/**
|
|
2234
|
+
* Extract overlay color from cover block
|
|
2235
|
+
*/
|
|
2236
|
+
function extractOverlayColor(block) {
|
|
2237
|
+
const attrs = block.attributes || {};
|
|
2238
|
+
const overlayColor = attrs['overlayColor'];
|
|
2239
|
+
if (typeof overlayColor === 'string') {
|
|
2240
|
+
return overlayColor;
|
|
2241
|
+
}
|
|
2242
|
+
return null;
|
|
2243
|
+
}
|
|
2244
|
+
/**
|
|
2245
|
+
* Extract dim ratio (overlay opacity) from cover block
|
|
2246
|
+
*/
|
|
2247
|
+
function extractDimRatio(block) {
|
|
2248
|
+
const attrs = block.attributes || {};
|
|
2249
|
+
const dimRatio = attrs['dimRatio'];
|
|
2250
|
+
if (typeof dimRatio === 'number') {
|
|
2251
|
+
return dimRatio;
|
|
2252
|
+
}
|
|
2253
|
+
return 0;
|
|
2254
|
+
}
|
|
2255
|
+
/**
|
|
2256
|
+
* Extract min height from block
|
|
2257
|
+
*/
|
|
2258
|
+
function extractMinHeight(block) {
|
|
2259
|
+
const attrs = block.attributes || {};
|
|
2260
|
+
const minHeight = attrs['minHeight'];
|
|
2261
|
+
const minHeightUnit = attrs['minHeightUnit'] || 'vh';
|
|
2262
|
+
if (typeof minHeight === 'number') {
|
|
2263
|
+
return { value: minHeight, unit: minHeightUnit };
|
|
2264
|
+
}
|
|
2265
|
+
return null;
|
|
2266
|
+
}
|
|
2267
|
+
/**
|
|
2268
|
+
* Extract heading level from heading block
|
|
2269
|
+
*/
|
|
2270
|
+
function extractHeadingLevel(block) {
|
|
2271
|
+
const attrs = block.attributes || {};
|
|
2272
|
+
const level = attrs['level'];
|
|
2273
|
+
if (typeof level === 'number' && level >= 1 && level <= 6) {
|
|
2274
|
+
return level;
|
|
2275
|
+
}
|
|
2276
|
+
return 2; // Default to h2
|
|
2277
|
+
}
|
|
2278
|
+
/**
|
|
2279
|
+
* Extract text alignment from block
|
|
2280
|
+
*/
|
|
2281
|
+
function extractTextAlign(block) {
|
|
2282
|
+
const attrs = block.attributes || {};
|
|
2283
|
+
const align = attrs['align'] || attrs['textAlign'];
|
|
2284
|
+
if (align === 'left' || align === 'center' || align === 'right') {
|
|
2285
|
+
return align;
|
|
2286
|
+
}
|
|
2287
|
+
return null;
|
|
2288
|
+
}
|
|
2289
|
+
/**
|
|
2290
|
+
* Extract font size from block
|
|
2291
|
+
*/
|
|
2292
|
+
function extractFontSize(block) {
|
|
2293
|
+
const attrs = block.attributes || {};
|
|
2294
|
+
const fontSize = attrs['fontSize'];
|
|
2295
|
+
return typeof fontSize === 'string' ? fontSize : null;
|
|
2296
|
+
}
|
|
2297
|
+
/**
|
|
2298
|
+
* Convert image URL to Cloudflare variant if it's a Cloudflare URL
|
|
2299
|
+
*/
|
|
2300
|
+
function convertImageToCloudflareVariant(url, options = {}) {
|
|
2301
|
+
if (!url)
|
|
2302
|
+
return null;
|
|
2303
|
+
if (isCloudflareImageUrl(url)) {
|
|
2304
|
+
const width = options.width || 1024;
|
|
2305
|
+
const height = options.height;
|
|
2306
|
+
return getCloudflareVariantUrl(url, { width, height });
|
|
2307
|
+
}
|
|
2308
|
+
return url;
|
|
2309
|
+
}
|
|
2310
|
+
|
|
2311
|
+
/**
|
|
2312
|
+
* Convert image URL with optional Cloudflare variant transformation
|
|
2313
|
+
*
|
|
2314
|
+
* @param url - Image URL (WordPress or Cloudflare)
|
|
2315
|
+
* @param options - Conversion options
|
|
2316
|
+
* @returns Converted URL or original if conversion not applicable
|
|
2317
|
+
*/
|
|
2318
|
+
function convertImageUrl(url, options = {}) {
|
|
2319
|
+
if (!url)
|
|
2320
|
+
return null;
|
|
2321
|
+
const { convertToCloudflare = true, defaultWidth = 1024, defaultHeight, forceCloudflare = false, } = options;
|
|
2322
|
+
// If already Cloudflare URL and conversion is enabled
|
|
2323
|
+
if (isCloudflareImageUrl(url)) {
|
|
2324
|
+
if (convertToCloudflare) {
|
|
2325
|
+
return getCloudflareVariantUrl(url, {
|
|
2326
|
+
width: defaultWidth,
|
|
2327
|
+
height: defaultHeight,
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2330
|
+
return url;
|
|
2331
|
+
}
|
|
2332
|
+
// If force conversion is enabled (not recommended - requires WordPress plugin to provide Cloudflare URLs)
|
|
2333
|
+
if (forceCloudflare) {
|
|
2334
|
+
// This would require additional logic to map WordPress URLs to Cloudflare URLs
|
|
2335
|
+
// which should be handled by the WordPress plugin providing Cloudflare URLs in block data
|
|
2336
|
+
console.warn('forceCloudflare is enabled but URL is not Cloudflare. WordPress plugin should provide Cloudflare URLs in block metadata.');
|
|
2337
|
+
}
|
|
2338
|
+
// Return original URL if not Cloudflare
|
|
2339
|
+
return url;
|
|
2340
|
+
}
|
|
2341
|
+
/**
|
|
2342
|
+
* Batch convert multiple image URLs
|
|
2343
|
+
*/
|
|
2344
|
+
function convertImageUrls(urls, options = {}) {
|
|
2345
|
+
return urls.map(url => convertImageUrl(url, options));
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
/**
|
|
2349
|
+
* Generic section wrapper component for consistent spacing and layout
|
|
2350
|
+
*
|
|
2351
|
+
* Usage in component mappings:
|
|
2352
|
+
* ```ts
|
|
2353
|
+
* {
|
|
2354
|
+
* pattern: { name: 'core/cover' },
|
|
2355
|
+
* component: HeroSection,
|
|
2356
|
+
* wrapper: SectionWrapper,
|
|
2357
|
+
* extractProps: (block) => ({ ... })
|
|
2358
|
+
* }
|
|
2359
|
+
* ```
|
|
2360
|
+
*/
|
|
2361
|
+
const SectionWrapper = ({ children, background = 'light', spacing = 'medium', container = 'contained', className, block, }) => {
|
|
2362
|
+
// Background classes
|
|
2363
|
+
const backgroundClasses = {
|
|
2364
|
+
light: 'bg-white',
|
|
2365
|
+
dark: 'bg-gray-900 text-white',
|
|
2366
|
+
transparent: 'bg-transparent',
|
|
2367
|
+
};
|
|
2368
|
+
// Spacing classes (vertical padding)
|
|
2369
|
+
const spacingClasses = {
|
|
2370
|
+
none: '',
|
|
2371
|
+
small: 'py-8 md:py-12',
|
|
2372
|
+
medium: 'py-16 md:py-24',
|
|
2373
|
+
large: 'py-24 md:py-32',
|
|
2374
|
+
};
|
|
2375
|
+
// Container classes
|
|
2376
|
+
const containerClasses = {
|
|
2377
|
+
full: 'w-full',
|
|
2378
|
+
wide: 'max-w-7xl mx-auto px-4',
|
|
2379
|
+
contained: 'container mx-auto px-4',
|
|
2380
|
+
};
|
|
2381
|
+
// Extract additional props from block if provided
|
|
2382
|
+
const blockAttrs = block?.attributes || {};
|
|
2383
|
+
const blockBackground = blockAttrs['backgroundColor'] || blockAttrs['background'];
|
|
2384
|
+
const blockSpacing = blockAttrs['spacing'];
|
|
2385
|
+
const blockContainer = blockAttrs['container'] || blockAttrs['align'];
|
|
2386
|
+
// Override with block attributes if present
|
|
2387
|
+
const finalBackground = blockBackground || background;
|
|
2388
|
+
const finalSpacing = blockSpacing || spacing;
|
|
2389
|
+
const finalContainer = blockContainer || container;
|
|
2390
|
+
return (jsxRuntimeExports.jsx("section", { className: buildClassName(backgroundClasses[finalBackground] || backgroundClasses.light, spacingClasses[finalSpacing] || spacingClasses.medium, containerClasses[finalContainer] || containerClasses.contained, className), children: children }));
|
|
2391
|
+
};
|
|
2392
|
+
|
|
2393
|
+
export { SectionWrapper, WPContent, WPErrorBoundary, WPPage, buildClassName, convertImageToCloudflareVariant, convertImageUrl, convertImageUrls, createDefaultRegistry, createEnhancedRegistry, extractAlignment, extractBackgroundImage, extractContent, extractDimRatio, extractFontSize, extractHeadingLevel, extractImageAttributes, extractImageUrl, extractMediaPosition, extractMinHeight, extractOverlayColor, extractTextAlign, extractTextFromHTML, extractTitle, extractVerticalAlignment, findMatchingMapping, findShortcodes, getAlignmentClasses, getBlockTextContent, getCloudflareVariantUrl, getContainerClasses, getContentSpacingClasses, getFontSizeClasses, getImageAttributes, getImageUrl, getSectionSpacingClasses, getTextAlignClasses, isCloudflareImageUrl, matchesPattern, parseGutenbergBlocks, parseShortcodeAttrs, renderNodes, renderTextWithShortcodes };
|
|
2015
2394
|
//# sourceMappingURL=index.esm.js.map
|