Build Mapbox GL styles by composing layers.
A build system lets you more easily maintain stylesheet variations by removing the need to make duplicative changes across multiple stylesheets.
This script assumes you have two directories:
context
: The variables this style defines that will be passed to layers during the buildtemplate
: The style, which is a Mapbox GL style, the only difference being that layers
is an array of layer ids.context
, which contains the variables passed from the style. The function
must return two objects:
baseStyle
: The base style objectoverrides
: Any overrides for to the baseStyle
, may be an empty object if no overrides are necessarySee the examples
directory for examples.
Once installed using your package manager:
mapbox-gl-style-build
--style-dir=templates/styles
--layer-dir=templates/layers
--out-dir=build
The parameters are as follows:
--style-dir
: the style directory as defined above--layer-dir
: the layer directory as defined above--out-dir
: the directory built styles will be placed within-v
: include for verbose outputAs a module, this library also exports two helper functions:
mergeOverrides
:
Merges overrides with a base style or other overrides. Typically you can rely on mapbox-gl-style-build
to add overrides to your layers' base styles, but sometimes it makes sense to merge overrides earlier in situations where a layer's styles are complicated.
Example:
// layer-template.js
const { mergeOverrides } = require('mapbox-gl-style-build');
module.exports.default = context => {
let baseStyle = {
id: 'example-layer',
type: 'fill',
paint: {
'fill-color': 'green'
}
};
let overrides = {};
if ((context.rootSource = 'source1')) {
overrides = mergeOverrides(overrides, {
paint: {
'fill-color': 'red'
}
});
}
if ((context.colorMode = 'dark')) {
// Add overrides to the existing overrides, if any.
//
// In thise case, only fill-opacity is added to the paint object, all other properties remain
overrides = mergeOverrides(overrides, {
paint: {
'fill-opacity': 0.2
}
});
}
};
mergeVariables
:
Merges a variables object with an extender object to override variable values.
Example:
// style-template.js
const { mergeVariables, modifyNumberVariables } = require('mapbox-gl-style-build');
const textSizes = require('../variables/textSizes');
module.exports.context = {
textSizes: mergeVariables(textSizes, { countryLabelSize: 16 }),
...
};
modifyNumberVariables
:
Takes a variable or object specifying variables and applies a math function to the values. Expression values have the math function applied to all outputs within the expression.
Supports the following operations:
*
: multiplication/
: division+
: addition-
: subtractionAlso added support for passing optional options object to round the modified value in different ways:
floor
: booleanceil
: booleanround
: booleantoFixed
: numberExample:
// style-template.js
const { mergeVariables, modifyNumberVariables } = require('mapbox-gl-style-build');
const textSizes = require('../variables/textSizes');
module.exports.context = {
textSizes: modifyNumberVariables(textSizes, '*', 2, { round: true }),
...
};
yarn install
yarn watch
src/
and they will be built into dist/
Implementation of the build system is most easily done with a combination of a provided script and manual work.
Based on the prerequisite decisions about primary differentiators for variants, this script can do the initial work of:
create-layer-templates
--in-dir=styles
--out-dir=templates
--base-style-path=styles/base-style.json
The parameters are as follows:
--in-dir
: the style directory containing existing variant styles to break out into template files--out-dir
: the directory to build your template files to--base-style-path
: the name of the style in the "in-dir" that is the base styleAfter running the implementation script, you may manually delete the initial styles directory unless reusing it for building the templates to. The script avoids this step as there may occasionally be reason to leave these pre-build-system styles for posterity.
Before running your script or otherwise setting up the file structure in your repo, all style PRs should be merged and style work should stop until the new repo structure is merged.
After merge, style work can begin again in parallel with further changes for the build system.
Further changes to templates will be a manual process that includes:
To reap the greatest benefit of a build system, you should consider addressing some prerequisites first:
context
in layers (can be style id if no larger grouping makes sense)After the build system is implemented, cartographers will no longer be able to make changes directly to a stylesheet. Instead all changes will be made directly to layer, variable, and style template files. These files will have to be built into output stylesheets via a command line tool provided by this library.
This means cartographers will be unable to make direct changes in an editor like Maputnik. If an editor is used to test style changes, those changes will need to be implemented by hand afterwards.
The build system will make certain large scale changes more difficult and others less difficult than editing stylesheets directly: