@phtngyn/cms 0.1.0-beta.0 → 0.1.0-beta.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/README.md +72 -1
- package/package.json +5 -5
- package/src/Authoring.d.ts +13 -1
- package/src/{AuthoringSchema-BQ5kbhVB.js → Configuration-DyKo0sLS.js} +595 -367
- package/src/Configuration-DyKo0sLS.js.map +1 -0
- package/src/{DocumentEngine-Da0kWotL.js → DocumentEngine-DYObwMDY.js} +44 -66
- package/src/DocumentEngine-DYObwMDY.js.map +1 -0
- package/src/DocumentModel.d.ts +4 -0
- package/src/DocumentModel.js.map +1 -1
- package/src/{HttpPaths-86qLGB90.js → HttpPaths-BbS21Jy8.js} +4 -2
- package/src/{HttpPaths-86qLGB90.js.map → HttpPaths-BbS21Jy8.js.map} +1 -1
- package/src/Module.js +27 -76
- package/src/Module.js.map +1 -1
- package/src/{StudioHttp-BTLLooh0.js → StudioHttp-jR2-bc01.js} +44 -242
- package/src/StudioHttp-jR2-bc01.js.map +1 -0
- package/src/{connection-ZGtL54qY.js → connection-CBTY-TzB.js} +3 -3
- package/src/{connection-ZGtL54qY.js.map → connection-CBTY-TzB.js.map} +1 -1
- package/src/{installation-BNKaVjni.js → installation-DeuBiFRE.js} +488 -236
- package/src/installation-DeuBiFRE.js.map +1 -0
- package/src/internal/authoring-catalog.js +147 -0
- package/src/internal/authoring-catalog.js.map +1 -0
- package/src/internal/authoring-compiler.js +2 -1
- package/src/internal/authoring-compiler.js.map +1 -1
- package/src/internal/authoring-metadata.js +67 -48
- package/src/internal/authoring-metadata.js.map +1 -1
- package/src/internal/configuration.js +5 -6
- package/src/internal/configuration.js.map +1 -1
- package/src/internal/document-model.js +3 -2
- package/src/internal/document-model.js.map +1 -1
- package/src/internal/studio-app.js +66 -0
- package/src/internal/studio-app.js.map +1 -0
- package/src/location-DtYv2aes.js +36 -0
- package/src/location-DtYv2aes.js.map +1 -0
- package/src/{metadata-Czvi3E4K.js → metadata-DE1Mc2td.js} +2 -2
- package/src/{metadata-Czvi3E4K.js.map → metadata-DE1Mc2td.js.map} +1 -1
- package/src/{models-Citx8jBi.js → models-BkMgeaOL.js} +252 -3
- package/src/models-BkMgeaOL.js.map +1 -0
- package/src/{models-DS5ClMsH.js → models-C3witQBK.js} +8 -31
- package/src/models-C3witQBK.js.map +1 -0
- package/src/runtime/blocks.js +17 -0
- package/src/runtime/blocks.js.map +1 -0
- package/src/runtime/collaboration.js +9 -4
- package/src/runtime/collaboration.js.map +1 -1
- package/src/runtime/delivery/DocumentRenderer.js +6 -3
- package/src/runtime/delivery/DocumentRenderer.js.map +1 -1
- package/src/runtime/delivery/blocks.js +6 -0
- package/src/runtime/delivery/blocks.js.map +1 -0
- package/src/runtime/delivery/context.js +12 -0
- package/src/runtime/delivery/context.js.map +1 -0
- package/src/runtime/delivery/document-page.js +5 -3
- package/src/runtime/delivery/document-page.js.map +1 -1
- package/src/runtime/delivery/document.js +18 -2
- package/src/runtime/delivery/document.js.map +1 -1
- package/src/runtime/delivery/error.js +11 -0
- package/src/runtime/delivery/error.js.map +1 -0
- package/src/runtime/delivery/plugin.js +21 -0
- package/src/runtime/delivery/plugin.js.map +1 -0
- package/src/runtime/delivery/useDocument.js +6 -3
- package/src/runtime/delivery/useDocument.js.map +1 -1
- package/src/runtime/delivery/useDocumentQuery.js +6 -3
- package/src/runtime/delivery/useDocumentQuery.js.map +1 -1
- package/src/runtime/installation.js +1 -1
- package/src/runtime/plugin.js +3 -3
- package/src/runtime/plugin.js.map +1 -1
- package/src/runtime/preview/connection.js +1 -1
- package/src/runtime/preview/controller.js +29 -10
- package/src/runtime/preview/controller.js.map +1 -1
- package/src/runtime/preview/overlay.js +65 -0
- package/src/runtime/preview/overlay.js.map +1 -0
- package/src/runtime/preview/plugin.client.js +21 -34
- package/src/runtime/preview/plugin.client.js.map +1 -1
- package/src/runtime/preview/preview.css +72 -4
- package/src/runtime/preview/store.js +1 -1
- package/src/runtime/studio-app.js +5 -1
- package/src/runtime/studio-app.js.map +1 -1
- package/src/runtime/studio-entry.js +36 -0
- package/src/runtime/studio-entry.js.map +1 -0
- package/src/runtime/studio-navigation.js +11 -0
- package/src/runtime/studio-navigation.js.map +1 -0
- package/src/{store-Nl4uxEXx.js → store-CfFFx9Ua.js} +3 -3
- package/src/{store-Nl4uxEXx.js.map → store-CfFFx9Ua.js.map} +1 -1
- package/studio/CreateDocumentDialog--L9lTfx6.js +256 -0
- package/studio/collaboration-DUuu678R.js +4565 -0
- package/studio/documentPlanning-BXX04Woe.js +28989 -0
- package/studio/dom-to-image-more.min-D6jGGdrW.js +877 -0
- package/studio/editor-PexnXkJY.js +30817 -0
- package/studio/host.css +3 -0
- package/studio/host.js +44179 -0
- package/studio/rolldown-runtime-B0aSnxlc.js +20 -0
- package/dist/studio/assets/ActivityEntryRow-D--fRvWI.js +0 -1
- package/dist/studio/assets/ActivityView-D-XBBUHb.js +0 -1
- package/dist/studio/assets/CreateDocumentDialog-CH8UH1QM.js +0 -1
- package/dist/studio/assets/DocumentsView-CxRpmAxt.js +0 -34
- package/dist/studio/assets/DropdownMenu-BSb1l7fr.js +0 -1
- package/dist/studio/assets/Input-DVao38h7.js +0 -3
- package/dist/studio/assets/MediaView-BHrPIjxB.js +0 -1
- package/dist/studio/assets/Modal-VNrXGa5C.js +0 -1
- package/dist/studio/assets/OverviewView-DfP6-mLZ.js +0 -1
- package/dist/studio/assets/Select-BJZIs9sY.js +0 -1
- package/dist/studio/assets/SettingsView-CerHe-ua.js +0 -1
- package/dist/studio/assets/Skeleton-CWJNi3nS.js +0 -1
- package/dist/studio/assets/StudioPageHeader-DP9HDAF2.js +0 -1
- package/dist/studio/assets/UsersView-cP3REkH2.js +0 -1
- package/dist/studio/assets/collaboration-BLnCzfvV.js +0 -4
- package/dist/studio/assets/context-dY4fNbn3.js +0 -1
- package/dist/studio/assets/editor-CE07wW83.js +0 -137
- package/dist/studio/assets/gateway-BAyQgCse.js +0 -10
- package/dist/studio/assets/index-CjoaPLhZ.js +0 -28
- package/dist/studio/assets/index-s2rPqCmP.css +0 -2
- package/dist/studio/assets/render-BkxbK2St.js +0 -83
- package/dist/studio/assets/rolldown-runtime-DK3Fl9T5.js +0 -1
- package/dist/studio/assets/useMediaLibrary-D7qR7aBf.js +0 -1
- package/dist/studio/index.html +0 -76
- package/src/AuthoringSchema-BQ5kbhVB.js.map +0 -1
- package/src/Configuration-BGYFD2N1.js +0 -150
- package/src/Configuration-BGYFD2N1.js.map +0 -1
- package/src/DocumentEngine-Da0kWotL.js.map +0 -1
- package/src/StudioHttp-BTLLooh0.js.map +0 -1
- package/src/installation-BNKaVjni.js.map +0 -1
- package/src/internal/component-metadata.js +0 -37
- package/src/internal/component-metadata.js.map +0 -1
- package/src/models-Citx8jBi.js.map +0 -1
- package/src/models-DS5ClMsH.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { St as RevisionNumber, gt as DocumentId, pt as RequestId, vt as EditorNodeId } from "../../models-BkMgeaOL.js";
|
|
2
|
+
import { r as PreviewIntentId } from "../../models-C3witQBK.js";
|
|
3
|
+
import { mountPreviewOverlay } from "./overlay.js";
|
|
3
4
|
import { clearPreviewTargets, decoratePreviewTargets, findPreviewNodeId, nearestPreviewElement, resolvePreviewTarget } from "./targets.js";
|
|
4
5
|
import { Crypto, Effect, PlatformError, Schema } from "effect";
|
|
5
6
|
|
|
@@ -20,6 +21,8 @@ const browserCrypto = Crypto.make({
|
|
|
20
21
|
const randomUuid = () => Effect.runSync(browserCrypto.randomUUIDv4.pipe(Effect.orDie));
|
|
21
22
|
function mountPreviewController(options) {
|
|
22
23
|
const { bridge, root, store, view } = options;
|
|
24
|
+
const selection = mountPreviewOverlay(root, view);
|
|
25
|
+
const hover = mountPreviewOverlay(root, view, "hover");
|
|
23
26
|
let active = false;
|
|
24
27
|
let desiredFocus;
|
|
25
28
|
let fallbacks = {};
|
|
@@ -61,10 +64,14 @@ function mountPreviewController(options) {
|
|
|
61
64
|
const applyFocus = (reveal = false) => {
|
|
62
65
|
clearElements(selectedElements, "data-cms-selected");
|
|
63
66
|
selectedElements = [];
|
|
64
|
-
if (!active || mode !== "edit")
|
|
67
|
+
if (!active || mode !== "edit") {
|
|
68
|
+
selection.set([]);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
65
71
|
const intent = desiredFocus;
|
|
66
72
|
const nodeId = intent?.nodeId;
|
|
67
73
|
if (!intent || !nodeId) {
|
|
74
|
+
selection.set([]);
|
|
68
75
|
sendApplied("exact");
|
|
69
76
|
return;
|
|
70
77
|
}
|
|
@@ -72,6 +79,7 @@ function mountPreviewController(options) {
|
|
|
72
79
|
decoratePreviewTargets(scope);
|
|
73
80
|
const target = resolvePreviewTarget(scope, nodeId, fallbacks);
|
|
74
81
|
selectedElements = target.elements;
|
|
82
|
+
selection.set(selectedElements);
|
|
75
83
|
for (const element of selectedElements) element.setAttribute("data-cms-selected", "");
|
|
76
84
|
const result = !target.resolvedNodeId ? "missing" : target.resolvedNodeId === nodeId ? "exact" : "fallback";
|
|
77
85
|
if (reveal && result !== "missing" && revealedIntentId !== intent.id) {
|
|
@@ -83,12 +91,19 @@ function mountPreviewController(options) {
|
|
|
83
91
|
const hoverElements = (target) => {
|
|
84
92
|
clearElements(hoveredElements, "data-cms-hovered");
|
|
85
93
|
hoveredElements = [];
|
|
86
|
-
if (!active || mode !== "edit" || !target)
|
|
94
|
+
if (!active || mode !== "edit" || !target) {
|
|
95
|
+
hover.set([]);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
87
98
|
const scope = target.closest("[data-cms-document]") ?? root;
|
|
88
99
|
const nodeId = findPreviewNodeId(scope, target);
|
|
89
|
-
if (!nodeId)
|
|
100
|
+
if (!nodeId) {
|
|
101
|
+
hover.set([]);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
90
104
|
hoveredElements = resolvePreviewTarget(scope, nodeId, fallbacks).elements;
|
|
91
105
|
for (const element of hoveredElements) element.setAttribute("data-cms-hovered", "");
|
|
106
|
+
hover.set(hoveredElements);
|
|
92
107
|
};
|
|
93
108
|
const settleRender = (sequence) => {
|
|
94
109
|
view.requestAnimationFrame(() => view.requestAnimationFrame(() => {
|
|
@@ -116,6 +131,7 @@ function mountPreviewController(options) {
|
|
|
116
131
|
hoverElements();
|
|
117
132
|
clearElements(selectedElements, "data-cms-selected");
|
|
118
133
|
selectedElements = [];
|
|
134
|
+
selection.set([]);
|
|
119
135
|
} else {
|
|
120
136
|
decoratePreviewTargets(root);
|
|
121
137
|
applyFocus();
|
|
@@ -152,7 +168,8 @@ function mountPreviewController(options) {
|
|
|
152
168
|
const destination = new URL(link.href, view.location.href);
|
|
153
169
|
if (destination.origin !== view.location.origin) return;
|
|
154
170
|
event.preventDefault();
|
|
155
|
-
|
|
171
|
+
event.stopPropagation();
|
|
172
|
+
options.navigate(`${destination.pathname}${destination.search}${destination.hash}`);
|
|
156
173
|
return;
|
|
157
174
|
}
|
|
158
175
|
const scope = target?.closest("[data-cms-document]");
|
|
@@ -202,7 +219,8 @@ function mountPreviewController(options) {
|
|
|
202
219
|
if (!(event.relatedTarget instanceof Element)) hoverElements();
|
|
203
220
|
};
|
|
204
221
|
let mutationQueued = false;
|
|
205
|
-
const observer = new MutationObserver(() => {
|
|
222
|
+
const observer = new MutationObserver((records) => {
|
|
223
|
+
if (records.every((record) => record.target instanceof Element && record.target.closest("[data-cms-preview-overlay]"))) return;
|
|
206
224
|
if (mutationQueued) return;
|
|
207
225
|
mutationQueued = true;
|
|
208
226
|
queueMicrotask(() => {
|
|
@@ -224,6 +242,8 @@ function mountPreviewController(options) {
|
|
|
224
242
|
stopBridge();
|
|
225
243
|
stopManifest();
|
|
226
244
|
observer.disconnect();
|
|
245
|
+
selection.destroy();
|
|
246
|
+
hover.destroy();
|
|
227
247
|
root.removeEventListener("click", handleClick, true);
|
|
228
248
|
root.removeEventListener("pointerover", handlePointerOver, true);
|
|
229
249
|
root.removeEventListener("pointerout", handlePointerOut, true);
|
|
@@ -233,10 +253,9 @@ function mountPreviewController(options) {
|
|
|
233
253
|
function revealElement(element, view) {
|
|
234
254
|
if (!element) return;
|
|
235
255
|
const rect = element.getBoundingClientRect();
|
|
236
|
-
|
|
237
|
-
if (rect.top >= margin && rect.bottom <= view.innerHeight - margin) return;
|
|
256
|
+
if (rect.bottom > 0 && rect.top < view.innerHeight && rect.right > 0 && rect.left < view.innerWidth) return;
|
|
238
257
|
element.scrollIntoView({
|
|
239
|
-
behavior:
|
|
258
|
+
behavior: "instant",
|
|
240
259
|
block: "center",
|
|
241
260
|
inline: "nearest"
|
|
242
261
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller.js","names":[],"sources":["../../../../../src/runtime/preview/controller.ts"],"sourcesContent":["import type { DocumentPreviewFocusIntent, PreviewSiteBridge, StudioPreviewPayload } from '@internal/protocol/Preview'\nimport type { StudioPreviewStore } from './store'\nimport { DocumentId, EditorNodeId, RevisionNumber } from '@internal/protocol/Documents'\nimport { RequestId } from '@internal/protocol/Identity'\nimport { PreviewIntentId } from '@internal/protocol/Preview'\nimport { Crypto, Effect, PlatformError, Schema } from 'effect'\nimport {\n clearPreviewTargets,\n decoratePreviewTargets,\n findPreviewNodeId,\n nearestPreviewElement,\n resolvePreviewTarget,\n} from './targets'\n\nconst browserCrypto = Crypto.make({\n digest: (algorithm, data) =>\n Effect.tryPromise({\n catch: (cause) =>\n PlatformError.systemError({\n _tag: 'Unknown',\n cause,\n description: 'Could not compute digest',\n method: 'digest',\n module: 'Crypto',\n }),\n try: () =>\n globalThis.crypto.subtle.digest(algorithm, Uint8Array.from(data)).then((digest) => new Uint8Array(digest)),\n }),\n randomBytes: (size) => globalThis.crypto.getRandomValues(new Uint8Array(size)),\n})\n\nconst randomUuid = (): string => Effect.runSync(browserCrypto.randomUUIDv4.pipe(Effect.orDie))\n\nexport function mountPreviewController(options: {\n readonly bridge: PreviewSiteBridge\n readonly navigate: (path: string) => Promise<void> | void\n readonly root: Document\n readonly store: StudioPreviewStore\n readonly view: Window\n}): () => void {\n type PreviewFallbacks = Extract<StudioPreviewPayload, { readonly type: 'studio:patch' }>['fallbacks']\n const { bridge, root, store, view } = options\n let active = false\n let desiredFocus: DocumentPreviewFocusIntent | undefined\n let fallbacks: PreviewFallbacks = {}\n let hoveredElements: ReadonlyArray<Element> = []\n let mode: 'browse' | 'edit' = 'edit'\n let renderSequence = 0\n let revision = RevisionNumber.make(0)\n let selectedElements: ReadonlyArray<Element> = []\n let lastApplied = ''\n let revealedIntentId = ''\n\n const sendManifest = (): void => {\n bridge.send({ manifest: store.manifest(), revision, type: 'preview:manifest' })\n }\n const stopManifest = store.subscribe(sendManifest)\n const clearElements = (elements: ReadonlyArray<Element>, attribute: string): void => {\n for (const element of elements) element.removeAttribute(attribute)\n }\n const sendApplied = (result: 'exact' | 'fallback' | 'missing'): void => {\n if (!desiredFocus) return\n const signature = `${desiredFocus.id}:${result}`\n if (signature === lastApplied) return\n lastApplied = signature\n const applied = {\n intentId: desiredFocus.id,\n result,\n revision,\n type: 'preview:applied',\n } as const\n bridge.send(desiredFocus.nodeId ? { ...applied, nodeId: desiredFocus.nodeId } : applied)\n }\n const documentRoot = (documentId: string): ParentNode =>\n [...root.querySelectorAll('[data-cms-document]')].find(\n (element) => element.getAttribute('data-cms-document') === documentId,\n ) ?? root\n const applyFocus = (reveal = false): void => {\n clearElements(selectedElements, 'data-cms-selected')\n selectedElements = []\n if (!active || mode !== 'edit') return\n const intent = desiredFocus\n const nodeId = intent?.nodeId\n if (!intent || !nodeId) {\n sendApplied('exact')\n return\n }\n const scope = documentRoot(intent.documentId)\n decoratePreviewTargets(scope)\n const target = resolvePreviewTarget(scope, nodeId, fallbacks)\n selectedElements = target.elements\n for (const element of selectedElements) element.setAttribute('data-cms-selected', '')\n const result = !target.resolvedNodeId ? 'missing' : target.resolvedNodeId === nodeId ? 'exact' : 'fallback'\n if (reveal && result !== 'missing' && revealedIntentId !== intent.id) {\n revealedIntentId = intent.id\n revealElement(nearestPreviewElement(selectedElements), view)\n }\n sendApplied(result)\n }\n const hoverElements = (target?: Element): void => {\n clearElements(hoveredElements, 'data-cms-hovered')\n hoveredElements = []\n if (!active || mode !== 'edit' || !target) return\n const scope = target.closest('[data-cms-document]') ?? root\n const nodeId = findPreviewNodeId(scope, target)\n if (!nodeId) return\n hoveredElements = resolvePreviewTarget(scope, nodeId, fallbacks).elements\n for (const element of hoveredElements) element.setAttribute('data-cms-hovered', '')\n }\n const settleRender = (sequence: number): void => {\n view.requestAnimationFrame(() =>\n view.requestAnimationFrame(() => {\n if (sequence !== renderSequence) return\n active = true\n decoratePreviewTargets(root)\n bridge.send({ revision, type: 'preview:rendered' })\n applyFocus(desiredFocus?.reveal)\n }),\n )\n }\n\n const stopBridge = bridge.subscribe((message) => {\n if (message.type === 'studio:connect') {\n active = true\n clearPreviewTargets(root)\n decoratePreviewTargets(root)\n sendManifest()\n return\n }\n if (message.type === 'studio:mode') {\n mode = message.mode\n if (mode === 'browse') {\n hoverElements()\n clearElements(selectedElements, 'data-cms-selected')\n selectedElements = []\n } else {\n decoratePreviewTargets(root)\n applyFocus()\n }\n return\n }\n if (message.type === 'studio:navigate') {\n void options.navigate(message.path)\n return\n }\n if (message.type === 'studio:focus') {\n if (message.focus.revision !== revision) return\n desiredFocus = message.focus\n applyFocus(desiredFocus.reveal)\n return\n }\n if (message.type !== 'studio:patch' || message.revision < revision) return\n revision = message.revision\n active = false\n desiredFocus = message.focus\n lastApplied = ''\n const sequence = ++renderSequence\n void store.patch(message.document).then((localFallbacks) => {\n fallbacks = Object.assign({}, message.fallbacks, localFallbacks)\n settleRender(sequence)\n })\n })\n\n const handleClick = (event: MouseEvent) => {\n if (!active) return\n const target = event.target instanceof Element ? event.target : null\n if (mode === 'browse') {\n const link = target?.closest('a[href]')\n if (\n !(link instanceof HTMLAnchorElement) ||\n link.target ||\n link.hasAttribute('download') ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n )\n return\n const destination = new URL(link.href, view.location.href)\n if (destination.origin !== view.location.origin) return\n event.preventDefault()\n void options.navigate(destination.pathname)\n return\n }\n const scope = target?.closest('[data-cms-document]')\n const documentIdValue = scope?.getAttribute('data-cms-document')\n if (!target || !scope || !Schema.is(DocumentId)(documentIdValue)) return\n event.preventDefault()\n event.stopPropagation()\n const nodeIdValue = findPreviewNodeId(scope, target)\n const nodeId = Schema.is(EditorNodeId)(nodeIdValue) ? nodeIdValue : undefined\n const field = target.closest('[data-cms-field]')?.getAttribute('data-cms-field') || undefined\n const activationFocus = {\n documentId: documentIdValue,\n id: PreviewIntentId.make(randomUuid()),\n origin: 'preview',\n reveal: false,\n revision,\n } as const\n desiredFocus = nodeId ? { ...activationFocus, nodeId } : activationFocus\n lastApplied = ''\n const activation = {\n documentId: desiredFocus.documentId,\n requestId: RequestId.make(randomUuid()),\n revision,\n type: 'preview:activate',\n } as const\n if (field && nodeId) bridge.send({ ...activation, field, nodeId })\n else if (field) bridge.send({ ...activation, field })\n else if (nodeId) bridge.send({ ...activation, nodeId })\n else bridge.send(activation)\n applyFocus()\n }\n const handlePointerOver = (event: PointerEvent) =>\n hoverElements(event.target instanceof Element ? event.target : undefined)\n const handlePointerOut = (event: PointerEvent) => {\n if (!(event.relatedTarget instanceof Element)) hoverElements()\n }\n let mutationQueued = false\n const observer = new MutationObserver(() => {\n if (mutationQueued) return\n mutationQueued = true\n queueMicrotask(() => {\n mutationQueued = false\n if (!active) return\n hoverElements()\n decoratePreviewTargets(root)\n if (desiredFocus) applyFocus(false)\n })\n })\n\n root.addEventListener('click', handleClick, true)\n root.addEventListener('pointerover', handlePointerOver, true)\n root.addEventListener('pointerout', handlePointerOut, true)\n observer.observe(root.documentElement, { childList: true, subtree: true })\n\n return () => {\n stopBridge()\n stopManifest()\n observer.disconnect()\n root.removeEventListener('click', handleClick, true)\n root.removeEventListener('pointerover', handlePointerOver, true)\n root.removeEventListener('pointerout', handlePointerOut, true)\n clearPreviewTargets(root)\n }\n}\n\nfunction revealElement(element: Element | undefined, view: Window): void {\n if (!element) return\n const rect = element.getBoundingClientRect()\n const margin = Math.min(80, view.innerHeight / 5)\n if (rect.top >= margin && rect.bottom <= view.innerHeight - margin) return\n element.scrollIntoView({\n behavior: view.matchMedia('(prefers-reduced-motion: reduce)').matches ? 'auto' : 'smooth',\n block: 'center',\n inline: 'nearest',\n })\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"controller.js","names":[],"sources":["../../../../../src/runtime/preview/controller.ts"],"sourcesContent":["import type { DocumentPreviewFocusIntent, PreviewSiteBridge, StudioPreviewPayload } from '@internal/protocol/Preview'\nimport type { StudioPreviewStore } from './store'\nimport { DocumentId, EditorNodeId, RevisionNumber } from '@internal/protocol/Documents'\nimport { RequestId } from '@internal/protocol/Identity'\nimport { PreviewIntentId } from '@internal/protocol/Preview'\nimport { Crypto, Effect, PlatformError, Schema } from 'effect'\nimport { mountPreviewOverlay } from './overlay'\nimport {\n clearPreviewTargets,\n decoratePreviewTargets,\n findPreviewNodeId,\n nearestPreviewElement,\n resolvePreviewTarget,\n} from './targets'\n\nconst browserCrypto = Crypto.make({\n digest: (algorithm, data) =>\n Effect.tryPromise({\n catch: (cause) =>\n PlatformError.systemError({\n _tag: 'Unknown',\n cause,\n description: 'Could not compute digest',\n method: 'digest',\n module: 'Crypto',\n }),\n try: () =>\n globalThis.crypto.subtle.digest(algorithm, Uint8Array.from(data)).then((digest) => new Uint8Array(digest)),\n }),\n randomBytes: (size) => globalThis.crypto.getRandomValues(new Uint8Array(size)),\n})\n\nconst randomUuid = (): string => Effect.runSync(browserCrypto.randomUUIDv4.pipe(Effect.orDie))\n\nexport function mountPreviewController(options: {\n readonly bridge: PreviewSiteBridge\n readonly navigate: (path: string) => Promise<void> | void\n readonly root: Document\n readonly store: StudioPreviewStore\n readonly view: Window\n}): () => void {\n type PreviewFallbacks = Extract<StudioPreviewPayload, { readonly type: 'studio:patch' }>['fallbacks']\n const { bridge, root, store, view } = options\n const selection = mountPreviewOverlay(root, view)\n const hover = mountPreviewOverlay(root, view, 'hover')\n let active = false\n let desiredFocus: DocumentPreviewFocusIntent | undefined\n let fallbacks: PreviewFallbacks = {}\n let hoveredElements: ReadonlyArray<Element> = []\n let mode: 'browse' | 'edit' = 'edit'\n let renderSequence = 0\n let revision = RevisionNumber.make(0)\n let selectedElements: ReadonlyArray<Element> = []\n let lastApplied = ''\n let revealedIntentId = ''\n\n const sendManifest = (): void => {\n bridge.send({ manifest: store.manifest(), revision, type: 'preview:manifest' })\n }\n const stopManifest = store.subscribe(sendManifest)\n const clearElements = (elements: ReadonlyArray<Element>, attribute: string): void => {\n for (const element of elements) element.removeAttribute(attribute)\n }\n const sendApplied = (result: 'exact' | 'fallback' | 'missing'): void => {\n if (!desiredFocus) return\n const signature = `${desiredFocus.id}:${result}`\n if (signature === lastApplied) return\n lastApplied = signature\n const applied = {\n intentId: desiredFocus.id,\n result,\n revision,\n type: 'preview:applied',\n } as const\n bridge.send(desiredFocus.nodeId ? { ...applied, nodeId: desiredFocus.nodeId } : applied)\n }\n const documentRoot = (documentId: string): ParentNode =>\n [...root.querySelectorAll('[data-cms-document]')].find(\n (element) => element.getAttribute('data-cms-document') === documentId,\n ) ?? root\n const applyFocus = (reveal = false): void => {\n clearElements(selectedElements, 'data-cms-selected')\n selectedElements = []\n if (!active || mode !== 'edit') {\n selection.set([])\n return\n }\n const intent = desiredFocus\n const nodeId = intent?.nodeId\n if (!intent || !nodeId) {\n selection.set([])\n sendApplied('exact')\n return\n }\n const scope = documentRoot(intent.documentId)\n decoratePreviewTargets(scope)\n const target = resolvePreviewTarget(scope, nodeId, fallbacks)\n selectedElements = target.elements\n selection.set(selectedElements)\n for (const element of selectedElements) element.setAttribute('data-cms-selected', '')\n const result = !target.resolvedNodeId ? 'missing' : target.resolvedNodeId === nodeId ? 'exact' : 'fallback'\n if (reveal && result !== 'missing' && revealedIntentId !== intent.id) {\n revealedIntentId = intent.id\n revealElement(nearestPreviewElement(selectedElements), view)\n }\n sendApplied(result)\n }\n const hoverElements = (target?: Element): void => {\n clearElements(hoveredElements, 'data-cms-hovered')\n hoveredElements = []\n if (!active || mode !== 'edit' || !target) {\n hover.set([])\n return\n }\n const scope = target.closest('[data-cms-document]') ?? root\n const nodeId = findPreviewNodeId(scope, target)\n if (!nodeId) {\n hover.set([])\n return\n }\n hoveredElements = resolvePreviewTarget(scope, nodeId, fallbacks).elements\n for (const element of hoveredElements) element.setAttribute('data-cms-hovered', '')\n hover.set(hoveredElements)\n }\n const settleRender = (sequence: number): void => {\n view.requestAnimationFrame(() =>\n view.requestAnimationFrame(() => {\n if (sequence !== renderSequence) return\n active = true\n decoratePreviewTargets(root)\n bridge.send({ revision, type: 'preview:rendered' })\n applyFocus(desiredFocus?.reveal)\n }),\n )\n }\n\n const stopBridge = bridge.subscribe((message) => {\n if (message.type === 'studio:connect') {\n active = true\n clearPreviewTargets(root)\n decoratePreviewTargets(root)\n sendManifest()\n return\n }\n if (message.type === 'studio:mode') {\n mode = message.mode\n if (mode === 'browse') {\n hoverElements()\n clearElements(selectedElements, 'data-cms-selected')\n selectedElements = []\n selection.set([])\n } else {\n decoratePreviewTargets(root)\n applyFocus()\n }\n return\n }\n if (message.type === 'studio:navigate') {\n void options.navigate(message.path)\n return\n }\n if (message.type === 'studio:focus') {\n if (message.focus.revision !== revision) return\n desiredFocus = message.focus\n applyFocus(desiredFocus.reveal)\n return\n }\n if (message.type !== 'studio:patch' || message.revision < revision) return\n revision = message.revision\n active = false\n desiredFocus = message.focus\n lastApplied = ''\n const sequence = ++renderSequence\n void store.patch(message.document).then((localFallbacks) => {\n fallbacks = Object.assign({}, message.fallbacks, localFallbacks)\n settleRender(sequence)\n })\n })\n\n const handleClick = (event: MouseEvent) => {\n if (!active) return\n const target = event.target instanceof Element ? event.target : null\n if (mode === 'browse') {\n const link = target?.closest('a[href]')\n if (\n !(link instanceof HTMLAnchorElement) ||\n link.target ||\n link.hasAttribute('download') ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey\n )\n return\n const destination = new URL(link.href, view.location.href)\n if (destination.origin !== view.location.origin) return\n event.preventDefault()\n event.stopPropagation()\n void options.navigate(`${destination.pathname}${destination.search}${destination.hash}`)\n return\n }\n const scope = target?.closest('[data-cms-document]')\n const documentIdValue = scope?.getAttribute('data-cms-document')\n if (!target || !scope || !Schema.is(DocumentId)(documentIdValue)) return\n event.preventDefault()\n event.stopPropagation()\n const nodeIdValue = findPreviewNodeId(scope, target)\n const nodeId = Schema.is(EditorNodeId)(nodeIdValue) ? nodeIdValue : undefined\n const field = target.closest('[data-cms-field]')?.getAttribute('data-cms-field') || undefined\n const activationFocus = {\n documentId: documentIdValue,\n id: PreviewIntentId.make(randomUuid()),\n origin: 'preview',\n reveal: false,\n revision,\n } as const\n desiredFocus = nodeId ? { ...activationFocus, nodeId } : activationFocus\n lastApplied = ''\n const activation = {\n documentId: desiredFocus.documentId,\n requestId: RequestId.make(randomUuid()),\n revision,\n type: 'preview:activate',\n } as const\n if (field && nodeId) bridge.send({ ...activation, field, nodeId })\n else if (field) bridge.send({ ...activation, field })\n else if (nodeId) bridge.send({ ...activation, nodeId })\n else bridge.send(activation)\n applyFocus()\n }\n const handlePointerOver = (event: PointerEvent) =>\n hoverElements(event.target instanceof Element ? event.target : undefined)\n const handlePointerOut = (event: PointerEvent) => {\n if (!(event.relatedTarget instanceof Element)) hoverElements()\n }\n let mutationQueued = false\n const observer = new MutationObserver((records) => {\n if (\n records.every((record) => record.target instanceof Element && record.target.closest('[data-cms-preview-overlay]'))\n )\n return\n if (mutationQueued) return\n mutationQueued = true\n queueMicrotask(() => {\n mutationQueued = false\n if (!active) return\n hoverElements()\n decoratePreviewTargets(root)\n if (desiredFocus) applyFocus(false)\n })\n })\n\n root.addEventListener('click', handleClick, true)\n root.addEventListener('pointerover', handlePointerOver, true)\n root.addEventListener('pointerout', handlePointerOut, true)\n observer.observe(root.documentElement, { childList: true, subtree: true })\n\n return () => {\n stopBridge()\n stopManifest()\n observer.disconnect()\n selection.destroy()\n hover.destroy()\n root.removeEventListener('click', handleClick, true)\n root.removeEventListener('pointerover', handlePointerOver, true)\n root.removeEventListener('pointerout', handlePointerOut, true)\n clearPreviewTargets(root)\n }\n}\n\nfunction revealElement(element: Element | undefined, view: Window): void {\n if (!element) return\n const rect = element.getBoundingClientRect()\n if (rect.bottom > 0 && rect.top < view.innerHeight && rect.right > 0 && rect.left < view.innerWidth) return\n element.scrollIntoView({\n behavior: 'instant',\n block: 'center',\n inline: 'nearest',\n })\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
//#region src/runtime/preview/overlay.ts
|
|
2
|
+
/** Preview-only chrome stays separate from the website's layout and element styles. */
|
|
3
|
+
function mountPreviewOverlay(root, view, kind = "selection") {
|
|
4
|
+
const host = root.createElement("div");
|
|
5
|
+
host.setAttribute("data-cms-preview-overlay", "");
|
|
6
|
+
host.setAttribute("aria-hidden", "true");
|
|
7
|
+
root.documentElement.append(host);
|
|
8
|
+
let targets = [];
|
|
9
|
+
let outlines = [];
|
|
10
|
+
let frame = 0;
|
|
11
|
+
const position = () => {
|
|
12
|
+
let labelled = false;
|
|
13
|
+
for (const [index, element] of targets.entries()) {
|
|
14
|
+
const outline = outlines[index];
|
|
15
|
+
if (!outline) continue;
|
|
16
|
+
const rect = element.getBoundingClientRect();
|
|
17
|
+
const visible = element.isConnected && (kind !== "hover" || !element.hasAttribute("data-cms-selected")) && rect.width > 0 && rect.height > 0 && rect.bottom > 0 && rect.top < view.innerHeight && rect.right > 0 && rect.left < view.innerWidth;
|
|
18
|
+
outline.hidden = !visible;
|
|
19
|
+
outline.toggleAttribute("data-cms-selection-label", kind === "selection" && visible && !labelled);
|
|
20
|
+
if (!visible) continue;
|
|
21
|
+
labelled = true;
|
|
22
|
+
const left = Math.max(2, rect.left - 3);
|
|
23
|
+
const right = Math.min(view.innerWidth - 2, rect.right + 3);
|
|
24
|
+
outline.style.left = `${left}px`;
|
|
25
|
+
outline.style.top = `${rect.top - 3}px`;
|
|
26
|
+
outline.style.width = `${Math.max(0, right - left)}px`;
|
|
27
|
+
outline.style.height = `${rect.height + 6}px`;
|
|
28
|
+
outline.style.setProperty("--cms-label-left", `${Math.max(0, Math.min(view.innerWidth - 76, left) - left)}px`);
|
|
29
|
+
outline.style.setProperty("--cms-label-top", `${Math.max(4 - rect.top, rect.top >= 30 ? -26 : 4)}px`);
|
|
30
|
+
}
|
|
31
|
+
frame = targets.length ? view.requestAnimationFrame(position) : 0;
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
set(elements) {
|
|
35
|
+
if (elements.length === targets.length && elements.every((element, index) => element === targets[index])) return;
|
|
36
|
+
if (frame) view.cancelAnimationFrame(frame);
|
|
37
|
+
targets = elements;
|
|
38
|
+
outlines = elements.map(() => {
|
|
39
|
+
const outline = root.createElement("div");
|
|
40
|
+
outline.setAttribute(kind === "selection" ? "data-cms-selection-outline" : "data-cms-hover-outline", "");
|
|
41
|
+
if (kind === "hover") for (const corner of [
|
|
42
|
+
"top-left",
|
|
43
|
+
"top-right",
|
|
44
|
+
"bottom-right",
|
|
45
|
+
"bottom-left"
|
|
46
|
+
]) {
|
|
47
|
+
const mark = root.createElement("span");
|
|
48
|
+
mark.setAttribute("data-cms-hover-corner", corner);
|
|
49
|
+
outline.append(mark);
|
|
50
|
+
}
|
|
51
|
+
return outline;
|
|
52
|
+
});
|
|
53
|
+
host.replaceChildren(...outlines);
|
|
54
|
+
position();
|
|
55
|
+
},
|
|
56
|
+
destroy() {
|
|
57
|
+
if (frame) view.cancelAnimationFrame(frame);
|
|
58
|
+
host.remove();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
//#endregion
|
|
64
|
+
export { mountPreviewOverlay };
|
|
65
|
+
//# sourceMappingURL=overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay.js","names":[],"sources":["../../../../../src/runtime/preview/overlay.ts"],"sourcesContent":["/** Preview-only chrome stays separate from the website's layout and element styles. */\nexport function mountPreviewOverlay(root: Document, view: Window, kind: 'selection' | 'hover' = 'selection') {\n const host = root.createElement('div')\n host.setAttribute('data-cms-preview-overlay', '')\n host.setAttribute('aria-hidden', 'true')\n root.documentElement.append(host)\n let targets: ReadonlyArray<Element> = []\n let outlines: Array<HTMLElement> = []\n let frame = 0\n\n const position = (): void => {\n let labelled = false\n for (const [index, element] of targets.entries()) {\n const outline = outlines[index]\n if (!outline) continue\n const rect = element.getBoundingClientRect()\n const visible =\n element.isConnected &&\n (kind !== 'hover' || !element.hasAttribute('data-cms-selected')) &&\n rect.width > 0 &&\n rect.height > 0 &&\n rect.bottom > 0 &&\n rect.top < view.innerHeight &&\n rect.right > 0 &&\n rect.left < view.innerWidth\n outline.hidden = !visible\n outline.toggleAttribute('data-cms-selection-label', kind === 'selection' && visible && !labelled)\n if (!visible) continue\n labelled = true\n const left = Math.max(2, rect.left - 3)\n const right = Math.min(view.innerWidth - 2, rect.right + 3)\n outline.style.left = `${left}px`\n outline.style.top = `${rect.top - 3}px`\n outline.style.width = `${Math.max(0, right - left)}px`\n outline.style.height = `${rect.height + 6}px`\n outline.style.setProperty('--cms-label-left', `${Math.max(0, Math.min(view.innerWidth - 76, left) - left)}px`)\n outline.style.setProperty('--cms-label-top', `${Math.max(4 - rect.top, rect.top >= 30 ? -26 : 4)}px`)\n }\n frame = targets.length ? view.requestAnimationFrame(position) : 0\n }\n\n return {\n set(elements: ReadonlyArray<Element>): void {\n if (elements.length === targets.length && elements.every((element, index) => element === targets[index])) return\n if (frame) view.cancelAnimationFrame(frame)\n targets = elements\n outlines = elements.map(() => {\n const outline = root.createElement('div')\n outline.setAttribute(kind === 'selection' ? 'data-cms-selection-outline' : 'data-cms-hover-outline', '')\n if (kind === 'hover') {\n for (const corner of ['top-left', 'top-right', 'bottom-right', 'bottom-left']) {\n const mark = root.createElement('span')\n mark.setAttribute('data-cms-hover-corner', corner)\n outline.append(mark)\n }\n }\n return outline\n })\n host.replaceChildren(...outlines)\n position()\n },\n destroy(): void {\n if (frame) view.cancelAnimationFrame(frame)\n host.remove()\n },\n }\n}\n"],"mappings":";;AACA,SAAgB,oBAAoB,MAAgB,MAAc,OAA8B,aAAa;CAC3G,MAAM,OAAO,KAAK,cAAc,KAAK;CACrC,KAAK,aAAa,4BAA4B,EAAE;CAChD,KAAK,aAAa,eAAe,MAAM;CACvC,KAAK,gBAAgB,OAAO,IAAI;CAChC,IAAI,UAAkC,CAAC;CACvC,IAAI,WAA+B,CAAC;CACpC,IAAI,QAAQ;CAEZ,MAAM,iBAAuB;EAC3B,IAAI,WAAW;EACf,KAAK,MAAM,CAAC,OAAO,YAAY,QAAQ,QAAQ,GAAG;GAChD,MAAM,UAAU,SAAS;GACzB,IAAI,CAAC,SAAS;GACd,MAAM,OAAO,QAAQ,sBAAsB;GAC3C,MAAM,UACJ,QAAQ,gBACP,SAAS,WAAW,CAAC,QAAQ,aAAa,mBAAmB,MAC9D,KAAK,QAAQ,KACb,KAAK,SAAS,KACd,KAAK,SAAS,KACd,KAAK,MAAM,KAAK,eAChB,KAAK,QAAQ,KACb,KAAK,OAAO,KAAK;GACnB,QAAQ,SAAS,CAAC;GAClB,QAAQ,gBAAgB,4BAA4B,SAAS,eAAe,WAAW,CAAC,QAAQ;GAChG,IAAI,CAAC,SAAS;GACd,WAAW;GACX,MAAM,OAAO,KAAK,IAAI,GAAG,KAAK,OAAO,CAAC;GACtC,MAAM,QAAQ,KAAK,IAAI,KAAK,aAAa,GAAG,KAAK,QAAQ,CAAC;GAC1D,QAAQ,MAAM,OAAO,GAAG,KAAK;GAC7B,QAAQ,MAAM,MAAM,GAAG,KAAK,MAAM,EAAE;GACpC,QAAQ,MAAM,QAAQ,GAAG,KAAK,IAAI,GAAG,QAAQ,IAAI,EAAE;GACnD,QAAQ,MAAM,SAAS,GAAG,KAAK,SAAS,EAAE;GAC1C,QAAQ,MAAM,YAAY,oBAAoB,GAAG,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,aAAa,IAAI,IAAI,IAAI,IAAI,EAAE,GAAG;GAC7G,QAAQ,MAAM,YAAY,mBAAmB,GAAG,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM,CAAC,EAAE,GAAG;EACtG;EACA,QAAQ,QAAQ,SAAS,KAAK,sBAAsB,QAAQ,IAAI;CAClE;CAEA,OAAO;EACL,IAAI,UAAwC;GAC1C,IAAI,SAAS,WAAW,QAAQ,UAAU,SAAS,OAAO,SAAS,UAAU,YAAY,QAAQ,MAAM,GAAG;GAC1G,IAAI,OAAO,KAAK,qBAAqB,KAAK;GAC1C,UAAU;GACV,WAAW,SAAS,UAAU;IAC5B,MAAM,UAAU,KAAK,cAAc,KAAK;IACxC,QAAQ,aAAa,SAAS,cAAc,+BAA+B,0BAA0B,EAAE;IACvG,IAAI,SAAS,SACX,KAAK,MAAM,UAAU;KAAC;KAAY;KAAa;KAAgB;IAAa,GAAG;KAC7E,MAAM,OAAO,KAAK,cAAc,MAAM;KACtC,KAAK,aAAa,yBAAyB,MAAM;KACjD,QAAQ,OAAO,IAAI;IACrB;IAEF,OAAO;GACT,CAAC;GACD,KAAK,gBAAgB,GAAG,QAAQ;GAChC,SAAS;EACX;EACA,UAAgB;GACd,IAAI,OAAO,KAAK,qBAAqB,KAAK;GAC1C,KAAK,OAAO;EACd;CACF;AACF"}
|
|
@@ -1,38 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { documentPreviewStoreKey } from "../delivery/preview.js";
|
|
1
|
+
import { yt as PublicPath } from "../../models-BkMgeaOL.js";
|
|
2
|
+
import { t as openSitePreviewConnection } from "../../connection-CBTY-TzB.js";
|
|
3
|
+
import { n as readPreviewLocation, r as withPreviewLocation } from "../../location-DtYv2aes.js";
|
|
5
4
|
import { mountPreviewController } from "./controller.js";
|
|
6
|
-
import { t as createStudioPreviewStore } from "../../store-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const ENABLED_PARAMETER = "_cms_preview";
|
|
12
|
-
const EDITOR_ORIGIN_PARAMETER = "_cms_preview_editor_origin";
|
|
13
|
-
const SESSION_PARAMETER = "_cms_preview_session";
|
|
14
|
-
const PreviewLocationParameters = Schema.Struct({
|
|
15
|
-
editorOrigin: PreviewOrigin,
|
|
16
|
-
sessionId: PreviewSessionId
|
|
17
|
-
});
|
|
18
|
-
function readPreviewLocation(url) {
|
|
19
|
-
if (!url.searchParams.has(ENABLED_PARAMETER)) return void 0;
|
|
20
|
-
return Schema.decodeUnknownOption(PreviewLocationParameters)({
|
|
21
|
-
editorOrigin: url.searchParams.get(EDITOR_ORIGIN_PARAMETER),
|
|
22
|
-
sessionId: url.searchParams.get(SESSION_PARAMETER)
|
|
23
|
-
}).pipe(Option.getOrUndefined);
|
|
24
|
-
}
|
|
25
|
-
function withPreviewLocation(url, parameters) {
|
|
26
|
-
const next = new URL(url);
|
|
27
|
-
next.searchParams.set(ENABLED_PARAMETER, "1");
|
|
28
|
-
next.searchParams.set(EDITOR_ORIGIN_PARAMETER, parameters.editorOrigin);
|
|
29
|
-
next.searchParams.set(SESSION_PARAMETER, parameters.sessionId);
|
|
30
|
-
return next;
|
|
31
|
-
}
|
|
5
|
+
import { t as createStudioPreviewStore } from "../../store-CfFFx9Ua.js";
|
|
6
|
+
import { documentPreviewStoreKey } from "../delivery/preview.js";
|
|
7
|
+
import { Schema } from "effect";
|
|
8
|
+
import { defineNuxtPlugin, navigateTo, onNuxtReady, useNuxtApp, useState } from "nuxt/app";
|
|
9
|
+
import { watch } from "vue";
|
|
32
10
|
|
|
33
|
-
//#endregion
|
|
34
11
|
//#region src/runtime/preview/plugin.client.ts
|
|
35
|
-
var plugin_client_default = defineNuxtPlugin(
|
|
12
|
+
var plugin_client_default = defineNuxtPlugin(() => {
|
|
36
13
|
const parameters = readPreviewLocation(new URL(window.location.href));
|
|
37
14
|
if (!parameters) return;
|
|
38
15
|
const route = () => Schema.decodeSync(PublicPath)(window.location.pathname);
|
|
@@ -40,12 +17,21 @@ var plugin_client_default = defineNuxtPlugin(async () => {
|
|
|
40
17
|
const nuxtApp = useNuxtApp();
|
|
41
18
|
nuxtApp.vueApp.provide(documentPreviewStoreKey, store);
|
|
42
19
|
nuxtApp.hooks.hook("page:finish", store.routeChanged);
|
|
20
|
+
const error = useState("cms:preview-error", () => null);
|
|
43
21
|
const mount = async () => {
|
|
44
22
|
const connection = await openSitePreviewConnection({
|
|
45
23
|
editorOrigin: parameters.editorOrigin,
|
|
46
24
|
route: route(),
|
|
47
25
|
sessionId: parameters.sessionId
|
|
48
26
|
});
|
|
27
|
+
const sendError = () => connection.send({
|
|
28
|
+
type: "preview:error",
|
|
29
|
+
message: error.value
|
|
30
|
+
});
|
|
31
|
+
const stopError = watch(error, sendError, { immediate: true });
|
|
32
|
+
const stopConnect = connection.subscribe((message) => {
|
|
33
|
+
if (message.type === "studio:connect") sendError();
|
|
34
|
+
});
|
|
49
35
|
const unmount = mountPreviewController({
|
|
50
36
|
bridge: connection,
|
|
51
37
|
navigate: async (path) => {
|
|
@@ -57,12 +43,13 @@ var plugin_client_default = defineNuxtPlugin(async () => {
|
|
|
57
43
|
view: window
|
|
58
44
|
});
|
|
59
45
|
window.addEventListener("pagehide", () => {
|
|
46
|
+
stopError();
|
|
47
|
+
stopConnect();
|
|
60
48
|
unmount();
|
|
61
49
|
connection.close();
|
|
62
50
|
}, { once: true });
|
|
63
51
|
};
|
|
64
|
-
|
|
65
|
-
else await mount();
|
|
52
|
+
onNuxtReady(mount);
|
|
66
53
|
});
|
|
67
54
|
|
|
68
55
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.client.js","names":[
|
|
1
|
+
{"version":3,"file":"plugin.client.js","names":[],"sources":["../../../../../src/runtime/preview/plugin.client.ts"],"sourcesContent":["import { defineNuxtPlugin, navigateTo, onNuxtReady, useNuxtApp, useState } from 'nuxt/app'\nimport { watch } from 'vue'\nimport { PublicPath } from '@internal/protocol/Documents'\nimport { readPreviewLocation, withPreviewLocation } from '@internal/protocol/Preview'\nimport { Schema } from 'effect'\nimport { openSitePreviewConnection } from './connection'\nimport { mountPreviewController } from './controller'\nimport { createStudioPreviewStore, documentPreviewStoreKey } from './store'\n\nexport default defineNuxtPlugin(() => {\n const parameters = readPreviewLocation(new URL(window.location.href))\n if (!parameters) return\n const route = () => Schema.decodeSync(PublicPath)(window.location.pathname)\n const store = createStudioPreviewStore(route)\n const nuxtApp = useNuxtApp()\n nuxtApp.vueApp.provide(documentPreviewStoreKey, store)\n nuxtApp.hooks.hook('page:finish', store.routeChanged)\n\n const error = useState<string | null>('cms:preview-error', () => null)\n const mount = async () => {\n const connection = await openSitePreviewConnection({\n editorOrigin: parameters.editorOrigin,\n route: route(),\n sessionId: parameters.sessionId,\n })\n const sendError = () => connection.send({ type: 'preview:error', message: error.value })\n const stopError = watch(error, sendError, { immediate: true })\n const stopConnect = connection.subscribe((message) => {\n if (message.type === 'studio:connect') sendError()\n })\n const unmount = mountPreviewController({\n bridge: connection,\n navigate: async (path) => {\n const target = withPreviewLocation(new URL(path, window.location.origin), parameters)\n await navigateTo(`${target.pathname}${target.search}${target.hash}`)\n },\n root: document,\n store,\n view: window,\n })\n window.addEventListener(\n 'pagehide',\n () => {\n stopError()\n stopConnect()\n unmount()\n void connection.close()\n },\n { once: true },\n )\n }\n\n onNuxtReady(mount)\n})\n"],"mappings":";;;;;;;;;;;AASA,4BAAe,uBAAuB;CACpC,MAAM,aAAa,oBAAoB,IAAI,IAAI,OAAO,SAAS,IAAI,CAAC;CACpE,IAAI,CAAC,YAAY;CACjB,MAAM,cAAc,OAAO,WAAW,UAAU,CAAC,CAAC,OAAO,SAAS,QAAQ;CAC1E,MAAM,QAAQ,yBAAyB,KAAK;CAC5C,MAAM,UAAU,WAAW;CAC3B,QAAQ,OAAO,QAAQ,yBAAyB,KAAK;CACrD,QAAQ,MAAM,KAAK,eAAe,MAAM,YAAY;CAEpD,MAAM,QAAQ,SAAwB,2BAA2B,IAAI;CACrE,MAAM,QAAQ,YAAY;EACxB,MAAM,aAAa,MAAM,0BAA0B;GACjD,cAAc,WAAW;GACzB,OAAO,MAAM;GACb,WAAW,WAAW;EACxB,CAAC;EACD,MAAM,kBAAkB,WAAW,KAAK;GAAE,MAAM;GAAiB,SAAS,MAAM;EAAM,CAAC;EACvF,MAAM,YAAY,MAAM,OAAO,WAAW,EAAE,WAAW,KAAK,CAAC;EAC7D,MAAM,cAAc,WAAW,WAAW,YAAY;GACpD,IAAI,QAAQ,SAAS,kBAAkB,UAAU;EACnD,CAAC;EACD,MAAM,UAAU,uBAAuB;GACrC,QAAQ;GACR,UAAU,OAAO,SAAS;IACxB,MAAM,SAAS,oBAAoB,IAAI,IAAI,MAAM,OAAO,SAAS,MAAM,GAAG,UAAU;IACpF,MAAM,WAAW,GAAG,OAAO,WAAW,OAAO,SAAS,OAAO,MAAM;GACrE;GACA,MAAM;GACN;GACA,MAAM;EACR,CAAC;EACD,OAAO,iBACL,kBACM;GACJ,UAAU;GACV,YAAY;GACZ,QAAQ;GACR,AAAK,WAAW,MAAM;EACxB,GACA,EAAE,MAAM,KAAK,CACf;CACF;CAEA,YAAY,KAAK;AACnB,CAAC"}
|
|
@@ -1,9 +1,77 @@
|
|
|
1
1
|
[data-cms-preview-decorated] {
|
|
2
2
|
cursor: text;
|
|
3
|
-
outline-offset: 3px;
|
|
4
3
|
}
|
|
5
4
|
|
|
6
|
-
[data-cms-preview-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
[data-cms-preview-overlay] {
|
|
6
|
+
pointer-events: none !important;
|
|
7
|
+
position: fixed;
|
|
8
|
+
inset: 0;
|
|
9
|
+
z-index: 2147483647;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
[data-cms-selection-outline],
|
|
13
|
+
[data-cms-hover-outline] {
|
|
14
|
+
all: initial;
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
position: fixed;
|
|
17
|
+
pointer-events: none !important;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
[data-cms-selection-outline] {
|
|
21
|
+
border: 1px solid #fff;
|
|
22
|
+
outline: 1px solid #171717;
|
|
23
|
+
border-radius: 3px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
[data-cms-selection-outline][hidden],
|
|
27
|
+
[data-cms-hover-outline][hidden] {
|
|
28
|
+
display: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
[data-cms-selection-label]::after {
|
|
32
|
+
content: 'Editing';
|
|
33
|
+
position: absolute;
|
|
34
|
+
left: var(--cms-label-left, 0px);
|
|
35
|
+
top: var(--cms-label-top, -26px);
|
|
36
|
+
padding: 3px 7px;
|
|
37
|
+
border: 1px solid #fff;
|
|
38
|
+
border-radius: 4px;
|
|
39
|
+
background: #171717;
|
|
40
|
+
color: #fff;
|
|
41
|
+
font:
|
|
42
|
+
500 11px/16px system-ui,
|
|
43
|
+
sans-serif;
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
[data-cms-hover-corner] {
|
|
48
|
+
all: initial;
|
|
49
|
+
box-sizing: border-box;
|
|
50
|
+
position: absolute;
|
|
51
|
+
width: min(12px, 40%);
|
|
52
|
+
height: min(12px, 40%);
|
|
53
|
+
border-top: 2px solid #fff;
|
|
54
|
+
border-left: 2px solid #fff;
|
|
55
|
+
pointer-events: none !important;
|
|
56
|
+
filter: drop-shadow(1px 0 #171717) drop-shadow(-1px 0 #171717) drop-shadow(0 1px #171717) drop-shadow(0 -1px #171717);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
[data-cms-hover-corner='top-left'] {
|
|
60
|
+
top: 0;
|
|
61
|
+
left: 0;
|
|
62
|
+
}
|
|
63
|
+
[data-cms-hover-corner='top-right'] {
|
|
64
|
+
top: 0;
|
|
65
|
+
right: 0;
|
|
66
|
+
transform: rotate(90deg);
|
|
67
|
+
}
|
|
68
|
+
[data-cms-hover-corner='bottom-right'] {
|
|
69
|
+
bottom: 0;
|
|
70
|
+
right: 0;
|
|
71
|
+
transform: rotate(180deg);
|
|
72
|
+
}
|
|
73
|
+
[data-cms-hover-corner='bottom-left'] {
|
|
74
|
+
bottom: 0;
|
|
75
|
+
left: 0;
|
|
76
|
+
transform: rotate(270deg);
|
|
9
77
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
+
import { t as createStudioPreviewStore } from "../../store-CfFFx9Ua.js";
|
|
1
2
|
import { documentPreviewStoreKey } from "../delivery/preview.js";
|
|
2
|
-
import { t as createStudioPreviewStore } from "../../store-Nl4uxEXx.js";
|
|
3
3
|
|
|
4
4
|
export { createStudioPreviewStore, documentPreviewStoreKey };
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { defineEventHandler, setResponseHeader } from "h3";
|
|
2
2
|
|
|
3
3
|
//#region src/runtime/studio-app.ts
|
|
4
|
-
function createStudioAppHandler(
|
|
4
|
+
function createStudioAppHandler(entryUrl, hmrUrl) {
|
|
5
|
+
const escape = (value) => value.replaceAll("&", "&").replaceAll("\"", """).replaceAll("<", "<");
|
|
6
|
+
const script = (url) => `<script type="module" src="${escape(url)}"><\/script>`;
|
|
7
|
+
const shell = `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>CMS Studio</title></head><body><div id="cms-studio"></div>${hmrUrl ? script(hmrUrl) : ""}${script(entryUrl)}</body></html>`;
|
|
5
8
|
return defineEventHandler((event) => {
|
|
6
9
|
setResponseHeader(event, "content-type", "text/html; charset=utf-8");
|
|
10
|
+
setResponseHeader(event, "cache-control", "no-store");
|
|
7
11
|
return shell;
|
|
8
12
|
});
|
|
9
13
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"studio-app.js","names":[],"sources":["../../../../src/runtime/studio-app.ts"],"sourcesContent":["import { defineEventHandler, setResponseHeader } from 'h3'\n\nexport function createStudioAppHandler(
|
|
1
|
+
{"version":3,"file":"studio-app.js","names":[],"sources":["../../../../src/runtime/studio-app.ts"],"sourcesContent":["import { defineEventHandler, setResponseHeader } from 'h3'\n\nexport function createStudioAppHandler(entryUrl: string, hmrUrl?: string) {\n const escape = (value: string) => value.replaceAll('&', '&').replaceAll('\"', '"').replaceAll('<', '<')\n const script = (url: string) => `<script type=\"module\" src=\"${escape(url)}\"></script>`\n const shell = `<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>CMS Studio</title></head><body><div id=\"cms-studio\"></div>${hmrUrl ? script(hmrUrl) : ''}${script(entryUrl)}</body></html>`\n return defineEventHandler((event) => {\n setResponseHeader(event, 'content-type', 'text/html; charset=utf-8')\n setResponseHeader(event, 'cache-control', 'no-store')\n return shell\n })\n}\n"],"mappings":";;;AAEA,SAAgB,uBAAuB,UAAkB,QAAiB;CACxE,MAAM,UAAU,UAAkB,MAAM,WAAW,KAAK,OAAO,CAAC,CAAC,WAAW,MAAK,QAAQ,CAAC,CAAC,WAAW,KAAK,MAAM;CACjH,MAAM,UAAU,QAAgB,8BAA8B,OAAO,GAAG,EAAE;CAC1E,MAAM,QAAQ,mMAAmM,SAAS,OAAO,MAAM,IAAI,KAAK,OAAO,QAAQ,EAAE;CACjQ,OAAO,oBAAoB,UAAU;EACnC,kBAAkB,OAAO,gBAAgB,0BAA0B;EACnE,kBAAkB,OAAO,iBAAiB,UAAU;EACpD,OAAO;CACT,CAAC;AACH"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { mountStudio } from "#cms/studio";
|
|
2
|
+
import catalog from "#cms/authoring";
|
|
3
|
+
import stylesheet from "#cms/studio-styles";
|
|
4
|
+
|
|
5
|
+
//#region src/runtime/studio-entry.ts
|
|
6
|
+
const root = document.getElementById("cms-studio");
|
|
7
|
+
if (!root) throw new Error("CMS Studio root is missing.");
|
|
8
|
+
let currentCatalog = catalog;
|
|
9
|
+
let studio;
|
|
10
|
+
const link = document.createElement("link");
|
|
11
|
+
link.rel = "stylesheet";
|
|
12
|
+
link.href = stylesheet;
|
|
13
|
+
link.onload = () => {
|
|
14
|
+
studio = mountStudio(root, currentCatalog);
|
|
15
|
+
};
|
|
16
|
+
link.onerror = () => {
|
|
17
|
+
root.textContent = "CMS Studio styles could not load. Reload this page to retry.";
|
|
18
|
+
};
|
|
19
|
+
document.head.append(link);
|
|
20
|
+
if (import.meta.hot) {
|
|
21
|
+
import.meta.hot.accept("#cms/authoring", (module) => {
|
|
22
|
+
if (!module) return;
|
|
23
|
+
currentCatalog = module.default;
|
|
24
|
+
studio?.updateAuthoring(currentCatalog);
|
|
25
|
+
});
|
|
26
|
+
import.meta.hot.dispose(() => {
|
|
27
|
+
link.onload = null;
|
|
28
|
+
link.onerror = null;
|
|
29
|
+
studio?.unmount();
|
|
30
|
+
link.remove();
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
export { };
|
|
36
|
+
//# sourceMappingURL=studio-entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-entry.js","names":[],"sources":["../../../../src/runtime/studio-entry.ts"],"sourcesContent":["import { mountStudio } from '#cms/studio'\nimport catalog from '#cms/authoring'\nimport stylesheet from '#cms/studio-styles'\n\nconst root = document.getElementById('cms-studio')\nif (!root) throw new Error('CMS Studio root is missing.')\nlet currentCatalog = catalog\nlet studio: ReturnType<typeof mountStudio> | undefined\nconst link = document.createElement('link')\nlink.rel = 'stylesheet'\nlink.href = stylesheet\nlink.onload = () => {\n studio = mountStudio(root, currentCatalog)\n}\nlink.onerror = () => {\n root.textContent = 'CMS Studio styles could not load. Reload this page to retry.'\n}\ndocument.head.append(link)\nif (import.meta.hot) {\n import.meta.hot.accept('#cms/authoring', (module) => {\n if (!module) return\n currentCatalog = module.default\n studio?.updateAuthoring(currentCatalog)\n })\n import.meta.hot.dispose(() => {\n link.onload = null\n link.onerror = null\n studio?.unmount()\n link.remove()\n })\n}\n"],"mappings":";;;;;AAIA,MAAM,OAAO,SAAS,eAAe,YAAY;AACjD,IAAI,CAAC,MAAM,MAAM,IAAI,MAAM,6BAA6B;AACxD,IAAI,iBAAiB;AACrB,IAAI;AACJ,MAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,KAAK,MAAM;AACX,KAAK,OAAO;AACZ,KAAK,eAAe;CAClB,SAAS,YAAY,MAAM,cAAc;AAC3C;AACA,KAAK,gBAAgB;CACnB,KAAK,cAAc;AACrB;AACA,SAAS,KAAK,OAAO,IAAI;AACzB,IAAI,YAAY,KAAK;CACnB,YAAY,IAAI,OAAO,mBAAmB,WAAW;EACnD,IAAI,CAAC,QAAQ;EACb,iBAAiB,OAAO;EACxB,QAAQ,gBAAgB,cAAc;CACxC,CAAC;CACD,YAAY,IAAI,cAAc;EAC5B,KAAK,SAAS;EACd,KAAK,UAAU;EACf,QAAQ,QAAQ;EAChB,KAAK,OAAO;CACd,CAAC;AACH"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { l as STUDIO_APP_PATH, u as STUDIO_BASE_PATH } from "../HttpPaths-BbS21Jy8.js";
|
|
2
|
+
import { defineNuxtRouteMiddleware, navigateTo } from "nuxt/app";
|
|
3
|
+
|
|
4
|
+
//#region src/runtime/studio-navigation.ts
|
|
5
|
+
var studio_navigation_default = defineNuxtRouteMiddleware((to) => {
|
|
6
|
+
if (to.path === "/_cms" || to.path === STUDIO_APP_PATH || to.path.startsWith(`${STUDIO_APP_PATH}/`)) return navigateTo(to.fullPath, { external: true });
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
export { studio_navigation_default as default };
|
|
11
|
+
//# sourceMappingURL=studio-navigation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"studio-navigation.js","names":[],"sources":["../../../../src/runtime/studio-navigation.ts"],"sourcesContent":["import { defineNuxtRouteMiddleware, navigateTo } from 'nuxt/app'\nimport { STUDIO_APP_PATH, STUDIO_BASE_PATH } from '@internal/protocol/HttpPaths'\n\nexport default defineNuxtRouteMiddleware((to) => {\n if (to.path === STUDIO_BASE_PATH || to.path === STUDIO_APP_PATH || to.path.startsWith(`${STUDIO_APP_PATH}/`)) {\n return navigateTo(to.fullPath, { external: true })\n }\n})\n"],"mappings":";;;;AAGA,gCAAe,2BAA2B,OAAO;CAC/C,IAAI,GAAG,oBAA6B,GAAG,SAAS,mBAAmB,GAAG,KAAK,WAAW,GAAG,gBAAgB,EAAE,GACzG,OAAO,WAAW,GAAG,UAAU,EAAE,UAAU,KAAK,CAAC;AAErD,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { l as mutableJson, n as editorMetadata, u as mutableJsonObject } from "./metadata-
|
|
1
|
+
import { gt as DocumentId, n as CmsMarkdownDocument, ut as CollectionName, yt as PublicPath } from "./models-BkMgeaOL.js";
|
|
2
|
+
import { l as mutableJson, n as editorMetadata, u as mutableJsonObject } from "./metadata-DE1Mc2td.js";
|
|
3
3
|
import { CMS_PREVIEW_INLINE_HOST_ATTRIBUTE, CMS_PREVIEW_MARKER_TAG, CMS_PREVIEW_NODE_ATTRIBUTE, CMS_PREVIEW_TARGET_ATTRIBUTE, CMS_PREVIEW_WRAPPER_ATTRIBUTE } from "./runtime/preview/protocol.js";
|
|
4
4
|
import { toPreviewRenderDocument } from "./runtime/preview/comark-document.js";
|
|
5
5
|
import { Predicate, Result, Schema } from "effect";
|
|
@@ -218,4 +218,4 @@ function createPreviewDocument(body) {
|
|
|
218
218
|
|
|
219
219
|
//#endregion
|
|
220
220
|
export { createStudioPreviewStore as t };
|
|
221
|
-
//# sourceMappingURL=store-
|
|
221
|
+
//# sourceMappingURL=store-CfFFx9Ua.js.map
|