@safe-ugc-ui/validator 0.3.0 → 0.4.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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Safe UGC UI Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.d.ts CHANGED
@@ -14,7 +14,7 @@ import { UGCCard } from '@safe-ugc-ui/types';
14
14
  /**
15
15
  * Machine-readable error codes for every validation failure type.
16
16
  */
17
- type ValidationErrorCode = 'INVALID_JSON' | 'MISSING_FIELD' | 'INVALID_TYPE' | 'INVALID_VALUE' | 'UNKNOWN_NODE_TYPE' | 'SCHEMA_ERROR' | 'EXPR_NOT_ALLOWED' | 'REF_NOT_ALLOWED' | 'DYNAMIC_NOT_ALLOWED' | 'FORBIDDEN_STYLE_PROPERTY' | 'STYLE_VALUE_OUT_OF_RANGE' | 'FORBIDDEN_CSS_FUNCTION' | 'INVALID_COLOR' | 'INVALID_LENGTH' | 'FORBIDDEN_OVERFLOW_VALUE' | 'TRANSFORM_SKEW_FORBIDDEN' | 'EXTERNAL_URL' | 'POSITION_FIXED_FORBIDDEN' | 'POSITION_STICKY_FORBIDDEN' | 'POSITION_ABSOLUTE_NOT_IN_STACK' | 'ASSET_PATH_TRAVERSAL' | 'INVALID_ASSET_PATH' | 'PROTOTYPE_POLLUTION' | 'CARD_SIZE_EXCEEDED' | 'TEXT_CONTENT_SIZE_EXCEEDED' | 'STYLE_SIZE_EXCEEDED' | 'NODE_COUNT_EXCEEDED' | 'LOOP_ITERATIONS_EXCEEDED' | 'NESTED_LOOPS_EXCEEDED' | 'OVERFLOW_AUTO_COUNT_EXCEEDED' | 'OVERFLOW_AUTO_NESTED' | 'STACK_NESTING_EXCEEDED' | 'EXPR_TOO_LONG' | 'REF_TOO_LONG' | 'EXPR_TOO_MANY_TOKENS' | 'EXPR_NESTING_TOO_DEEP' | 'EXPR_CONDITION_NESTING_TOO_DEEP' | 'EXPR_REF_DEPTH_EXCEEDED' | 'EXPR_ARRAY_INDEX_EXCEEDED' | 'EXPR_STRING_LITERAL_TOO_LONG' | 'EXPR_FORBIDDEN_TOKEN' | 'EXPR_FUNCTION_CALL' | 'EXPR_INVALID_TOKEN' | 'LOOP_SOURCE_NOT_ARRAY' | 'LOOP_SOURCE_MISSING' | 'STYLE_CIRCULAR_REF' | 'STYLE_REF_NOT_FOUND' | 'INVALID_STYLE_REF' | 'INVALID_STYLE_NAME' | 'INVALID_HOVER_STYLE' | 'HOVER_STYLE_NESTED' | 'TRANSITION_RAW_STRING' | 'TRANSITION_COUNT_EXCEEDED' | 'TRANSITION_PROPERTY_FORBIDDEN';
17
+ type ValidationErrorCode = 'INVALID_JSON' | 'MISSING_FIELD' | 'INVALID_TYPE' | 'INVALID_VALUE' | 'UNKNOWN_NODE_TYPE' | 'SCHEMA_ERROR' | 'REF_NOT_ALLOWED' | 'DYNAMIC_NOT_ALLOWED' | 'FORBIDDEN_STYLE_PROPERTY' | 'STYLE_VALUE_OUT_OF_RANGE' | 'FORBIDDEN_CSS_FUNCTION' | 'INVALID_COLOR' | 'INVALID_LENGTH' | 'FORBIDDEN_OVERFLOW_VALUE' | 'TRANSFORM_SKEW_FORBIDDEN' | 'EXTERNAL_URL' | 'POSITION_FIXED_FORBIDDEN' | 'POSITION_STICKY_FORBIDDEN' | 'POSITION_ABSOLUTE_NOT_IN_STACK' | 'ASSET_PATH_TRAVERSAL' | 'INVALID_ASSET_PATH' | 'PROTOTYPE_POLLUTION' | 'CARD_SIZE_EXCEEDED' | 'TEXT_CONTENT_SIZE_EXCEEDED' | 'STYLE_SIZE_EXCEEDED' | 'NODE_COUNT_EXCEEDED' | 'LOOP_ITERATIONS_EXCEEDED' | 'NESTED_LOOPS_EXCEEDED' | 'OVERFLOW_AUTO_COUNT_EXCEEDED' | 'OVERFLOW_AUTO_NESTED' | 'STACK_NESTING_EXCEEDED' | 'LOOP_SOURCE_NOT_ARRAY' | 'LOOP_SOURCE_MISSING' | 'STYLE_CIRCULAR_REF' | 'STYLE_REF_NOT_FOUND' | 'INVALID_STYLE_REF' | 'INVALID_STYLE_NAME' | 'INVALID_HOVER_STYLE' | 'HOVER_STYLE_NESTED' | 'TRANSITION_RAW_STRING' | 'TRANSITION_COUNT_EXCEEDED' | 'TRANSITION_PROPERTY_FORBIDDEN';
18
18
  /**
19
19
  * A single validation error with location and diagnostic info.
20
20
  */
@@ -101,7 +101,6 @@ interface TraversableNode {
101
101
  type: string;
102
102
  children?: TraversableNode[] | ForLoopLike;
103
103
  style?: Record<string, unknown>;
104
- condition?: unknown;
105
104
  [key: string]: unknown;
106
105
  }
107
106
  interface ForLoopLike {
@@ -182,29 +181,29 @@ declare function validateNodes(views: Record<string, unknown>): ValidationError[
182
181
  /**
183
182
  * @safe-ugc-ui/validator — Value Type Validation
184
183
  *
185
- * Validates per-property $ref / $expr permission rules based on spec
184
+ * Validates per-property $ref permission rules based on spec
186
185
  * section 4.5 value type table.
187
186
  *
188
- * | Property Type | Literal | $ref | $expr |
189
- * |-------------------|---------|------|-------|
190
- * | Image.src | yes | yes | no |
191
- * | Avatar.src | yes | yes | no |
192
- * | Icon.name | yes | no | no |
193
- * | Text.content | yes | yes | yes |
194
- * | Color properties | yes | yes | yes |
195
- * | Size properties | yes | yes | yes |
196
- * | position | yes | no | no |
197
- * | transform | yes | no | no |
198
- * | gradient | yes | no | no |
199
- *
200
- * Additionally, several style properties must always be static
201
- * (no $ref or $expr): overflow, border*, boxShadow, zIndex,
202
- * and position offset properties (top/right/bottom/left).
187
+ * | Property Type | Literal | $ref |
188
+ * |-------------------|---------|------|
189
+ * | Image.src | yes | yes |
190
+ * | Avatar.src | yes | yes |
191
+ * | Icon.name | yes | yes |
192
+ * | Text.content | yes | yes |
193
+ * | Color properties | yes | yes |
194
+ * | Size properties | yes | yes |
195
+ * | position | yes | no |
196
+ * | overflow | yes | no |
197
+ * | zIndex | yes | no |
198
+ * | structured style objects | object literal | top-level $ref no |
199
+ *
200
+ * Structured style objects such as border/transform/boxShadow/backgroundGradient
201
+ * must remain object literals, but selected leaf fields inside them may use $ref.
203
202
  */
204
203
 
205
204
  /**
206
205
  * Walk all nodes in the card and validate that each field's value
207
- * respects its allowed value types ($ref / $expr permissions).
206
+ * respects its allowed value types ($ref permissions).
208
207
  *
209
208
  * @param views - The `views` object from a UGCCard.
210
209
  * @returns An array of validation errors (empty if all values are valid).
@@ -310,28 +309,6 @@ declare function validateLimits(card: {
310
309
  cardStyles?: Record<string, Record<string, unknown>>;
311
310
  }): ValidationError[];
312
311
 
313
- /**
314
- * @safe-ugc-ui/validator -- Expression & Reference Constraint Validation
315
- *
316
- * Validates $expr and $ref values found in the card tree against the
317
- * constraints defined in the spec's "expression constraint" section (6.3).
318
- *
319
- * A simple tokenizer splits expression strings into typed tokens so that
320
- * structural limits (nesting, token count, forbidden operators) can be
321
- * checked without executing the expression.
322
- */
323
-
324
- /**
325
- * Validates all $expr and $ref values found in the card's views.
326
- *
327
- * Uses tree traversal to visit every node, then deep-scans each node's
328
- * flattened node fields and `style` (and `condition`) for dynamic values.
329
- *
330
- * @param views - The `views` object from a UGCCard.
331
- * @returns An array of validation errors (empty if all constraints pass).
332
- */
333
- declare function validateExprConstraints(views: Record<string, unknown>): ValidationError[];
334
-
335
312
  /**
336
313
  * @safe-ugc-ui/validator — Public API
337
314
  *
@@ -349,7 +326,7 @@ declare function validateExprConstraints(views: Record<string, unknown>): Valida
349
326
  * 2. (validateRaw only) JSON.parse — parse error → ValidationResult
350
327
  * 3. Schema validation → fail → early return
351
328
  * 4. All remaining checks run, errors accumulated:
352
- * node → value-types → style → security → limits → expr-constraints
329
+ * node → value-types → style → security → limits
353
330
  */
354
331
 
355
332
  /**
@@ -359,7 +336,7 @@ declare function validateExprConstraints(views: Record<string, unknown>): Valida
359
336
  *
360
337
  * Pipeline:
361
338
  * 1. Schema validation → fail → early return
362
- * 2. All remaining checks (node, value-types, style, security, limits, expr)
339
+ * 2. All remaining checks (node, value-types, style, security, limits)
363
340
  *
364
341
  * @param input - An unknown value (typically parsed JSON).
365
342
  * @returns A ValidationResult — safe to render only if `valid` is true.
@@ -382,4 +359,4 @@ declare function validate(input: unknown): ValidationResult;
382
359
  */
383
360
  declare function validateRaw(rawJson: string): ValidationResult;
384
361
 
385
- export { type NodeVisitor, type TraversableNode, type TraversalContext, type ValidationError, type ValidationErrorCode, type ValidationResult, createError, invalidResult, merge, parseCard, toResult, traverseCard, traverseNode, validResult, validate, validateExprConstraints, validateLimits, validateNodes, validateRaw, validateSchema, validateSecurity, validateStyles, validateValueTypes };
362
+ export { type NodeVisitor, type TraversableNode, type TraversalContext, type ValidationError, type ValidationErrorCode, type ValidationResult, createError, invalidResult, merge, parseCard, toResult, traverseCard, traverseNode, validResult, validate, validateLimits, validateNodes, validateRaw, validateSchema, validateSecurity, validateStyles, validateValueTypes };