@vectoriox/iox-ui 5.58.0 → 5.59.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 +27 -3
- package/fesm2022/vectoriox-iox-ui-generation-core.mjs.map +1 -1
- package/fesm2022/vectoriox-iox-ui-harness-core.mjs +2 -4
- package/fesm2022/vectoriox-iox-ui-harness-core.mjs.map +1 -1
- package/generation-core/index.d.ts +14 -2
- package/package.json +1 -1
- package/src/generation-core/plan-words.ts +3 -2
- 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 +3 -4
|
@@ -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
|
}
|
|
@@ -6130,6 +6139,9 @@ interface WrittenText {
|
|
|
6130
6139
|
}
|
|
6131
6140
|
/** Every text in a plan a model writes (never ids, routes, field names or pattern ids). */
|
|
6132
6141
|
declare function writtenTexts(plan: SitePlan): WrittenText[];
|
|
6142
|
+
/** Hebrew joins up to two one-letter words (and, the, in, to, from, that, as) to the next: "והטוב" holds "טוב". The
|
|
6143
|
+
* ONE rule — the intake's keyword match (harness-core) uses it too. */
|
|
6144
|
+
declare const HEBREW_PREFIXES = "[\u05D5\u05D4\u05D1\u05DC\u05DE\u05E9\u05DB]{0,2}";
|
|
6133
6145
|
/** A word (or phrase) as a whole-word pattern; Hebrew allows its one-letter prefixes. */
|
|
6134
6146
|
declare function wordPattern(word: string): RegExp;
|
|
6135
6147
|
/** The words to avoid and the facts never given, in every written text of the plan. */
|
|
@@ -6365,5 +6377,5 @@ declare function addStockCredits(footer: SerializedNode, credits: ReadonlyArray<
|
|
|
6365
6377
|
url: string;
|
|
6366
6378
|
}>): number;
|
|
6367
6379
|
|
|
6368
|
-
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, 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 };
|
|
6369
|
-
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
|
@@ -54,8 +54,9 @@ export function writtenTexts(plan: SitePlan): WrittenText[] {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
const HEBREW = /[-]/;
|
|
57
|
-
/** Hebrew joins up to two one-letter words (and, the, in, to, from, that, as) to the next: "והטוב" holds "טוב".
|
|
58
|
-
|
|
57
|
+
/** Hebrew joins up to two one-letter words (and, the, in, to, from, that, as) to the next: "והטוב" holds "טוב". The
|
|
58
|
+
* ONE rule — the intake's keyword match (harness-core) uses it too. */
|
|
59
|
+
export const HEBREW_PREFIXES = '[והבלמשכ]{0,2}';
|
|
59
60
|
const escape = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
60
61
|
const normalise = (s: string) => s.normalize('NFKC').toLowerCase();
|
|
61
62
|
|
|
@@ -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}]`;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { HEBREW_PREFIXES } from '@vectoriox/iox-ui/generation-core';
|
|
2
|
+
|
|
1
3
|
import { BUSINESS_TYPES, BusinessType } from './business-types';
|
|
2
4
|
|
|
3
5
|
/**
|
|
@@ -7,9 +9,6 @@ import { BUSINESS_TYPES, BusinessType } from './business-types';
|
|
|
7
9
|
* the reading stage (M1-1) checks the model against the same match.
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
|
-
/** A single Hebrew letter that prefixes a word (the, in, to, and, from, that, as) — "בסדנאות" holds "סדנ". */
|
|
11
|
-
const HEBREW_PREFIX = '[הבלומשכ]?';
|
|
12
|
-
|
|
13
12
|
const escapeRe = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
14
13
|
|
|
15
14
|
const KEYWORD_RES = new Map<string, RegExp>();
|
|
@@ -18,7 +17,7 @@ const KEYWORD_RES = new Map<string, RegExp>();
|
|
|
18
17
|
function keywordRe(keyword: string): RegExp {
|
|
19
18
|
let re = KEYWORD_RES.get(keyword);
|
|
20
19
|
if (!re) {
|
|
21
|
-
re = new RegExp(`(^|[^\\p{L}\\p{N}])${
|
|
20
|
+
re = new RegExp(`(^|[^\\p{L}\\p{N}])${HEBREW_PREFIXES}${escapeRe(keyword.toLocaleLowerCase())}`, 'u');
|
|
22
21
|
KEYWORD_RES.set(keyword, re);
|
|
23
22
|
}
|
|
24
23
|
return re;
|