Skip to content

Conversation

@mattpodwysocki
Copy link
Contributor

@mattpodwysocki mattpodwysocki commented Jan 8, 2026

Summary

Adds a comprehensive offline Mapbox expression validation tool that checks style expressions for correctness without requiring API access.

Features

  • ✅ Validates 90+ Mapbox expression operators:

    • Decision: case, match, coalesce
    • Lookup: get, has, in, index-of, length, slice
    • Math: +, -, *, /, %, ^, min, max, round, floor, ceil, abs, sqrt, log10, log2, ln, e, pi
    • Comparison: ==, !=, >, <, >=, <=
    • Logical: !, all, any
    • String: concat, downcase, upcase
    • Color: rgb, rgba, to-rgba
    • Type conversion: array, boolean, number, string, to-boolean, to-color, to-number, to-string, typeof
    • Interpolation: interpolate, step
    • Feature data: get, has, feature-state, geometry-type, id, properties
    • Camera: zoom, pitch, distance-from-center
    • Variable binding: let, var
  • ✅ Comprehensive validation checks:

    • Expression syntax (array format, string operators)
    • Operator validity
    • Argument count validation for each operator
    • Recursive validation of nested expressions
    • Expression depth analysis (warns about deeply nested expressions)
  • ✅ Structured validation results:

    • valid boolean flag
    • errors array (critical issues)
    • warnings array (non-critical issues like deep nesting)
    • info array (informational messages)
    • metadata object (expressionType, returnType, depth)
  • ✅ Developer-friendly:

    • Detailed error messages with expression paths
    • Actionable suggestions for fixing issues
    • Accepts both JSON strings and expression arrays as input

Implementation Details

  • Architecture: Extends BaseTool (offline, no HttpRequest dependency)
  • Testing: 25 comprehensive test cases covering:
    • Literal expressions (strings, numbers, booleans)
    • Valid expressions (all operator categories)
    • Invalid expressions (syntax errors, unknown operators, wrong argument counts)
    • Nested expressions
    • Error handling
    • Metadata validation
  • Documentation: Added to README with examples and usage patterns

Test Results

All 395 tests pass ✅

Example Usage

{
  "expression": ["case", ["==", ["get", "type"], "park"], "green", "gray"]
}

Returns:

{
  "valid": true,
  "errors": [],
  "warnings": [],
  "info": [],
  "metadata": {
    "expressionType": "case",
    "depth": 1
  }
}

Error Example

{
  "expression": ["unknown_operator", "value"]
}

Returns:

{
  "valid": false,
  "errors": [
    {
      "severity": "error",
      "message": "Unknown expression operator: \"unknown_operator\"",
      "path": "[0]",
      "suggestion": "Use a valid Mapbox expression operator (e.g., \"get\", \"case\", \"match\")"
    }
  ]
}

Testing


Test 1: Valid Simple Expression ✅

Validate this Mapbox expression:

  ["get", "name"]

Expected: Valid - gets the "name" property from a feature

Screenshot 2026-01-09 at 12 54 04

Test 2: Valid Conditional Expression ✅

Can you validate this expression?

  ["case",
    ["==", ["get", "type"], "park"], "green",
    ["==", ["get", "type"], "water"], "blue",
    "gray"
  ]

Expected: Valid - conditional styling based on feature type

Screenshot 2026-01-09 at 12 54 58

Test 3: Valid Math Expression ✅

Validate this:

  ["*", ["get", "population"], 0.001]

Expected: Valid - multiplies population by 0.001

Screenshot 2026-01-09 at 17 44 44

Test 4: Invalid Operator ❌

Check this expression:

  ["unknown_operator", "value"]

Expected:

  • Invalid
  • Error: Unknown expression operator "unknown_operator"
  • Suggestion: Use valid operators like "get", "case", "match"
Screenshot 2026-01-09 at 12 58 27

Test 5: Wrong Argument Count ❌

Is this valid?

  ["get"]

Expected:

  • Invalid
  • Error: Operator "get" requires at least 1 argument, got 0
  • Suggestion: "get" expects arguments like ["get", "propertyName"]
Screenshot 2026-01-09 at 17 46 22

Test 6: Valid Interpolation Expression ✅

Validate this interpolation:

  ["interpolate",
    "linear",
    ["zoom"],
    10, 1,
    15, 5,
    20, 10
  ]

Expected: Valid - interpolates circle radius based on zoom level

Screenshot 2026-01-09 at 17 47 54

Test 7: Nested Expression with Error ❌

Check this nested expression:

  ["case",
    ["bad_operator", ["get", "type"]],
    "red",
    "blue"
  ]

Expected:

  • Invalid
  • Error: Unknown operator "bad_operator" in nested expression
  • Shows path to where the error occurs
Screenshot 2026-01-09 at 18 06 59

Test 8: Valid String Expression ✅

Validate:

  ["concat", "Street: ", ["get", "street_name"]]

Expected: Valid - concatenates strings for labels

Screenshot 2026-01-09 at 18 08 57

Test 9: Valid Color Expression ✅

Is this valid?

  ["rgb", 255, 100, 50]

Expected: Valid - creates RGB color

Screenshot 2026-01-09 at 18 09 39

Test 10: Complex Valid Expression ✅

Validate this complex expression:

  ["interpolate",
    ["exponential", 1.5],
    ["get", "population"],
    0, ["rgb", 255, 255, 178],
    100000, ["rgb", 254, 204, 92],
    1000000, ["rgb", 253, 141, 60],
    10000000, ["rgb", 227, 26, 28]
  ]

Expected: Valid - data-driven color based on population with exponential interpolation

Screenshot 2026-01-09 at 18 10 19

Related

Part of a series of offline validation tools being added to the server:

This commit adds a comprehensive Mapbox expression validation tool that
performs offline validation of style expressions without requiring API access.

Features:
- Validates all Mapbox expression operators (90+ operators supported)
- Checks expression syntax (array format, string operators)
- Validates argument counts for each operator
- Recursive validation of nested expressions
- Detects and warns about deeply nested expressions (depth > 10)
- Returns structured errors, warnings, and info messages with suggestions
- Provides metadata (expressionType, returnType, depth)
- Accepts both JSON strings and expression arrays as input

Supported operator categories:
- Decision: case, match, coalesce
- Lookup: get, has, in, index-of, length
- Math: +, -, *, /, %, ^, min, max, round, floor, ceil, abs, sqrt, log10, log2, ln, e, pi
- Comparison: ==, !=, >, <, >=, <=
- Logical: !, all, any
- String: concat, downcase, upcase
- Color: rgb, rgba, to-rgba
- Type conversion: array, boolean, number, string, to-boolean, to-color, to-number, to-string, typeof
- Interpolation: interpolate, step
- Feature data: get, has, feature-state, geometry-type, id, properties
- Camera: zoom, pitch, distance-from-center
- Variable binding: let, var

The tool is implemented as a BaseTool (offline, no HttpRequest dependency)
and includes 25 comprehensive test cases covering literals, valid expressions,
invalid expressions, nested expressions, error handling, and metadata.

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
@mattpodwysocki mattpodwysocki requested a review from a team as a code owner January 8, 2026 20:34
mattpodwysocki added a commit that referenced this pull request Jan 9, 2026
…roduction prompt

Adds comprehensive style quality validation capabilities:

Skill:
- Created mapbox-style-quality skill document (390+ lines)
- Pre-production checklist and validation best practices
- Guidance on expression validation, GeoJSON validation, and accessibility
- Optimization strategies and workflow recommendations
- Integration patterns for Git hooks, CI/CD, and code review

Prompt:
- Created prepare-style-for-production prompt
- Orchestrates validation workflow using 5 quality tools:
  * validate_expression_tool - Validate expressions in filters/paint/layout
  * validate_geojson_tool - Validate GeoJSON sources
  * check_color_contrast_tool - WCAG accessibility compliance
  * optimize_style_tool - Remove redundancies and optimize
  * compare_styles_tool - Compare versions (implicit in workflow)
- Configurable WCAG level (AA/AAA) and optional optimization skip
- Generates comprehensive quality report with deployment readiness assessment

Testing:
- 15 test cases for PrepareStyleForProductionPrompt
- All 386 tests passing
- Updated prompt registry tests

Documentation:
- Updated README with new skill listing
- Added prompt documentation with usage examples
- Cross-referenced skill and prompt

Related PRs:
- PR #50: validate_geojson_tool
- PR #51: validate_expression_tool
- PR #52: compare_styles_tool
- PR #53: check_color_contrast_tool
- PR #54: optimize_style_tool

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant