@vectoriox/iox-ui 5.67.0 → 5.69.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/fesm2022/vectoriox-iox-ui-generation-core.mjs +149 -24
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-seo-core.mjs +2 -2
- package/fesm2022/vectoriox-iox-ui-seo-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui.mjs +2 -2
- package/fesm2022/vectoriox-iox-ui.mjs.map +1 -1
- package/generation-core/index.d.ts +44 -6
- package/package.json +1 -1
- package/src/generation-core/compose-site.ts +23 -4
- package/src/generation-core/plan-wire.ts +22 -12
- package/src/generation-core/plan-words.ts +3 -1
- package/src/generation-core/site-plan.model.ts +35 -0
- package/src/generation-core/site-spec.generated.ts +5 -4
- package/src/generation-core/stock-photos.ts +37 -0
- package/src/generation-core/validate-site-plan.ts +17 -3
- package/src/seo-core/schema.ts +2 -2
|
@@ -75,6 +75,7 @@ const SPEC_SITE_PLAN_SHAPE = {
|
|
|
75
75
|
"count": "integer ≥ 0",
|
|
76
76
|
"sample": "boolean — items are flagged isSample",
|
|
77
77
|
"isPublished": "boolean",
|
|
78
|
+
"perItem?": "per field, one string per sample: real content that wins over the template",
|
|
78
79
|
"[field]?": "the field's value — strings are templates: {n} = the item's 1-based number, {sampleImage:n} / {sampleImage:n+k} = a bundled sample image"
|
|
79
80
|
},
|
|
80
81
|
"cmsDataSource": {
|
|
@@ -4244,12 +4245,12 @@ const SPEC_SITE_TEMPLATES = {
|
|
|
4244
4245
|
{
|
|
4245
4246
|
"name": "cover",
|
|
4246
4247
|
"type": "string",
|
|
4247
|
-
"controller": "
|
|
4248
|
+
"controller": "media"
|
|
4248
4249
|
},
|
|
4249
4250
|
{
|
|
4250
4251
|
"name": "gallery",
|
|
4251
4252
|
"type": "array",
|
|
4252
|
-
"controller": "
|
|
4253
|
+
"controller": "gallery"
|
|
4253
4254
|
},
|
|
4254
4255
|
{
|
|
4255
4256
|
"name": "year",
|
|
@@ -4462,7 +4463,7 @@ const SPEC_SITE_TEMPLATES = {
|
|
|
4462
4463
|
{
|
|
4463
4464
|
"name": "photo",
|
|
4464
4465
|
"type": "string",
|
|
4465
|
-
"controller": "
|
|
4466
|
+
"controller": "media"
|
|
4466
4467
|
},
|
|
4467
4468
|
{
|
|
4468
4469
|
"name": "price",
|
|
@@ -4698,7 +4699,7 @@ const SPEC_SITE_TEMPLATES = {
|
|
|
4698
4699
|
{
|
|
4699
4700
|
"name": "photo",
|
|
4700
4701
|
"type": "string",
|
|
4701
|
-
"controller": "
|
|
4702
|
+
"controller": "media"
|
|
4702
4703
|
}
|
|
4703
4704
|
],
|
|
4704
4705
|
"seed": {
|
|
@@ -10259,6 +10260,38 @@ var SitePlanSourceKind;
|
|
|
10259
10260
|
const FACT_KEYS = Object.keys(SPEC_SITE_FACTS);
|
|
10260
10261
|
/** The label a missing fact shows, verbatim from the contract. */
|
|
10261
10262
|
const SITE_FACT_LABELS = SPEC_SITE_FACTS;
|
|
10263
|
+
/** How a content field is edited: the closed list a plan chooses from. */
|
|
10264
|
+
var ContentFieldControl;
|
|
10265
|
+
(function (ContentFieldControl) {
|
|
10266
|
+
ContentFieldControl["Text"] = "text";
|
|
10267
|
+
ContentFieldControl["Textarea"] = "textarea";
|
|
10268
|
+
/** One picture. `image` is the deprecated name of this control. */
|
|
10269
|
+
ContentFieldControl["Media"] = "media";
|
|
10270
|
+
/** A list of pictures. */
|
|
10271
|
+
ContentFieldControl["Gallery"] = "gallery";
|
|
10272
|
+
/** A list of words. */
|
|
10273
|
+
ContentFieldControl["List"] = "list";
|
|
10274
|
+
ContentFieldControl["Number"] = "number";
|
|
10275
|
+
ContentFieldControl["Switch"] = "switch";
|
|
10276
|
+
})(ContentFieldControl || (ContentFieldControl = {}));
|
|
10277
|
+
/** How a field is stored. The schema editor's and the item editor's own list: anything else renders no input. */
|
|
10278
|
+
var ContentFieldType;
|
|
10279
|
+
(function (ContentFieldType) {
|
|
10280
|
+
ContentFieldType["String"] = "string";
|
|
10281
|
+
ContentFieldType["Number"] = "number";
|
|
10282
|
+
ContentFieldType["Boolean"] = "boolean";
|
|
10283
|
+
ContentFieldType["Array"] = "array";
|
|
10284
|
+
})(ContentFieldType || (ContentFieldType = {}));
|
|
10285
|
+
/** ONE rule: how a field is stored follows from how it is edited, so a plan never has to say. */
|
|
10286
|
+
const FIELD_TYPE_OF_CONTROL = {
|
|
10287
|
+
[ContentFieldControl.Text]: ContentFieldType.String,
|
|
10288
|
+
[ContentFieldControl.Textarea]: ContentFieldType.String,
|
|
10289
|
+
[ContentFieldControl.Media]: ContentFieldType.String,
|
|
10290
|
+
[ContentFieldControl.Gallery]: ContentFieldType.Array,
|
|
10291
|
+
[ContentFieldControl.List]: ContentFieldType.Array,
|
|
10292
|
+
[ContentFieldControl.Number]: ContentFieldType.Number,
|
|
10293
|
+
[ContentFieldControl.Switch]: ContentFieldType.Boolean,
|
|
10294
|
+
};
|
|
10262
10295
|
/** The part a field plays (contract `site.roles`, AI plan L0-3): what a pattern binds instead of a field name, so one
|
|
10263
10296
|
* card grid shows projects, services or a menu. `title` is required on every type. */
|
|
10264
10297
|
var ContentRole;
|
|
@@ -10855,6 +10888,7 @@ const ROLE_KEYS$1 = shapeKeys(SHAPE['roles']);
|
|
|
10855
10888
|
const PAGE_SEO_KEYS = shapeKeys(SHAPE['pageSeo']);
|
|
10856
10889
|
const ARRAY_TYPE = 'array';
|
|
10857
10890
|
const FIELD_KEYS = shapeKeys(SHAPE['field']);
|
|
10891
|
+
const SLUG_FIELD = 'slug';
|
|
10858
10892
|
const SEED_FIXED_KEYS = shapeKeys(SHAPE['seed']);
|
|
10859
10893
|
const CMS_SOURCE_KEYS = shapeKeys(SHAPE['cmsDataSource']);
|
|
10860
10894
|
const RELATIVE_SOURCE_KEYS = shapeKeys(SHAPE['relativeDataSource']);
|
|
@@ -10969,8 +11003,13 @@ function validateContentTypes(c, list) {
|
|
|
10969
11003
|
return null;
|
|
10970
11004
|
}
|
|
10971
11005
|
c.keys(f, FIELD_KEYS, fp);
|
|
10972
|
-
c.string(f, '
|
|
10973
|
-
c.string(f, '
|
|
11006
|
+
const control = c.string(f, 'controller', fp);
|
|
11007
|
+
const stored = c.string(f, 'type', fp);
|
|
11008
|
+
const expected = control ? FIELD_TYPE_OF_CONTROL[control] : undefined;
|
|
11009
|
+
if (control && !expected)
|
|
11010
|
+
c.add(SitePlanIssueCode.Shape, `${fp}.controller`, `"${control}" is not a field control (${Object.values(ContentFieldControl).join(', ')})`);
|
|
11011
|
+
if (expected && stored && stored !== expected)
|
|
11012
|
+
c.add(SitePlanIssueCode.Shape, `${fp}.type`, `a ${control} field is stored as ${expected}, not "${stored}"`);
|
|
10974
11013
|
c.boolean(f, 'required', fp);
|
|
10975
11014
|
return c.string(f, 'name', fp);
|
|
10976
11015
|
});
|
|
@@ -10988,6 +11027,21 @@ function validateContentTypes(c, list) {
|
|
|
10988
11027
|
for (const key of ['sample', 'isPublished'])
|
|
10989
11028
|
if (typeof seed[key] !== 'boolean')
|
|
10990
11029
|
c.add(SitePlanIssueCode.Shape, `${path}.seed.${key}`, 'must be a boolean');
|
|
11030
|
+
const perItem = seed['perItem'];
|
|
11031
|
+
if (perItem !== undefined) {
|
|
11032
|
+
if (!isPlainObject(perItem))
|
|
11033
|
+
c.add(SitePlanIssueCode.Shape, `${path}.seed.perItem`, 'must be an object');
|
|
11034
|
+
else
|
|
11035
|
+
for (const [field, list] of Object.entries(perItem)) {
|
|
11036
|
+
const at = `${path}.seed.perItem.${field}`;
|
|
11037
|
+
if (!fieldSet.has(field))
|
|
11038
|
+
c.add(SitePlanIssueCode.UnknownField, at, `"${field}" is not a field of ${name}`);
|
|
11039
|
+
else if (!Array.isArray(list) || list.length !== seed['count'] || list.some(v => typeof v !== 'string'))
|
|
11040
|
+
c.add(SitePlanIssueCode.Shape, at, `must be ${String(seed['count'])} strings, one per sample`);
|
|
11041
|
+
else if (field === SLUG_FIELD && new Set(list).size !== list.length)
|
|
11042
|
+
c.add(SitePlanIssueCode.Shape, at, 'each sample needs its own slug');
|
|
11043
|
+
}
|
|
11044
|
+
}
|
|
10991
11045
|
for (const key of Object.keys(seed)) {
|
|
10992
11046
|
if (!SEED_FIXED_KEYS.includes(key) && !fieldSet.has(key))
|
|
10993
11047
|
c.add(SitePlanIssueCode.UnknownField, `${path}.seed.${key}`, `"${key}" is not a field of ${name}`);
|
|
@@ -13002,16 +13056,33 @@ function expandSeedValue(value, n) {
|
|
|
13002
13056
|
.replace(ITEM_NUMBER, String(n))
|
|
13003
13057
|
.replace(SAMPLE_IMAGE_TEMPLATE, (_m, plus) => sampleImageRef(n + (plus ? Number(plus) : 0)));
|
|
13004
13058
|
}
|
|
13005
|
-
|
|
13059
|
+
/** An AI plan's sample always has something to edit: a field it left empty gets a marked placeholder, never an invented fact. A template's blanks are deliberate. */
|
|
13060
|
+
function defaultSeed(type, field) {
|
|
13061
|
+
const word = field.name.replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/[_-]+/g, ' ').toLowerCase();
|
|
13062
|
+
const defaults = {
|
|
13063
|
+
[ContentFieldControl.Text]: word === 'slug' ? `sample-${type.name}-{n}`.toLowerCase() : `Sample ${word} {n}`,
|
|
13064
|
+
[ContentFieldControl.Textarea]: `Sample ${word}: two lines the studio replaces.`,
|
|
13065
|
+
[ContentFieldControl.Media]: '{sampleImage:n}',
|
|
13066
|
+
[ContentFieldControl.Gallery]: ['{sampleImage:n}', '{sampleImage:n+1}', '{sampleImage:n+2}'],
|
|
13067
|
+
[ContentFieldControl.List]: [`Sample ${word} {n}`],
|
|
13068
|
+
};
|
|
13069
|
+
return defaults[field.controller];
|
|
13070
|
+
}
|
|
13071
|
+
function composeItems(type, fillEmpty) {
|
|
13006
13072
|
const seed = type.seed;
|
|
13007
13073
|
if (!seed)
|
|
13008
13074
|
return [];
|
|
13009
13075
|
const items = [];
|
|
13010
13076
|
for (let n = 1; n <= seed.count; n++) {
|
|
13011
13077
|
const item = {};
|
|
13012
|
-
for (const field of type.fields)
|
|
13013
|
-
|
|
13014
|
-
|
|
13078
|
+
for (const field of type.fields) {
|
|
13079
|
+
const given = seed[field.name];
|
|
13080
|
+
const empty = !(field.name in seed) || given === '' || (Array.isArray(given) && !given.length);
|
|
13081
|
+
const own = seed.perItem?.[field.name]?.[n - 1];
|
|
13082
|
+
const value = own || (empty && fillEmpty ? defaultSeed(type, field) : given);
|
|
13083
|
+
if (value !== undefined)
|
|
13084
|
+
item[field.name] = expandSeedValue(value, n);
|
|
13085
|
+
}
|
|
13015
13086
|
items.push({ ...item, isPublished: seed.isPublished, isSample: seed.sample });
|
|
13016
13087
|
}
|
|
13017
13088
|
return items;
|
|
@@ -13071,7 +13142,7 @@ function composeSite(plan, context) {
|
|
|
13071
13142
|
business: clone$1(plan.business),
|
|
13072
13143
|
design,
|
|
13073
13144
|
schemas: clone$1(plan.contentTypes),
|
|
13074
|
-
items: Object.fromEntries(plan.contentTypes.map(t => [t.name, composeItems(t)])),
|
|
13145
|
+
items: Object.fromEntries(plan.contentTypes.map(t => [t.name, composeItems(t, plan.source.kind === SitePlanSourceKind.Ai)])),
|
|
13075
13146
|
dataSources: plan.dataSources.map(composeDataSource),
|
|
13076
13147
|
pages,
|
|
13077
13148
|
globals,
|
|
@@ -13603,8 +13674,7 @@ const WIRE_KEYS = {
|
|
|
13603
13674
|
},
|
|
13604
13675
|
field: {
|
|
13605
13676
|
name: key('field.name'),
|
|
13606
|
-
|
|
13607
|
-
controller: key('field.controller'),
|
|
13677
|
+
controller: { refs: ['field.controller'], text: `one of ${Object.values(ContentFieldControl).join(', ')} — how the field is edited (gallery is a list of pictures, list a list of words); how it is stored follows from this` },
|
|
13608
13678
|
required: { refs: ['field.required'], text: 'boolean — the field must be filled', none: 'false' },
|
|
13609
13679
|
note: key('field.note', "''"),
|
|
13610
13680
|
},
|
|
@@ -13612,11 +13682,12 @@ const WIRE_KEYS = {
|
|
|
13612
13682
|
count: key('seed.count'),
|
|
13613
13683
|
sample: key('seed.sample'),
|
|
13614
13684
|
isPublished: key('seed.isPublished'),
|
|
13615
|
-
values: { refs: ['seed.[field]'], text: "seedValue[] — one per field: the samples' value for it" },
|
|
13685
|
+
values: { refs: ['seed.[field]'], text: "seedValue[] — one per field, for EVERY field: the samples' value for it, with {n} for the sample's number and {sampleImage:n} for a picture, words a person replaces" },
|
|
13616
13686
|
},
|
|
13617
13687
|
seedValue: {
|
|
13618
13688
|
field: { refs: ['seed.[field]'], text: 'string — a field of the type' },
|
|
13619
13689
|
value: { refs: ['seed.[field]'], text: `string | string[] — ${describeShapeKey(PLAN_SHAPE['seed'], '[field]')} (a list for an array field)` },
|
|
13690
|
+
each: { refs: ['seed.perItem'], text: 'string[] — one value per sample, in order, when each sample has its own content', none: '[]' },
|
|
13620
13691
|
},
|
|
13621
13692
|
dataSource: {
|
|
13622
13693
|
alias: { refs: ['cmsDataSource.alias', 'relativeDataSource.alias'] },
|
|
@@ -13670,6 +13741,7 @@ const WIRE_KEYS = {
|
|
|
13670
13741
|
};
|
|
13671
13742
|
/** The plan keys the model does not write, and where the expander takes each from. */
|
|
13672
13743
|
const PLAN_WIRE_DERIVED = {
|
|
13744
|
+
'field.type': 'follows from the field\'s control (FIELD_TYPE_OF_CONTROL)',
|
|
13673
13745
|
'plan.version': `always '${SITE_PLAN_VERSION}'`,
|
|
13674
13746
|
'plan.source': 'this run (the context)',
|
|
13675
13747
|
'plan.locale': "the reading's language (the context)",
|
|
@@ -13731,7 +13803,7 @@ function sectionPatternIds() {
|
|
|
13731
13803
|
const sectionPatterns = () => sectionPatternIds().map(id => SITE_PATTERNS[id]);
|
|
13732
13804
|
const globalIds = (position) => Object.entries(SITE_PATTERNS).filter(([, p]) => p.global === position).map(([id]) => id);
|
|
13733
13805
|
function wireFieldJsonSchema() {
|
|
13734
|
-
return shaped(PlanWireEntry.Field, { name: jsonText(),
|
|
13806
|
+
return shaped(PlanWireEntry.Field, { name: jsonText(), controller: jsonOneOf(Object.values(ContentFieldControl)), required: jsonBoolean(), note: jsonText() });
|
|
13735
13807
|
}
|
|
13736
13808
|
/** The keys an entry leaves out under `options`. */
|
|
13737
13809
|
const CHILD_KEYS = { contentType: 'fields', page: 'sections' };
|
|
@@ -13745,7 +13817,7 @@ const shapedAs = (entry, options, properties) => {
|
|
|
13745
13817
|
return jsonShapedObject(wireEntryShape(entry, options), Object.fromEntries(Object.entries(properties).filter(([k]) => !left.includes(k))), `wire ${entry}`);
|
|
13746
13818
|
};
|
|
13747
13819
|
function wireContentTypeJsonSchema(options = {}) {
|
|
13748
|
-
const value = shaped(PlanWireEntry.SeedValue, { field: jsonText(), value: jsonAnyOf([jsonText(), jsonListOf(jsonText())]) });
|
|
13820
|
+
const value = shaped(PlanWireEntry.SeedValue, { field: jsonText(), value: jsonAnyOf([jsonText(), jsonListOf(jsonText())]), each: jsonListOf(jsonText()) });
|
|
13749
13821
|
return shapedAs(PlanWireEntry.ContentType, options, {
|
|
13750
13822
|
name: jsonText(),
|
|
13751
13823
|
label: jsonText(),
|
|
@@ -13843,7 +13915,8 @@ function expandWireField(wire) {
|
|
|
13843
13915
|
if (!isPlainObject(wire))
|
|
13844
13916
|
return wire;
|
|
13845
13917
|
const { required, note, ...rest } = wire;
|
|
13846
|
-
|
|
13918
|
+
const type = FIELD_TYPE_OF_CONTROL[rest['controller']];
|
|
13919
|
+
return { ...rest, ...(type ? { type } : {}), ...optional('required', required, v => v === undefined || v === false), ...optional('note', note) };
|
|
13847
13920
|
}
|
|
13848
13921
|
function expandWireContentType(wire, options = {}) {
|
|
13849
13922
|
if (!isPlainObject(wire))
|
|
@@ -13856,8 +13929,18 @@ function expandWireContentType(wire, options = {}) {
|
|
|
13856
13929
|
const { values, ...fixed } = seed;
|
|
13857
13930
|
if (fixed['count'] === 0 && emptyList(values))
|
|
13858
13931
|
return out;
|
|
13859
|
-
const
|
|
13860
|
-
|
|
13932
|
+
const perItem = {};
|
|
13933
|
+
const plain = Array.isArray(values) ? values.map(row => {
|
|
13934
|
+
if (!isPlainObject(row))
|
|
13935
|
+
return row;
|
|
13936
|
+
const { each, ...rest } = row;
|
|
13937
|
+
if (Array.isArray(each) && each.length)
|
|
13938
|
+
perItem[String(rest['field'])] = each;
|
|
13939
|
+
return rest;
|
|
13940
|
+
}) : values;
|
|
13941
|
+
const map = listToMap(plain ?? [], 'field', 'value');
|
|
13942
|
+
const items = Object.keys(perItem).length ? { perItem } : {};
|
|
13943
|
+
return { ...out, seed: isPlainObject(map) ? { ...fixed, ...items, ...map } : { ...fixed, values } };
|
|
13861
13944
|
}
|
|
13862
13945
|
function expandWireDataSource(wire) {
|
|
13863
13946
|
if (!isPlainObject(wire))
|
|
@@ -13935,15 +14018,15 @@ function expandPlanWire(parts, context) {
|
|
|
13935
14018
|
}
|
|
13936
14019
|
// ── The plan → the wire ────────────────────────────────────────────────────────────────────────────────────────────
|
|
13937
14020
|
function fieldToWire(field) {
|
|
13938
|
-
return { name: field.name,
|
|
14021
|
+
return { name: field.name, controller: field.controller, required: field.required ?? false, note: field.note ?? NONE };
|
|
13939
14022
|
}
|
|
13940
14023
|
function contentTypeToWire(type, options = {}) {
|
|
13941
14024
|
const played = type.roles;
|
|
13942
14025
|
const roles = ROLE_KEYS.filter(role => played[role]).map(role => ({ role, field: played[role] }));
|
|
13943
|
-
const { count = 0, sample = false, isPublished = false, ...values } = type.seed ?? {};
|
|
14026
|
+
const { count = 0, sample = false, isPublished = false, perItem = {}, ...values } = type.seed ?? {};
|
|
13944
14027
|
return {
|
|
13945
14028
|
name: type.name, label: type.label, roles, ...(options.children === false ? {} : { fields: type.fields.map(fieldToWire) }),
|
|
13946
|
-
seed: { count, sample, isPublished, values: mapToList(values, 'field', 'value') },
|
|
14029
|
+
seed: { count, sample, isPublished, values: mapToList(values, 'field', 'value').map(row => ({ ...row, each: perItem[String(row['field'])] ?? [] })) },
|
|
13947
14030
|
};
|
|
13948
14031
|
}
|
|
13949
14032
|
function dataSourceToWire(source) {
|
|
@@ -14895,7 +14978,10 @@ function writtenTexts(plan) {
|
|
|
14895
14978
|
});
|
|
14896
14979
|
plan.contentTypes?.forEach((type, t) => {
|
|
14897
14980
|
add(`contentTypes[${t}].label`, type.label);
|
|
14898
|
-
|
|
14981
|
+
const { perItem, ...seed } = type.seed ?? {};
|
|
14982
|
+
for (const [field, list] of Object.entries(perItem ?? {}))
|
|
14983
|
+
list.forEach((v, k) => add(`contentTypes[${t}].seed.perItem.${field}[${k}]`, v));
|
|
14984
|
+
for (const [field, value] of Object.entries(seed)) {
|
|
14899
14985
|
const values = Array.isArray(value) ? value : [value];
|
|
14900
14986
|
values.forEach((v, k) => add(`contentTypes[${t}].seed.${field}${Array.isArray(value) ? `[${k}]` : ''}`, v));
|
|
14901
14987
|
}
|
|
@@ -15561,6 +15647,45 @@ var StockSlotKind;
|
|
|
15561
15647
|
/** The image field of a marked sample item. */
|
|
15562
15648
|
StockSlotKind["Item"] = "item";
|
|
15563
15649
|
})(StockSlotKind || (StockSlotKind = {}));
|
|
15650
|
+
/** The owner's photos, in order, come before any stock or sample picture: sections never repeat one, and sample items go round again. */
|
|
15651
|
+
function planOwnPhotos(slots, urls) {
|
|
15652
|
+
if (!urls.length)
|
|
15653
|
+
return { placements: [], rest: [...slots] };
|
|
15654
|
+
const placements = [];
|
|
15655
|
+
const rest = [];
|
|
15656
|
+
let next = 0;
|
|
15657
|
+
for (const slot of slots) {
|
|
15658
|
+
if (slot.kind === StockSlotKind.Section) {
|
|
15659
|
+
if (next < urls.length)
|
|
15660
|
+
placements.push({ nodeId: slot.nodeId, owner: slot.owner, url: urls[next++] });
|
|
15661
|
+
else
|
|
15662
|
+
rest.push(slot);
|
|
15663
|
+
}
|
|
15664
|
+
else {
|
|
15665
|
+
placements.push({ item: { contentType: slot.contentType, index: slot.index, field: slot.field }, url: urls[next++ % urls.length] });
|
|
15666
|
+
}
|
|
15667
|
+
}
|
|
15668
|
+
return { placements, rest };
|
|
15669
|
+
}
|
|
15670
|
+
/** Each marked sample's gallery shows the owner's photos instead of bundled samples, each list starting where the last one stopped. */
|
|
15671
|
+
function applyOwnPhotoGalleries(plan, items, urls) {
|
|
15672
|
+
if (!urls.length)
|
|
15673
|
+
return 0;
|
|
15674
|
+
let changed = 0;
|
|
15675
|
+
for (const type of plan.contentTypes) {
|
|
15676
|
+
const field = roleField(type, ContentRole.Gallery);
|
|
15677
|
+
if (!field)
|
|
15678
|
+
continue;
|
|
15679
|
+
(items[type.name] ?? []).forEach((item, index) => {
|
|
15680
|
+
const list = item[field];
|
|
15681
|
+
if (!item['isSample'] || !Array.isArray(list))
|
|
15682
|
+
return;
|
|
15683
|
+
item[field] = list.map((value, i) => (parseSampleImageRef(value) === null ? value : urls[(index + i) % urls.length]));
|
|
15684
|
+
changed++;
|
|
15685
|
+
});
|
|
15686
|
+
}
|
|
15687
|
+
return changed;
|
|
15688
|
+
}
|
|
15564
15689
|
/** Where a photo may not appear twice: one page; one content type's samples (a list shows them together). */
|
|
15565
15690
|
function stockGroupOf(target) {
|
|
15566
15691
|
return target.kind === StockSlotKind.Section ? `page:${target.owner}` : `items:${target.contentType}`;
|
|
@@ -15753,5 +15878,5 @@ function addStockCredits(footer, credits) {
|
|
|
15753
15878
|
* Generated bundle index. Do not edit.
|
|
15754
15879
|
*/
|
|
15755
15880
|
|
|
15756
|
-
export { ACTIVE_BUILD_STATUSES, AI_REFUSAL_NEXT, AI_REFUSAL_STATUS, AI_STEPS, AI_STEP_LABELS, AI_STEP_NEEDS, AI_STEP_PART_TOKENS, AI_STEP_TYPICAL_TOKENS, AiCallStatus, AiCapability, AiFeature, AiGenerationStage, AiKeyMode, AiLimit, AiNextKind, AiProviderId, AiRefusalCode, AiStep, BAR_ITEMS_MAX, BAR_ITEMS_MIN, BASELINE_ROLES, BUILD_STEPS, BaselineRole, BindScope, BuildNoticeCode, BuildStep, CONTENT_ROLE_MEANINGS, CREDITS_PER_USD, CardBindTarget, CheckSeverity, ComposeError, ComposeIssueCode, ContentRole, ContentTypeAction, CreatedKind, DANGLING_LINK_CODES, DEFAULT_PHONE_MENU_BREAKPOINT, DEFAULT_SITE_LOCALE, ENTRANCE_EASING, ENTRANCE_ORIGIN_LOOK, ENTRANCE_TRIGGER, EntrancePart, EntranceSide, FACT_KEYS, FINAL_GENERATION_STAGES, FINDING_SEVERITY, GRAMMAR_TOO_LARGE_MESSAGE, GlobalSlot, HEBREW_PREFIXES, JSON_SCHEMA_BANNED_KEYWORDS, JsonSchemaShapeError, KeptReason, NAV_PART_LABELS, NAV_SHAPE_COPY, NEUTRAL_STYLE_PROPS, NODE_BASELINES, NO_TOKENS, NavPagesSource, NavRole, NavShape, NavShapeError, PAGE_ARCHETYPES, PLAN_EDITS_ANSWER_SHAPES, PLAN_EDITS_PART_SCHEMA_NAMES, PLAN_EDIT_OP_PART, PLAN_EDIT_SHAPE, PLAN_EDIT_WIRE_KEYS, PLAN_PARTS, PLAN_PART_KEYS, PLAN_WIRE_DERIVED, PLAN_WIRE_PART_SCHEMA_NAMES, PLAN_WIRE_SHAPE, PRICING_PATTERN, PUBLISH_BLOCKING_PLACEHOLDERS, PageDataKind, PathIssueCollector, PatternDirective, PatternGlobalPosition, PatternOpens, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, PlaceholderKind, PlanChangeAction, PlanChangeKind, PlanDataSourceMode, PlanDataSourceType, PlanEditIssueCode, PlanEditOp, PlanEditsOutcome, PlanPart, PlanWireEntry, PlanWireShapeError, PlanWordIssueCode, PreflightRefusalCode, PublishRefusalCode, REQUIRED_CONTENT_ROLES, RelativeOp, SAMPLE_IMAGE_REF, SITE_CHECKS, SITE_FACT_LABELS, SITE_HEADER_PATTERN, SITE_LIBRARY, SITE_LOCALES, SITE_NEED_IDS, SITE_PATTERNS, SITE_PLAN_VERSION, SITE_TEMPLATES, SPEC_SITE_ARCHETYPES, SPEC_SITE_COPY_LENGTHS, SPEC_SITE_DENSITY_COPY, SPEC_SITE_FACTS, SPEC_SITE_LIBRARY, SPEC_SITE_LOCALES, SPEC_SITE_NEED_IDS, SPEC_SITE_PATTERNS, SPEC_SITE_PLAN_SHAPE, SPEC_SITE_REQUIRED_ROLES, SPEC_SITE_ROLES, SPEC_SITE_TEMPLATES, STOCK_FAMILIES, STOCK_FAMILY_INTENTS, STOCK_INTENT_ORDER, STOCK_INTENT_SUBJECTS, STOCK_ITEM_ASPECT, STOCK_MIN_KEPT, STOCK_PROVIDER_TERMS, STOCK_SUBJECT_WORDS, STRICT_SCHEMA_BUDGET, STRICT_SCHEMA_LIMITS, STUDIO_TEMPLATE, SiteBuildKind, SiteBuildStatus, SiteCheckId, SiteFindingCode, SiteLocale, SitePlanError, SitePlanIssueCode, SitePlanSourceKind, SiteTemplateError, SiteTemplateId, StepState, StockIntent, StockOrientation, StockProviderId, StockReviewFlag, StockReviewVerdict, StockSlotKind, StockSubject, addBarItem, addStockCredits, aiStepParts, applyPlanEdits, applyStockItemPhotos, applyStockPhotos, archetypeIssues, aspectRatioOf, assertStyleSlots, assertValidSitePlan, auditSite, barIconForRoute, blocksPublish, buildKeys, buildStepFacts, builtHomePageId, composeNavHeader, composeSection, composeSite, contentTypePreviewFields, contentTypeToWire, copyLengthOf, costUsd, createSerializedNode, creditsOfUsd, dataSourceToWire, derivedDataSources, describePlanData, describeShapeKey, entranceAction, entranceInteraction, estimateStepCredits, expandPlanWire, expandWireContentType, expandWireDataSource, expandWireEdit, expandWireField, expandWirePage, expandWireSection, failedBuildStep, fieldToWire, findNavRoot, isActiveBuild, isNonEmptyString, isPlainObject, isRtlLocale, jsonAnyOf, jsonBoolean, jsonClosedObject, jsonInteger, jsonListOf, jsonOneOf, jsonSchemaKeywords, jsonSchemaObjects, jsonShapedObject, jsonText, modelCanDo, moveBarItem, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, orientationOfRatio, pageToWire, parsePatternPath, parseSampleImageRef, pathAt, patternById, patternHasForm, patternLinkSlots, patternListGap, patternManifest, patternNeedsBinding, patternNodes, patternOptionalParts, patternRoleNeeds, patternScopes, patternSlotBudgets, patternSlots, patternTakesBinding, phoneMenuPages, planEditOps, planEditToWire, planEditWireGaps, planEditWireKeys, planEditWireOps, planEditWireShape, planEditsFromWire, planEditsJsonSchema, planEditsToWire, planEntrances, planFromTemplate, planNavShape, planPartOfPath, planPartToWire, planStockPhotos, planToWire, planWireGaps, planWirePartJsonSchema, planWirePartShape, planWordIssues, publishRefusal, publishVerdict, recipeListBinds, releasedLayoutDefaults, removeBarItem, requiredAcknowledgements, requiredShapeKeys, roleField, routeMatches, routeParams, sampleImageRef, scoreStockPhoto, sectionEntrances, sectionPatternIds, sectionToWire, setStyleProps, shapeKeys, showcaseGlobals, showcasePages, showcasePlans, siteNavPages, slotBudget, stockCopyKey, stockCreditLine, stockCreditLines, stockCreditNode, stockCreditNodeId, stockFits, stockGroupOf, stockItemSlots, stockKept, stockPhotoRatio, stockPhotoSubject, stockPhotoUsable, stockPhotoWords, stockSlots, stockWord, stockWords, strictSchemaComplexity, strictSchemaRefusal, typicalStepTokens, validatePlanEdits, validateSitePlan, walkSerialized, wireContentTypeJsonSchema, wireDataSourceJsonSchema, wireFieldJsonSchema, wirePageJsonSchema, wireSectionJsonSchema, withDerivedSources, wordPattern, writtenTexts };
|
|
15881
|
+
export { ACTIVE_BUILD_STATUSES, AI_REFUSAL_NEXT, AI_REFUSAL_STATUS, AI_STEPS, AI_STEP_LABELS, AI_STEP_NEEDS, AI_STEP_PART_TOKENS, AI_STEP_TYPICAL_TOKENS, AiCallStatus, AiCapability, AiFeature, AiGenerationStage, AiKeyMode, AiLimit, AiNextKind, AiProviderId, AiRefusalCode, AiStep, BAR_ITEMS_MAX, BAR_ITEMS_MIN, BASELINE_ROLES, BUILD_STEPS, BaselineRole, BindScope, BuildNoticeCode, BuildStep, CONTENT_ROLE_MEANINGS, CREDITS_PER_USD, CardBindTarget, CheckSeverity, ComposeError, ComposeIssueCode, ContentFieldControl, ContentFieldType, ContentRole, ContentTypeAction, CreatedKind, DANGLING_LINK_CODES, DEFAULT_PHONE_MENU_BREAKPOINT, DEFAULT_SITE_LOCALE, ENTRANCE_EASING, ENTRANCE_ORIGIN_LOOK, ENTRANCE_TRIGGER, EntrancePart, EntranceSide, FACT_KEYS, FIELD_TYPE_OF_CONTROL, FINAL_GENERATION_STAGES, FINDING_SEVERITY, GRAMMAR_TOO_LARGE_MESSAGE, GlobalSlot, HEBREW_PREFIXES, JSON_SCHEMA_BANNED_KEYWORDS, JsonSchemaShapeError, KeptReason, NAV_PART_LABELS, NAV_SHAPE_COPY, NEUTRAL_STYLE_PROPS, NODE_BASELINES, NO_TOKENS, NavPagesSource, NavRole, NavShape, NavShapeError, PAGE_ARCHETYPES, PLAN_EDITS_ANSWER_SHAPES, PLAN_EDITS_PART_SCHEMA_NAMES, PLAN_EDIT_OP_PART, PLAN_EDIT_SHAPE, PLAN_EDIT_WIRE_KEYS, PLAN_PARTS, PLAN_PART_KEYS, PLAN_WIRE_DERIVED, PLAN_WIRE_PART_SCHEMA_NAMES, PLAN_WIRE_SHAPE, PRICING_PATTERN, PUBLISH_BLOCKING_PLACEHOLDERS, PageDataKind, PathIssueCollector, PatternDirective, PatternGlobalPosition, PatternOpens, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, PlaceholderKind, PlanChangeAction, PlanChangeKind, PlanDataSourceMode, PlanDataSourceType, PlanEditIssueCode, PlanEditOp, PlanEditsOutcome, PlanPart, PlanWireEntry, PlanWireShapeError, PlanWordIssueCode, PreflightRefusalCode, PublishRefusalCode, REQUIRED_CONTENT_ROLES, RelativeOp, SAMPLE_IMAGE_REF, SITE_CHECKS, SITE_FACT_LABELS, SITE_HEADER_PATTERN, SITE_LIBRARY, SITE_LOCALES, SITE_NEED_IDS, SITE_PATTERNS, SITE_PLAN_VERSION, SITE_TEMPLATES, SPEC_SITE_ARCHETYPES, SPEC_SITE_COPY_LENGTHS, SPEC_SITE_DENSITY_COPY, SPEC_SITE_FACTS, SPEC_SITE_LIBRARY, SPEC_SITE_LOCALES, SPEC_SITE_NEED_IDS, SPEC_SITE_PATTERNS, SPEC_SITE_PLAN_SHAPE, SPEC_SITE_REQUIRED_ROLES, SPEC_SITE_ROLES, SPEC_SITE_TEMPLATES, STOCK_FAMILIES, STOCK_FAMILY_INTENTS, STOCK_INTENT_ORDER, STOCK_INTENT_SUBJECTS, STOCK_ITEM_ASPECT, STOCK_MIN_KEPT, STOCK_PROVIDER_TERMS, STOCK_SUBJECT_WORDS, STRICT_SCHEMA_BUDGET, STRICT_SCHEMA_LIMITS, STUDIO_TEMPLATE, SiteBuildKind, SiteBuildStatus, SiteCheckId, SiteFindingCode, SiteLocale, SitePlanError, SitePlanIssueCode, SitePlanSourceKind, SiteTemplateError, SiteTemplateId, StepState, StockIntent, StockOrientation, StockProviderId, StockReviewFlag, StockReviewVerdict, StockSlotKind, StockSubject, addBarItem, addStockCredits, aiStepParts, applyOwnPhotoGalleries, applyPlanEdits, applyStockItemPhotos, applyStockPhotos, archetypeIssues, aspectRatioOf, assertStyleSlots, assertValidSitePlan, auditSite, barIconForRoute, blocksPublish, buildKeys, buildStepFacts, builtHomePageId, composeNavHeader, composeSection, composeSite, contentTypePreviewFields, contentTypeToWire, copyLengthOf, costUsd, createSerializedNode, creditsOfUsd, dataSourceToWire, derivedDataSources, describePlanData, describeShapeKey, entranceAction, entranceInteraction, estimateStepCredits, expandPlanWire, expandWireContentType, expandWireDataSource, expandWireEdit, expandWireField, expandWirePage, expandWireSection, failedBuildStep, fieldToWire, findNavRoot, isActiveBuild, isNonEmptyString, isPlainObject, isRtlLocale, jsonAnyOf, jsonBoolean, jsonClosedObject, jsonInteger, jsonListOf, jsonOneOf, jsonSchemaKeywords, jsonSchemaObjects, jsonShapedObject, jsonText, modelCanDo, moveBarItem, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, orientationOfRatio, pageToWire, parsePatternPath, parseSampleImageRef, pathAt, patternById, patternHasForm, patternLinkSlots, patternListGap, patternManifest, patternNeedsBinding, patternNodes, patternOptionalParts, patternRoleNeeds, patternScopes, patternSlotBudgets, patternSlots, patternTakesBinding, phoneMenuPages, planEditOps, planEditToWire, planEditWireGaps, planEditWireKeys, planEditWireOps, planEditWireShape, planEditsFromWire, planEditsJsonSchema, planEditsToWire, planEntrances, planFromTemplate, planNavShape, planOwnPhotos, planPartOfPath, planPartToWire, planStockPhotos, planToWire, planWireGaps, planWirePartJsonSchema, planWirePartShape, planWordIssues, publishRefusal, publishVerdict, recipeListBinds, releasedLayoutDefaults, removeBarItem, requiredAcknowledgements, requiredShapeKeys, roleField, routeMatches, routeParams, sampleImageRef, scoreStockPhoto, sectionEntrances, sectionPatternIds, sectionToWire, setStyleProps, shapeKeys, showcaseGlobals, showcasePages, showcasePlans, siteNavPages, slotBudget, stockCopyKey, stockCreditLine, stockCreditLines, stockCreditNode, stockCreditNodeId, stockFits, stockGroupOf, stockItemSlots, stockKept, stockPhotoRatio, stockPhotoSubject, stockPhotoUsable, stockPhotoWords, stockSlots, stockWord, stockWords, strictSchemaComplexity, strictSchemaRefusal, typicalStepTokens, validatePlanEdits, validateSitePlan, walkSerialized, wireContentTypeJsonSchema, wireDataSourceJsonSchema, wireFieldJsonSchema, wirePageJsonSchema, wireSectionJsonSchema, withDerivedSources, wordPattern, writtenTexts };
|
|
15757
15882
|
//# sourceMappingURL=vectoriox-iox-ui-generation-core.mjs.map
|