@phtngyn/cms 0.2.0-beta.4 → 0.2.0-beta.6
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 +31 -13
- package/package.json +7 -7
- package/src/ApplicationTypes.d.ts +3 -3
- package/src/Authoring.d.ts +11 -3
- package/src/{Configuration-BU-UyGoH.js → Configuration-JQ1qyaU0.js} +347 -189
- package/src/Configuration-JQ1qyaU0.js.map +1 -0
- package/src/Configuration.d.ts +1 -1
- package/src/Content.d.ts +7 -6
- package/src/Content.js +106 -47
- package/src/Content.js.map +1 -1
- package/src/ContentTransfer-BxwswWn3.js +86 -0
- package/src/ContentTransfer-BxwswWn3.js.map +1 -0
- package/src/{ContentTransfer-CRQet3QJ.d.ts → ContentTransfer-Z9FHyLez.d.ts} +33 -9
- package/src/{DocumentEngine-ClhFXW9M.js → DocumentEngine-j6Vi7nQo.js} +279 -178
- package/src/DocumentEngine-j6Vi7nQo.js.map +1 -0
- package/src/DocumentModel.d.ts +9 -2
- package/src/DocumentModel.js +17 -4
- package/src/DocumentModel.js.map +1 -1
- package/src/{Forms-DoB56hfe.js → Forms-CX-hwmJF.js} +18 -11
- package/src/Forms-CX-hwmJF.js.map +1 -0
- package/src/{Forms-BbkE7QfC.js → Forms-CfNPTiCr.js} +2 -2
- package/src/{Forms-BbkE7QfC.js.map → Forms-CfNPTiCr.js.map} +1 -1
- package/src/Media-j1bTritO.js +112 -0
- package/src/Media-j1bTritO.js.map +1 -0
- package/src/Module.js +0 -4
- package/src/Module.js.map +1 -1
- package/src/References-CCPDAPve.js +45 -0
- package/src/References-CCPDAPve.js.map +1 -0
- package/src/{S3MediaObjects-CR3p1WTg.js → S3MediaObjects-BRuPQbxl.js} +454 -516
- package/src/S3MediaObjects-BRuPQbxl.js.map +1 -0
- package/src/cli/content.js +6 -5
- package/src/cli/content.js.map +1 -1
- package/src/cli.js +16 -3
- package/src/cli.js.map +1 -1
- package/src/{connection-D5S9Iph-.js → connection-BP80q4d-.js} +2 -2
- package/src/{connection-D5S9Iph-.js.map → connection-BP80q4d-.js.map} +1 -1
- package/src/{dev-lifecycle-D3f9-upa.js → dev-lifecycle-CExksm2R.js} +27 -7
- package/src/dev-lifecycle-CExksm2R.js.map +1 -0
- package/src/{installation-fZtNxtoW.js → installation-BoG8E3nJ.js} +7982 -7155
- package/src/installation-BoG8E3nJ.js.map +1 -0
- package/src/internal/authoring-catalog.js +2 -2
- package/src/internal/authoring-compiler.js +35 -9
- package/src/internal/authoring-compiler.js.map +1 -1
- package/src/internal/authoring-metadata.js +14 -5
- package/src/internal/authoring-metadata.js.map +1 -1
- package/src/internal/configuration.js +27 -3
- package/src/internal/configuration.js.map +1 -1
- package/src/internal/dev-lifecycle.js +2 -2
- package/src/internal/document-model.js +134 -43
- package/src/internal/document-model.js.map +1 -1
- package/src/internal/field-metadata.js +2 -1
- package/src/internal/field-metadata.js.map +1 -1
- package/src/internal/form-capabilities.js +1 -1
- package/src/{location-CPX7oj0o.js → location-CMNGO3lU.js} +2 -2
- package/src/{location-CPX7oj0o.js.map → location-CMNGO3lU.js.map} +1 -1
- package/src/{metadata-BEZPWh-3.js → metadata-UzZmjwxM.js} +2 -2
- package/src/{metadata-BEZPWh-3.js.map → metadata-UzZmjwxM.js.map} +1 -1
- package/src/{models-C9kF9JlQ.js → models-5j67LMqW.js} +4 -4
- package/src/{models-C9kF9JlQ.js.map → models-5j67LMqW.js.map} +1 -1
- package/src/{models-ChRxBChy.js → models-VmGmG19-.js} +42 -130
- package/src/models-VmGmG19-.js.map +1 -0
- package/src/runtime/delivery/DocumentRenderer.js +5 -1
- package/src/runtime/delivery/DocumentRenderer.js.map +1 -1
- package/src/runtime/delivery/context.js +1 -1
- package/src/runtime/delivery/plugin.js +2 -2
- package/src/runtime/delivery/preview.d.ts +1 -1
- package/src/runtime/delivery/types.d.ts +1 -1
- package/src/runtime/delivery/useCmsDocumentSeo.d.ts +1 -1
- package/src/runtime/forms/document.js +2 -2
- package/src/runtime/forms/useCmsForm.js +2 -2
- package/src/runtime/installation.js +1 -1
- package/src/runtime/plugin.js +1 -1
- package/src/runtime/preview/CmsStudioPreviewMarker.js +18 -4
- package/src/runtime/preview/CmsStudioPreviewMarker.js.map +1 -1
- package/src/runtime/preview/connection.js +1 -1
- package/src/runtime/preview/controller.js +65 -74
- package/src/runtime/preview/controller.js.map +1 -1
- package/src/runtime/preview/overlay.js +85 -28
- package/src/runtime/preview/overlay.js.map +1 -1
- package/src/runtime/preview/plugin.client.js +4 -4
- package/src/runtime/preview/preview.css +50 -36
- package/src/runtime/preview/protocol.d.ts +11 -5
- package/src/runtime/preview/protocol.js +17 -5
- package/src/runtime/preview/protocol.js.map +1 -1
- package/src/runtime/preview/regions.js +142 -0
- package/src/runtime/preview/regions.js.map +1 -0
- package/src/runtime/preview/store.js +1 -1
- package/src/runtime/sitemap.js +9 -10
- package/src/runtime/sitemap.js.map +1 -1
- package/src/{scalars-B2lgGUnj.js → scalars-CVZqT3L0.js} +2 -6
- package/src/scalars-CVZqT3L0.js.map +1 -0
- package/src/{store-CCsjHaZm.js → store-PKKB8xa2.js} +49 -66
- package/src/store-PKKB8xa2.js.map +1 -0
- package/src/{types-DutFRtaG.d.ts → types-DZ0IV-Ow.d.ts} +14 -3
- package/studio/CreateDocumentDialog-DqvusuGU.js +335 -0
- package/studio/{documentPlanning-CDb31mnl.js → SelectMenu-BgikeouH.js} +16292 -12303
- package/studio/{editor-Bzlh3zXt.js → editor-P2rB7Csp.js} +11228 -11927
- package/studio/host.css +1 -1
- package/studio/host.js +28987 -34295
- package/studio/rolldown-runtime-Dy4uBu1J.js +11 -0
- package/src/Configuration-BU-UyGoH.js.map +0 -1
- package/src/ContentTransfer-BhF9G56s.js +0 -57
- package/src/ContentTransfer-BhF9G56s.js.map +0 -1
- package/src/DocumentEngine-ClhFXW9M.js.map +0 -1
- package/src/Forms-DoB56hfe.js.map +0 -1
- package/src/S3MediaObjects-CR3p1WTg.js.map +0 -1
- package/src/dev-lifecycle-D3f9-upa.js.map +0 -1
- package/src/installation-fZtNxtoW.js.map +0 -1
- package/src/models-ChRxBChy.js.map +0 -1
- package/src/runtime/preview/targets.js +0 -101
- package/src/runtime/preview/targets.js.map +0 -1
- package/src/scalars-B2lgGUnj.js.map +0 -1
- package/src/store-CCsjHaZm.js.map +0 -1
- package/studio/CreateDocumentDialog-DJ8c0WZb.js +0 -256
- package/studio/dom-to-image-more.min-D6jGGdrW.js +0 -877
- package/studio/rolldown-runtime-B0aSnxlc.js +0 -20
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { o as PublicPath, r as DocumentId } from "./scalars-CVZqT3L0.js";
|
|
2
|
+
import { P as DocumentSeo, _ as DocumentSourceMapping, b as DocumentValidationResult, l as DocumentIssue, n as CmsMarkdownDocument, r as CompiledDocument, t as CmsDocumentAnalysis } from "./models-VmGmG19-.js";
|
|
3
|
+
import { i as decodeManagedMediaReference, r as decodeAuthoredDocumentReference } from "./References-CCPDAPve.js";
|
|
4
|
+
import { c as resolveCmsComarkAttributes, d as createCmsComarkRenderData, l as withCmsComarkProps, o as normalizeCmsComponentBindings, u as cmsComarkTextContent } from "./Forms-CX-hwmJF.js";
|
|
5
|
+
import { h as SOURCE_MAPPINGS_META_KEY, l as validateCollectionBody, m as createDocumentParser, o as createAuthoringDocumentValidator, p as DOCUMENT_ENGINE_FINGERPRINT } from "./Configuration-JQ1qyaU0.js";
|
|
5
6
|
import { DateTime, Effect, Option, Predicate, Result, Schema } from "effect";
|
|
6
7
|
|
|
7
8
|
//#region ../document/src/internal/document-address.ts
|
|
@@ -12,15 +13,15 @@ function parseDocumentAddress(pattern) {
|
|
|
12
13
|
name: match[1] ?? ""
|
|
13
14
|
}));
|
|
14
15
|
if (pattern.replace(addressTokenPattern, "").includes(":") || tokens.some((token) => !token.name)) return Result.fail({
|
|
15
|
-
field: "
|
|
16
|
+
field: "routes.entry",
|
|
16
17
|
message: `Document address pattern "${pattern}" contains an invalid token.`
|
|
17
18
|
});
|
|
18
19
|
if (tokens.filter((token) => token.catchAll).length > 1) return Result.fail({
|
|
19
|
-
field: "
|
|
20
|
+
field: "routes.entry",
|
|
20
21
|
message: `Document address pattern "${pattern}" contains more than one catch-all token.`
|
|
21
22
|
});
|
|
22
23
|
if (new Set(tokens.map((token) => token.name)).size !== tokens.length) return Result.fail({
|
|
23
|
-
field: "
|
|
24
|
+
field: "routes.entry",
|
|
24
25
|
message: `Document address pattern "${pattern}" contains duplicate tokens.`
|
|
25
26
|
});
|
|
26
27
|
return Result.succeed({
|
|
@@ -45,16 +46,6 @@ function resolveDocumentAddress(address, relativeKey, data) {
|
|
|
45
46
|
}
|
|
46
47
|
return normalizePublicPath(resolved);
|
|
47
48
|
}
|
|
48
|
-
function documentKeyFromSourcePath(relativeSourcePath) {
|
|
49
|
-
const extension = relativeSourcePath.match(/\.(?:md|mdc)$/iu)?.[0];
|
|
50
|
-
if (!extension) return Result.fail({
|
|
51
|
-
field: "sourcePath",
|
|
52
|
-
message: `Document source must be a Markdown file: "${relativeSourcePath}".`
|
|
53
|
-
});
|
|
54
|
-
const segments = relativeSourcePath.slice(0, -extension.length).split("/");
|
|
55
|
-
if (segments.at(-1)?.toLocaleLowerCase() === "index") segments.pop();
|
|
56
|
-
return normalizeDocumentRelativePath(segments.join("/")).pipe(Result.flatMap(normalizePublicPath));
|
|
57
|
-
}
|
|
58
49
|
function localizeDocumentPath(key, locale, configuration) {
|
|
59
50
|
if (!configuration || !locale || locale === configuration.defaultLocale && !configuration.prefixDefaultLocale) return key;
|
|
60
51
|
return PublicPath.make(`/${locale}${key === "/" ? "" : key}`);
|
|
@@ -95,7 +86,7 @@ var DocumentEngineConfigurationInvalid = class extends Schema.TaggedError()("Doc
|
|
|
95
86
|
field: Schema.optionalKey(Schema.NonEmptyString)
|
|
96
87
|
}) {};
|
|
97
88
|
var DocumentParseFailed = class extends Schema.TaggedError()("DocumentEngine.DocumentParseFailed", {
|
|
98
|
-
|
|
89
|
+
documentId: DocumentId,
|
|
99
90
|
cause: Schema.Defect()
|
|
100
91
|
}) {};
|
|
101
92
|
var DocumentCompilationFailed = class extends Schema.TaggedError()("DocumentEngine.DocumentCompilationFailed", { issues: Schema.Array(DocumentIssue) }) {};
|
|
@@ -209,12 +200,12 @@ function normalizeText(value) {
|
|
|
209
200
|
|
|
210
201
|
//#endregion
|
|
211
202
|
//#region ../document/src/internal/document-engine/frontmatter-validation.ts
|
|
212
|
-
const validateFrontmatter = Effect.fn("DocumentEngine.validateFrontmatter")(function* (raw, schema, type,
|
|
203
|
+
const validateFrontmatter = Effect.fn("DocumentEngine.validateFrontmatter")(function* (raw, schema, type, documentId) {
|
|
213
204
|
const projection = schema.project(raw);
|
|
214
|
-
const issues = projection.unknownPaths.toSorted().map((path) => unknownFieldIssue(path, type,
|
|
205
|
+
const issues = projection.unknownPaths.toSorted().map((path) => unknownFieldIssue(path, type, documentId));
|
|
215
206
|
const result = yield* schema.validate(projection.value);
|
|
216
207
|
if ("issues" in result) {
|
|
217
|
-
issues.push(...result.issues.map((issue) => schemaIssue(issue, projection.value, type,
|
|
208
|
+
issues.push(...result.issues.map((issue) => schemaIssue(issue, projection.value, type, documentId)));
|
|
218
209
|
return {
|
|
219
210
|
data: projection.value,
|
|
220
211
|
issues
|
|
@@ -222,7 +213,7 @@ const validateFrontmatter = Effect.fn("DocumentEngine.validateFrontmatter")(func
|
|
|
222
213
|
}
|
|
223
214
|
const parsed = Schema.decodeUnknownOption(Schema.JsonObject)(result.value);
|
|
224
215
|
if (Option.isNone(parsed)) {
|
|
225
|
-
issues.push(issue("schema.constraint", "The collection schema output must be a JSON-compatible object.", type,
|
|
216
|
+
issues.push(issue("schema.constraint", "The collection schema output must be a JSON-compatible object.", type, documentId, "frontmatter"));
|
|
226
217
|
return {
|
|
227
218
|
data: projection.value,
|
|
228
219
|
issues
|
|
@@ -236,13 +227,13 @@ const validateFrontmatter = Effect.fn("DocumentEngine.validateFrontmatter")(func
|
|
|
236
227
|
issues
|
|
237
228
|
};
|
|
238
229
|
});
|
|
239
|
-
function unknownFieldIssue(path, type,
|
|
240
|
-
if (path === "id") return issue("document.id", "Document identity is managed by the CMS and cannot be authored in frontmatter.", type,
|
|
241
|
-
return issue("schema.unknown", `Frontmatter field "${path}" is not declared by collection "${type.collection}".`, type,
|
|
230
|
+
function unknownFieldIssue(path, type, documentId) {
|
|
231
|
+
if (path === "id") return issue("document.id", "Document identity is managed by the CMS and cannot be authored in frontmatter.", type, documentId, path);
|
|
232
|
+
return issue("schema.unknown", `Frontmatter field "${path}" is not declared by collection "${type.collection}".`, type, documentId, path);
|
|
242
233
|
}
|
|
243
|
-
function schemaIssue(error, input, type,
|
|
234
|
+
function schemaIssue(error, input, type, documentId) {
|
|
244
235
|
const field = issuePath(error.path);
|
|
245
|
-
return issue(issueCode(error, input, field), error.message, type,
|
|
236
|
+
return issue(issueCode(error, input, field), error.message, type, documentId, field || void 0);
|
|
246
237
|
}
|
|
247
238
|
function issueCode(error, input, field) {
|
|
248
239
|
if (error.code === "invalid_type") return nestedValue(input, field) === void 0 ? "schema.required" : "schema.type";
|
|
@@ -262,14 +253,14 @@ function nestedValue(value, path) {
|
|
|
262
253
|
return Schema.is(Schema.JsonObject)(current) ? current[segment] : void 0;
|
|
263
254
|
}, value);
|
|
264
255
|
}
|
|
265
|
-
function issue(code, message, type,
|
|
256
|
+
function issue(code, message, type, documentId, field) {
|
|
266
257
|
return {
|
|
267
258
|
code,
|
|
268
259
|
collection: type.collection,
|
|
269
260
|
...field === void 0 ? void 0 : { field },
|
|
270
261
|
message,
|
|
271
262
|
severity: "error",
|
|
272
|
-
|
|
263
|
+
documentId
|
|
273
264
|
};
|
|
274
265
|
}
|
|
275
266
|
|
|
@@ -277,26 +268,27 @@ function issue(code, message, type, sourcePath, field) {
|
|
|
277
268
|
//#region ../document/src/internal/document-engine/compilation.ts
|
|
278
269
|
const isDocumentParseFailed$1 = Schema.is(DocumentParseFailed);
|
|
279
270
|
const compileCompiledDocument = Effect.fn("DocumentEngine.compileDocument")(function* (configuration, parseMarkdown, source) {
|
|
280
|
-
const
|
|
271
|
+
const collection = yield* resolveCollection(configuration, source);
|
|
281
272
|
const parsedBody = yield* parseBody(parseMarkdown, source);
|
|
282
273
|
const mappings = yield* sourceMappings(parsedBody, source);
|
|
283
274
|
const body = normalizeCmsComponentBindings(withoutSourceMappings(parsedBody), configuration.components);
|
|
284
275
|
const { collectionFrontmatter, rawSeo } = splitFrontmatter(body.frontmatter);
|
|
285
|
-
const seoProjection = projectSeo(rawSeo, source.
|
|
286
|
-
const
|
|
287
|
-
const validation = yield* validateFrontmatter(collectionFrontmatter, location.type.schema, location.type.definition, source.sourcePath).pipe(Effect.mapError((cause) => new DocumentCompilationFailed({ issues: [{
|
|
276
|
+
const seoProjection = projectSeo(rawSeo, source.identity.documentId);
|
|
277
|
+
const validation = yield* validateFrontmatter(collectionFrontmatter, collection.schema, collection.definition, source.identity.documentId).pipe(Effect.mapError((cause) => new DocumentCompilationFailed({ issues: [{
|
|
288
278
|
code: "schema.constraint",
|
|
289
|
-
collection:
|
|
279
|
+
collection: collection.definition.collection,
|
|
280
|
+
documentId: source.identity.documentId,
|
|
290
281
|
message: cause.message,
|
|
291
|
-
severity: "error"
|
|
292
|
-
sourcePath: source.sourcePath
|
|
282
|
+
severity: "error"
|
|
293
283
|
}] })));
|
|
294
|
-
const
|
|
295
|
-
const
|
|
296
|
-
const
|
|
297
|
-
const
|
|
284
|
+
const relativeKey = PublicPath.make(source.placement.kind === "home" ? "/" : `/${source.placement.slug}`);
|
|
285
|
+
const route = source.placement.kind === "home" ? collection.homeRoute : collection.entryRoute;
|
|
286
|
+
const address = resolveDocumentAddress(route, relativeKey, validation.data);
|
|
287
|
+
const key = Result.isSuccess(address) ? address.success : provisionalKey(source.identity.documentId);
|
|
288
|
+
const path = localizeDocumentPath(key, source.identity.locale, configuration.documents.locales);
|
|
289
|
+
const title = stringValue(validation.data.title) ?? stringValue(body.meta.title) ?? (source.placement.kind === "home" ? collection.definition.label : humanize(source.placement.slug));
|
|
298
290
|
const description = stringValue(validation.data.description) ?? stringValue(body.meta.description);
|
|
299
|
-
const issues = Result.isSuccess(address) ? validation.issues : [...validation.issues, addressIssue(address.failure, source.
|
|
291
|
+
const issues = Result.isSuccess(address) ? validation.issues : [...validation.issues, addressIssue(address.failure, source.identity.documentId)];
|
|
300
292
|
const canonicalFrontmatter = rawSeo === void 0 ? validation.data : Object.assign({ _seo: rawSeo }, validation.data);
|
|
301
293
|
const canonicalBody = CmsMarkdownDocument.make({
|
|
302
294
|
frontmatter: canonicalFrontmatter,
|
|
@@ -308,32 +300,35 @@ const compileCompiledDocument = Effect.fn("DocumentEngine.compileDocument")(func
|
|
|
308
300
|
title
|
|
309
301
|
});
|
|
310
302
|
return CompiledDocument.make(Object.assign({
|
|
311
|
-
id: source.documentId,
|
|
303
|
+
id: source.identity.documentId,
|
|
304
|
+
identity: source.identity,
|
|
305
|
+
placement: source.placement,
|
|
312
306
|
key,
|
|
313
307
|
path,
|
|
314
|
-
collection:
|
|
308
|
+
collection: source.identity.collection,
|
|
315
309
|
draft: source.draft,
|
|
316
310
|
title,
|
|
317
311
|
data: validation.data,
|
|
318
312
|
issues: [
|
|
319
313
|
...issues,
|
|
320
314
|
...seoProjection.issues,
|
|
321
|
-
...(configuration.validateAuthoringDocument?.(canonicalBody,
|
|
315
|
+
...(configuration.validateAuthoringDocument?.(canonicalBody, collection.definition.body) ?? []).map((issue) => ({
|
|
322
316
|
code: "reference.component",
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
317
|
+
component: issue.component,
|
|
318
|
+
documentId: source.identity.documentId,
|
|
319
|
+
...issue.field ? { field: issue.field.join(".") } : void 0,
|
|
320
|
+
message: issue.message,
|
|
321
|
+
severity: "error"
|
|
326
322
|
}))
|
|
327
323
|
],
|
|
328
324
|
analysis,
|
|
329
325
|
body: canonicalBody,
|
|
330
326
|
engineFingerprint: DOCUMENT_ENGINE_FINGERPRINT,
|
|
331
327
|
source: {
|
|
332
|
-
path: source.sourcePath,
|
|
333
328
|
mappings,
|
|
334
329
|
...source.publishedAt === void 0 ? void 0 : { publishedAt: source.publishedAt }
|
|
335
330
|
}
|
|
336
|
-
},
|
|
331
|
+
}, source.identity.locale === void 0 ? void 0 : { locale: source.identity.locale }, description === void 0 ? void 0 : { description }, seoProjection.seo === void 0 ? void 0 : { seo: seoProjection.seo }));
|
|
337
332
|
});
|
|
338
333
|
function splitFrontmatter(frontmatter) {
|
|
339
334
|
const { _seo: rawSeo, ...collectionFrontmatter } = frontmatter;
|
|
@@ -342,7 +337,7 @@ function splitFrontmatter(frontmatter) {
|
|
|
342
337
|
rawSeo
|
|
343
338
|
};
|
|
344
339
|
}
|
|
345
|
-
function projectSeo(rawSeo,
|
|
340
|
+
function projectSeo(rawSeo, documentId) {
|
|
346
341
|
if (rawSeo === void 0) return { issues: [] };
|
|
347
342
|
const decoded = Schema.decodeUnknownResult(DocumentSeo)(rawSeo, { onExcessProperty: "error" });
|
|
348
343
|
if (Result.isSuccess(decoded)) return {
|
|
@@ -351,83 +346,60 @@ function projectSeo(rawSeo, sourcePath) {
|
|
|
351
346
|
};
|
|
352
347
|
return { issues: [{
|
|
353
348
|
code: "seo.invalid",
|
|
349
|
+
documentId,
|
|
354
350
|
field: "_seo",
|
|
355
351
|
message: `Document SEO is invalid: ${String(decoded.failure)}`,
|
|
356
|
-
severity: "error"
|
|
357
|
-
sourcePath
|
|
352
|
+
severity: "error"
|
|
358
353
|
}] };
|
|
359
354
|
}
|
|
360
355
|
function provisionalKey(documentId) {
|
|
361
356
|
return PublicPath.make(`/_cms-invalid/${documentId}`);
|
|
362
357
|
}
|
|
363
|
-
function addressIssue(error,
|
|
364
|
-
|
|
358
|
+
function addressIssue(error, documentId) {
|
|
359
|
+
return {
|
|
365
360
|
code: "document.invalid",
|
|
361
|
+
documentId,
|
|
362
|
+
...error.field === void 0 ? void 0 : { field: error.field },
|
|
366
363
|
message: error.message,
|
|
367
|
-
severity: "error"
|
|
368
|
-
sourcePath
|
|
369
|
-
};
|
|
370
|
-
return error.field === void 0 ? issue : {
|
|
371
|
-
...issue,
|
|
372
|
-
field: error.field
|
|
364
|
+
severity: "error"
|
|
373
365
|
};
|
|
374
366
|
}
|
|
375
|
-
function
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
if (configuration.documents.locales) {
|
|
379
|
-
const candidate = segments.shift();
|
|
380
|
-
locale = configuration.documents.locales.locales.find((value) => value === candidate);
|
|
381
|
-
if (!locale) return compilationFailure({
|
|
382
|
-
code: "document.invalid",
|
|
383
|
-
field: "locale",
|
|
384
|
-
message: `Localized document "${source.sourcePath}" must begin with a configured locale.`,
|
|
385
|
-
severity: "error",
|
|
386
|
-
sourcePath: source.sourcePath
|
|
387
|
-
});
|
|
388
|
-
}
|
|
389
|
-
const localizedSourcePath = segments.join("/");
|
|
390
|
-
const type = configuration.types.find(({ definition }) => definition.directory === "." || localizedSourcePath.startsWith(`${definition.directory}/`));
|
|
391
|
-
if (!type) return compilationFailure({
|
|
367
|
+
function resolveCollection(configuration, source) {
|
|
368
|
+
const collection = configuration.types.find(({ definition }) => definition.collection === source.identity.collection);
|
|
369
|
+
if (!collection) return compilationFailure({
|
|
392
370
|
code: "document.invalid",
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
371
|
+
documentId: source.identity.documentId,
|
|
372
|
+
field: "identity.collection",
|
|
373
|
+
message: `Document collection "${source.identity.collection}" does not exist.`,
|
|
374
|
+
severity: "error"
|
|
397
375
|
});
|
|
398
|
-
const
|
|
399
|
-
|
|
376
|
+
const locales = configuration.documents.locales;
|
|
377
|
+
const locale = source.identity.locale;
|
|
378
|
+
if (!locales && locale !== void 0 || locales && (locale === void 0 || !locales.locales.includes(locale))) return compilationFailure({
|
|
400
379
|
code: "document.invalid",
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
});
|
|
406
|
-
return Effect.succeed(locale === void 0 ? {
|
|
407
|
-
relativeSourcePath,
|
|
408
|
-
type
|
|
409
|
-
} : {
|
|
410
|
-
locale,
|
|
411
|
-
relativeSourcePath,
|
|
412
|
-
type
|
|
380
|
+
documentId: source.identity.documentId,
|
|
381
|
+
field: "identity.locale",
|
|
382
|
+
message: locale ? `Document locale "${locale}" is not configured.` : "A locale is required for this document.",
|
|
383
|
+
severity: "error"
|
|
413
384
|
});
|
|
385
|
+
return Effect.succeed(collection);
|
|
414
386
|
}
|
|
415
387
|
function parseBody(parseMarkdown, source) {
|
|
416
388
|
return Effect.tryPromise({
|
|
417
389
|
try: () => parseMarkdown(source.markdown),
|
|
418
390
|
catch: (cause) => new DocumentParseFailed({
|
|
419
391
|
cause,
|
|
420
|
-
|
|
392
|
+
documentId: source.identity.documentId
|
|
421
393
|
})
|
|
422
394
|
}).pipe(Effect.flatMap(Schema.decodeUnknownEffect(CmsMarkdownDocument)), Effect.mapError((cause) => isDocumentParseFailed$1(cause) ? cause : new DocumentParseFailed({
|
|
423
395
|
cause,
|
|
424
|
-
|
|
396
|
+
documentId: source.identity.documentId
|
|
425
397
|
})));
|
|
426
398
|
}
|
|
427
399
|
function sourceMappings(body, source) {
|
|
428
400
|
return Schema.decodeUnknownEffect(Schema.Array(DocumentSourceMapping))(body.meta["__cmsSourceMappings"] ?? []).pipe(Effect.mapError((cause) => new DocumentParseFailed({
|
|
429
401
|
cause,
|
|
430
|
-
|
|
402
|
+
documentId: source.identity.documentId
|
|
431
403
|
})));
|
|
432
404
|
}
|
|
433
405
|
function withoutSourceMappings(body) {
|
|
@@ -438,25 +410,21 @@ function withoutSourceMappings(body) {
|
|
|
438
410
|
nodes: body.nodes
|
|
439
411
|
});
|
|
440
412
|
}
|
|
441
|
-
function fromAddressResult(result, sourcePath) {
|
|
442
|
-
if (Result.isSuccess(result)) return Effect.succeed(result.success);
|
|
443
|
-
return compilationFailure(addressIssue(result.failure, sourcePath));
|
|
444
|
-
}
|
|
445
413
|
function compilationFailure(issue) {
|
|
446
414
|
return Effect.fail(new DocumentCompilationFailed({ issues: [issue] }));
|
|
447
415
|
}
|
|
448
416
|
function stringValue(value) {
|
|
449
417
|
return Predicate.isString(value) && value.trim() ? value.trim() : void 0;
|
|
450
418
|
}
|
|
451
|
-
function
|
|
452
|
-
|
|
453
|
-
return (stem.toLocaleLowerCase() === "index" ? sourcePath.split("/").at(-2) ?? "home" : stem).replace(/[-_]+/gu, " ").replace(/^./u, (character) => character.toLocaleUpperCase());
|
|
419
|
+
function humanize(value) {
|
|
420
|
+
return value.replace(/[-_]+/gu, " ").replace(/^./u, (character) => character.toLocaleUpperCase());
|
|
454
421
|
}
|
|
455
422
|
|
|
456
423
|
//#endregion
|
|
457
424
|
//#region ../document/src/internal/document-engine/catalog-lookup.ts
|
|
458
425
|
function createCatalogLookup(documents, configuration) {
|
|
459
426
|
const byPath = new Map(documents.map((document) => [document.path, document]));
|
|
427
|
+
const byId = new Map(documents.map((document) => [document.id, document]));
|
|
460
428
|
const byVariant = new Map(documents.map((document) => [localeAndKey(document.locale, document.key), document]));
|
|
461
429
|
const findByKey = (input, locale) => {
|
|
462
430
|
const keyResult = normalizePublicPath(input);
|
|
@@ -486,6 +454,7 @@ function createCatalogLookup(documents, configuration) {
|
|
|
486
454
|
return Option.fromNullishOr(byVariant.get(localeAndKey(locales.fallbackLocale, request.key)));
|
|
487
455
|
};
|
|
488
456
|
return {
|
|
457
|
+
findById: (documentId) => Option.fromNullishOr(byId.get(documentId)),
|
|
489
458
|
findByKey,
|
|
490
459
|
findByPath
|
|
491
460
|
};
|
|
@@ -519,15 +488,14 @@ function collisionIssues(documents) {
|
|
|
519
488
|
const byPath = /* @__PURE__ */ new Map();
|
|
520
489
|
const byVariant = /* @__PURE__ */ new Map();
|
|
521
490
|
for (const document of documents) {
|
|
522
|
-
|
|
523
|
-
if (identityCollision) issues.push(collisionIssue(`Document identity collision for "${document.id}" between "${identityCollision.source.path}" and "${document.source.path}".`, document));
|
|
491
|
+
if (byId.get(document.id)) issues.push(collisionIssue(`Document identity collision for "${document.id}".`, document));
|
|
524
492
|
else byId.set(document.id, document);
|
|
525
493
|
const pathCollision = byPath.get(document.path);
|
|
526
|
-
if (pathCollision) issues.push(collisionIssue(`Document route collision at "${document.path}" between "${pathCollision.
|
|
494
|
+
if (pathCollision) issues.push(collisionIssue(`Document route collision at "${document.path}" between documents "${pathCollision.id}" and "${document.id}".`, document, document.path));
|
|
527
495
|
else byPath.set(document.path, document);
|
|
528
496
|
const variant = localeAndKey(document.locale, document.key);
|
|
529
497
|
const variantCollision = byVariant.get(variant);
|
|
530
|
-
if (variantCollision && variantCollision.path !== pathCollision?.path) issues.push(collisionIssue(`Document locale collision at "${document.key}" between "${variantCollision.
|
|
498
|
+
if (variantCollision && variantCollision.path !== pathCollision?.path) issues.push(collisionIssue(`Document locale collision at "${document.key}" between documents "${variantCollision.id}" and "${document.id}".`, document, document.key));
|
|
531
499
|
else byVariant.set(variant, document);
|
|
532
500
|
}
|
|
533
501
|
return issues;
|
|
@@ -549,21 +517,15 @@ function collisionIssue(message, document, key) {
|
|
|
549
517
|
code: "document.collision",
|
|
550
518
|
message,
|
|
551
519
|
severity: "error",
|
|
552
|
-
|
|
520
|
+
documentId: document.id
|
|
553
521
|
};
|
|
554
522
|
return key === void 0 ? issue : Object.assign(issue, { key });
|
|
555
523
|
}
|
|
556
524
|
|
|
557
525
|
//#endregion
|
|
558
526
|
//#region ../document/src/internal/document-engine/reference-target.ts
|
|
559
|
-
function referenceTarget(tag, attributes,
|
|
560
|
-
if (tag === "a")
|
|
561
|
-
const path = documentTarget(attributes.get("href"), documentPath);
|
|
562
|
-
return path ? {
|
|
563
|
-
kind: "document",
|
|
564
|
-
path
|
|
565
|
-
} : void 0;
|
|
566
|
-
}
|
|
527
|
+
function referenceTarget(tag, attributes, mediaBaseUrl) {
|
|
528
|
+
if (tag === "a") return decodeDocumentReference(attributes.get("href"));
|
|
567
529
|
if (tag === "img") {
|
|
568
530
|
const key = mediaKey(attributes.get("src"), mediaBaseUrl);
|
|
569
531
|
return key ? {
|
|
@@ -580,10 +542,29 @@ function referenceTarget(tag, attributes, documentPath, mediaBaseUrl) {
|
|
|
580
542
|
function targetKey(target) {
|
|
581
543
|
switch (target.kind) {
|
|
582
544
|
case "component": return `component:${target.name.toLocaleLowerCase()}`;
|
|
583
|
-
case "document": return `document:${target.
|
|
545
|
+
case "document": return `document:${target.documentId}`;
|
|
584
546
|
case "media": return `media:${target.key}`;
|
|
585
547
|
}
|
|
586
548
|
}
|
|
549
|
+
function decodeDocumentReference(value) {
|
|
550
|
+
if (!Predicate.isString(value)) return void 0;
|
|
551
|
+
const reference = decodeAuthoredDocumentReference(value);
|
|
552
|
+
return reference ? {
|
|
553
|
+
kind: "document",
|
|
554
|
+
...reference
|
|
555
|
+
} : void 0;
|
|
556
|
+
}
|
|
557
|
+
function decodeMediaReference(value, mediaBaseUrl) {
|
|
558
|
+
if (!Predicate.isString(value)) return void 0;
|
|
559
|
+
const reference = decodeManagedMediaReference(value);
|
|
560
|
+
if (!reference) return void 0;
|
|
561
|
+
const key = mediaKey(reference.lastKnownUrl, mediaBaseUrl);
|
|
562
|
+
return key ? {
|
|
563
|
+
kind: "media",
|
|
564
|
+
key,
|
|
565
|
+
mediaId: reference.mediaId
|
|
566
|
+
} : void 0;
|
|
567
|
+
}
|
|
587
568
|
function mediaKey(value, mediaBaseUrl) {
|
|
588
569
|
if (!Predicate.isString(value) || mediaBaseUrl === void 0) return void 0;
|
|
589
570
|
const prefix = `${mediaBaseUrl}/`;
|
|
@@ -599,25 +580,6 @@ function mediaKey(value, mediaBaseUrl) {
|
|
|
599
580
|
return;
|
|
600
581
|
}
|
|
601
582
|
}
|
|
602
|
-
function documentTarget(value, documentPath) {
|
|
603
|
-
if (!Predicate.isString(value)) return void 0;
|
|
604
|
-
const href = value.trim();
|
|
605
|
-
if (!href || href.startsWith("#") || href.startsWith("?") || href.startsWith("//") || /^[a-z][a-z\d+.-]*:/iu.test(href)) return;
|
|
606
|
-
const resolvedPath = resolveRelativePath(href.split(/[?#]/u)[0] ?? "", documentPath);
|
|
607
|
-
if ((resolvedPath.split("/").at(-1) ?? "").includes(".")) return void 0;
|
|
608
|
-
const normalized = normalizePublicPath(resolvedPath);
|
|
609
|
-
return Result.isSuccess(normalized) ? normalized.success : void 0;
|
|
610
|
-
}
|
|
611
|
-
function resolveRelativePath(href, documentPath) {
|
|
612
|
-
const normalizedHref = href.replace(/\\/gu, "/");
|
|
613
|
-
const segments = normalizedHref.startsWith("/") ? [] : documentPath.split("/").filter(Boolean).slice(0, -1);
|
|
614
|
-
for (const segment of normalizedHref.split("/")) {
|
|
615
|
-
if (!segment || segment === ".") continue;
|
|
616
|
-
if (segment === "..") segments.pop();
|
|
617
|
-
else segments.push(segment);
|
|
618
|
-
}
|
|
619
|
-
return `/${segments.join("/")}`;
|
|
620
|
-
}
|
|
621
583
|
function hasControlCharacter(value) {
|
|
622
584
|
for (const character of value) {
|
|
623
585
|
const codePoint = character.codePointAt(0);
|
|
@@ -629,19 +591,24 @@ function hasControlCharacter(value) {
|
|
|
629
591
|
//#endregion
|
|
630
592
|
//#region ../document/src/internal/document-engine/references.ts
|
|
631
593
|
const noReferences = Object.freeze([]);
|
|
632
|
-
function createDocumentReferenceIndex(documents, configuration,
|
|
594
|
+
function createDocumentReferenceIndex(documents, configuration, findById) {
|
|
633
595
|
const all = [];
|
|
634
596
|
const byTarget = /* @__PURE__ */ new Map();
|
|
635
597
|
const issues = /* @__PURE__ */ new Map();
|
|
636
598
|
for (const document of documents) {
|
|
599
|
+
const invalidManagedMedia = (lastKnownUrl) => addIssue(issues, document.id, {
|
|
600
|
+
code: "reference.media",
|
|
601
|
+
documentId: document.id,
|
|
602
|
+
message: `Managed-media reference "${lastKnownUrl}" is outside the configured media library.`,
|
|
603
|
+
severity: "error"
|
|
604
|
+
});
|
|
637
605
|
const indexTarget = (target, nodePath) => {
|
|
638
606
|
if (!target) return;
|
|
639
607
|
const reference = freezeReference({
|
|
640
608
|
nodePath,
|
|
641
609
|
source: {
|
|
642
610
|
documentId: document.id,
|
|
643
|
-
|
|
644
|
-
sourcePath: document.source.path
|
|
611
|
+
route: document.path
|
|
645
612
|
},
|
|
646
613
|
target
|
|
647
614
|
});
|
|
@@ -650,18 +617,20 @@ function createDocumentReferenceIndex(documents, configuration, findByPath) {
|
|
|
650
617
|
const matching = byTarget.get(key) ?? [];
|
|
651
618
|
matching.push(reference);
|
|
652
619
|
byTarget.set(key, matching);
|
|
653
|
-
if (target.kind === "document" && Option.isNone(
|
|
620
|
+
if (target.kind === "document" && Option.isNone(findById(target.documentId))) addIssue(issues, document.id, {
|
|
654
621
|
code: "reference.document",
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
622
|
+
documentId: document.id,
|
|
623
|
+
key: target.lastKnownRoute,
|
|
624
|
+
message: `Document link target "${target.documentId}" does not resolve.`,
|
|
625
|
+
severity: "error"
|
|
659
626
|
});
|
|
660
627
|
};
|
|
661
|
-
const seoImageTarget = document.seo?.socialImage ? referenceTarget("img", /* @__PURE__ */ new Map([["src", document.seo.socialImage.url]]),
|
|
628
|
+
const seoImageTarget = document.seo?.socialImage ? referenceTarget("img", /* @__PURE__ */ new Map([["src", document.seo.socialImage.url]]), configuration.mediaBaseUrl) : void 0;
|
|
662
629
|
indexTarget(seoImageTarget?.kind === "media" ? Object.assign({}, seoImageTarget, { mediaId: document.seo?.socialImage?.mediaId }) : seoImageTarget, []);
|
|
630
|
+
const collection = configuration.types.find(({ definition }) => definition.collection === document.collection);
|
|
631
|
+
for (const target of propertyTargets(collection?.definition.authoringFields ?? [], document.data, configuration.mediaBaseUrl, invalidManagedMedia)) indexTarget(target, []);
|
|
663
632
|
visit(document.body.nodes, createCmsComarkRenderData(document.body), (tag, attributes, children, nodePath) => {
|
|
664
|
-
const targets = [referenceTarget(tag, attributes,
|
|
633
|
+
const targets = [referenceTarget(tag, attributes, configuration.mediaBaseUrl), ...propertyTargets(configuration.components?.get(tag.toLowerCase())?.authoring.props ?? [], Object.fromEntries([...attributes].flatMap(([key, value]) => value === void 0 ? [] : [[key, value]])), configuration.mediaBaseUrl, invalidManagedMedia)];
|
|
665
634
|
for (const target of targets) indexTarget(target, nodePath);
|
|
666
635
|
});
|
|
667
636
|
}
|
|
@@ -692,19 +661,31 @@ function freezeReference(reference) {
|
|
|
692
661
|
target: Object.freeze({ ...reference.target })
|
|
693
662
|
});
|
|
694
663
|
}
|
|
695
|
-
function addIssue(issues,
|
|
696
|
-
const sourceIssues = issues.get(
|
|
664
|
+
function addIssue(issues, documentId, issue) {
|
|
665
|
+
const sourceIssues = issues.get(documentId) ?? [];
|
|
697
666
|
sourceIssues.push(issue);
|
|
698
|
-
issues.set(
|
|
667
|
+
issues.set(documentId, sourceIssues);
|
|
699
668
|
}
|
|
700
|
-
function propertyTargets(fields, values,
|
|
669
|
+
function propertyTargets(fields, values, mediaBaseUrl, onInvalidManagedMedia) {
|
|
701
670
|
return fields.flatMap((field) => {
|
|
702
671
|
const value = values[field.name] === void 0 ? field.defaultValue : values[field.name];
|
|
672
|
+
if (field.input === "document") {
|
|
673
|
+
const target = decodeDocumentReference(value);
|
|
674
|
+
return target ? [target] : [];
|
|
675
|
+
}
|
|
676
|
+
if (field.input === "media") {
|
|
677
|
+
const target = decodeMediaReference(value, mediaBaseUrl);
|
|
678
|
+
if (!target && Predicate.isString(value)) {
|
|
679
|
+
const reference = decodeManagedMediaReference(value);
|
|
680
|
+
if (reference) onInvalidManagedMedia(reference.lastKnownUrl);
|
|
681
|
+
}
|
|
682
|
+
return target ? [target] : [];
|
|
683
|
+
}
|
|
703
684
|
if (field.input === "link" || field.input === "image") {
|
|
704
|
-
const target = referenceTarget(field.input === "link" ? "a" : "img", /* @__PURE__ */ new Map([[field.input === "link" ? "href" : "src", value]]),
|
|
685
|
+
const target = referenceTarget(field.input === "link" ? "a" : "img", /* @__PURE__ */ new Map([[field.input === "link" ? "href" : "src", value]]), mediaBaseUrl);
|
|
705
686
|
return target ? [target] : [];
|
|
706
687
|
}
|
|
707
|
-
if (field.fields) return (Array.isArray(value) ? value : [value]).flatMap((entry) => Schema.is(Schema.JsonObject)(entry) ? propertyTargets(field.fields ?? [], entry,
|
|
688
|
+
if (field.fields) return (Array.isArray(value) ? value : [value]).flatMap((entry) => Schema.is(Schema.JsonObject)(entry) ? propertyTargets(field.fields ?? [], entry, mediaBaseUrl, onInvalidManagedMedia) : []);
|
|
708
689
|
return [];
|
|
709
690
|
});
|
|
710
691
|
}
|
|
@@ -712,44 +693,168 @@ function propertyTargets(fields, values, path, mediaBaseUrl) {
|
|
|
712
693
|
//#endregion
|
|
713
694
|
//#region ../document/src/internal/document-engine/catalog.ts
|
|
714
695
|
function createDocumentCatalog(configuration, input) {
|
|
715
|
-
const
|
|
696
|
+
const resolved = resolvePlacementGraph(configuration, input);
|
|
697
|
+
if (Result.isFailure(resolved)) return Result.fail(resolved.failure);
|
|
698
|
+
const documents = resolved.success.toSorted((left, right) => left.path.localeCompare(right.path));
|
|
716
699
|
const collisions = collisionIssues(documents);
|
|
717
700
|
if (collisions.length > 0) return Result.fail(new DocumentCompilationFailed({ issues: collisions }));
|
|
718
701
|
const lookup = createCatalogLookup(documents, configuration);
|
|
719
|
-
const references = createDocumentReferenceIndex(documents, configuration, lookup.
|
|
702
|
+
const references = createDocumentReferenceIndex(documents, configuration, lookup.findById);
|
|
720
703
|
const withReferenceIssues = documents.map((document) => {
|
|
721
|
-
const additional = references.issues.get(document.
|
|
722
|
-
|
|
704
|
+
const additional = references.issues.get(document.id) ?? [];
|
|
705
|
+
const projected = resolveSemanticRoutes(document, lookup.findById);
|
|
706
|
+
return additional.length === 0 ? projected : CompiledDocument.make(Object.assign({}, projected, { issues: [...document.issues, ...additional] }));
|
|
723
707
|
});
|
|
708
|
+
const finalLookup = createCatalogLookup(withReferenceIssues, configuration);
|
|
724
709
|
return Result.succeed({
|
|
725
710
|
documents: withReferenceIssues,
|
|
726
711
|
issues: [...withReferenceIssues.flatMap((document) => document.issues), ...translationIssues(withReferenceIssues, configuration)],
|
|
727
|
-
...
|
|
712
|
+
...finalLookup,
|
|
728
713
|
references: references.index
|
|
729
714
|
});
|
|
730
715
|
}
|
|
716
|
+
function resolveSemanticRoutes(document, findById) {
|
|
717
|
+
const nodes = document.body.nodes.map((node) => resolveNodeReferences(node, findById));
|
|
718
|
+
const data = resolveJsonObjectReferences(document.data, findById);
|
|
719
|
+
const frontmatter = resolveJsonObjectReferences(document.body.frontmatter, findById);
|
|
720
|
+
return CompiledDocument.make(Object.assign({}, document, {
|
|
721
|
+
data,
|
|
722
|
+
body: Object.assign({}, document.body, {
|
|
723
|
+
frontmatter,
|
|
724
|
+
nodes
|
|
725
|
+
})
|
|
726
|
+
}));
|
|
727
|
+
}
|
|
728
|
+
function resolveNodeReferences(node, findById) {
|
|
729
|
+
if (Schema.is(Schema.String)(node)) return node;
|
|
730
|
+
const [tag, attributes, ...children] = node;
|
|
731
|
+
if (tag === null) return node;
|
|
732
|
+
return [
|
|
733
|
+
tag,
|
|
734
|
+
resolveJsonObjectReferences(attributes, findById),
|
|
735
|
+
...children.map((child) => resolveNodeReferences(child, findById))
|
|
736
|
+
];
|
|
737
|
+
}
|
|
738
|
+
function resolveJsonObjectReferences(value, findById) {
|
|
739
|
+
return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, resolveJsonReferences(entry, findById)]));
|
|
740
|
+
}
|
|
741
|
+
function resolveJsonReferences(value, findById) {
|
|
742
|
+
if (Schema.is(Schema.String)(value)) {
|
|
743
|
+
const reference = decodeDocumentReference(value);
|
|
744
|
+
if (reference?.kind === "document") {
|
|
745
|
+
const target = findById(reference.documentId);
|
|
746
|
+
return Option.isSome(target) ? target.value.path : reference.lastKnownRoute;
|
|
747
|
+
}
|
|
748
|
+
return decodeManagedMediaReference(value)?.lastKnownUrl ?? value;
|
|
749
|
+
}
|
|
750
|
+
if (Array.isArray(value)) return value.map((entry) => resolveJsonReferences(entry, findById));
|
|
751
|
+
if (Schema.is(Schema.JsonObject)(value)) return resolveJsonObjectReferences(value, findById);
|
|
752
|
+
return value;
|
|
753
|
+
}
|
|
754
|
+
function resolvePlacementGraph(configuration, documents) {
|
|
755
|
+
const byId = /* @__PURE__ */ new Map();
|
|
756
|
+
const homes = /* @__PURE__ */ new Map();
|
|
757
|
+
const issues = [];
|
|
758
|
+
for (const document of documents) {
|
|
759
|
+
if (byId.get(document.id)) {
|
|
760
|
+
issues.push(invalid$1(document, `Document identity "${document.id}" appears more than once.`));
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
763
|
+
byId.set(document.id, document);
|
|
764
|
+
if (document.placement.kind === "home") {
|
|
765
|
+
const key = identityScope(document);
|
|
766
|
+
const existing = homes.get(key);
|
|
767
|
+
if (existing) issues.push(invalid$1(document, `Documents "${existing.id}" and "${document.id}" are both home documents for collection "${document.collection}"${document.locale ? ` in locale "${document.locale}"` : ""}.`));
|
|
768
|
+
else homes.set(key, document);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
const segments = /* @__PURE__ */ new Map();
|
|
772
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
773
|
+
const resolveSegments = (document) => {
|
|
774
|
+
const cached = segments.get(document.id);
|
|
775
|
+
if (cached) return cached;
|
|
776
|
+
if (visiting.has(document.id)) {
|
|
777
|
+
issues.push(invalid$1(document, `Document placement cycle includes "${document.id}".`, "placement"));
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
visiting.add(document.id);
|
|
781
|
+
let result;
|
|
782
|
+
if (document.placement.kind === "home") result = [];
|
|
783
|
+
else {
|
|
784
|
+
const parent = byId.get(document.placement.parentDocumentId);
|
|
785
|
+
if (!parent) issues.push(invalid$1(document, `Parent document "${document.placement.parentDocumentId}" does not exist in this catalog.`, "placement.parentDocumentId"));
|
|
786
|
+
else if (parent.collection !== document.collection) issues.push(invalid$1(document, "A parent document must belong to the same collection.", "placement.parentDocumentId"));
|
|
787
|
+
else if (parent.locale !== document.locale) issues.push(invalid$1(document, "A parent document must use the same locale.", "placement.parentDocumentId"));
|
|
788
|
+
else {
|
|
789
|
+
const collection = configuration.types.find(({ definition }) => definition.collection === document.collection);
|
|
790
|
+
if (!collection) issues.push(invalid$1(document, `Collection "${document.collection}" is not configured.`));
|
|
791
|
+
else if (!collection.definition.hierarchy && parent.placement.kind !== "home") issues.push(invalid$1(document, "This collection allows entries only directly below its home document.", "placement"));
|
|
792
|
+
else {
|
|
793
|
+
const parentSegments = resolveSegments(parent);
|
|
794
|
+
if (parentSegments) result = [...parentSegments, document.placement.slug];
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
visiting.delete(document.id);
|
|
799
|
+
if (result) segments.set(document.id, result);
|
|
800
|
+
return result;
|
|
801
|
+
};
|
|
802
|
+
for (const document of documents) resolveSegments(document);
|
|
803
|
+
if (issues.length > 0) return Result.fail(new DocumentCompilationFailed({ issues }));
|
|
804
|
+
const projected = documents.map((document) => {
|
|
805
|
+
const collection = configuration.types.find(({ definition }) => definition.collection === document.collection);
|
|
806
|
+
const placementSegments = segments.get(document.id);
|
|
807
|
+
if (!collection || !placementSegments) return document;
|
|
808
|
+
const relativeKey = PublicPath.make(`/${placementSegments.join("/")}`);
|
|
809
|
+
const configuredRoute = document.placement.kind === "home" ? collection.homeRoute : collection.entryRoute;
|
|
810
|
+
const route = resolveDocumentAddress(configuredRoute, relativeKey, document.data);
|
|
811
|
+
if (Result.isFailure(route)) {
|
|
812
|
+
issues.push(invalid$1(document, route.failure.message, route.failure.field));
|
|
813
|
+
return document;
|
|
814
|
+
}
|
|
815
|
+
return CompiledDocument.make(Object.assign({}, document, {
|
|
816
|
+
key: route.success,
|
|
817
|
+
path: localizeDocumentPath(route.success, document.locale, configuration.documents.locales)
|
|
818
|
+
}));
|
|
819
|
+
});
|
|
820
|
+
return issues.length > 0 ? Result.fail(new DocumentCompilationFailed({ issues })) : Result.succeed(projected);
|
|
821
|
+
}
|
|
822
|
+
function identityScope(document) {
|
|
823
|
+
return `${document.collection}:${document.locale ?? ""}`;
|
|
824
|
+
}
|
|
825
|
+
function invalid$1(document, message, field) {
|
|
826
|
+
return {
|
|
827
|
+
code: "document.invalid",
|
|
828
|
+
collection: document.collection,
|
|
829
|
+
documentId: document.id,
|
|
830
|
+
...field === void 0 ? void 0 : { field },
|
|
831
|
+
...document.locale === void 0 ? void 0 : { locale: document.locale },
|
|
832
|
+
message,
|
|
833
|
+
severity: "error"
|
|
834
|
+
};
|
|
835
|
+
}
|
|
731
836
|
|
|
732
837
|
//#endregion
|
|
733
838
|
//#region ../document/src/internal/document-engine/configuration.ts
|
|
734
839
|
function resolveDocumentEngineConfiguration(documents, options) {
|
|
735
840
|
if (documents.types.length === 0) return invalid("Documents must define at least one collection.", "types");
|
|
736
841
|
const collections = /* @__PURE__ */ new Set();
|
|
737
|
-
const directories = /* @__PURE__ */ new Map();
|
|
738
842
|
const resolved = [];
|
|
739
843
|
for (const definition of documents.types) {
|
|
740
844
|
if (collections.has(definition.collection)) return invalid(`Document collection "${definition.collection}" is defined more than once.`, "types");
|
|
741
845
|
collections.add(definition.collection);
|
|
742
|
-
const
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
if (
|
|
747
|
-
if (definition.hierarchy && !
|
|
846
|
+
const homeRoute = parseDocumentAddress(definition.routes.home);
|
|
847
|
+
const entryRoute = parseDocumentAddress(definition.routes.entry);
|
|
848
|
+
if (Result.isFailure(homeRoute)) return invalid(homeRoute.failure.message, homeRoute.failure.field);
|
|
849
|
+
if (Result.isFailure(entryRoute)) return invalid(entryRoute.failure.message, entryRoute.failure.field);
|
|
850
|
+
if (homeRoute.success.tokens.length > 0) return invalid(`Document collection "${definition.collection}" home route cannot contain tokens.`, "types");
|
|
851
|
+
if (definition.hierarchy && !entryRoute.success.tokens.some((token) => token.catchAll)) return invalid(`Document collection "${definition.collection}" can only enable hierarchy with a catch-all entry route.`, "types");
|
|
748
852
|
const schema = options.documentModel.types[definition.collection];
|
|
749
853
|
if (!schema) return invalid(`Document collection "${definition.collection}" has no executable schema.`, "documentModel");
|
|
750
854
|
resolved.push({
|
|
751
|
-
address: addressResult.success,
|
|
752
855
|
definition,
|
|
856
|
+
entryRoute: entryRoute.success,
|
|
857
|
+
homeRoute: homeRoute.success,
|
|
753
858
|
schema
|
|
754
859
|
});
|
|
755
860
|
}
|
|
@@ -772,7 +877,6 @@ function resolveDocumentEngineConfiguration(documents, options) {
|
|
|
772
877
|
}
|
|
773
878
|
}
|
|
774
879
|
const mediaBaseUrl = options.mediaBaseUrl?.replace(/\/+$/u, "");
|
|
775
|
-
resolved.sort((left, right) => directoryDepth(right.definition.directory) - directoryDepth(left.definition.directory));
|
|
776
880
|
const configuration = {
|
|
777
881
|
documents,
|
|
778
882
|
types: resolved
|
|
@@ -798,9 +902,6 @@ function resolveComponents(definitions) {
|
|
|
798
902
|
return invalid(cause instanceof Error ? cause.message : "The component authoring catalog is invalid.", "components");
|
|
799
903
|
}
|
|
800
904
|
}
|
|
801
|
-
function directoryDepth(directory) {
|
|
802
|
-
return directory === "." ? 0 : directory.split("/").length;
|
|
803
|
-
}
|
|
804
905
|
function invalid(message, field) {
|
|
805
906
|
return Result.fail(new DocumentEngineConfigurationInvalid(field === void 0 ? { message } : {
|
|
806
907
|
field,
|
|
@@ -819,14 +920,14 @@ const createDocumentEngine = Effect.fn("DocumentEngine.make")(function* (documen
|
|
|
819
920
|
const compileAll = Effect.fn("DocumentEngine.compileAll")(function* (input) {
|
|
820
921
|
const previous = input.previous ? compilations.get(input.previous) : void 0;
|
|
821
922
|
const compiled = yield* Effect.forEach(input.sources, (source) => {
|
|
822
|
-
const cached = previous?.get(source.documentId);
|
|
923
|
+
const cached = previous?.get(source.identity.documentId);
|
|
823
924
|
return cached && sameCompilationSource(cached.source, source) ? Effect.succeed(cached.document) : compile(source);
|
|
824
925
|
});
|
|
825
926
|
const catalog = yield* Effect.fromResult(createDocumentCatalog(configuration, compiled));
|
|
826
927
|
compilations.set(catalog, new Map(input.sources.map((source, index) => {
|
|
827
928
|
const document = compiled[index];
|
|
828
|
-
if (!document) throw new Error(`Compiled document "${source.documentId}" is missing.`);
|
|
829
|
-
return [source.documentId, {
|
|
929
|
+
if (!document) throw new Error(`Compiled document "${source.identity.documentId}" is missing.`);
|
|
930
|
+
return [source.identity.documentId, {
|
|
830
931
|
document,
|
|
831
932
|
source
|
|
832
933
|
}];
|
|
@@ -848,7 +949,7 @@ const createDocumentEngine = Effect.fn("DocumentEngine.make")(function* (documen
|
|
|
848
949
|
code: "markdown.parse",
|
|
849
950
|
message: errorMessage(error.cause),
|
|
850
951
|
severity: "error",
|
|
851
|
-
|
|
952
|
+
documentId: error.documentId
|
|
852
953
|
}] : error.issues;
|
|
853
954
|
return DocumentValidationResult.make({
|
|
854
955
|
valid: false,
|
|
@@ -863,7 +964,7 @@ const createDocumentEngine = Effect.fn("DocumentEngine.make")(function* (documen
|
|
|
863
964
|
};
|
|
864
965
|
});
|
|
865
966
|
function sameCompilationSource(left, right) {
|
|
866
|
-
return left.documentId === right.documentId && left.
|
|
967
|
+
return left.identity.documentId === right.identity.documentId && left.identity.collection === right.identity.collection && left.identity.locale === right.identity.locale && left.placement.kind === right.placement.kind && (left.placement.kind === "home" || right.placement.kind === "entry" && left.placement.parentDocumentId === right.placement.parentDocumentId && left.placement.slug === right.placement.slug) && left.draft === right.draft && left.markdown === right.markdown && samePublishedAt(left.publishedAt, right.publishedAt);
|
|
867
968
|
}
|
|
868
969
|
function samePublishedAt(left, right) {
|
|
869
970
|
return left === void 0 || right === void 0 ? left === right : DateTime.Equivalence(left, right);
|
|
@@ -873,5 +974,5 @@ function errorMessage(cause) {
|
|
|
873
974
|
}
|
|
874
975
|
|
|
875
976
|
//#endregion
|
|
876
|
-
export {
|
|
877
|
-
//# sourceMappingURL=DocumentEngine-
|
|
977
|
+
export { DocumentCompilationFailed as n, createDocumentEngine as t };
|
|
978
|
+
//# sourceMappingURL=DocumentEngine-j6Vi7nQo.js.map
|