@vectoriox/iox-ui 5.58.1 → 5.59.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.
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs +25 -2
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-harness-core.mjs +2 -1
- package/fesm2022/vectoriox-iox-ui-harness-core.mjs.map +1 -1
- package/generation-core/index.d.ts +11 -2
- package/package.json +1 -1
- package/src/generation-core/site-plan-schema.ts +2 -2
- package/src/generation-core/site-plan.model.ts +7 -1
- package/src/generation-core/site-spec.generated.ts +18 -0
- package/src/generation-core/validate-site-plan.ts +5 -1
- package/src/harness-core/intake.ts +2 -1
|
@@ -93,6 +93,7 @@ declare const SPEC_SITE_PLAN_SHAPE: {
|
|
|
93
93
|
readonly "required?": "boolean — a template page the wizard's Pages step cannot leave out";
|
|
94
94
|
readonly "inNav?": "boolean — a Link in the header and footer navigation, in plan order";
|
|
95
95
|
readonly "archetype?": "string — site.archetypes: the kind of page; its sections must fill its required slots from the families it allows";
|
|
96
|
+
readonly "need?": "string — site.needIds (= harness.needs): the inferred need this page answers — the Plan screen tags it \"we added\"";
|
|
96
97
|
readonly "template?": "string — the content type a template page renders one item of";
|
|
97
98
|
readonly "routeSource?": "string — the single source read by the route param (route.* binds it)";
|
|
98
99
|
readonly "seo?": "pageSeo";
|
|
@@ -152,6 +153,7 @@ declare const SPEC_SITE_DENSITY_COPY: {
|
|
|
152
153
|
readonly regular: "standard";
|
|
153
154
|
readonly airy: "standard";
|
|
154
155
|
};
|
|
156
|
+
declare const SPEC_SITE_NEED_IDS: readonly ["collection", "detail", "services", "prices", "menu", "visit", "team", "about", "faq", "blog", "gallery", "booking-request", "sign-up-form", "contact"];
|
|
155
157
|
declare const SPEC_SITE_ARCHETYPES: {
|
|
156
158
|
readonly home: {
|
|
157
159
|
readonly label: "Home";
|
|
@@ -4445,6 +4447,9 @@ interface PageArchetype {
|
|
|
4445
4447
|
readonly slots: ReadonlyArray<PageArchetypeSlot>;
|
|
4446
4448
|
}
|
|
4447
4449
|
declare const PAGE_ARCHETYPES: Readonly<Record<string, PageArchetype>>;
|
|
4450
|
+
/** What a business may need (contract `site.needIds`, derived from the harness's ONE list — harness-core `NEEDS`). */
|
|
4451
|
+
type SiteNeedId = (typeof SPEC_SITE_NEED_IDS)[number];
|
|
4452
|
+
declare const SITE_NEED_IDS: ReadonlyArray<SiteNeedId>;
|
|
4448
4453
|
interface PagePlan {
|
|
4449
4454
|
readonly key: string;
|
|
4450
4455
|
readonly name: string;
|
|
@@ -4460,6 +4465,8 @@ interface PagePlan {
|
|
|
4460
4465
|
readonly routeSource?: string;
|
|
4461
4466
|
/** The kind of page (`PAGE_ARCHETYPES`): its sections fill the type's required slots from the families it allows. */
|
|
4462
4467
|
readonly archetype?: PageArchetypeId;
|
|
4468
|
+
/** The inferred need this page answers (the Plan screen tags it "we added") — a harness-core need id. */
|
|
4469
|
+
readonly need?: SiteNeedId;
|
|
4463
4470
|
readonly seo?: PageSeoPlan;
|
|
4464
4471
|
readonly sections: ReadonlyArray<PageSectionPlan>;
|
|
4465
4472
|
}
|
|
@@ -5079,6 +5086,8 @@ declare enum SitePlanIssueCode {
|
|
|
5079
5086
|
InvalidLocale = "invalid-locale",
|
|
5080
5087
|
/** A page's SEO words are longer than a search result shows (seo-core limits). */
|
|
5081
5088
|
InvalidSeo = "invalid-seo",
|
|
5089
|
+
/** A page names a need the harness does not have. */
|
|
5090
|
+
UnknownNeed = "unknown-need",
|
|
5082
5091
|
/** A page key that is a global slot's name (`header`, `footer`): its sections' ids would be the global's. */
|
|
5083
5092
|
ReservedPageKey = "reserved-page-key"
|
|
5084
5093
|
}
|
|
@@ -6368,5 +6377,5 @@ declare function addStockCredits(footer: SerializedNode, credits: ReadonlyArray<
|
|
|
6368
6377
|
url: string;
|
|
6369
6378
|
}>): number;
|
|
6370
6379
|
|
|
6371
|
-
export { ACTIVE_BUILD_STATUSES, AI_REFUSAL_NEXT, AI_REFUSAL_STATUS, AI_STEPS, AI_STEP_LABELS, AI_STEP_NEEDS, 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, 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_SHAPE, PLAN_EDITS_SCHEMA_NAME, PLAN_EDIT_SHAPE, PRICING_PATTERN, PUBLISH_BLOCKING_PLACEHOLDERS, PageDataKind, PathIssueCollector, PatternDirective, PatternGlobalPosition, PatternOpens, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, PlaceholderKind, PlanChangeAction, PlanChangeKind, PlanDataSourceMode, PlanDataSourceType, PlanEditIssueCode, PlanEditOp, PlanEditsOutcome, PlanWordIssueCode, PreflightRefusalCode, PublishRefusalCode, REQUIRED_CONTENT_ROLES, RelativeOp, SAMPLE_IMAGE_REF, SITE_CHECKS, SITE_FACT_LABELS, SITE_HEADER_PATTERN, SITE_LIBRARY, SITE_LOCALES, SITE_PATTERNS, SITE_PLAN_SCHEMA_NAME, 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_PATTERNS, SPEC_SITE_PLAN_SHAPE, SPEC_SITE_REQUIRED_ROLES, SPEC_SITE_ROLES, SPEC_SITE_TEMPLATES, STOCK_FAMILIES, STUDIO_TEMPLATE, SiteBuildKind, SiteBuildStatus, SiteCheckId, SiteFindingCode, SiteLocale, SitePlanError, SitePlanIssueCode, SitePlanSourceKind, SitePlanWireKey, SiteTemplateError, SiteTemplateId, StepState, StockProviderId, addBarItem, addStockCredits, applyPlanEdits, applyStockPhotos, archetypeIssues, assertStyleSlots, assertValidSitePlan, auditSite, barIconForRoute, blocksPublish, buildKeys, buildStepFacts, builtHomePageId, composeNavHeader, composeSection, composeSite, contentTypeFromWire, contentTypeJsonSchema, contentTypePreviewFields, copyLengthOf, costUsd, createSerializedNode, creditsOfUsd, dataSourceJsonSchema, describePlanData, describeShapeKey, entranceAction, entranceInteraction, estimateStepCredits, failedBuildStep, fieldJsonSchema, findNavRoot, isActiveBuild, isNonEmptyString, isPlainObject, isRtlLocale, jsonAnyOf, jsonBoolean, jsonClosedObject, jsonInteger, jsonListOf, jsonOneOf, jsonSchemaKeywords, jsonSchemaObjects, jsonShapedObject, jsonText, modelCanDo, moveBarItem, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, pageJsonSchema, parsePatternPath, parseSampleImageRef, pathAt, patternById, patternHasForm, patternLinkSlots, patternManifest, patternNeedsBinding, patternNodes, patternOptionalParts, patternRoleNeeds, patternScopes, patternSlotBudgets, patternSlots, patternTakesBinding, phoneMenuPages, planEditsFromWire, planEditsJsonSchema, planEntrances, planFromTemplate, planNavShape, planStockPhotos, planWordIssues, publishRefusal, publishVerdict, releasedLayoutDefaults, removeBarItem, requiredAcknowledgements, requiredShapeKeys, roleField, routeMatches, routeParams, sampleImageRef, sectionEntrances, sectionFromWire, sectionJsonSchema, sectionPatternIds, setStyleProps, shapeKeys, showcaseGlobals, showcasePages, showcasePlans, siteNavPages, sitePlanFromWire, sitePlanJsonSchema, sitePlanToWire, slotBudget, stockCopyKey, stockCreditLines, stockCreditNode, stockCreditNodeId, stockSlots, validatePlanEdits, validateSitePlan, walkSerialized, wordPattern, writtenTexts };
|
|
6372
|
-
export type { AddBarItemResult, AiEntitlementsView, AiMeter, AiModelEntry, AiRefusal, AiTokenCounts, AiTokenPrice, AuditPage, AuditPlaceholder, BarItemsEditResult, BuildNotice, BuildStepError, BuildStepFacts, BuildStepRecord, CmsDataSourcePlan, ComposeContext, ComposeIssue, ComposedDataSource, ComposedItem, ComposedNavHeader, ComposedPage, ComposedPlaceholder, ComposedRoute, ComposedSection, ComposedSite, ContentFieldPlan, ContentRoles, ContentSeedPlan, ContentTypePlan, CreateNodeOptions, CreatedRecord, DataSourcePlan, DynamicKeysAsList, EntranceAction, EntranceActionOptions, EntranceInteraction, EntranceMark, EntranceSpec, EntranceStamp, FactKey, JsonSchema, NavHeaderInput, NavHeaderOptions, NavPage, NavShapeOptions, NavShapeResult, NodeBaseline, PageArchetype, PageArchetypeId, PageArchetypeSlot, PageData, PageDataLine, PagePlan, PageSectionPlan, PageSeoPlan, PathIssue, PatternManifestEntry, PatternNode, PatternPath, PatternRoleNeed, PlainObject, PlanChange, PlanEdit, PlanEditIssue, PlanEditResult, PlanEditsAnswer, PlanEntrancesInput, PlanWordContext, PlanWordIssue, PreflightRefusal, PublishRefusal, RelativeDataSourcePlan, SectionEntrances, SectionInput, SectionOptions, SerializedBinding, SerializedNode, SerializedResponsive, ShapeEntry, ShapeIssueCodes, ShowcaseInput, SiteAudit, SiteAuditOptions, SiteAuditSnapshot, SiteBuildRun, SiteBusiness, SiteCheck, SiteFinding, SitePageRef, SitePattern, SitePlan, SitePlanIssue, SitePlanSchemaPin, SitePlanSource, SitePlanValidation, SiteTemplate, StockCredit, StockPhoto, StockPlacement, StockSlot, TemplatePlanInput, UndoKept, UndoPreview, UndoRecord, WrittenText };
|
|
6380
|
+
export { ACTIVE_BUILD_STATUSES, AI_REFUSAL_NEXT, AI_REFUSAL_STATUS, AI_STEPS, AI_STEP_LABELS, AI_STEP_NEEDS, 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, 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_SHAPE, PLAN_EDITS_SCHEMA_NAME, PLAN_EDIT_SHAPE, PRICING_PATTERN, PUBLISH_BLOCKING_PLACEHOLDERS, PageDataKind, PathIssueCollector, PatternDirective, PatternGlobalPosition, PatternOpens, PatternPlaceholder, PatternRecipe, PhoneMenuBreakpoint, PlaceholderKind, PlanChangeAction, PlanChangeKind, PlanDataSourceMode, PlanDataSourceType, PlanEditIssueCode, PlanEditOp, PlanEditsOutcome, 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_SCHEMA_NAME, 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, STUDIO_TEMPLATE, SiteBuildKind, SiteBuildStatus, SiteCheckId, SiteFindingCode, SiteLocale, SitePlanError, SitePlanIssueCode, SitePlanSourceKind, SitePlanWireKey, SiteTemplateError, SiteTemplateId, StepState, StockProviderId, addBarItem, addStockCredits, applyPlanEdits, applyStockPhotos, archetypeIssues, assertStyleSlots, assertValidSitePlan, auditSite, barIconForRoute, blocksPublish, buildKeys, buildStepFacts, builtHomePageId, composeNavHeader, composeSection, composeSite, contentTypeFromWire, contentTypeJsonSchema, contentTypePreviewFields, copyLengthOf, costUsd, createSerializedNode, creditsOfUsd, dataSourceJsonSchema, describePlanData, describeShapeKey, entranceAction, entranceInteraction, estimateStepCredits, failedBuildStep, fieldJsonSchema, findNavRoot, isActiveBuild, isNonEmptyString, isPlainObject, isRtlLocale, jsonAnyOf, jsonBoolean, jsonClosedObject, jsonInteger, jsonListOf, jsonOneOf, jsonSchemaKeywords, jsonSchemaObjects, jsonShapedObject, jsonText, modelCanDo, moveBarItem, navPages, navShapeBreakpoint, navShapeOf, nextSourceOf, nodeBindPaths, pageJsonSchema, parsePatternPath, parseSampleImageRef, pathAt, patternById, patternHasForm, patternLinkSlots, patternManifest, patternNeedsBinding, patternNodes, patternOptionalParts, patternRoleNeeds, patternScopes, patternSlotBudgets, patternSlots, patternTakesBinding, phoneMenuPages, planEditsFromWire, planEditsJsonSchema, planEntrances, planFromTemplate, planNavShape, planStockPhotos, planWordIssues, publishRefusal, publishVerdict, releasedLayoutDefaults, removeBarItem, requiredAcknowledgements, requiredShapeKeys, roleField, routeMatches, routeParams, sampleImageRef, sectionEntrances, sectionFromWire, sectionJsonSchema, sectionPatternIds, setStyleProps, shapeKeys, showcaseGlobals, showcasePages, showcasePlans, siteNavPages, sitePlanFromWire, sitePlanJsonSchema, sitePlanToWire, slotBudget, stockCopyKey, stockCreditLines, stockCreditNode, stockCreditNodeId, stockSlots, validatePlanEdits, validateSitePlan, walkSerialized, wordPattern, writtenTexts };
|
|
6381
|
+
export type { AddBarItemResult, AiEntitlementsView, AiMeter, AiModelEntry, AiRefusal, AiTokenCounts, AiTokenPrice, AuditPage, AuditPlaceholder, BarItemsEditResult, BuildNotice, BuildStepError, BuildStepFacts, BuildStepRecord, CmsDataSourcePlan, ComposeContext, ComposeIssue, ComposedDataSource, ComposedItem, ComposedNavHeader, ComposedPage, ComposedPlaceholder, ComposedRoute, ComposedSection, ComposedSite, ContentFieldPlan, ContentRoles, ContentSeedPlan, ContentTypePlan, CreateNodeOptions, CreatedRecord, DataSourcePlan, DynamicKeysAsList, EntranceAction, EntranceActionOptions, EntranceInteraction, EntranceMark, EntranceSpec, EntranceStamp, FactKey, JsonSchema, NavHeaderInput, NavHeaderOptions, NavPage, NavShapeOptions, NavShapeResult, NodeBaseline, PageArchetype, PageArchetypeId, PageArchetypeSlot, PageData, PageDataLine, PagePlan, PageSectionPlan, PageSeoPlan, PathIssue, PatternManifestEntry, PatternNode, PatternPath, PatternRoleNeed, PlainObject, PlanChange, PlanEdit, PlanEditIssue, PlanEditResult, PlanEditsAnswer, PlanEntrancesInput, PlanWordContext, PlanWordIssue, PreflightRefusal, PublishRefusal, RelativeDataSourcePlan, SectionEntrances, SectionInput, SectionOptions, SerializedBinding, SerializedNode, SerializedResponsive, ShapeEntry, ShapeIssueCodes, ShowcaseInput, SiteAudit, SiteAuditOptions, SiteAuditSnapshot, SiteBuildRun, SiteBusiness, SiteCheck, SiteFinding, SiteNeedId, SitePageRef, SitePattern, SitePlan, SitePlanIssue, SitePlanSchemaPin, SitePlanSource, SitePlanValidation, SiteTemplate, StockCredit, StockPhoto, StockPlacement, StockSlot, TemplatePlanInput, UndoKept, UndoPreview, UndoRecord, WrittenText };
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
patternHasForm, patternLinkSlots, patternOptionalParts, patternSlots, patternTakesBinding, PatternGlobalPosition, SITE_PATTERNS, SitePattern,
|
|
9
9
|
} from './patterns';
|
|
10
10
|
import {
|
|
11
|
-
FACT_KEYS, GlobalSlot, PAGE_ARCHETYPES, PlanDataSourceMode, PlanDataSourceType, RelativeOp, SitePlan, SitePlanSource, SitePlanSourceKind, SITE_LOCALES,
|
|
11
|
+
FACT_KEYS, GlobalSlot, PAGE_ARCHETYPES, SITE_NEED_IDS, PlanDataSourceMode, PlanDataSourceType, RelativeOp, SitePlan, SitePlanSource, SitePlanSourceKind, SITE_LOCALES,
|
|
12
12
|
SITE_PLAN_VERSION,
|
|
13
13
|
} from './site-plan.model';
|
|
14
14
|
import { SPEC_SITE_PLAN_SHAPE } from './site-spec.generated';
|
|
@@ -151,7 +151,7 @@ export function pageJsonSchema(): JsonSchema {
|
|
|
151
151
|
const seo = jsonShapedObject(SHAPE['pageSeo'], { title: jsonText(), description: jsonText() }, 'pageSeo');
|
|
152
152
|
return jsonShapedObject(SHAPE['page'], {
|
|
153
153
|
key: jsonText(), name: jsonText(), route: jsonText(), isHome: jsonBoolean(), required: jsonBoolean(), inNav: jsonBoolean(),
|
|
154
|
-
archetype: jsonOneOf(Object.keys(PAGE_ARCHETYPES)), template: jsonText(), routeSource: jsonText(), seo, sections: jsonListOf(sectionJsonSchema()),
|
|
154
|
+
archetype: jsonOneOf(Object.keys(PAGE_ARCHETYPES)), need: jsonOneOf(SITE_NEED_IDS), template: jsonText(), routeSource: jsonText(), seo, sections: jsonListOf(sectionJsonSchema()),
|
|
155
155
|
}, 'page');
|
|
156
156
|
}
|
|
157
157
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AnimateId, DesignChoices } from '@vectoriox/iox-ui/design-core';
|
|
2
2
|
|
|
3
|
-
import { SPEC_SITE_ARCHETYPES, SPEC_SITE_FACTS, SPEC_SITE_LOCALES, SPEC_SITE_REQUIRED_ROLES, SPEC_SITE_ROLES } from './site-spec.generated';
|
|
3
|
+
import { SPEC_SITE_ARCHETYPES, SPEC_SITE_FACTS, SPEC_SITE_LOCALES, SPEC_SITE_NEED_IDS, SPEC_SITE_REQUIRED_ROLES, SPEC_SITE_ROLES } from './site-spec.generated';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* The Site Plan (contract `site.planShape`, `SPEC_SITE_PLAN_SHAPE`: every key typed and explained, and the
|
|
@@ -157,6 +157,10 @@ export interface PageArchetype {
|
|
|
157
157
|
}
|
|
158
158
|
export const PAGE_ARCHETYPES: Readonly<Record<string, PageArchetype>> = SPEC_SITE_ARCHETYPES;
|
|
159
159
|
|
|
160
|
+
/** What a business may need (contract `site.needIds`, derived from the harness's ONE list — harness-core `NEEDS`). */
|
|
161
|
+
export type SiteNeedId = (typeof SPEC_SITE_NEED_IDS)[number];
|
|
162
|
+
export const SITE_NEED_IDS: ReadonlyArray<SiteNeedId> = SPEC_SITE_NEED_IDS;
|
|
163
|
+
|
|
160
164
|
export interface PagePlan {
|
|
161
165
|
readonly key: string;
|
|
162
166
|
readonly name: string;
|
|
@@ -172,6 +176,8 @@ export interface PagePlan {
|
|
|
172
176
|
readonly routeSource?: string;
|
|
173
177
|
/** The kind of page (`PAGE_ARCHETYPES`): its sections fill the type's required slots from the families it allows. */
|
|
174
178
|
readonly archetype?: PageArchetypeId;
|
|
179
|
+
/** The inferred need this page answers (the Plan screen tags it "we added") — a harness-core need id. */
|
|
180
|
+
readonly need?: SiteNeedId;
|
|
175
181
|
readonly seo?: PageSeoPlan;
|
|
176
182
|
readonly sections: ReadonlyArray<PageSectionPlan>;
|
|
177
183
|
}
|
|
@@ -94,6 +94,7 @@ export const SPEC_SITE_PLAN_SHAPE = {
|
|
|
94
94
|
"required?": "boolean — a template page the wizard's Pages step cannot leave out",
|
|
95
95
|
"inNav?": "boolean — a Link in the header and footer navigation, in plan order",
|
|
96
96
|
"archetype?": "string — site.archetypes: the kind of page; its sections must fill its required slots from the families it allows",
|
|
97
|
+
"need?": "string — site.needIds (= harness.needs): the inferred need this page answers — the Plan screen tags it \"we added\"",
|
|
97
98
|
"template?": "string — the content type a template page renders one item of",
|
|
98
99
|
"routeSource?": "string — the single source read by the route param (route.* binds it)",
|
|
99
100
|
"seo?": "pageSeo",
|
|
@@ -162,6 +163,23 @@ export const SPEC_SITE_DENSITY_COPY = {
|
|
|
162
163
|
"airy": "standard"
|
|
163
164
|
} as const;
|
|
164
165
|
|
|
166
|
+
export const SPEC_SITE_NEED_IDS = [
|
|
167
|
+
"collection",
|
|
168
|
+
"detail",
|
|
169
|
+
"services",
|
|
170
|
+
"prices",
|
|
171
|
+
"menu",
|
|
172
|
+
"visit",
|
|
173
|
+
"team",
|
|
174
|
+
"about",
|
|
175
|
+
"faq",
|
|
176
|
+
"blog",
|
|
177
|
+
"gallery",
|
|
178
|
+
"booking-request",
|
|
179
|
+
"sign-up-form",
|
|
180
|
+
"contact"
|
|
181
|
+
] as const;
|
|
182
|
+
|
|
165
183
|
export const SPEC_SITE_ARCHETYPES = {
|
|
166
184
|
"home": {
|
|
167
185
|
"label": "Home",
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
patternSlots, PatternGlobalPosition, slotBudget,
|
|
8
8
|
} from './patterns';
|
|
9
9
|
import {
|
|
10
|
-
FACT_KEYS, GlobalSlot, PAGE_ARCHETYPES, PlanDataSourceMode, PlanDataSourceType, RelativeOp, REQUIRED_CONTENT_ROLES, SitePlan, SitePlanSourceKind,
|
|
10
|
+
FACT_KEYS, GlobalSlot, PAGE_ARCHETYPES, SITE_NEED_IDS, PlanDataSourceMode, PlanDataSourceType, RelativeOp, REQUIRED_CONTENT_ROLES, SitePlan, SitePlanSourceKind,
|
|
11
11
|
SITE_LOCALES, SITE_PLAN_VERSION,
|
|
12
12
|
} from './site-plan.model';
|
|
13
13
|
import { SPEC_SITE_PLAN_SHAPE } from './site-spec.generated';
|
|
@@ -65,6 +65,8 @@ export enum SitePlanIssueCode {
|
|
|
65
65
|
InvalidLocale = 'invalid-locale',
|
|
66
66
|
/** A page's SEO words are longer than a search result shows (seo-core limits). */
|
|
67
67
|
InvalidSeo = 'invalid-seo',
|
|
68
|
+
/** A page names a need the harness does not have. */
|
|
69
|
+
UnknownNeed = 'unknown-need',
|
|
68
70
|
/** A page key that is a global slot's name (`header`, `footer`): its sections' ids would be the global's. */
|
|
69
71
|
ReservedPageKey = 'reserved-page-key',
|
|
70
72
|
}
|
|
@@ -335,6 +337,8 @@ function validatePages(c: Collector, list: unknown[], types: Map<string, Content
|
|
|
335
337
|
const archetype = c.string(raw, 'archetype', path, false);
|
|
336
338
|
if (archetype && !has(PAGE_ARCHETYPES, archetype)) c.add(SitePlanIssueCode.Archetype, `${path}.archetype`, `"${archetype}" is not a page type (${Object.keys(PAGE_ARCHETYPES).join(', ')})`);
|
|
337
339
|
validatePageSeo(c, raw['seo'], `${path}.seo`);
|
|
340
|
+
const need = c.string(raw, 'need', path, false);
|
|
341
|
+
if (need && !(SITE_NEED_IDS as ReadonlyArray<string>).includes(need)) c.add(SitePlanIssueCode.UnknownNeed, `${path}.need`, `"${need}" is not a need (${SITE_NEED_IDS.join(', ')})`);
|
|
338
342
|
|
|
339
343
|
c.array(raw, 'sections', path).forEach((s, j) => {
|
|
340
344
|
const sp = `${path}.sections[${j}]`;
|
|
@@ -50,7 +50,8 @@ export function matchBusinessType(text: string, types: ReadonlyArray<BusinessTyp
|
|
|
50
50
|
return matchBusinessTypes(text, types)[0]?.id ?? null;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
// A port stays with its host ("staging.example:8080"): dropping it would read a DIFFERENT site.
|
|
54
|
+
const ADDRESS_RE = /(?:https?:\/\/)?(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z]{2,}(?::\d{1,5})?(?:\/[^\s<>"']*)?/gi;
|
|
54
55
|
const TRAILING = /[.,;:!?)\]}'"״׳]+$/;
|
|
55
56
|
|
|
56
57
|
/** An address as a chip shows it: no scheme, no `www.`, no trailing punctuation or slash, lower-case host. */
|