@exdst-sitecore-content-sdk/astro 0.0.16 → 0.0.19
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/README.md +3 -3
- package/package.json +41 -42
- package/src/client/index.ts +1 -1
- package/src/client/sitecore-astro-client.test.ts +41 -20
- package/src/client/sitecore-astro-client.ts +74 -57
- package/src/components/AstroImage.astro +2 -2
- package/src/components/AstroImage.astro.test.ts +542 -0
- package/src/components/Date.astro +5 -1
- package/src/components/Date.astro.test.ts +197 -0
- package/src/components/DefaultEmptyFieldEditingComponentImage.astro +4 -0
- package/src/components/DefaultEmptyFieldEditingComponentText.astro +4 -0
- package/src/components/EditingScripts.astro +2 -2
- package/src/components/EditingScripts.astro.test.ts +267 -0
- package/src/components/ErrorBoundary.astro +8 -9
- package/src/components/ErrorBoundary.astro.test.ts +252 -0
- package/src/components/ErrorComponent.astro +16 -0
- package/src/components/ErrorComponent.astro.test.ts +31 -0
- package/src/components/FieldMetadata.astro +1 -1
- package/src/components/FieldMetadata.astro.test.ts +40 -0
- package/src/components/File.astro +5 -1
- package/src/components/File.astro.test.ts +68 -0
- package/src/components/HiddenRendering.astro.test.ts +36 -0
- package/src/components/Image.astro +18 -4
- package/src/components/Image.astro.test.ts +438 -0
- package/src/components/Link.astro +13 -1
- package/src/components/Link.astro.test.ts +261 -0
- package/src/components/MissingComponent.astro.test.ts +21 -0
- package/src/components/Placeholder/Placeholder.astro +18 -23
- package/src/components/Placeholder/Placeholder.astro.test.ts +1088 -0
- package/src/components/Placeholder/PlaceholderMetadata.astro +24 -18
- package/src/components/Placeholder/PlaceholderMetadata.astro.test.ts +228 -0
- package/src/components/Placeholder/PlaceholderUtils.astro +21 -40
- package/src/components/Placeholder/PlaceholderUtils.astro.test.ts +149 -0
- package/src/components/Placeholder/models.ts +26 -17
- package/src/components/Placeholder/placeholder-utils.test.ts +153 -6
- package/src/components/Placeholder/placeholder-utils.ts +33 -11
- package/src/components/RichText.astro +9 -1
- package/src/components/RichText.astro.test.ts +205 -0
- package/src/components/Text.astro +15 -3
- package/src/components/Text.astro.test.ts +273 -0
- package/src/config/define-config.test.ts +5 -5
- package/src/config/define-config.ts +22 -42
- package/src/config-cli/define-cli-config.test.ts +5 -12
- package/src/config-cli/define-cli-config.ts +4 -8
- package/src/context.ts +42 -11
- package/src/debug.ts +13 -0
- package/src/editing/editing-config-middleware.test.ts +5 -7
- package/src/editing/editing-config-middleware.ts +11 -7
- package/src/editing/editing-render-middleware.test.ts +366 -24
- package/src/editing/editing-render-middleware.ts +34 -12
- package/src/editing/index.ts +2 -0
- package/src/editing/render-middleware.test.ts +1 -1
- package/src/editing/render-middleware.ts +1 -1
- package/src/editing/types.ts +39 -0
- package/src/editing/utils.test.ts +364 -4
- package/src/editing/utils.ts +82 -24
- package/src/enhancers/WithEmptyFieldEditingComponent.astro +1 -1
- package/src/enhancers/WithEmptyFieldEditingComponent.astro.test.ts +380 -0
- package/src/enhancers/WithFieldMetadata.astro.test.ts +113 -0
- package/src/index.ts +10 -7
- package/src/middleware/index.ts +4 -12
- package/src/middleware/middleware.test.ts +13 -0
- package/src/middleware/middleware.ts +12 -3
- package/src/middleware/multisite-middleware.test.ts +45 -50
- package/src/middleware/multisite-middleware.ts +33 -6
- package/src/middleware/robots-middleware.test.ts +20 -4
- package/src/middleware/robots-middleware.ts +10 -3
- package/src/middleware/sitemap-middleware.test.ts +35 -3
- package/src/middleware/sitemap-middleware.ts +7 -6
- package/src/services/component-props-service.ts +7 -6
- package/src/sharedTypes/component-props.ts +15 -4
- package/src/site/index.ts +1 -1
- package/src/tests/astro-helpers.ts +61 -0
- package/src/tests/test-components/CustomErrorComponent.astro +3 -0
- package/src/tests/test-components/CustomHiddenRendering.astro +10 -0
- package/src/tests/test-components/CustomMissingComponent.astro +9 -0
- package/src/tests/test-components/DownloadCallout.astro +12 -0
- package/src/tests/test-components/EmptyFieldEditingComponent.astro +5 -0
- package/src/tests/test-components/ErrorBoundaryWithError.astro +10 -0
- package/src/tests/test-components/Home.astro +12 -0
- package/src/tests/test-components/SxaRichText.astro +23 -0
- package/src/tests/test-components/SxaRichTextDefault.astro +7 -0
- package/src/tests/test-components/SxaRichTextWithTitle.astro +8 -0
- package/src/tests/test-components/TestComponent.astro +9 -0
- package/src/tests/test-components/TestComponentWithError.astro +4 -0
- package/src/tests/test-components/TestComponentWithField.astro +17 -0
- package/src/tests/test-components/TestHeader.astro +8 -0
- package/src/tests/test-components/TestLogo.astro +5 -0
- package/src/tests/test-components/TestParentWrapperComponent.astro +5 -0
- package/src/tests/test-components/TestWrapperComponent.astro +5 -0
- package/src/tests/test-data/metadata-data.ts +86 -0
- package/src/tests/test-data/normal-mode-data.ts +466 -0
- package/src/tests/vitest.setup.ts +4 -0
- package/src/tools/generate-map.ts +4 -3
- package/src/tools/index.ts +2 -4
- package/src/tools/templating/components.test.ts +100 -87
- package/src/tools/templating/components.ts +2 -1
- package/src/tools/templating/default-component.ts +3 -8
- package/src/utils/utils.ts +20 -2
- /package/src/{test-data → tests}/helpers.ts +0 -0
- /package/src/{test-data → tests}/personalizeData.ts +0 -0
- /package/src/{test-data/components → tests/test-components/map-components}/Bar.astro +0 -0
- /package/src/{test-data/components → tests/test-components/map-components}/Baz.astro +0 -0
- /package/src/{test-data/components → tests/test-components/map-components}/Foo.astro +0 -0
- /package/src/{test-data/components → tests/test-components/map-components}/Hero.variant.astro +0 -0
- /package/src/{test-data/components → tests/test-components/map-components}/NotComponent.bsx +0 -0
- /package/src/{test-data/components → tests/test-components/map-components}/Qux.astro +0 -0
- /package/src/{test-data/components → tests/test-components/map-components}/folded/Folded.astro +0 -0
- /package/src/{test-data/components → tests/test-components/map-components}/folded/random-file-2.docx +0 -0
- /package/src/{test-data/components → tests/test-components/map-components}/random-file.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
2
|
/**
|
|
3
3
|
* An Astro component to generate metadata blocks for a placeholder or rendering.
|
|
4
4
|
* It utilizes dynamic attributes based on whether the component acts as a placeholder
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
ComponentRendering,
|
|
10
10
|
getDynamicPlaceholderPattern,
|
|
11
11
|
isDynamicPlaceholder,
|
|
12
|
-
} from '@sitecore-content-sdk/
|
|
12
|
+
} from '@sitecore-content-sdk/content/layout';
|
|
13
13
|
import {
|
|
14
14
|
MetadataKind,
|
|
15
15
|
DEFAULT_PLACEHOLDER_UID,
|
|
16
|
-
} from '@sitecore-content-sdk/
|
|
16
|
+
} from '@sitecore-content-sdk/content/editing';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Props containing the component data to render.
|
|
@@ -21,6 +21,10 @@ import {
|
|
|
21
21
|
export interface PlaceholderMetadataProps {
|
|
22
22
|
rendering: ComponentRendering;
|
|
23
23
|
placeholderName?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Component runtime type. Used to add data-csdk-component-runtime attribute to rendering chromes
|
|
26
|
+
*/
|
|
27
|
+
componentRuntime?: 'server';
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
export type CodeBlockAttributes = {
|
|
@@ -29,15 +33,20 @@ export type CodeBlockAttributes = {
|
|
|
29
33
|
className: string;
|
|
30
34
|
kind: string;
|
|
31
35
|
id?: string;
|
|
36
|
+
'data-csdk-component-runtime'?: 'server';
|
|
32
37
|
};
|
|
33
38
|
|
|
34
39
|
const props = Astro.props as PlaceholderMetadataProps;
|
|
35
40
|
|
|
36
|
-
const getCodeBlockAttributes = (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
const getCodeBlockAttributes = ({
|
|
42
|
+
kind,
|
|
43
|
+
id,
|
|
44
|
+
placeholderName,
|
|
45
|
+
}: {
|
|
46
|
+
kind: MetadataKind;
|
|
47
|
+
id?: string;
|
|
48
|
+
placeholderName?: string;
|
|
49
|
+
}): CodeBlockAttributes => {
|
|
41
50
|
const chrometype = placeholderName ? 'placeholder' : 'rendering';
|
|
42
51
|
|
|
43
52
|
const attributes: CodeBlockAttributes = {
|
|
@@ -79,6 +88,11 @@ const getCodeBlockAttributes = (
|
|
|
79
88
|
} else {
|
|
80
89
|
attributes.id = id;
|
|
81
90
|
}
|
|
91
|
+
|
|
92
|
+
// Add component runtime attribute for rendering chromes
|
|
93
|
+
if (chrometype === 'rendering' && props.componentRuntime) {
|
|
94
|
+
attributes['data-csdk-component-runtime'] = 'server';
|
|
95
|
+
}
|
|
82
96
|
}
|
|
83
97
|
|
|
84
98
|
return attributes;
|
|
@@ -87,16 +101,8 @@ const getCodeBlockAttributes = (
|
|
|
87
101
|
|
|
88
102
|
<>
|
|
89
103
|
<code
|
|
90
|
-
{...getCodeBlockAttributes(
|
|
91
|
-
MetadataKind.Open,
|
|
92
|
-
props.rendering.uid,
|
|
93
|
-
props.placeholderName
|
|
94
|
-
)}></code>
|
|
104
|
+
{...getCodeBlockAttributes({ kind: MetadataKind.Open, id: props.rendering.uid, placeholderName: props.placeholderName })}></code>
|
|
95
105
|
<slot />
|
|
96
106
|
<code
|
|
97
|
-
{...getCodeBlockAttributes(
|
|
98
|
-
MetadataKind.Close,
|
|
99
|
-
props.rendering.uid,
|
|
100
|
-
props.placeholderName
|
|
101
|
-
)}></code>
|
|
107
|
+
{...getCodeBlockAttributes({ kind: MetadataKind.Close, placeholderName: props.placeholderName })}></code>
|
|
102
108
|
</>
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest';
|
|
2
|
+
import { renderAstroComponent } from '../../tests/astro-helpers';
|
|
3
|
+
import PlaceholderMetadata from './PlaceholderMetadata.astro';
|
|
4
|
+
|
|
5
|
+
describe('PlaceholderMetadata', () => {
|
|
6
|
+
test('renders rendering code blocks for metadataType rendering', async () => {
|
|
7
|
+
const children = '<div class="richtext-class"></div>';
|
|
8
|
+
|
|
9
|
+
const wrapper = await renderAstroComponent(PlaceholderMetadata, {
|
|
10
|
+
props: { rendering: { uid: '123', componentName: 'RichText' } },
|
|
11
|
+
slots: {
|
|
12
|
+
default: children,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect(wrapper.innerHTML).to.equal(
|
|
17
|
+
[
|
|
18
|
+
'<code type="text/sitecore" chrometype="rendering" class="scpm" kind="open" id="123"></code>',
|
|
19
|
+
'<div class="richtext-class"></div>',
|
|
20
|
+
'<code type="text/sitecore" chrometype="rendering" class="scpm" kind="close"></code>',
|
|
21
|
+
].join('')
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('renders placeholder code blocks when metadataType is placeholder', async () => {
|
|
26
|
+
const children = '<div class="richtext-mock"></div>';
|
|
27
|
+
|
|
28
|
+
const wrapper = await renderAstroComponent(PlaceholderMetadata, {
|
|
29
|
+
props: {
|
|
30
|
+
rendering: {
|
|
31
|
+
uid: '123',
|
|
32
|
+
componentName: 'RichText',
|
|
33
|
+
placeholders: { main: [] },
|
|
34
|
+
},
|
|
35
|
+
placeholderName: 'main',
|
|
36
|
+
},
|
|
37
|
+
slots: {
|
|
38
|
+
default: children,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
expect(wrapper.innerHTML).to.equal(
|
|
43
|
+
[
|
|
44
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="open" id="main_123"></code>',
|
|
45
|
+
'<div class="richtext-mock"></div>',
|
|
46
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="close"></code>',
|
|
47
|
+
].join('')
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('renders placeholder code blocks with DEFAULT_PLACEHOLDER_UID value when metadataType is a placeholder(root) and uid is not present', async () => {
|
|
52
|
+
const children = '<div class="richtext-mock"></div>';
|
|
53
|
+
|
|
54
|
+
const wrapper = await renderAstroComponent(PlaceholderMetadata, {
|
|
55
|
+
props: {
|
|
56
|
+
rendering: {
|
|
57
|
+
componentName: 'RichText',
|
|
58
|
+
placeholders: { main: [] },
|
|
59
|
+
},
|
|
60
|
+
placeholderName: 'main',
|
|
61
|
+
},
|
|
62
|
+
slots: {
|
|
63
|
+
default: children,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
expect(wrapper.innerHTML).to.equal(
|
|
68
|
+
[
|
|
69
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="open" id="main_00000000-0000-0000-0000-000000000000"></code>',
|
|
70
|
+
'<div class="richtext-mock"></div>',
|
|
71
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="close"></code>',
|
|
72
|
+
].join('')
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('renders placeholder blocks with rendering uid when metadataType is dynamic placeholder', async () => {
|
|
77
|
+
const children = '<div class="richtext-mock"></div>';
|
|
78
|
+
|
|
79
|
+
const wrapper = await renderAstroComponent(PlaceholderMetadata, {
|
|
80
|
+
props: {
|
|
81
|
+
rendering: {
|
|
82
|
+
uid: 'renderinguid',
|
|
83
|
+
componentName: 'RichText',
|
|
84
|
+
placeholders: { 'main-{*}': [] },
|
|
85
|
+
},
|
|
86
|
+
placeholderName: 'main-1',
|
|
87
|
+
},
|
|
88
|
+
slots: {
|
|
89
|
+
default: children,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
expect(wrapper.innerHTML).to.equal(
|
|
94
|
+
[
|
|
95
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="open" id="main-{*}_renderinguid"></code>',
|
|
96
|
+
'<div class="richtext-mock"></div>',
|
|
97
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="close"></code>',
|
|
98
|
+
].join('')
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('renders placeholder blocks with DEFAULT_PLACEHOLDER_UID value when metadataType is dynamic placeholder and uid is not present', async () => {
|
|
103
|
+
const children = '<div class="richtext-mock"></div>';
|
|
104
|
+
|
|
105
|
+
const wrapper = await renderAstroComponent(PlaceholderMetadata, {
|
|
106
|
+
props: {
|
|
107
|
+
rendering: {
|
|
108
|
+
componentName: 'RichText',
|
|
109
|
+
placeholders: { 'main-{*}': [] },
|
|
110
|
+
},
|
|
111
|
+
placeholderName: 'main-1',
|
|
112
|
+
},
|
|
113
|
+
slots: {
|
|
114
|
+
default: children,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
expect(wrapper.innerHTML).to.equal(
|
|
119
|
+
[
|
|
120
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="open" id="main-{*}_00000000-0000-0000-0000-000000000000"></code>',
|
|
121
|
+
'<div class="richtext-mock"></div>',
|
|
122
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="close"></code>',
|
|
123
|
+
].join('')
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('renders placeholder code blocks when metadataType is double digit dynamic placeholder', async () => {
|
|
128
|
+
const children = '<div class="richtext-mock"></div>';
|
|
129
|
+
|
|
130
|
+
const wrapper = await renderAstroComponent(PlaceholderMetadata, {
|
|
131
|
+
props: {
|
|
132
|
+
rendering: {
|
|
133
|
+
uid: 'renderinguid',
|
|
134
|
+
componentName: 'RichText',
|
|
135
|
+
placeholders: { 'main-1-{*}': [] },
|
|
136
|
+
},
|
|
137
|
+
placeholderName: 'main-1-1',
|
|
138
|
+
},
|
|
139
|
+
slots: {
|
|
140
|
+
default: children,
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
expect(wrapper.innerHTML).to.equal(
|
|
145
|
+
[
|
|
146
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="open" id="main-1-{*}_renderinguid"></code>',
|
|
147
|
+
'<div class="richtext-mock"></div>',
|
|
148
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="close"></code>',
|
|
149
|
+
].join('')
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('adds data-csdk-component-runtime attribute to rendering chrome', async () => {
|
|
154
|
+
const children = '<div class="richtext-class"></div>';
|
|
155
|
+
|
|
156
|
+
const wrapper = await renderAstroComponent(PlaceholderMetadata, {
|
|
157
|
+
props: {
|
|
158
|
+
rendering: {
|
|
159
|
+
uid: '123',
|
|
160
|
+
componentName: 'RichText',
|
|
161
|
+
},
|
|
162
|
+
componentRuntime: 'server',
|
|
163
|
+
},
|
|
164
|
+
slots: {
|
|
165
|
+
default: children,
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
expect(wrapper.innerHTML).to.equal(
|
|
170
|
+
[
|
|
171
|
+
'<code type="text/sitecore" chrometype="rendering" class="scpm" kind="open" id="123" data-csdk-component-runtime="server"></code>',
|
|
172
|
+
'<div class="richtext-class"></div>',
|
|
173
|
+
'<code type="text/sitecore" chrometype="rendering" class="scpm" kind="close"></code>',
|
|
174
|
+
].join('')
|
|
175
|
+
);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test('does not add data-csdk-component-runtime attribute to placeholder chrome even when componentRuntime is provided', async () => {
|
|
179
|
+
const children = '<div class="richtext-mock"></div>';
|
|
180
|
+
|
|
181
|
+
const wrapper = await renderAstroComponent(PlaceholderMetadata, {
|
|
182
|
+
props: {
|
|
183
|
+
rendering: {
|
|
184
|
+
uid: '123',
|
|
185
|
+
componentName: 'RichText',
|
|
186
|
+
placeholders: { main: [] },
|
|
187
|
+
},
|
|
188
|
+
componentRuntime: 'server',
|
|
189
|
+
placeholderName: 'main',
|
|
190
|
+
},
|
|
191
|
+
slots: {
|
|
192
|
+
default: children,
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
expect(wrapper.innerHTML).to.equal(
|
|
197
|
+
[
|
|
198
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="open" id="main_123"></code>',
|
|
199
|
+
'<div class="richtext-mock"></div>',
|
|
200
|
+
'<code type="text/sitecore" chrometype="placeholder" class="scpm" kind="close"></code>',
|
|
201
|
+
].join('')
|
|
202
|
+
);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test('does not add data-csdk-component-runtime attribute when componentRuntime is not provided', async () => {
|
|
206
|
+
const children = '<div class="richtext-class"></div>';
|
|
207
|
+
|
|
208
|
+
const wrapper = await renderAstroComponent(PlaceholderMetadata, {
|
|
209
|
+
props: {
|
|
210
|
+
rendering: {
|
|
211
|
+
uid: '123',
|
|
212
|
+
componentName: 'RichText',
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
slots: {
|
|
216
|
+
default: children,
|
|
217
|
+
},
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
expect(wrapper.innerHTML).to.equal(
|
|
221
|
+
[
|
|
222
|
+
'<code type="text/sitecore" chrometype="rendering" class="scpm" kind="open" id="123"></code>',
|
|
223
|
+
'<div class="richtext-class"></div>',
|
|
224
|
+
'<code type="text/sitecore" chrometype="rendering" class="scpm" kind="close"></code>',
|
|
225
|
+
].join('')
|
|
226
|
+
);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
@@ -1,37 +1,31 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { ComponentRendering } from "@sitecore-content-sdk/
|
|
3
|
-
import { constants } from '@sitecore-content-sdk/core';
|
|
2
|
+
import { ComponentRendering } from "@sitecore-content-sdk/content/layout";
|
|
4
3
|
import EmptyRendering from "../EmptyRendering.astro";
|
|
5
4
|
import HiddenRendering from "../HiddenRendering.astro";
|
|
6
5
|
import MissingComponent from "../MissingComponent.astro";
|
|
7
|
-
import {
|
|
6
|
+
import { getChildComponentProps } from "./placeholder-utils";
|
|
8
7
|
import { ComponentForRendering, PlaceholderProps } from "./models";
|
|
9
8
|
import { AstroContentSdkComponent, ComponentMap } from "../../sharedTypes/component-props";
|
|
9
|
+
import { HIDDEN_RENDERING_NAME } from "@sitecore-content-sdk/content";
|
|
10
10
|
import { useComponentMap } from "../../context";
|
|
11
11
|
|
|
12
|
-
export const
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
export const getPlaceholderComponents = (
|
|
13
|
+
placeholderProps: PlaceholderProps,
|
|
14
|
+
placeholderRenderings: ComponentRendering[],
|
|
15
15
|
) => {
|
|
16
|
+
|
|
16
17
|
const {
|
|
17
18
|
name,
|
|
18
|
-
|
|
19
|
-
params: placeholderParams,
|
|
19
|
+
rendering,
|
|
20
20
|
missingComponentComponent,
|
|
21
21
|
hiddenRenderingComponent,
|
|
22
|
-
|
|
23
|
-
} =
|
|
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 };
|
|
22
|
+
modifyComponentProps,
|
|
23
|
+
} = placeholderProps;
|
|
31
24
|
|
|
32
|
-
|
|
33
|
-
const componentMap = useComponentMap();
|
|
25
|
+
const componentMap = useComponentMap();
|
|
34
26
|
|
|
27
|
+
const transformedComponents = placeholderRenderings
|
|
28
|
+
.map((componentRendering: ComponentRendering) => {
|
|
35
29
|
const component = getComponentForRendering(
|
|
36
30
|
componentRendering,
|
|
37
31
|
name,
|
|
@@ -39,28 +33,15 @@ export const getComponentsForRenderingData = (
|
|
|
39
33
|
hiddenRenderingComponent,
|
|
40
34
|
missingComponentComponent
|
|
41
35
|
);
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
};
|
|
36
|
+
|
|
37
|
+
const renderedProps = modifyComponentProps
|
|
38
|
+
? modifyComponentProps(getChildComponentProps(placeholderProps, componentRendering))
|
|
39
|
+
: getChildComponentProps(placeholderProps, componentRendering);
|
|
59
40
|
|
|
60
41
|
let components = {
|
|
61
42
|
component: component,
|
|
62
|
-
props:
|
|
63
|
-
rendering:
|
|
43
|
+
props: renderedProps,
|
|
44
|
+
rendering: componentRendering,
|
|
64
45
|
placeholderName: name
|
|
65
46
|
};
|
|
66
47
|
|
|
@@ -90,7 +71,7 @@ export const getComponentForRendering = (
|
|
|
90
71
|
|
|
91
72
|
let component;
|
|
92
73
|
|
|
93
|
-
if (renderingDefinition.componentName ===
|
|
74
|
+
if (renderingDefinition.componentName === HIDDEN_RENDERING_NAME) {
|
|
94
75
|
return {
|
|
95
76
|
component: hiddenRenderingComponent ?? HiddenRendering,
|
|
96
77
|
isEmpty: true
|
|
@@ -128,7 +109,7 @@ export const getComponentForRendering = (
|
|
|
128
109
|
// isEmpty: false,
|
|
129
110
|
// };
|
|
130
111
|
// } else if (renderingDefinition.componentName === BYOC_WRAPPER_RENDERING_NAME) {
|
|
131
|
-
// // wrapping with error boundary could cause problems in case where parent component uses withPlaceholder
|
|
112
|
+
// // wrapping with error boundary could cause problems in case where parent component uses withPlaceholder HOCs and tries to access its children props
|
|
132
113
|
// // that's why we need to mark BYOC wrapper dynamic
|
|
133
114
|
// return {
|
|
134
115
|
// component: BYOCWrapper,
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/* eslint-disable no-unused-expressions */
|
|
2
|
+
import { describe, test, expect, beforeEach, afterEach } from 'vitest';
|
|
3
|
+
import { ComponentRendering } from '@sitecore-content-sdk/content/layout';
|
|
4
|
+
import { ComponentMap } from '../../sharedTypes/component-props';
|
|
5
|
+
import { createSandbox } from 'sinon';
|
|
6
|
+
import { getComponentForRendering } from './PlaceholderUtils.astro';
|
|
7
|
+
import MissingComponent from '../MissingComponent.astro';
|
|
8
|
+
import HiddenRendering from '../HiddenRendering.astro';
|
|
9
|
+
import TestComponent from '../../tests/test-components/TestComponent.astro';
|
|
10
|
+
import CustomMissingComponent from '../../tests/test-components/CustomMissingComponent.astro';
|
|
11
|
+
import CustomHiddenRendering from '../../tests/test-components/CustomHiddenRendering.astro';
|
|
12
|
+
import { HIDDEN_RENDERING_NAME } from '@sitecore-content-sdk/content';
|
|
13
|
+
|
|
14
|
+
describe('placeholder-utils', () => {
|
|
15
|
+
const sandbox = createSandbox();
|
|
16
|
+
let consoleWarnStub: ReturnType<typeof sandbox.stub>;
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
consoleWarnStub = sandbox.stub(console, 'warn');
|
|
20
|
+
sandbox.stub(console, 'error');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
sandbox.restore();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('getComponentForRendering', () => {
|
|
28
|
+
let componentMap: ComponentMap;
|
|
29
|
+
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
componentMap = new Map();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('should return null when componentMap is empty', () => {
|
|
35
|
+
const rendering: ComponentRendering = {
|
|
36
|
+
componentName: 'TestComponent',
|
|
37
|
+
uid: 'test-uid',
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const result = getComponentForRendering(rendering, 'test-placeholder');
|
|
41
|
+
|
|
42
|
+
expect(result?.component).to.equal(MissingComponent);
|
|
43
|
+
expect(result?.isEmpty).to.be.true;
|
|
44
|
+
expect(consoleWarnStub.calledOnce).to.be.true;
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('should return null when componentMap is not provided', () => {
|
|
48
|
+
const rendering: ComponentRendering = {
|
|
49
|
+
componentName: 'TestComponent',
|
|
50
|
+
uid: 'test-uid',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const result = getComponentForRendering(rendering, 'test-placeholder', undefined);
|
|
54
|
+
|
|
55
|
+
expect(result?.component).to.equal(MissingComponent);
|
|
56
|
+
expect(result?.isEmpty).to.be.true;
|
|
57
|
+
expect(consoleWarnStub.calledOnce).to.be.true;
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('should return component directly when it is not a module', () => {
|
|
61
|
+
componentMap.set('TestComponent', TestComponent);
|
|
62
|
+
|
|
63
|
+
const rendering: ComponentRendering = {
|
|
64
|
+
componentName: 'TestComponent',
|
|
65
|
+
uid: 'test-uid',
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const result = getComponentForRendering(rendering, 'test-placeholder', componentMap);
|
|
69
|
+
|
|
70
|
+
expect(result?.component).to.equal(TestComponent);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test('should return default missing component when component not found in component map', () => {
|
|
74
|
+
// Add a dummy entry so componentMap is not empty
|
|
75
|
+
componentMap.set('DummyComponent', TestComponent);
|
|
76
|
+
|
|
77
|
+
const rendering: ComponentRendering = {
|
|
78
|
+
componentName: 'NonExistentComponent',
|
|
79
|
+
uid: 'test-uid',
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const result = getComponentForRendering(rendering, 'test-placeholder', componentMap);
|
|
83
|
+
|
|
84
|
+
expect(result?.component).to.equal(MissingComponent);
|
|
85
|
+
expect(result?.isEmpty).to.be.true;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('should return custom missing component when specified and component not found in component map', () => {
|
|
89
|
+
// Add a dummy entry so componentMap is not empty
|
|
90
|
+
componentMap.set('DummyComponent', TestComponent);
|
|
91
|
+
|
|
92
|
+
const rendering: ComponentRendering = {
|
|
93
|
+
componentName: 'NonExistentComponent',
|
|
94
|
+
uid: 'test-uid',
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const result = getComponentForRendering(
|
|
98
|
+
rendering,
|
|
99
|
+
'test-placeholder',
|
|
100
|
+
componentMap,
|
|
101
|
+
undefined,
|
|
102
|
+
CustomMissingComponent
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
expect(result?.component).to.equal(CustomMissingComponent);
|
|
106
|
+
expect(result?.isEmpty).to.be.true;
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('should return hiddenRenderingComponent when component is hidden', () => {
|
|
110
|
+
const rendering: ComponentRendering = {
|
|
111
|
+
componentName: HIDDEN_RENDERING_NAME,
|
|
112
|
+
uid: 'test-uid',
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const result = getComponentForRendering(
|
|
116
|
+
rendering,
|
|
117
|
+
'test-placeholder',
|
|
118
|
+
componentMap,
|
|
119
|
+
CustomHiddenRendering
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
expect(result?.component).to.equal(CustomHiddenRendering);
|
|
123
|
+
expect(result?.isEmpty).to.be.true;
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('should return default HiddenRendering when component is hidden and no custom hidden component provided', () => {
|
|
127
|
+
const rendering: ComponentRendering = {
|
|
128
|
+
componentName: HIDDEN_RENDERING_NAME,
|
|
129
|
+
uid: 'test-uid',
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const result = getComponentForRendering(rendering, 'test-placeholder', componentMap);
|
|
133
|
+
|
|
134
|
+
expect(result?.component).to.equal(HiddenRendering);
|
|
135
|
+
expect(result?.isEmpty).to.be.true;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test('should handle rendering without componentName', () => {
|
|
139
|
+
const rendering: ComponentRendering = {
|
|
140
|
+
componentName: '',
|
|
141
|
+
uid: 'test-uid',
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const result = getComponentForRendering(rendering, 'test-placeholder', componentMap);
|
|
145
|
+
|
|
146
|
+
expect(result?.isEmpty).to.be.true;
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import { Page } from '@sitecore-content-sdk/
|
|
1
|
+
import { Page } from '@sitecore-content-sdk/content/client';
|
|
2
2
|
import { AstroContentSdkComponent } from '../../sharedTypes/component-props';
|
|
3
|
-
import { ComponentRendering, Field, Item, RouteData } from '@sitecore-content-sdk/
|
|
4
|
-
|
|
5
|
-
/** Provided for the component which represents rendering data */
|
|
6
|
-
export type ComponentProps = {
|
|
7
|
-
[key: string]: unknown;
|
|
8
|
-
rendering: ComponentRendering;
|
|
9
|
-
};
|
|
3
|
+
import { ComponentRendering, Field, Item, RouteData } from '@sitecore-content-sdk/content/layout';
|
|
10
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Base Placeholder props
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
11
9
|
export interface PlaceholderProps {
|
|
12
|
-
[key: string]: unknown;
|
|
13
10
|
/** Name of the placeholder to render. */
|
|
14
11
|
name: string;
|
|
15
12
|
/** Rendering data to be used when rendering the placeholder. */
|
|
@@ -28,13 +25,7 @@ export interface PlaceholderProps {
|
|
|
28
25
|
params?: {
|
|
29
26
|
[name: string]: string;
|
|
30
27
|
};
|
|
31
|
-
|
|
32
|
-
* Modify final props of component (before render) provided by rendering data.
|
|
33
|
-
* Can be used in case when you need to insert additional data into the component.
|
|
34
|
-
* @param {ComponentProps} componentProps component props to be modified
|
|
35
|
-
* @returns {ComponentProps} modified or initial props
|
|
36
|
-
*/
|
|
37
|
-
modifyComponentProps?: (componentProps: ComponentProps) => ComponentProps;
|
|
28
|
+
|
|
38
29
|
/**
|
|
39
30
|
* A component that is rendered in place of any components that are in this placeholder,
|
|
40
31
|
* but do not have a definition in the componentMap (i.e. don't have an implementation)
|
|
@@ -55,7 +46,7 @@ export interface PlaceholderProps {
|
|
|
55
46
|
* Page data.
|
|
56
47
|
* This data is passed by the SitecoreProvider.
|
|
57
48
|
*/
|
|
58
|
-
page
|
|
49
|
+
page?: Page;
|
|
59
50
|
|
|
60
51
|
/**
|
|
61
52
|
* Render HTML or an Astro component when the placeholder contains no content components.
|
|
@@ -74,6 +65,24 @@ export interface PlaceholderProps {
|
|
|
74
65
|
* Mutually exclusive with `render`.
|
|
75
66
|
*/
|
|
76
67
|
renderEach?: string | AstroContentSdkComponent;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Modify final props of component (before render) provided by rendering data.
|
|
71
|
+
* Can be used in case when you need to insert additional data into the component.
|
|
72
|
+
* @param {ChildComponentProps} componentProps component props to be modified
|
|
73
|
+
* @returns {ChildComponentProps} modified or initial props
|
|
74
|
+
*/
|
|
75
|
+
modifyComponentProps?: (componentProps: ChildComponentProps) => ChildComponentProps;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface ChildComponentProps {
|
|
79
|
+
fields: {
|
|
80
|
+
[name: string]: Field | Item | Item[];
|
|
81
|
+
};
|
|
82
|
+
params: {
|
|
83
|
+
[name: string]: string;
|
|
84
|
+
};
|
|
85
|
+
rendering: ComponentRendering;
|
|
77
86
|
}
|
|
78
87
|
|
|
79
88
|
export interface ComponentForRendering {
|