canopycms 0.4.0 → 0.5.0
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/CHANGELOG.md +66 -42
- package/dist/ai/generate.d.ts +3 -0
- package/dist/ai/generate.js +12 -29
- package/dist/ai/handler.js +1 -0
- package/dist/ai/types.d.ts +3 -9
- package/dist/api/reference-options.d.ts +2 -5
- package/dist/api/reference-options.js +21 -2
- package/dist/api/schema.d.ts +4 -4
- package/dist/build/generate-ai-content.js +1 -0
- package/dist/cli/cli.js +131 -38
- package/dist/cli/generate-ai-content.js +75 -32
- package/dist/cli/init.js +29 -4
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schemas/config.d.ts +74 -0
- package/dist/config/schemas/config.js +21 -0
- package/dist/config/schemas/field.d.ts +30 -0
- package/dist/config/schemas/field.js +22 -0
- package/dist/config/types.d.ts +39 -0
- package/dist/config/validation.d.ts +6 -0
- package/dist/config/validation.js +33 -0
- package/dist/editor/FormRenderer.js +15 -13
- package/dist/editor/copy.d.ts +5 -0
- package/dist/editor/copy.js +5 -0
- package/dist/editor/fields/BlockField.d.ts +2 -0
- package/dist/editor/fields/BlockField.js +15 -8
- package/dist/editor/fields/ItemList.d.ts +21 -3
- package/dist/editor/fields/ItemList.js +16 -8
- package/dist/editor/fields/NumberListField.d.ts +2 -0
- package/dist/editor/fields/NumberListField.js +6 -2
- package/dist/editor/fields/ObjectListField.js +9 -3
- package/dist/editor/fields/ReferenceField.d.ts +6 -7
- package/dist/editor/fields/ReferenceField.js +28 -122
- package/dist/editor/fields/ReferenceListField.d.ts +41 -0
- package/dist/editor/fields/ReferenceListField.js +139 -0
- package/dist/editor/fields/SelectField.d.ts +2 -0
- package/dist/editor/fields/SelectField.js +6 -3
- package/dist/editor/fields/StringListField.d.ts +10 -1
- package/dist/editor/fields/StringListField.js +18 -8
- package/dist/editor/fields/item-expansion.d.ts +7 -3
- package/dist/editor/fields/item-expansion.js +6 -4
- package/dist/editor/fields/list-item-keys.d.ts +6 -5
- package/dist/editor/fields/list-item-keys.js +45 -13
- package/dist/editor/fields/reference-noindex.d.ts +37 -0
- package/dist/editor/fields/reference-noindex.js +48 -0
- package/dist/editor/fields/use-reference-options.d.ts +36 -0
- package/dist/editor/fields/use-reference-options.js +121 -0
- package/dist/editor/form-outline.d.ts +2 -2
- package/dist/editor/form-outline.js +4 -2
- package/dist/editor/theme.js +5 -0
- package/dist/entry-schema-registry.d.ts +1 -1
- package/dist/entry-schema-registry.js +3 -2
- package/dist/entry-schema.d.ts +5 -3
- package/dist/entry-schema.js +2 -1
- package/dist/reference-resolver.d.ts +18 -1
- package/dist/reference-resolver.js +175 -8
- package/dist/schema/schema-store.d.ts +2 -2
- package/dist/static/index.d.ts +8 -4
- package/dist/static/index.js +38 -13
- package/dist/static/seo.d.ts +7 -5
- package/dist/static/seo.js +13 -6
- package/dist/validation/entry-validator.d.ts +5 -0
- package/dist/validation/entry-validator.js +12 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/static/seo.js
CHANGED
|
@@ -75,7 +75,12 @@ const asTwitterCard = (value) => {
|
|
|
75
75
|
* rather than throwing.
|
|
76
76
|
*/
|
|
77
77
|
export function extractSeoFields(entryData, opts = {}) {
|
|
78
|
-
const names = { ...DEFAULT_SEO_FIELD_NAMES
|
|
78
|
+
const names = { ...DEFAULT_SEO_FIELD_NAMES };
|
|
79
|
+
// Only a real name overrides: `{ noindex: undefined }` (an unset env var, say) keeps the default.
|
|
80
|
+
for (const [key, name] of Object.entries(opts.fields ?? {})) {
|
|
81
|
+
if (typeof name === 'string' && name !== '')
|
|
82
|
+
names[key] = name;
|
|
83
|
+
}
|
|
79
84
|
const entry = asRecord(entryData);
|
|
80
85
|
const source = opts.group ? asRecord(entry?.[opts.group]) : entry;
|
|
81
86
|
return {
|
|
@@ -89,14 +94,16 @@ export function extractSeoFields(entryData, opts = {}) {
|
|
|
89
94
|
};
|
|
90
95
|
}
|
|
91
96
|
/**
|
|
92
|
-
* THE `noindex` predicate. Every surface that
|
|
93
|
-
*
|
|
97
|
+
* THE `noindex` predicate. Every surface that reads the flag routes through this one function,
|
|
98
|
+
* with `opts` taken from `CanopyConfig.seo` (canopycms-next's free helpers take it as an
|
|
99
|
+
* argument instead), rather than re-deriving it:
|
|
94
100
|
*
|
|
95
101
|
* - the page's own `robots: { index: false }` (canopycms-next's `entryToMetadata`),
|
|
96
|
-
* - exclusion from the sitemap (canopycms-next's `generateContentSitemap`),
|
|
97
|
-
* - exclusion from AI content (`ai/generate.ts`, unless `exclude.noindex: false`)
|
|
102
|
+
* - exclusion from the sitemap (canopycms-next's `generateContentSitemap`),
|
|
103
|
+
* - exclusion from AI content (`ai/generate.ts`, unless `exclude.noindex: false`), and
|
|
104
|
+
* - the marker on a reference picker's option (`ReferenceResolver.loadReferenceOptions`).
|
|
98
105
|
*
|
|
99
|
-
*
|
|
106
|
+
* One predicate at one configured location is the point. Derived separately, a `noindex` entry
|
|
100
107
|
* stays advertised in one surface while correctly absent from another, and nothing warns.
|
|
101
108
|
*
|
|
102
109
|
* NOT applied to enumeration: `noindex` means "don't advertise this", not "don't build this".
|
|
@@ -20,6 +20,11 @@ import type { ContentFormat, EntrySchema } from '../config/index.js';
|
|
|
20
20
|
export interface EntryFieldError {
|
|
21
21
|
fieldPath: string;
|
|
22
22
|
message: string;
|
|
23
|
+
/** Set on an over-cap list's error, so a caller can say how to fix it. */
|
|
24
|
+
maxItems?: {
|
|
25
|
+
count: number;
|
|
26
|
+
cap: number;
|
|
27
|
+
};
|
|
23
28
|
}
|
|
24
29
|
/**
|
|
25
30
|
* Merge an md/mdx body string into the data record under the schema's body
|
|
@@ -173,6 +173,18 @@ export function validateEntryData(fields, data, pathPrefix = '', options = {}) {
|
|
|
173
173
|
}
|
|
174
174
|
if (value === undefined || value === null)
|
|
175
175
|
continue;
|
|
176
|
+
// No `continue`: the items inside an over-cap list are still checked and reported.
|
|
177
|
+
if (Array.isArray(value) &&
|
|
178
|
+
'maxItems' in field &&
|
|
179
|
+
typeof field.maxItems === 'number' &&
|
|
180
|
+
value.length > field.maxItems) {
|
|
181
|
+
const cap = field.maxItems;
|
|
182
|
+
errors.push({
|
|
183
|
+
fieldPath: path,
|
|
184
|
+
message: `At most ${cap} ${cap === 1 ? 'item' : 'items'}; this list has ${value.length}`,
|
|
185
|
+
maxItems: { count: value.length, cap },
|
|
186
|
+
});
|
|
187
|
+
}
|
|
176
188
|
if (field.type === 'block') {
|
|
177
189
|
const blockField = field;
|
|
178
190
|
if (!Array.isArray(value)) {
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CANOPYCMS_VERSION = "0.
|
|
1
|
+
export declare const CANOPYCMS_VERSION = "0.5.0";
|
package/dist/version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// Generated by scripts/bump-version.mjs, its only writer. The package builds with plain
|
|
2
2
|
// tsc (rootDir: src), so src/ cannot import ../package.json; version.test.ts keeps the two equal.
|
|
3
|
-
export const CANOPYCMS_VERSION = '0.
|
|
3
|
+
export const CANOPYCMS_VERSION = '0.5.0';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"//": "@codemirror/language, @lezer/highlight: workaround — @mdxeditor/editor uses cm6-theme-basic-light which peer-requires these but mdxeditor doesn't declare them as dependencies",
|
|
3
3
|
"name": "canopycms",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"description": "CanopyCMS core package: schema-driven content, branch-aware editing, and editor UI for Next.js.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|