@vectoriox/iox-ui 5.46.0 → 5.47.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 +224 -78
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-harness-core.mjs +4109 -0
- package/fesm2022/vectoriox-iox-ui-harness-core.mjs.map +1 -0
- package/generation-core/index.d.ts +145 -17
- package/harness-core/index.d.ts +2479 -0
- package/harness-core/package.json +3 -0
- package/package.json +5 -1
- package/src/generation-core/public-api.ts +1 -0
- package/src/generation-core/shape-check.ts +92 -0
- package/src/generation-core/site-spec.generated.ts +131 -2
- package/src/generation-core/validate-site-plan.ts +9 -62
- package/src/harness-core/business-types.ts +141 -0
- package/src/harness-core/harness-spec.generated.ts +3528 -0
- package/src/harness-core/lint.ts +94 -0
- package/src/harness-core/look.ts +32 -0
- package/src/harness-core/motion.ts +67 -0
- package/src/harness-core/needs.ts +42 -0
- package/src/harness-core/prompt-context.ts +91 -0
- package/src/harness-core/public-api.ts +18 -0
- package/src/harness-core/rank.ts +226 -0
- package/src/harness-core/site-analysis.ts +180 -0
|
@@ -29,7 +29,7 @@ const SPEC_SITE_PLAN_SHAPE = {
|
|
|
29
29
|
"business": {
|
|
30
30
|
"name": "string — the brand: the header, the hero, the copyright line",
|
|
31
31
|
"tagline?": "string — the hero lead and the footer line",
|
|
32
|
-
"facts?": "{ [fact]: string } — facts (email, phone, city): only the customer's own words; a blank fact is a publish-blocking placeholder, never invented"
|
|
32
|
+
"facts?": "{ [fact]: string } — facts (email, phone, city, address, hours): only the customer's own words; a blank fact is a publish-blocking placeholder, never invented"
|
|
33
33
|
},
|
|
34
34
|
"design": {
|
|
35
35
|
"flavorId": "string — a v2 flavor pack id",
|
|
@@ -107,7 +107,9 @@ const SPEC_SITE_PLAN_SHAPE = {
|
|
|
107
107
|
const SPEC_SITE_FACTS = {
|
|
108
108
|
"email": "Email address",
|
|
109
109
|
"phone": "Phone number",
|
|
110
|
-
"city": "City or area"
|
|
110
|
+
"city": "City or area",
|
|
111
|
+
"address": "Street address",
|
|
112
|
+
"hours": "Opening hours"
|
|
111
113
|
};
|
|
112
114
|
const SPEC_SITE_PATTERNS = {
|
|
113
115
|
"nav.inline-cta": {
|
|
@@ -2053,6 +2055,132 @@ const SPEC_SITE_TEMPLATES = {
|
|
|
2053
2055
|
}
|
|
2054
2056
|
}
|
|
2055
2057
|
};
|
|
2058
|
+
const SPEC_SITE_LIBRARY = [
|
|
2059
|
+
{
|
|
2060
|
+
"id": "nav.inline-cta",
|
|
2061
|
+
"family": "nav"
|
|
2062
|
+
},
|
|
2063
|
+
{
|
|
2064
|
+
"id": "nav.centered-logo",
|
|
2065
|
+
"family": "nav"
|
|
2066
|
+
},
|
|
2067
|
+
{
|
|
2068
|
+
"id": "nav.overlay-menu",
|
|
2069
|
+
"family": "nav"
|
|
2070
|
+
},
|
|
2071
|
+
{
|
|
2072
|
+
"id": "hero.split",
|
|
2073
|
+
"family": "hero"
|
|
2074
|
+
},
|
|
2075
|
+
{
|
|
2076
|
+
"id": "hero.centered",
|
|
2077
|
+
"family": "hero"
|
|
2078
|
+
},
|
|
2079
|
+
{
|
|
2080
|
+
"id": "hero.full-bleed-media",
|
|
2081
|
+
"family": "hero"
|
|
2082
|
+
},
|
|
2083
|
+
{
|
|
2084
|
+
"id": "hero.stacked-editorial",
|
|
2085
|
+
"family": "hero"
|
|
2086
|
+
},
|
|
2087
|
+
{
|
|
2088
|
+
"id": "proof.logo-strip",
|
|
2089
|
+
"family": "proof"
|
|
2090
|
+
},
|
|
2091
|
+
{
|
|
2092
|
+
"id": "proof.stat-row",
|
|
2093
|
+
"family": "proof"
|
|
2094
|
+
},
|
|
2095
|
+
{
|
|
2096
|
+
"id": "proof.testimonial-single",
|
|
2097
|
+
"family": "proof"
|
|
2098
|
+
},
|
|
2099
|
+
{
|
|
2100
|
+
"id": "proof.testimonial-carousel",
|
|
2101
|
+
"family": "proof"
|
|
2102
|
+
},
|
|
2103
|
+
{
|
|
2104
|
+
"id": "feature.triad",
|
|
2105
|
+
"family": "feature"
|
|
2106
|
+
},
|
|
2107
|
+
{
|
|
2108
|
+
"id": "feature.alternating-rows",
|
|
2109
|
+
"family": "feature"
|
|
2110
|
+
},
|
|
2111
|
+
{
|
|
2112
|
+
"id": "feature.icon-list",
|
|
2113
|
+
"family": "feature"
|
|
2114
|
+
},
|
|
2115
|
+
{
|
|
2116
|
+
"id": "feature.tabbed",
|
|
2117
|
+
"family": "feature"
|
|
2118
|
+
},
|
|
2119
|
+
{
|
|
2120
|
+
"id": "collection.card-grid",
|
|
2121
|
+
"family": "collection"
|
|
2122
|
+
},
|
|
2123
|
+
{
|
|
2124
|
+
"id": "collection.masonry-gallery",
|
|
2125
|
+
"family": "collection"
|
|
2126
|
+
},
|
|
2127
|
+
{
|
|
2128
|
+
"id": "collection.slider",
|
|
2129
|
+
"family": "collection"
|
|
2130
|
+
},
|
|
2131
|
+
{
|
|
2132
|
+
"id": "collection.list-detail",
|
|
2133
|
+
"family": "collection"
|
|
2134
|
+
},
|
|
2135
|
+
{
|
|
2136
|
+
"id": "story.long-form",
|
|
2137
|
+
"family": "story"
|
|
2138
|
+
},
|
|
2139
|
+
{
|
|
2140
|
+
"id": "story.timeline",
|
|
2141
|
+
"family": "story"
|
|
2142
|
+
},
|
|
2143
|
+
{
|
|
2144
|
+
"id": "story.quote-break",
|
|
2145
|
+
"family": "story"
|
|
2146
|
+
},
|
|
2147
|
+
{
|
|
2148
|
+
"id": "cta.banner",
|
|
2149
|
+
"family": "cta"
|
|
2150
|
+
},
|
|
2151
|
+
{
|
|
2152
|
+
"id": "cta.split-form",
|
|
2153
|
+
"family": "cta"
|
|
2154
|
+
},
|
|
2155
|
+
{
|
|
2156
|
+
"id": "contact.split-map",
|
|
2157
|
+
"family": "contact"
|
|
2158
|
+
},
|
|
2159
|
+
{
|
|
2160
|
+
"id": "contact.simple",
|
|
2161
|
+
"family": "contact"
|
|
2162
|
+
},
|
|
2163
|
+
{
|
|
2164
|
+
"id": "faq.accordion",
|
|
2165
|
+
"family": "faq"
|
|
2166
|
+
},
|
|
2167
|
+
{
|
|
2168
|
+
"id": "pricing.tiers",
|
|
2169
|
+
"family": "pricing"
|
|
2170
|
+
},
|
|
2171
|
+
{
|
|
2172
|
+
"id": "footer.three-column",
|
|
2173
|
+
"family": "footer"
|
|
2174
|
+
},
|
|
2175
|
+
{
|
|
2176
|
+
"id": "footer.mega",
|
|
2177
|
+
"family": "footer"
|
|
2178
|
+
},
|
|
2179
|
+
{
|
|
2180
|
+
"id": "footer.minimal",
|
|
2181
|
+
"family": "footer"
|
|
2182
|
+
}
|
|
2183
|
+
];
|
|
2056
2184
|
|
|
2057
2185
|
const NODE_BASELINES = {
|
|
2058
2186
|
"Button": {
|
|
@@ -7531,6 +7659,76 @@ function walkSerialized(nodes, visit, ancestors = []) {
|
|
|
7531
7659
|
}
|
|
7532
7660
|
}
|
|
7533
7661
|
|
|
7662
|
+
/**
|
|
7663
|
+
* The ONE way a framework-free gate refuses a document "with a path, never repairs" (W1's site-plan gate, the
|
|
7664
|
+
* harness's analysis gate): a documented shape table (key → type text; `key?` optional, `[name]` the object's
|
|
7665
|
+
* own field names) whose key lists the gate READS — so the shape a model is told about is the shape refused —
|
|
7666
|
+
* and a collector that records each refusal at its dotted path. Generic over each gate's issue-code enum.
|
|
7667
|
+
*/
|
|
7668
|
+
const OPTIONAL_MARK = '?';
|
|
7669
|
+
const DYNAMIC_KEY = /^\[[^\]]+\]\??$/;
|
|
7670
|
+
const isDynamic = (key) => DYNAMIC_KEY.test(key);
|
|
7671
|
+
/** Every fixed key an object of the shape may carry. */
|
|
7672
|
+
function shapeKeys(entry) {
|
|
7673
|
+
return Object.keys(entry).filter(k => !isDynamic(k)).map(k => (k.endsWith(OPTIONAL_MARK) ? k.slice(0, -1) : k));
|
|
7674
|
+
}
|
|
7675
|
+
/** The keys an object of the shape must carry. */
|
|
7676
|
+
function requiredShapeKeys(entry) {
|
|
7677
|
+
return Object.keys(entry).filter(k => !isDynamic(k) && !k.endsWith(OPTIONAL_MARK));
|
|
7678
|
+
}
|
|
7679
|
+
const isPlainObject = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
|
|
7680
|
+
const isNonEmptyString = (v) => typeof v === 'string' && v.trim() !== '';
|
|
7681
|
+
/** `path.key`, or `key` at the root. */
|
|
7682
|
+
const pathAt = (path, key) => (path ? `${path}.${key}` : key);
|
|
7683
|
+
class PathIssueCollector {
|
|
7684
|
+
/** `subject` names the document in a refusal ("… is not part of the plan shape"). */
|
|
7685
|
+
constructor(subject, codes) {
|
|
7686
|
+
this.subject = subject;
|
|
7687
|
+
this.codes = codes;
|
|
7688
|
+
this.issues = [];
|
|
7689
|
+
}
|
|
7690
|
+
add(code, path, message) {
|
|
7691
|
+
this.issues.push({ code, path, message });
|
|
7692
|
+
}
|
|
7693
|
+
keys(obj, allowed, path) {
|
|
7694
|
+
for (const key of Object.keys(obj))
|
|
7695
|
+
if (!allowed.includes(key))
|
|
7696
|
+
this.add(this.codes.unknownKey, pathAt(path, key), `"${key}" is not part of the ${this.subject} shape`);
|
|
7697
|
+
}
|
|
7698
|
+
string(obj, key, path, required = true) {
|
|
7699
|
+
const v = obj[key];
|
|
7700
|
+
if (v === undefined && !required)
|
|
7701
|
+
return null;
|
|
7702
|
+
if (!isNonEmptyString(v)) {
|
|
7703
|
+
this.add(this.codes.shape, pathAt(path, key), 'must be a non-empty string');
|
|
7704
|
+
return null;
|
|
7705
|
+
}
|
|
7706
|
+
return v;
|
|
7707
|
+
}
|
|
7708
|
+
boolean(obj, key, path) {
|
|
7709
|
+
if (obj[key] !== undefined && typeof obj[key] !== 'boolean')
|
|
7710
|
+
this.add(this.codes.shape, pathAt(path, key), 'must be a boolean');
|
|
7711
|
+
}
|
|
7712
|
+
array(obj, key, path) {
|
|
7713
|
+
const v = obj[key];
|
|
7714
|
+
if (!Array.isArray(v)) {
|
|
7715
|
+
this.add(this.codes.shape, pathAt(path, key), 'must be an array');
|
|
7716
|
+
return [];
|
|
7717
|
+
}
|
|
7718
|
+
return v;
|
|
7719
|
+
}
|
|
7720
|
+
unique(values, path, what) {
|
|
7721
|
+
const seen = new Set();
|
|
7722
|
+
values.forEach((v, i) => {
|
|
7723
|
+
if (v === null)
|
|
7724
|
+
return;
|
|
7725
|
+
if (seen.has(v))
|
|
7726
|
+
this.add(this.codes.duplicate, path(i), `${what} "${v}" is used twice`);
|
|
7727
|
+
seen.add(v);
|
|
7728
|
+
});
|
|
7729
|
+
}
|
|
7730
|
+
}
|
|
7731
|
+
|
|
7534
7732
|
/**
|
|
7535
7733
|
* The Site Plan validator — the gate in front of the composer. The wizard's plan and (later) the AI's
|
|
7536
7734
|
* plan go through the SAME checks: an unknown pattern, a slot the pattern does not declare, a source
|
|
@@ -7576,17 +7774,8 @@ class SitePlanError extends Error {
|
|
|
7576
7774
|
/** Route-scope aliases (`$route`, `$current`, …) are platform-owned. */
|
|
7577
7775
|
const RESERVED_PREFIX = '$';
|
|
7578
7776
|
const ID_FIELD = '_id';
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
const isDynamic = (key) => DYNAMIC_KEY.test(key);
|
|
7582
|
-
/** Every fixed key an object of the shape may carry. */
|
|
7583
|
-
function shapeKeys(entry) {
|
|
7584
|
-
return Object.keys(entry).filter(k => !isDynamic(k)).map(k => (k.endsWith(OPTIONAL_MARK) ? k.slice(0, -1) : k));
|
|
7585
|
-
}
|
|
7586
|
-
/** The keys an object of the shape must carry. */
|
|
7587
|
-
function requiredShapeKeys(entry) {
|
|
7588
|
-
return Object.keys(entry).filter(k => !isDynamic(k) && !k.endsWith(OPTIONAL_MARK));
|
|
7589
|
-
}
|
|
7777
|
+
/** The documented plan shape (contract `site.planShape`): its key lists are READ (`shape-check`), so a key
|
|
7778
|
+
* the plan documents is a key the gate validates — and an undocumented one is refused. */
|
|
7590
7779
|
const SHAPE = SPEC_SITE_PLAN_SHAPE;
|
|
7591
7780
|
const PLAN_KEYS = shapeKeys(SHAPE['plan']);
|
|
7592
7781
|
const TEMPLATE_SOURCE_KEYS = shapeKeys(SHAPE['sourceTemplate']);
|
|
@@ -7607,61 +7796,18 @@ const GLOBAL_POSITION = {
|
|
|
7607
7796
|
};
|
|
7608
7797
|
const ROUTE = /^\/(?:(?:[a-z0-9]+(?:-[a-z0-9]+)*|:[a-zA-Z_][a-zA-Z0-9_]*)(?:\/(?:[a-z0-9]+(?:-[a-z0-9]+)*|:[a-zA-Z_][a-zA-Z0-9_]*))*)?$/;
|
|
7609
7798
|
const ROUTE_PARAM$1 = /:([a-zA-Z_][a-zA-Z0-9_]*)/g;
|
|
7610
|
-
const isObject = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
|
|
7611
|
-
const isNonEmptyString = (v) => typeof v === 'string' && v.trim() !== '';
|
|
7612
7799
|
const has = (table, key) => Object.prototype.hasOwnProperty.call(table, key);
|
|
7613
|
-
const at = (path, key) => (path ? `${path}.${key}` : key);
|
|
7614
7800
|
/** The `:param` names of a route, in order. */
|
|
7615
7801
|
function routeParams(route) {
|
|
7616
7802
|
return [...route.matchAll(ROUTE_PARAM$1)].map(m => m[1]);
|
|
7617
7803
|
}
|
|
7618
|
-
class Collector {
|
|
7804
|
+
class Collector extends PathIssueCollector {
|
|
7619
7805
|
constructor() {
|
|
7620
|
-
|
|
7621
|
-
}
|
|
7622
|
-
add(code, path, message) {
|
|
7623
|
-
this.issues.push({ code, path, message });
|
|
7624
|
-
}
|
|
7625
|
-
keys(obj, allowed, path) {
|
|
7626
|
-
for (const key of Object.keys(obj))
|
|
7627
|
-
if (!allowed.includes(key))
|
|
7628
|
-
this.add(SitePlanIssueCode.UnknownKey, at(path, key), `"${key}" is not part of the plan shape`);
|
|
7629
|
-
}
|
|
7630
|
-
string(obj, key, path, required = true) {
|
|
7631
|
-
const v = obj[key];
|
|
7632
|
-
if (v === undefined && !required)
|
|
7633
|
-
return null;
|
|
7634
|
-
if (!isNonEmptyString(v)) {
|
|
7635
|
-
this.add(SitePlanIssueCode.Shape, at(path, key), 'must be a non-empty string');
|
|
7636
|
-
return null;
|
|
7637
|
-
}
|
|
7638
|
-
return v;
|
|
7639
|
-
}
|
|
7640
|
-
boolean(obj, key, path) {
|
|
7641
|
-
if (obj[key] !== undefined && typeof obj[key] !== 'boolean')
|
|
7642
|
-
this.add(SitePlanIssueCode.Shape, at(path, key), 'must be a boolean');
|
|
7643
|
-
}
|
|
7644
|
-
array(obj, key, path) {
|
|
7645
|
-
const v = obj[key];
|
|
7646
|
-
if (!Array.isArray(v)) {
|
|
7647
|
-
this.add(SitePlanIssueCode.Shape, at(path, key), 'must be an array');
|
|
7648
|
-
return [];
|
|
7649
|
-
}
|
|
7650
|
-
return v;
|
|
7651
|
-
}
|
|
7652
|
-
unique(values, path, what) {
|
|
7653
|
-
const seen = new Set();
|
|
7654
|
-
values.forEach((v, i) => {
|
|
7655
|
-
if (v === null)
|
|
7656
|
-
return;
|
|
7657
|
-
if (seen.has(v))
|
|
7658
|
-
this.add(SitePlanIssueCode.Duplicate, path(i), `${what} "${v}" is used twice`);
|
|
7659
|
-
seen.add(v);
|
|
7660
|
-
});
|
|
7806
|
+
super('plan', { shape: SitePlanIssueCode.Shape, unknownKey: SitePlanIssueCode.UnknownKey, duplicate: SitePlanIssueCode.Duplicate });
|
|
7661
7807
|
}
|
|
7662
7808
|
}
|
|
7663
7809
|
function validateSource(c, source) {
|
|
7664
|
-
if (!
|
|
7810
|
+
if (!isPlainObject(source))
|
|
7665
7811
|
return c.add(SitePlanIssueCode.Shape, 'source', 'must be an object');
|
|
7666
7812
|
if (source['kind'] === SitePlanSourceKind.Template) {
|
|
7667
7813
|
c.keys(source, TEMPLATE_SOURCE_KEYS, 'source');
|
|
@@ -7678,7 +7824,7 @@ function validateSource(c, source) {
|
|
|
7678
7824
|
}
|
|
7679
7825
|
}
|
|
7680
7826
|
function validateBusiness(c, business) {
|
|
7681
|
-
if (!
|
|
7827
|
+
if (!isPlainObject(business))
|
|
7682
7828
|
return c.add(SitePlanIssueCode.Shape, 'business', 'must be an object');
|
|
7683
7829
|
c.keys(business, BUSINESS_KEYS, 'business');
|
|
7684
7830
|
if (!isNonEmptyString(business['name']))
|
|
@@ -7688,7 +7834,7 @@ function validateBusiness(c, business) {
|
|
|
7688
7834
|
const facts = business['facts'];
|
|
7689
7835
|
if (facts === undefined)
|
|
7690
7836
|
return;
|
|
7691
|
-
if (!
|
|
7837
|
+
if (!isPlainObject(facts))
|
|
7692
7838
|
return c.add(SitePlanIssueCode.Shape, 'business.facts', 'must be an object');
|
|
7693
7839
|
for (const [key, value] of Object.entries(facts)) {
|
|
7694
7840
|
if (!FACT_KEYS.includes(key))
|
|
@@ -7698,7 +7844,7 @@ function validateBusiness(c, business) {
|
|
|
7698
7844
|
}
|
|
7699
7845
|
}
|
|
7700
7846
|
function validateDesign(c, design) {
|
|
7701
|
-
if (!
|
|
7847
|
+
if (!isPlainObject(design))
|
|
7702
7848
|
return c.add(SitePlanIssueCode.Shape, 'design', 'must be an object');
|
|
7703
7849
|
c.keys(design, DESIGN_KEYS, 'design');
|
|
7704
7850
|
for (const key of DESIGN_REQUIRED)
|
|
@@ -7728,14 +7874,14 @@ function validateDesign(c, design) {
|
|
|
7728
7874
|
bad('mode', `must be one of ${SPEC_AXES.modes.join(', ')}`);
|
|
7729
7875
|
if (design['pillButtons'] !== undefined && typeof design['pillButtons'] !== 'boolean')
|
|
7730
7876
|
bad('pillButtons', 'must be a boolean');
|
|
7731
|
-
if (design['fonts'] !== undefined && !
|
|
7877
|
+
if (design['fonts'] !== undefined && !isPlainObject(design['fonts']))
|
|
7732
7878
|
bad('fonts', 'must be an object');
|
|
7733
7879
|
}
|
|
7734
7880
|
function validateContentTypes(c, list) {
|
|
7735
7881
|
const types = new Map();
|
|
7736
7882
|
list.forEach((raw, i) => {
|
|
7737
7883
|
const path = `contentTypes[${i}]`;
|
|
7738
|
-
if (!
|
|
7884
|
+
if (!isPlainObject(raw))
|
|
7739
7885
|
return c.add(SitePlanIssueCode.Shape, path, 'must be an object');
|
|
7740
7886
|
c.keys(raw, CONTENT_TYPE_KEYS, path);
|
|
7741
7887
|
const name = c.string(raw, 'name', path);
|
|
@@ -7743,7 +7889,7 @@ function validateContentTypes(c, list) {
|
|
|
7743
7889
|
const fields = c.array(raw, 'fields', path);
|
|
7744
7890
|
const names = fields.map((f, j) => {
|
|
7745
7891
|
const fp = `${path}.fields[${j}]`;
|
|
7746
|
-
if (!
|
|
7892
|
+
if (!isPlainObject(f)) {
|
|
7747
7893
|
c.add(SitePlanIssueCode.Shape, fp, 'must be an object');
|
|
7748
7894
|
return null;
|
|
7749
7895
|
}
|
|
@@ -7764,7 +7910,7 @@ function validateContentTypes(c, list) {
|
|
|
7764
7910
|
}
|
|
7765
7911
|
const seed = raw['seed'];
|
|
7766
7912
|
if (seed !== undefined) {
|
|
7767
|
-
if (!
|
|
7913
|
+
if (!isPlainObject(seed))
|
|
7768
7914
|
c.add(SitePlanIssueCode.Shape, `${path}.seed`, 'must be an object');
|
|
7769
7915
|
else {
|
|
7770
7916
|
if (!Number.isInteger(seed['count']) || seed['count'] < 0)
|
|
@@ -7789,7 +7935,7 @@ function validateDataSources(c, list, types) {
|
|
|
7789
7935
|
const sources = new Map();
|
|
7790
7936
|
list.forEach((raw, i) => {
|
|
7791
7937
|
const path = `dataSources[${i}]`;
|
|
7792
|
-
if (!
|
|
7938
|
+
if (!isPlainObject(raw))
|
|
7793
7939
|
return c.add(SitePlanIssueCode.Shape, path, 'must be an object');
|
|
7794
7940
|
const alias = c.string(raw, 'alias', path);
|
|
7795
7941
|
if (alias && alias.startsWith(RESERVED_PREFIX)) {
|
|
@@ -7809,7 +7955,7 @@ function validateDataSources(c, list, types) {
|
|
|
7809
7955
|
let routeParam;
|
|
7810
7956
|
const byRoute = raw['filterByRouteParam'];
|
|
7811
7957
|
if (byRoute !== undefined) {
|
|
7812
|
-
if (!
|
|
7958
|
+
if (!isPlainObject(byRoute))
|
|
7813
7959
|
c.add(SitePlanIssueCode.Shape, `${path}.filterByRouteParam`, 'must be an object');
|
|
7814
7960
|
else {
|
|
7815
7961
|
c.keys(byRoute, ['field', 'routeParam'], `${path}.filterByRouteParam`);
|
|
@@ -7837,10 +7983,10 @@ function validateDataSources(c, list, types) {
|
|
|
7837
7983
|
c.add(SitePlanIssueCode.InvalidDataSource, `${path}.type`, `must be "${PlanDataSourceType.Cms}" or "${PlanDataSourceType.Relative}"`);
|
|
7838
7984
|
}
|
|
7839
7985
|
});
|
|
7840
|
-
c.unique(list.map(r => (
|
|
7986
|
+
c.unique(list.map(r => (isPlainObject(r) && isNonEmptyString(r['alias']) ? r['alias'] : null)), i => `dataSources[${i}].alias`, 'alias');
|
|
7841
7987
|
// A relative source locates its subject (a single item) within a collection of the SAME type.
|
|
7842
7988
|
list.forEach((raw, i) => {
|
|
7843
|
-
if (!
|
|
7989
|
+
if (!isPlainObject(raw) || raw['type'] !== PlanDataSourceType.Relative)
|
|
7844
7990
|
return;
|
|
7845
7991
|
const of = sources.get(raw['of']);
|
|
7846
7992
|
const within = sources.get(raw['within']);
|
|
@@ -7857,7 +8003,7 @@ function validatePages(c, list, types, sources) {
|
|
|
7857
8003
|
const homes = [];
|
|
7858
8004
|
list.forEach((raw, i) => {
|
|
7859
8005
|
const path = `pages[${i}]`;
|
|
7860
|
-
if (!
|
|
8006
|
+
if (!isPlainObject(raw))
|
|
7861
8007
|
return c.add(SitePlanIssueCode.Shape, path, 'must be an object');
|
|
7862
8008
|
c.keys(raw, PAGE_KEYS, path);
|
|
7863
8009
|
c.string(raw, 'key', path);
|
|
@@ -7898,7 +8044,7 @@ function validatePages(c, list, types, sources) {
|
|
|
7898
8044
|
}
|
|
7899
8045
|
c.array(raw, 'sections', path).forEach((s, j) => {
|
|
7900
8046
|
const sp = `${path}.sections[${j}]`;
|
|
7901
|
-
if (!
|
|
8047
|
+
if (!isPlainObject(s))
|
|
7902
8048
|
return c.add(SitePlanIssueCode.Shape, sp, 'must be an object');
|
|
7903
8049
|
c.keys(s, SECTION_KEYS, sp);
|
|
7904
8050
|
const patternId = c.string(s, 'pattern', sp);
|
|
@@ -7911,7 +8057,7 @@ function validatePages(c, list, types, sources) {
|
|
|
7911
8057
|
c.add(SitePlanIssueCode.GlobalPattern, `${sp}.pattern`, `"${patternId}" is a header/footer pattern (globals)`);
|
|
7912
8058
|
const slots = s['slots'];
|
|
7913
8059
|
if (slots !== undefined) {
|
|
7914
|
-
if (!
|
|
8060
|
+
if (!isPlainObject(slots))
|
|
7915
8061
|
c.add(SitePlanIssueCode.Shape, `${sp}.slots`, 'must be an object');
|
|
7916
8062
|
else {
|
|
7917
8063
|
const declared = patternSlots(pattern);
|
|
@@ -7970,8 +8116,8 @@ function validatePages(c, list, types, sources) {
|
|
|
7970
8116
|
}
|
|
7971
8117
|
});
|
|
7972
8118
|
});
|
|
7973
|
-
c.unique(list.map(p => (
|
|
7974
|
-
c.unique(list.map(p => (
|
|
8119
|
+
c.unique(list.map(p => (isPlainObject(p) && isNonEmptyString(p['key']) ? p['key'] : null)), i => `pages[${i}].key`, 'page key');
|
|
8120
|
+
c.unique(list.map(p => (isPlainObject(p) && isNonEmptyString(p['route']) ? p['route'] : null)), i => `pages[${i}].route`, 'route');
|
|
7975
8121
|
if (homes.length !== 1)
|
|
7976
8122
|
c.add(SitePlanIssueCode.Home, 'pages', `exactly one page is the home page (found ${homes.length})`);
|
|
7977
8123
|
}
|
|
@@ -7983,7 +8129,7 @@ function nextSourceOf(sources, routeSource) {
|
|
|
7983
8129
|
return null;
|
|
7984
8130
|
}
|
|
7985
8131
|
function validateGlobals(c, globals) {
|
|
7986
|
-
if (!
|
|
8132
|
+
if (!isPlainObject(globals))
|
|
7987
8133
|
return c.add(SitePlanIssueCode.Shape, 'globals', 'must be an object');
|
|
7988
8134
|
c.keys(globals, Object.values(GlobalSlot), 'globals');
|
|
7989
8135
|
for (const slot of Object.values(GlobalSlot)) {
|
|
@@ -7998,7 +8144,7 @@ function validateGlobals(c, globals) {
|
|
|
7998
8144
|
/** Check a Site Plan against the plan shape and the pattern library. Never throws, never repairs. */
|
|
7999
8145
|
function validateSitePlan(plan) {
|
|
8000
8146
|
const c = new Collector();
|
|
8001
|
-
if (!
|
|
8147
|
+
if (!isPlainObject(plan)) {
|
|
8002
8148
|
c.add(SitePlanIssueCode.Shape, '', 'a site plan is an object');
|
|
8003
8149
|
return { valid: false, issues: c.issues };
|
|
8004
8150
|
}
|
|
@@ -9575,5 +9721,5 @@ function composeSection(patternId, input, options) {
|
|
|
9575
9721
|
* Generated bundle index. Do not edit.
|
|
9576
9722
|
*/
|
|
9577
9723
|
|
|
9578
|
-
export { BAR_ITEMS_MAX, BAR_ITEMS_MIN, BASELINE_ROLES, BaselineRole, BindScope, CardBindTarget, ComposeError, ComposeIssueCode, DANGLING_LINK_CODES, DEFAULT_PHONE_MENU_BREAKPOINT, FACT_KEYS, GlobalSlot, NAV_PART_LABELS, NAV_SHAPE_COPY, NEUTRAL_STYLE_PROPS, NODE_BASELINES, NavPagesSource, NavRole, NavShape, NavShapeError, PRICING_PATTERN, PUBLISH_BLOCKING_PLACEHOLDERS, PatternDirective, PatternGlobalPosition, PatternOpens, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, PlaceholderKind, PlanDataSourceMode, PlanDataSourceType, RelativeOp, SAMPLE_IMAGE_REF, SITE_FACT_LABELS, SITE_HEADER_PATTERN, SITE_PATTERNS, SITE_PLAN_VERSION, SITE_TEMPLATES, SPEC_SITE_FACTS, SPEC_SITE_PATTERNS, SPEC_SITE_PLAN_SHAPE, SPEC_SITE_TEMPLATES, STUDIO_TEMPLATE, SitePlanError, SitePlanIssueCode, SitePlanSourceKind, SiteTemplateError, SiteTemplateId, addBarItem, altSourceScopes, assertStyleSlots, assertValidSitePlan, barIconForRoute, blocksPublish, composeNavHeader, composeSection, composeSite, createSerializedNode, findNavRoot, moveBarItem, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, parseSampleImageRef, patternById, patternNeedsBinding, patternNodes, patternOptionalParts, patternScopes, patternSlots, patternTakesBinding, phoneMenuPages, planFromTemplate, planNavShape, releasedLayoutDefaults, removeBarItem, requiredShapeKeys, routeParams, sampleImageRef, setStyleProps, shapeKeys, siteNavPages, validateSitePlan, walkSerialized };
|
|
9724
|
+
export { BAR_ITEMS_MAX, BAR_ITEMS_MIN, BASELINE_ROLES, BaselineRole, BindScope, CardBindTarget, ComposeError, ComposeIssueCode, DANGLING_LINK_CODES, DEFAULT_PHONE_MENU_BREAKPOINT, FACT_KEYS, GlobalSlot, NAV_PART_LABELS, NAV_SHAPE_COPY, NEUTRAL_STYLE_PROPS, NODE_BASELINES, NavPagesSource, NavRole, NavShape, NavShapeError, PRICING_PATTERN, PUBLISH_BLOCKING_PLACEHOLDERS, PathIssueCollector, PatternDirective, PatternGlobalPosition, PatternOpens, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, PlaceholderKind, PlanDataSourceMode, PlanDataSourceType, RelativeOp, SAMPLE_IMAGE_REF, SITE_FACT_LABELS, SITE_HEADER_PATTERN, SITE_PATTERNS, SITE_PLAN_VERSION, SITE_TEMPLATES, SPEC_SITE_FACTS, SPEC_SITE_LIBRARY, SPEC_SITE_PATTERNS, SPEC_SITE_PLAN_SHAPE, SPEC_SITE_TEMPLATES, STUDIO_TEMPLATE, SitePlanError, SitePlanIssueCode, SitePlanSourceKind, SiteTemplateError, SiteTemplateId, addBarItem, altSourceScopes, assertStyleSlots, assertValidSitePlan, barIconForRoute, blocksPublish, composeNavHeader, composeSection, composeSite, createSerializedNode, findNavRoot, isNonEmptyString, isPlainObject, moveBarItem, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, parseSampleImageRef, pathAt, patternById, patternNeedsBinding, patternNodes, patternOptionalParts, patternScopes, patternSlots, patternTakesBinding, phoneMenuPages, planFromTemplate, planNavShape, releasedLayoutDefaults, removeBarItem, requiredShapeKeys, routeParams, sampleImageRef, setStyleProps, shapeKeys, siteNavPages, validateSitePlan, walkSerialized };
|
|
9579
9725
|
//# sourceMappingURL=vectoriox-iox-ui-generation-core.mjs.map
|