@slicemachine/adapter-next 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 +202 -0
- package/README.md +98 -0
- package/dist/index.cjs +699 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +671 -0
- package/dist/index.js.map +1 -0
- package/package.json +87 -0
- package/src/SliceSimulator.tsx +158 -0
- package/src/hooks/customType-create.ts +56 -0
- package/src/hooks/customType-delete.ts +13 -0
- package/src/hooks/customType-library-read.ts +40 -0
- package/src/hooks/customType-read.ts +19 -0
- package/src/hooks/customType-update.ts +3 -0
- package/src/hooks/slice-create.ts +146 -0
- package/src/hooks/slice-delete.ts +50 -0
- package/src/hooks/slice-library-read.ts +51 -0
- package/src/hooks/slice-read.ts +20 -0
- package/src/hooks/slice-update.ts +58 -0
- package/src/hooks/sliceSimulator-setup-read.ts +244 -0
- package/src/hooks/snippet-read.ts +115 -0
- package/src/index.ts +10 -0
- package/src/lib/buildSliceLibraryIndexFileContents.ts +38 -0
- package/src/lib/getJSOrTSXFileExtension.ts +13 -0
- package/src/lib/pascalCase.ts +12 -0
- package/src/lib/readJSONFile.ts +7 -0
- package/src/plugin.ts +43 -0
- package/src/types.ts +12 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
SliceDeleteHook,
|
|
3
|
+
SliceDeleteHookData,
|
|
4
|
+
SliceMachineContext,
|
|
5
|
+
} from "@slicemachine/plugin-kit";
|
|
6
|
+
import * as fs from "node:fs/promises";
|
|
7
|
+
|
|
8
|
+
import { buildSliceLibraryIndexFileContents } from "../lib/buildSliceLibraryIndexFileContents";
|
|
9
|
+
import { pascalCase } from "../lib/pascalCase";
|
|
10
|
+
|
|
11
|
+
import type { PluginOptions } from "../types";
|
|
12
|
+
|
|
13
|
+
type Args = {
|
|
14
|
+
data: SliceDeleteHookData;
|
|
15
|
+
} & SliceMachineContext<PluginOptions>;
|
|
16
|
+
|
|
17
|
+
const deleteSliceDir = async ({ data, helpers }: Args) => {
|
|
18
|
+
const dir = helpers.joinPathFromRoot(
|
|
19
|
+
data.libraryID,
|
|
20
|
+
pascalCase(data.model.id),
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
await fs.rm(dir, { recursive: true });
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const updateSliceLibraryIndexFile = async ({
|
|
27
|
+
data,
|
|
28
|
+
actions,
|
|
29
|
+
helpers,
|
|
30
|
+
project,
|
|
31
|
+
options,
|
|
32
|
+
}: Args) => {
|
|
33
|
+
const { filePath, contents } = await buildSliceLibraryIndexFileContents({
|
|
34
|
+
libraryID: data.libraryID,
|
|
35
|
+
actions,
|
|
36
|
+
helpers,
|
|
37
|
+
project,
|
|
38
|
+
options,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
await fs.writeFile(filePath, contents);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const sliceDelete: SliceDeleteHook<PluginOptions> = async (
|
|
45
|
+
data,
|
|
46
|
+
context,
|
|
47
|
+
) => {
|
|
48
|
+
await deleteSliceDir({ data, ...context });
|
|
49
|
+
await updateSliceLibraryIndexFile({ data, ...context });
|
|
50
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { SliceLibraryReadHook } from "@slicemachine/plugin-kit";
|
|
2
|
+
import * as prismicT from "@prismicio/types";
|
|
3
|
+
import * as fs from "node:fs/promises";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
|
|
6
|
+
import { readJSONFile } from "../lib/readJSONFile";
|
|
7
|
+
|
|
8
|
+
import type { PluginOptions } from "../types";
|
|
9
|
+
|
|
10
|
+
const isSharedSliceModel = (
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
+
input: any,
|
|
13
|
+
): input is prismicT.SharedSliceModel => {
|
|
14
|
+
return (
|
|
15
|
+
typeof input === "object" &&
|
|
16
|
+
input !== null &&
|
|
17
|
+
"type" in input &&
|
|
18
|
+
input.type === prismicT.CustomTypeModelSliceType.SharedSlice
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const sliceLibraryRead: SliceLibraryReadHook<PluginOptions> = async (
|
|
23
|
+
data,
|
|
24
|
+
{ helpers },
|
|
25
|
+
) => {
|
|
26
|
+
const dirPath = helpers.joinPathFromRoot(data.libraryID);
|
|
27
|
+
|
|
28
|
+
const childDirs = await fs.readdir(dirPath);
|
|
29
|
+
|
|
30
|
+
const sliceIDs: string[] = [];
|
|
31
|
+
await Promise.all(
|
|
32
|
+
childDirs.map(async (childDir) => {
|
|
33
|
+
const modelPath = path.join(dirPath, childDir, "model.json");
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const modelContents = await readJSONFile(modelPath);
|
|
37
|
+
|
|
38
|
+
if (isSharedSliceModel(modelContents)) {
|
|
39
|
+
sliceIDs.push(modelContents.id);
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
// noop
|
|
43
|
+
}
|
|
44
|
+
}),
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
id: data.libraryID,
|
|
49
|
+
sliceIDs: sliceIDs.sort(),
|
|
50
|
+
};
|
|
51
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SliceReadHook } from "@slicemachine/plugin-kit";
|
|
2
|
+
import * as prismicT from "@prismicio/types";
|
|
3
|
+
|
|
4
|
+
import { readJSONFile } from "../lib/readJSONFile";
|
|
5
|
+
import { pascalCase } from "../lib/pascalCase";
|
|
6
|
+
|
|
7
|
+
import type { PluginOptions } from "../types";
|
|
8
|
+
|
|
9
|
+
export const sliceRead: SliceReadHook<PluginOptions> = async (
|
|
10
|
+
data,
|
|
11
|
+
{ helpers },
|
|
12
|
+
) => {
|
|
13
|
+
const filePath = helpers.joinPathFromRoot(
|
|
14
|
+
data.libraryID,
|
|
15
|
+
pascalCase(data.sliceID),
|
|
16
|
+
"model.json",
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
return await readJSONFile<prismicT.SharedSliceModel>(filePath);
|
|
20
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
SliceMachineContext,
|
|
3
|
+
SliceUpdateHook,
|
|
4
|
+
SliceUpdateHookData,
|
|
5
|
+
} from "@slicemachine/plugin-kit";
|
|
6
|
+
import { generateTypes } from "prismic-ts-codegen";
|
|
7
|
+
import * as fs from "node:fs/promises";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
|
|
10
|
+
import { pascalCase } from "../lib/pascalCase";
|
|
11
|
+
|
|
12
|
+
import type { PluginOptions } from "../types";
|
|
13
|
+
|
|
14
|
+
type Args = {
|
|
15
|
+
dir: string;
|
|
16
|
+
data: SliceUpdateHookData;
|
|
17
|
+
} & SliceMachineContext<PluginOptions>;
|
|
18
|
+
|
|
19
|
+
const updateModelFile = async ({ dir, data, helpers, options }: Args) => {
|
|
20
|
+
const filePath = path.join(dir, "model.json");
|
|
21
|
+
|
|
22
|
+
let contents = JSON.stringify(data.model);
|
|
23
|
+
|
|
24
|
+
if (options.format) {
|
|
25
|
+
contents = await helpers.format(contents, filePath);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
await fs.writeFile(filePath, contents);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const updateTypesFile = async ({ dir, data, helpers, options }: Args) => {
|
|
32
|
+
const filePath = path.join(dir, "types.ts");
|
|
33
|
+
|
|
34
|
+
let contents = generateTypes({
|
|
35
|
+
sharedSliceModels: [data.model],
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
if (options.format) {
|
|
39
|
+
contents = await helpers.format(contents, filePath);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
await fs.writeFile(filePath, contents);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const sliceUpdate: SliceUpdateHook<PluginOptions> = async (
|
|
46
|
+
data,
|
|
47
|
+
context,
|
|
48
|
+
) => {
|
|
49
|
+
const dir = context.helpers.joinPathFromRoot(
|
|
50
|
+
data.libraryID,
|
|
51
|
+
pascalCase(data.model.id),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
await Promise.allSettled([
|
|
55
|
+
updateModelFile({ dir, data, ...context }),
|
|
56
|
+
updateTypesFile({ dir, data, ...context }),
|
|
57
|
+
]);
|
|
58
|
+
};
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
SliceMachineContext,
|
|
3
|
+
SliceSimulatorSetupReadHook,
|
|
4
|
+
SliceSimulatorSetupStep,
|
|
5
|
+
} from "@slicemachine/plugin-kit";
|
|
6
|
+
import { SliceSimulatorSetupStepValidationMessageType } from "@slicemachine/plugin-kit";
|
|
7
|
+
import { stripIndent } from "common-tags";
|
|
8
|
+
import { createRequire } from "node:module";
|
|
9
|
+
import * as http from "node:http";
|
|
10
|
+
|
|
11
|
+
import { getJSOrTSXFileExtension } from "../lib/getJSOrTSXFileExtension";
|
|
12
|
+
|
|
13
|
+
import type { PluginOptions } from "../types";
|
|
14
|
+
|
|
15
|
+
const REQUIRED_DEPENDENCIES = [
|
|
16
|
+
"@prismicio/react",
|
|
17
|
+
"@prismicio/slice-simulator-react",
|
|
18
|
+
"@prismicio/client@latest",
|
|
19
|
+
"@prismicio/helpers",
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
type Args = SliceMachineContext<PluginOptions>;
|
|
23
|
+
|
|
24
|
+
const createStep1 = async ({
|
|
25
|
+
project,
|
|
26
|
+
}: Args): Promise<SliceSimulatorSetupStep> => {
|
|
27
|
+
const require = createRequire(project.root);
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
title: "Install packages",
|
|
31
|
+
body: stripIndent`
|
|
32
|
+
The simulator requires extra dependencies. Run the following command to install them.
|
|
33
|
+
|
|
34
|
+
~~~sh
|
|
35
|
+
npm install --save @prismicio/react @prismicio/slice-simulator-react @prismicio/client@latest @prismicio/helpers
|
|
36
|
+
~~~
|
|
37
|
+
`,
|
|
38
|
+
validate: async () => {
|
|
39
|
+
const missingDependencies: string[] = [];
|
|
40
|
+
|
|
41
|
+
for (const dependency of REQUIRED_DEPENDENCIES) {
|
|
42
|
+
try {
|
|
43
|
+
// `require.resolve()` is preferred
|
|
44
|
+
// over `import()` because we don't
|
|
45
|
+
// want to load the module. Loading a
|
|
46
|
+
// module could introduce side-effects.
|
|
47
|
+
require.resolve(dependency);
|
|
48
|
+
} catch {
|
|
49
|
+
missingDependencies.push(dependency);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (missingDependencies.length >= REQUIRED_DEPENDENCIES.length) {
|
|
54
|
+
return {
|
|
55
|
+
type: SliceSimulatorSetupStepValidationMessageType.Error,
|
|
56
|
+
title: "Missing all dependencies",
|
|
57
|
+
message: stripIndent`
|
|
58
|
+
Install the required dependencies to continue.
|
|
59
|
+
`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (missingDependencies.length > 0) {
|
|
64
|
+
const formattedMissingDependencies = missingDependencies
|
|
65
|
+
.map((missingDependency) => `\`${missingDependency}\``)
|
|
66
|
+
.join(", ");
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
type: SliceSimulatorSetupStepValidationMessageType.Warning,
|
|
70
|
+
title: "Missing some dependencies",
|
|
71
|
+
message: stripIndent`
|
|
72
|
+
The following dependencies are missing: ${formattedMissingDependencies}
|
|
73
|
+
`,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const createStep2 = async ({
|
|
81
|
+
helpers,
|
|
82
|
+
options,
|
|
83
|
+
}: Args): Promise<SliceSimulatorSetupStep> => {
|
|
84
|
+
const fileName = `slice-simulator.${getJSOrTSXFileExtension}`;
|
|
85
|
+
const filePath = helpers.joinPathFromRoot("pages", fileName);
|
|
86
|
+
|
|
87
|
+
let fileContents: string;
|
|
88
|
+
|
|
89
|
+
if (options.typescript) {
|
|
90
|
+
fileContents = stripIndent`
|
|
91
|
+
import { GetStaticProps } from "next/types";
|
|
92
|
+
import { SliceSimulator } from "@prismicio/slice-simulator-react";
|
|
93
|
+
import { SliceZone } from "@prismicio/react";
|
|
94
|
+
|
|
95
|
+
import state from "../.slicemachine/libraries-state.json";
|
|
96
|
+
import { components } from "../slices";
|
|
97
|
+
|
|
98
|
+
const SliceSimulatorPage = () => {
|
|
99
|
+
return (
|
|
100
|
+
<SliceSimulator
|
|
101
|
+
sliceZone={(props) => <SliceZone {...props} components={components} />}
|
|
102
|
+
state={state}
|
|
103
|
+
/>
|
|
104
|
+
);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export default SliceSimulatorPage;
|
|
108
|
+
|
|
109
|
+
export const getStaticProps: GetStaticProps = () => {
|
|
110
|
+
return {
|
|
111
|
+
// Exclude this page from production builds.
|
|
112
|
+
notFound: process.env.NODE_ENV === "production",
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
`;
|
|
116
|
+
} else {
|
|
117
|
+
fileContents = stripIndent`
|
|
118
|
+
import { SliceSimulator } from "@prismicio/slice-simulator-react";
|
|
119
|
+
import { SliceZone } from "@prismicio/react";
|
|
120
|
+
|
|
121
|
+
import state from "../.slicemachine/libraries-state.json";
|
|
122
|
+
import { components } from "../slices";
|
|
123
|
+
|
|
124
|
+
const SliceSimulatorPage = () => {
|
|
125
|
+
return (
|
|
126
|
+
<SliceSimulator
|
|
127
|
+
sliceZone={(props) => <SliceZone {...props} components={components} />}
|
|
128
|
+
state={state}
|
|
129
|
+
/>
|
|
130
|
+
);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export default SliceSimulatorPage;
|
|
134
|
+
|
|
135
|
+
export const getStaticProps= () => {
|
|
136
|
+
return {
|
|
137
|
+
// Exclude this page from production builds.
|
|
138
|
+
notFound: process.env.NODE_ENV === "production",
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
fileContents = await helpers.format(fileContents, filePath);
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
title: "Create a page for the simulator",
|
|
148
|
+
body: stripIndent`
|
|
149
|
+
In your \`pages\` directory, create a file called \`${fileName}\` and add the following code. This route will be used to simulate and develop your components.
|
|
150
|
+
|
|
151
|
+
~~~tsx
|
|
152
|
+
${fileContents}
|
|
153
|
+
~~~
|
|
154
|
+
`,
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const createStep3 = async ({
|
|
159
|
+
helpers,
|
|
160
|
+
}: Args): Promise<SliceSimulatorSetupStep> => {
|
|
161
|
+
const filePath = helpers.joinPathFromRoot("sm.json");
|
|
162
|
+
const fileContents = await helpers.format(
|
|
163
|
+
`
|
|
164
|
+
{
|
|
165
|
+
"localSliceSimulatorURL": "http://localhost:3000/slice-simulator"
|
|
166
|
+
}
|
|
167
|
+
`,
|
|
168
|
+
filePath,
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
title: "Update `sm.json`",
|
|
173
|
+
body: stripIndent`
|
|
174
|
+
Update your \`sm.json\` file with a \`localSliceSimulatorURL\` property pointing to your \`slice-simulator\` page.
|
|
175
|
+
|
|
176
|
+
~~~json
|
|
177
|
+
${fileContents}
|
|
178
|
+
~~~
|
|
179
|
+
`,
|
|
180
|
+
validate: async () => {
|
|
181
|
+
const project = await helpers.getProject();
|
|
182
|
+
|
|
183
|
+
if (!("localSliceSimulatorURL" in project.config)) {
|
|
184
|
+
return {
|
|
185
|
+
type: SliceSimulatorSetupStepValidationMessageType.Error,
|
|
186
|
+
title: "Missing `localSliceSimulatorURL` property",
|
|
187
|
+
message: stripIndent`
|
|
188
|
+
A \`localSliceSimulatorURL\` property was not found in your \`sm.json\` file.
|
|
189
|
+
`,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Test if the URL is valid.
|
|
194
|
+
try {
|
|
195
|
+
if (project.config.localSliceSimulatorURL) {
|
|
196
|
+
new URL(project.config.localSliceSimulatorURL);
|
|
197
|
+
} else {
|
|
198
|
+
throw new Error("Undefined Slice Simulator URL");
|
|
199
|
+
}
|
|
200
|
+
} catch {
|
|
201
|
+
return {
|
|
202
|
+
type: SliceSimulatorSetupStepValidationMessageType.Warning,
|
|
203
|
+
title: "An invalid URL was provided",
|
|
204
|
+
message: stripIndent`
|
|
205
|
+
The \`localSliceSimulatorURL\` property should be of the shape \`http://localhost:PORT/PATH\`. See the codeblock for an example.
|
|
206
|
+
`,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Check if the URL is accessible.
|
|
211
|
+
const ok = await new Promise<boolean>((resolve) => {
|
|
212
|
+
if (project.config.localSliceSimulatorURL) {
|
|
213
|
+
http.get(project.config.localSliceSimulatorURL, (res) => {
|
|
214
|
+
if (res.statusCode) {
|
|
215
|
+
resolve(res.statusCode >= 200 && res.statusCode < 300);
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
resolve(false);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
if (!ok) {
|
|
224
|
+
return {
|
|
225
|
+
type: SliceSimulatorSetupStepValidationMessageType.Warning,
|
|
226
|
+
title: "Unable to connect to simulator page",
|
|
227
|
+
message: stripIndent`
|
|
228
|
+
Check that the \`localSliceSimulatorURL\` property in \`sm.json\` is correct and try again. See the [troubleshooting page](https://prismic.io/docs/technologies/setup-slice-simulator-nextjs) for more details.
|
|
229
|
+
`,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
export const sliceSimulatorSetupRead: SliceSimulatorSetupReadHook<
|
|
237
|
+
PluginOptions
|
|
238
|
+
> = async (_data, context) => {
|
|
239
|
+
return Promise.all([
|
|
240
|
+
createStep1(context),
|
|
241
|
+
createStep2(context),
|
|
242
|
+
createStep3(context),
|
|
243
|
+
]);
|
|
244
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { SnippetReadHook } from "@slicemachine/plugin-kit";
|
|
2
|
+
import * as prismicT from "@prismicio/types";
|
|
3
|
+
import { stripIndent } from "common-tags";
|
|
4
|
+
import type { Config as PrettierConfig } from "prettier";
|
|
5
|
+
|
|
6
|
+
import type { PluginOptions } from "../types";
|
|
7
|
+
|
|
8
|
+
const prettierOptions: PrettierConfig = { parser: "typescript" };
|
|
9
|
+
|
|
10
|
+
const dotPath = (segments: string[]): string => {
|
|
11
|
+
return segments.join(".");
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const snippetRead: SnippetReadHook<PluginOptions> = async (
|
|
15
|
+
data,
|
|
16
|
+
{ helpers },
|
|
17
|
+
) => {
|
|
18
|
+
const { fieldPath } = data;
|
|
19
|
+
|
|
20
|
+
const label = "React";
|
|
21
|
+
|
|
22
|
+
switch (data.model.type) {
|
|
23
|
+
case prismicT.CustomTypeModelFieldType.Link: {
|
|
24
|
+
return {
|
|
25
|
+
label,
|
|
26
|
+
language: "tsx",
|
|
27
|
+
code: await helpers.format(
|
|
28
|
+
stripIndent`
|
|
29
|
+
<PrismicLink field={${dotPath(fieldPath)}}>Link</PrismicLink>
|
|
30
|
+
`,
|
|
31
|
+
undefined,
|
|
32
|
+
{ prettier: prettierOptions },
|
|
33
|
+
),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
case prismicT.CustomTypeModelFieldType.Image: {
|
|
38
|
+
return [
|
|
39
|
+
{
|
|
40
|
+
label: `${label} (next/image)`,
|
|
41
|
+
language: "tsx",
|
|
42
|
+
code: await helpers.format(
|
|
43
|
+
stripIndent`
|
|
44
|
+
<PrismicNextImage field={${dotPath(fieldPath)}} />
|
|
45
|
+
`,
|
|
46
|
+
undefined,
|
|
47
|
+
{ prettier: prettierOptions },
|
|
48
|
+
),
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
label,
|
|
52
|
+
language: "tsx",
|
|
53
|
+
code: await helpers.format(
|
|
54
|
+
stripIndent`
|
|
55
|
+
<PrismicImage field={${dotPath(fieldPath)}} />
|
|
56
|
+
`,
|
|
57
|
+
undefined,
|
|
58
|
+
{ prettier: prettierOptions },
|
|
59
|
+
),
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
case prismicT.CustomTypeModelFieldType.Group: {
|
|
65
|
+
const code = await helpers.format(
|
|
66
|
+
stripIndent`
|
|
67
|
+
<>{${dotPath(fieldPath)}.map(item => (
|
|
68
|
+
<>{/* Render content for item */}</>
|
|
69
|
+
))}</>
|
|
70
|
+
`,
|
|
71
|
+
undefined,
|
|
72
|
+
{ prettier: prettierOptions },
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
label,
|
|
77
|
+
language: "tsx",
|
|
78
|
+
code,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
case prismicT.CustomTypeModelFieldType.Slices: {
|
|
83
|
+
const code = await helpers.format(
|
|
84
|
+
stripIndent`
|
|
85
|
+
<SliceZone
|
|
86
|
+
slices={${dotPath(fieldPath)}}
|
|
87
|
+
components={components}
|
|
88
|
+
/>
|
|
89
|
+
`,
|
|
90
|
+
undefined,
|
|
91
|
+
{ prettier: prettierOptions },
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
label,
|
|
96
|
+
language: "tsx",
|
|
97
|
+
code,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
default: {
|
|
102
|
+
return {
|
|
103
|
+
label,
|
|
104
|
+
language: "tsx",
|
|
105
|
+
code: await helpers.format(
|
|
106
|
+
stripIndent`
|
|
107
|
+
<>{${dotPath(fieldPath)}}</>
|
|
108
|
+
`,
|
|
109
|
+
undefined,
|
|
110
|
+
{ prettier: prettierOptions },
|
|
111
|
+
),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { plugin } from "./plugin";
|
|
2
|
+
export default plugin;
|
|
3
|
+
|
|
4
|
+
export type { PluginOptions } from "./types";
|
|
5
|
+
|
|
6
|
+
export { SliceSimulator } from "./SliceSimulator";
|
|
7
|
+
export type {
|
|
8
|
+
SliceSimulatorProps,
|
|
9
|
+
SliceSimulatorSliceZoneProps,
|
|
10
|
+
} from "./SliceSimulator";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { SliceMachineContext } from "@slicemachine/plugin-kit";
|
|
2
|
+
import { stripIndent } from "common-tags";
|
|
3
|
+
|
|
4
|
+
import { PluginOptions } from "../types";
|
|
5
|
+
|
|
6
|
+
import { pascalCase } from "./pascalCase";
|
|
7
|
+
|
|
8
|
+
type BuildSliceLibraryIndexFileContentsArgs = {
|
|
9
|
+
libraryID: string;
|
|
10
|
+
} & SliceMachineContext<PluginOptions>;
|
|
11
|
+
|
|
12
|
+
export const buildSliceLibraryIndexFileContents = async (
|
|
13
|
+
args: BuildSliceLibraryIndexFileContentsArgs,
|
|
14
|
+
): Promise<{ filePath: string; contents: string }> => {
|
|
15
|
+
const filePath = args.helpers.joinPathFromRoot(
|
|
16
|
+
args.libraryID,
|
|
17
|
+
args.options.typescript ? "index.ts" : "index.js",
|
|
18
|
+
);
|
|
19
|
+
const sliceLibrary = await args.actions.readSliceLibrary({
|
|
20
|
+
libraryID: args.libraryID,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
let contents = stripIndent`
|
|
24
|
+
import dynamic from 'next/dynamic'
|
|
25
|
+
|
|
26
|
+
export const components = {
|
|
27
|
+
${sliceLibrary.sliceIDs.map(
|
|
28
|
+
(id) => `${id}: dynamic(() => import('./${pascalCase(id)}')),`,
|
|
29
|
+
)}
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
if (args.options.format) {
|
|
34
|
+
contents = await args.helpers.format(contents, filePath);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { filePath, contents };
|
|
38
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PluginOptions } from "../types";
|
|
2
|
+
|
|
3
|
+
export const getJSOrTSXFileExtension = (
|
|
4
|
+
pluginOptions: PluginOptions,
|
|
5
|
+
): string => {
|
|
6
|
+
if (pluginOptions.typescript) {
|
|
7
|
+
return "tsx";
|
|
8
|
+
} else if (pluginOptions.jsxExtension) {
|
|
9
|
+
return "jsx";
|
|
10
|
+
} else {
|
|
11
|
+
return "js";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { pascalCase as basePascalCase } from "pascal-case";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Converts a string to a Pascal cased string.
|
|
5
|
+
*
|
|
6
|
+
* @param input - String to convert into a Pascal cased string.
|
|
7
|
+
*
|
|
8
|
+
* @returns Pascal cased string version of `input`.
|
|
9
|
+
*/
|
|
10
|
+
export const pascalCase = (...input: (string | undefined)[]): string => {
|
|
11
|
+
return basePascalCase(input.filter(Boolean).join(" "));
|
|
12
|
+
};
|
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { defineSliceMachinePlugin } from "@slicemachine/plugin-kit";
|
|
2
|
+
|
|
3
|
+
import { name as pkgName } from "../package.json";
|
|
4
|
+
import { PluginOptions } from "./types";
|
|
5
|
+
|
|
6
|
+
import { sliceCreate } from "./hooks/slice-create";
|
|
7
|
+
import { sliceUpdate } from "./hooks/slice-update";
|
|
8
|
+
import { sliceDelete } from "./hooks/slice-delete";
|
|
9
|
+
import { sliceRead } from "./hooks/slice-read";
|
|
10
|
+
import { sliceLibraryRead } from "./hooks/slice-library-read";
|
|
11
|
+
import { customTypeCreate } from "./hooks/customType-create";
|
|
12
|
+
import { customTypeUpdate } from "./hooks/customType-update";
|
|
13
|
+
import { customTypeDelete } from "./hooks/customType-delete";
|
|
14
|
+
import { customTypeRead } from "./hooks/customType-read";
|
|
15
|
+
import { customTypeLibraryRead } from "./hooks/customType-library-read";
|
|
16
|
+
import { snippetRead } from "./hooks/snippet-read";
|
|
17
|
+
import { sliceSimulatorSetupRead } from "./hooks/sliceSimulator-setup-read";
|
|
18
|
+
|
|
19
|
+
export const plugin = defineSliceMachinePlugin<PluginOptions>({
|
|
20
|
+
meta: {
|
|
21
|
+
name: pkgName,
|
|
22
|
+
},
|
|
23
|
+
defaultOptions: {
|
|
24
|
+
format: true,
|
|
25
|
+
},
|
|
26
|
+
setup({ hook }) {
|
|
27
|
+
hook("slice:create", sliceCreate);
|
|
28
|
+
hook("slice:update", sliceUpdate);
|
|
29
|
+
hook("slice:delete", sliceDelete);
|
|
30
|
+
hook("slice:read", sliceRead);
|
|
31
|
+
hook("slice-library:read", sliceLibraryRead);
|
|
32
|
+
|
|
33
|
+
hook("custom-type:create", customTypeCreate);
|
|
34
|
+
hook("custom-type:update", customTypeUpdate);
|
|
35
|
+
hook("custom-type:delete", customTypeDelete);
|
|
36
|
+
hook("custom-type:read", customTypeRead);
|
|
37
|
+
hook("custom-type-library:read", customTypeLibraryRead);
|
|
38
|
+
|
|
39
|
+
hook("snippet:read", snippetRead);
|
|
40
|
+
|
|
41
|
+
hook("slice-simulator:setup:read", sliceSimulatorSetupRead);
|
|
42
|
+
},
|
|
43
|
+
});
|