@phtngyn/cms 0.1.0-beta.1 → 0.1.0-beta.3
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 +212 -12
- package/bin/cms.mjs +2 -0
- package/package.json +30 -15
- package/src/{Configuration-DyKo0sLS.js → Configuration-CDMYfTre.js} +26 -147
- package/src/Configuration-CDMYfTre.js.map +1 -0
- package/src/Configuration.d.ts +24 -8
- package/src/Configuration.js +0 -1
- package/src/Configuration.js.map +1 -1
- package/src/ContentTransfer-C3Av9sWz.js +53 -0
- package/src/ContentTransfer-C3Av9sWz.js.map +1 -0
- package/src/{DocumentEngine-DYObwMDY.js → DocumentEngine-J7g-emdf.js} +75 -27
- package/src/DocumentEngine-J7g-emdf.js.map +1 -0
- package/src/DocumentModel.d.ts +8 -9
- package/src/DocumentModel.js +13 -3
- package/src/DocumentModel.js.map +1 -1
- package/src/Forms-BsJMev5_.d.ts +74 -0
- package/src/Forms-CfcI3tPU.js +79 -0
- package/src/Forms-CfcI3tPU.js.map +1 -0
- package/src/Forms-Dj6NuW66.js +367 -0
- package/src/Forms-Dj6NuW66.js.map +1 -0
- package/src/Forms.d.ts +51 -0
- package/src/Forms.js +13 -0
- package/src/Forms.js.map +1 -0
- package/src/{HttpPaths-BbS21Jy8.js → HttpPaths-c9nLZ9H2.js} +6 -2
- package/src/HttpPaths-c9nLZ9H2.js.map +1 -0
- package/src/I18n.d.ts +20 -0
- package/src/I18n.js +1 -0
- package/src/Module.js +59 -14
- package/src/Module.js.map +1 -1
- package/src/S3MediaObjects-CpPSzJto.js +2777 -0
- package/src/S3MediaObjects-CpPSzJto.js.map +1 -0
- package/src/Seo-402YumpT.d.ts +198 -0
- package/src/cli/content.js +258 -0
- package/src/cli/content.js.map +1 -0
- package/src/cli.js +71 -0
- package/src/cli.js.map +1 -0
- package/src/{connection-CBTY-TzB.js → connection-CBAy2qGy.js} +5 -7
- package/src/connection-CBAy2qGy.js.map +1 -0
- package/src/{installation-DeuBiFRE.js → installation-CNfIriVm.js} +1007 -2246
- package/src/installation-CNfIriVm.js.map +1 -0
- package/src/internal/authoring-catalog.js +10 -4
- package/src/internal/authoring-catalog.js.map +1 -1
- package/src/internal/authoring-compiler.js +0 -1
- package/src/internal/authoring-compiler.js.map +1 -1
- package/src/internal/authoring-metadata.js +4 -4
- package/src/internal/authoring-metadata.js.map +1 -1
- package/src/internal/cms-config.js +0 -1
- package/src/internal/cms-config.js.map +1 -1
- package/src/internal/configuration.js +26 -17
- package/src/internal/configuration.js.map +1 -1
- package/src/internal/document-model.js +69 -21
- package/src/internal/document-model.js.map +1 -1
- package/src/internal/form-capabilities.js +12 -0
- package/src/internal/form-capabilities.js.map +1 -0
- package/src/internal/i18n.js +47 -0
- package/src/internal/i18n.js.map +1 -0
- package/src/internal/studio-app.js +2 -2
- package/src/internal/studio-app.js.map +1 -1
- package/src/{location-DtYv2aes.js → location-BTqdfIzX.js} +2 -3
- package/src/location-BTqdfIzX.js.map +1 -0
- package/src/{metadata-DE1Mc2td.js → metadata-BEZPWh-3.js} +3 -72
- package/src/metadata-BEZPWh-3.js.map +1 -0
- package/src/{models-C3witQBK.js → models-B4IoTmp7.js} +3 -2
- package/src/models-B4IoTmp7.js.map +1 -0
- package/src/{models-BkMgeaOL.js → models-Bah5B3bT.js} +205 -51
- package/src/models-Bah5B3bT.js.map +1 -0
- package/src/runtime/blocks.js +22 -9
- package/src/runtime/blocks.js.map +1 -1
- package/src/runtime/collaboration.js.map +1 -1
- package/src/runtime/delivery/DocumentRenderer.js +7 -4
- package/src/runtime/delivery/DocumentRenderer.js.map +1 -1
- package/src/runtime/delivery/blocks.js +3 -1
- package/src/runtime/delivery/blocks.js.map +1 -1
- package/src/runtime/delivery/context.js +1 -1
- package/src/runtime/delivery/document-page.js +12 -12
- package/src/runtime/delivery/document-page.js.map +1 -1
- package/src/runtime/delivery/document.js +4 -2
- package/src/runtime/delivery/document.js.map +1 -1
- package/src/runtime/delivery/error.js.map +1 -1
- package/src/runtime/delivery/plugin.js +28 -2
- package/src/runtime/delivery/plugin.js.map +1 -1
- package/src/runtime/delivery/types.d.ts +5 -0
- package/src/runtime/delivery/useCmsDocumentSeo.d.ts +59 -0
- package/src/runtime/delivery/useCmsDocumentSeo.js +101 -0
- package/src/runtime/delivery/useCmsDocumentSeo.js.map +1 -0
- package/src/runtime/delivery/useDocument.js +2 -2
- package/src/runtime/delivery/useDocument.js.map +1 -1
- package/src/runtime/delivery/useDocumentQuery.js +2 -2
- package/src/runtime/delivery/useDocumentQuery.js.map +1 -1
- package/src/runtime/forms/document.js +38 -0
- package/src/runtime/forms/document.js.map +1 -0
- package/src/runtime/forms/useCmsForm.js +190 -0
- package/src/runtime/forms/useCmsForm.js.map +1 -0
- package/src/runtime/i18n/translator.js +51 -0
- package/src/runtime/i18n/translator.js.map +1 -0
- package/src/runtime/i18n/useCmsI18n.d.ts +11 -0
- package/src/runtime/i18n/useCmsI18n.js +37 -0
- package/src/runtime/i18n/useCmsI18n.js.map +1 -0
- 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/comark-document.js +0 -1
- package/src/runtime/preview/comark-document.js.map +1 -1
- package/src/runtime/preview/connection.js +1 -1
- package/src/runtime/preview/controller.js +10 -3
- package/src/runtime/preview/controller.js.map +1 -1
- package/src/runtime/preview/overlay.js.map +1 -1
- package/src/runtime/preview/plugin.client.js +59 -48
- package/src/runtime/preview/plugin.client.js.map +1 -1
- package/src/runtime/preview/protocol.js.map +1 -1
- package/src/runtime/preview/store.js +1 -1
- package/src/runtime/preview/targets.js +0 -1
- package/src/runtime/preview/targets.js.map +1 -1
- package/src/runtime/sitemap-entries.js +17 -0
- package/src/runtime/sitemap-entries.js.map +1 -0
- package/src/runtime/sitemap.js +24 -0
- package/src/runtime/sitemap.js.map +1 -0
- package/src/runtime/studio-app.js.map +1 -1
- package/src/runtime/studio-entry.js +2 -2
- package/src/runtime/studio-entry.js.map +1 -1
- package/src/runtime/studio-navigation.js +1 -1
- package/src/scalars-B2lgGUnj.js +26 -0
- package/src/scalars-B2lgGUnj.js.map +1 -0
- package/src/{store-CfFFx9Ua.js → store-b2CSXgMt.js} +12 -7
- package/src/store-b2CSXgMt.js.map +1 -0
- package/studio/{CreateDocumentDialog--L9lTfx6.js → CreateDocumentDialog-GGey1uBc.js} +44 -44
- package/studio/{collaboration-DUuu678R.js → collaboration-DcK2F6v9.js} +7 -6
- package/studio/{documentPlanning-BXX04Woe.js → documentPlanning-DRErYmBU.js} +7340 -6469
- package/studio/{editor-PexnXkJY.js → editor-Bzlh3zXt.js} +7965 -7955
- package/studio/host.css +1 -1
- package/studio/host.js +10416 -7981
- package/src/Configuration-DyKo0sLS.js.map +0 -1
- package/src/DocumentEngine-DYObwMDY.js.map +0 -1
- package/src/HttpPaths-BbS21Jy8.js.map +0 -1
- package/src/StudioHttp-jR2-bc01.js +0 -718
- package/src/StudioHttp-jR2-bc01.js.map +0 -1
- package/src/connection-CBTY-TzB.js.map +0 -1
- package/src/installation-DeuBiFRE.js.map +0 -1
- package/src/location-DtYv2aes.js.map +0 -1
- package/src/metadata-DE1Mc2td.js.map +0 -1
- package/src/models-BkMgeaOL.js.map +0 -1
- package/src/models-C3witQBK.js.map +0 -1
- package/src/store-CfFFx9Ua.js.map +0 -1
|
@@ -2,21 +2,21 @@ import DocumentRenderer_default from "./DocumentRenderer.js";
|
|
|
2
2
|
import { h } from "vue";
|
|
3
3
|
|
|
4
4
|
//#region src/runtime/delivery/document-page.ts
|
|
5
|
-
function resolveDocumentPage(request
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return request.ready.then(() => {
|
|
11
|
-
const failure = request.error() ?? (!request.page() ? request.notFound() : void 0);
|
|
5
|
+
function resolveDocumentPage(request) {
|
|
6
|
+
function render() {
|
|
7
|
+
const error = request.error();
|
|
8
|
+
const page = request.page();
|
|
9
|
+
const failure = error ?? (!page ? request.notFound() : void 0);
|
|
12
10
|
if (failure) {
|
|
13
|
-
if (request.renderError) return request.renderError(failure);
|
|
11
|
+
if (request.renderError) return request.renderError(failure)();
|
|
14
12
|
throw failure;
|
|
15
13
|
}
|
|
16
|
-
return ()
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
return page ? h(DocumentRenderer_default, { value: page }) : void 0;
|
|
15
|
+
}
|
|
16
|
+
return request.ready.then(() => {
|
|
17
|
+
const failure = request.error() ?? (!request.page() ? request.notFound() : void 0);
|
|
18
|
+
if (failure && !request.renderError) throw failure;
|
|
19
|
+
return render;
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-page.js","names":["DocumentRenderer"],"sources":["../../../../../src/runtime/delivery/document-page.ts"],"sourcesContent":["import type { VNode } from 'vue'\nimport type { DeliveryDocument } from './types'\nimport { h } from 'vue'\nimport DocumentRenderer from './DocumentRenderer'\n\nexport interface
|
|
1
|
+
{"version":3,"file":"document-page.js","names":["DocumentRenderer"],"sources":["../../../../../src/runtime/delivery/document-page.ts"],"sourcesContent":["import type { VNode } from 'vue'\nimport type { DeliveryDocument } from './types'\nimport { h } from 'vue'\nimport DocumentRenderer from './DocumentRenderer'\n\nexport interface DocumentPageRequest {\n readonly error: () => Error | undefined\n readonly notFound: () => Error\n readonly page: () => DeliveryDocument | null\n readonly renderError?: ((error: Error) => () => VNode) | undefined\n readonly ready: Promise<unknown>\n}\n\nexport function resolveDocumentPage(request: DocumentPageRequest): Promise<() => VNode | undefined> {\n function render(): VNode | undefined {\n const error = request.error()\n const page = request.page()\n const failure = error ?? (!page ? request.notFound() : undefined)\n\n if (failure) {\n if (request.renderError) return request.renderError(failure)()\n throw failure\n }\n\n return page ? h(DocumentRenderer, { value: page }) : undefined\n }\n\n return request.ready.then(() => {\n // Reject initial delivery failures during setup so Nuxt can set the HTTP status.\n const failure = request.error() ?? (!request.page() ? request.notFound() : undefined)\n\n if (failure && !request.renderError) throw failure\n\n return render\n })\n}\n"],"mappings":";;;;AAaA,SAAgB,oBAAoB,SAAgE;CAClG,SAAS,SAA4B;EACnC,MAAM,QAAQ,QAAQ,MAAM;EAC5B,MAAM,OAAO,QAAQ,KAAK;EAC1B,MAAM,UAAU,UAAU,CAAC,OAAO,QAAQ,SAAS,IAAI;EAEvD,IAAI,SAAS;GACX,IAAI,QAAQ,aAAa,OAAO,QAAQ,YAAY,OAAO,CAAC,CAAC;GAC7D,MAAM;EACR;EAEA,OAAO,OAAO,EAAEA,0BAAkB,EAAE,OAAO,KAAK,CAAC,IAAI;CACvD;CAEA,OAAO,QAAQ,MAAM,WAAW;EAE9B,MAAM,UAAU,QAAQ,MAAM,MAAM,CAAC,QAAQ,KAAK,IAAI,QAAQ,SAAS,IAAI;EAE3E,IAAI,WAAW,CAAC,QAAQ,aAAa,MAAM;EAE3C,OAAO;CACT,CAAC;AACH"}
|
|
@@ -2,8 +2,9 @@ import { usePreviewDelivery } from "./context.js";
|
|
|
2
2
|
import { resolveDocumentPage } from "./document-page.js";
|
|
3
3
|
import { previewErrorMessage } from "./error.js";
|
|
4
4
|
import { useDocument } from "./useDocument.js";
|
|
5
|
-
import {
|
|
5
|
+
import { useCmsDocumentSeo } from "./useCmsDocumentSeo.js";
|
|
6
6
|
import { h } from "vue";
|
|
7
|
+
import { createError, defineNuxtComponent, useRoute, useState } from "nuxt/app";
|
|
7
8
|
|
|
8
9
|
//#region src/runtime/delivery/document.ts
|
|
9
10
|
var document_default = defineNuxtComponent({
|
|
@@ -13,6 +14,7 @@ var document_default = defineNuxtComponent({
|
|
|
13
14
|
const preview = usePreviewDelivery();
|
|
14
15
|
const previewError = useState("cms:preview-error", () => null);
|
|
15
16
|
const request = useDocument(() => route.path);
|
|
17
|
+
useCmsDocumentSeo(() => request.data.value);
|
|
16
18
|
return resolveDocumentPage({
|
|
17
19
|
error: () => request.error.value,
|
|
18
20
|
renderError: preview.value ? (error) => {
|
|
@@ -32,7 +34,7 @@ var document_default = defineNuxtComponent({
|
|
|
32
34
|
return request.data.value;
|
|
33
35
|
},
|
|
34
36
|
ready: request
|
|
35
|
-
}
|
|
37
|
+
});
|
|
36
38
|
}
|
|
37
39
|
});
|
|
38
40
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.js","names":[],"sources":["../../../../../src/runtime/delivery/document.ts"],"sourcesContent":["import { createError, defineNuxtComponent, useRoute,
|
|
1
|
+
{"version":3,"file":"document.js","names":[],"sources":["../../../../../src/runtime/delivery/document.ts"],"sourcesContent":["import { createError, defineNuxtComponent, useRoute, useState } from 'nuxt/app'\nimport { h } from 'vue'\nimport { usePreviewDelivery } from './context'\nimport { previewErrorMessage } from './error'\nimport { resolveDocumentPage } from './document-page'\nimport { useDocument } from './useDocument'\nimport { useCmsDocumentSeo } from './useCmsDocumentSeo'\n\nexport default defineNuxtComponent({\n name: 'CmsDocumentPage',\n setup() {\n const route = useRoute()\n const preview = usePreviewDelivery()\n const previewError = useState<string | null>('cms:preview-error', () => null)\n const request = useDocument(() => route.path)\n\n useCmsDocumentSeo(() => request.data.value)\n\n return resolveDocumentPage({\n error: () => request.error.value,\n renderError: preview.value\n ? (error) => {\n const status = createError(error).statusCode ?? 500\n previewError.value = previewErrorMessage(status)\n\n return () => h('p', { role: 'alert', class: 'p-6' }, previewError.value ?? '')\n }\n : undefined,\n notFound: () =>\n createError({\n statusCode: 404,\n statusMessage: 'Document not found',\n }),\n page: () => {\n if (request.data.value) previewError.value = null\n\n return request.data.value\n },\n ready: request,\n })\n },\n})\n"],"mappings":";;;;;;;;;AAQA,uBAAe,oBAAoB;CACjC,MAAM;CACN,QAAQ;EACN,MAAM,QAAQ,SAAS;EACvB,MAAM,UAAU,mBAAmB;EACnC,MAAM,eAAe,SAAwB,2BAA2B,IAAI;EAC5E,MAAM,UAAU,kBAAkB,MAAM,IAAI;EAE5C,wBAAwB,QAAQ,KAAK,KAAK;EAE1C,OAAO,oBAAoB;GACzB,aAAa,QAAQ,MAAM;GAC3B,aAAa,QAAQ,SAChB,UAAU;IACT,MAAM,SAAS,YAAY,KAAK,CAAC,CAAC,cAAc;IAChD,aAAa,QAAQ,oBAAoB,MAAM;IAE/C,aAAa,EAAE,KAAK;KAAE,MAAM;KAAS,OAAO;IAAM,GAAG,aAAa,SAAS,EAAE;GAC/E,IACA;GACJ,gBACE,YAAY;IACV,YAAY;IACZ,eAAe;GACjB,CAAC;GACH,YAAY;IACV,IAAI,QAAQ,KAAK,OAAO,aAAa,QAAQ;IAE7C,OAAO,QAAQ,KAAK;GACtB;GACA,OAAO;EACT,CAAC;CACH;AACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.js","names":[],"sources":["../../../../../src/runtime/delivery/error.ts"],"sourcesContent":["export function previewErrorMessage(status: number): string {\n if (status === 401) return 'Your session has expired. Sign in to Studio and reload the preview.'\n if (status === 403) return 'You do not have permission to preview this page.'\n if (status === 404) return 'This page could not be found. It may have moved or been deleted.'\n return 'The preview could not load. Try reloading the page.'\n}\n"],"mappings":";AAAA,SAAgB,oBAAoB,QAAwB;CAC1D,IAAI,WAAW,KAAK,OAAO;
|
|
1
|
+
{"version":3,"file":"error.js","names":[],"sources":["../../../../../src/runtime/delivery/error.ts"],"sourcesContent":["export function previewErrorMessage(status: number): string {\n if (status === 401) return 'Your session has expired. Sign in to Studio and reload the preview.'\n\n if (status === 403) return 'You do not have permission to preview this page.'\n\n if (status === 404) return 'This page could not be found. It may have moved or been deleted.'\n\n return 'The preview could not load. Try reloading the page.'\n}\n"],"mappings":";AAAA,SAAgB,oBAAoB,QAAwB;CAC1D,IAAI,WAAW,KAAK,OAAO;CAE3B,IAAI,WAAW,KAAK,OAAO;CAE3B,IAAI,WAAW,KAAK,OAAO;CAE3B,OAAO;AACT"}
|
|
@@ -1,9 +1,35 @@
|
|
|
1
|
-
import { n as readPreviewLocation, t as previewRedirect } from "../../location-
|
|
1
|
+
import { n as readPreviewLocation, t as previewRedirect } from "../../location-BTqdfIzX.js";
|
|
2
2
|
import { usePreviewDelivery } from "./context.js";
|
|
3
|
-
import {
|
|
3
|
+
import { installCmsDocumentSeoAdapters } from "./useCmsDocumentSeo.js";
|
|
4
|
+
import { localeFromPath } from "../i18n/translator.js";
|
|
5
|
+
import { computed, watch } from "vue";
|
|
6
|
+
import { addRouteMiddleware, defineNuxtPlugin, useHead, useRequestURL, useResponseHeader, useRoute, useSeoMeta } from "nuxt/app";
|
|
7
|
+
import configuration from "#cms/i18n";
|
|
8
|
+
import { useRobotsRule, useSchemaOrg } from "#imports";
|
|
4
9
|
|
|
5
10
|
//#region src/runtime/delivery/plugin.ts
|
|
6
11
|
var plugin_default = defineNuxtPlugin(() => {
|
|
12
|
+
if (configuration.defaultLocale) {
|
|
13
|
+
const route = useRoute();
|
|
14
|
+
useHead({ htmlAttrs: { lang: computed(() => localeFromPath(configuration, route.path)) } });
|
|
15
|
+
}
|
|
16
|
+
installCmsDocumentSeoAdapters({
|
|
17
|
+
head: (input) => {
|
|
18
|
+
useHead(input);
|
|
19
|
+
},
|
|
20
|
+
robots: (input) => {
|
|
21
|
+
const robots = useRobotsRule(input);
|
|
22
|
+
if (import.meta.server) watch(input, (value) => {
|
|
23
|
+
robots.value = value;
|
|
24
|
+
}, { flush: "sync" });
|
|
25
|
+
},
|
|
26
|
+
schema: (input) => {
|
|
27
|
+
useSchemaOrg(input);
|
|
28
|
+
},
|
|
29
|
+
seoMeta: (input) => {
|
|
30
|
+
useSeoMeta(input);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
7
33
|
const url = useRequestURL();
|
|
8
34
|
const parameters = readPreviewLocation(url);
|
|
9
35
|
if (!usePreviewDelivery().value || !parameters) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","names":[],"sources":["../../../../../src/runtime/delivery/plugin.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"plugin.js","names":[],"sources":["../../../../../src/runtime/delivery/plugin.ts"],"sourcesContent":["import configuration from '#cms/i18n'\nimport {\n addRouteMiddleware,\n defineNuxtPlugin,\n useHead,\n useRequestURL,\n useResponseHeader,\n useRoute,\n useSeoMeta,\n} from 'nuxt/app'\nimport { useRobotsRule, useSchemaOrg } from '#imports'\nimport { previewRedirect, readPreviewLocation } from '@internal/protocol/Preview'\nimport { computed, watch } from 'vue'\nimport { usePreviewDelivery } from './context'\nimport { installCmsDocumentSeoAdapters } from './useCmsDocumentSeo'\nimport { localeFromPath } from '../i18n/translator'\n\nexport default defineNuxtPlugin(() => {\n if (configuration.defaultLocale) {\n const route = useRoute()\n\n useHead({ htmlAttrs: { lang: computed(() => localeFromPath(configuration, route.path)) } })\n }\n\n installCmsDocumentSeoAdapters({\n head: (input) => {\n useHead(input)\n },\n robots: (input) => {\n const robots = useRobotsRule(input)\n\n if (import.meta.server) {\n watch(\n input,\n (value) => {\n robots.value = value\n },\n { flush: 'sync' },\n )\n }\n },\n schema: (input) => {\n useSchemaOrg(input)\n },\n seoMeta: (input) => {\n useSeoMeta(input)\n },\n })\n\n const url = useRequestURL()\n const parameters = readPreviewLocation(url)\n const preview = usePreviewDelivery()\n\n if (!preview.value || !parameters) return\n\n if (import.meta.server) {\n useResponseHeader('cache-control').value = 'private, no-store'\n useResponseHeader('x-frame-options').value = 'SAMEORIGIN'\n }\n\n addRouteMiddleware(\n 'cms-preview',\n (to) => {\n return previewRedirect(new URL(to.fullPath, url.origin), parameters)\n },\n { global: true },\n )\n})\n"],"mappings":";;;;;;;;;;AAiBA,qBAAe,uBAAuB;CACpC,IAAI,cAAc,eAAe;EAC/B,MAAM,QAAQ,SAAS;EAEvB,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,eAAe,eAAe,MAAM,IAAI,CAAC,EAAE,EAAE,CAAC;CAC5F;CAEA,8BAA8B;EAC5B,OAAO,UAAU;GACf,QAAQ,KAAK;EACf;EACA,SAAS,UAAU;GACjB,MAAM,SAAS,cAAc,KAAK;GAElC,IAAI,YAAY,QACd,MACE,QACC,UAAU;IACT,OAAO,QAAQ;GACjB,GACA,EAAE,OAAO,OAAO,CAClB;EAEJ;EACA,SAAS,UAAU;GACjB,aAAa,KAAK;EACpB;EACA,UAAU,UAAU;GAClB,WAAW,KAAK;EAClB;CACF,CAAC;CAED,MAAM,MAAM,cAAc;CAC1B,MAAM,aAAa,oBAAoB,GAAG;CAG1C,IAAI,CAFY,mBAEL,CAAC,CAAC,SAAS,CAAC,YAAY;CAEnC,IAAI,YAAY,QAAQ;EACtB,kBAAkB,eAAe,CAAC,CAAC,QAAQ;EAC3C,kBAAkB,iBAAiB,CAAC,CAAC,QAAQ;CAC/C;CAEA,mBACE,gBACC,OAAO;EACN,OAAO,gBAAgB,IAAI,IAAI,GAAG,UAAU,IAAI,MAAM,GAAG,UAAU;CACrE,GACA,EAAE,QAAQ,KAAK,CACjB;AACF,CAAC"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { n as ResolvedSeo, t as DocumentSeo } from "../../Seo-402YumpT.js";
|
|
2
|
+
import { DateTime } from "effect";
|
|
1
3
|
//#region src/runtime/delivery/types.d.ts
|
|
2
4
|
export type DeliveryJson = null | boolean | number | string | ReadonlyArray<DeliveryJson> | DeliveryJsonObject;
|
|
3
5
|
export interface DeliveryJsonObject {
|
|
@@ -40,6 +42,8 @@ export interface DeliveryDocument {
|
|
|
40
42
|
readonly key: string;
|
|
41
43
|
readonly locale?: string;
|
|
42
44
|
readonly path: string;
|
|
45
|
+
readonly resolvedSeo?: ResolvedSeo;
|
|
46
|
+
readonly seo?: DocumentSeo;
|
|
43
47
|
readonly source: {
|
|
44
48
|
readonly mappings: ReadonlyArray<{
|
|
45
49
|
readonly nodePath: ReadonlyArray<number>;
|
|
@@ -57,6 +61,7 @@ export interface DeliveryDocument {
|
|
|
57
61
|
};
|
|
58
62
|
}>;
|
|
59
63
|
readonly path: string;
|
|
64
|
+
readonly publishedAt?: DateTime.Utc;
|
|
60
65
|
};
|
|
61
66
|
readonly title: string;
|
|
62
67
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { i as SiteIdentity } from "../../Seo-402YumpT.js";
|
|
2
|
+
import { DeliveryDocument } from "./types.js";
|
|
3
|
+
import { ComputedRef, MaybeRefOrGetter } from "vue";
|
|
4
|
+
//#region src/runtime/delivery/useCmsDocumentSeo.d.ts
|
|
5
|
+
type ReactiveMetadataValue = () => string | undefined;
|
|
6
|
+
export interface CmsSeoMetadata {
|
|
7
|
+
readonly title: ReactiveMetadataValue;
|
|
8
|
+
readonly description: ReactiveMetadataValue;
|
|
9
|
+
readonly ogTitle: ReactiveMetadataValue;
|
|
10
|
+
readonly ogDescription: ReactiveMetadataValue;
|
|
11
|
+
readonly ogImage: ReactiveMetadataValue;
|
|
12
|
+
readonly ogImageAlt: ReactiveMetadataValue;
|
|
13
|
+
readonly robots: ReactiveMetadataValue;
|
|
14
|
+
}
|
|
15
|
+
interface CmsIdentitySchemaNode {
|
|
16
|
+
readonly '@type': SiteIdentity['type'];
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly url?: string;
|
|
19
|
+
readonly image?: string;
|
|
20
|
+
readonly logo?: string;
|
|
21
|
+
readonly telephone?: string;
|
|
22
|
+
readonly address?: NonNullable<Extract<SiteIdentity, {
|
|
23
|
+
readonly type: 'LocalBusiness';
|
|
24
|
+
}>['address']>;
|
|
25
|
+
}
|
|
26
|
+
interface CmsPageSchemaNode {
|
|
27
|
+
readonly '@type': 'Article' | 'WebPage';
|
|
28
|
+
readonly name: string;
|
|
29
|
+
readonly description?: string;
|
|
30
|
+
readonly image?: string;
|
|
31
|
+
readonly url?: string;
|
|
32
|
+
readonly headline?: string;
|
|
33
|
+
readonly datePublished?: string;
|
|
34
|
+
readonly dateModified?: string;
|
|
35
|
+
}
|
|
36
|
+
export type CmsSeoSchemaNode = CmsIdentitySchemaNode | CmsPageSchemaNode;
|
|
37
|
+
export interface CmsDocumentSeoAdapters {
|
|
38
|
+
readonly head: (input: () => {
|
|
39
|
+
htmlAttrs?: {
|
|
40
|
+
lang: string;
|
|
41
|
+
};
|
|
42
|
+
link: Array<{
|
|
43
|
+
href: string;
|
|
44
|
+
rel: 'canonical';
|
|
45
|
+
}>;
|
|
46
|
+
titleTemplate: null;
|
|
47
|
+
}) => void;
|
|
48
|
+
readonly robots: (input: ComputedRef<{
|
|
49
|
+
readonly follow: boolean;
|
|
50
|
+
readonly index: boolean;
|
|
51
|
+
}>) => void;
|
|
52
|
+
readonly schema: (input: ComputedRef<ReadonlyArray<CmsSeoSchemaNode>>) => void;
|
|
53
|
+
readonly seoMeta: (input: CmsSeoMetadata) => void;
|
|
54
|
+
}
|
|
55
|
+
/** Installs Nuxt's composables once before document page setup. */
|
|
56
|
+
export declare function installCmsDocumentSeoAdapters(adapters: CmsDocumentSeoAdapters): void;
|
|
57
|
+
export declare function useCmsDocumentSeo(document: MaybeRefOrGetter<DeliveryDocument | null>): void;
|
|
58
|
+
//#endregion
|
|
59
|
+
//# sourceMappingURL=useCmsDocumentSeo.d.ts.map
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { computed, toValue } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/runtime/delivery/useCmsDocumentSeo.ts
|
|
4
|
+
let installedAdapters;
|
|
5
|
+
/** Installs Nuxt's composables once before document page setup. */
|
|
6
|
+
function installCmsDocumentSeoAdapters(adapters) {
|
|
7
|
+
installedAdapters = adapters;
|
|
8
|
+
}
|
|
9
|
+
function useCmsDocumentSeo(document) {
|
|
10
|
+
const adapters = installedCmsDocumentSeoAdapters();
|
|
11
|
+
const current = computed(() => toValue(document));
|
|
12
|
+
const seo = computed(() => resolvedSeo(current.value));
|
|
13
|
+
adapters.seoMeta({
|
|
14
|
+
title: () => seo.value?.title,
|
|
15
|
+
description: () => seo.value?.description,
|
|
16
|
+
ogTitle: () => seo.value?.socialTitle,
|
|
17
|
+
ogDescription: () => seo.value?.socialDescription,
|
|
18
|
+
ogImage: () => seo.value?.socialImage?.url,
|
|
19
|
+
ogImageAlt: () => seo.value?.socialImage?.alt,
|
|
20
|
+
robots: () => seo.value ? `${seo.value.index ? "index" : "noindex"}, ${seo.value.follow ? "follow" : "nofollow"}` : void 0
|
|
21
|
+
});
|
|
22
|
+
adapters.head(() => ({
|
|
23
|
+
...current.value?.locale ? { htmlAttrs: { lang: current.value.locale } } : void 0,
|
|
24
|
+
link: seo.value?.canonicalUrl ? [{
|
|
25
|
+
href: seo.value.canonicalUrl,
|
|
26
|
+
rel: "canonical"
|
|
27
|
+
}] : [],
|
|
28
|
+
titleTemplate: null
|
|
29
|
+
}));
|
|
30
|
+
adapters.robots(computed(() => ({
|
|
31
|
+
follow: seo.value?.follow ?? true,
|
|
32
|
+
index: seo.value?.index ?? true
|
|
33
|
+
})));
|
|
34
|
+
adapters.schema(computed(() => seo.value ? schemaNodes(seo.value) : []));
|
|
35
|
+
}
|
|
36
|
+
function installedCmsDocumentSeoAdapters() {
|
|
37
|
+
if (!installedAdapters) throw new Error("The CMS document SEO adapter has not been installed.");
|
|
38
|
+
return installedAdapters;
|
|
39
|
+
}
|
|
40
|
+
function resolvedSeo(document) {
|
|
41
|
+
if (!document) return void 0;
|
|
42
|
+
if (document.resolvedSeo) return document.resolvedSeo;
|
|
43
|
+
return {
|
|
44
|
+
description: document.description,
|
|
45
|
+
follow: true,
|
|
46
|
+
index: true,
|
|
47
|
+
socialDescription: document.description,
|
|
48
|
+
socialTitle: document.title,
|
|
49
|
+
structuredData: { type: "WebPage" },
|
|
50
|
+
title: document.title
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function schemaNodes(seo) {
|
|
54
|
+
const identity = seo.identity ? [identityNode(seo.identity)] : [];
|
|
55
|
+
if (!seo.structuredData) return identity;
|
|
56
|
+
const common = {
|
|
57
|
+
name: seo.title,
|
|
58
|
+
...seo.description ? { description: seo.description } : void 0,
|
|
59
|
+
...seo.socialImage ? { image: seo.socialImage.url } : void 0,
|
|
60
|
+
...seo.canonicalUrl ? { url: seo.canonicalUrl } : void 0
|
|
61
|
+
};
|
|
62
|
+
if (seo.structuredData.type === "Article") return [...identity, {
|
|
63
|
+
"@type": "Article",
|
|
64
|
+
...common,
|
|
65
|
+
headline: seo.structuredData.headline ?? seo.title,
|
|
66
|
+
...seo.structuredData.datePublished ? { datePublished: seo.structuredData.datePublished } : void 0,
|
|
67
|
+
...seo.structuredData.dateModified ? { dateModified: seo.structuredData.dateModified } : void 0
|
|
68
|
+
}];
|
|
69
|
+
return [...identity, {
|
|
70
|
+
"@type": "WebPage",
|
|
71
|
+
...common
|
|
72
|
+
}];
|
|
73
|
+
}
|
|
74
|
+
function identityNode(identity) {
|
|
75
|
+
const common = {
|
|
76
|
+
"@type": identity.type,
|
|
77
|
+
name: identity.name,
|
|
78
|
+
...identity.url ? { url: identity.url } : void 0
|
|
79
|
+
};
|
|
80
|
+
switch (identity.type) {
|
|
81
|
+
case "Person": return {
|
|
82
|
+
...common,
|
|
83
|
+
...identity.image ? { image: identity.image.url } : void 0
|
|
84
|
+
};
|
|
85
|
+
case "Organization": return {
|
|
86
|
+
...common,
|
|
87
|
+
...identity.logo ? { logo: identity.logo.url } : void 0
|
|
88
|
+
};
|
|
89
|
+
case "LocalBusiness": return {
|
|
90
|
+
...common,
|
|
91
|
+
...identity.address ? { address: identity.address } : void 0,
|
|
92
|
+
...identity.image ? { image: identity.image.url } : void 0,
|
|
93
|
+
...identity.logo ? { logo: identity.logo.url } : void 0,
|
|
94
|
+
...identity.telephone ? { telephone: identity.telephone } : void 0
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
//#endregion
|
|
100
|
+
export { installCmsDocumentSeoAdapters, useCmsDocumentSeo };
|
|
101
|
+
//# sourceMappingURL=useCmsDocumentSeo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCmsDocumentSeo.js","names":[],"sources":["../../../../../src/runtime/delivery/useCmsDocumentSeo.ts"],"sourcesContent":["import type { ResolvedSeo, SiteIdentity } from '@internal/protocol/Seo'\nimport type { ComputedRef, MaybeRefOrGetter } from 'vue'\nimport type { DeliveryDocument } from './types'\nimport { computed, toValue } from 'vue'\n\ntype ReactiveMetadataValue = () => string | undefined\n\nexport interface CmsSeoMetadata {\n readonly title: ReactiveMetadataValue\n readonly description: ReactiveMetadataValue\n readonly ogTitle: ReactiveMetadataValue\n readonly ogDescription: ReactiveMetadataValue\n readonly ogImage: ReactiveMetadataValue\n readonly ogImageAlt: ReactiveMetadataValue\n readonly robots: ReactiveMetadataValue\n}\n\ninterface CmsIdentitySchemaNode {\n readonly '@type': SiteIdentity['type']\n readonly name: string\n readonly url?: string\n readonly image?: string\n readonly logo?: string\n readonly telephone?: string\n readonly address?: NonNullable<Extract<SiteIdentity, { readonly type: 'LocalBusiness' }>['address']>\n}\n\ninterface CmsPageSchemaNode {\n readonly '@type': 'Article' | 'WebPage'\n readonly name: string\n readonly description?: string\n readonly image?: string\n readonly url?: string\n readonly headline?: string\n readonly datePublished?: string\n readonly dateModified?: string\n}\n\nexport type CmsSeoSchemaNode = CmsIdentitySchemaNode | CmsPageSchemaNode\n\ntype EffectiveSeo = Omit<ResolvedSeo, 'canonicalUrl'> & {\n readonly canonicalUrl?: ResolvedSeo['canonicalUrl']\n}\n\nexport interface CmsDocumentSeoAdapters {\n readonly head: (\n input: () => {\n htmlAttrs?: { lang: string }\n link: Array<{ href: string; rel: 'canonical' }>\n titleTemplate: null\n },\n ) => void\n readonly robots: (input: ComputedRef<{ readonly follow: boolean; readonly index: boolean }>) => void\n readonly schema: (input: ComputedRef<ReadonlyArray<CmsSeoSchemaNode>>) => void\n readonly seoMeta: (input: CmsSeoMetadata) => void\n}\n\nlet installedAdapters: CmsDocumentSeoAdapters | undefined\n\n/** Installs Nuxt's composables once before document page setup. */\nexport function installCmsDocumentSeoAdapters(adapters: CmsDocumentSeoAdapters): void {\n installedAdapters = adapters\n}\n\nexport function useCmsDocumentSeo(document: MaybeRefOrGetter<DeliveryDocument | null>): void {\n const adapters = installedCmsDocumentSeoAdapters()\n const current = computed(() => toValue(document))\n const seo = computed(() => resolvedSeo(current.value))\n\n adapters.seoMeta({\n title: () => seo.value?.title,\n description: () => seo.value?.description,\n ogTitle: () => seo.value?.socialTitle,\n ogDescription: () => seo.value?.socialDescription,\n ogImage: () => seo.value?.socialImage?.url,\n ogImageAlt: () => seo.value?.socialImage?.alt,\n robots: () =>\n seo.value ? `${seo.value.index ? 'index' : 'noindex'}, ${seo.value.follow ? 'follow' : 'nofollow'}` : undefined,\n })\n\n adapters.head(() => ({\n ...(current.value?.locale ? { htmlAttrs: { lang: current.value.locale } } : undefined),\n link: seo.value?.canonicalUrl ? [{ href: seo.value.canonicalUrl, rel: 'canonical' }] : [],\n titleTemplate: null,\n }))\n adapters.robots(\n computed(() => ({\n follow: seo.value?.follow ?? true,\n index: seo.value?.index ?? true,\n })),\n )\n adapters.schema(computed(() => (seo.value ? schemaNodes(seo.value) : [])))\n}\n\nfunction installedCmsDocumentSeoAdapters(): CmsDocumentSeoAdapters {\n if (!installedAdapters) throw new Error('The CMS document SEO adapter has not been installed.')\n\n return installedAdapters\n}\n\nfunction resolvedSeo(document: DeliveryDocument | null): EffectiveSeo | undefined {\n if (!document) return undefined\n\n if (document.resolvedSeo) return document.resolvedSeo\n\n return {\n description: document.description,\n follow: true,\n index: true,\n socialDescription: document.description,\n socialTitle: document.title,\n structuredData: { type: 'WebPage' },\n title: document.title,\n }\n}\n\nfunction schemaNodes(seo: EffectiveSeo): ReadonlyArray<CmsSeoSchemaNode> {\n const identity = seo.identity ? [identityNode(seo.identity)] : []\n\n if (!seo.structuredData) return identity\n\n const common = {\n name: seo.title,\n ...(seo.description ? { description: seo.description } : undefined),\n ...(seo.socialImage ? { image: seo.socialImage.url } : undefined),\n ...(seo.canonicalUrl ? { url: seo.canonicalUrl } : undefined),\n }\n\n if (seo.structuredData.type === 'Article') {\n return [\n ...identity,\n {\n '@type': 'Article',\n ...common,\n headline: seo.structuredData.headline ?? seo.title,\n ...(seo.structuredData.datePublished ? { datePublished: seo.structuredData.datePublished } : undefined),\n ...(seo.structuredData.dateModified ? { dateModified: seo.structuredData.dateModified } : undefined),\n },\n ]\n }\n\n return [...identity, { '@type': 'WebPage', ...common }]\n}\n\nfunction identityNode(identity: SiteIdentity): CmsIdentitySchemaNode {\n const common = {\n '@type': identity.type,\n name: identity.name,\n ...(identity.url ? { url: identity.url } : undefined),\n }\n\n switch (identity.type) {\n case 'Person':\n return { ...common, ...(identity.image ? { image: identity.image.url } : undefined) }\n case 'Organization':\n return { ...common, ...(identity.logo ? { logo: identity.logo.url } : undefined) }\n case 'LocalBusiness':\n return {\n ...common,\n ...(identity.address ? { address: identity.address } : undefined),\n ...(identity.image ? { image: identity.image.url } : undefined),\n ...(identity.logo ? { logo: identity.logo.url } : undefined),\n ...(identity.telephone ? { telephone: identity.telephone } : undefined),\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as CMS_PREVIEW_READ_PATH, r as CMS_DELIVERY_READ_PATH } from "../../HttpPaths-c9nLZ9H2.js";
|
|
2
2
|
import { usePreviewDelivery } from "./context.js";
|
|
3
|
-
import { useFetch } from "nuxt/app";
|
|
4
3
|
import { computed, toValue } from "vue";
|
|
4
|
+
import { useFetch } from "nuxt/app";
|
|
5
5
|
|
|
6
6
|
//#region src/runtime/delivery/useDocument.ts
|
|
7
7
|
function useDocument(path) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDocument.js","names":[],"sources":["../../../../../src/runtime/delivery/useDocument.ts"],"sourcesContent":["import { useFetch } from 'nuxt/app'\nimport { usePreviewDelivery } from './context'\nimport type { MaybeRefOrGetter } from 'vue'\nimport { computed, toValue } from 'vue'\nimport { CMS_DELIVERY_READ_PATH, CMS_PREVIEW_READ_PATH } from '@internal/protocol/HttpPaths'\nimport type { DeliveryDocument } from './types'\n\nexport function useDocument(path: MaybeRefOrGetter<string>) {\n const preview = usePreviewDelivery()\n const endpoint = computed(() => (preview.value ? CMS_PREVIEW_READ_PATH : CMS_DELIVERY_READ_PATH))\n const body = computed(() => ({ kind: 'path' as const, path: toValue(path) }))\n return useFetch<DeliveryDocument | null>(endpoint, {\n body,\n default: () => null,\n method: 'POST',\n })\n}\n"],"mappings":";;;;;;AAOA,SAAgB,YAAY,MAAgC;CAC1D,MAAM,UAAU,mBAAmB;CACnC,MAAM,WAAW,eAAgB,QAAQ,QAAQ,wBAAwB,sBAAuB;CAChG,MAAM,OAAO,gBAAgB;EAAE,MAAM;EAAiB,MAAM,QAAQ,IAAI;CAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"useDocument.js","names":[],"sources":["../../../../../src/runtime/delivery/useDocument.ts"],"sourcesContent":["import { useFetch } from 'nuxt/app'\nimport { usePreviewDelivery } from './context'\nimport type { MaybeRefOrGetter } from 'vue'\nimport { computed, toValue } from 'vue'\nimport { CMS_DELIVERY_READ_PATH, CMS_PREVIEW_READ_PATH } from '@internal/protocol/HttpPaths'\nimport type { DeliveryDocument } from './types'\n\nexport function useDocument(path: MaybeRefOrGetter<string>) {\n const preview = usePreviewDelivery()\n const endpoint = computed(() => (preview.value ? CMS_PREVIEW_READ_PATH : CMS_DELIVERY_READ_PATH))\n const body = computed(() => ({ kind: 'path' as const, path: toValue(path) }))\n\n return useFetch<DeliveryDocument | null>(endpoint, {\n body,\n default: () => null,\n method: 'POST',\n })\n}\n"],"mappings":";;;;;;AAOA,SAAgB,YAAY,MAAgC;CAC1D,MAAM,UAAU,mBAAmB;CACnC,MAAM,WAAW,eAAgB,QAAQ,QAAQ,wBAAwB,sBAAuB;CAChG,MAAM,OAAO,gBAAgB;EAAE,MAAM;EAAiB,MAAM,QAAQ,IAAI;CAAE,EAAE;CAE5E,OAAO,SAAkC,UAAU;EACjD;EACA,eAAe;EACf,QAAQ;CACV,CAAC;AACH"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as CMS_DELIVERY_QUERY_PATH, s as CMS_PREVIEW_QUERY_PATH } from "../../HttpPaths-c9nLZ9H2.js";
|
|
2
2
|
import { usePreviewDelivery } from "./context.js";
|
|
3
|
-
import { useFetch } from "nuxt/app";
|
|
4
3
|
import { computed, toValue } from "vue";
|
|
4
|
+
import { useFetch } from "nuxt/app";
|
|
5
5
|
|
|
6
6
|
//#region src/runtime/delivery/useDocumentQuery.ts
|
|
7
7
|
function useDocumentQuery(query) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDocumentQuery.js","names":[],"sources":["../../../../../src/runtime/delivery/useDocumentQuery.ts"],"sourcesContent":["import { useFetch } from 'nuxt/app'\nimport { usePreviewDelivery } from './context'\nimport type { MaybeRefOrGetter } from 'vue'\nimport { computed, toValue } from 'vue'\nimport { CMS_DELIVERY_QUERY_PATH, CMS_PREVIEW_QUERY_PATH } from '@internal/protocol/HttpPaths'\nimport type { DeliveryDocumentPage, DeliveryDocumentQuery } from './types'\n\nexport type { DeliveryDocumentQuery, DeliveryDocumentQuerySort } from './types'\n\nexport function useDocumentQuery(query: MaybeRefOrGetter<DeliveryDocumentQuery>) {\n const preview = usePreviewDelivery()\n const endpoint = computed(() => (preview.value ? CMS_PREVIEW_QUERY_PATH : CMS_DELIVERY_QUERY_PATH))\n const body = computed(() => {\n const value = toValue(query)\n return {\n ...value,\n sort: value.sort === undefined ? undefined : Array.isArray(value.sort) ? value.sort : [value.sort],\n }\n })\n return useFetch<DeliveryDocumentPage>(endpoint, {\n body,\n default: () => ({ items: [], total: 0 }),\n method: 'POST',\n })\n}\n"],"mappings":";;;;;;AASA,SAAgB,iBAAiB,OAAgD;CAC/E,MAAM,UAAU,mBAAmB;CACnC,MAAM,WAAW,eAAgB,QAAQ,QAAQ,yBAAyB,uBAAwB;
|
|
1
|
+
{"version":3,"file":"useDocumentQuery.js","names":[],"sources":["../../../../../src/runtime/delivery/useDocumentQuery.ts"],"sourcesContent":["import { useFetch } from 'nuxt/app'\nimport { usePreviewDelivery } from './context'\nimport type { MaybeRefOrGetter } from 'vue'\nimport { computed, toValue } from 'vue'\nimport { CMS_DELIVERY_QUERY_PATH, CMS_PREVIEW_QUERY_PATH } from '@internal/protocol/HttpPaths'\nimport type { DeliveryDocumentPage, DeliveryDocumentQuery } from './types'\n\nexport type { DeliveryDocumentQuery, DeliveryDocumentQuerySort } from './types'\n\nexport function useDocumentQuery(query: MaybeRefOrGetter<DeliveryDocumentQuery>) {\n const preview = usePreviewDelivery()\n const endpoint = computed(() => (preview.value ? CMS_PREVIEW_QUERY_PATH : CMS_DELIVERY_QUERY_PATH))\n\n const body = computed(() => {\n const value = toValue(query)\n\n return {\n ...value,\n sort: value.sort === undefined ? undefined : Array.isArray(value.sort) ? value.sort : [value.sort],\n }\n })\n\n return useFetch<DeliveryDocumentPage>(endpoint, {\n body,\n default: () => ({ items: [], total: 0 }),\n method: 'POST',\n })\n}\n"],"mappings":";;;;;;AASA,SAAgB,iBAAiB,OAAgD;CAC/E,MAAM,UAAU,mBAAmB;CACnC,MAAM,WAAW,eAAgB,QAAQ,QAAQ,yBAAyB,uBAAwB;CAElG,MAAM,OAAO,eAAe;EAC1B,MAAM,QAAQ,QAAQ,KAAK;EAE3B,OAAO;GACL,GAAG;GACH,MAAM,MAAM,SAAS,SAAY,SAAY,MAAM,QAAQ,MAAM,IAAI,IAAI,MAAM,OAAO,CAAC,MAAM,IAAI;EACnG;CACF,CAAC;CAED,OAAO,SAA+B,UAAU;EAC9C;EACA,gBAAgB;GAAE,OAAO,CAAC;GAAG,OAAO;EAAE;EACtC,QAAQ;CACV,CAAC;AACH"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { r as DocumentId } from "../../scalars-B2lgGUnj.js";
|
|
2
|
+
import { t as documentForms } from "../../Forms-Dj6NuW66.js";
|
|
3
|
+
import { Predicate, Result, Schema } from "effect";
|
|
4
|
+
|
|
5
|
+
//#region src/runtime/forms/document.ts
|
|
6
|
+
/** Both ordinary rendering and Comark's live preview cache receive the same derived form props. */
|
|
7
|
+
function prepareFormDocument(value, components, preview) {
|
|
8
|
+
if (!components.some((component) => component.authoring.form)) return value;
|
|
9
|
+
const definitions = documentForms({
|
|
10
|
+
id: DocumentId.make(value.id),
|
|
11
|
+
body: value.body
|
|
12
|
+
}, components, preview || value.draft);
|
|
13
|
+
const visit = (nodes, parent) => nodes.map((node, index) => {
|
|
14
|
+
if (Predicate.isString(node) || node[0] === null) return node;
|
|
15
|
+
const [tag, attributes, ...children] = node;
|
|
16
|
+
const path = [...parent, index];
|
|
17
|
+
const form = definitions.find((candidate) => JSON.stringify(candidate.nodePath) === JSON.stringify(path));
|
|
18
|
+
return [
|
|
19
|
+
tag,
|
|
20
|
+
{
|
|
21
|
+
...attributes,
|
|
22
|
+
...form ? { cmsForm: Result.getOrThrow(Schema.decodeUnknownResult(Schema.JsonObject)(form)) } : void 0
|
|
23
|
+
},
|
|
24
|
+
...visit(children, path)
|
|
25
|
+
];
|
|
26
|
+
});
|
|
27
|
+
return {
|
|
28
|
+
...value,
|
|
29
|
+
body: {
|
|
30
|
+
...value.body,
|
|
31
|
+
nodes: visit(value.body.nodes, [])
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//#endregion
|
|
37
|
+
export { prepareFormDocument };
|
|
38
|
+
//# sourceMappingURL=document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document.js","names":[],"sources":["../../../../../src/runtime/forms/document.ts"],"sourcesContent":["import type { ComponentDefinition } from '@internal/protocol/Configuration'\nimport type { DeliveryDocument, DeliveryMarkdownNode } from '../delivery/types'\nimport { DocumentId } from '@internal/protocol/Documents'\nimport { documentForms } from '@internal/document/Forms'\nimport { Result, Predicate, Schema } from 'effect'\n\n/** Both ordinary rendering and Comark's live preview cache receive the same derived form props. */\nexport function prepareFormDocument(\n value: DeliveryDocument,\n components: ReadonlyArray<ComponentDefinition>,\n preview: boolean,\n): DeliveryDocument {\n if (!components.some((component) => component.authoring.form)) return value\n\n const definitions = documentForms(\n { id: DocumentId.make(value.id), body: value.body },\n components,\n preview || value.draft,\n )\n\n const visit = (nodes: ReadonlyArray<DeliveryMarkdownNode>, parent: number[]): ReadonlyArray<DeliveryMarkdownNode> =>\n nodes.map((node, index) => {\n if (Predicate.isString(node) || node[0] === null) return node\n const [tag, attributes, ...children] = node\n const path = [...parent, index]\n const form = definitions.find((candidate) => JSON.stringify(candidate.nodePath) === JSON.stringify(path))\n\n return [\n tag,\n {\n ...attributes,\n ...(form ? { cmsForm: Result.getOrThrow(Schema.decodeUnknownResult(Schema.JsonObject)(form)) } : undefined),\n },\n ...visit(children, path),\n ]\n })\n\n return { ...value, body: { ...value.body, nodes: visit(value.body.nodes, []) } }\n}\n"],"mappings":";;;;;;AAOA,SAAgB,oBACd,OACA,YACA,SACkB;CAClB,IAAI,CAAC,WAAW,MAAM,cAAc,UAAU,UAAU,IAAI,GAAG,OAAO;CAEtE,MAAM,cAAc,cAClB;EAAE,IAAI,WAAW,KAAK,MAAM,EAAE;EAAG,MAAM,MAAM;CAAK,GAClD,YACA,WAAW,MAAM,KACnB;CAEA,MAAM,SAAS,OAA4C,WACzD,MAAM,KAAK,MAAM,UAAU;EACzB,IAAI,UAAU,SAAS,IAAI,KAAK,KAAK,OAAO,MAAM,OAAO;EACzD,MAAM,CAAC,KAAK,YAAY,GAAG,YAAY;EACvC,MAAM,OAAO,CAAC,GAAG,QAAQ,KAAK;EAC9B,MAAM,OAAO,YAAY,MAAM,cAAc,KAAK,UAAU,UAAU,QAAQ,MAAM,KAAK,UAAU,IAAI,CAAC;EAExG,OAAO;GACL;GACA;IACE,GAAG;IACH,GAAI,OAAO,EAAE,SAAS,OAAO,WAAW,OAAO,oBAAoB,OAAO,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI;GACnG;GACA,GAAG,MAAM,UAAU,IAAI;EACzB;CACF,CAAC;CAEH,OAAO;EAAE,GAAG;EAAO,MAAM;GAAE,GAAG,MAAM;GAAM,OAAO,MAAM,MAAM,KAAK,OAAO,CAAC,CAAC;EAAE;CAAE;AACjF"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { i as FormResult } from "../../Forms-CfcI3tPU.js";
|
|
2
|
+
import { i as validateFormValues } from "../../Forms-Dj6NuW66.js";
|
|
3
|
+
import { a as CMS_FORM_SUBMIT_PATH } from "../../HttpPaths-c9nLZ9H2.js";
|
|
4
|
+
import { Result, Schema } from "effect";
|
|
5
|
+
import { computed, getCurrentInstance, getCurrentScope, onScopeDispose, readonly, ref, shallowRef, toValue, useId, watch } from "vue";
|
|
6
|
+
|
|
7
|
+
//#region src/runtime/forms/useCmsForm.ts
|
|
8
|
+
/** Headless, per-instance form state. Definition changes preserve answers for unchanged field types. */
|
|
9
|
+
function useCmsForm(input, options = {}) {
|
|
10
|
+
const fieldIdPrefix = getCurrentInstance() ? useId() : "cms-form";
|
|
11
|
+
const definition = computed(() => toValue(input));
|
|
12
|
+
const steps = computed(() => definition.value.steps);
|
|
13
|
+
const fields = computed(() => steps.value.flatMap((step) => step.fields));
|
|
14
|
+
const values = ref({});
|
|
15
|
+
const errors = shallowRef({});
|
|
16
|
+
const stepIndex = ref(0);
|
|
17
|
+
const currentStep = computed(() => steps.value[stepIndex.value]);
|
|
18
|
+
const isFirstStep = computed(() => stepIndex.value === 0);
|
|
19
|
+
const isLastStep = computed(() => stepIndex.value === steps.value.length - 1);
|
|
20
|
+
const isSubmitting = ref(false);
|
|
21
|
+
const isSuccess = ref(false);
|
|
22
|
+
const isPreview = computed(() => definition.value.preview);
|
|
23
|
+
const error = shallowRef();
|
|
24
|
+
let controller;
|
|
25
|
+
let generation = 0;
|
|
26
|
+
let previousFields = /* @__PURE__ */ new Map();
|
|
27
|
+
const stop = watch(definition, (next, before) => {
|
|
28
|
+
generation++;
|
|
29
|
+
controller?.abort();
|
|
30
|
+
isSubmitting.value = false;
|
|
31
|
+
const sameForm = before?.documentId === next.documentId && JSON.stringify(before.nodePath) === JSON.stringify(next.nodePath) && before.name === next.name;
|
|
32
|
+
values.value = Object.fromEntries(next.steps.flatMap((step) => step.fields).map((field) => [field.id, sameForm && previousFields.get(field.id) === field.type ? values.value[field.id] ?? null : field.type === "checkbox" ? false : field.type === "number" ? null : ""]));
|
|
33
|
+
previousFields = new Map(next.steps.flatMap((step) => step.fields).map((field) => [field.id, field.type]));
|
|
34
|
+
stepIndex.value = Math.max(0, next.steps.findIndex((step) => step.id === before?.steps[stepIndex.value]?.id));
|
|
35
|
+
errors.value = {};
|
|
36
|
+
error.value = void 0;
|
|
37
|
+
isSuccess.value = false;
|
|
38
|
+
}, {
|
|
39
|
+
immediate: true,
|
|
40
|
+
deep: true,
|
|
41
|
+
flush: "sync"
|
|
42
|
+
});
|
|
43
|
+
function validate() {
|
|
44
|
+
errors.value = validateFormValues(fields.value, values.value);
|
|
45
|
+
return Object.keys(errors.value).length === 0;
|
|
46
|
+
}
|
|
47
|
+
function fieldState(field) {
|
|
48
|
+
const id = `${fieldIdPrefix}-${encodeURIComponent(field.id)}`;
|
|
49
|
+
return {
|
|
50
|
+
field,
|
|
51
|
+
get value() {
|
|
52
|
+
return values.value[field.id] ?? emptyFormValue(field);
|
|
53
|
+
},
|
|
54
|
+
get error() {
|
|
55
|
+
return errors.value[field.id];
|
|
56
|
+
},
|
|
57
|
+
helpId: `${id}-help`,
|
|
58
|
+
errorId: `${id}-error`,
|
|
59
|
+
get inputAttrs() {
|
|
60
|
+
const error = errors.value[field.id];
|
|
61
|
+
const invalid = error ? "true" : void 0;
|
|
62
|
+
const describedBy = [field.help ? `${id}-help` : void 0, error ? `${id}-error` : void 0].filter((part) => part !== void 0).join(" ");
|
|
63
|
+
return {
|
|
64
|
+
id,
|
|
65
|
+
name: field.id,
|
|
66
|
+
required: field.required === true,
|
|
67
|
+
"aria-invalid": invalid,
|
|
68
|
+
"aria-describedby": describedBy || void 0
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
setValue: (value) => {
|
|
72
|
+
values.value[field.id] = normalizeFormValue(field, value);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function next() {
|
|
77
|
+
if (isSubmitting.value || isLastStep.value) return false;
|
|
78
|
+
const stepFields = currentStep.value?.fields ?? [];
|
|
79
|
+
const issues = validateFormValues(stepFields, values.value);
|
|
80
|
+
errors.value = {
|
|
81
|
+
...Object.fromEntries(Object.entries(errors.value).filter(([id]) => !stepFields.some((field) => field.id === id))),
|
|
82
|
+
...issues
|
|
83
|
+
};
|
|
84
|
+
if (Object.keys(issues).length) return false;
|
|
85
|
+
stepIndex.value++;
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
function previous() {
|
|
89
|
+
if (!isSubmitting.value && !isFirstStep.value) stepIndex.value--;
|
|
90
|
+
}
|
|
91
|
+
function reset() {
|
|
92
|
+
generation++;
|
|
93
|
+
controller?.abort();
|
|
94
|
+
isSubmitting.value = false;
|
|
95
|
+
values.value = Object.fromEntries(fields.value.map((field) => [field.id, emptyFormValue(field)]));
|
|
96
|
+
errors.value = {};
|
|
97
|
+
error.value = void 0;
|
|
98
|
+
isSuccess.value = false;
|
|
99
|
+
stepIndex.value = 0;
|
|
100
|
+
}
|
|
101
|
+
async function submit() {
|
|
102
|
+
if (isSubmitting.value || isSuccess.value) return false;
|
|
103
|
+
error.value = void 0;
|
|
104
|
+
if (!validate()) {
|
|
105
|
+
stepIndex.value = Math.max(0, steps.value.findIndex((step) => step.fields.some((field) => errors.value[field.id])));
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
if (isPreview.value) {
|
|
109
|
+
isSuccess.value = true;
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
const currentGeneration = ++generation;
|
|
113
|
+
controller = new AbortController();
|
|
114
|
+
isSubmitting.value = true;
|
|
115
|
+
try {
|
|
116
|
+
const { documentId, nodePath, revision } = definition.value;
|
|
117
|
+
const result = await (options.submit ?? send)({
|
|
118
|
+
documentId,
|
|
119
|
+
nodePath,
|
|
120
|
+
revision,
|
|
121
|
+
values: { ...values.value }
|
|
122
|
+
}, controller.signal);
|
|
123
|
+
if (generation !== currentGeneration) return false;
|
|
124
|
+
errors.value = { ...result.errors };
|
|
125
|
+
isSuccess.value = result.status === "accepted";
|
|
126
|
+
if (result.status === "invalid") stepIndex.value = Math.max(0, steps.value.findIndex((step) => step.fields.some((field) => errors.value[field.id])));
|
|
127
|
+
if (result.status !== "accepted" && result.status !== "invalid") error.value = result.status === "stale" ? "This form has changed. Reload the page before submitting." : "Submission failed. Please try again.";
|
|
128
|
+
return isSuccess.value;
|
|
129
|
+
} catch {
|
|
130
|
+
if (generation === currentGeneration) error.value = "Submission failed. Please try again.";
|
|
131
|
+
return false;
|
|
132
|
+
} finally {
|
|
133
|
+
if (generation === currentGeneration) isSubmitting.value = false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (getCurrentScope()) onScopeDispose(() => {
|
|
137
|
+
generation++;
|
|
138
|
+
controller?.abort();
|
|
139
|
+
stop();
|
|
140
|
+
});
|
|
141
|
+
return {
|
|
142
|
+
fields,
|
|
143
|
+
steps,
|
|
144
|
+
values,
|
|
145
|
+
errors: readonly(errors),
|
|
146
|
+
currentStep,
|
|
147
|
+
stepIndex: readonly(stepIndex),
|
|
148
|
+
isFirstStep,
|
|
149
|
+
isLastStep,
|
|
150
|
+
isSubmitting: readonly(isSubmitting),
|
|
151
|
+
isSuccess: readonly(isSuccess),
|
|
152
|
+
isPreview,
|
|
153
|
+
error: readonly(error),
|
|
154
|
+
fieldState,
|
|
155
|
+
next,
|
|
156
|
+
previous,
|
|
157
|
+
validate,
|
|
158
|
+
submit,
|
|
159
|
+
reset
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function normalizeFormValue(field, input) {
|
|
163
|
+
if (field.type === "checkbox") return input === true;
|
|
164
|
+
if (field.type === "number") {
|
|
165
|
+
if (input === "" || input == null) return null;
|
|
166
|
+
const value = Schema.is(Schema.Finite)(input) || Schema.is(Schema.String)(input) ? Number(input) : NaN;
|
|
167
|
+
if (Number.isFinite(value)) return value;
|
|
168
|
+
return Schema.is(Schema.String)(input) ? input : null;
|
|
169
|
+
}
|
|
170
|
+
return Schema.is(Schema.String)(input) ? input : "";
|
|
171
|
+
}
|
|
172
|
+
function emptyFormValue(field) {
|
|
173
|
+
if (field.type === "checkbox") return false;
|
|
174
|
+
if (field.type === "number") return null;
|
|
175
|
+
return "";
|
|
176
|
+
}
|
|
177
|
+
async function send(submission, signal) {
|
|
178
|
+
const response = await fetch(CMS_FORM_SUBMIT_PATH, {
|
|
179
|
+
method: "POST",
|
|
180
|
+
headers: { "content-type": "application/json" },
|
|
181
|
+
body: JSON.stringify(submission),
|
|
182
|
+
signal
|
|
183
|
+
});
|
|
184
|
+
if (!response.ok) throw new Error("Submission failed.");
|
|
185
|
+
return Result.getOrThrow(Schema.decodeUnknownResult(FormResult)(await response.json()));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
//#endregion
|
|
189
|
+
export { useCmsForm };
|
|
190
|
+
//# sourceMappingURL=useCmsForm.js.map
|