@exdst-sitecore-content-sdk/astro 0.0.1

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.
Files changed (87) hide show
  1. package/LICENSE.txt +202 -0
  2. package/README.md +3 -0
  3. package/package.json +101 -0
  4. package/src/client/index.ts +12 -0
  5. package/src/client/sitecore-astro-client.test.ts +271 -0
  6. package/src/client/sitecore-astro-client.ts +137 -0
  7. package/src/components/AstroImage.astro +114 -0
  8. package/src/components/Date.astro +76 -0
  9. package/src/components/DefaultEmptyFieldEditingComponentImage.astro +24 -0
  10. package/src/components/DefaultEmptyFieldEditingComponentText.astro +12 -0
  11. package/src/components/EditingScripts.astro +49 -0
  12. package/src/components/EmptyRendering.astro +3 -0
  13. package/src/components/ErrorBoundary.astro +77 -0
  14. package/src/components/FieldMetadata.astro +30 -0
  15. package/src/components/File.astro +46 -0
  16. package/src/components/HiddenRendering.astro +22 -0
  17. package/src/components/Image.astro +155 -0
  18. package/src/components/Link.astro +105 -0
  19. package/src/components/MissingComponent.astro +39 -0
  20. package/src/components/Placeholder/EmptyPlaceholder.astro +9 -0
  21. package/src/components/Placeholder/Placeholder.astro +100 -0
  22. package/src/components/Placeholder/PlaceholderMetadata.astro +102 -0
  23. package/src/components/Placeholder/PlaceholderUtils.astro +153 -0
  24. package/src/components/Placeholder/index.ts +5 -0
  25. package/src/components/Placeholder/models.ts +82 -0
  26. package/src/components/Placeholder/placeholder-utils.test.ts +162 -0
  27. package/src/components/Placeholder/placeholder-utils.ts +80 -0
  28. package/src/components/RenderWrapper.astro +31 -0
  29. package/src/components/RichText.astro +59 -0
  30. package/src/components/Text.astro +97 -0
  31. package/src/components/sharedTypes/index.ts +1 -0
  32. package/src/components/sharedTypes/props.ts +17 -0
  33. package/src/config/define-config.test.ts +526 -0
  34. package/src/config/define-config.ts +99 -0
  35. package/src/config/index.ts +1 -0
  36. package/src/config-cli/define-cli-config.test.ts +95 -0
  37. package/src/config-cli/define-cli-config.ts +50 -0
  38. package/src/config-cli/index.ts +1 -0
  39. package/src/context.ts +68 -0
  40. package/src/editing/constants.ts +8 -0
  41. package/src/editing/editing-config-middleware.test.ts +166 -0
  42. package/src/editing/editing-config-middleware.ts +111 -0
  43. package/src/editing/editing-render-middleware.test.ts +801 -0
  44. package/src/editing/editing-render-middleware.ts +288 -0
  45. package/src/editing/index.ts +16 -0
  46. package/src/editing/render-middleware.test.ts +57 -0
  47. package/src/editing/render-middleware.ts +51 -0
  48. package/src/editing/utils.test.ts +852 -0
  49. package/src/editing/utils.ts +308 -0
  50. package/src/enhancers/WithEmptyFieldEditingComponent.astro +56 -0
  51. package/src/enhancers/WithFieldMetadata.astro +31 -0
  52. package/src/env.d.ts +12 -0
  53. package/src/index.ts +16 -0
  54. package/src/middleware/index.ts +24 -0
  55. package/src/middleware/middleware.test.ts +507 -0
  56. package/src/middleware/middleware.ts +167 -0
  57. package/src/middleware/multisite-middleware.test.ts +672 -0
  58. package/src/middleware/multisite-middleware.ts +147 -0
  59. package/src/middleware/robots-middleware.test.ts +113 -0
  60. package/src/middleware/robots-middleware.ts +47 -0
  61. package/src/middleware/sitemap-middleware.test.ts +152 -0
  62. package/src/middleware/sitemap-middleware.ts +65 -0
  63. package/src/services/component-props-service.ts +182 -0
  64. package/src/sharedTypes/component-props.ts +17 -0
  65. package/src/site/index.ts +1 -0
  66. package/src/test-data/components/Bar.astro +0 -0
  67. package/src/test-data/components/Baz.astro +0 -0
  68. package/src/test-data/components/Foo.astro +0 -0
  69. package/src/test-data/components/Hero.variant.astro +0 -0
  70. package/src/test-data/components/NotComponent.bsx +0 -0
  71. package/src/test-data/components/Qux.astro +0 -0
  72. package/src/test-data/components/folded/Folded.astro +0 -0
  73. package/src/test-data/components/folded/random-file-2.docx +0 -0
  74. package/src/test-data/components/random-file.txt +0 -0
  75. package/src/test-data/helpers.ts +46 -0
  76. package/src/test-data/personalizeData.ts +63 -0
  77. package/src/tools/generate-map.ts +83 -0
  78. package/src/tools/index.ts +8 -0
  79. package/src/tools/templating/components.test.ts +305 -0
  80. package/src/tools/templating/components.ts +49 -0
  81. package/src/tools/templating/constants.ts +4 -0
  82. package/src/tools/templating/default-component.test.ts +31 -0
  83. package/src/tools/templating/default-component.ts +63 -0
  84. package/src/tools/templating/index.ts +2 -0
  85. package/src/utils/index.ts +1 -0
  86. package/src/utils/utils.test.ts +48 -0
  87. package/src/utils/utils.ts +52 -0
@@ -0,0 +1,155 @@
1
+ ---
2
+ import { mediaApi } from '@sitecore-content-sdk/core/media';
3
+ import { EditableFieldProps } from './sharedTypes';
4
+ import {
5
+ FieldMetadata,
6
+ isFieldValueEmpty,
7
+ } from '@sitecore-content-sdk/core/layout';
8
+ import { addClassName } from '../utils';
9
+ import WithFieldMetadata from '../enhancers/WithFieldMetadata.astro';
10
+ import WithEmptyFieldEditingComponent from '../enhancers/WithEmptyFieldEditingComponent.astro';
11
+ import DefaultEmptyFieldEditingComponentImage from './DefaultEmptyFieldEditingComponentImage.astro';
12
+
13
+ export interface ImageFieldValue {
14
+ [attributeName: string]: unknown;
15
+ src?: string;
16
+ }
17
+
18
+ export interface ImageField {
19
+ value?: ImageFieldValue;
20
+ }
21
+
22
+ export interface ImageSizeParameters {
23
+ [attr: string]: string | number | undefined;
24
+ /** Fixed width of the image */
25
+ w?: number;
26
+ /** Fixed height of the image */
27
+ h?: number;
28
+ /** Max width of the image */
29
+ mw?: number;
30
+ /** Max height of the image */
31
+ mh?: number;
32
+ /** Ignore aspect ratio */
33
+ iar?: 1 | 0;
34
+ /** Allow stretch */
35
+ as?: 1 | 0;
36
+ /** Image scale. Defaults to 1.0 */
37
+ sc?: number;
38
+ }
39
+
40
+ export interface BaseImageProps {
41
+ [attributeName: string]: unknown;
42
+ /** Image field data (consistent with other field types) */
43
+ field?: (ImageField | ImageFieldValue) & FieldMetadata;
44
+ /**
45
+ * Parameters that will be attached to Sitecore media URLs
46
+ */
47
+ imageParams?: {
48
+ [paramName: string]: string | number;
49
+ };
50
+ /**
51
+ * Custom regexp that finds media URL prefix that will be replaced by `/-/jssmedia` or `/~/jssmedia`.
52
+ * @example
53
+ * /\/([-~]{1})assets\//i
54
+ * /-assets/website -> /-/jssmedia/website
55
+ * /~assets/website -> /~/jssmedia/website
56
+ */
57
+ mediaUrlPrefix?: RegExp;
58
+ }
59
+
60
+ export interface ImageProps extends BaseImageProps, EditableFieldProps {
61
+ srcSet?: ImageSizeParameters[];
62
+ }
63
+
64
+ const getImageAttrs = (
65
+ {
66
+ src,
67
+ srcSet,
68
+ ...otherAttrs
69
+ }: {
70
+ [key: string]: unknown;
71
+ src?: string;
72
+ srcSet?: ImageSizeParameters[];
73
+ },
74
+ imageParams?: { [paramName: string]: string | number },
75
+ mediaUrlPrefix?: RegExp
76
+ ) => {
77
+ if (!src) {
78
+ return null;
79
+ }
80
+ addClassName(otherAttrs);
81
+
82
+ const newAttrs: { [attr: string]: unknown } = {
83
+ ...otherAttrs,
84
+ };
85
+
86
+ // update image URL for content sdk handler and image rendering params
87
+ const resolvedSrc = mediaApi.updateImageUrl(src, imageParams, mediaUrlPrefix);
88
+ if (srcSet) {
89
+ // replace with HTML-formatted srcset, including updated image URLs
90
+ newAttrs.srcSet = mediaApi.getSrcSet(
91
+ resolvedSrc,
92
+ srcSet,
93
+ imageParams,
94
+ mediaUrlPrefix
95
+ );
96
+ }
97
+ // always output original src as fallback for older browsers
98
+ newAttrs.src = resolvedSrc;
99
+ return newAttrs;
100
+ };
101
+
102
+ const {
103
+ editable = true,
104
+ imageParams,
105
+ field,
106
+ mediaUrlPrefix,
107
+ emptyFieldEditingComponent,
108
+ ...otherProps
109
+ } = Astro.props as ImageProps;
110
+
111
+ const dynamicMedia = field as ImageField | ImageFieldValue;
112
+
113
+ const isEmptyField = isFieldValueEmpty(dynamicMedia);
114
+
115
+ let img;
116
+ if (!isEmptyField) {
117
+ // handle image directly on field for forgetful devs
118
+ img = (dynamicMedia as ImageFieldValue).src
119
+ ? { ...field }
120
+ : (dynamicMedia.value as ImageFieldValue);
121
+
122
+ if (img) {
123
+ // prevent metadata from being passed to the img tag
124
+ if (img.metadata) {
125
+ delete img.metadata;
126
+ }
127
+ }
128
+ }
129
+
130
+ const attrs = getImageAttrs(
131
+ { ...img, ...otherProps },
132
+ imageParams,
133
+ mediaUrlPrefix
134
+ );
135
+
136
+ console.log("Attrs", attrs);
137
+ ---
138
+
139
+ {
140
+ (
141
+ <WithFieldMetadata field={field} editable={editable}>
142
+ <WithEmptyFieldEditingComponent
143
+ field={field}
144
+ editable={editable}
145
+ defaultEmptyFieldEditingComponent={
146
+ DefaultEmptyFieldEditingComponentImage
147
+ }
148
+ emptyFieldEditingComponent={emptyFieldEditingComponent}
149
+ {...otherProps}
150
+ >
151
+ {!isEmptyField && img && attrs && <img {...attrs} />}
152
+ </WithEmptyFieldEditingComponent>
153
+ </WithFieldMetadata>
154
+ )
155
+ }
@@ -0,0 +1,105 @@
1
+ ---
2
+ import {
3
+ FieldMetadata,
4
+ isFieldValueEmpty,
5
+ } from '@sitecore-content-sdk/core/layout';
6
+ import { EditableFieldProps } from './sharedTypes';
7
+ import WithFieldMetadata from '../enhancers/WithFieldMetadata.astro';
8
+ import WithEmptyFieldEditingComponent from '../enhancers/WithEmptyFieldEditingComponent.astro';
9
+ import DefaultEmptyFieldEditingComponentText from './DefaultEmptyFieldEditingComponentText.astro';
10
+
11
+ export interface LinkFieldValue {
12
+ [attributeName: string]: unknown;
13
+ href?: string;
14
+ class?: string;
15
+ title?: string;
16
+ target?: string;
17
+ text?: string;
18
+ anchor?: string;
19
+ querystring?: string;
20
+ linktype?: string;
21
+ }
22
+
23
+ export interface LinkField {
24
+ value: LinkFieldValue;
25
+ }
26
+
27
+ export interface LinkProps extends EditableFieldProps {
28
+ [htmlAttributes: string]: unknown;
29
+ /** The link field data. */
30
+ field: (LinkField | LinkFieldValue) & FieldMetadata;
31
+ /**
32
+ * Displays a link text ('description' in Sitecore) even when children exist
33
+ */
34
+ showLinkTextWithChildrenPresent?: boolean;
35
+ }
36
+
37
+ const {
38
+ field,
39
+ editable = true,
40
+ showLinkTextWithChildrenPresent,
41
+ emptyFieldEditingComponent,
42
+ ...otherProps
43
+ } = Astro.props as LinkProps;
44
+
45
+ const children = await Astro.slots.render('default');
46
+ const dynamicField: LinkField | LinkFieldValue = field;
47
+
48
+ const isEmptyField = isFieldValueEmpty(dynamicField);
49
+
50
+ let link,
51
+ finalChildren,
52
+ anchorAttrs: { [attr: string]: unknown } = {};
53
+
54
+ if (!isEmptyField) {
55
+ // handle link directly on field for forgetful devs
56
+ link = (dynamicField as LinkFieldValue).href
57
+ ? (field as LinkFieldValue)
58
+ : (dynamicField as LinkField).value;
59
+
60
+ if (link) {
61
+ const anchor =
62
+ link.linktype !== 'anchor' && link.anchor ? `#${link.anchor}` : '';
63
+ const querystring = link.querystring ? `?${link.querystring}` : '';
64
+
65
+ anchorAttrs = {
66
+ href: `${link.href}${querystring}${anchor}`,
67
+ class: link.class,
68
+ title: link.title,
69
+ target: link.target,
70
+ };
71
+
72
+ if (anchorAttrs.target === '_blank' && !anchorAttrs.rel) {
73
+ // information disclosure attack prevention keeps target blank site from getting ref to window.opener
74
+ anchorAttrs.rel = 'noopener noreferrer';
75
+ }
76
+
77
+ const linkText =
78
+ showLinkTextWithChildrenPresent || !children
79
+ ? link.text || link.href
80
+ : null;
81
+
82
+ finalChildren = children ? [linkText, ...children] : linkText;
83
+ }
84
+ }
85
+
86
+ const attrs = { ...anchorAttrs, ...otherProps };
87
+ ---
88
+
89
+ {
90
+ (
91
+ <WithFieldMetadata field={field} editable={editable}>
92
+ <WithEmptyFieldEditingComponent
93
+ field={field}
94
+ editable={editable}
95
+ defaultEmptyFieldEditingComponent={
96
+ DefaultEmptyFieldEditingComponentText
97
+ }
98
+ emptyFieldEditingComponent={emptyFieldEditingComponent}
99
+ {...otherProps}
100
+ >
101
+ {!isEmptyField && link && <a {...attrs} set:html={finalChildren} />}
102
+ </WithEmptyFieldEditingComponent>
103
+ </WithFieldMetadata>
104
+ )
105
+ }
@@ -0,0 +1,39 @@
1
+ ---
2
+ interface MissingComponentProps {
3
+ rendering?: {
4
+ componentName?: string;
5
+ };
6
+ errorOverride?: string;
7
+ }
8
+
9
+ const props = Astro.props as MissingComponentProps;
10
+
11
+ const componentName =
12
+ props.rendering && props.rendering.componentName
13
+ ? props.rendering.componentName
14
+ : 'Unnamed Component';
15
+
16
+ // error override would mean component is not unimplemented
17
+ !props.errorOverride &&
18
+ console.log(
19
+ `Component props for unimplemented '${componentName}' component`,
20
+ props
21
+ );
22
+
23
+ const errorMessage =
24
+ props.errorOverride ||
25
+ 'Content SDK component is missing Astro implementation. See the developer console for more information.';
26
+ ---
27
+
28
+ <div
29
+ style={{
30
+ background: 'darkorange',
31
+ outline: '5px solid orange',
32
+ padding: '10px',
33
+ color: 'white',
34
+ maxWidth: '500px',
35
+ }}
36
+ >
37
+ <h2>{componentName}</h2>
38
+ <p>{errorMessage}</p>
39
+ </div>
@@ -0,0 +1,9 @@
1
+ ---
2
+ /**
3
+ * Renders the empty placeholder. The required CSS styles are applied to the placeholder in edit mode.
4
+ */
5
+ ---
6
+
7
+ <div class="sc-jss-empty-placeholder">
8
+ <slot />
9
+ </div>
@@ -0,0 +1,100 @@
1
+ ---
2
+ import { ComponentRendering } from '@sitecore-content-sdk/core/layout';
3
+ import ErrorBoundary from '../ErrorBoundary.astro';
4
+ import PlaceholderMetadata from './PlaceholderMetadata.astro';
5
+ import { useSitecore } from '../../context';
6
+ import RenderWrapper from '../RenderWrapper.astro';
7
+ import EmptyPlaceholder from './EmptyPlaceholder.astro';
8
+ import { PlaceholderProps } from './models';
9
+ import { getPlaceholderRenderings } from './placeholder-utils';
10
+ import { getComponentsForRenderingData } from './PlaceholderUtils.astro';
11
+
12
+ const props = Astro.props as PlaceholderProps;
13
+
14
+ const { page } = useSitecore();
15
+ const childProps: PlaceholderProps = { ...props, page };
16
+
17
+ delete childProps.componentMap;
18
+
19
+ const renderingData = childProps.rendering;
20
+
21
+ const placeholderData = getPlaceholderRenderings(
22
+ renderingData,
23
+ childProps.name,
24
+ childProps.page.mode.isEditing
25
+ );
26
+
27
+ const isEmpty = !placeholderData.length;
28
+
29
+ const components = getComponentsForRenderingData(placeholderData, childProps);
30
+ ---
31
+
32
+ {
33
+ (
34
+ <RenderWrapper
35
+ wrapper={
36
+ isEmpty
37
+ ? childProps.page.mode.isEditing && EmptyPlaceholder
38
+ : childProps.render
39
+ }
40
+ >
41
+ <ErrorBoundary>
42
+ <RenderWrapper wrapper={isEmpty && childProps.renderEmpty}>
43
+ {
44
+ // Conditional rendering based on editing mode
45
+ childProps.page.mode.isEditing ? (
46
+ <PlaceholderMetadata
47
+ placeholderName={childProps.name}
48
+ rendering={childProps.rendering as ComponentRendering}
49
+ >
50
+ {components.map((component) => {
51
+ const Component = component.component.component;
52
+
53
+ return (
54
+ <RenderWrapper wrapper={childProps.renderEach}>
55
+ <PlaceholderMetadata
56
+ rendering={component.rendering as ComponentRendering}
57
+ >
58
+ {!component.component.isEmpty && (
59
+ <ErrorBoundary
60
+ errorComponent={childProps.errorComponent}
61
+ {...component.props}
62
+ >
63
+ <Component {...component.props} />
64
+ </ErrorBoundary>
65
+ )}
66
+ {component.component.isEmpty && (
67
+ <Component {...component.props} />
68
+ )}
69
+ </PlaceholderMetadata>
70
+ </RenderWrapper>
71
+ );
72
+ })}
73
+ </PlaceholderMetadata>
74
+ ) : (
75
+ <>
76
+ {components.map((component) => {
77
+ const Component = component.component.component;
78
+ return (
79
+ <RenderWrapper
80
+ wrapper={
81
+ isEmpty ? childProps.renderEmpty : childProps.renderEach
82
+ }
83
+ >
84
+ <ErrorBoundary
85
+ errorComponent={childProps.errorComponent}
86
+ {...component.props}
87
+ >
88
+ <Component {...component.props} />
89
+ </ErrorBoundary>
90
+ </RenderWrapper>
91
+ );
92
+ })}
93
+ </>
94
+ )
95
+ }
96
+ </RenderWrapper>
97
+ </ErrorBoundary>
98
+ </RenderWrapper>
99
+ )
100
+ }
@@ -0,0 +1,102 @@
1
+ ---
2
+ /**
3
+ * An Astro component to generate metadata blocks for a placeholder or rendering.
4
+ * It utilizes dynamic attributes based on whether the component acts as a placeholder
5
+ * or as a rendering to properly render the surrounding code blocks.
6
+ */
7
+
8
+ import {
9
+ ComponentRendering,
10
+ getDynamicPlaceholderPattern,
11
+ isDynamicPlaceholder,
12
+ } from '@sitecore-content-sdk/core/layout';
13
+ import {
14
+ MetadataKind,
15
+ DEFAULT_PLACEHOLDER_UID,
16
+ } from '@sitecore-content-sdk/core/editing';
17
+
18
+ /**
19
+ * Props containing the component data to render.
20
+ */
21
+ export interface PlaceholderMetadataProps {
22
+ rendering: ComponentRendering;
23
+ placeholderName?: string;
24
+ }
25
+
26
+ export type CodeBlockAttributes = {
27
+ type: string;
28
+ chrometype: string;
29
+ className: string;
30
+ kind: string;
31
+ id?: string;
32
+ };
33
+
34
+ const props = Astro.props as PlaceholderMetadataProps;
35
+
36
+ const getCodeBlockAttributes = (
37
+ kind: MetadataKind,
38
+ id?: string,
39
+ placeholderName?: string
40
+ ): CodeBlockAttributes => {
41
+ const chrometype = placeholderName ? 'placeholder' : 'rendering';
42
+
43
+ const attributes: CodeBlockAttributes = {
44
+ type: 'text/sitecore',
45
+ chrometype: chrometype,
46
+ className: 'scpm',
47
+ kind: kind,
48
+ };
49
+
50
+ if (kind === MetadataKind.Open) {
51
+ if (chrometype === 'placeholder' && placeholderName) {
52
+ let phId = '';
53
+
54
+ for (const placeholder of Object.keys(
55
+ props.rendering.placeholders ?? {}
56
+ )) {
57
+ if (placeholderName === placeholder) {
58
+ phId = id
59
+ ? `${placeholderName}_${id}`
60
+ : `${placeholderName}_${DEFAULT_PLACEHOLDER_UID}`;
61
+ break;
62
+ }
63
+
64
+ // Check if the placeholder is a dynamic placeholder
65
+ if (isDynamicPlaceholder(placeholder)) {
66
+ const pattern = getDynamicPlaceholderPattern(placeholder);
67
+
68
+ // Check if the placeholder matches the dynamic placeholder pattern
69
+ if (pattern.test(placeholderName)) {
70
+ phId = id
71
+ ? `${placeholder}_${id}`
72
+ : `${placeholder}_${DEFAULT_PLACEHOLDER_UID}`;
73
+ break;
74
+ }
75
+ }
76
+ }
77
+
78
+ attributes.id = phId;
79
+ } else {
80
+ attributes.id = id;
81
+ }
82
+ }
83
+
84
+ return attributes;
85
+ };
86
+ ---
87
+
88
+ <>
89
+ <code
90
+ {...getCodeBlockAttributes(
91
+ MetadataKind.Open,
92
+ props.rendering.uid,
93
+ props.placeholderName
94
+ )}></code>
95
+ <slot />
96
+ <code
97
+ {...getCodeBlockAttributes(
98
+ MetadataKind.Close,
99
+ props.rendering.uid,
100
+ props.placeholderName
101
+ )}></code>
102
+ </>
@@ -0,0 +1,153 @@
1
+ ---
2
+ import { ComponentRendering } from "@sitecore-content-sdk/core/layout";
3
+ import { constants } from '@sitecore-content-sdk/core';
4
+ import EmptyRendering from "../EmptyRendering.astro";
5
+ import HiddenRendering from "../HiddenRendering.astro";
6
+ import MissingComponent from "../MissingComponent.astro";
7
+ import { getSXAParams } from "./placeholder-utils";
8
+ import { ComponentForRendering, PlaceholderProps } from "./models";
9
+ import { AstroContentSdkComponent, ComponentMap } from "../../sharedTypes/component-props";
10
+ import { useComponentMap } from "../../context";
11
+
12
+ export const getComponentsForRenderingData = (
13
+ placeholderData: ComponentRendering[],
14
+ props: PlaceholderProps
15
+ ) => {
16
+ const {
17
+ name,
18
+ fields: placeholderFields,
19
+ params: placeholderParams,
20
+ missingComponentComponent,
21
+ hiddenRenderingComponent,
22
+ ...placeholderProps
23
+ } = props;
24
+
25
+ const transformedComponents = placeholderData
26
+ .map((rendering: ComponentRendering, index: number) => {
27
+ const key = (rendering as ComponentRendering).uid
28
+ ? (rendering as ComponentRendering).uid
29
+ : `component-${index}`;
30
+ const commonProps = { key };
31
+
32
+ const componentRendering = rendering as ComponentRendering;
33
+ const componentMap = useComponentMap();
34
+
35
+ const component = getComponentForRendering(
36
+ componentRendering,
37
+ name,
38
+ componentMap,
39
+ hiddenRenderingComponent,
40
+ missingComponentComponent
41
+ );
42
+
43
+ const finalProps = {
44
+ ...commonProps,
45
+ ...placeholderProps,
46
+ ...((placeholderFields || componentRendering.fields) && {
47
+ fields: { ...placeholderFields, ...componentRendering.fields },
48
+ }),
49
+ ...((placeholderParams || componentRendering.params) && {
50
+ params: {
51
+ ...placeholderParams,
52
+ ...componentRendering.params,
53
+ // Provide SXA styles
54
+ ...getSXAParams(componentRendering),
55
+ },
56
+ }),
57
+ rendering: componentRendering,
58
+ };
59
+
60
+ let components = {
61
+ component: component,
62
+ props: props.modifyComponentProps ? props.modifyComponentProps(finalProps) : finalProps,
63
+ rendering: rendering,
64
+ placeholderName: name
65
+ };
66
+
67
+ return components;
68
+ })
69
+ .filter((element) => element); // remove nulls
70
+
71
+ return transformedComponents;
72
+ };
73
+
74
+ export const getComponentForRendering = (
75
+ renderingDefinition: ComponentRendering,
76
+ placeholderName: string,
77
+ componentMap?: ComponentMap,
78
+ hiddenRenderingComponent?: AstroContentSdkComponent,
79
+ missingComponentComponent?: AstroContentSdkComponent
80
+ ): ComponentForRendering => {
81
+ const logUnknownComponentError = (variant?: string) => {
82
+ console.error(
83
+ `Placeholder ${placeholderName} contains unknown component ${
84
+ renderingDefinition.componentName
85
+ }${
86
+ variant ? ` (${variant})` : ''
87
+ }. Ensure that a React component exists for it, and that it is registered in your component-map file.`
88
+ );
89
+ };
90
+
91
+ let component;
92
+
93
+ if (renderingDefinition.componentName === constants.HIDDEN_RENDERING_NAME) {
94
+ return {
95
+ component: hiddenRenderingComponent ?? HiddenRendering,
96
+ isEmpty: true
97
+ };
98
+ } else if (!renderingDefinition.componentName) {
99
+ return {
100
+ component: EmptyRendering,
101
+ isEmpty: true
102
+ };
103
+ }
104
+
105
+ if (!componentMap || componentMap.size === 0) {
106
+ console.warn(
107
+ `No components were available in component map to service request for component ${renderingDefinition}`
108
+ );
109
+ } else {
110
+ component = componentMap.get(renderingDefinition.componentName);
111
+ }
112
+
113
+ if (!component) {
114
+ // Fallback/defaults for Sitecore Component renderings (in case not defined in component map)
115
+ // if (renderingDefinition.componentName === FEAAS_COMPONENT_RENDERING_NAME) {
116
+ // return {
117
+ // component: FEaaSComponent,
118
+ // isEmpty: false,
119
+ // };
120
+ // } else if (renderingDefinition.componentName === FEAAS_WRAPPER_RENDERING_NAME) {
121
+ // return {
122
+ // component: FEaaSWrapper,
123
+ // isEmpty: false,
124
+ // };
125
+ // } else if (renderingDefinition.componentName === BYOC_COMPONENT_RENDERING_NAME) {
126
+ // return {
127
+ // component: BYOCComponent,
128
+ // isEmpty: false,
129
+ // };
130
+ // } else if (renderingDefinition.componentName === BYOC_WRAPPER_RENDERING_NAME) {
131
+ // // wrapping with error boundary could cause problems in case where parent component uses withPlaceholder HOC and tries to access its children props
132
+ // // that's why we need to mark BYOC wrapper dynamic
133
+ // return {
134
+ // component: BYOCWrapper,
135
+ // isEmpty: false,
136
+ // };
137
+ // }
138
+
139
+ logUnknownComponentError();
140
+
141
+ return {
142
+ component: missingComponentComponent ?? MissingComponent,
143
+ isEmpty: true,
144
+ };
145
+ }
146
+
147
+ return {
148
+ component,
149
+ isEmpty: false
150
+ }
151
+ };
152
+
153
+ ---
@@ -0,0 +1,5 @@
1
+ // @ts-ignore
2
+ export { Placeholder, PlaceholderComponent } from './Placeholder.astro';
3
+ // @ts-ignore
4
+ export { PlaceholderMetadata } from './PlaceholderMetadata.astro';
5
+ export { PlaceholderProps } from './models';