@prismicio/next 0.0.1 → 0.0.5
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 +90 -0
- package/dist/index.cjs +86 -11
- package/dist/index.d.ts +62 -68
- package/dist/index.mjs +67 -11
- package/package.json +1 -1
- package/src/PrismicPreview.tsx +42 -10
- package/src/enableAutoPreviews.ts +4 -7
- package/src/index.ts +1 -5
- package/src/redirectToPreviewURL.ts +2 -0
- package/src/setPreviewData.ts +5 -2
- package/src/types.ts +4 -12
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# @prismicio/next
|
|
2
|
+
|
|
3
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
|
+
[![Github Actions CI][github-actions-ci-src]][github-actions-ci-href]
|
|
6
|
+
[![Codecov][codecov-src]][codecov-href]
|
|
7
|
+
[![Conventional Commits][conventional-commits-src]][conventional-commits-href]
|
|
8
|
+
[![License][license-src]][license-href]
|
|
9
|
+
|
|
10
|
+
> ⚠ This project is in an experimental state and therefore primarily meant to be used by Prismic kits. Use it at your own risks or stay tuned for the official release!
|
|
11
|
+
|
|
12
|
+
<!-- TODO: Replacing link to Prismic with [Prismic][prismic] is useful here -->
|
|
13
|
+
|
|
14
|
+
A Next.js Integration with Prismic that makes it easier to take advantage of Next.js features.
|
|
15
|
+
|
|
16
|
+
- 🎥 Easily set up Prismic Previews;
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @prismicio/next
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Documentation
|
|
25
|
+
|
|
26
|
+
To discover what's new on this package check out [the changelog][changelog]. For full documentation, visit the [official Prismic documentation][prismic-docs].
|
|
27
|
+
|
|
28
|
+
## Contributing
|
|
29
|
+
|
|
30
|
+
Whether you're helping us fix bugs, improve the docs, or spread the word, we'd love to have you as part of the Prismic developer community!
|
|
31
|
+
|
|
32
|
+
**Asking a question**: [Open a new topic][forum-question] on our community forum explaining what you want to achieve / your question. Our support team will get back to you shortly.
|
|
33
|
+
|
|
34
|
+
**Reporting a bug**: [Open an issue][repo-bug-report] explaining your application's setup and the bug you're encountering.
|
|
35
|
+
|
|
36
|
+
**Suggesting an improvement**: [Open an issue][repo-feature-request] explaining your improvement or feature so we can discuss and learn more.
|
|
37
|
+
|
|
38
|
+
**Submitting code changes**: For small fixes, feel free to [open a pull request][repo-pull-requests] with a description of your changes. For large changes, please first [open an issue][repo-feature-request] so we can discuss if and how the changes should be implemented.
|
|
39
|
+
|
|
40
|
+
For more clarity on this project and its structure you can also check out the detailed [CONTRIBUTING.md][contributing] document.
|
|
41
|
+
|
|
42
|
+
## License
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
Copyright 2013-2021 Prismic <contact@prismic.io> (https://prismic.io)
|
|
46
|
+
|
|
47
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
48
|
+
you may not use this file except in compliance with the License.
|
|
49
|
+
You may obtain a copy of the License at
|
|
50
|
+
|
|
51
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
52
|
+
|
|
53
|
+
Unless required by applicable law or agreed to in writing, software
|
|
54
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
55
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
56
|
+
See the License for the specific language governing permissions and
|
|
57
|
+
limitations under the License.
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
<!-- Links -->
|
|
61
|
+
|
|
62
|
+
[prismic]: https://prismic.io
|
|
63
|
+
|
|
64
|
+
<!-- TODO: Replace link with a more useful one if available -->
|
|
65
|
+
|
|
66
|
+
[prismic-docs]: https://prismic.io/docs
|
|
67
|
+
[changelog]: ./CHANGELOG.md
|
|
68
|
+
[contributing]: ./CONTRIBUTING.md
|
|
69
|
+
|
|
70
|
+
<!-- TODO: Replace link with a more useful one if available -->
|
|
71
|
+
|
|
72
|
+
[forum-question]: https://community.prismic.io
|
|
73
|
+
[repo-bug-report]: https://github.com/prismicio/prismic-next/issues/new?assignees=&labels=bug&template=bug_report.md&title=
|
|
74
|
+
[repo-feature-request]: https://github.com/prismicio/prismic-next/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=
|
|
75
|
+
[repo-pull-requests]: https://github.com/prismicio/prismic-next/pulls
|
|
76
|
+
|
|
77
|
+
<!-- Badges -->
|
|
78
|
+
|
|
79
|
+
[npm-version-src]: https://img.shields.io/npm/v/@prismicio/next/latest.svg
|
|
80
|
+
[npm-version-href]: https://npmjs.com/package/@prismicio/next
|
|
81
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/@prismicio/next.svg
|
|
82
|
+
[npm-downloads-href]: https://npmjs.com/package/@prismicio/next
|
|
83
|
+
[github-actions-ci-src]: https://github.com/prismicio/prismic-next/workflows/ci/badge.svg
|
|
84
|
+
[github-actions-ci-href]: https://github.com/prismicio/prismic-next/actions?query=workflow%3Aci
|
|
85
|
+
[codecov-src]: https://img.shields.io/codecov/c/github/prismicio/prismic-next.svg
|
|
86
|
+
[codecov-href]: https://codecov.io/gh/prismicio/prismic-next
|
|
87
|
+
[conventional-commits-src]: https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg
|
|
88
|
+
[conventional-commits-href]: https://conventionalcommits.org
|
|
89
|
+
[license-src]: https://img.shields.io/npm/l/@prismicio/next.svg
|
|
90
|
+
[license-href]: https://npmjs.com/package/@prismicio/next
|
package/dist/index.cjs
CHANGED
|
@@ -2,19 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
const prismic = require('@prismicio/client');
|
|
5
6
|
const React = require('react');
|
|
6
7
|
const react = require('@prismicio/react');
|
|
8
|
+
const router = require('next/router');
|
|
7
9
|
|
|
8
10
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
11
|
|
|
12
|
+
function _interopNamespace(e) {
|
|
13
|
+
if (e && e.__esModule) return e;
|
|
14
|
+
const n = Object.create(null);
|
|
15
|
+
if (e) {
|
|
16
|
+
for (const k in e) {
|
|
17
|
+
if (k !== 'default') {
|
|
18
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
19
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () { return e[k]; }
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
n["default"] = e;
|
|
27
|
+
return Object.freeze(n);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const prismic__namespace = /*#__PURE__*/_interopNamespace(prismic);
|
|
10
31
|
const React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
11
32
|
|
|
12
33
|
async function setPreviewData({
|
|
13
34
|
req,
|
|
14
35
|
res
|
|
15
36
|
}) {
|
|
16
|
-
|
|
17
|
-
|
|
37
|
+
const ref = req.query.token || req.cookies[prismic__namespace.cookie.preview];
|
|
38
|
+
if (ref) {
|
|
18
39
|
res.setPreviewData({ ref });
|
|
19
40
|
}
|
|
20
41
|
}
|
|
@@ -32,6 +53,50 @@ function exitPreview(config) {
|
|
|
32
53
|
config.res.redirect("/");
|
|
33
54
|
}
|
|
34
55
|
|
|
56
|
+
const readValue = (value) => {
|
|
57
|
+
return value.replace(/%3B/g, ";");
|
|
58
|
+
};
|
|
59
|
+
const parse = (cookieString) => {
|
|
60
|
+
const result = {};
|
|
61
|
+
const cookies = cookieString.split("; ");
|
|
62
|
+
for (const cookie of cookies) {
|
|
63
|
+
const parts = cookie.split("=");
|
|
64
|
+
const value = parts.slice(1).join("=");
|
|
65
|
+
const name = readValue(parts[0]).replace(/%3D/g, "=");
|
|
66
|
+
result[name] = readValue(value);
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
};
|
|
70
|
+
const getAll = (cookieStore) => parse(cookieStore);
|
|
71
|
+
const getCookie = (name, cookieStore) => getAll(cookieStore)[name];
|
|
72
|
+
|
|
73
|
+
const extractFirstSubdomain = (host) => host.split(".")[0];
|
|
74
|
+
const extractRepositoryNameFromObjectRef = (previewRef) => {
|
|
75
|
+
try {
|
|
76
|
+
const parsed = JSON.parse(decodeURIComponent(previewRef));
|
|
77
|
+
const keys = Object.keys(parsed);
|
|
78
|
+
const domainKey = keys.find((key) => /\.prismic\.io$/.test(key));
|
|
79
|
+
if (domainKey) {
|
|
80
|
+
return extractFirstSubdomain(domainKey);
|
|
81
|
+
} else {
|
|
82
|
+
return void 0;
|
|
83
|
+
}
|
|
84
|
+
} catch (e) {
|
|
85
|
+
return void 0;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const extractRepositoryNameFromURLRef = (previewRef) => {
|
|
89
|
+
try {
|
|
90
|
+
const url = new URL(previewRef);
|
|
91
|
+
return extractFirstSubdomain(url.host);
|
|
92
|
+
} catch (e) {
|
|
93
|
+
return void 0;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const extractPreviewRefRepositoryName = (previewRef) => {
|
|
97
|
+
return extractRepositoryNameFromObjectRef(previewRef) || extractRepositoryNameFromURLRef(previewRef);
|
|
98
|
+
};
|
|
99
|
+
|
|
35
100
|
const isPrismicUpdateToolbarEvent = (event) => {
|
|
36
101
|
return "detail" in event && typeof event.detail.ref === "string";
|
|
37
102
|
};
|
|
@@ -41,27 +106,36 @@ function PrismicPreview({
|
|
|
41
106
|
updatePreviewURL = "/api/preview",
|
|
42
107
|
exitPreviewURL = "/api/exit-preview"
|
|
43
108
|
}) {
|
|
109
|
+
const router$1 = router.useRouter();
|
|
44
110
|
React.useEffect(() => {
|
|
45
|
-
const
|
|
111
|
+
const previewRefRepositoryName = extractPreviewRefRepositoryName(getCookie("io.prismic.preview", globalThis.document.cookie));
|
|
112
|
+
const startPreviewIfLoadedFromSharedLink = async () => {
|
|
113
|
+
if (previewRefRepositoryName === repositoryName && !router$1.isPreview) {
|
|
114
|
+
await fetch(updatePreviewURL);
|
|
115
|
+
window.location.reload();
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
startPreviewIfLoadedFromSharedLink();
|
|
119
|
+
const handlePrismicPreviewUpdate = async (event) => {
|
|
46
120
|
if (isPrismicUpdateToolbarEvent(event)) {
|
|
47
121
|
event.preventDefault();
|
|
48
|
-
await fetch(
|
|
122
|
+
await fetch(updatePreviewURL);
|
|
49
123
|
window.location.reload();
|
|
50
124
|
}
|
|
51
125
|
};
|
|
52
|
-
const
|
|
126
|
+
const handlePrismicPreviewEnd = async (event) => {
|
|
53
127
|
event.preventDefault();
|
|
54
128
|
await fetch(exitPreviewURL);
|
|
55
129
|
window.location.reload();
|
|
56
130
|
};
|
|
57
131
|
if (window) {
|
|
58
|
-
window.addEventListener("prismicPreviewUpdate",
|
|
59
|
-
window.addEventListener("prismicPreviewEnd",
|
|
132
|
+
window.addEventListener("prismicPreviewUpdate", handlePrismicPreviewUpdate);
|
|
133
|
+
window.addEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
60
134
|
}
|
|
61
135
|
return () => {
|
|
62
136
|
if (window) {
|
|
63
|
-
window.removeEventListener("prismicPreviewUpdate",
|
|
64
|
-
window.removeEventListener("prismicPreviewEnd",
|
|
137
|
+
window.removeEventListener("prismicPreviewUpdate", handlePrismicPreviewUpdate);
|
|
138
|
+
window.removeEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
65
139
|
}
|
|
66
140
|
};
|
|
67
141
|
}, []);
|
|
@@ -74,8 +148,8 @@ const isPrismicNextPreviewData = (previewData) => {
|
|
|
74
148
|
return typeof previewData === "object" && "ref" in previewData;
|
|
75
149
|
};
|
|
76
150
|
const enableAutoPreviews = (config) => {
|
|
77
|
-
if ("
|
|
78
|
-
const previewData = config
|
|
151
|
+
if ("previewData" in config && config.previewData) {
|
|
152
|
+
const { previewData } = config;
|
|
79
153
|
if (isPrismicNextPreviewData(previewData) && previewData.ref) {
|
|
80
154
|
config.client.queryContentFromRef(previewData.ref);
|
|
81
155
|
}
|
|
@@ -101,6 +175,7 @@ async function redirectToPreviewURL({
|
|
|
101
175
|
previewToken: token
|
|
102
176
|
});
|
|
103
177
|
res.redirect(previewUrl);
|
|
178
|
+
return;
|
|
104
179
|
}
|
|
105
180
|
res.redirect(defaultURL);
|
|
106
181
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NextApiRequest, NextApiResponse, PreviewData } from 'next';
|
|
2
2
|
import { Client, HttpRequestLike } from '@prismicio/client';
|
|
3
|
-
import { LinkResolverFunction } from '@prismicio/helpers';
|
|
4
3
|
import React from 'react';
|
|
4
|
+
import { LinkResolverFunction } from '@prismicio/helpers';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Configuration for `setPreviewData`.
|
|
@@ -15,6 +15,7 @@ declare type SetPreviewDataConfig = {
|
|
|
15
15
|
*/
|
|
16
16
|
req: {
|
|
17
17
|
query: NextApiRequest["query"];
|
|
18
|
+
cookies: NextApiRequest["cookies"];
|
|
18
19
|
};
|
|
19
20
|
/**
|
|
20
21
|
* The `res` object from a Next.js API route. This is given as a parameter to
|
|
@@ -31,70 +32,6 @@ declare type SetPreviewDataConfig = {
|
|
|
31
32
|
*/
|
|
32
33
|
declare function setPreviewData({ req, res, }: SetPreviewDataConfig): Promise<void>;
|
|
33
34
|
|
|
34
|
-
/**
|
|
35
|
-
* Next.js context object from APIs supporting Preview Mode. This includes the
|
|
36
|
-
* context object from `getStaticProps` and `getServerSideProps`.
|
|
37
|
-
*/
|
|
38
|
-
declare type NextContextLike<TPreviewData extends PreviewData = PreviewData> = {
|
|
39
|
-
previewData?: TPreviewData;
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* Configuration for creating a Prismic client with automatic preview support in
|
|
43
|
-
* Next.js apps.
|
|
44
|
-
*/
|
|
45
|
-
declare type CreateClientConfig = {
|
|
46
|
-
/**
|
|
47
|
-
* A Next.js context object (such as the context object from `getStaticProps`
|
|
48
|
-
* or `getServerSideProps`).
|
|
49
|
-
*
|
|
50
|
-
* Pass a `context` when using outside a Next.js API endpoint.
|
|
51
|
-
*/
|
|
52
|
-
context?: NextContextLike;
|
|
53
|
-
/**
|
|
54
|
-
* A Next.js API endpoint request object.
|
|
55
|
-
*
|
|
56
|
-
* Pass a `req` object when using in a Next.js API endpoint.
|
|
57
|
-
*/
|
|
58
|
-
req?: NextApiRequest;
|
|
59
|
-
};
|
|
60
|
-
/**
|
|
61
|
-
* Preview config for enabling previews with redirectToPreviewURL
|
|
62
|
-
*/
|
|
63
|
-
declare type PreviewConfig = {
|
|
64
|
-
/**
|
|
65
|
-
* The `req` object from a Next.js API route. This is given as a parameter to
|
|
66
|
-
* the API route.
|
|
67
|
-
*
|
|
68
|
-
* @see Next.js API route docs: {@link https://nextjs.org/docs/api-routes/introduction}
|
|
69
|
-
*/
|
|
70
|
-
req: {
|
|
71
|
-
query: NextApiRequest["query"];
|
|
72
|
-
};
|
|
73
|
-
/**
|
|
74
|
-
* The `res` object from a Next.js API route. This is given as a parameter to
|
|
75
|
-
* the API route.
|
|
76
|
-
*
|
|
77
|
-
* @see Next.js API route docs: {@link https://nextjs.org/docs/api-routes/introduction}
|
|
78
|
-
*/
|
|
79
|
-
res: {
|
|
80
|
-
redirect: NextApiResponse["redirect"];
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* The Prismic client configured for the preview session's repository.
|
|
84
|
-
*/
|
|
85
|
-
client: Client;
|
|
86
|
-
/**
|
|
87
|
-
* A Link Resolver used to resolve the previewed document's URL.
|
|
88
|
-
*
|
|
89
|
-
* @see To learn more about Link Resolver: {@link https://prismic.io/docs/core-concepts/link-resolver-route-resolver}
|
|
90
|
-
*/
|
|
91
|
-
linkResolver?: LinkResolverFunction;
|
|
92
|
-
/**
|
|
93
|
-
* The default redirect URL if a URL cannot be determined for the previewed document.
|
|
94
|
-
*/
|
|
95
|
-
defaultURL?: string;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
35
|
/**
|
|
99
36
|
* Configuration for `enableAutoPreviews`.
|
|
100
37
|
*
|
|
@@ -113,7 +50,7 @@ declare type EnableAutoPreviewsConfig<TPreviewData extends PreviewData = Preview
|
|
|
113
50
|
* Pass a `context` object when using `enableAutoPreviews` outside a
|
|
114
51
|
* Next.js API endpoint.
|
|
115
52
|
*/
|
|
116
|
-
|
|
53
|
+
previewData?: TPreviewData;
|
|
117
54
|
} | {
|
|
118
55
|
/**
|
|
119
56
|
* A Next.js API endpoint request object.
|
|
@@ -129,7 +66,7 @@ declare type EnableAutoPreviewsConfig<TPreviewData extends PreviewData = Preview
|
|
|
129
66
|
*
|
|
130
67
|
* @param config - Configuration for the function.
|
|
131
68
|
*/
|
|
132
|
-
declare const enableAutoPreviews: <TPreviewData extends PreviewData
|
|
69
|
+
declare const enableAutoPreviews: <TPreviewData extends PreviewData>(config: EnableAutoPreviewsConfig<TPreviewData>) => void;
|
|
133
70
|
|
|
134
71
|
/**
|
|
135
72
|
* Configuration for `exitPreview`.
|
|
@@ -203,4 +140,61 @@ declare function PrismicPreview({ repositoryName, children, updatePreviewURL, ex
|
|
|
203
140
|
*/
|
|
204
141
|
declare function redirectToPreviewURL({ req, res, client, linkResolver, defaultURL, }: PreviewConfig): Promise<void>;
|
|
205
142
|
|
|
206
|
-
|
|
143
|
+
/**
|
|
144
|
+
* Configuration for creating a Prismic client with automatic preview support in
|
|
145
|
+
* Next.js apps.
|
|
146
|
+
*/
|
|
147
|
+
declare type CreateClientConfig = {
|
|
148
|
+
/**
|
|
149
|
+
* Preview data coming from Next.js context object. This context object comes
|
|
150
|
+
* from `getStaticProps` or `getServerSideProps`.
|
|
151
|
+
*
|
|
152
|
+
* Pass `previewData` when using outside a Next.js API endpoint.
|
|
153
|
+
*/
|
|
154
|
+
previewData?: PreviewData;
|
|
155
|
+
/**
|
|
156
|
+
* A Next.js API endpoint request object.
|
|
157
|
+
*
|
|
158
|
+
* Pass a `req` object when using in a Next.js API endpoint.
|
|
159
|
+
*/
|
|
160
|
+
req?: NextApiRequest;
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Preview config for enabling previews with redirectToPreviewURL
|
|
164
|
+
*/
|
|
165
|
+
declare type PreviewConfig = {
|
|
166
|
+
/**
|
|
167
|
+
* The `req` object from a Next.js API route. This is given as a parameter to
|
|
168
|
+
* the API route.
|
|
169
|
+
*
|
|
170
|
+
* @see Next.js API route docs: {@link https://nextjs.org/docs/api-routes/introduction}
|
|
171
|
+
*/
|
|
172
|
+
req: {
|
|
173
|
+
query: NextApiRequest["query"];
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* The `res` object from a Next.js API route. This is given as a parameter to
|
|
177
|
+
* the API route.
|
|
178
|
+
*
|
|
179
|
+
* @see Next.js API route docs: {@link https://nextjs.org/docs/api-routes/introduction}
|
|
180
|
+
*/
|
|
181
|
+
res: {
|
|
182
|
+
redirect: NextApiResponse["redirect"];
|
|
183
|
+
};
|
|
184
|
+
/**
|
|
185
|
+
* The Prismic client configured for the preview session's repository.
|
|
186
|
+
*/
|
|
187
|
+
client: Client;
|
|
188
|
+
/**
|
|
189
|
+
* A Link Resolver used to resolve the previewed document's URL.
|
|
190
|
+
*
|
|
191
|
+
* @see To learn more about Link Resolver: {@link https://prismic.io/docs/core-concepts/link-resolver-route-resolver}
|
|
192
|
+
*/
|
|
193
|
+
linkResolver?: LinkResolverFunction;
|
|
194
|
+
/**
|
|
195
|
+
* The default redirect URL if a URL cannot be determined for the previewed document.
|
|
196
|
+
*/
|
|
197
|
+
defaultURL?: string;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
export { CreateClientConfig, EnableAutoPreviewsConfig, ExitPreviewConfig as ExitPreviewParams, PreviewConfig, PrismicPreview, SetPreviewDataConfig, enableAutoPreviews, exitPreview, redirectToPreviewURL, setPreviewData };
|
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
import * as prismic from '@prismicio/client';
|
|
1
2
|
import React, { useEffect } from 'react';
|
|
2
3
|
import { PrismicToolbar } from '@prismicio/react';
|
|
4
|
+
import { useRouter } from 'next/router';
|
|
3
5
|
|
|
4
6
|
async function setPreviewData({
|
|
5
7
|
req,
|
|
6
8
|
res
|
|
7
9
|
}) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
const ref = req.query.token || req.cookies[prismic.cookie.preview];
|
|
11
|
+
if (ref) {
|
|
10
12
|
res.setPreviewData({ ref });
|
|
11
13
|
}
|
|
12
14
|
}
|
|
@@ -24,6 +26,50 @@ function exitPreview(config) {
|
|
|
24
26
|
config.res.redirect("/");
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
const readValue = (value) => {
|
|
30
|
+
return value.replace(/%3B/g, ";");
|
|
31
|
+
};
|
|
32
|
+
const parse = (cookieString) => {
|
|
33
|
+
const result = {};
|
|
34
|
+
const cookies = cookieString.split("; ");
|
|
35
|
+
for (const cookie of cookies) {
|
|
36
|
+
const parts = cookie.split("=");
|
|
37
|
+
const value = parts.slice(1).join("=");
|
|
38
|
+
const name = readValue(parts[0]).replace(/%3D/g, "=");
|
|
39
|
+
result[name] = readValue(value);
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
const getAll = (cookieStore) => parse(cookieStore);
|
|
44
|
+
const getCookie = (name, cookieStore) => getAll(cookieStore)[name];
|
|
45
|
+
|
|
46
|
+
const extractFirstSubdomain = (host) => host.split(".")[0];
|
|
47
|
+
const extractRepositoryNameFromObjectRef = (previewRef) => {
|
|
48
|
+
try {
|
|
49
|
+
const parsed = JSON.parse(decodeURIComponent(previewRef));
|
|
50
|
+
const keys = Object.keys(parsed);
|
|
51
|
+
const domainKey = keys.find((key) => /\.prismic\.io$/.test(key));
|
|
52
|
+
if (domainKey) {
|
|
53
|
+
return extractFirstSubdomain(domainKey);
|
|
54
|
+
} else {
|
|
55
|
+
return void 0;
|
|
56
|
+
}
|
|
57
|
+
} catch (e) {
|
|
58
|
+
return void 0;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const extractRepositoryNameFromURLRef = (previewRef) => {
|
|
62
|
+
try {
|
|
63
|
+
const url = new URL(previewRef);
|
|
64
|
+
return extractFirstSubdomain(url.host);
|
|
65
|
+
} catch (e) {
|
|
66
|
+
return void 0;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const extractPreviewRefRepositoryName = (previewRef) => {
|
|
70
|
+
return extractRepositoryNameFromObjectRef(previewRef) || extractRepositoryNameFromURLRef(previewRef);
|
|
71
|
+
};
|
|
72
|
+
|
|
27
73
|
const isPrismicUpdateToolbarEvent = (event) => {
|
|
28
74
|
return "detail" in event && typeof event.detail.ref === "string";
|
|
29
75
|
};
|
|
@@ -33,27 +79,36 @@ function PrismicPreview({
|
|
|
33
79
|
updatePreviewURL = "/api/preview",
|
|
34
80
|
exitPreviewURL = "/api/exit-preview"
|
|
35
81
|
}) {
|
|
82
|
+
const router = useRouter();
|
|
36
83
|
useEffect(() => {
|
|
37
|
-
const
|
|
84
|
+
const previewRefRepositoryName = extractPreviewRefRepositoryName(getCookie("io.prismic.preview", globalThis.document.cookie));
|
|
85
|
+
const startPreviewIfLoadedFromSharedLink = async () => {
|
|
86
|
+
if (previewRefRepositoryName === repositoryName && !router.isPreview) {
|
|
87
|
+
await fetch(updatePreviewURL);
|
|
88
|
+
window.location.reload();
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
startPreviewIfLoadedFromSharedLink();
|
|
92
|
+
const handlePrismicPreviewUpdate = async (event) => {
|
|
38
93
|
if (isPrismicUpdateToolbarEvent(event)) {
|
|
39
94
|
event.preventDefault();
|
|
40
|
-
await fetch(
|
|
95
|
+
await fetch(updatePreviewURL);
|
|
41
96
|
window.location.reload();
|
|
42
97
|
}
|
|
43
98
|
};
|
|
44
|
-
const
|
|
99
|
+
const handlePrismicPreviewEnd = async (event) => {
|
|
45
100
|
event.preventDefault();
|
|
46
101
|
await fetch(exitPreviewURL);
|
|
47
102
|
window.location.reload();
|
|
48
103
|
};
|
|
49
104
|
if (window) {
|
|
50
|
-
window.addEventListener("prismicPreviewUpdate",
|
|
51
|
-
window.addEventListener("prismicPreviewEnd",
|
|
105
|
+
window.addEventListener("prismicPreviewUpdate", handlePrismicPreviewUpdate);
|
|
106
|
+
window.addEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
52
107
|
}
|
|
53
108
|
return () => {
|
|
54
109
|
if (window) {
|
|
55
|
-
window.removeEventListener("prismicPreviewUpdate",
|
|
56
|
-
window.removeEventListener("prismicPreviewEnd",
|
|
110
|
+
window.removeEventListener("prismicPreviewUpdate", handlePrismicPreviewUpdate);
|
|
111
|
+
window.removeEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
57
112
|
}
|
|
58
113
|
};
|
|
59
114
|
}, []);
|
|
@@ -66,8 +121,8 @@ const isPrismicNextPreviewData = (previewData) => {
|
|
|
66
121
|
return typeof previewData === "object" && "ref" in previewData;
|
|
67
122
|
};
|
|
68
123
|
const enableAutoPreviews = (config) => {
|
|
69
|
-
if ("
|
|
70
|
-
const previewData = config
|
|
124
|
+
if ("previewData" in config && config.previewData) {
|
|
125
|
+
const { previewData } = config;
|
|
71
126
|
if (isPrismicNextPreviewData(previewData) && previewData.ref) {
|
|
72
127
|
config.client.queryContentFromRef(previewData.ref);
|
|
73
128
|
}
|
|
@@ -93,6 +148,7 @@ async function redirectToPreviewURL({
|
|
|
93
148
|
previewToken: token
|
|
94
149
|
});
|
|
95
150
|
res.redirect(previewUrl);
|
|
151
|
+
return;
|
|
96
152
|
}
|
|
97
153
|
res.redirect(defaultURL);
|
|
98
154
|
}
|
package/package.json
CHANGED
package/src/PrismicPreview.tsx
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import React, { useEffect } from "react";
|
|
2
2
|
import { PrismicToolbar } from "@prismicio/react";
|
|
3
|
+
import { useRouter } from "next/router";
|
|
4
|
+
|
|
5
|
+
import { getCookie } from "../lib/getCookie";
|
|
6
|
+
import { extractPreviewRefRepositoryName } from "../lib/extractPreviewRefRepositoryName";
|
|
3
7
|
|
|
4
8
|
/**
|
|
5
9
|
* Props for `<PrismicPreview>`.
|
|
@@ -56,38 +60,66 @@ export function PrismicPreview({
|
|
|
56
60
|
updatePreviewURL = "/api/preview",
|
|
57
61
|
exitPreviewURL = "/api/exit-preview",
|
|
58
62
|
}: PrismicPreviewProps): JSX.Element {
|
|
63
|
+
const router = useRouter();
|
|
64
|
+
|
|
59
65
|
useEffect(() => {
|
|
60
|
-
const
|
|
66
|
+
const previewRefRepositoryName = extractPreviewRefRepositoryName(
|
|
67
|
+
getCookie("io.prismic.preview", globalThis.document.cookie) as string,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const startPreviewIfLoadedFromSharedLink = async () => {
|
|
71
|
+
if (previewRefRepositoryName === repositoryName && !router.isPreview) {
|
|
72
|
+
await fetch(updatePreviewURL);
|
|
73
|
+
window.location.reload();
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
startPreviewIfLoadedFromSharedLink();
|
|
78
|
+
|
|
79
|
+
const handlePrismicPreviewUpdate = async (event: Event) => {
|
|
61
80
|
if (isPrismicUpdateToolbarEvent(event)) {
|
|
62
81
|
// Prevent the toolbar from reloading the page.
|
|
63
82
|
event.preventDefault();
|
|
64
|
-
// Update the preview cookie.
|
|
65
|
-
await fetch(`${updatePreviewURL}?token=${event.detail.ref}`);
|
|
66
83
|
|
|
67
|
-
//
|
|
84
|
+
// Start Next.js Preview Mode via the given preview API endpoint.
|
|
85
|
+
await fetch(updatePreviewURL);
|
|
86
|
+
|
|
87
|
+
// Reload the page with an active Preview Mode.
|
|
68
88
|
window.location.reload();
|
|
69
89
|
}
|
|
70
90
|
};
|
|
71
91
|
|
|
72
|
-
const
|
|
92
|
+
const handlePrismicPreviewEnd = async (event: Event) => {
|
|
93
|
+
// Prevent the toolbar from reloading the page.
|
|
73
94
|
event.preventDefault();
|
|
95
|
+
|
|
96
|
+
// Exit Next.js Preview Mode via the given preview API endpoint.
|
|
74
97
|
await fetch(exitPreviewURL);
|
|
98
|
+
|
|
99
|
+
// Reload the page with an active Preview Mode.
|
|
75
100
|
window.location.reload();
|
|
76
101
|
};
|
|
77
102
|
|
|
103
|
+
// Register Prismic Toolbar event handlers.
|
|
78
104
|
if (window) {
|
|
79
|
-
window.addEventListener(
|
|
80
|
-
|
|
81
|
-
|
|
105
|
+
window.addEventListener(
|
|
106
|
+
"prismicPreviewUpdate",
|
|
107
|
+
handlePrismicPreviewUpdate,
|
|
108
|
+
);
|
|
109
|
+
window.addEventListener("prismicPreviewEnd", handlePrismicPreviewEnd);
|
|
82
110
|
}
|
|
83
111
|
|
|
112
|
+
// On cleanup, unregister Prismic Toolbar event handlers.
|
|
84
113
|
return () => {
|
|
85
114
|
if (window) {
|
|
86
115
|
window.removeEventListener(
|
|
87
116
|
"prismicPreviewUpdate",
|
|
88
|
-
|
|
117
|
+
handlePrismicPreviewUpdate,
|
|
118
|
+
);
|
|
119
|
+
window.removeEventListener(
|
|
120
|
+
"prismicPreviewEnd",
|
|
121
|
+
handlePrismicPreviewEnd,
|
|
89
122
|
);
|
|
90
|
-
window.removeEventListener("prismicPreviewEnd", prismicPreviewEnd);
|
|
91
123
|
}
|
|
92
124
|
};
|
|
93
125
|
}, []);
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { PreviewData } from "next";
|
|
2
2
|
import { Client, HttpRequestLike } from "@prismicio/client";
|
|
3
|
-
import { NextContextLike } from "./types";
|
|
4
3
|
|
|
5
4
|
interface PrismicNextPreviewData {
|
|
6
5
|
ref: string;
|
|
@@ -40,7 +39,7 @@ export type EnableAutoPreviewsConfig<
|
|
|
40
39
|
* Pass a `context` object when using `enableAutoPreviews` outside a
|
|
41
40
|
* Next.js API endpoint.
|
|
42
41
|
*/
|
|
43
|
-
|
|
42
|
+
previewData?: TPreviewData;
|
|
44
43
|
}
|
|
45
44
|
| {
|
|
46
45
|
/**
|
|
@@ -58,16 +57,14 @@ export type EnableAutoPreviewsConfig<
|
|
|
58
57
|
*
|
|
59
58
|
* @param config - Configuration for the function.
|
|
60
59
|
*/
|
|
61
|
-
export const enableAutoPreviews = <
|
|
62
|
-
TPreviewData extends PreviewData = PreviewData,
|
|
63
|
-
>(
|
|
60
|
+
export const enableAutoPreviews = <TPreviewData extends PreviewData>(
|
|
64
61
|
config: EnableAutoPreviewsConfig<TPreviewData>,
|
|
65
62
|
): void => {
|
|
66
63
|
/**
|
|
67
64
|
* If preview data is being passed from Next Context then use queryContentFromRef
|
|
68
65
|
*/
|
|
69
|
-
if ("
|
|
70
|
-
const previewData = config
|
|
66
|
+
if ("previewData" in config && config.previewData) {
|
|
67
|
+
const { previewData } = config;
|
|
71
68
|
|
|
72
69
|
if (isPrismicNextPreviewData(previewData) && previewData.ref) {
|
|
73
70
|
config.client.queryContentFromRef(previewData.ref);
|
package/src/index.ts
CHANGED
|
@@ -6,8 +6,4 @@ export { exitPreview } from "./exitPreview";
|
|
|
6
6
|
export { PrismicPreview } from "./PrismicPreview";
|
|
7
7
|
export { enableAutoPreviews } from "./enableAutoPreviews";
|
|
8
8
|
export { redirectToPreviewURL } from "./redirectToPreviewURL";
|
|
9
|
-
export type {
|
|
10
|
-
NextContextLike,
|
|
11
|
-
CreateClientConfig,
|
|
12
|
-
PreviewConfig,
|
|
13
|
-
} from "./types";
|
|
9
|
+
export type { CreateClientConfig, PreviewConfig } from "./types";
|
package/src/setPreviewData.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NextApiResponse, NextApiRequest } from "next";
|
|
2
|
+
import * as prismic from "@prismicio/client";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Configuration for `setPreviewData`.
|
|
@@ -12,6 +13,7 @@ export type SetPreviewDataConfig = {
|
|
|
12
13
|
*/
|
|
13
14
|
req: {
|
|
14
15
|
query: NextApiRequest["query"];
|
|
16
|
+
cookies: NextApiRequest["cookies"];
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
/**
|
|
@@ -32,8 +34,9 @@ export async function setPreviewData({
|
|
|
32
34
|
req,
|
|
33
35
|
res,
|
|
34
36
|
}: SetPreviewDataConfig): Promise<void> {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
const ref = req.query.token || req.cookies[prismic.cookie.preview];
|
|
38
|
+
|
|
39
|
+
if (ref) {
|
|
37
40
|
res.setPreviewData({ ref });
|
|
38
41
|
}
|
|
39
42
|
}
|
package/src/types.ts
CHANGED
|
@@ -2,26 +2,18 @@ import { PreviewData, NextApiRequest, NextApiResponse } from "next";
|
|
|
2
2
|
import { LinkResolverFunction } from "@prismicio/helpers";
|
|
3
3
|
import { Client } from "@prismicio/client";
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Next.js context object from APIs supporting Preview Mode. This includes the
|
|
7
|
-
* context object from `getStaticProps` and `getServerSideProps`.
|
|
8
|
-
*/
|
|
9
|
-
export type NextContextLike<TPreviewData extends PreviewData = PreviewData> = {
|
|
10
|
-
previewData?: TPreviewData;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
5
|
/**
|
|
14
6
|
* Configuration for creating a Prismic client with automatic preview support in
|
|
15
7
|
* Next.js apps.
|
|
16
8
|
*/
|
|
17
9
|
export type CreateClientConfig = {
|
|
18
10
|
/**
|
|
19
|
-
*
|
|
20
|
-
* or `getServerSideProps
|
|
11
|
+
* Preview data coming from Next.js context object. This context object comes
|
|
12
|
+
* from `getStaticProps` or `getServerSideProps`.
|
|
21
13
|
*
|
|
22
|
-
* Pass
|
|
14
|
+
* Pass `previewData` when using outside a Next.js API endpoint.
|
|
23
15
|
*/
|
|
24
|
-
|
|
16
|
+
previewData?: PreviewData;
|
|
25
17
|
|
|
26
18
|
/**
|
|
27
19
|
* A Next.js API endpoint request object.
|