mapbox / mapbox/mapbox-gl-js

Expression engine extension points

Open
#9,462 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

needs discussion :speech_balloon:
Dominant language
TypeScript
Stars
12.4k
Forks
2.4k
PR merge metrics
No merged PRs in 30d

Description

## Motivation

I repeatedly find myself forking and extending `mapbox-gl` for various projects where the functionality of the readily available expressions feels lacking. This mostly involves adding ad-hoc functions to the second argument of `CompoundExpression.register()` in [`definitions/index.js`](https://github.com/mapbox/mapbox-gl-js/blob/8f342c18a9ff21768bb8b686c6dfeb2aeeb70838/src/style-spec/expression/definitions/index.js#L123).

Past use cases include:
- Using some expression that was unavailable at the time (mostly the `in` expression – this was implemented since)
- Implementing some performance-critical, project-specific functionality – some of which could have been done using the LISP-like syntax as well, but was more performant using Javascript.

For this reason, I propose a way for end users to be able to extend the list of built-in expression functions by supplying their own Javascript (or C++, in the case of `gl-native`) implementations. This would allow the user to use the full potential of the underlying Javascript runtime to specify feature styles during render time.

Similar functionality is available in mainstream desktop GIS software as well, see:
- [Using Custom Python Expression Functions (QGIS3)](https://www.qgistutorials.com/en/docs/3/custom_python_functions.html)
- [Text formatting tags (ArcGIS Pro)](https://pro.arcgis.com/en/pro-app/help/mapping/text/text-formatting-tags.htm)

...and also in OpenLayers:

- [StyleFunction (OpenLayers API)](https://openlayers.org/en/latest/apidoc/module-ol_style_Style.html#~StyleFunction)

(Please note that this is orthogonal to #7010 which proposes a way to define first-class functions _inside_ the expression language.)

## Design Alternatives

- Do nothing: as noted above, forking `mapbox-gl` is always an option for those who want to do this.

## Design

I do realize that you probably consciously chose _not_ to implement this in the past, although I failed to find a write up on the exact reasons (been reading [discussions](https://github.com/mapbox/mapbox-gl-function/issues/28) in the old `mapbox-gl-function` repo etc.).

### Mock-Up

This is modelled after how expression functions are defined in [`definitions/index.js`](https://github.com/mapbox/mapbox-gl-js/blob/8f342c18a9ff21768bb8b686c6dfeb2aeeb70838/src/style-spec/expression/definitions/index.js#L123).

Note that I'm using the type names defined in [`compound_expression.js`](https://github.com/mapbox/mapbox-gl-js/blob/8f342c18a9ff21768bb8b686c6dfeb2aeeb70838/src/style-spec/expression/compound_expression.js#L14)

```js
map.registerExpression(
'my-function', // Function name
StringType, // Type
[ValueType], // Signature
(evaluationContext, args) => {
...
} // Evaluate
);
```

### Concepts

Another thing that makes this potentially unfeasible is that this exposes a large number of concepts, classes and types internal to mapbox-gl, such as `EvaluationContext`, the above mentioned types in `compound_expression.js` etc.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading CompoundExpression.register() in src/style-spec/expression/definitions/index.js and the type names in src/style-spec/expression/compound_expression.js. Compare those existing extension points with the proposed map.registerExpression() mock-up. Done would require a settled design for registering and evaluating user-defined expression functions, including the exposed concepts and types.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
frontend, web-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.