@paroicms/site-generator-plugin 0.31.6 → 0.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -167,7 +167,10 @@ function fixSiteSchema(siteSchema) {
167
167
  continue;
168
168
  // Add Tiptap plugin to fields with renderAs "html"
169
169
  for (const field of nodeType.fields) {
170
- if (typeof field !== "string" && field.renderAs === "html" && field.storedAs !== "labeling") {
170
+ if (typeof field !== "string" &&
171
+ field.renderAs === "html" &&
172
+ field.storedAs !== "labeling" &&
173
+ field.storedAs !== "partField") {
171
174
  field.dataType = "json";
172
175
  field.plugin = "@paroicms/tiptap-editor-plugin";
173
176
  }
@@ -181,9 +184,29 @@ function fixSiteSchema(siteSchema) {
181
184
  ];
182
185
  }
183
186
  }
187
+ validatePartFieldReferences(nodeTypes);
184
188
  setMenuPlacementOnTaxonomies(nodeTypes);
185
189
  return siteSchema;
186
190
  }
191
+ function validatePartFieldReferences(nodeTypes) {
192
+ if (!nodeTypes)
193
+ return;
194
+ const partTypeNames = new Set(nodeTypes.filter((nt) => nt.kind === "part").map((nt) => nt.typeName));
195
+ for (const nodeType of nodeTypes) {
196
+ if (!nodeType.fields)
197
+ continue;
198
+ nodeType.fields = nodeType.fields.filter((field) => {
199
+ if (typeof field === "string")
200
+ return true;
201
+ if (field.storedAs !== "partField")
202
+ return true;
203
+ if (typeof field.partType !== "string" || !partTypeNames.has(field.partType)) {
204
+ return false;
205
+ }
206
+ return true;
207
+ });
208
+ }
209
+ }
187
210
  function setMenuPlacementOnTaxonomies(nodeTypes) {
188
211
  if (!nodeTypes)
189
212
  return;
@@ -163,6 +163,9 @@ function templateOfFields(ctx, fields, { parentKey }) {
163
163
  return fieldTemplates.join("\n");
164
164
  }
165
165
  function templateOfField(ctx, fieldOrQualifiedName, parentKey) {
166
+ if (typeof fieldOrQualifiedName !== "string" && fieldOrQualifiedName.storedAs === "partField") {
167
+ return templateOfPartField(ctx, fieldOrQualifiedName, parentKey);
168
+ }
166
169
  const { dataType, renderAs, name } = typeof fieldOrQualifiedName === "string"
167
170
  ? getPredefinedDataType(ctx, fieldOrQualifiedName)
168
171
  : fieldOrQualifiedName.storedAs === "labeling"
@@ -229,6 +232,21 @@ function templateOfField(ctx, fieldOrQualifiedName, parentKey) {
229
232
  }
230
233
  return `<div class="Field">{{ ${parentKey}.${name} }}</div>`;
231
234
  }
235
+ function templateOfPartField(ctx, field, parentKey) {
236
+ const partKey = `${parentKey}.${field.name}`;
237
+ const partType = ctx.siteSchema.nodeTypes?.find((nt) => nt.typeName === field.partType && nt.kind === "part");
238
+ if (!partType?.fields || partType.fields.length === 0) {
239
+ return `{%- comment -%} Part field: ${field.name} (no fields) {%- endcomment -%}`;
240
+ }
241
+ const innerFields = templateOfFields(ctx, partType.fields, { parentKey: `${partKey}.field` });
242
+ if (!innerFields)
243
+ return "";
244
+ return `{% if ${partKey} %}
245
+ <div class="${camelToKebabCase(field.partType)}">
246
+ ${innerFields}
247
+ </div>
248
+ {% endif %}`;
249
+ }
232
250
  function templateOfPicture({ imageKey }) {
233
251
  return `{% if ${imageKey} %}
234
252
  {% set smallIm = image(${imageKey}, resize: "360x48") %}
@@ -89,7 +89,23 @@ A labeling field lets the user assign taxonomy terms to a document (or part).
89
89
 
90
90
  Most of the time, the field name will be the same as the taxonomy type name.
91
91
 
92
- # 4. Examine the current JSON data, which conforms to the `JtSiteSchema` type
92
+ # 4. Part Field (embedding a part inline)
93
+
94
+ A part field embeds a single part directly within a document or part's field list. The referenced part type must exist in the schema's nodeTypes as a `kind: "part"` node type.
95
+
96
+ <field_type_example>
97
+ {
98
+ "name": "seo",
99
+ "storedAs": "partField",
100
+ "partType": "myPartTypeName"
101
+ }
102
+ </field_type_example>
103
+
104
+ When using a partField, the referenced part type (e.g., "myPartTypeName") must be defined as a `kind: "part"` node type in the schema. The part will be embedded inline in the document editor, not in the parts tab.
105
+
106
+ Use partField when a group of fields should logically belong together as a reusable unit (e.g., SEO metadata, social sharing settings, address blocks).
107
+
108
+ # 5. Examine the current JSON data, which conforms to the `JtSiteSchema` type
93
109
 
94
110
  <site_schema_json>
95
111
  {{siteSchemaJson}}
@@ -101,20 +117,20 @@ Also, the attached locales:
101
117
  {{l10nJson}}
102
118
  </l10n_json>
103
119
 
104
- # 5. Now, here is what to do
120
+ # 6. Now, here is what to do
105
121
 
106
122
  <user_request>
107
123
  {{taskDetailsMd}}
108
124
  </user_request>
109
125
 
110
- # 6. Guidelines
126
+ # 7. Guidelines
111
127
 
112
128
  - Don't assume how the CMS works. If you are not sure how to do something, don't do it.
113
129
  - You are allowed to be proactive, but only when the user asks you to do something.
114
130
  - Remember to adhere strictly to the TypeScript typing when making changes. If the update message requests changes that would violate the typing, then prioritize maintaining the correct structure over making those specific changes.
115
131
  - Field choice for listing pages: For new routing documents that have `regularChildren` (like blog index, products index, etc.), prefer `introduction[@paroicms/tiptap-editor-plugin]` instead of `htmlContent[@paroicms/tiptap-editor-plugin]`. These pages display a list of child items, so they only need a short introduction, not full HTML content.
116
132
 
117
- # 7. Output
133
+ # 8. Output
118
134
 
119
135
  If there is a change in the site schema, then provide the updated site schema in JSON within <updated_site_schema_json> tags. Otherwise, let this tag empty.
120
136
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paroicms/site-generator-plugin",
3
- "version": "0.31.6",
3
+ "version": "0.32.1",
4
4
  "description": "ParoiCMS Site Generator Plugin",
5
5
  "keywords": [
6
6
  "paroicms",
@@ -30,7 +30,7 @@
30
30
  "dependencies": {
31
31
  "@anthropic-ai/sdk": "~0.78.0",
32
32
  "@mistralai/mistralai": "~1.14.1",
33
- "@paroicms/script-lib": "0.3.19",
33
+ "@paroicms/script-lib": "0.3.21",
34
34
  "arktype": "~2.2.0",
35
35
  "jsonwebtoken": "~9.0.3",
36
36
  "knex": "~3.1.0",
@@ -42,9 +42,9 @@
42
42
  "@paroicms/public-server-lib": "0"
43
43
  },
44
44
  "devDependencies": {
45
- "@paroicms/internal-anywhere-lib": "1.39.0",
46
- "@paroicms/internal-server-lib": "1.24.4",
47
- "@paroicms/public-server-lib": "0.55.0",
45
+ "@paroicms/internal-anywhere-lib": "1.39.2",
46
+ "@paroicms/internal-server-lib": "1.24.6",
47
+ "@paroicms/public-server-lib": "0.56.1",
48
48
  "@types/node": "~24.11.0",
49
49
  "marked": "~17.0.4",
50
50
  "nodemon": "~3.1.14",