@bettercms-ai/types 1.39.0 → 1.41.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/dist/index.d.ts +266 -34
- package/dist/index.js +152 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -377,7 +377,8 @@ function splitButtonStyle(style) {
|
|
|
377
377
|
paint: Object.keys(paint).length ? paint : void 0
|
|
378
378
|
};
|
|
379
379
|
}
|
|
380
|
-
var FIELD_STYLE_KEYS = ["contentWidth", "contentAlign", "marginTop", "marginBottom", "align", "fontSize", "weight"];
|
|
380
|
+
var FIELD_STYLE_KEYS = ["contentWidth", "contentAlign", "marginTop", "marginBottom", "align", "fontSize", "weight", "size"];
|
|
381
|
+
var FIELD_SIZE_ZOOM = { sm: "0.875", lg: "1.125" };
|
|
381
382
|
var FIELD_KEY_SET = new Set(FIELD_STYLE_KEYS);
|
|
382
383
|
function pickFieldStyle(style) {
|
|
383
384
|
const out = {};
|
|
@@ -389,6 +390,8 @@ function fieldStyleToCss(style) {
|
|
|
389
390
|
const picked = pickFieldStyle(style);
|
|
390
391
|
const css = { ...blockStyleToCss(picked) };
|
|
391
392
|
Object.assign(css, blockStyleToColumnCss(picked));
|
|
393
|
+
const zoom = own(FIELD_SIZE_ZOOM, picked.size);
|
|
394
|
+
if (zoom) css.zoom = zoom;
|
|
392
395
|
return Object.keys(css).length ? css : void 0;
|
|
393
396
|
}
|
|
394
397
|
function blockStyleToColumnCss(style) {
|
|
@@ -424,7 +427,27 @@ var COMPONENT_PROP_TYPES = [
|
|
|
424
427
|
"color",
|
|
425
428
|
"file",
|
|
426
429
|
"icon",
|
|
427
|
-
"multiselect"
|
|
430
|
+
"multiselect",
|
|
431
|
+
// V2 schema language (F1.x). `object` is ONE nested value of named `config.fields`, stored as
|
|
432
|
+
// `{ [childKey]: value }` like the model field `object`; the six after it store what the
|
|
433
|
+
// same-named content-model FIELD stores (`location` is the V2 geopoint) and are judged by
|
|
434
|
+
// that field's validator.
|
|
435
|
+
"object",
|
|
436
|
+
"datetime",
|
|
437
|
+
"slug",
|
|
438
|
+
"email",
|
|
439
|
+
"phone",
|
|
440
|
+
"json",
|
|
441
|
+
"location",
|
|
442
|
+
// V2 leaves, each storing what the same-named content-model FIELD stores: a taxonomy string[],
|
|
443
|
+
// a rating number, a code value (`{ language?, code }` or a string).
|
|
444
|
+
"tags",
|
|
445
|
+
"rating",
|
|
446
|
+
"code",
|
|
447
|
+
// CMS items, as the same-named content-model FIELDS store them: an entry id (or a polymorphic
|
|
448
|
+
// `{ entryId, modelSlug }`), and a list of them. Delivery hydrates them like an entry's.
|
|
449
|
+
"reference",
|
|
450
|
+
"multi-reference"
|
|
428
451
|
];
|
|
429
452
|
var SLOT_MAX_ITEMS = 12;
|
|
430
453
|
var SLOT_ITEMS_CAP = 50;
|
|
@@ -2685,7 +2708,7 @@ function listItems(f) {
|
|
|
2685
2708
|
}
|
|
2686
2709
|
function zoneFields(f) {
|
|
2687
2710
|
const c = f.config ?? {};
|
|
2688
|
-
if (f.type === "group") return c.fields ?? f.fields ?? [];
|
|
2711
|
+
if (f.type === "group" || f.type === "object") return c.fields ?? f.fields ?? [];
|
|
2689
2712
|
if (f.type === "array" && c.zones?.nonRepeatable) return c.zones.nonRepeatable;
|
|
2690
2713
|
return void 0;
|
|
2691
2714
|
}
|
|
@@ -2924,12 +2947,101 @@ function buttonLinkPairs(candidates) {
|
|
|
2924
2947
|
|
|
2925
2948
|
// src/button-look.ts
|
|
2926
2949
|
import { ICON_MARKUP, iconSvg } from "@bettercms-ai/icons/markup";
|
|
2950
|
+
|
|
2951
|
+
// src/link-value.ts
|
|
2952
|
+
var LINK_RELS = ["nofollow", "sponsored", "ugc"];
|
|
2953
|
+
var LINK_VALUE_TYPES = ["url", "page", "entry", "email", "phone", "anchor", "section", "file"];
|
|
2954
|
+
var isPlainObject = (v) => !!v && typeof v === "object" && !Array.isArray(v);
|
|
2955
|
+
function isLinkObject(value) {
|
|
2956
|
+
return isPlainObject(value) && typeof value.href === "string";
|
|
2957
|
+
}
|
|
2958
|
+
function linkHref(value) {
|
|
2959
|
+
if (typeof value === "string") return value;
|
|
2960
|
+
return isLinkObject(value) ? value.href : null;
|
|
2961
|
+
}
|
|
2962
|
+
function linkRefOf(value) {
|
|
2963
|
+
if (!isLinkObject(value) || value.type !== "page" && value.type !== "entry") return null;
|
|
2964
|
+
const id = value.ref ?? (value.type === "page" ? value.pageId : value.entryId);
|
|
2965
|
+
return typeof id === "string" && id.length > 0 ? { kind: value.type, id } : null;
|
|
2966
|
+
}
|
|
2967
|
+
var isScriptHref = (href) => /^(javascript|data|vbscript):/i.test(href.replace(/[\u0000- \u007F]/g, ""));
|
|
2968
|
+
var newTabOf = (v) => v.newTab === true || v.newTab === void 0 && v.target === "_blank";
|
|
2969
|
+
function linkValueProblem(value) {
|
|
2970
|
+
if (!isPlainObject(value)) return "link_value_invalid: must be an href string or a link object { type, href, \u2026 }";
|
|
2971
|
+
const v = value;
|
|
2972
|
+
if (typeof v.href !== "string") return "link_value_invalid: needs an href string";
|
|
2973
|
+
if (isScriptHref(v.href)) return "link_value_invalid: script links (javascript:, data:, vbscript:) aren't allowed";
|
|
2974
|
+
if (v.type !== void 0 && !LINK_VALUE_TYPES.includes(v.type)) {
|
|
2975
|
+
return `link_value_invalid: unknown type "${String(v.type)}" (${LINK_VALUE_TYPES.join(", ")})`;
|
|
2976
|
+
}
|
|
2977
|
+
for (const key of ["title", "section", "ref"]) {
|
|
2978
|
+
if (v[key] !== void 0 && typeof v[key] !== "string") return `link_value_invalid: ${key} must be a string`;
|
|
2979
|
+
}
|
|
2980
|
+
if (v.ref !== void 0 && v.type !== "page" && v.type !== "entry") return "link_value_invalid: ref is the target of a page or entry link";
|
|
2981
|
+
if (v.newTab !== void 0 && typeof v.newTab !== "boolean") return "link_value_invalid: newTab must be true or false";
|
|
2982
|
+
if (v.target !== void 0 && v.target !== "_self" && v.target !== "_blank") return 'link_value_invalid: target must be "_self" or "_blank"';
|
|
2983
|
+
if (typeof v.newTab === "boolean" && v.target !== void 0 && v.newTab !== (v.target === "_blank")) {
|
|
2984
|
+
return "link_value_invalid: newTab and target disagree";
|
|
2985
|
+
}
|
|
2986
|
+
if (v.rel !== void 0 && !LINK_RELS.includes(v.rel)) {
|
|
2987
|
+
return `link_value_invalid: unknown rel "${String(v.rel)}" (nofollow, sponsored or ugc)`;
|
|
2988
|
+
}
|
|
2989
|
+
return null;
|
|
2990
|
+
}
|
|
2991
|
+
function normalizeLinkValue(value) {
|
|
2992
|
+
if (!isLinkObject(value)) return value;
|
|
2993
|
+
const out = { ...value };
|
|
2994
|
+
delete out.resolved;
|
|
2995
|
+
if (out.rel === "follow") delete out.rel;
|
|
2996
|
+
if (out.newTab === void 0 && out.target !== void 0) out.newTab = out.target === "_blank";
|
|
2997
|
+
const ref = linkRefOf(out);
|
|
2998
|
+
if (ref && out.ref === void 0) out.ref = ref.id;
|
|
2999
|
+
return out;
|
|
3000
|
+
}
|
|
3001
|
+
function linkAnchorOf(value) {
|
|
3002
|
+
if (typeof value === "string") return { href: value, newTab: false };
|
|
3003
|
+
if (!isLinkObject(value)) return null;
|
|
3004
|
+
return {
|
|
3005
|
+
href: value.href,
|
|
3006
|
+
newTab: newTabOf(value),
|
|
3007
|
+
...LINK_RELS.includes(value.rel) ? { rel: value.rel } : {}
|
|
3008
|
+
};
|
|
3009
|
+
}
|
|
3010
|
+
|
|
3011
|
+
// src/button-look.ts
|
|
2927
3012
|
var BUTTON_VARIANTS = ["primary", "secondary", "tertiary", "brand", "dark", "light", "outline", "link"];
|
|
2928
3013
|
var BUTTON_ICONS = ICON_MARKUP;
|
|
2929
3014
|
var BUTTON_ICON_NAMES = DOCK_ICON_NAMES;
|
|
2930
3015
|
function buttonVariantOf(value) {
|
|
2931
3016
|
return BUTTON_VARIANTS.includes(value) ? value : "primary";
|
|
2932
3017
|
}
|
|
3018
|
+
var SITE_CLASS = /^[^\s"'<>`=]{1,64}$/;
|
|
3019
|
+
var LOOK_VALUE = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
3020
|
+
function buttonSiteLookOf(value) {
|
|
3021
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
3022
|
+
const v = value;
|
|
3023
|
+
const tokens = (list) => Array.isArray(list) ? list.filter((c) => typeof c === "string" && SITE_CLASS.test(c)) : [];
|
|
3024
|
+
const variant = v.attrs?.["data-variant"];
|
|
3025
|
+
const classes = tokens(v.classes);
|
|
3026
|
+
const also = tokens(v.also);
|
|
3027
|
+
const size = tokens(v.size);
|
|
3028
|
+
const sizeAlso = tokens(v.sizeAlso);
|
|
3029
|
+
const attrs = typeof variant === "string" && LOOK_VALUE.test(variant) ? { "data-variant": variant } : void 0;
|
|
3030
|
+
if (classes.length === 0 && !attrs) return null;
|
|
3031
|
+
return {
|
|
3032
|
+
classes,
|
|
3033
|
+
...attrs ? { attrs } : {},
|
|
3034
|
+
...also.length ? { also } : {},
|
|
3035
|
+
...size.length ? { size } : {},
|
|
3036
|
+
...sizeAlso.length ? { sizeAlso } : {}
|
|
3037
|
+
};
|
|
3038
|
+
}
|
|
3039
|
+
function buttonLookValue(slug, siteLook) {
|
|
3040
|
+
return siteLook?.attrs?.["data-variant"] ?? slug;
|
|
3041
|
+
}
|
|
3042
|
+
function isButtonLookValue(value) {
|
|
3043
|
+
return typeof value === "string" && LOOK_VALUE.test(value);
|
|
3044
|
+
}
|
|
2933
3045
|
function buttonIconOf(value) {
|
|
2934
3046
|
return typeof value === "string" && DOCK_ICON_NAME_SET.has(value) ? value : null;
|
|
2935
3047
|
}
|
|
@@ -2937,14 +3049,15 @@ function buttonIconSvg(name, cls) {
|
|
|
2937
3049
|
return iconSvg(name, cls);
|
|
2938
3050
|
}
|
|
2939
3051
|
var BUTTON_SIZES = ["sm", "md", "lg"];
|
|
2940
|
-
var LINK_RELS = ["nofollow", "sponsored", "ugc"];
|
|
2941
3052
|
function anchorTargetRel(newTab, rel) {
|
|
2942
3053
|
const tokens = [...newTab ? ["noopener", "noreferrer"] : [], ...LINK_RELS.includes(rel) ? [rel] : []];
|
|
2943
3054
|
return `${newTab ? ' target="_blank"' : ""}${tokens.length ? ` rel="${tokens.join(" ")}"` : ""}`;
|
|
2944
3055
|
}
|
|
2945
|
-
var hrefOf =
|
|
3056
|
+
var hrefOf = linkHref;
|
|
2946
3057
|
function readButtonValue(value) {
|
|
2947
3058
|
const v = value && typeof value === "object" ? value : {};
|
|
3059
|
+
const link = isLinkObject(v.href) ? linkAnchorOf(v.href) : null;
|
|
3060
|
+
const rel = v.rel ?? link?.rel;
|
|
2948
3061
|
return {
|
|
2949
3062
|
label: typeof v.label === "string" ? v.label : "",
|
|
2950
3063
|
href: hrefOf(v.href) ?? "",
|
|
@@ -2952,16 +3065,22 @@ function readButtonValue(value) {
|
|
|
2952
3065
|
size: BUTTON_SIZES.includes(v.size) ? v.size : "md",
|
|
2953
3066
|
arrow: v.arrow === true,
|
|
2954
3067
|
icon: buttonIconOf(v.icon),
|
|
2955
|
-
newTab: v.newTab === true,
|
|
2956
|
-
...LINK_RELS.includes(
|
|
3068
|
+
newTab: v.newTab === void 0 ? link?.newTab === true : v.newTab === true,
|
|
3069
|
+
...LINK_RELS.includes(rel) ? { rel } : {}
|
|
2957
3070
|
};
|
|
2958
3071
|
}
|
|
2959
|
-
function buttonValueProblem(value) {
|
|
3072
|
+
function buttonValueProblem(value, looks) {
|
|
2960
3073
|
if (!value || typeof value !== "object" || Array.isArray(value)) return "must be a { label, href } button";
|
|
2961
3074
|
const v = value;
|
|
2962
3075
|
if (typeof v.label !== "string") return "needs a label";
|
|
2963
3076
|
if (hrefOf(v.href) === null) return "needs an href";
|
|
2964
|
-
if (
|
|
3077
|
+
if (isLinkObject(v.href)) {
|
|
3078
|
+
const problem = linkValueProblem(v.href);
|
|
3079
|
+
if (problem) return `href ${problem}`;
|
|
3080
|
+
}
|
|
3081
|
+
if (v.variant !== void 0 && !BUTTON_VARIANTS.includes(v.variant) && !(typeof v.variant === "string" && looks?.has(v.variant))) {
|
|
3082
|
+
return `has an unknown variant "${String(v.variant)}"${looks?.size ? ` (this project's looks: ${[...looks].join(", ")})` : ""}`;
|
|
3083
|
+
}
|
|
2965
3084
|
if (v.size !== void 0 && !BUTTON_SIZES.includes(v.size)) return `has an unknown size "${String(v.size)}"`;
|
|
2966
3085
|
if (v.arrow !== void 0 && typeof v.arrow !== "boolean") return "arrow must be true or false";
|
|
2967
3086
|
if (v.newTab !== void 0 && typeof v.newTab !== "boolean") return "newTab must be true or false";
|
|
@@ -2976,7 +3095,14 @@ function buttonBlockProps(value) {
|
|
|
2976
3095
|
const out = {};
|
|
2977
3096
|
if (typeof v.label === "string") out.text = v.label;
|
|
2978
3097
|
const href = hrefOf(v.href);
|
|
2979
|
-
|
|
3098
|
+
const script = href !== null && isScriptHref(href);
|
|
3099
|
+
if (href !== null) out.href = script ? "#" : href;
|
|
3100
|
+
if (isLinkObject(v.href) && !script) {
|
|
3101
|
+
const link = linkAnchorOf(v.href);
|
|
3102
|
+
out.newTab = link.newTab;
|
|
3103
|
+
out.rel = link.rel;
|
|
3104
|
+
}
|
|
3105
|
+
if (v.rel !== void 0) out.rel = v.rel;
|
|
2980
3106
|
for (const key of BUTTON_LOOK_KEYS) if (key in v) out[key] = v[key];
|
|
2981
3107
|
return out;
|
|
2982
3108
|
}
|
|
@@ -3029,6 +3155,9 @@ function buttonValueOfInstance(def, overrides) {
|
|
|
3029
3155
|
return readButtonValue({ ...props, label: props.text });
|
|
3030
3156
|
}
|
|
3031
3157
|
|
|
3158
|
+
// src/content-model.ts
|
|
3159
|
+
var OPTION_DESCRIPTION_MAX = 140;
|
|
3160
|
+
|
|
3032
3161
|
// src/locator.ts
|
|
3033
3162
|
var LANDMARK_SELECTOR = "header,nav,footer";
|
|
3034
3163
|
var LANDMARK_TAGS = /* @__PURE__ */ new Set(["HEADER", "NAV", "FOOTER"]);
|
|
@@ -3103,14 +3232,17 @@ export {
|
|
|
3103
3232
|
DOCK_BUDGET,
|
|
3104
3233
|
DOCK_ICON_NAMES,
|
|
3105
3234
|
DOCK_ICON_NAME_SET,
|
|
3235
|
+
FIELD_SIZE_ZOOM,
|
|
3106
3236
|
FIELD_STYLE_KEYS,
|
|
3107
3237
|
FOOTER_SECTION_ID,
|
|
3108
3238
|
LANDMARK_SELECTOR,
|
|
3109
3239
|
LAYOUT_SECTION_ICONS,
|
|
3110
3240
|
LAYOUT_SECTION_ICON_SET,
|
|
3111
3241
|
LINK_RELS,
|
|
3242
|
+
LINK_VALUE_TYPES,
|
|
3112
3243
|
MAIN_SELECTOR,
|
|
3113
3244
|
NAVIGATION_SECTION_ID,
|
|
3245
|
+
OPTION_DESCRIPTION_MAX,
|
|
3114
3246
|
PAGE_CONTENT_ANCHOR_ID,
|
|
3115
3247
|
RESPONSIVE_CSS,
|
|
3116
3248
|
SECTION_DOCTRINE,
|
|
@@ -3127,6 +3259,8 @@ export {
|
|
|
3127
3259
|
buttonIconOf,
|
|
3128
3260
|
buttonIconSvg,
|
|
3129
3261
|
buttonLinkPairs,
|
|
3262
|
+
buttonLookValue,
|
|
3263
|
+
buttonSiteLookOf,
|
|
3130
3264
|
buttonValueOfInstance,
|
|
3131
3265
|
buttonValueProblem,
|
|
3132
3266
|
buttonVariantOf,
|
|
@@ -3145,10 +3279,18 @@ export {
|
|
|
3145
3279
|
hideOnAttr,
|
|
3146
3280
|
inWindow,
|
|
3147
3281
|
isBlock,
|
|
3282
|
+
isButtonLookValue,
|
|
3148
3283
|
isChromeLandmark,
|
|
3284
|
+
isLinkObject,
|
|
3285
|
+
isScriptHref,
|
|
3149
3286
|
keyWords,
|
|
3150
3287
|
landmarkRegions,
|
|
3288
|
+
linkAnchorOf,
|
|
3289
|
+
linkHref,
|
|
3290
|
+
linkRefOf,
|
|
3291
|
+
linkValueProblem,
|
|
3151
3292
|
locatorFor,
|
|
3293
|
+
normalizeLinkValue,
|
|
3152
3294
|
normalizeWindow,
|
|
3153
3295
|
parsePropsAttribute,
|
|
3154
3296
|
pickFieldStyle,
|