@peekling/runtime 0.1.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.
Files changed (120) hide show
  1. package/AUTHORS +8 -0
  2. package/LICENSE +202 -0
  3. package/LICENSING.md +20 -0
  4. package/NOTICE +6 -0
  5. package/README.md +294 -0
  6. package/dist/configuration-validation.d.ts +19 -0
  7. package/dist/configuration-validation.d.ts.map +1 -0
  8. package/dist/configuration-validation.js +298 -0
  9. package/dist/content.d.ts +44 -0
  10. package/dist/content.d.ts.map +1 -0
  11. package/dist/content.js +738 -0
  12. package/dist/contracts.d.ts +10 -0
  13. package/dist/contracts.d.ts.map +1 -0
  14. package/dist/contracts.js +106 -0
  15. package/dist/defaults.d.ts +7 -0
  16. package/dist/defaults.d.ts.map +1 -0
  17. package/dist/defaults.js +6 -0
  18. package/dist/diagnostics.d.ts +25 -0
  19. package/dist/diagnostics.d.ts.map +1 -0
  20. package/dist/diagnostics.js +122 -0
  21. package/dist/direction.d.ts +3 -0
  22. package/dist/direction.d.ts.map +1 -0
  23. package/dist/direction.js +6 -0
  24. package/dist/errors.d.ts +15 -0
  25. package/dist/errors.d.ts.map +1 -0
  26. package/dist/errors.js +53 -0
  27. package/dist/events.d.ts +5 -0
  28. package/dist/events.d.ts.map +1 -0
  29. package/dist/events.js +60 -0
  30. package/dist/index.d.ts +6 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +3 -0
  33. package/dist/input.d.ts +31 -0
  34. package/dist/input.d.ts.map +1 -0
  35. package/dist/input.js +215 -0
  36. package/dist/json.d.ts +3 -0
  37. package/dist/json.d.ts.map +1 -0
  38. package/dist/json.js +109 -0
  39. package/dist/loader.d.ts +33 -0
  40. package/dist/loader.d.ts.map +1 -0
  41. package/dist/loader.js +477 -0
  42. package/dist/locomotion.d.ts +8 -0
  43. package/dist/locomotion.d.ts.map +1 -0
  44. package/dist/locomotion.js +29 -0
  45. package/dist/normalized.d.ts +5 -0
  46. package/dist/normalized.d.ts.map +1 -0
  47. package/dist/normalized.js +266 -0
  48. package/dist/overrides.d.ts +29 -0
  49. package/dist/overrides.d.ts.map +1 -0
  50. package/dist/overrides.js +296 -0
  51. package/dist/own-data.d.ts +18 -0
  52. package/dist/own-data.d.ts.map +1 -0
  53. package/dist/own-data.js +205 -0
  54. package/dist/pack-api.d.ts +9 -0
  55. package/dist/pack-api.d.ts.map +1 -0
  56. package/dist/pack-api.js +6 -0
  57. package/dist/pack-shared.d.ts +28 -0
  58. package/dist/pack-shared.d.ts.map +1 -0
  59. package/dist/pack-shared.js +408 -0
  60. package/dist/pack.d.ts +6 -0
  61. package/dist/pack.d.ts.map +1 -0
  62. package/dist/pack.js +316 -0
  63. package/dist/peekling.css +1 -0
  64. package/dist/peekling.css.sri +1 -0
  65. package/dist/peekling.js +7469 -0
  66. package/dist/peekling.js.sri +1 -0
  67. package/dist/peekling.min.js +2 -0
  68. package/dist/peekling.min.js.sri +1 -0
  69. package/dist/plan-compiler.d.ts +82 -0
  70. package/dist/plan-compiler.d.ts.map +1 -0
  71. package/dist/plan-compiler.js +724 -0
  72. package/dist/plan.d.ts +21 -0
  73. package/dist/plan.d.ts.map +1 -0
  74. package/dist/plan.js +287 -0
  75. package/dist/preflight-api.d.ts +3 -0
  76. package/dist/preflight-api.d.ts.map +1 -0
  77. package/dist/preflight-api.js +1 -0
  78. package/dist/preflight.d.ts +22 -0
  79. package/dist/preflight.d.ts.map +1 -0
  80. package/dist/preflight.js +158 -0
  81. package/dist/registry.d.ts +9 -0
  82. package/dist/registry.d.ts.map +1 -0
  83. package/dist/registry.js +24 -0
  84. package/dist/renderer.d.ts +16 -0
  85. package/dist/renderer.d.ts.map +1 -0
  86. package/dist/renderer.js +176 -0
  87. package/dist/resolver.d.ts +3 -0
  88. package/dist/resolver.d.ts.map +1 -0
  89. package/dist/resolver.js +30 -0
  90. package/dist/runtime-diagnostics.d.ts +3 -0
  91. package/dist/runtime-diagnostics.d.ts.map +1 -0
  92. package/dist/runtime-diagnostics.js +5 -0
  93. package/dist/runtime-validation.d.ts +6 -0
  94. package/dist/runtime-validation.d.ts.map +1 -0
  95. package/dist/runtime-validation.js +104 -0
  96. package/dist/runtime.d.ts +87 -0
  97. package/dist/runtime.d.ts.map +1 -0
  98. package/dist/runtime.js +1015 -0
  99. package/dist/sections.d.ts +15 -0
  100. package/dist/sections.d.ts.map +1 -0
  101. package/dist/sections.js +221 -0
  102. package/dist/styles.d.ts +18 -0
  103. package/dist/styles.d.ts.map +1 -0
  104. package/dist/styles.js +132 -0
  105. package/dist/tooling-preflight.d.ts +23 -0
  106. package/dist/tooling-preflight.d.ts.map +1 -0
  107. package/dist/tooling-preflight.js +207 -0
  108. package/dist/tooling-validation.d.ts +8 -0
  109. package/dist/tooling-validation.d.ts.map +1 -0
  110. package/dist/tooling-validation.js +94 -0
  111. package/dist/types.d.ts +403 -0
  112. package/dist/types.d.ts.map +1 -0
  113. package/dist/types.js +29 -0
  114. package/dist/visibility.d.ts +12 -0
  115. package/dist/visibility.d.ts.map +1 -0
  116. package/dist/visibility.js +333 -0
  117. package/dist/web-component.d.ts +31 -0
  118. package/dist/web-component.d.ts.map +1 -0
  119. package/dist/web-component.js +236 -0
  120. package/package.json +74 -0
@@ -0,0 +1,298 @@
1
+ import { validateHostContent } from "./content.js";
2
+ import { isHttpPath, isSurfaceColor, NAME_PATTERN } from "./contracts.js";
3
+ import { isRegisteredCharacter } from "./registry.js";
4
+ import { compactRuntimeDiagnostics } from "./runtime-diagnostics.js";
5
+ import { validStyleIntegrity } from "./styles.js";
6
+ import { CONTENT_REGIONS } from "./types.js";
7
+ const collectConfigurationFaults = !compactRuntimeDiagnostics;
8
+ const CONFIGURATION_FIELDS = [
9
+ "format",
10
+ "character",
11
+ "pack",
12
+ "packUrl",
13
+ "atlasUrl",
14
+ "styles",
15
+ "plan",
16
+ "content",
17
+ "bindings",
18
+ "theme",
19
+ "accessibility",
20
+ "diagnostics",
21
+ "name",
22
+ "scale",
23
+ "position",
24
+ "density",
25
+ "maxDensity",
26
+ "onDiagnostic",
27
+ "logger",
28
+ "document",
29
+ "window",
30
+ ];
31
+ export class PeeklingPreflightError extends TypeError {
32
+ issues;
33
+ constructor(code, path, message) {
34
+ super(`${path}: ${message}`);
35
+ this.name = "PeeklingPreflightError";
36
+ this.issues = [{ code, path, message }];
37
+ }
38
+ }
39
+ /**
40
+ * Validate shared Configuration semantics without selecting presentation prose.
41
+ * A throwing sink is fail-fast. A collecting sink receives every safe fault.
42
+ */
43
+ export function validateConfiguration(options, baseUrl, fault) {
44
+ closed(options, CONFIGURATION_FIELDS, "$", fault);
45
+ if (options.character === undefined &&
46
+ options.pack === undefined &&
47
+ options.packUrl === undefined) {
48
+ reportConfigurationFault("manifest.selection", "$", fault);
49
+ }
50
+ if (options.format !== undefined && options.format !== 1) {
51
+ reportConfigurationFault("unsupported-format", "$.format", fault);
52
+ }
53
+ if (options.character !== undefined) {
54
+ if (typeof options.character !== "string" ||
55
+ !NAME_PATTERN.test(options.character)) {
56
+ reportConfigurationFault("invalid-character", "$.character", fault);
57
+ }
58
+ else if (options.pack === undefined &&
59
+ options.packUrl === undefined &&
60
+ !isRegisteredCharacter(options.character)) {
61
+ reportConfigurationFault("character.unknown", "$.character", fault, options.character);
62
+ }
63
+ }
64
+ if (options.scale !== undefined &&
65
+ (!Number.isInteger(options.scale) || options.scale < 1 || options.scale > 4)) {
66
+ reportConfigurationFault("out-of-range", "$.scale", fault, "scale");
67
+ }
68
+ for (const field of ["density", "maxDensity"]) {
69
+ const value = options[field];
70
+ if (value !== undefined && value !== 1 && value !== 2 && value !== 4) {
71
+ reportConfigurationFault("invalid-density", `$.${field}`, fault, field);
72
+ }
73
+ }
74
+ if (options.density !== undefined &&
75
+ options.maxDensity !== undefined &&
76
+ options.density > options.maxDensity) {
77
+ reportConfigurationFault("incompatible-density", "$.density", fault);
78
+ }
79
+ if (!validRuntimeName(options.name)) {
80
+ reportConfigurationFault("invalid-name", "$.name", fault);
81
+ }
82
+ for (const field of ["packUrl", "atlasUrl"]) {
83
+ const value = options[field];
84
+ if (value !== undefined && !isHttpPath(value, baseUrl)) {
85
+ reportConfigurationFault("invalid-url", `$.${field}`, fault, field);
86
+ }
87
+ }
88
+ const position = options.position;
89
+ if (position !== undefined &&
90
+ position !== "bottom-left" &&
91
+ position !== "bottom-right" &&
92
+ position !== "center") {
93
+ const point = shape(position, "invalid-position", "$.position", ["x", "y"], fault);
94
+ if (!collectConfigurationFaults || point) {
95
+ const checked = point;
96
+ if (typeof checked.x !== "number" ||
97
+ !Number.isFinite(checked.x) ||
98
+ Math.abs(checked.x) > 100_000 ||
99
+ typeof checked.y !== "number" ||
100
+ !Number.isFinite(checked.y) ||
101
+ Math.abs(checked.y) > 100_000) {
102
+ reportConfigurationFault("invalid-position", "$.position", fault);
103
+ }
104
+ }
105
+ }
106
+ const styles = options.styles;
107
+ if (styles !== undefined) {
108
+ const checked = shape(styles, "invalid-styles", "$.styles", ["url", "integrity"], fault);
109
+ if (!collectConfigurationFaults || checked) {
110
+ const validated = checked;
111
+ if (typeof validated.url !== "string" ||
112
+ !isHttpPath(validated.url, baseUrl)) {
113
+ reportConfigurationFault("invalid-styles-url", "$.styles.url", fault);
114
+ }
115
+ if (!validStyleIntegrity(validated.integrity)) {
116
+ reportConfigurationFault("invalid-styles-integrity", "$.styles.integrity", fault);
117
+ }
118
+ }
119
+ }
120
+ let content;
121
+ try {
122
+ content = validateHostContent(options.content, baseUrl);
123
+ }
124
+ catch (cause) {
125
+ reportConfigurationFault("invalid-content", "$.content", fault, cause instanceof Error ? cause.message : String(cause));
126
+ if (collectConfigurationFaults)
127
+ content = {};
128
+ }
129
+ validateBindings(options.bindings, content, fault);
130
+ validateTheme(options.theme, fault);
131
+ validateDiagnostics(options.diagnostics, fault);
132
+ validateAccessibility(options.accessibility, fault);
133
+ for (const field of ["onDiagnostic", "logger"]) {
134
+ if (options[field] !== undefined && typeof options[field] !== "function") {
135
+ reportConfigurationFault("invalid-callback", `$.${field}`, fault, field);
136
+ }
137
+ }
138
+ return content;
139
+ }
140
+ export function validRuntimeName(value) {
141
+ return value === undefined || typeof value === "boolean" || text(value, 80);
142
+ }
143
+ function validateBindings(bindings, content, fault) {
144
+ let mounts;
145
+ if (bindings !== undefined) {
146
+ const checked = shape(bindings, "invalid-bindings", "$.bindings", ["mounts"], fault);
147
+ if ((!collectConfigurationFaults || checked) &&
148
+ checked.mounts !== undefined) {
149
+ const checkedMounts = shape(checked.mounts, "invalid-bindings", "$.bindings.mounts", undefined, fault);
150
+ if (!collectConfigurationFaults || checkedMounts) {
151
+ const validatedMounts = checkedMounts;
152
+ mounts = validatedMounts;
153
+ const entries = Object.entries(validatedMounts);
154
+ if (entries.length > 64) {
155
+ reportConfigurationFault("binding-limit", "$.bindings.mounts", fault);
156
+ }
157
+ for (const [id, mount] of entries) {
158
+ if (!NAME_PATTERN.test(id) || typeof mount !== "function") {
159
+ reportConfigurationFault("invalid-binding", `$.bindings.mounts.${id}`, fault);
160
+ }
161
+ }
162
+ }
163
+ }
164
+ }
165
+ for (const [id, item] of Object.entries(content)) {
166
+ for (const region of CONTENT_REGIONS) {
167
+ const value = item[region];
168
+ if (value &&
169
+ typeof value !== "string" &&
170
+ value.mountId &&
171
+ !Object.hasOwn(mounts ?? {}, value.mountId)) {
172
+ reportConfigurationFault("missing-binding", `$.content.${id}.${region}.mountId`, fault, value.mountId);
173
+ }
174
+ }
175
+ }
176
+ }
177
+ function validateTheme(theme, fault) {
178
+ if (theme === undefined)
179
+ return;
180
+ const checked = shape(theme, "invalid-theme", "$.theme", [
181
+ "background",
182
+ "color",
183
+ "linkColor",
184
+ "borderColor",
185
+ "radius",
186
+ "width",
187
+ "padding",
188
+ ], fault);
189
+ if (collectConfigurationFaults && !checked)
190
+ return;
191
+ const validated = checked;
192
+ for (const [field, minimum, maximum] of [
193
+ ["radius", 0, 64],
194
+ ["width", 120, 640],
195
+ ["padding", 0, 48],
196
+ ]) {
197
+ const value = validated[field];
198
+ if (value !== undefined &&
199
+ (typeof value !== "number" ||
200
+ !Number.isFinite(value) ||
201
+ value < minimum ||
202
+ value > maximum)) {
203
+ reportConfigurationFault("invalid-theme", `$.theme.${field}`, fault, field);
204
+ }
205
+ }
206
+ for (const field of [
207
+ "background",
208
+ "color",
209
+ "linkColor",
210
+ "borderColor",
211
+ ]) {
212
+ const value = validated[field];
213
+ if (value !== undefined && !isSurfaceColor(value)) {
214
+ reportConfigurationFault("invalid-theme", `$.theme.${field}`, fault, field);
215
+ }
216
+ }
217
+ }
218
+ function validateDiagnostics(diagnostics, fault) {
219
+ if (diagnostics === undefined)
220
+ return;
221
+ const checked = shape(diagnostics, "invalid-diagnostics", "$.diagnostics", ["console", "debug", "context"], fault);
222
+ if (collectConfigurationFaults && !checked)
223
+ return;
224
+ const validated = checked;
225
+ for (const field of ["console", "debug"]) {
226
+ if (validated[field] !== undefined &&
227
+ typeof validated[field] !== "boolean") {
228
+ reportConfigurationFault("invalid-diagnostics", `$.diagnostics.${field}`, fault, field);
229
+ }
230
+ }
231
+ const diagnosticContext = validated.context;
232
+ if (diagnosticContext === undefined)
233
+ return;
234
+ const context = shape(diagnosticContext, "invalid-diagnostic-context", "$.diagnostics.context", undefined, fault);
235
+ if (collectConfigurationFaults && !context)
236
+ return;
237
+ const entries = Object.entries(context);
238
+ if (entries.length > 16) {
239
+ reportConfigurationFault("diagnostic-context-limit", "$.diagnostics.context", fault);
240
+ }
241
+ for (const [key, value] of entries) {
242
+ if (!/^[a-z][a-z0-9_.-]{0,31}$/.test(key) ||
243
+ !["string", "number", "boolean"].includes(typeof value) ||
244
+ (typeof value === "string" && value.length > 64) ||
245
+ (typeof value === "number" && !Number.isFinite(value))) {
246
+ reportConfigurationFault("invalid-diagnostic-context", `$.diagnostics.context.${key}`, fault, key);
247
+ }
248
+ }
249
+ }
250
+ function validateAccessibility(accessibility, fault) {
251
+ if (accessibility === undefined)
252
+ return;
253
+ const checked = shape(accessibility, "invalid-accessibility", "$.accessibility", ["announceContent", "contentLabel"], fault);
254
+ if (collectConfigurationFaults && !checked)
255
+ return;
256
+ const validated = checked;
257
+ if (validated.announceContent !== undefined &&
258
+ typeof validated.announceContent !== "boolean") {
259
+ reportConfigurationFault("invalid-accessibility", "$.accessibility.announceContent", fault, "announceContent");
260
+ }
261
+ if (validated.contentLabel !== undefined &&
262
+ !text(validated.contentLabel, 120)) {
263
+ reportConfigurationFault("invalid-accessibility", "$.accessibility.contentLabel", fault, "contentLabel");
264
+ }
265
+ }
266
+ function shape(value, code, path, allowed, fault) {
267
+ if (!record(value)) {
268
+ reportConfigurationFault(code, path, fault);
269
+ if (collectConfigurationFaults)
270
+ return;
271
+ }
272
+ const checked = value;
273
+ if (allowed)
274
+ closed(checked, allowed, path, fault);
275
+ return checked;
276
+ }
277
+ function closed(value, allowed, path, fault) {
278
+ for (const key of Object.keys(value)) {
279
+ if (!allowed.includes(key)) {
280
+ reportConfigurationFault("unknown-field", `${path}.${key}`, fault);
281
+ }
282
+ }
283
+ }
284
+ function record(value) {
285
+ return typeof value === "object" && value !== null && !Array.isArray(value);
286
+ }
287
+ function text(value, maximum) {
288
+ return (typeof value === "string" &&
289
+ value.length > 0 &&
290
+ value.length <= maximum &&
291
+ !/[\u0000-\u001f\u007f]/.test(value));
292
+ }
293
+ function reportConfigurationFault(code, path, fault, detail) {
294
+ if (compactRuntimeDiagnostics) {
295
+ throw new PeeklingPreflightError(code, path, code);
296
+ }
297
+ fault(code, path, detail);
298
+ }
@@ -0,0 +1,44 @@
1
+ import { type ContentRegion, type HostContent, type HostBindings, type JsonValue, type Point, type SurfaceTheme } from "./types.js";
2
+ import { type RuntimeStyleAsset } from "./styles.js";
3
+ export declare function validateHostContent(input: HostContent | undefined, baseUrl: string): HostContent;
4
+ export declare function validateContentReferences(ids: readonly (string | undefined)[], content: HostContent): void;
5
+ export declare function placeContentRegion(region: ContentRegion, position: Point, viewport: {
6
+ width: number;
7
+ height: number;
8
+ }, character: {
9
+ width: number;
10
+ height: number;
11
+ }, surface: {
12
+ width: number;
13
+ height: number;
14
+ }): Point;
15
+ export interface ContentSelection {
16
+ id: string;
17
+ contentId: string;
18
+ data?: JsonValue;
19
+ key: string;
20
+ }
21
+ export interface ContentRendererOptions {
22
+ diagnostic?: (message: string) => void;
23
+ bindings?: HostBindings;
24
+ theme?: SurfaceTheme;
25
+ announce?: boolean;
26
+ label?: string;
27
+ emit?: (name: string, payload?: unknown) => import("./types.js").EmitResult;
28
+ wake?: () => void;
29
+ styles?: RuntimeStyleAsset;
30
+ }
31
+ export declare class ContentRenderer {
32
+ #private;
33
+ readonly ready: Promise<void>;
34
+ constructor(document: Document, options?: ContentRendererOptions);
35
+ renderSurfaces(selections: readonly ContentSelection[], content: HostContent, position: Point, viewport: {
36
+ width: number;
37
+ height: number;
38
+ }, character: {
39
+ width: number;
40
+ height: number;
41
+ }, name?: string): void;
42
+ destroy(): void;
43
+ }
44
+ //# sourceMappingURL=content.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,WAAW,EAGhB,KAAK,YAAY,EAGjB,KAAK,SAAS,EACd,KAAK,KAAK,EACV,KAAK,YAAY,EAClB,MAAM,YAAY,CAAC;AAIpB,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,aAAa,CAAC;AAErB,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,GAAG,SAAS,EAC9B,OAAO,EAAE,MAAM,GACd,WAAW,CA2Cb;AAyGD,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,SAAS,CAAC,MAAM,GAAG,SAAS,CAAC,EAAE,EACpC,OAAO,EAAE,WAAW,GACnB,IAAI,CAON;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,KAAK,EACf,QAAQ,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC3C,SAAS,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC5C,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzC,KAAK,CAwBP;AA8CD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,YAAY,EAAE,UAAU,CAAC;IAC5E,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED,qBAAa,eAAe;;IAC1B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IA2B9B,YAAY,QAAQ,EAAE,QAAQ,EAAE,OAAO,GAAE,sBAA2B,EAmCnE;IAED,cAAc,CACZ,UAAU,EAAE,SAAS,gBAAgB,EAAE,EACvC,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,KAAK,EACf,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAC3C,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAC5C,IAAI,CAAC,EAAE,MAAM,GACZ,IAAI,CAuIN;IAmXD,OAAO,IAAI,IAAI,CAQd;CA0DF"}