@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.
- package/LICENSE.txt +202 -0
- package/README.md +3 -0
- package/package.json +101 -0
- package/src/client/index.ts +12 -0
- package/src/client/sitecore-astro-client.test.ts +271 -0
- package/src/client/sitecore-astro-client.ts +137 -0
- package/src/components/AstroImage.astro +114 -0
- package/src/components/Date.astro +76 -0
- package/src/components/DefaultEmptyFieldEditingComponentImage.astro +24 -0
- package/src/components/DefaultEmptyFieldEditingComponentText.astro +12 -0
- package/src/components/EditingScripts.astro +49 -0
- package/src/components/EmptyRendering.astro +3 -0
- package/src/components/ErrorBoundary.astro +77 -0
- package/src/components/FieldMetadata.astro +30 -0
- package/src/components/File.astro +46 -0
- package/src/components/HiddenRendering.astro +22 -0
- package/src/components/Image.astro +155 -0
- package/src/components/Link.astro +105 -0
- package/src/components/MissingComponent.astro +39 -0
- package/src/components/Placeholder/EmptyPlaceholder.astro +9 -0
- package/src/components/Placeholder/Placeholder.astro +100 -0
- package/src/components/Placeholder/PlaceholderMetadata.astro +102 -0
- package/src/components/Placeholder/PlaceholderUtils.astro +153 -0
- package/src/components/Placeholder/index.ts +5 -0
- package/src/components/Placeholder/models.ts +82 -0
- package/src/components/Placeholder/placeholder-utils.test.ts +162 -0
- package/src/components/Placeholder/placeholder-utils.ts +80 -0
- package/src/components/RenderWrapper.astro +31 -0
- package/src/components/RichText.astro +59 -0
- package/src/components/Text.astro +97 -0
- package/src/components/sharedTypes/index.ts +1 -0
- package/src/components/sharedTypes/props.ts +17 -0
- package/src/config/define-config.test.ts +526 -0
- package/src/config/define-config.ts +99 -0
- package/src/config/index.ts +1 -0
- package/src/config-cli/define-cli-config.test.ts +95 -0
- package/src/config-cli/define-cli-config.ts +50 -0
- package/src/config-cli/index.ts +1 -0
- package/src/context.ts +68 -0
- package/src/editing/constants.ts +8 -0
- package/src/editing/editing-config-middleware.test.ts +166 -0
- package/src/editing/editing-config-middleware.ts +111 -0
- package/src/editing/editing-render-middleware.test.ts +801 -0
- package/src/editing/editing-render-middleware.ts +288 -0
- package/src/editing/index.ts +16 -0
- package/src/editing/render-middleware.test.ts +57 -0
- package/src/editing/render-middleware.ts +51 -0
- package/src/editing/utils.test.ts +852 -0
- package/src/editing/utils.ts +308 -0
- package/src/enhancers/WithEmptyFieldEditingComponent.astro +56 -0
- package/src/enhancers/WithFieldMetadata.astro +31 -0
- package/src/env.d.ts +12 -0
- package/src/index.ts +16 -0
- package/src/middleware/index.ts +24 -0
- package/src/middleware/middleware.test.ts +507 -0
- package/src/middleware/middleware.ts +167 -0
- package/src/middleware/multisite-middleware.test.ts +672 -0
- package/src/middleware/multisite-middleware.ts +147 -0
- package/src/middleware/robots-middleware.test.ts +113 -0
- package/src/middleware/robots-middleware.ts +47 -0
- package/src/middleware/sitemap-middleware.test.ts +152 -0
- package/src/middleware/sitemap-middleware.ts +65 -0
- package/src/services/component-props-service.ts +182 -0
- package/src/sharedTypes/component-props.ts +17 -0
- package/src/site/index.ts +1 -0
- package/src/test-data/components/Bar.astro +0 -0
- package/src/test-data/components/Baz.astro +0 -0
- package/src/test-data/components/Foo.astro +0 -0
- package/src/test-data/components/Hero.variant.astro +0 -0
- package/src/test-data/components/NotComponent.bsx +0 -0
- package/src/test-data/components/Qux.astro +0 -0
- package/src/test-data/components/folded/Folded.astro +0 -0
- package/src/test-data/components/folded/random-file-2.docx +0 -0
- package/src/test-data/components/random-file.txt +0 -0
- package/src/test-data/helpers.ts +46 -0
- package/src/test-data/personalizeData.ts +63 -0
- package/src/tools/generate-map.ts +83 -0
- package/src/tools/index.ts +8 -0
- package/src/tools/templating/components.test.ts +305 -0
- package/src/tools/templating/components.ts +49 -0
- package/src/tools/templating/constants.ts +4 -0
- package/src/tools/templating/default-component.test.ts +31 -0
- package/src/tools/templating/default-component.ts +63 -0
- package/src/tools/templating/index.ts +2 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/utils.test.ts +48 -0
- package/src/utils/utils.ts +52 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type ComponentPropsError = { error: string; componentName: string };
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shape of component props storage
|
|
5
|
+
*/
|
|
6
|
+
export type ComponentPropsCollection = {
|
|
7
|
+
[componentUid: string]: unknown | ComponentPropsError;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type AstroContentSdkComponent = (_props: Record<string, any>) => any;
|
|
11
|
+
|
|
12
|
+
export type PreviewData = string | false | object | undefined;
|
|
13
|
+
|
|
14
|
+
export type ComponentMap<
|
|
15
|
+
TComponent extends AstroContentSdkComponent = AstroContentSdkComponent
|
|
16
|
+
> = Map<string, TComponent>;
|
|
17
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SiteResolver, SiteInfo } from '@sitecore-content-sdk/core/site';
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export type Query = {
|
|
2
|
+
[key: string]: string | string[];
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
const baseUrl = 'https://test.com';
|
|
6
|
+
|
|
7
|
+
export const mockRequest = ({
|
|
8
|
+
url,
|
|
9
|
+
method,
|
|
10
|
+
query,
|
|
11
|
+
headers,
|
|
12
|
+
}: {
|
|
13
|
+
url?: string;
|
|
14
|
+
method?: string;
|
|
15
|
+
query?: Query;
|
|
16
|
+
headers?: { [key: string]: string };
|
|
17
|
+
}) => {
|
|
18
|
+
const requestUrl = addQueryToUrl(url || baseUrl, query);
|
|
19
|
+
return new Request(requestUrl, {
|
|
20
|
+
method,
|
|
21
|
+
headers: headers,
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const addQueryToUrl = (baseUrl: string, query?: Query): string => {
|
|
26
|
+
const url = new URL(baseUrl);
|
|
27
|
+
const params = new URLSearchParams();
|
|
28
|
+
|
|
29
|
+
if (query) {
|
|
30
|
+
Object.entries(query).forEach(([key, value]) => {
|
|
31
|
+
if (Array.isArray(value)) {
|
|
32
|
+
value.forEach((item) => {
|
|
33
|
+
params.append(key, item);
|
|
34
|
+
});
|
|
35
|
+
} else {
|
|
36
|
+
params.append(key, value);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
params.forEach((value, key) => {
|
|
41
|
+
url.searchParams.append(key, value);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return url.toString();
|
|
46
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export const mountain_bike_audience = {
|
|
2
|
+
uid: '0b6d23d8-c50e-4e79-9eca-317ec43e82b0',
|
|
3
|
+
componentName: 'ContentBlock',
|
|
4
|
+
dataSource: '20679cd4-356b-4452-b507-453beeb0be39',
|
|
5
|
+
fields: {
|
|
6
|
+
content: {
|
|
7
|
+
value:
|
|
8
|
+
'<p><img src="https://edge-beta.sitecorecloud.io/ser-edge-personalization/media/CsdkNextWeb/Mountain-Bike.jpg?h=675&w=1200" style="width:1200px;height:675px;" /></p>',
|
|
9
|
+
},
|
|
10
|
+
heading: { value: 'Mountain Bike' },
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const city_bike_audience = {
|
|
15
|
+
uid: '0b6d23d8-c50e-4e79-9eca-317ec43e82b0',
|
|
16
|
+
componentName: 'ContentBlock',
|
|
17
|
+
dataSource: '36e02581-2056-4c55-a4d5-f4b700ba1ae2',
|
|
18
|
+
fields: {
|
|
19
|
+
content: {
|
|
20
|
+
value:
|
|
21
|
+
'<p><img src="https://edge-beta.sitecorecloud.io/ser-edge-personalization/media/CsdkNextWeb/Mountain-Bike.jpg?h=675&w=1200" style="width:1200px;height:675px;" /></p>',
|
|
22
|
+
},
|
|
23
|
+
heading: { value: 'Mountain Bike' },
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const layoutData = {
|
|
28
|
+
sitecore: {
|
|
29
|
+
context: {
|
|
30
|
+
pageEditing: false,
|
|
31
|
+
site: { name: 'CsdkNextWeb' },
|
|
32
|
+
visitorIdentificationTimestamp: 1038543,
|
|
33
|
+
language: 'en',
|
|
34
|
+
variantId: undefined,
|
|
35
|
+
},
|
|
36
|
+
route: {
|
|
37
|
+
name: 'landingpage',
|
|
38
|
+
placeholders: {
|
|
39
|
+
'content-sdk-main': [
|
|
40
|
+
{
|
|
41
|
+
uid: '0b6d23d8-c50e-4e79-9eca-317ec43e82b0',
|
|
42
|
+
componentName: 'ContentBlock',
|
|
43
|
+
dataSource: 'e020fb58-1be8-4537-aab8-67916452ecf2',
|
|
44
|
+
fields: { content: { value: '' }, heading: { value: 'Default Content' } },
|
|
45
|
+
experiences: {
|
|
46
|
+
mountain_bike_audience: mountain_bike_audience,
|
|
47
|
+
city_bike_audience: city_bike_audience,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const componentWithExperiences = {
|
|
57
|
+
uid: '0b6d23d8-c50e-4e79-9eca-317ec43e82b0',
|
|
58
|
+
componentName: 'ContentBlock',
|
|
59
|
+
dataSource: '20679cd4-356b-4452-b507-453beeb0be39',
|
|
60
|
+
fields: mountain_bike_audience.fields,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const componentsWithExperiencesArray = [componentWithExperiences];
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GenerateMapArgs,
|
|
3
|
+
GenerateMapFunction,
|
|
4
|
+
ComponentMapTemplate,
|
|
5
|
+
} from '@sitecore-content-sdk/core/tools';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import { getComponentList } from './templating/components';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate and write componentMap.ts file based on provided params.
|
|
12
|
+
* @param {GenerateMapArgs} param0 params for generateMap
|
|
13
|
+
*/
|
|
14
|
+
export const generateMap: GenerateMapFunction = ({
|
|
15
|
+
paths,
|
|
16
|
+
destination = '.sitecore',
|
|
17
|
+
exclude,
|
|
18
|
+
componentImports,
|
|
19
|
+
mapTemplate = buildAstroMapContent,
|
|
20
|
+
}: GenerateMapArgs) => {
|
|
21
|
+
const components = getComponentList(paths, exclude);
|
|
22
|
+
|
|
23
|
+
const content = (mapTemplate as ComponentMapTemplate)(components, componentImports);
|
|
24
|
+
|
|
25
|
+
const componentMapFile = path.join(process.cwd(), destination, 'component-map.ts');
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
fs.writeFileSync(componentMapFile, content, {
|
|
29
|
+
encoding: 'utf8',
|
|
30
|
+
});
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error(`Component Map generation failed. Error writing to file ${destination}:`, error);
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const buildAstroMapContent: ComponentMapTemplate = (components, componentImports): string => {
|
|
38
|
+
const wildcardImports: string[] = [];
|
|
39
|
+
const namedImports: string[] = [];
|
|
40
|
+
|
|
41
|
+
const componentMapEntries: string[] = [];
|
|
42
|
+
|
|
43
|
+
components.forEach((component) => {
|
|
44
|
+
wildcardImports.push(`import ${component.moduleName} from '${component.importPath}.astro';`);
|
|
45
|
+
componentMapEntries.push(`['${component.moduleName}', ${component.moduleName}]`);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
componentImports?.forEach((packageEntry) => {
|
|
49
|
+
if (packageEntry.importInfo.namedImports) {
|
|
50
|
+
namedImports.push(
|
|
51
|
+
`import { ${packageEntry.importInfo.namedImports.join(', ')} } from '${
|
|
52
|
+
packageEntry.importInfo.importFrom
|
|
53
|
+
}.astro';`
|
|
54
|
+
);
|
|
55
|
+
packageEntry.importInfo.namedImports.forEach((importName) => {
|
|
56
|
+
componentMapEntries.push(`['${importName}', ${importName}]`);
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
wildcardImports.push(
|
|
60
|
+
`import ${packageEntry.importName} from '${packageEntry.importInfo.importFrom}';`
|
|
61
|
+
);
|
|
62
|
+
componentMapEntries.push(`['${packageEntry.importName}', ${packageEntry.importName}]`);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return `//@ts-nocheck
|
|
67
|
+
import { AstroContentSdkComponent } from '@astro-sitecore-jss/astro-content-sdk';
|
|
68
|
+
|
|
69
|
+
// Components imported from the app itself
|
|
70
|
+
${wildcardImports.join('\n')}
|
|
71
|
+
${namedImports.join('\n')}
|
|
72
|
+
|
|
73
|
+
// Components must be registered within the map to match the string key with component name in Sitecore
|
|
74
|
+
export const componentMap = new Map<string, AstroContentSdkComponent>([
|
|
75
|
+
${componentMapEntries
|
|
76
|
+
.map((component) => {
|
|
77
|
+
return ` ${component},\n`;
|
|
78
|
+
})
|
|
79
|
+
.join('')}]);
|
|
80
|
+
|
|
81
|
+
export default componentMap;
|
|
82
|
+
`;
|
|
83
|
+
};
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/* eslint-disable no-unused-expressions */
|
|
2
|
+
import { expect } from 'chai';
|
|
3
|
+
import sinon from 'sinon';
|
|
4
|
+
import { getComponentList } from './components';
|
|
5
|
+
import { ComponentFile } from '@sitecore-content-sdk/core/tools';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
|
|
8
|
+
describe('components', () => {
|
|
9
|
+
const sandbox = sinon.createSandbox();
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
sandbox.restore();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
describe('getComponentList', () => {
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
sandbox.restore();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should return results when one of "paths" is a glob pattern', () => {
|
|
20
|
+
const items = [
|
|
21
|
+
{
|
|
22
|
+
importPath: 'src/test-data/components/Qux',
|
|
23
|
+
filePath: path.normalize('src/test-data/components/Qux.astro'),
|
|
24
|
+
componentName: 'Qux',
|
|
25
|
+
moduleName: 'Qux',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
importPath: 'src/test-data/components/Foo',
|
|
29
|
+
filePath: path.normalize('src/test-data/components/Foo.astro'),
|
|
30
|
+
componentName: 'Foo',
|
|
31
|
+
moduleName: 'Foo',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
importPath: 'src/test-data/components/Baz',
|
|
35
|
+
filePath: path.normalize('src/test-data/components/Baz.astro'),
|
|
36
|
+
componentName: 'Baz',
|
|
37
|
+
moduleName: 'Baz',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
importPath: 'src/test-data/components/Bar',
|
|
41
|
+
filePath: path.normalize('src/test-data/components/Bar.astro'),
|
|
42
|
+
componentName: 'Bar',
|
|
43
|
+
moduleName: 'Bar',
|
|
44
|
+
},
|
|
45
|
+
] as ComponentFile[];
|
|
46
|
+
|
|
47
|
+
const result = getComponentList(['src/test-data/components/*.astro'], ['**/*.test.*'], false);
|
|
48
|
+
expect(result).to.deep.equal(items);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should return results with all folded paths when path is a non-glob path', () => {
|
|
52
|
+
const items = [
|
|
53
|
+
{
|
|
54
|
+
importPath: 'src/test-data/components/Qux',
|
|
55
|
+
filePath: path.normalize('src/test-data/components/Qux.astro'),
|
|
56
|
+
componentName: 'Qux',
|
|
57
|
+
moduleName: 'Qux',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
importPath: 'src/test-data/components/Foo',
|
|
61
|
+
filePath: path.normalize('src/test-data/components/Foo.astro'),
|
|
62
|
+
componentName: 'Foo',
|
|
63
|
+
moduleName: 'Foo',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
importPath: 'src/test-data/components/Baz',
|
|
67
|
+
filePath: path.normalize('src/test-data/components/Baz.astro'),
|
|
68
|
+
componentName: 'Baz',
|
|
69
|
+
moduleName: 'Baz',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
importPath: 'src/test-data/components/Bar',
|
|
73
|
+
filePath: path.normalize('src/test-data/components/Bar.astro'),
|
|
74
|
+
componentName: 'Bar',
|
|
75
|
+
moduleName: 'Bar',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
importPath: 'src/test-data/components/folded/Folded',
|
|
79
|
+
filePath: path.normalize('src/test-data/components/folded/Folded.astro'),
|
|
80
|
+
componentName: 'Folded',
|
|
81
|
+
moduleName: 'Folded',
|
|
82
|
+
},
|
|
83
|
+
] as ComponentFile[];
|
|
84
|
+
|
|
85
|
+
const result = getComponentList(['src/test-data/components'], ['**/*.test.*'], false);
|
|
86
|
+
expect(result).to.deep.equal(items);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should filter out results that are not components', () => {
|
|
90
|
+
const items = [
|
|
91
|
+
{
|
|
92
|
+
importPath: 'src/test-data/components/Qux',
|
|
93
|
+
filePath: path.normalize('src/test-data/components/Qux.astro'),
|
|
94
|
+
componentName: 'Qux',
|
|
95
|
+
moduleName: 'Qux',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
importPath: 'src/test-data/components/Foo',
|
|
99
|
+
filePath: path.normalize('src/test-data/components/Foo.astro'),
|
|
100
|
+
componentName: 'Foo',
|
|
101
|
+
moduleName: 'Foo',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
importPath: 'src/test-data/components/Baz',
|
|
105
|
+
filePath: path.normalize('src/test-data/components/Baz.astro'),
|
|
106
|
+
componentName: 'Baz',
|
|
107
|
+
moduleName: 'Baz',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
importPath: 'src/test-data/components/Bar',
|
|
111
|
+
filePath: path.normalize('src/test-data/components/Bar.astro'),
|
|
112
|
+
componentName: 'Bar',
|
|
113
|
+
moduleName: 'Bar',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
importPath: 'src/test-data/components/folded/Folded',
|
|
117
|
+
filePath: path.normalize('src/test-data/components/folded/Folded.astro'),
|
|
118
|
+
componentName: 'Folded',
|
|
119
|
+
moduleName: 'Folded',
|
|
120
|
+
},
|
|
121
|
+
] as ComponentFile[];
|
|
122
|
+
|
|
123
|
+
const result = getComponentList(['src/test-data/components/**/*']);
|
|
124
|
+
expect(result).to.deep.equal(items);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('should return result when "paths" contain exact paths to Astro components', () => {
|
|
128
|
+
const items = [
|
|
129
|
+
{
|
|
130
|
+
importPath: 'src/test-data/components/Foo',
|
|
131
|
+
filePath: path.normalize('src/test-data/components/Foo.astro'),
|
|
132
|
+
componentName: 'Foo',
|
|
133
|
+
moduleName: 'Foo',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
importPath: 'src/test-data/components/Bar',
|
|
137
|
+
filePath: path.normalize('src/test-data/components/Bar.astro'),
|
|
138
|
+
componentName: 'Bar',
|
|
139
|
+
moduleName: 'Bar',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
importPath: 'src/test-data/components/Baz',
|
|
143
|
+
filePath: path.normalize('src/test-data/components/Baz.astro'),
|
|
144
|
+
componentName: 'Baz',
|
|
145
|
+
moduleName: 'Baz',
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
importPath: 'src/test-data/components/Qux',
|
|
149
|
+
filePath: path.normalize('src/test-data/components/Qux.astro'),
|
|
150
|
+
componentName: 'Qux',
|
|
151
|
+
moduleName: 'Qux',
|
|
152
|
+
},
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
const result = getComponentList([
|
|
156
|
+
'src/test-data/components/Foo.astro',
|
|
157
|
+
'src/test-data/components/Bar.astro',
|
|
158
|
+
'src/test-data/components/Baz.astro',
|
|
159
|
+
'src/test-data/components/Qux.astro',
|
|
160
|
+
]);
|
|
161
|
+
expect(result).to.deep.equal(items);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should return filtered results when "exclude" contains a glob pattern', () => {
|
|
165
|
+
const exclude = ['**/components/**'];
|
|
166
|
+
expect(getComponentList(['src/test-data/components/*.astro'], exclude)).to.be.empty;
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('should return variants in results when includeVariants is true', () => {
|
|
170
|
+
sandbox.stub(console, 'debug');
|
|
171
|
+
|
|
172
|
+
const items = [
|
|
173
|
+
{
|
|
174
|
+
importPath: 'src/test-data/components/Qux',
|
|
175
|
+
filePath: path.normalize('src/test-data/components/Qux.astro'),
|
|
176
|
+
componentName: 'Qux',
|
|
177
|
+
moduleName: 'Qux',
|
|
178
|
+
},
|
|
179
|
+
// variant component
|
|
180
|
+
{
|
|
181
|
+
importPath: 'src/test-data/components/Hero.variant',
|
|
182
|
+
filePath: path.normalize('src/test-data/components/Hero.variant.astro'),
|
|
183
|
+
componentName: 'Hero.variant',
|
|
184
|
+
moduleName: 'Herovariant',
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
importPath: 'src/test-data/components/Foo',
|
|
188
|
+
filePath: path.normalize('src/test-data/components/Foo.astro'),
|
|
189
|
+
componentName: 'Foo',
|
|
190
|
+
moduleName: 'Foo',
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
importPath: 'src/test-data/components/Baz',
|
|
194
|
+
filePath: path.normalize('src/test-data/components/Baz.astro'),
|
|
195
|
+
componentName: 'Baz',
|
|
196
|
+
moduleName: 'Baz',
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
importPath: 'src/test-data/components/Bar',
|
|
200
|
+
filePath: path.normalize('src/test-data/components/Bar.astro'),
|
|
201
|
+
componentName: 'Bar',
|
|
202
|
+
moduleName: 'Bar',
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
importPath: 'src/test-data/components/folded/Folded',
|
|
206
|
+
filePath: path.normalize('src/test-data/components/folded/Folded.astro'),
|
|
207
|
+
componentName: 'Folded',
|
|
208
|
+
moduleName: 'Folded',
|
|
209
|
+
},
|
|
210
|
+
] as ComponentFile[];
|
|
211
|
+
|
|
212
|
+
const result = getComponentList(['src/test-data/components'], ['**/*.test.*'], true);
|
|
213
|
+
expect(result).to.deep.equal(items);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('should return filtered results when "exclude" contains an exact path', () => {
|
|
217
|
+
const exclude = ['src/test-data/components/Foo.astro'];
|
|
218
|
+
getComponentList(['src/test-data/components/*.astro'], exclude);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('should return correct result in unix file systems', () => {
|
|
222
|
+
const stubbedPaths = [
|
|
223
|
+
'src/test-data/components/Foo.astro',
|
|
224
|
+
'src/test-data/components/Bar.astro',
|
|
225
|
+
'src/test-data/components/Baz.astro',
|
|
226
|
+
'src/test-data/components/Qux.astro',
|
|
227
|
+
];
|
|
228
|
+
const expected = [
|
|
229
|
+
{
|
|
230
|
+
importPath: 'src/test-data/components/Foo',
|
|
231
|
+
filePath: 'src/test-data/components/Foo.astro',
|
|
232
|
+
componentName: 'Foo',
|
|
233
|
+
moduleName: 'Foo',
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
importPath: 'src/test-data/components/Bar',
|
|
237
|
+
filePath: 'src/test-data/components/Bar.astro',
|
|
238
|
+
componentName: 'Bar',
|
|
239
|
+
moduleName: 'Bar',
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
importPath: 'src/test-data/components/Baz',
|
|
243
|
+
filePath: 'src/test-data/components/Baz.astro',
|
|
244
|
+
componentName: 'Baz',
|
|
245
|
+
moduleName: 'Baz',
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
importPath: 'src/test-data/components/Qux',
|
|
249
|
+
filePath: 'src/test-data/components/Qux.astro',
|
|
250
|
+
componentName: 'Qux',
|
|
251
|
+
moduleName: 'Qux',
|
|
252
|
+
},
|
|
253
|
+
];
|
|
254
|
+
|
|
255
|
+
const globSyncStub = sandbox.stub(require('glob'), 'sync').returns(stubbedPaths);
|
|
256
|
+
|
|
257
|
+
const result = getComponentList(['src/test-data/components/*.astro']);
|
|
258
|
+
expect(result).to.deep.equal(expected);
|
|
259
|
+
|
|
260
|
+
globSyncStub.restore();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('should return correct result in windows file systems', () => {
|
|
264
|
+
const stubbedPaths = [
|
|
265
|
+
'src\\test-data\\components\\Foo.astro',
|
|
266
|
+
'src\\test-data\\components\\Bar.astro',
|
|
267
|
+
'src\\test-data\\components\\Baz.astro',
|
|
268
|
+
'src\\test-data\\components\\Qux.astro',
|
|
269
|
+
];
|
|
270
|
+
const expected = [
|
|
271
|
+
{
|
|
272
|
+
importPath: 'src/test-data/components/Foo',
|
|
273
|
+
filePath: 'src\\test-data\\components\\Foo.astro',
|
|
274
|
+
componentName: 'Foo',
|
|
275
|
+
moduleName: 'Foo',
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
importPath: 'src/test-data/components/Bar',
|
|
279
|
+
filePath: 'src\\test-data\\components\\Bar.astro',
|
|
280
|
+
componentName: 'Bar',
|
|
281
|
+
moduleName: 'Bar',
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
importPath: 'src/test-data/components/Baz',
|
|
285
|
+
filePath: 'src\\test-data\\components\\Baz.astro',
|
|
286
|
+
componentName: 'Baz',
|
|
287
|
+
moduleName: 'Baz',
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
importPath: 'src/test-data/components/Qux',
|
|
291
|
+
filePath: 'src\\test-data\\components\\Qux.astro',
|
|
292
|
+
componentName: 'Qux',
|
|
293
|
+
moduleName: 'Qux',
|
|
294
|
+
},
|
|
295
|
+
];
|
|
296
|
+
|
|
297
|
+
const globSyncStub = sandbox.stub(require('glob'), 'sync').returns(stubbedPaths);
|
|
298
|
+
|
|
299
|
+
const result = getComponentList(['src/test-data/components/*.astro']);
|
|
300
|
+
expect(result).to.deep.equal(expected);
|
|
301
|
+
|
|
302
|
+
globSyncStub.restore();
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import * as glob from 'glob';
|
|
2
|
+
import { ComponentFile } from '@sitecore-content-sdk/core/tools';
|
|
3
|
+
|
|
4
|
+
const componentNamePattern = /^[\/]*(.+[\/\\])*(.+)\.astro?$/;
|
|
5
|
+
|
|
6
|
+
const componentPathPattern = /^([\/]*.+[\/\\].+)\..+$/;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get list of components from @var path
|
|
10
|
+
* Returns a list of components in the following format:
|
|
11
|
+
* {
|
|
12
|
+
* path: 'path/to/component',
|
|
13
|
+
* componentName: 'ComponentName',
|
|
14
|
+
* moduleName: 'ComponentName'
|
|
15
|
+
* }
|
|
16
|
+
* @param {string[]} paths paths to search
|
|
17
|
+
* @param {string[]} [exclude] paths and glob patterns to exclude from final result
|
|
18
|
+
* @param {boolean} [includeVariants] whether to include variant components
|
|
19
|
+
*/
|
|
20
|
+
export function getComponentList(
|
|
21
|
+
paths: string[],
|
|
22
|
+
exclude?: string[],
|
|
23
|
+
includeVariants?: boolean
|
|
24
|
+
): ComponentFile[] {
|
|
25
|
+
const components = paths.reduce<ComponentFile[]>((result, path) => {
|
|
26
|
+
const globPath =
|
|
27
|
+
glob.hasMagic(path, { magicalBraces: true }) || path.match(componentNamePattern)
|
|
28
|
+
? path
|
|
29
|
+
: path.replace(/\/$/, '').concat('/**/*.astro');
|
|
30
|
+
return result.concat(
|
|
31
|
+
...glob
|
|
32
|
+
.sync(globPath, { ignore: exclude, nodir: true })
|
|
33
|
+
.filter((path: string) => path.match(componentNamePattern))
|
|
34
|
+
.map((filePath: string) => {
|
|
35
|
+
const name = filePath.match(componentNamePattern)![2];
|
|
36
|
+
return {
|
|
37
|
+
filePath,
|
|
38
|
+
importPath: filePath.match(componentPathPattern)![1].replace(/\\/g, '/'), // use forward slashes for consistency
|
|
39
|
+
componentName: name,
|
|
40
|
+
moduleName: name.replace(/[^\w]+/g, ''),
|
|
41
|
+
};
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
return includeVariants
|
|
47
|
+
? components
|
|
48
|
+
: components.filter((component) => !component.componentName.includes('.'));
|
|
49
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* eslint-disable no-unused-expressions, @typescript-eslint/no-unused-expressions */
|
|
2
|
+
import { expect } from 'chai';
|
|
3
|
+
import { defaultTemplate } from './default-component';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
|
|
6
|
+
describe('default-component', () => {
|
|
7
|
+
describe('generateTemplate', () => {
|
|
8
|
+
it('should generate a template with the given component name', () => {
|
|
9
|
+
const componentName = 'TestComponent';
|
|
10
|
+
const template = defaultTemplate.generateTemplate(componentName);
|
|
11
|
+
expect(template).to.include(`export type ${componentName}Props`);
|
|
12
|
+
expect(template).to.include(`<p>${componentName} Component</p>`);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
describe('getNextSteps', () => {
|
|
17
|
+
it('should return an empty array if no componentOutputPath is provided', () => {
|
|
18
|
+
const nextSteps = defaultTemplate.getNextSteps && defaultTemplate.getNextSteps('');
|
|
19
|
+
expect(nextSteps).to.be.an('array').that.is.empty;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should return an array with next steps if componentOutputPath is provided', () => {
|
|
23
|
+
const componentOutputPath = 'src/components/TestComponent.astro';
|
|
24
|
+
const nextSteps =
|
|
25
|
+
defaultTemplate.getNextSteps && defaultTemplate.getNextSteps(componentOutputPath);
|
|
26
|
+
expect(nextSteps)
|
|
27
|
+
.to.be.an('array')
|
|
28
|
+
.that.includes(`* Implement the Astro component in ${chalk.green(componentOutputPath)}`);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
});
|