diff --git a/.babelrc.js b/.babelrc.js index 2ddd5a3..1a1aa4b 100644 --- a/.babelrc.js +++ b/.babelrc.js @@ -1,5 +1,15 @@ module.exports = { - presets: ['@babel/preset-env', '@babel/preset-react'], + presets: [ + [ + '@babel/preset-env', + { + targets: { + node: 'current', + }, + }, + ], + '@babel/preset-react' + ], plugins: [ // Preact ['@babel/plugin-transform-react-jsx', { pragma: 'h' }], diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..93193ca --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "resolveJsonModule": true, + "baseUrl": ".", + "paths": { + "@common": ["./src/common"], + "@common/*": ["./src/common/*"], + } + }, + "exclude": ["node_modules", "build"] +} diff --git a/package-lock.json b/package-lock.json index b8ed5df..f67d044 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "prismic-toolbar", - "version": "4.0.2", + "version": "4.0.5", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a8c5b08..cf44afa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "prismic-toolbar", - "version": "4.0.4", + "version": "4.0.6", "description": "Prismic Toolbar", "license": "Apache-2.0", "main": "build/prismic-toolbar.js", diff --git a/src/common/events.js b/src/common/events.js new file mode 100644 index 0000000..e222fc6 --- /dev/null +++ b/src/common/events.js @@ -0,0 +1,20 @@ +export const toolbarEvents = { + prismic: 'prismic', + previewUpdate: 'prismicPreviewUpdate', + previewEnd: 'prismicPreviewEnd' +}; + +/** + * Dispatches an event with given data + * + * @param {string} event - Event name + * @param {?any} data - Data to attach to the event + * + * @return {boolean} - `true` if event `event.preventDefault()` + * was not called (event was not cancelled) + */ +export const dispatchToolbarEvent = (event, data = null) => + window.dispatchEvent(new CustomEvent(event, { + detail: data, + cancelable: true + })); diff --git a/src/common/index.js b/src/common/index.js index 7bb54f5..343cf94 100644 --- a/src/common/index.js +++ b/src/common/index.js @@ -2,6 +2,10 @@ export { getCookie, setCookie, deleteCookie, demolishCookie } from './cookie'; export { Hooks } from './hooks'; export { Sorter } from './sorter'; +export { + toolbarEvents, + dispatchToolbarEvent, +} from './events'; export { warn, err, diff --git a/src/iframe/preview.js b/src/iframe/preview.js index 46842f8..19d568e 100644 --- a/src/iframe/preview.js +++ b/src/iframe/preview.js @@ -1,4 +1,4 @@ -import { fetchy, query, getCookie, demolishCookie, throttle, memoize, once } from '@common'; +import { fetchy, query, getCookie, demolishCookie, throttle, memoize } from '@common'; const SESSION_ID = getCookie('io.prismic.previewSession'); @@ -11,7 +11,14 @@ const PreviewRef = { getCurrent: throttle(async () => { const s = await State.get(); const ref = encodeURIComponent(s.preview.ref); - return fetchy({ url: `/previews/${SESSION_ID}/ping?ref=${ref}` }); + const current = await fetchy({ url: `/previews/${SESSION_ID}/ping?ref=${ref}` }); + + if (typeof s.preview === 'object') { + s.preview.ref = current.ref; + State.set(s); + } + + return current; }, 2000) }; @@ -65,12 +72,30 @@ const Share = { const State = { liveStateNeeded: Boolean(getCookie('is-logged-in')) || Boolean(getCookie('io.prismic.previewSession')), - get: once(async () => { - if (!State.liveStateNeeded) return State.normalize(); - return fetchy({ - url: '/toolbar/state', - }).then(State.normalize); - }), + state: null, + + get: async () => { + if (!State.state) { + await State.insert(); + } + return State.state; + }, + + set: (newState = {}) => { + State.state = newState; + }, + + setNormalized: (newState = {}) => { + State.set(State.normalize(newState)); + }, + + insert: async () => { + if (!State.liveStateNeeded) { + State.setNormalized(); + } else { + State.setNormalized(await fetchy({ url: '/toolbar/state' })); + } + }, normalize: (_state = {}) => ( Object.assign({}, { diff --git a/src/toolbar/index.js b/src/toolbar/index.js index 23aab29..c697fbf 100644 --- a/src/toolbar/index.js +++ b/src/toolbar/index.js @@ -1,6 +1,6 @@ import './checkBrowser'; import { ToolbarService } from '@toolbar-service'; -import { script } from '@common'; +import { toolbarEvents, dispatchToolbarEvent, script } from '@common'; import { reloadOrigin, getAbsoluteURL } from './utils'; import { Preview } from './preview'; import { Prediction } from './prediction'; @@ -40,7 +40,7 @@ window.prismic = window.PrismicToolbar = { let repos = new Set(); // Prismic variable is available -window.dispatchEvent(new CustomEvent('prismic')); +dispatchToolbarEvent(toolbarEvents.prismic); // Auto-querystring setup const scriptURL = new URL(getAbsoluteURL(document.currentScript.getAttribute('src'))); @@ -56,10 +56,11 @@ if (legacyEndpoint) { if (!repos.size) warn`Your are not connected to a repository.`; -repos.forEach(setup); - // Setup the Prismic Toolbar for one repository TODO support multi-repo let setupDomain = null; + +repos.forEach(setup); + async function setup (rawInput) { // Validate repository const domain = parseEndpoint(rawInput); diff --git a/src/toolbar/preview/index.js b/src/toolbar/preview/index.js index 6fc6b11..24e13e4 100644 --- a/src/toolbar/preview/index.js +++ b/src/toolbar/preview/index.js @@ -1,4 +1,4 @@ -import { getLocation } from '@common'; +import { toolbarEvents, dispatchToolbarEvent, getLocation } from '@common'; import { reloadOrigin } from '../utils'; import screenshot from './screenshot'; @@ -44,7 +44,12 @@ export class Preview { async updatePreview() { const { reload, ref } = await this.client.updatePreview(); this.start(ref); - if (reload) { reloadOrigin(); } + if (reload) { + // Dispatch the update event and hard reload if not cancelled by handlers + if (dispatchToolbarEvent(toolbarEvents.previewUpdate, { ref })) { + reloadOrigin(); + } + } } // Start preview @@ -67,8 +72,11 @@ export class Preview { await this.client.closePreviewSession(); if (!this.cookie.getRefForDomain()) return; this.cookie.deletePreviewForDomain(); - // reload to get rid of preview data and display the live version - reloadOrigin(); + + // Dispatch the end event and hard reload if not cancelled by handlers + if (dispatchToolbarEvent(toolbarEvents.previewEnd)) { + reloadOrigin(); + } } async share() {