@phtngyn/cms 0.1.0-beta.1 → 0.1.0-beta.2

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.
Files changed (142) hide show
  1. package/README.md +192 -9
  2. package/package.json +30 -15
  3. package/src/Configuration-Br7tE9Qt.d.ts +68 -0
  4. package/src/{Configuration-DyKo0sLS.js → Configuration-CA_jvQKG.js} +26 -147
  5. package/src/Configuration-CA_jvQKG.js.map +1 -0
  6. package/src/Configuration.d.ts +2 -44
  7. package/src/Configuration.js +0 -1
  8. package/src/Configuration.js.map +1 -1
  9. package/src/{DocumentEngine-DYObwMDY.js → DocumentEngine-CgiBQU4g.js} +75 -27
  10. package/src/DocumentEngine-CgiBQU4g.js.map +1 -0
  11. package/src/DocumentModel-BB9igGC7.d.ts +34 -0
  12. package/src/DocumentModel.d.ts +2 -34
  13. package/src/DocumentModel.js +13 -3
  14. package/src/DocumentModel.js.map +1 -1
  15. package/src/Forms-BsJMev5_.d.ts +74 -0
  16. package/src/Forms-CfcI3tPU.js +79 -0
  17. package/src/Forms-CfcI3tPU.js.map +1 -0
  18. package/src/Forms-DxbkU3_5.js +367 -0
  19. package/src/Forms-DxbkU3_5.js.map +1 -0
  20. package/src/Forms.d.ts +35 -0
  21. package/src/Forms.js +13 -0
  22. package/src/Forms.js.map +1 -0
  23. package/src/{HttpPaths-BbS21Jy8.js → HttpPaths-c9nLZ9H2.js} +6 -2
  24. package/src/HttpPaths-c9nLZ9H2.js.map +1 -0
  25. package/src/I18n-DZK4CkJF.d.ts +21 -0
  26. package/src/I18n.d.ts +2 -0
  27. package/src/I18n.js +1 -0
  28. package/src/Module.js +57 -11
  29. package/src/Module.js.map +1 -1
  30. package/src/S3MediaObjects-JKMAWyVB.js +2664 -0
  31. package/src/S3MediaObjects-JKMAWyVB.js.map +1 -0
  32. package/src/Seed.d.ts +6 -0
  33. package/src/Seed.js +34 -0
  34. package/src/Seed.js.map +1 -0
  35. package/src/Seo-402YumpT.d.ts +198 -0
  36. package/src/{connection-CBTY-TzB.js → connection-B-iz0Y9Y.js} +5 -7
  37. package/src/connection-B-iz0Y9Y.js.map +1 -0
  38. package/src/{installation-DeuBiFRE.js → installation-DgF2M1gL.js} +1005 -2242
  39. package/src/installation-DgF2M1gL.js.map +1 -0
  40. package/src/internal/authoring-catalog.js +10 -4
  41. package/src/internal/authoring-catalog.js.map +1 -1
  42. package/src/internal/authoring-compiler.js +0 -1
  43. package/src/internal/authoring-compiler.js.map +1 -1
  44. package/src/internal/authoring-metadata.js +4 -4
  45. package/src/internal/authoring-metadata.js.map +1 -1
  46. package/src/internal/cms-config.js +0 -1
  47. package/src/internal/cms-config.js.map +1 -1
  48. package/src/internal/configuration.js +23 -10
  49. package/src/internal/configuration.js.map +1 -1
  50. package/src/internal/document-model.js +65 -20
  51. package/src/internal/document-model.js.map +1 -1
  52. package/src/internal/form-capabilities.js +12 -0
  53. package/src/internal/form-capabilities.js.map +1 -0
  54. package/src/internal/i18n.js +47 -0
  55. package/src/internal/i18n.js.map +1 -0
  56. package/src/internal/studio-app.js +2 -2
  57. package/src/internal/studio-app.js.map +1 -1
  58. package/src/{location-DtYv2aes.js → location-CFKTeK1K.js} +2 -3
  59. package/src/location-CFKTeK1K.js.map +1 -0
  60. package/src/{metadata-DE1Mc2td.js → metadata-BEZPWh-3.js} +3 -72
  61. package/src/metadata-BEZPWh-3.js.map +1 -0
  62. package/src/{models-C3witQBK.js → models-BWm1pTAf.js} +3 -2
  63. package/src/models-BWm1pTAf.js.map +1 -0
  64. package/src/{models-BkMgeaOL.js → models-DwYioyNV.js} +203 -32
  65. package/src/models-DwYioyNV.js.map +1 -0
  66. package/src/runtime/blocks.js +22 -9
  67. package/src/runtime/blocks.js.map +1 -1
  68. package/src/runtime/collaboration.js.map +1 -1
  69. package/src/runtime/delivery/DocumentRenderer.js +7 -4
  70. package/src/runtime/delivery/DocumentRenderer.js.map +1 -1
  71. package/src/runtime/delivery/blocks.js +3 -1
  72. package/src/runtime/delivery/blocks.js.map +1 -1
  73. package/src/runtime/delivery/context.js +1 -1
  74. package/src/runtime/delivery/document-page.js +12 -12
  75. package/src/runtime/delivery/document-page.js.map +1 -1
  76. package/src/runtime/delivery/document.js +4 -2
  77. package/src/runtime/delivery/document.js.map +1 -1
  78. package/src/runtime/delivery/error.js.map +1 -1
  79. package/src/runtime/delivery/plugin.js +22 -2
  80. package/src/runtime/delivery/plugin.js.map +1 -1
  81. package/src/runtime/delivery/types.d.ts +5 -0
  82. package/src/runtime/delivery/useCmsDocumentSeo.d.ts +56 -0
  83. package/src/runtime/delivery/useCmsDocumentSeo.js +99 -0
  84. package/src/runtime/delivery/useCmsDocumentSeo.js.map +1 -0
  85. package/src/runtime/delivery/useDocument.js +2 -2
  86. package/src/runtime/delivery/useDocument.js.map +1 -1
  87. package/src/runtime/delivery/useDocumentQuery.js +2 -2
  88. package/src/runtime/delivery/useDocumentQuery.js.map +1 -1
  89. package/src/runtime/forms/document.js +38 -0
  90. package/src/runtime/forms/document.js.map +1 -0
  91. package/src/runtime/forms/useCmsForm.js +149 -0
  92. package/src/runtime/forms/useCmsForm.js.map +1 -0
  93. package/src/runtime/i18n/translator.js +22 -0
  94. package/src/runtime/i18n/translator.js.map +1 -0
  95. package/src/runtime/i18n/useCmsI18n.d.ts +9 -0
  96. package/src/runtime/i18n/useCmsI18n.js +29 -0
  97. package/src/runtime/i18n/useCmsI18n.js.map +1 -0
  98. package/src/runtime/installation.js +1 -1
  99. package/src/runtime/plugin.js +1 -1
  100. package/src/runtime/plugin.js.map +1 -1
  101. package/src/runtime/preview/comark-document.js +0 -1
  102. package/src/runtime/preview/comark-document.js.map +1 -1
  103. package/src/runtime/preview/connection.js +1 -1
  104. package/src/runtime/preview/controller.js +10 -3
  105. package/src/runtime/preview/controller.js.map +1 -1
  106. package/src/runtime/preview/overlay.js.map +1 -1
  107. package/src/runtime/preview/plugin.client.js +59 -48
  108. package/src/runtime/preview/plugin.client.js.map +1 -1
  109. package/src/runtime/preview/protocol.js.map +1 -1
  110. package/src/runtime/preview/store.js +1 -1
  111. package/src/runtime/preview/targets.js +0 -1
  112. package/src/runtime/preview/targets.js.map +1 -1
  113. package/src/runtime/sitemap-entries.js +17 -0
  114. package/src/runtime/sitemap-entries.js.map +1 -0
  115. package/src/runtime/sitemap.js +24 -0
  116. package/src/runtime/sitemap.js.map +1 -0
  117. package/src/runtime/studio-app.js.map +1 -1
  118. package/src/runtime/studio-entry.js +2 -2
  119. package/src/runtime/studio-entry.js.map +1 -1
  120. package/src/runtime/studio-navigation.js +1 -1
  121. package/src/scalars-B2lgGUnj.js +26 -0
  122. package/src/scalars-B2lgGUnj.js.map +1 -0
  123. package/src/{store-CfFFx9Ua.js → store-DjJs3I7k.js} +12 -7
  124. package/src/store-DjJs3I7k.js.map +1 -0
  125. package/studio/{CreateDocumentDialog--L9lTfx6.js → CreateDocumentDialog-CTeIFlPb.js} +44 -44
  126. package/studio/{collaboration-DUuu678R.js → collaboration-DcK2F6v9.js} +7 -6
  127. package/studio/{documentPlanning-BXX04Woe.js → documentPlanning-Bfv-d7OU.js} +7310 -6479
  128. package/studio/{editor-PexnXkJY.js → editor-Bzlh3zXt.js} +7965 -7955
  129. package/studio/host.css +1 -1
  130. package/studio/host.js +10416 -7981
  131. package/src/Configuration-DyKo0sLS.js.map +0 -1
  132. package/src/DocumentEngine-DYObwMDY.js.map +0 -1
  133. package/src/HttpPaths-BbS21Jy8.js.map +0 -1
  134. package/src/StudioHttp-jR2-bc01.js +0 -718
  135. package/src/StudioHttp-jR2-bc01.js.map +0 -1
  136. package/src/connection-CBTY-TzB.js.map +0 -1
  137. package/src/installation-DeuBiFRE.js.map +0 -1
  138. package/src/location-DtYv2aes.js.map +0 -1
  139. package/src/metadata-DE1Mc2td.js.map +0 -1
  140. package/src/models-BkMgeaOL.js.map +0 -1
  141. package/src/models-C3witQBK.js.map +0 -1
  142. package/src/store-CfFFx9Ua.js.map +0 -1
@@ -0,0 +1,79 @@
1
+ import { r as DocumentId } from "./scalars-B2lgGUnj.js";
2
+ import { Schema } from "effect";
3
+
4
+ //#region ../protocol/src/Forms.ts
5
+ const FORM_SUBMISSION_MAX_BYTES = 131072;
6
+ /** Budget for the JSON-escaped revision, leaving space for the envelope and answers. */
7
+ const FORM_REVISION_MAX_BYTES = 6e4;
8
+ const FormFieldType = Schema.Literals([
9
+ "text",
10
+ "email",
11
+ "textarea",
12
+ "number",
13
+ "checkbox",
14
+ "select"
15
+ ]);
16
+ const FormRule = Schema.Literals([
17
+ "required",
18
+ "minLength",
19
+ "maxLength",
20
+ "min",
21
+ "max"
22
+ ]);
23
+ const FormCapabilities = Schema.Struct({
24
+ label: Schema.NonEmptyString,
25
+ fieldTypes: Schema.Array(FormFieldType).check(Schema.isMinLength(1)),
26
+ rules: Schema.Array(FormRule)
27
+ });
28
+ const FormOption = Schema.Struct({
29
+ id: Schema.NonEmptyString,
30
+ label: Schema.NonEmptyString
31
+ });
32
+ const FormField = Schema.Struct({
33
+ id: Schema.NonEmptyString,
34
+ label: Schema.NonEmptyString,
35
+ type: FormFieldType,
36
+ help: Schema.optionalKey(Schema.String),
37
+ required: Schema.optionalKey(Schema.Boolean),
38
+ minLength: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),
39
+ maxLength: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),
40
+ min: Schema.optionalKey(Schema.Finite),
41
+ max: Schema.optionalKey(Schema.Finite),
42
+ options: Schema.optionalKey(Schema.Array(FormOption))
43
+ });
44
+ const FormStep = Schema.Struct({
45
+ id: Schema.NonEmptyString,
46
+ title: Schema.NonEmptyString,
47
+ fields: Schema.Array(FormField).check(Schema.isMinLength(1), Schema.isMaxLength(100))
48
+ });
49
+ const FormSteps = Schema.Array(FormStep).check(Schema.isMinLength(1), Schema.isMaxLength(20));
50
+ const referenceFields = {
51
+ documentId: DocumentId,
52
+ nodePath: Schema.Array(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))).check(Schema.isMinLength(1), Schema.isMaxLength(64)),
53
+ revision: Schema.String.check(Schema.isMaxLength(FORM_REVISION_MAX_BYTES))
54
+ };
55
+ const FormReference = Schema.Struct(referenceFields);
56
+ const FormValues = Schema.Record(Schema.String, Schema.Union([
57
+ Schema.String,
58
+ Schema.Finite,
59
+ Schema.Boolean,
60
+ Schema.Null
61
+ ]));
62
+ const FormSubmission = Schema.Struct({
63
+ ...referenceFields,
64
+ values: FormValues
65
+ });
66
+ const FormResult = Schema.Struct({
67
+ status: Schema.Literals([
68
+ "accepted",
69
+ "invalid",
70
+ "stale",
71
+ "unavailable",
72
+ "failed"
73
+ ]),
74
+ errors: Schema.Record(Schema.String, Schema.String)
75
+ });
76
+
77
+ //#endregion
78
+ export { FormSteps as a, FormResult as i, FORM_SUBMISSION_MAX_BYTES as n, FormSubmission as o, FormCapabilities as r, FORM_REVISION_MAX_BYTES as t };
79
+ //# sourceMappingURL=Forms-CfcI3tPU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Forms-CfcI3tPU.js","names":[],"sources":["../../../../protocol/src/Forms.ts"],"sourcesContent":["import { Schema } from 'effect'\nimport { DocumentId } from './internal/documents/scalars'\n\nexport const FORM_SUBMISSION_MAX_BYTES = 128 * 1024\n\n/** Budget for the JSON-escaped revision, leaving space for the envelope and answers. */\nexport const FORM_REVISION_MAX_BYTES = 60000\n\nexport type FormFieldType = 'text' | 'email' | 'textarea' | 'number' | 'checkbox' | 'select'\n\nexport const FormFieldType: Schema.Codec<FormFieldType> = Schema.Literals([\n 'text',\n 'email',\n 'textarea',\n 'number',\n 'checkbox',\n 'select',\n])\n\nexport type FormRule = 'required' | 'minLength' | 'maxLength' | 'min' | 'max'\n\nexport const FormRule: Schema.Codec<FormRule> = Schema.Literals(['required', 'minLength', 'maxLength', 'min', 'max'])\n\nexport interface FormCapabilities {\n readonly label: string\n readonly fieldTypes: ReadonlyArray<FormFieldType>\n readonly rules: ReadonlyArray<FormRule>\n}\n\nexport const FormCapabilities: Schema.Codec<FormCapabilities> = Schema.Struct({\n label: Schema.NonEmptyString,\n fieldTypes: Schema.Array(FormFieldType).check(Schema.isMinLength(1)),\n rules: Schema.Array(FormRule),\n})\n\nexport interface FormOption {\n readonly id: string\n readonly label: string\n}\n\nexport const FormOption: Schema.Codec<FormOption> = Schema.Struct({\n id: Schema.NonEmptyString,\n label: Schema.NonEmptyString,\n})\n\nexport interface FormField {\n readonly id: string\n readonly label: string\n readonly type: FormFieldType\n readonly help?: string\n readonly required?: boolean\n readonly minLength?: number\n readonly maxLength?: number\n readonly min?: number\n readonly max?: number\n readonly options?: ReadonlyArray<FormOption>\n}\n\nexport const FormField: Schema.Codec<FormField> = Schema.Struct({\n id: Schema.NonEmptyString,\n label: Schema.NonEmptyString,\n type: FormFieldType,\n help: Schema.optionalKey(Schema.String),\n required: Schema.optionalKey(Schema.Boolean),\n minLength: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),\n maxLength: Schema.optionalKey(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))),\n min: Schema.optionalKey(Schema.Finite),\n max: Schema.optionalKey(Schema.Finite),\n options: Schema.optionalKey(Schema.Array(FormOption)),\n})\n\nexport interface FormStep {\n readonly id: string\n readonly title: string\n readonly fields: ReadonlyArray<FormField>\n}\n\nexport const FormStep: Schema.Codec<FormStep> = Schema.Struct({\n id: Schema.NonEmptyString,\n title: Schema.NonEmptyString,\n fields: Schema.Array(FormField).check(Schema.isMinLength(1), Schema.isMaxLength(100)),\n})\n\nexport const FormSteps: Schema.Codec<ReadonlyArray<FormStep>> = Schema.Array(FormStep).check(\n Schema.isMinLength(1),\n Schema.isMaxLength(20),\n)\n\nexport interface FormReference {\n readonly documentId: DocumentId\n readonly nodePath: ReadonlyArray<number>\n readonly revision: string\n}\n\nconst referenceFields = {\n documentId: DocumentId,\n nodePath: Schema.Array(Schema.Int.check(Schema.isGreaterThanOrEqualTo(0))).check(\n Schema.isMinLength(1),\n Schema.isMaxLength(64),\n ),\n revision: Schema.String.check(Schema.isMaxLength(FORM_REVISION_MAX_BYTES)),\n}\n\nexport const FormReference: Schema.Codec<\n FormReference,\n { readonly documentId: string; readonly nodePath: ReadonlyArray<number>; readonly revision: string }\n> = Schema.Struct(referenceFields)\n\nexport interface FormDefinition extends FormReference {\n readonly name: string\n readonly steps: ReadonlyArray<FormStep>\n readonly preview: boolean\n}\n\nexport type FormValues = Readonly<Record<string, string | number | boolean | null>>\n\nexport const FormValues: Schema.Codec<FormValues> = Schema.Record(\n Schema.String,\n Schema.Union([Schema.String, Schema.Finite, Schema.Boolean, Schema.Null]),\n)\n\nexport interface FormSubmission extends FormReference {\n readonly values: FormValues\n}\n\nexport const FormSubmission: Schema.Codec<\n FormSubmission,\n {\n readonly documentId: string\n readonly nodePath: ReadonlyArray<number>\n readonly revision: string\n readonly values: FormValues\n }\n> = Schema.Struct({ ...referenceFields, values: FormValues })\n\nexport interface FormResult {\n readonly status: 'accepted' | 'invalid' | 'stale' | 'unavailable' | 'failed'\n readonly errors: Readonly<Record<string, string>>\n}\n\nexport const FormResult: Schema.Codec<FormResult> = Schema.Struct({\n status: Schema.Literals(['accepted', 'invalid', 'stale', 'unavailable', 'failed']),\n errors: Schema.Record(Schema.String, Schema.String),\n})\n"],"mappings":";;;;AAGA,MAAa,4BAA4B;;AAGzC,MAAa,0BAA0B;AAIvC,MAAa,gBAA6C,OAAO,SAAS;CACxE;CACA;CACA;CACA;CACA;CACA;AACF,CAAC;AAID,MAAa,WAAmC,OAAO,SAAS;CAAC;CAAY;CAAa;CAAa;CAAO;AAAK,CAAC;AAQpH,MAAa,mBAAmD,OAAO,OAAO;CAC5E,OAAO,OAAO;CACd,YAAY,OAAO,MAAM,aAAa,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;CACnE,OAAO,OAAO,MAAM,QAAQ;AAC9B,CAAC;AAOD,MAAa,aAAuC,OAAO,OAAO;CAChE,IAAI,OAAO;CACX,OAAO,OAAO;AAChB,CAAC;AAeD,MAAa,YAAqC,OAAO,OAAO;CAC9D,IAAI,OAAO;CACX,OAAO,OAAO;CACd,MAAM;CACN,MAAM,OAAO,YAAY,OAAO,MAAM;CACtC,UAAU,OAAO,YAAY,OAAO,OAAO;CAC3C,WAAW,OAAO,YAAY,OAAO,IAAI,MAAM,OAAO,uBAAuB,CAAC,CAAC,CAAC;CAChF,WAAW,OAAO,YAAY,OAAO,IAAI,MAAM,OAAO,uBAAuB,CAAC,CAAC,CAAC;CAChF,KAAK,OAAO,YAAY,OAAO,MAAM;CACrC,KAAK,OAAO,YAAY,OAAO,MAAM;CACrC,SAAS,OAAO,YAAY,OAAO,MAAM,UAAU,CAAC;AACtD,CAAC;AAQD,MAAa,WAAmC,OAAO,OAAO;CAC5D,IAAI,OAAO;CACX,OAAO,OAAO;CACd,QAAQ,OAAO,MAAM,SAAS,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,GAAG,OAAO,YAAY,GAAG,CAAC;AACtF,CAAC;AAED,MAAa,YAAmD,OAAO,MAAM,QAAQ,CAAC,CAAC,MACrF,OAAO,YAAY,CAAC,GACpB,OAAO,YAAY,EAAE,CACvB;AAQA,MAAM,kBAAkB;CACtB,YAAY;CACZ,UAAU,OAAO,MAAM,OAAO,IAAI,MAAM,OAAO,uBAAuB,CAAC,CAAC,CAAC,CAAC,CAAC,MACzE,OAAO,YAAY,CAAC,GACpB,OAAO,YAAY,EAAE,CACvB;CACA,UAAU,OAAO,OAAO,MAAM,OAAO,YAAY,uBAAuB,CAAC;AAC3E;AAEA,MAAa,gBAGT,OAAO,OAAO,eAAe;AAUjC,MAAa,aAAuC,OAAO,OACzD,OAAO,QACP,OAAO,MAAM;CAAC,OAAO;CAAQ,OAAO;CAAQ,OAAO;CAAS,OAAO;AAAI,CAAC,CAC1E;AAMA,MAAa,iBAQT,OAAO,OAAO;CAAE,GAAG;CAAiB,QAAQ;AAAW,CAAC;AAO5D,MAAa,aAAuC,OAAO,OAAO;CAChE,QAAQ,OAAO,SAAS;EAAC;EAAY;EAAW;EAAS;EAAe;CAAQ,CAAC;CACjF,QAAQ,OAAO,OAAO,OAAO,QAAQ,OAAO,MAAM;AACpD,CAAC"}
@@ -0,0 +1,367 @@
1
+ import { a as FormSteps, t as FORM_REVISION_MAX_BYTES } from "./Forms-CfcI3tPU.js";
2
+ import { n as CmsMarkdownDocument } from "./models-DwYioyNV.js";
3
+ import { Option, Predicate, Result, Schema } from "effect";
4
+ import { resolveAttributes, textContent } from "comark/utils";
5
+
6
+ //#region ../document/src/internal/comark/document-adapter.ts
7
+ const isJsonObject$1 = Schema.is(Schema.JsonObject);
8
+ function toComarkDocument(document) {
9
+ return {
10
+ frontmatter: mutableJsonObject(document.frontmatter),
11
+ meta: mutableJsonObject(document.meta),
12
+ nodes: document.nodes.map(toComarkNode)
13
+ };
14
+ }
15
+ function createCmsComarkRenderData(document) {
16
+ return {
17
+ data: {},
18
+ frontmatter: mutableJsonObject(document.frontmatter),
19
+ meta: mutableJsonObject(document.meta),
20
+ props: {}
21
+ };
22
+ }
23
+ /** Extracts inline text with Comark semantics, preserving punctuation between nested inline nodes. */
24
+ function cmsComarkTextContent(node) {
25
+ return textContent(toComarkNode(node), { decodeUnicodeEntities: true });
26
+ }
27
+ function toMutableComarkAttributes(attributes) {
28
+ const result = {};
29
+ for (const [name, value] of Object.entries(attributes)) if (name !== "$") result[name] = mutableJson(value);
30
+ const internal = jsonObject$1(attributes.$);
31
+ const line = internal.line;
32
+ const html = binaryFlag(internal.html);
33
+ const block = binaryFlag(internal.block);
34
+ if (Predicate.isNumber(line) || html !== void 0 || block !== void 0) {
35
+ const metadata = {};
36
+ if (Predicate.isNumber(line)) metadata.line = line;
37
+ if (html !== void 0) metadata.html = html;
38
+ if (block !== void 0) metadata.block = block;
39
+ result.$ = metadata;
40
+ }
41
+ return result;
42
+ }
43
+ function mutableJson(value) {
44
+ if (Array.isArray(value)) return value.map(mutableJson);
45
+ if (isJsonObject$1(value)) return mutableJsonObject(value);
46
+ return value;
47
+ }
48
+ function toComarkNode(node) {
49
+ if (Predicate.isString(node)) return node;
50
+ if (node[0] === null) return [
51
+ null,
52
+ toMutableComarkAttributes(node[1]),
53
+ node[2]
54
+ ];
55
+ const [tag, attributes, ...children] = node;
56
+ return [
57
+ tag,
58
+ toMutableComarkAttributes(attributes),
59
+ ...children.map(toComarkNode)
60
+ ];
61
+ }
62
+ function mutableJsonObject(value) {
63
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, mutableJson(child)]));
64
+ }
65
+ function binaryFlag(value) {
66
+ return value === 0 || value === 1 ? value : void 0;
67
+ }
68
+ function jsonObject$1(value) {
69
+ return isJsonObject$1(value) ? value : {};
70
+ }
71
+
72
+ //#endregion
73
+ //#region ../document/src/internal/comark/bindings.ts
74
+ const isJsonObject = Schema.is(Schema.JsonObject);
75
+ const decodeJson = Schema.decodeUnknownOption(Schema.Json);
76
+ /** Normalizes bindings exactly as Comark's framework renderers do before passing props to a component. */
77
+ function resolveCmsComarkAttributes(attributes, renderData) {
78
+ const resolved = /* @__PURE__ */ new Map();
79
+ for (const [name, value] of Object.entries(resolveAttributes(toMutableComarkAttributes(attributes), renderData, { parseJson: true }))) {
80
+ if (Predicate.isUndefined(value)) {
81
+ resolved.set(name, void 0);
82
+ continue;
83
+ }
84
+ const decoded = decodeJson(value);
85
+ if (Option.isNone(decoded)) throw new Error(`Comark resolved non-JSON attribute "${name}".`);
86
+ resolved.set(name, decoded.value);
87
+ }
88
+ return resolved;
89
+ }
90
+ /** Projects bindings to editable values while retaining enough metadata to reconstruct their authored form. */
91
+ function projectCmsEditorComponentAttributes(attributes, renderData) {
92
+ const resolved = resolveCmsComarkAttributes(attributes, renderData);
93
+ const props = {};
94
+ for (const [name, value] of resolved) if (!Predicate.isUndefined(value)) props[name] = mutableJson(value);
95
+ const bindings = {};
96
+ for (const [authoredName, authoredValue] of Object.entries(attributes)) {
97
+ if (!authoredName.startsWith(":") || authoredName.length === 1) continue;
98
+ const name = authoredName.slice(1);
99
+ if (!resolved.has(name)) continue;
100
+ const literal = jsonLiteral(authoredValue);
101
+ if (!Predicate.isString(authoredValue) || literal !== authoredValue) {
102
+ bindings[name] = { kind: "literal" };
103
+ continue;
104
+ }
105
+ const resolvedValue = resolved.get(name);
106
+ bindings[name] = Object.assign({
107
+ expression: authoredValue,
108
+ kind: "expression"
109
+ }, Predicate.isUndefined(resolvedValue) ? void 0 : { resolved: mutableJson(resolvedValue) });
110
+ }
111
+ return {
112
+ bindings,
113
+ props,
114
+ renderData: withCmsComarkProps(renderData, resolved)
115
+ };
116
+ }
117
+ /** Reconstructs authored bindings, keeping expressions until a user replaces their resolved value. */
118
+ function encodeCmsEditorComponentAttributes(props, bindings) {
119
+ const attributes = mutableJsonObject(props);
120
+ for (const [name, encodedBinding] of Object.entries(bindings)) {
121
+ const binding = jsonObject(encodedBinding);
122
+ const kind = binding.kind;
123
+ if (kind !== "literal" && kind !== "expression") continue;
124
+ const current = props[name];
125
+ if (Predicate.isUndefined(current)) {
126
+ const expression = binding.expression;
127
+ if (kind === "expression" && Predicate.isString(expression)) attributes[`:${name}`] = expression;
128
+ continue;
129
+ }
130
+ delete attributes[name];
131
+ const expression = binding.expression;
132
+ const resolved = binding.resolved;
133
+ attributes[`:${name}`] = kind === "expression" && Predicate.isString(expression) && Object.hasOwn(binding, "resolved") && sameJson(current, resolved) ? expression : mutableJson(current);
134
+ }
135
+ return attributes;
136
+ }
137
+ function withCmsComarkProps(renderData, attributes) {
138
+ return attributes.size > 0 ? {
139
+ ...renderData,
140
+ props: Object.fromEntries(attributes)
141
+ } : renderData;
142
+ }
143
+ /** Restores typed component bindings that Comark's block-YAML roundtrip can emit as plain attributes. */
144
+ function normalizeCmsComponentBindings(document, components) {
145
+ if (!components) return document;
146
+ return CmsMarkdownDocument.make({
147
+ frontmatter: document.frontmatter,
148
+ meta: document.meta,
149
+ nodes: document.nodes.map((node) => normalizeComponentNode(node, components))
150
+ });
151
+ }
152
+ function matchesCmsComponentPropType(value, type) {
153
+ switch (type) {
154
+ case "object": return isJsonObject(value);
155
+ case "array": return Array.isArray(value);
156
+ case "boolean": return Predicate.isBoolean(value);
157
+ case "number": return Predicate.isNumber(value);
158
+ case "string": return Predicate.isString(value);
159
+ }
160
+ }
161
+ function normalizeComponentNode(node, components) {
162
+ if (Predicate.isString(node) || node[0] === null) return node;
163
+ const [tag, originalAttributes, ...originalChildren] = node;
164
+ const attributes = mutableJsonObject(originalAttributes);
165
+ const definition = components.get(tag.toLocaleLowerCase());
166
+ if (definition) for (const prop of definition.authoring.props) {
167
+ if (prop.type === "string" || `:${prop.name}` in attributes || !(prop.name in attributes)) continue;
168
+ const value = attributes[prop.name];
169
+ if (Predicate.isUndefined(value)) continue;
170
+ if (!matchesCmsComponentPropType(jsonLiteral(value), prop.type)) continue;
171
+ delete attributes[prop.name];
172
+ attributes[`:${prop.name}`] = value;
173
+ }
174
+ return [
175
+ tag,
176
+ attributes,
177
+ ...originalChildren.map((child) => normalizeComponentNode(child, components))
178
+ ];
179
+ }
180
+ function jsonLiteral(value) {
181
+ if (!Predicate.isString(value)) return value;
182
+ try {
183
+ const decoded = decodeJson(JSON.parse(value));
184
+ return Option.isSome(decoded) ? decoded.value : value;
185
+ } catch {
186
+ return value;
187
+ }
188
+ }
189
+ function jsonObject(value) {
190
+ return isJsonObject(value) ? value : {};
191
+ }
192
+ function sameJson(left, right) {
193
+ return !Predicate.isUndefined(right) && JSON.stringify(left) === JSON.stringify(right);
194
+ }
195
+
196
+ //#endregion
197
+ //#region ../document/src/Forms.ts
198
+ function formStructureIssues(input, capabilities, name) {
199
+ const decoded = Schema.decodeUnknownResult(FormSteps)(input, { onExcessProperty: "error" });
200
+ if (Result.isFailure(decoded)) return ["Each form needs steps with a title and at least one valid question."];
201
+ const issues = [];
202
+ if (new TextEncoder().encode(JSON.stringify(formRevision(name, capabilities, decoded.success))).byteLength > 6e4) issues.push("This form is too large. Reduce the number or size of questions.");
203
+ const ids = /* @__PURE__ */ new Set();
204
+ for (const step of decoded.success) {
205
+ if (ids.has(step.id)) issues.push("Steps and questions must have unique identities.");
206
+ ids.add(step.id);
207
+ for (const field of step.fields) {
208
+ if (ids.has(field.id)) issues.push("Steps and questions must have unique identities.");
209
+ ids.add(field.id);
210
+ if ([
211
+ "_form",
212
+ "__proto__",
213
+ "constructor",
214
+ "prototype"
215
+ ].includes(field.id)) issues.push("This question identity is reserved.");
216
+ if (!capabilities.fieldTypes.includes(field.type)) issues.push(`${field.label}: this question type is unavailable.`);
217
+ for (const rule of [
218
+ "required",
219
+ "minLength",
220
+ "maxLength",
221
+ "min",
222
+ "max"
223
+ ]) if (field[rule] !== void 0 && !capabilities.rules.includes(rule)) issues.push(`${field.label}: ${rule} is unavailable.`);
224
+ if (![
225
+ "text",
226
+ "email",
227
+ "textarea"
228
+ ].includes(field.type) && (field.minLength !== void 0 || field.maxLength !== void 0)) issues.push(`${field.label}: length limits require a text question.`);
229
+ if (field.type !== "number" && (field.min !== void 0 || field.max !== void 0)) issues.push(`${field.label}: numeric limits require a number question.`);
230
+ if (field.min !== void 0 && field.max !== void 0 && field.min > field.max) issues.push(`${field.label}: minimum exceeds maximum.`);
231
+ if (field.minLength !== void 0 && field.maxLength !== void 0 && field.minLength > field.maxLength) issues.push(`${field.label}: minimum length exceeds maximum length.`);
232
+ const options = field.options ?? [];
233
+ if (field.type === "select" && (!options.length || new Set(options.map((option) => option.id)).size !== options.length)) issues.push(`${field.label}: choices need unique identities and at least one option.`);
234
+ if (field.type !== "select" && options.length) issues.push(`${field.label}: choices require a select question.`);
235
+ }
236
+ }
237
+ return issues;
238
+ }
239
+ function validateFormValues(fields, values) {
240
+ return Object.fromEntries(fields.flatMap((field) => {
241
+ const issue = fieldIssue(field, Object.hasOwn(values, field.id) ? values[field.id] : void 0);
242
+ return issue ? [[field.id, issue]] : [];
243
+ }));
244
+ }
245
+ function fieldIssue(field, value) {
246
+ if (value === void 0 || value === null || value === "" || Predicate.isString(value) && !value.trim()) return field.required ? `${field.label} is required.` : void 0;
247
+ if (field.type === "checkbox") return !Predicate.isBoolean(value) ? "Choose yes or no." : field.required && !value ? `${field.label} must be checked.` : void 0;
248
+ if (field.type === "number") {
249
+ if (!Predicate.isNumber(value) || !Number.isFinite(value)) return "Enter a number.";
250
+ if (field.min !== void 0 && value < field.min) return `Enter at least ${field.min}.`;
251
+ if (field.max !== void 0 && value > field.max) return `Enter at most ${field.max}.`;
252
+ return;
253
+ }
254
+ if (!Predicate.isString(value)) return "Enter text.";
255
+ if (field.type === "select" && !field.options?.some((option) => option.id === value)) return "Choose an available option.";
256
+ if (field.type === "email" && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/u.test(value)) return "Enter a valid email address.";
257
+ if (field.minLength !== void 0 && value.length < field.minLength) return `Enter at least ${field.minLength} characters.`;
258
+ if (field.maxLength !== void 0 && value.length > field.maxLength) return `Enter at most ${field.maxLength} characters.`;
259
+ }
260
+ /** Paths refer to authored nodes, never rendered Vue children. Revision comparison is exact. */
261
+ function documentForms(document, components, preview = false) {
262
+ const forms = [];
263
+ const visit = (nodes, parent, renderData) => {
264
+ nodes.forEach((node, index) => {
265
+ if (Predicate.isString(node) || node[0] === null) return;
266
+ const nodePath = [...parent, index];
267
+ const projection = projectCmsEditorComponentAttributes(node[1], renderData);
268
+ const capabilities = components.find((component) => component.name === node[0])?.authoring.form;
269
+ if (capabilities && !formStructureIssues(projection.props.steps, capabilities, node[0]).length) {
270
+ const steps = Result.getOrThrow(Schema.decodeUnknownResult(FormSteps)(projection.props.steps));
271
+ forms.push({
272
+ name: node[0],
273
+ documentId: document.id,
274
+ nodePath,
275
+ steps,
276
+ preview,
277
+ revision: formRevision(node[0], capabilities, steps)
278
+ });
279
+ }
280
+ visit(node.slice(2).filter(isNode), nodePath, projection.renderData);
281
+ });
282
+ };
283
+ visit(document.body.nodes, [], createCmsComarkRenderData(document.body));
284
+ return forms;
285
+ }
286
+ function formRevision(name, capabilities, steps) {
287
+ return JSON.stringify([
288
+ name,
289
+ capabilities,
290
+ steps
291
+ ]);
292
+ }
293
+ function isNode(value) {
294
+ return Predicate.isString(value) || Array.isArray(value);
295
+ }
296
+ function formAuthoring(capabilities) {
297
+ const prop = (name, label, type, input, extra = {}) => ({
298
+ name,
299
+ label,
300
+ type,
301
+ input,
302
+ required: false,
303
+ nullable: false,
304
+ options: [],
305
+ ...extra
306
+ });
307
+ const question = [
308
+ prop("label", "Question", "string", "text", {
309
+ required: true,
310
+ defaultValue: "New question"
311
+ }),
312
+ prop("type", "Answer type", "string", "select", {
313
+ required: true,
314
+ defaultValue: capabilities.fieldTypes[0],
315
+ options: capabilities.fieldTypes.map((value) => ({
316
+ value,
317
+ label: value
318
+ }))
319
+ }),
320
+ prop("help", "Help text", "string", "textarea"),
321
+ ...capabilities.rules.map((rule) => prop(rule, {
322
+ required: "Required",
323
+ minLength: "Minimum characters",
324
+ maxLength: "Maximum characters",
325
+ min: "Minimum value",
326
+ max: "Maximum value"
327
+ }[rule], rule === "required" ? "boolean" : "number", rule === "required" ? "toggle" : "number")),
328
+ prop("options", "Choices", "array", "list", { fields: [prop("label", "Choice", "string", "text", {
329
+ required: true,
330
+ defaultValue: "New choice"
331
+ })] })
332
+ ];
333
+ return {
334
+ version: 1,
335
+ label: capabilities.label,
336
+ group: "Forms",
337
+ form: capabilities,
338
+ props: [prop("steps", "Steps", "array", "list", {
339
+ required: true,
340
+ fields: [prop("title", "Step title", "string", "text", {
341
+ required: true,
342
+ defaultValue: "New step"
343
+ }), prop("fields", "Questions", "array", "list", {
344
+ required: true,
345
+ fields: question
346
+ })]
347
+ })],
348
+ slots: [],
349
+ initialProps: { steps: [{
350
+ id: "first-step",
351
+ title: "Your details",
352
+ fields: [{
353
+ id: "first-question",
354
+ label: "Your answer",
355
+ type: capabilities.fieldTypes[0] ?? "text",
356
+ ...capabilities.fieldTypes[0] === "select" ? { options: [{
357
+ id: "first-choice",
358
+ label: "First choice"
359
+ }] } : void 0
360
+ }]
361
+ }] }
362
+ };
363
+ }
364
+
365
+ //#endregion
366
+ export { encodeCmsEditorComponentAttributes as a, resolveCmsComarkAttributes as c, createCmsComarkRenderData as d, mutableJson as f, validateFormValues as i, withCmsComarkProps as l, toComarkDocument as m, formAuthoring as n, normalizeCmsComponentBindings as o, mutableJsonObject as p, formStructureIssues as r, projectCmsEditorComponentAttributes as s, documentForms as t, cmsComarkTextContent as u };
367
+ //# sourceMappingURL=Forms-DxbkU3_5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Forms-DxbkU3_5.js","names":["isJsonObject","jsonObject","CmsMarkdownDocumentSchema"],"sources":["../../../../document/src/internal/comark/document-adapter.ts","../../../../document/src/internal/comark/bindings.ts","../../../../document/src/Forms.ts"],"sourcesContent":["import type { CmsMarkdownDocument, MarkdownNode } from '@internal/protocol/Documents'\nimport type {\n ElementNodeAttributes,\n MarkdownDocument as ComarkMarkdownDocument,\n Node as ComarkNode,\n NodeRenderData,\n} from 'comark'\nimport { textContent } from 'comark/utils'\nimport { Predicate, Schema } from 'effect'\n\nconst isJsonObject = Schema.is(Schema.JsonObject)\n\nexport function toComarkDocument(document: CmsMarkdownDocument): ComarkMarkdownDocument {\n return {\n frontmatter: mutableJsonObject(document.frontmatter),\n meta: mutableJsonObject(document.meta),\n nodes: document.nodes.map(toComarkNode),\n }\n}\n\nexport function createCmsComarkRenderData(document: CmsMarkdownDocument): NodeRenderData {\n return {\n data: {},\n frontmatter: mutableJsonObject(document.frontmatter),\n meta: mutableJsonObject(document.meta),\n props: {},\n }\n}\n\n/** Extracts inline text with Comark semantics, preserving punctuation between nested inline nodes. */\nexport function cmsComarkTextContent(node: MarkdownNode): string {\n return textContent(toComarkNode(node), { decodeUnicodeEntities: true })\n}\n\nexport function toMutableComarkAttributes(attributes: Schema.JsonObject): ElementNodeAttributes {\n const result: ElementNodeAttributes = {}\n\n for (const [name, value] of Object.entries(attributes)) {\n if (name !== '$') result[name] = mutableJson(value)\n }\n\n const internal = jsonObject(attributes.$)\n const line = internal.line\n const html = binaryFlag(internal.html)\n const block = binaryFlag(internal.block)\n\n if (Predicate.isNumber(line) || html !== undefined || block !== undefined) {\n const metadata: Record<string, number> = {}\n\n if (Predicate.isNumber(line)) metadata.line = line\n\n if (html !== undefined) metadata.html = html\n\n if (block !== undefined) metadata.block = block\n result.$ = metadata\n }\n\n return result\n}\n\nexport function mutableJson(value: Schema.Json): Schema.Json {\n if (Array.isArray(value)) return value.map(mutableJson)\n\n if (isJsonObject(value)) return mutableJsonObject(value)\n\n return value\n}\n\nfunction toComarkNode(node: MarkdownNode): ComarkNode {\n if (Predicate.isString(node)) return node\n\n if (node[0] === null) return [null, toMutableComarkAttributes(node[1]), node[2]]\n const [tag, attributes, ...children] = node\n\n return [tag, toMutableComarkAttributes(attributes), ...children.map(toComarkNode)]\n}\n\nexport function mutableJsonObject(value: Schema.JsonObject): Record<string, Schema.Json> {\n return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, mutableJson(child)]))\n}\n\nfunction binaryFlag(value: Schema.Json | undefined): 0 | 1 | undefined {\n return value === 0 || value === 1 ? value : undefined\n}\n\nfunction jsonObject(value: Schema.Json | undefined): Schema.JsonObject {\n return isJsonObject(value) ? value : {}\n}\n","import type { ComponentDefinition } from '@internal/protocol/Configuration'\nimport type { CmsMarkdownDocument, MarkdownNode } from '@internal/protocol/Documents'\nimport type { NodeRenderData } from 'comark'\nimport { CmsMarkdownDocument as CmsMarkdownDocumentSchema } from '@internal/protocol/Documents'\nimport { resolveAttributes } from 'comark/utils'\nimport { Option, Predicate, Schema } from 'effect'\nimport { mutableJson, mutableJsonObject, toMutableComarkAttributes } from './document-adapter'\n\nconst isJsonObject = Schema.is(Schema.JsonObject)\n\nconst decodeJson = Schema.decodeUnknownOption(Schema.Json)\n\nexport type CmsComarkAttributeValue = Schema.Json | undefined\n\nexport type CmsComarkAttributes = ReadonlyMap<string, CmsComarkAttributeValue>\n\ninterface CmsEditorComponentProjection {\n readonly bindings: Schema.JsonObject\n readonly props: Schema.JsonObject\n readonly renderData: NodeRenderData\n}\n\n/** Normalizes bindings exactly as Comark's framework renderers do before passing props to a component. */\nexport function resolveCmsComarkAttributes(\n attributes: Schema.JsonObject,\n renderData: NodeRenderData,\n): CmsComarkAttributes {\n const resolved = new Map<string, CmsComarkAttributeValue>()\n\n for (const [name, value] of Object.entries(\n resolveAttributes(toMutableComarkAttributes(attributes), renderData, { parseJson: true }),\n )) {\n if (Predicate.isUndefined(value)) {\n resolved.set(name, undefined)\n continue\n }\n\n const decoded = decodeJson(value)\n\n if (Option.isNone(decoded)) throw new Error(`Comark resolved non-JSON attribute \"${name}\".`)\n resolved.set(name, decoded.value)\n }\n\n return resolved\n}\n\n/** Projects bindings to editable values while retaining enough metadata to reconstruct their authored form. */\nexport function projectCmsEditorComponentAttributes(\n attributes: Schema.JsonObject,\n renderData: NodeRenderData,\n): CmsEditorComponentProjection {\n const resolved = resolveCmsComarkAttributes(attributes, renderData)\n const props: Record<string, Schema.Json> = {}\n\n for (const [name, value] of resolved) {\n if (!Predicate.isUndefined(value)) props[name] = mutableJson(value)\n }\n\n const bindings: Record<string, Schema.Json> = {}\n\n for (const [authoredName, authoredValue] of Object.entries(attributes)) {\n if (!authoredName.startsWith(':') || authoredName.length === 1) continue\n const name = authoredName.slice(1)\n\n if (!resolved.has(name)) continue\n const literal = jsonLiteral(authoredValue)\n\n if (!Predicate.isString(authoredValue) || literal !== authoredValue) {\n bindings[name] = { kind: 'literal' }\n continue\n }\n\n const resolvedValue = resolved.get(name)\n bindings[name] = Object.assign(\n { expression: authoredValue, kind: 'expression' },\n Predicate.isUndefined(resolvedValue) ? undefined : { resolved: mutableJson(resolvedValue) },\n )\n }\n\n return { bindings, props, renderData: withCmsComarkProps(renderData, resolved) }\n}\n\n/** Reconstructs authored bindings, keeping expressions until a user replaces their resolved value. */\nexport function encodeCmsEditorComponentAttributes(\n props: Schema.JsonObject,\n bindings: Schema.JsonObject,\n): Schema.JsonObject {\n const attributes = mutableJsonObject(props)\n\n for (const [name, encodedBinding] of Object.entries(bindings)) {\n const binding = jsonObject(encodedBinding)\n const kind = binding.kind\n\n if (kind !== 'literal' && kind !== 'expression') continue\n const current = props[name]\n\n if (Predicate.isUndefined(current)) {\n const expression = binding.expression\n\n if (kind === 'expression' && Predicate.isString(expression)) attributes[`:${name}`] = expression\n continue\n }\n\n delete attributes[name]\n const expression = binding.expression\n const resolved = binding.resolved\n attributes[`:${name}`] =\n kind === 'expression' &&\n Predicate.isString(expression) &&\n Object.hasOwn(binding, 'resolved') &&\n sameJson(current, resolved)\n ? expression\n : mutableJson(current)\n }\n\n return attributes\n}\n\nexport function withCmsComarkProps(renderData: NodeRenderData, attributes: CmsComarkAttributes): NodeRenderData {\n return attributes.size > 0 ? { ...renderData, props: Object.fromEntries(attributes) } : renderData\n}\n\n/** Restores typed component bindings that Comark's block-YAML roundtrip can emit as plain attributes. */\nexport function normalizeCmsComponentBindings(\n document: CmsMarkdownDocument,\n components: ReadonlyMap<string, ComponentDefinition> | undefined,\n): CmsMarkdownDocument {\n if (!components) return document\n\n return CmsMarkdownDocumentSchema.make({\n frontmatter: document.frontmatter,\n meta: document.meta,\n nodes: document.nodes.map((node) => normalizeComponentNode(node, components)),\n })\n}\n\nexport function matchesCmsComponentPropType(\n value: CmsComarkAttributeValue,\n type: ComponentDefinition['authoring']['props'][number]['type'],\n): boolean {\n switch (type) {\n case 'object':\n return isJsonObject(value)\n case 'array':\n return Array.isArray(value)\n case 'boolean':\n return Predicate.isBoolean(value)\n case 'number':\n return Predicate.isNumber(value)\n case 'string':\n return Predicate.isString(value)\n }\n}\n\nfunction normalizeComponentNode(\n node: MarkdownNode,\n components: ReadonlyMap<string, ComponentDefinition>,\n): MarkdownNode {\n if (Predicate.isString(node) || node[0] === null) return node\n const [tag, originalAttributes, ...originalChildren] = node\n const attributes = mutableJsonObject(originalAttributes)\n const definition = components.get(tag.toLocaleLowerCase())\n\n if (definition) {\n for (const prop of definition.authoring.props) {\n if (prop.type === 'string' || `:${prop.name}` in attributes || !(prop.name in attributes)) continue\n const value = attributes[prop.name]\n\n if (Predicate.isUndefined(value)) continue\n const resolved = jsonLiteral(value)\n\n if (!matchesCmsComponentPropType(resolved, prop.type)) continue\n delete attributes[prop.name]\n attributes[`:${prop.name}`] = value\n }\n }\n\n return [tag, attributes, ...originalChildren.map((child) => normalizeComponentNode(child, components))]\n}\n\nfunction jsonLiteral(value: Schema.Json | undefined): CmsComarkAttributeValue {\n if (!Predicate.isString(value)) return value\n\n try {\n const decoded = decodeJson(JSON.parse(value))\n\n return Option.isSome(decoded) ? decoded.value : value\n } catch {\n return value\n }\n}\n\nfunction jsonObject(value: Schema.Json | undefined): Schema.JsonObject {\n return isJsonObject(value) ? value : {}\n}\n\nfunction sameJson(left: Schema.Json, right: Schema.Json | undefined): boolean {\n return !Predicate.isUndefined(right) && JSON.stringify(left) === JSON.stringify(right)\n}\n","import { createCmsComarkRenderData } from './internal/comark/document-adapter'\nimport { projectCmsEditorComponentAttributes } from './internal/comark/bindings'\nimport type { NodeRenderData } from 'comark'\nimport type { BlockAuthoring, BlockProp } from '@internal/protocol/Authoring'\nimport type { ComponentDefinition } from '@internal/protocol/Configuration'\nimport type { CmsMarkdownDocument } from '@internal/protocol/Documents'\nimport type { FormCapabilities, FormDefinition, FormField, FormStep, FormValues } from '@internal/protocol/Forms'\nimport { FORM_REVISION_MAX_BYTES, FormSteps } from '@internal/protocol/Forms'\nimport { Predicate, Result, Schema } from 'effect'\n\nexport function formStructureIssues(\n input: Schema.Json | undefined,\n capabilities: FormCapabilities,\n name: string,\n): string[] {\n const decoded = Schema.decodeUnknownResult(FormSteps)(input, { onExcessProperty: 'error' })\n\n if (Result.isFailure(decoded)) return ['Each form needs steps with a title and at least one valid question.']\n const issues: string[] = []\n const revisionBytes = new TextEncoder().encode(JSON.stringify(formRevision(name, capabilities, decoded.success)))\n\n if (revisionBytes.byteLength > FORM_REVISION_MAX_BYTES)\n issues.push('This form is too large. Reduce the number or size of questions.')\n const ids = new Set<string>()\n\n for (const step of decoded.success) {\n if (ids.has(step.id)) issues.push('Steps and questions must have unique identities.')\n ids.add(step.id)\n\n for (const field of step.fields) {\n if (ids.has(field.id)) issues.push('Steps and questions must have unique identities.')\n ids.add(field.id)\n\n if (['_form', '__proto__', 'constructor', 'prototype'].includes(field.id))\n issues.push('This question identity is reserved.')\n\n if (!capabilities.fieldTypes.includes(field.type))\n issues.push(`${field.label}: this question type is unavailable.`)\n\n for (const rule of ['required', 'minLength', 'maxLength', 'min', 'max'] as const) {\n if (field[rule] !== undefined && !capabilities.rules.includes(rule))\n issues.push(`${field.label}: ${rule} is unavailable.`)\n }\n\n const text = ['text', 'email', 'textarea'].includes(field.type)\n\n if (!text && (field.minLength !== undefined || field.maxLength !== undefined))\n issues.push(`${field.label}: length limits require a text question.`)\n\n if (field.type !== 'number' && (field.min !== undefined || field.max !== undefined))\n issues.push(`${field.label}: numeric limits require a number question.`)\n\n if (field.min !== undefined && field.max !== undefined && field.min > field.max)\n issues.push(`${field.label}: minimum exceeds maximum.`)\n\n if (field.minLength !== undefined && field.maxLength !== undefined && field.minLength > field.maxLength)\n issues.push(`${field.label}: minimum length exceeds maximum length.`)\n const options = field.options ?? []\n\n if (\n field.type === 'select' &&\n (!options.length || new Set(options.map((option) => option.id)).size !== options.length)\n )\n issues.push(`${field.label}: choices need unique identities and at least one option.`)\n\n if (field.type !== 'select' && options.length) issues.push(`${field.label}: choices require a select question.`)\n }\n }\n\n return issues\n}\n\nexport function validateFormValues(fields: ReadonlyArray<FormField>, values: FormValues): Record<string, string> {\n return Object.fromEntries(\n fields.flatMap((field) => {\n const issue = fieldIssue(field, Object.hasOwn(values, field.id) ? values[field.id] : undefined)\n\n return issue ? [[field.id, issue]] : []\n }),\n )\n}\n\nfunction fieldIssue(field: FormField, value: FormValues[string] | undefined): string | undefined {\n const empty = value === undefined || value === null || value === '' || (Predicate.isString(value) && !value.trim())\n\n if (empty) return field.required ? `${field.label} is required.` : undefined\n\n if (field.type === 'checkbox')\n return !Predicate.isBoolean(value)\n ? 'Choose yes or no.'\n : field.required && !value\n ? `${field.label} must be checked.`\n : undefined\n\n if (field.type === 'number') {\n if (!Predicate.isNumber(value) || !Number.isFinite(value)) return 'Enter a number.'\n\n if (field.min !== undefined && value < field.min) return `Enter at least ${field.min}.`\n\n if (field.max !== undefined && value > field.max) return `Enter at most ${field.max}.`\n\n return undefined\n }\n\n if (!Predicate.isString(value)) return 'Enter text.'\n\n if (field.type === 'select' && !field.options?.some((option) => option.id === value))\n return 'Choose an available option.'\n\n if (field.type === 'email' && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/u.test(value)) return 'Enter a valid email address.'\n\n if (field.minLength !== undefined && value.length < field.minLength)\n return `Enter at least ${field.minLength} characters.`\n\n if (field.maxLength !== undefined && value.length > field.maxLength)\n return `Enter at most ${field.maxLength} characters.`\n\n return undefined\n}\n\n/** Paths refer to authored nodes, never rendered Vue children. Revision comparison is exact. */\nexport function documentForms(\n document: { readonly id: FormDefinition['documentId']; readonly body: CmsMarkdownDocument },\n components: ReadonlyArray<ComponentDefinition>,\n preview = false,\n): FormDefinition[] {\n const forms: FormDefinition[] = []\n\n const visit = (nodes: CmsMarkdownDocument['nodes'], parent: number[], renderData: NodeRenderData) => {\n nodes.forEach((node, index) => {\n if (Predicate.isString(node) || node[0] === null) return\n const nodePath = [...parent, index]\n const projection = projectCmsEditorComponentAttributes(node[1], renderData)\n const capabilities = components.find((component) => component.name === node[0])?.authoring.form\n\n if (capabilities && !formStructureIssues(projection.props.steps, capabilities, node[0]).length) {\n const steps = Result.getOrThrow(Schema.decodeUnknownResult(FormSteps)(projection.props.steps))\n forms.push({\n name: node[0],\n documentId: document.id,\n nodePath,\n steps,\n preview,\n revision: formRevision(node[0], capabilities, steps),\n })\n }\n\n visit(node.slice(2).filter(isNode), nodePath, projection.renderData)\n })\n }\n\n visit(document.body.nodes, [], createCmsComarkRenderData(document.body))\n\n return forms\n}\n\nfunction formRevision(name: string, capabilities: FormCapabilities, steps: ReadonlyArray<FormStep>): string {\n return JSON.stringify([name, capabilities, steps])\n}\n\nfunction isNode(value: Schema.Json | undefined): value is CmsMarkdownDocument['nodes'][number] {\n return Predicate.isString(value) || Array.isArray(value)\n}\n\nexport function formAuthoring(capabilities: FormCapabilities): BlockAuthoring {\n const prop = (\n name: string,\n label: string,\n type: BlockProp['type'],\n input: BlockProp['input'],\n extra: Partial<BlockProp> = {},\n ): BlockProp => ({ name, label, type, input, required: false, nullable: false, options: [], ...extra })\n\n const question = [\n prop('label', 'Question', 'string', 'text', { required: true, defaultValue: 'New question' }),\n prop('type', 'Answer type', 'string', 'select', {\n required: true,\n defaultValue: capabilities.fieldTypes[0],\n options: capabilities.fieldTypes.map((value) => ({ value, label: value })),\n }),\n prop('help', 'Help text', 'string', 'textarea'),\n ...capabilities.rules.map((rule) =>\n prop(\n rule,\n {\n required: 'Required',\n minLength: 'Minimum characters',\n maxLength: 'Maximum characters',\n min: 'Minimum value',\n max: 'Maximum value',\n }[rule],\n rule === 'required' ? 'boolean' : 'number',\n rule === 'required' ? 'toggle' : 'number',\n ),\n ),\n prop('options', 'Choices', 'array', 'list', {\n fields: [prop('label', 'Choice', 'string', 'text', { required: true, defaultValue: 'New choice' })],\n }),\n ]\n\n return {\n version: 1,\n label: capabilities.label,\n group: 'Forms',\n form: capabilities,\n props: [\n prop('steps', 'Steps', 'array', 'list', {\n required: true,\n fields: [\n prop('title', 'Step title', 'string', 'text', { required: true, defaultValue: 'New step' }),\n prop('fields', 'Questions', 'array', 'list', { required: true, fields: question }),\n ],\n }),\n ],\n slots: [],\n initialProps: {\n steps: [\n {\n id: 'first-step',\n title: 'Your details',\n fields: [\n {\n id: 'first-question',\n label: 'Your answer',\n type: capabilities.fieldTypes[0] ?? 'text',\n ...(capabilities.fieldTypes[0] === 'select'\n ? { options: [{ id: 'first-choice', label: 'First choice' }] }\n : undefined),\n },\n ],\n },\n ],\n },\n }\n}\n"],"mappings":"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"}
package/src/Forms.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ import { a as FormStep, i as FormResult, n as FormDefinition, o as FormSubmission, r as FormField, s as FormValues, t as FormCapabilities } from "./Forms-BsJMev5_.js";
2
+ import { ComputedRef, MaybeRefOrGetter, Ref } from "vue";
3
+ //#region src/runtime/forms/useCmsForm.d.ts
4
+ interface UseCmsFormOptions {
5
+ /** Replace the HTTP transport, retaining validation and submission state. */
6
+ readonly submit?: (submission: FormSubmission, signal: AbortSignal) => Promise<FormResult>;
7
+ }
8
+ interface UseCmsFormReturn {
9
+ readonly fields: ComputedRef<ReadonlyArray<FormField>>;
10
+ readonly steps: ComputedRef<ReadonlyArray<FormStep>>;
11
+ readonly values: Ref<Record<string, FormValues[string]>>;
12
+ readonly errors: Readonly<Ref<Readonly<Record<string, string>>>>;
13
+ readonly currentStep: ComputedRef<FormStep | undefined>;
14
+ readonly stepIndex: Readonly<Ref<number>>;
15
+ readonly isFirstStep: ComputedRef<boolean>;
16
+ readonly isLastStep: ComputedRef<boolean>;
17
+ readonly isSubmitting: Readonly<Ref<boolean>>;
18
+ readonly isSuccess: Readonly<Ref<boolean>>;
19
+ readonly isPreview: ComputedRef<boolean>;
20
+ readonly error: Readonly<Ref<string | undefined>>;
21
+ readonly next: () => boolean;
22
+ readonly previous: () => void;
23
+ readonly validate: () => boolean;
24
+ readonly submit: () => Promise<boolean>;
25
+ readonly reset: () => void;
26
+ }
27
+ /** Headless, per-instance form state. Definition changes preserve answers for unchanged field types. */
28
+ export declare function useCmsForm(input: MaybeRefOrGetter<FormDefinition>, options?: UseCmsFormOptions): UseCmsFormReturn;
29
+ //#endregion
30
+ //#region src/Forms.d.ts
31
+ /** Register this definition under the kebab-case name of your Vue form renderer. */
32
+ export declare function defineCmsForm<const Definition extends FormCapabilities>(definition: Definition): Definition;
33
+ //#endregion
34
+ export type { FormDefinition as CmsFormDefinition, FormField as CmsFormField, FormResult as CmsFormResult, FormStep as CmsFormStep, FormValues as CmsFormValues, UseCmsFormOptions, UseCmsFormReturn };
35
+ //# sourceMappingURL=Forms.d.ts.map
package/src/Forms.js ADDED
@@ -0,0 +1,13 @@
1
+ import { validateFormCapabilities } from "./internal/form-capabilities.js";
2
+ import { useCmsForm } from "./runtime/forms/useCmsForm.js";
3
+
4
+ //#region src/Forms.ts
5
+ /** Register this definition under the kebab-case name of your Vue form renderer. */
6
+ function defineCmsForm(definition) {
7
+ validateFormCapabilities(definition);
8
+ return definition;
9
+ }
10
+
11
+ //#endregion
12
+ export { defineCmsForm, useCmsForm };
13
+ //# sourceMappingURL=Forms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Forms.js","names":[],"sources":["../../../src/Forms.ts"],"sourcesContent":["import type { FormCapabilities } from '@internal/protocol/Forms'\nimport { validateFormCapabilities } from './internal/form-capabilities'\n\nexport type {\n FormDefinition as CmsFormDefinition,\n FormField as CmsFormField,\n FormStep as CmsFormStep,\n FormValues as CmsFormValues,\n FormResult as CmsFormResult,\n} from '@internal/protocol/Forms'\n\nexport type { UseCmsFormOptions, UseCmsFormReturn } from './runtime/forms/useCmsForm'\n\nexport { useCmsForm } from './runtime/forms/useCmsForm'\n\n/** Register this definition under the kebab-case name of your Vue form renderer. */\nexport function defineCmsForm<const Definition extends FormCapabilities>(definition: Definition): Definition {\n validateFormCapabilities(definition)\n\n return definition\n}\n"],"mappings":";;;;;AAgBA,SAAgB,cAAyD,YAAoC;CAC3G,yBAAyB,UAAU;CAEnC,OAAO;AACT"}
@@ -9,9 +9,13 @@ const CMS_LIVENESS_PATH = `${STUDIO_HEALTH_PATH}/live`;
9
9
  const CMS_READINESS_PATH = `${STUDIO_HEALTH_PATH}/ready`;
10
10
  const CMS_DELIVERY_READ_PATH = `${STUDIO_API_PATH}/delivery/read`;
11
11
  const CMS_DELIVERY_QUERY_PATH = `${STUDIO_API_PATH}/delivery/query`;
12
+ const CMS_DELIVERY_SEO_PATH = `${STUDIO_API_PATH}/delivery/seo`;
13
+ const CMS_DELIVERY_SITEMAP_PATH = `${STUDIO_API_PATH}/delivery/sitemap`;
12
14
  const CMS_PREVIEW_READ_PATH = `${STUDIO_API_PATH}/preview/read`;
13
15
  const CMS_PREVIEW_QUERY_PATH = `${STUDIO_API_PATH}/preview/query`;
16
+ const CMS_PREVIEW_SEO_PATH = `${STUDIO_API_PATH}/preview/seo`;
17
+ const CMS_FORM_SUBMIT_PATH = `${STUDIO_API_PATH}/forms/submit`;
14
18
 
15
19
  //#endregion
16
- export { CMS_PREVIEW_QUERY_PATH as a, STUDIO_API_PATH as c, STUDIO_COLLABORATION_PATH as d, STUDIO_HEALTH_PATH as f, CMS_LIVENESS_PATH as i, STUDIO_APP_PATH as l, CMS_DELIVERY_QUERY_PATH as n, CMS_PREVIEW_READ_PATH as o, CMS_DELIVERY_READ_PATH as r, CMS_READINESS_PATH as s, CMS_AUTHENTICATION_PATH as t, STUDIO_BASE_PATH as u };
17
- //# sourceMappingURL=HttpPaths-BbS21Jy8.js.map
20
+ export { CMS_FORM_SUBMIT_PATH as a, CMS_PREVIEW_READ_PATH as c, STUDIO_APP_PATH as d, STUDIO_BASE_PATH as f, CMS_DELIVERY_SITEMAP_PATH as i, CMS_READINESS_PATH as l, STUDIO_HEALTH_PATH as m, CMS_DELIVERY_QUERY_PATH as n, CMS_LIVENESS_PATH as o, STUDIO_COLLABORATION_PATH as p, CMS_DELIVERY_READ_PATH as r, CMS_PREVIEW_QUERY_PATH as s, CMS_AUTHENTICATION_PATH as t, STUDIO_API_PATH as u };
21
+ //# sourceMappingURL=HttpPaths-c9nLZ9H2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HttpPaths-c9nLZ9H2.js","names":[],"sources":["../../../../protocol/src/HttpPaths.ts"],"sourcesContent":["export const STUDIO_BASE_PATH = '/_cms'\n\nexport const STUDIO_APP_PATH = `${STUDIO_BASE_PATH}/app`\n\nexport const STUDIO_API_PATH = `${STUDIO_BASE_PATH}/api`\n\nexport const STUDIO_COLLABORATION_PATH = `${STUDIO_BASE_PATH}/collaboration`\n\nexport const STUDIO_HEALTH_PATH = `${STUDIO_BASE_PATH}/health`\n\nexport const CMS_AUTHENTICATION_PATH = '/api/cms/auth'\n\nexport const CMS_LIVENESS_PATH = `${STUDIO_HEALTH_PATH}/live`\n\nexport const CMS_READINESS_PATH = `${STUDIO_HEALTH_PATH}/ready`\n\nexport const CMS_DELIVERY_READ_PATH = `${STUDIO_API_PATH}/delivery/read`\n\nexport const CMS_DELIVERY_QUERY_PATH = `${STUDIO_API_PATH}/delivery/query`\n\nexport const CMS_DELIVERY_SEO_PATH = `${STUDIO_API_PATH}/delivery/seo`\n\nexport const CMS_DELIVERY_SITEMAP_PATH = `${STUDIO_API_PATH}/delivery/sitemap`\n\nexport const CMS_PREVIEW_READ_PATH = `${STUDIO_API_PATH}/preview/read`\n\nexport const CMS_PREVIEW_QUERY_PATH = `${STUDIO_API_PATH}/preview/query`\n\nexport const CMS_PREVIEW_SEO_PATH = `${STUDIO_API_PATH}/preview/seo`\n\nexport const CMS_FORM_SUBMIT_PATH = `${STUDIO_API_PATH}/forms/submit`\n"],"mappings":";AAAA,MAAa,mBAAmB;AAEhC,MAAa,kBAAkB,GAAG,iBAAiB;AAEnD,MAAa,kBAAkB,GAAG,iBAAiB;AAEnD,MAAa,4BAA4B,GAAG,iBAAiB;AAE7D,MAAa,qBAAqB,GAAG,iBAAiB;AAEtD,MAAa,0BAA0B;AAEvC,MAAa,oBAAoB,GAAG,mBAAmB;AAEvD,MAAa,qBAAqB,GAAG,mBAAmB;AAExD,MAAa,yBAAyB,GAAG,gBAAgB;AAEzD,MAAa,0BAA0B,GAAG,gBAAgB;AAE1D,MAAa,wBAAwB,GAAG,gBAAgB;AAExD,MAAa,4BAA4B,GAAG,gBAAgB;AAE5D,MAAa,wBAAwB,GAAG,gBAAgB;AAExD,MAAa,yBAAyB,GAAG,gBAAgB;AAEzD,MAAa,uBAAuB,GAAG,gBAAgB;AAEvD,MAAa,uBAAuB,GAAG,gBAAgB"}
@@ -0,0 +1,21 @@
1
+ //#region src/I18n.d.ts
2
+ interface CmsMessages {
3
+ readonly [key: string]: string | CmsMessages;
4
+ }
5
+ interface CmsI18nOptions {
6
+ readonly defaultLocale: string;
7
+ readonly fallbackLocale?: string | null;
8
+ readonly prefixDefaultLocale?: boolean;
9
+ readonly locales: Readonly<Record<string, {
10
+ readonly name: string;
11
+ readonly messages?: CmsMessages;
12
+ }>>;
13
+ }
14
+ /** Nuxt augments this registry with the message keys from cms.config.ts. */
15
+ interface CmsI18nRegistry {}
16
+ type CmsMessageKey = CmsI18nRegistry extends {
17
+ messageKey: infer Key extends string;
18
+ } ? Key : string;
19
+ //#endregion
20
+ export { CmsMessages as i, CmsI18nRegistry as n, CmsMessageKey as r, CmsI18nOptions as t };
21
+ //# sourceMappingURL=I18n-DZK4CkJF.d.ts.map
package/src/I18n.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { i as CmsMessages, n as CmsI18nRegistry, r as CmsMessageKey, t as CmsI18nOptions } from "./I18n-DZK4CkJF.js";
2
+ export { CmsI18nOptions, CmsI18nRegistry, CmsMessageKey, CmsMessages };
package/src/I18n.js ADDED
@@ -0,0 +1 @@
1
+ export { };