@kerusiweb/core 2.0.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/LICENSE +22 -0
- package/README.md +68 -0
- package/dist/kerusi/index.d.ts +19 -0
- package/dist/kerusi/index.d.ts.map +1 -0
- package/dist/kerusi/index.js +19 -0
- package/dist/kerusi/index.js.map +1 -0
- package/dist/kerusi/kerusi-layout-mode.d.ts +58 -0
- package/dist/kerusi/kerusi-layout-mode.d.ts.map +1 -0
- package/dist/kerusi/kerusi-layout-mode.js +117 -0
- package/dist/kerusi/kerusi-layout-mode.js.map +1 -0
- package/dist/kerusi/kerusi-locale.d.ts +43 -0
- package/dist/kerusi/kerusi-locale.d.ts.map +1 -0
- package/dist/kerusi/kerusi-locale.js +111 -0
- package/dist/kerusi/kerusi-locale.js.map +1 -0
- package/dist/kerusi/kerusi-map.model.d.ts +258 -0
- package/dist/kerusi/kerusi-map.model.d.ts.map +1 -0
- package/dist/kerusi/kerusi-map.model.js +11 -0
- package/dist/kerusi/kerusi-map.model.js.map +1 -0
- package/dist/kerusi/kerusi-price.d.ts +22 -0
- package/dist/kerusi/kerusi-price.d.ts.map +1 -0
- package/dist/kerusi/kerusi-price.js +48 -0
- package/dist/kerusi/kerusi-price.js.map +1 -0
- package/dist/kerusi/kerusi-rows.d.ts +25 -0
- package/dist/kerusi/kerusi-rows.d.ts.map +1 -0
- package/dist/kerusi/kerusi-rows.js +36 -0
- package/dist/kerusi/kerusi-rows.js.map +1 -0
- package/dist/kerusi/kerusi-state.d.ts +85 -0
- package/dist/kerusi/kerusi-state.d.ts.map +1 -0
- package/dist/kerusi/kerusi-state.js +117 -0
- package/dist/kerusi/kerusi-state.js.map +1 -0
- package/dist/kerusi/kerusi-state.model.d.ts +79 -0
- package/dist/kerusi/kerusi-state.model.d.ts.map +1 -0
- package/dist/kerusi/kerusi-state.model.js +7 -0
- package/dist/kerusi/kerusi-state.model.js.map +1 -0
- package/dist/kerusi/kerusi-validator.d.ts +96 -0
- package/dist/kerusi/kerusi-validator.d.ts.map +1 -0
- package/dist/kerusi/kerusi-validator.js +525 -0
- package/dist/kerusi/kerusi-validator.js.map +1 -0
- package/dist/kerusi/kerusi-violation.d.ts +36 -0
- package/dist/kerusi/kerusi-violation.d.ts.map +1 -0
- package/dist/kerusi/kerusi-violation.js +13 -0
- package/dist/kerusi/kerusi-violation.js.map +1 -0
- package/dist/public-api.d.ts +4 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +13 -0
- package/dist/public-api.js.map +1 -0
- package/dist/render/build-render-model.d.ts +36 -0
- package/dist/render/build-render-model.d.ts.map +1 -0
- package/dist/render/build-render-model.js +258 -0
- package/dist/render/build-render-model.js.map +1 -0
- package/dist/render/element-shapes.d.ts +34 -0
- package/dist/render/element-shapes.d.ts.map +1 -0
- package/dist/render/element-shapes.js +41 -0
- package/dist/render/element-shapes.js.map +1 -0
- package/dist/render/index.d.ts +14 -0
- package/dist/render/index.d.ts.map +1 -0
- package/dist/render/index.js +14 -0
- package/dist/render/index.js.map +1 -0
- package/dist/render/navigation-order.d.ts +49 -0
- package/dist/render/navigation-order.d.ts.map +1 -0
- package/dist/render/navigation-order.js +109 -0
- package/dist/render/navigation-order.js.map +1 -0
- package/dist/render/render-model.d.ts +151 -0
- package/dist/render/render-model.d.ts.map +1 -0
- package/dist/render/render-model.js +2 -0
- package/dist/render/render-model.js.map +1 -0
- package/dist/render/seat-shapes.d.ts +72 -0
- package/dist/render/seat-shapes.d.ts.map +1 -0
- package/dist/render/seat-shapes.js +161 -0
- package/dist/render/seat-shapes.js.map +1 -0
- package/dist/render/section-layout.d.ts +66 -0
- package/dist/render/section-layout.d.ts.map +1 -0
- package/dist/render/section-layout.js +173 -0
- package/dist/render/section-layout.js.map +1 -0
- package/dist/view/index.d.ts +12 -0
- package/dist/view/index.d.ts.map +1 -0
- package/dist/view/index.js +12 -0
- package/dist/view/index.js.map +1 -0
- package/dist/view/kerusi-seatmap-colors.d.ts +176 -0
- package/dist/view/kerusi-seatmap-colors.d.ts.map +1 -0
- package/dist/view/kerusi-seatmap-colors.js +215 -0
- package/dist/view/kerusi-seatmap-colors.js.map +1 -0
- package/dist/view/rtl.d.ts +17 -0
- package/dist/view/rtl.d.ts.map +1 -0
- package/dist/view/rtl.js +29 -0
- package/dist/view/rtl.js.map +1 -0
- package/dist/view/seat-aria.d.ts +44 -0
- package/dist/view/seat-aria.d.ts.map +1 -0
- package/dist/view/seat-aria.js +103 -0
- package/dist/view/seat-aria.js.map +1 -0
- package/dist/view/selection.d.ts +84 -0
- package/dist/view/selection.d.ts.map +1 -0
- package/dist/view/selection.js +98 -0
- package/dist/view/selection.js.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
import { resolveSeatPrice } from './kerusi-price.js';
|
|
2
|
+
import { checkSectionLayout, hasAnyCoordinate, hasCol, hasXY, resolveSectionLayoutMode, } from './kerusi-layout-mode.js';
|
|
3
|
+
import { rowOrderIndexes } from './kerusi-rows.js';
|
|
4
|
+
import { error, errorsOf, warning } from './kerusi-violation.js';
|
|
5
|
+
export { errorsOf } from './kerusi-violation.js';
|
|
6
|
+
/** The spec major version this library implements. */
|
|
7
|
+
const SUPPORTED_MAJOR = 1;
|
|
8
|
+
/** Valid `transferArmrest` values (§4.3.4). */
|
|
9
|
+
const TRANSFER_ARMREST = new Set(['left', 'right', 'both', 'fixed', 'none']);
|
|
10
|
+
/**
|
|
11
|
+
* Thrown when a Kerusi document violates a MUST-level rule in the standard.
|
|
12
|
+
* The message names the failing rule and the id that triggered it, so a
|
|
13
|
+
* malformed document is diagnosable rather than surfacing as a generic parse
|
|
14
|
+
* error (spec §4.6, §7).
|
|
15
|
+
*
|
|
16
|
+
* `violations` carries every finding from the same pass, not just the one that
|
|
17
|
+
* was thrown — useful when reporting a document's problems all at once. Use the
|
|
18
|
+
* non-throwing `checkKerusi*` functions when that is the primary goal.
|
|
19
|
+
*/
|
|
20
|
+
export class KerusiValidationError extends Error {
|
|
21
|
+
rule;
|
|
22
|
+
id;
|
|
23
|
+
violations;
|
|
24
|
+
constructor(message,
|
|
25
|
+
/** Short slug of the violated rule, e.g. "seat-type-reference". */
|
|
26
|
+
rule,
|
|
27
|
+
/** The id (seat, section, tier, ...) that triggered the failure, if any. */
|
|
28
|
+
id,
|
|
29
|
+
/** Every violation found in the same pass, in document order. */
|
|
30
|
+
violations = []) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.rule = rule;
|
|
33
|
+
this.id = id;
|
|
34
|
+
this.violations = violations;
|
|
35
|
+
this.name = 'KerusiValidationError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// --- Non-throwing surface ---------------------------------------------------
|
|
39
|
+
/**
|
|
40
|
+
* Collects every conformance violation in a {@link KerusiMap}, in document
|
|
41
|
+
* order, without throwing. An empty array means the map is valid.
|
|
42
|
+
*
|
|
43
|
+
* Accepts `unknown` so it can be pointed at freshly parsed JSON: a value that
|
|
44
|
+
* isn't a usable map yields a shape violation rather than a crash.
|
|
45
|
+
*/
|
|
46
|
+
export function checkKerusiMap(map) {
|
|
47
|
+
return collectMapViolations(map);
|
|
48
|
+
}
|
|
49
|
+
/** Collects every violation in a {@link KerusiState} without throwing. */
|
|
50
|
+
export function checkKerusiState(state) {
|
|
51
|
+
const violations = collectStateEnvelope(state, 'KerusiState');
|
|
52
|
+
const doc = state;
|
|
53
|
+
if (doc && typeof doc === 'object' && (!doc.seats || typeof doc.seats !== 'object')) {
|
|
54
|
+
violations.push(error('state-seats', 'KerusiState is missing the required "seats" object.'));
|
|
55
|
+
}
|
|
56
|
+
else if (doc && typeof doc === 'object') {
|
|
57
|
+
violations.push(...collectSeatStatusViolations(doc.seats, 'seats'));
|
|
58
|
+
}
|
|
59
|
+
return violations;
|
|
60
|
+
}
|
|
61
|
+
/** Collects every violation in a {@link KerusiStateDelta} without throwing. */
|
|
62
|
+
export function checkKerusiStateDelta(delta) {
|
|
63
|
+
const violations = collectStateEnvelope(delta, 'KerusiStateDelta');
|
|
64
|
+
const doc = delta;
|
|
65
|
+
if (doc && typeof doc === 'object' && (!doc.changes || typeof doc.changes !== 'object')) {
|
|
66
|
+
violations.push(error('delta-changes', 'KerusiStateDelta is missing the required "changes" object.'));
|
|
67
|
+
}
|
|
68
|
+
else if (doc && typeof doc === 'object') {
|
|
69
|
+
violations.push(...collectSeatStatusViolations(doc.changes, 'changes'));
|
|
70
|
+
}
|
|
71
|
+
return violations;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* §5.1.1 applies to every timestamp in a document, `holdExpires` included: a
|
|
75
|
+
* consumer that cannot parse it cannot show a correct hold countdown, which is
|
|
76
|
+
* the one thing the field exists for.
|
|
77
|
+
*/
|
|
78
|
+
function collectSeatStatusViolations(seats, member) {
|
|
79
|
+
const violations = [];
|
|
80
|
+
for (const [seatId, status] of Object.entries(seats ?? {})) {
|
|
81
|
+
if (status?.holdExpires !== undefined && !isRfc3339(status.holdExpires)) {
|
|
82
|
+
violations.push(error('seat-status-hold-expires-format', `Seat "${seatId}" has "holdExpires": "${status.holdExpires}", which is not ` +
|
|
83
|
+
'an RFC 3339 date-time (§5.1.1).', { id: seatId, path: `${member}.${seatId}` }));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return violations;
|
|
87
|
+
}
|
|
88
|
+
/** Collects every violation in a {@link KerusiSession} without throwing (§5.3). */
|
|
89
|
+
export function checkKerusiSession(session) {
|
|
90
|
+
const doc = session;
|
|
91
|
+
if (!doc || typeof doc !== 'object') {
|
|
92
|
+
return [error('session-shape', 'KerusiSession is missing or not an object.')];
|
|
93
|
+
}
|
|
94
|
+
const violations = [];
|
|
95
|
+
if (!doc.kerusi) {
|
|
96
|
+
violations.push(error('session-version', 'KerusiSession is missing the required "kerusi" version member.'));
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
violations.push(...checkVersion(doc.kerusi, 'KerusiSession', 'session'));
|
|
100
|
+
}
|
|
101
|
+
if (!doc.id) {
|
|
102
|
+
violations.push(error('session-id', 'KerusiSession is missing the required "id" member.'));
|
|
103
|
+
}
|
|
104
|
+
if (!doc.mapId) {
|
|
105
|
+
violations.push(error('session-mapid', 'KerusiSession is missing the required "mapId" member.', {
|
|
106
|
+
id: doc.id,
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
for (const member of ['startsAt', 'endsAt']) {
|
|
110
|
+
const value = doc[member];
|
|
111
|
+
if (value !== undefined && !isRfc3339(value)) {
|
|
112
|
+
violations.push(error(`session-${member.toLowerCase()}-format`, `KerusiSession "${member}" is "${value}", which is not an RFC 3339 ` +
|
|
113
|
+
'date-time (§5.1.1).', { id: doc.id }));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return violations;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* An RFC 3339 `date-time` (§5.1.1) — the profile `format: "date-time"` has
|
|
120
|
+
* always meant in the published JSON Schemas.
|
|
121
|
+
*
|
|
122
|
+
* "ISO 8601", which the spec said before rev 13, admits forms a consumer cannot
|
|
123
|
+
* reliably parse: seconds omitted, the basic format without separators, ordinal
|
|
124
|
+
* and week dates, and local times carrying no offset at all. The regex fixes
|
|
125
|
+
* the shape; the calendar check then rejects a date the shape allows but the
|
|
126
|
+
* calendar does not, such as a 31st of February. `Date.parse` cannot stand in
|
|
127
|
+
* for that — it rolls such a date silently into the next month.
|
|
128
|
+
*/
|
|
129
|
+
const RFC_3339 = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:[Zz]|[+-](\d{2}):(\d{2}))$/;
|
|
130
|
+
function isRfc3339(value) {
|
|
131
|
+
const match = RFC_3339.exec(value);
|
|
132
|
+
if (!match) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const [year, month, day, hour, minute, second, offsetHour, offsetMinute] = match
|
|
136
|
+
.slice(1)
|
|
137
|
+
.map((part) => Number(part ?? 0));
|
|
138
|
+
if (month < 1 || month > 12 || day < 1 || day > daysInMonth(year, month)) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
// A second of 60 is a leap second, which RFC 3339 permits.
|
|
142
|
+
if (hour > 23 || minute > 59 || second > 60) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
return offsetHour <= 23 && offsetMinute <= 59;
|
|
146
|
+
}
|
|
147
|
+
function daysInMonth(year, month) {
|
|
148
|
+
const leap = (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
|
|
149
|
+
return [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1];
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Validates a map together with the session and/or state that reference it,
|
|
153
|
+
* checking the joins the individual validators cannot see (§5.1, §5.3): a
|
|
154
|
+
* state's `mapId` must be the map's id, its `sessionId` the session's, and the
|
|
155
|
+
* session's `mapId` the map's.
|
|
156
|
+
*/
|
|
157
|
+
export function validateDocumentSet(docs) {
|
|
158
|
+
const { map, state, session } = docs;
|
|
159
|
+
const violations = [...collectMapViolations(map)];
|
|
160
|
+
if (session) {
|
|
161
|
+
violations.push(...checkKerusiSession(session));
|
|
162
|
+
if (map?.id && session.mapId && session.mapId !== map.id) {
|
|
163
|
+
violations.push(error('session-map-mismatch', `KerusiSession "${session.id}" references mapId "${session.mapId}", but the ` +
|
|
164
|
+
`supplied map is "${map.id}" (§5.3).`, { id: session.id }));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (state) {
|
|
168
|
+
violations.push(...checkKerusiState(state));
|
|
169
|
+
if (state.mapId !== undefined && map?.id && state.mapId !== map.id) {
|
|
170
|
+
violations.push(error('state-map-mismatch', `KerusiState references mapId "${state.mapId}", but the supplied map is ` +
|
|
171
|
+
`"${map.id}" (§5.1).`));
|
|
172
|
+
}
|
|
173
|
+
if (state.sessionId !== undefined && session && state.sessionId !== session.id) {
|
|
174
|
+
violations.push(error('state-session-mismatch', `KerusiState references sessionId "${state.sessionId}", but the supplied ` +
|
|
175
|
+
`session is "${session.id}" (§5.1).`));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return violations;
|
|
179
|
+
}
|
|
180
|
+
// --- Throwing surface (signatures unchanged from 0.x) -----------------------
|
|
181
|
+
/**
|
|
182
|
+
* Validates a {@link KerusiMap} against the MUST-level rules of spec §4.
|
|
183
|
+
* Throws {@link KerusiValidationError} on the first violation; returns the map
|
|
184
|
+
* unchanged when valid, so it can be used inline.
|
|
185
|
+
*
|
|
186
|
+
* Enforced rules:
|
|
187
|
+
* - Required members present: `kerusi`, `id`, `legend`, `sections` (§4), and
|
|
188
|
+
* `kerusi` declares a supported major version.
|
|
189
|
+
* - Every seat has `col`, or `x`+`y`, or both — never neither (§4.3.1) — and
|
|
190
|
+
* conforms to its section's declared or inferred `layout` mode (§4.5).
|
|
191
|
+
* - Section, seat and element ids are unique (§4.1, §4.3, §4.4).
|
|
192
|
+
* - Every `Seat.type` resolves to a `SeatType.id` in `legend` (§4.6).
|
|
193
|
+
* - Every `Seat.priceTier` resolves to a `PriceTier.id` (§4.6).
|
|
194
|
+
* - Every `Seat.row` resolves to a `RowMeta.id` when the section declares
|
|
195
|
+
* `rows`; opaque free-text otherwise (§4.6).
|
|
196
|
+
* - Every `Seat.companions[]` entry resolves to another seat in the SAME
|
|
197
|
+
* section, and the relationship is symmetric (§4.6).
|
|
198
|
+
* - Every `Element` has the required `id` and `kind` (§4.4), is positioned in
|
|
199
|
+
* its section's own layout mode, and — in a grid section — carries integer
|
|
200
|
+
* column and row spans that stay inside the section's rows (§4.4.1, §4.6).
|
|
201
|
+
* - All resolved currencies across the map are identical (§4.9).
|
|
202
|
+
*
|
|
203
|
+
* Advisory findings never throw; use {@link checkKerusiMap} to see them.
|
|
204
|
+
*/
|
|
205
|
+
export function validateKerusiMap(map) {
|
|
206
|
+
throwFirstError(collectMapViolations(map));
|
|
207
|
+
return map;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Validates a {@link KerusiState} against the MUST-level rules of spec §5.1,
|
|
211
|
+
* including the RFC 3339 timestamp profile of §5.1.1:
|
|
212
|
+
* `kerusi` present and supported, `updatedAt` present, exactly one of
|
|
213
|
+
* `sessionId`/`mapId`, and a `seats` object.
|
|
214
|
+
*/
|
|
215
|
+
export function validateKerusiState(state) {
|
|
216
|
+
throwFirstError(checkKerusiState(state));
|
|
217
|
+
return state;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Validates a {@link KerusiStateDelta} against the MUST-level rules of §5.2:
|
|
221
|
+
* `kerusi` present and supported, `updatedAt` present, exactly one of
|
|
222
|
+
* `sessionId`/`mapId`, and a `changes` object.
|
|
223
|
+
*/
|
|
224
|
+
export function validateKerusiStateDelta(delta) {
|
|
225
|
+
throwFirstError(checkKerusiStateDelta(delta));
|
|
226
|
+
return delta;
|
|
227
|
+
}
|
|
228
|
+
/** Validates a {@link KerusiSession} against §5.3. */
|
|
229
|
+
export function validateKerusiSession(session) {
|
|
230
|
+
throwFirstError(checkKerusiSession(session));
|
|
231
|
+
return session;
|
|
232
|
+
}
|
|
233
|
+
function throwFirstError(violations) {
|
|
234
|
+
const errors = errorsOf(violations);
|
|
235
|
+
if (errors.length > 0) {
|
|
236
|
+
const first = errors[0];
|
|
237
|
+
throw new KerusiValidationError(first.message, first.rule, first.id, violations);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
// --- Collectors -------------------------------------------------------------
|
|
241
|
+
/**
|
|
242
|
+
* Walks a map and returns every violation in document order. The order matters:
|
|
243
|
+
* `validateKerusiMap` throws the first error, so it must report the same rule
|
|
244
|
+
* the pre-1.0 short-circuiting validator did for any given document.
|
|
245
|
+
*/
|
|
246
|
+
function collectMapViolations(map) {
|
|
247
|
+
if (!map || typeof map !== 'object') {
|
|
248
|
+
return [error('map-shape', 'KerusiMap is missing or not an object.')];
|
|
249
|
+
}
|
|
250
|
+
const violations = [];
|
|
251
|
+
if (!map.kerusi) {
|
|
252
|
+
violations.push(error('map-version', 'KerusiMap is missing the required "kerusi" version member.'));
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
violations.push(...checkVersion(map.kerusi, 'KerusiMap', 'map'));
|
|
256
|
+
}
|
|
257
|
+
if (!map.id) {
|
|
258
|
+
violations.push(error('map-id', 'KerusiMap is missing the required "id" member.'));
|
|
259
|
+
}
|
|
260
|
+
if (!Array.isArray(map.legend)) {
|
|
261
|
+
violations.push(error('map-legend', 'KerusiMap is missing the required "legend" array.', { id: map.id }));
|
|
262
|
+
}
|
|
263
|
+
if (!Array.isArray(map.sections)) {
|
|
264
|
+
violations.push(error('map-sections', 'KerusiMap is missing the required "sections" array.', { id: map.id }));
|
|
265
|
+
}
|
|
266
|
+
// Without a legend and sections there is nothing further to walk, and
|
|
267
|
+
// reporting a hundred downstream failures would bury the real problem.
|
|
268
|
+
if (!Array.isArray(map.legend) || !Array.isArray(map.sections)) {
|
|
269
|
+
return violations;
|
|
270
|
+
}
|
|
271
|
+
const seatTypeIds = new Set(map.legend.map((t) => t.id));
|
|
272
|
+
const priceTierIds = new Set((map.priceTiers ?? []).map((t) => t.id));
|
|
273
|
+
const currencies = new Set();
|
|
274
|
+
// Tier-level currencies count toward the single-currency rule regardless of
|
|
275
|
+
// whether a seat references the tier.
|
|
276
|
+
for (const tier of map.priceTiers ?? []) {
|
|
277
|
+
if (tier.price?.currency) {
|
|
278
|
+
currencies.add(tier.price.currency);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const seenSectionIds = new Set();
|
|
282
|
+
const seenSeatIds = new Set();
|
|
283
|
+
const duplicateSections = [];
|
|
284
|
+
const duplicateSeats = [];
|
|
285
|
+
map.sections.forEach((section, sectionIndex) => {
|
|
286
|
+
const path = `sections[${sectionIndex}]`;
|
|
287
|
+
violations.push(...collectSectionViolations(section, map, seatTypeIds, priceTierIds, currencies, path));
|
|
288
|
+
if (seenSectionIds.has(section?.id)) {
|
|
289
|
+
duplicateSections.push(section.id);
|
|
290
|
+
}
|
|
291
|
+
seenSectionIds.add(section?.id);
|
|
292
|
+
for (const seat of section?.seats ?? []) {
|
|
293
|
+
if (seenSeatIds.has(seat.id)) {
|
|
294
|
+
duplicateSeats.push(seat.id);
|
|
295
|
+
}
|
|
296
|
+
seenSeatIds.add(seat.id);
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
for (const id of duplicateSections) {
|
|
300
|
+
violations.push(error('section-id-duplicate', `Section id "${id}" is declared more than once (§4.1).`, {
|
|
301
|
+
id,
|
|
302
|
+
}));
|
|
303
|
+
}
|
|
304
|
+
for (const id of duplicateSeats) {
|
|
305
|
+
violations.push(error('seat-id-duplicate', `Seat id "${id}" is declared more than once; seat ids must be globally unique ` +
|
|
306
|
+
'within a KerusiMap (§4.3).', { id }));
|
|
307
|
+
}
|
|
308
|
+
if (currencies.size > 1) {
|
|
309
|
+
violations.push(error('single-currency', `KerusiMap mixes currencies (${[...currencies].sort().join(', ')}); ` +
|
|
310
|
+
'exactly one currency must apply to the whole map (§4.9).', { id: map.id }));
|
|
311
|
+
}
|
|
312
|
+
return violations;
|
|
313
|
+
}
|
|
314
|
+
function collectSectionViolations(section, map, seatTypeIds, priceTierIds, currencies, path) {
|
|
315
|
+
if (!section || typeof section !== 'object') {
|
|
316
|
+
return [error('section-shape', 'A section is missing or not an object.', { path })];
|
|
317
|
+
}
|
|
318
|
+
const violations = [];
|
|
319
|
+
if (!section.id) {
|
|
320
|
+
violations.push(error('section-id', 'A section is missing the required "id".', { path }));
|
|
321
|
+
}
|
|
322
|
+
if (!Array.isArray(section.seats)) {
|
|
323
|
+
violations.push(error('section-seats', `Section "${section.id}" is missing the required "seats" array.`, {
|
|
324
|
+
id: section.id,
|
|
325
|
+
path,
|
|
326
|
+
}));
|
|
327
|
+
return violations;
|
|
328
|
+
}
|
|
329
|
+
const rowIds = section.rows ? new Set(section.rows.map((r) => r.id)) : null;
|
|
330
|
+
const seatIds = new Set(section.seats.map((s) => s.id));
|
|
331
|
+
const companionsBySeat = new Map();
|
|
332
|
+
section.seats.forEach((seat, seatIndex) => {
|
|
333
|
+
const seatPath = `${path}.seats[${seatIndex}]`;
|
|
334
|
+
// §4.3.1 positioning. Checked before the §4.5 mode rules so a seat with no
|
|
335
|
+
// position at all gets the clearer message rather than a mode complaint.
|
|
336
|
+
if (!hasCol(seat) && !hasXY(seat)) {
|
|
337
|
+
violations.push(error('seat-position', `Seat "${seat.id}" has neither "col" nor "x"+"y"; a seat must specify ` +
|
|
338
|
+
'at least one positioning method (§4.3.1).', { id: seat.id, path: seatPath }));
|
|
339
|
+
}
|
|
340
|
+
// §4.6 type reference.
|
|
341
|
+
if (!seatTypeIds.has(seat.type)) {
|
|
342
|
+
violations.push(error('seat-type-reference', `Seat "${seat.id}" references unknown type "${seat.type}"; not found in ` +
|
|
343
|
+
'the map legend (§4.6).', { id: seat.id, path: seatPath }));
|
|
344
|
+
}
|
|
345
|
+
// §4.6 priceTier reference.
|
|
346
|
+
if (seat.priceTier !== undefined && !priceTierIds.has(seat.priceTier)) {
|
|
347
|
+
violations.push(error('seat-pricetier-reference', `Seat "${seat.id}" references unknown priceTier "${seat.priceTier}" (§4.6).`, { id: seat.id, path: seatPath }));
|
|
348
|
+
}
|
|
349
|
+
// §4.6 row reference — only when the section declares a rows array.
|
|
350
|
+
if (rowIds && seat.row !== undefined && !rowIds.has(seat.row)) {
|
|
351
|
+
violations.push(error('seat-row-reference', `Seat "${seat.id}" references unknown row "${seat.row}"; not found in ` +
|
|
352
|
+
`section "${section.id}" rows (§4.6).`, { id: seat.id, path: seatPath }));
|
|
353
|
+
}
|
|
354
|
+
// §4.3.4 accessibility. Advisory rather than fatal: §7 tells consumers to
|
|
355
|
+
// ignore members they don't recognize instead of rejecting the document.
|
|
356
|
+
const armrest = seat.accessibility?.transferArmrest;
|
|
357
|
+
if (armrest !== undefined && !TRANSFER_ARMREST.has(armrest)) {
|
|
358
|
+
violations.push(warning('accessibility-transfer-armrest', `Seat "${seat.id}" has transferArmrest "${armrest}", which is not one of ` +
|
|
359
|
+
'left | right | both | fixed | none (§4.3.4).', { id: seat.id, path: seatPath }));
|
|
360
|
+
}
|
|
361
|
+
// Collect the resolved currency for the single-currency rule (§4.9).
|
|
362
|
+
const price = resolveSeatPrice(seat, map);
|
|
363
|
+
if (price?.currency) {
|
|
364
|
+
currencies.add(price.currency);
|
|
365
|
+
}
|
|
366
|
+
companionsBySeat.set(seat.id, new Set(seat.companions ?? []));
|
|
367
|
+
});
|
|
368
|
+
// §4.6 companion resolution + symmetry.
|
|
369
|
+
for (const [seatId, companions] of companionsBySeat) {
|
|
370
|
+
for (const companionId of companions) {
|
|
371
|
+
if (!seatIds.has(companionId)) {
|
|
372
|
+
violations.push(error('companion-reference', `Seat "${seatId}" lists companion "${companionId}", which is not a ` +
|
|
373
|
+
`seat in section "${section.id}" (§4.6).`, { id: seatId, path }));
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
const back = companionsBySeat.get(companionId);
|
|
377
|
+
if (!back || !back.has(seatId)) {
|
|
378
|
+
violations.push(error('companion-symmetry', `Companion link is not symmetric: seat "${seatId}" lists "${companionId}", ` +
|
|
379
|
+
`but "${companionId}" does not list "${seatId}" in return (§4.6).`, { id: seatId, path }));
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
// §4.5 layout modes — a strict, validated constraint at v1.0.
|
|
384
|
+
violations.push(...checkSectionLayout(section, path));
|
|
385
|
+
// §4.4 elements.
|
|
386
|
+
violations.push(...collectElementViolations(section, path));
|
|
387
|
+
return violations;
|
|
388
|
+
}
|
|
389
|
+
function collectElementViolations(section, path) {
|
|
390
|
+
const violations = [];
|
|
391
|
+
const mode = resolveSectionLayoutMode(section);
|
|
392
|
+
const rowIndexes = rowOrderIndexes(section);
|
|
393
|
+
const declaresRows = Boolean(section.rows);
|
|
394
|
+
const seen = new Set();
|
|
395
|
+
(section.elements ?? []).forEach((element, i) => {
|
|
396
|
+
const elementPath = `${path}.elements[${i}]`;
|
|
397
|
+
if (!element.id) {
|
|
398
|
+
violations.push(error('element-id', `An element in section "${section.id}" has no "id" (§4.4).`, {
|
|
399
|
+
path: elementPath,
|
|
400
|
+
}));
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
if (seen.has(element.id)) {
|
|
404
|
+
violations.push(error('element-id-duplicate', `Element id "${element.id}" is declared more than once in section ` +
|
|
405
|
+
`"${section.id}" (§4.4).`, { id: element.id, path: elementPath }));
|
|
406
|
+
}
|
|
407
|
+
seen.add(element.id);
|
|
408
|
+
}
|
|
409
|
+
if (!element.kind) {
|
|
410
|
+
violations.push(error('element-kind', `Element "${element.id}" has no "kind" (§4.4).`, {
|
|
411
|
+
id: element.id,
|
|
412
|
+
path: elementPath,
|
|
413
|
+
}));
|
|
414
|
+
}
|
|
415
|
+
// §4.6: an element's row resolves against the registry exactly as a seat's
|
|
416
|
+
// does, and for the same reason — a row that does not exist places nothing.
|
|
417
|
+
if (declaresRows && element.row !== undefined && !rowIndexes.has(element.row)) {
|
|
418
|
+
violations.push(error('element-row-unresolved', `Element "${element.id}" references unknown row "${element.row}" in ` +
|
|
419
|
+
`section "${section.id}" rows (§4.6).`, { id: element.id, path: elementPath }));
|
|
420
|
+
}
|
|
421
|
+
const usesGrid = hasCol(element) || element.row !== undefined;
|
|
422
|
+
const usesFreeform = hasAnyCoordinate(element);
|
|
423
|
+
if (!usesGrid && !usesFreeform) {
|
|
424
|
+
violations.push(warning('element-position', `Element "${element.id}" has neither "row"/"col" nor "x"/"y"; it cannot be ` +
|
|
425
|
+
'placed within the seating area (§4.4).', { id: element.id, path: elementPath }));
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
// §4.4.1 binds an element to its section's positioning mode exactly as §4.5
|
|
429
|
+
// binds its seats: a section whose elements are addressed differently from
|
|
430
|
+
// its seats cannot be laid out deterministically by two renderers. `mixed`
|
|
431
|
+
// permits either, and a freeform element may still carry `row` as a label.
|
|
432
|
+
if (mode === 'grid' && usesFreeform) {
|
|
433
|
+
violations.push(error('element-layout-mismatch', `Element "${element.id}" carries "x"/"y" in grid section "${section.id}"; ` +
|
|
434
|
+
'a grid element is positioned by "row" and/or "col" (§4.4.1).', { id: element.id, path: elementPath }));
|
|
435
|
+
}
|
|
436
|
+
else if (mode === 'freeform' && hasCol(element)) {
|
|
437
|
+
violations.push(error('element-layout-mismatch', `Element "${element.id}" carries "col" in freeform section ` +
|
|
438
|
+
`"${section.id}", which has no column grid to place it in (§4.4.1).`, { id: element.id, path: elementPath }));
|
|
439
|
+
}
|
|
440
|
+
violations.push(...collectElementSpanViolations(element, section, mode, rowIndexes, elementPath));
|
|
441
|
+
});
|
|
442
|
+
return violations;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* §4.4.1 spans. For a grid-addressed element `width` and `height` are
|
|
446
|
+
* dimensionless cell counts — positive integers, defaulting to 1 — so a
|
|
447
|
+
* fractional or zero span leaves two renderers to disagree about how much space
|
|
448
|
+
* it occupies. They are percentages once `x`/`y` governs placement, where any
|
|
449
|
+
* positive number is meaningful, so nothing is checked there. A mixed section
|
|
450
|
+
* can hold both kinds, one element at a time.
|
|
451
|
+
*
|
|
452
|
+
* A row span is also bounded, and only in a grid section as §4.6 scopes it: an
|
|
453
|
+
* element reaching past the last row in the §4.2.1 order occupies rows that do
|
|
454
|
+
* not exist.
|
|
455
|
+
*/
|
|
456
|
+
function collectElementSpanViolations(element, section, mode, rowIndexes, elementPath) {
|
|
457
|
+
const gridAddressed = mode === 'grid' || (mode === 'mixed' && !hasAnyCoordinate(element));
|
|
458
|
+
if (!gridAddressed) {
|
|
459
|
+
return [];
|
|
460
|
+
}
|
|
461
|
+
const violations = [];
|
|
462
|
+
for (const [axis, span] of [
|
|
463
|
+
['width', element.width],
|
|
464
|
+
['height', element.height],
|
|
465
|
+
]) {
|
|
466
|
+
if (span !== undefined && (!Number.isInteger(span) || span < 1)) {
|
|
467
|
+
violations.push(error('element-span-invalid', `Element "${element.id}" has "${axis}": ${span} in grid section ` +
|
|
468
|
+
`"${section.id}"; a grid span is a positive integer count of cells (§4.4.1).`, { id: element.id, path: elementPath }));
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
const start = mode === 'grid' && element.row !== undefined ? rowIndexes.get(element.row) : undefined;
|
|
472
|
+
const span = element.height ?? 1;
|
|
473
|
+
if (start !== undefined && Number.isInteger(span) && span >= 1) {
|
|
474
|
+
const last = start + span - 1;
|
|
475
|
+
if (last > rowIndexes.size - 1) {
|
|
476
|
+
violations.push(error('element-row-span-overrun', `Element "${element.id}" spans ${span} rows from "${element.row}", ` +
|
|
477
|
+
`reaching past the last row of section "${section.id}" (§4.2.1, §4.6).`, { id: element.id, path: elementPath }));
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return violations;
|
|
481
|
+
}
|
|
482
|
+
function collectStateEnvelope(doc, typeName) {
|
|
483
|
+
if (!doc || typeof doc !== 'object') {
|
|
484
|
+
return [error('state-shape', `${typeName} is missing or not an object.`)];
|
|
485
|
+
}
|
|
486
|
+
const violations = [];
|
|
487
|
+
const slug = typeName === 'KerusiState' ? 'state' : 'delta';
|
|
488
|
+
if (!doc.kerusi) {
|
|
489
|
+
violations.push(error('state-version', `${typeName} is missing the required "kerusi" version member.`));
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
violations.push(...checkVersion(doc.kerusi, typeName, slug));
|
|
493
|
+
}
|
|
494
|
+
if (!doc.updatedAt) {
|
|
495
|
+
violations.push(error('state-updatedat', `${typeName} is missing the required "updatedAt" timestamp.`));
|
|
496
|
+
}
|
|
497
|
+
else if (!isRfc3339(doc.updatedAt)) {
|
|
498
|
+
violations.push(error('state-updatedat-format', `${typeName} "updatedAt" is "${doc.updatedAt}", which is not an RFC 3339 ` +
|
|
499
|
+
'date-time (§5.1.1).'));
|
|
500
|
+
}
|
|
501
|
+
const hasSession = doc.sessionId !== undefined && doc.sessionId !== null;
|
|
502
|
+
const hasMap = doc.mapId !== undefined && doc.mapId !== null;
|
|
503
|
+
if (hasSession === hasMap) {
|
|
504
|
+
violations.push(error('state-scope', `${typeName} must specify exactly one of "sessionId" or "mapId" ` +
|
|
505
|
+
`(found ${hasSession ? 'both' : 'neither'}) (§5.1).`));
|
|
506
|
+
}
|
|
507
|
+
return violations;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Checks a document's `kerusi` member declares a major version this library
|
|
511
|
+
* understands. A future *minor* version is accepted — §7 requires consumers to
|
|
512
|
+
* ignore members they don't recognize rather than reject the document — but a
|
|
513
|
+
* different major is not.
|
|
514
|
+
*/
|
|
515
|
+
function checkVersion(version, typeName, slug) {
|
|
516
|
+
const major = Number.parseInt(String(version).split('.')[0], 10);
|
|
517
|
+
if (Number.isNaN(major) || major !== SUPPORTED_MAJOR) {
|
|
518
|
+
return [
|
|
519
|
+
error(`${slug}-version-unsupported`, `${typeName} declares kerusi version "${version}"; this library implements ` +
|
|
520
|
+
`${SUPPORTED_MAJOR}.x. A future minor version is accepted, a different major is not.`),
|
|
521
|
+
];
|
|
522
|
+
}
|
|
523
|
+
return [];
|
|
524
|
+
}
|
|
525
|
+
//# sourceMappingURL=kerusi-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kerusi-validator.js","sourceRoot":"","sources":["../../src/kerusi/kerusi-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A single conformance finding against a Kerusi document.
|
|
3
|
+
*
|
|
4
|
+
* The validator collects these rather than throwing at the first fault, so a
|
|
5
|
+
* caller can show every problem in a document at once. `validateKerusiMap` and
|
|
6
|
+
* friends still throw on the first `error`, preserving the pre-1.0 behavior.
|
|
7
|
+
*/
|
|
8
|
+
export interface KerusiViolation {
|
|
9
|
+
/** Short slug of the violated rule, e.g. "seat-type-reference". Stable. */
|
|
10
|
+
rule: string;
|
|
11
|
+
/** Human-readable explanation, citing the spec section where one applies. */
|
|
12
|
+
message: string;
|
|
13
|
+
/** The id (seat, section, element, tier, ...) that triggered it, if any. */
|
|
14
|
+
id?: string;
|
|
15
|
+
/**
|
|
16
|
+
* `error` — a MUST-level violation; the document is invalid.
|
|
17
|
+
* `warning` — a SHOULD-level or advisory finding; the document still renders.
|
|
18
|
+
*/
|
|
19
|
+
severity: ViolationSeverity;
|
|
20
|
+
/** Where in the document it occurred, e.g. `sections[1].seats[7]`. */
|
|
21
|
+
path?: string;
|
|
22
|
+
}
|
|
23
|
+
export type ViolationSeverity = 'error' | 'warning';
|
|
24
|
+
/** Builds an `error` violation. */
|
|
25
|
+
export declare function error(rule: string, message: string, opts?: {
|
|
26
|
+
id?: string;
|
|
27
|
+
path?: string;
|
|
28
|
+
}): KerusiViolation;
|
|
29
|
+
/** Builds a `warning` violation. */
|
|
30
|
+
export declare function warning(rule: string, message: string, opts?: {
|
|
31
|
+
id?: string;
|
|
32
|
+
path?: string;
|
|
33
|
+
}): KerusiViolation;
|
|
34
|
+
/** The subset of violations that make a document invalid. */
|
|
35
|
+
export declare function errorsOf(violations: readonly KerusiViolation[]): readonly KerusiViolation[];
|
|
36
|
+
//# sourceMappingURL=kerusi-violation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kerusi-violation.d.ts","sourceRoot":"","sources":["../../src/kerusi/kerusi-violation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,sEAAsE;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,SAAS,CAAC;AAEpD,mCAAmC;AACnC,wBAAgB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,eAAe,CAEjB;AAED,oCAAoC;AACpC,wBAAgB,OAAO,CACrB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,GAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GACxC,eAAe,CAEjB;AAED,6DAA6D;AAC7D,wBAAgB,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,eAAe,EAAE,CAE3F"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Builds an `error` violation. */
|
|
2
|
+
export function error(rule, message, opts = {}) {
|
|
3
|
+
return { rule, message, severity: 'error', ...opts };
|
|
4
|
+
}
|
|
5
|
+
/** Builds a `warning` violation. */
|
|
6
|
+
export function warning(rule, message, opts = {}) {
|
|
7
|
+
return { rule, message, severity: 'warning', ...opts };
|
|
8
|
+
}
|
|
9
|
+
/** The subset of violations that make a document invalid. */
|
|
10
|
+
export function errorsOf(violations) {
|
|
11
|
+
return violations.filter((v) => v.severity === 'error');
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=kerusi-violation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kerusi-violation.js","sourceRoot":"","sources":["../../src/kerusi/kerusi-violation.ts"],"names":[],"mappings":"AAyBA,mCAAmC;AACnC,MAAM,UAAU,KAAK,CACnB,IAAY,EACZ,OAAe,EACf,OAAuC,EAAE;IAEzC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,CAAC;AACvD,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,OAAO,CACrB,IAAY,EACZ,OAAe,EACf,OAAuC,EAAE;IAEzC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,CAAC;AACzD,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,QAAQ,CAAC,UAAsC;IAC7D,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAQA,cAAc,mBAAmB,CAAC;AAGlC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Public API Surface of @kerusiweb/core
|
|
3
|
+
*
|
|
4
|
+
* Framework-agnostic Kerusi seat-map logic. Nothing here imports Angular,
|
|
5
|
+
* React, or any other framework — see docs/architecture.md for the boundary.
|
|
6
|
+
*/
|
|
7
|
+
// --- Kerusi format: document types, validation, pricing, locale, state ------
|
|
8
|
+
export * from './kerusi/index.js';
|
|
9
|
+
// --- Render model: the resolved view a renderer consumes, plus geometry -----
|
|
10
|
+
export * from './render/index.js';
|
|
11
|
+
// --- View policy: colours, ARIA strings, selection rules --------------------
|
|
12
|
+
export * from './view/index.js';
|
|
13
|
+
//# sourceMappingURL=public-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,+EAA+E;AAC/E,cAAc,mBAAmB,CAAC;AAElC,+EAA+E;AAC/E,cAAc,mBAAmB,CAAC;AAElC,+EAA+E;AAC/E,cAAc,iBAAiB,CAAC"}
|