Expression engine extension points
Nobody has claimed this yet.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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