diff --git a/.circleci/config.yml b/.circleci/config.yml index ab5f96bf396..8d4fa648104 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -200,8 +200,11 @@ jobs: name: Build command: BENCHMARK_VERSION="${CIRCLE_TAG:-$CIRCLE_BRANCH} $(git rev-parse --short=7 HEAD)" yarn run build-benchmarks - run: - name: Upload + name: Upload benchmark command: aws s3 cp --acl public-read --content-type application/javascript bench/versions/benchmarks_generated.js s3://mapbox-gl-js/${CIRCLE_TAG:-$CIRCLE_BRANCH}/benchmarks.js + - run: + name: Upload source maps + command: aws s3 cp --acl public-read --content-type application/javascript bench/versions/benchmarks_generated.js.map s3://mapbox-gl-js/${CIRCLE_TAG:-$CIRCLE_BRANCH}/benchmarks.js.map deploy-release: <<: *defaults diff --git a/.flowconfig b/.flowconfig index 6707ec53291..0aaae7a8923 100644 --- a/.flowconfig +++ b/.flowconfig @@ -1,5 +1,6 @@ [ignore] .*/node_modules/@mapbox/jsonlint-lines-primitives/.* +.*/node_modules/jsonlint-lines/.* .*/node_modules/stylelint/.* .*/node_modules/unflowify/.* .*/node_modules/flow-coverage-report/.* @@ -17,4 +18,7 @@ .*/_site/.* [version] -0.91.0 +0.95.1 + +[options] +server.max_workers=4 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ca536ab3dec..3d17e3beb7e 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,3 +10,4 @@ - [ ] post benchmark scores - [ ] manually test the debug page - [ ] tagged `@mapbox/studio` and/or `@mapbox/maps-design` if this PR includes style spec changes + - [ ] tagged `@mapbox/gl-native` if this PR includes shader changes or needs a native port diff --git a/.gitignore b/.gitignore index 96f74f72a6f..24de88105db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,7 @@ /rollup/build/ /docs/components/api.json /dist/ -/docs/pages/dist/mapbox-gl-dev.js -/docs/pages/dist/mapbox-gl.js -/docs/pages/dist/mapbox-gl-unminified.js +/docs/pages/dist/ /docs/img/dist/ *.js.map node_modules @@ -13,12 +11,8 @@ coverage flow-coverage .DS_Store .nyc_output -bench/versions/benchmarks_generated.js -bench/versions/benchmarks_view_generated.js -bench/styles/benchmarks_generated.js -bench/styles/benchmarks_view_generated.js -debug/access_token_generated.js -debug/style_property_editor_generated.js +*_generated.js +*_generated.js.map test/integration/**/index*.html test/integration/**/actual.png test/integration/**/actual.json diff --git a/CHANGELOG.md b/CHANGELOG.md index c1a5a1ffdd4..fbf8f4da335 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,43 @@ +## 0.54.0 + +### Breaking changes + +- Turned `localIdeographFontFamily` map option on by default. This may change how CJK labels are rendered, but dramatically improves performance of CJK maps (because the browser no longer needs to download heavy amounts of font data from the server). Add `localIdeographyFontFamily: false` to turn this off. [#8008](https://github.com/mapbox/mapbox-gl-js/pull/8008) +- Added `Popup` `maxWidth` option, set to `"240px"` by default. [#7906](https://github.com/mapbox/mapbox-gl-js/pull/7906) + +### Major features + +- Added support for updating and animating style images. [#7999](https://github.com/mapbox/mapbox-gl-js/pull/7999) +- Added support for generating style images dynamically (e.g. for drawing icons based on feature properties). [#7987](https://github.com/mapbox/mapbox-gl-js/pull/7987) +- Added antialiasing support for custom layers. [#7821](https://github.com/mapbox/mapbox-gl-js/pull/7821) +- Added a new `mapbox-gl-csp.js` bundle for strict CSP environments where `worker-src: blob` is disallowed. [#8044](https://github.com/mapbox/mapbox-gl-js/pull/8044) + +### Minor features and improvements + +- Improved performance of fill extrusions. [#7821](https://github.com/mapbox/mapbox-gl-js/pull/7821) +- Improved performance of symbol layers. [#7967](https://github.com/mapbox/mapbox-gl-js/pull/7967) +- Slightly improved rendering performance in general. [#7969](https://github.com/mapbox/mapbox-gl-js/pull/7969) +- Slightly improved performance of HTML markers. [#8018](https://github.com/mapbox/mapbox-gl-js/pull/8018) +- Improved diffing of styles with `"visibility": "visible"`. [#8005](https://github.com/mapbox/mapbox-gl-js/pull/8005) +- Improved zoom buttons to grey out when reaching min/max zoom. [#8023](https://github.com/mapbox/mapbox-gl-js/pull/8023) +- Added a title to fullscreen control button. [#8012](https://github.com/mapbox/mapbox-gl-js/pull/8012) +- Added `rel="noopener"` attributes to links that lead to external websites (such as Mapbox logo and OpenStreetMap edit link) for improved security. [#7914](https://github.com/mapbox/mapbox-gl-js/pull/7914) +- Added tile size info when `map.showTileBoundaries` is turned on. [#7963](https://github.com/mapbox/mapbox-gl-js/pull/7963) +- Significantly improved load times of the benchmark suite. [#8066](https://github.com/mapbox/mapbox-gl-js/pull/8066) +- Improved behavior of `canvasSource.pause` to be more reliable and able to render a single frame. [#8130](https://github.com/mapbox/mapbox-gl-js/pull/8130) + +### Bug fixes + +- Fixed a bug in Mac Safari 12+ where controls would disappear until you interact with the map. [8193](https://github.com/mapbox/mapbox-gl-js/pull/8193) +- Fixed a memory leak when calling `source.setData(url)` many times. [#8035](https://github.com/mapbox/mapbox-gl-js/pull/8035) +- Fixed a bug where marker lost focus when dragging. [#7799](https://github.com/mapbox/mapbox-gl-js/pull/7799) +- Fixed a bug where `map.getCenter()` returned a reference to an internal `LngLat` object instead of cloning it, leading to potential mutability bugs. [#7922](https://github.com/mapbox/mapbox-gl-js/pull/7922) +- Fixed a bug where default HTML marker positioning was slightly off. [#8074](https://github.com/mapbox/mapbox-gl-js/pull/8074) +- Fixed a bug where adding a fill extrusion layer for non-polygon layers would lead to visual artifacts. [#7685](https://github.com/mapbox/mapbox-gl-js/pull/7685) +- Fixed intermittent Flow failures on CI. [#8061](https://github.com/mapbox/mapbox-gl-js/pull/8061) +- Fixed a bug where calling `Map#removeFeatureState` does not remove the state from some tile zooms [#8087](https://github.com/mapbox/mapbox-gl-js/pull/8087) +- Fixed a bug where `removeFeatureState` didn't work on features with `id` equal to `0`. [#8150](https://github.com/mapbox/mapbox-gl-js/pull/8150) + ## 0.53.1 ## Bug fixes diff --git a/README.md b/README.md index 01cf3eedfde..fa971eecb03 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ [Mapbox](https://www.mapbox.com/) **Mapbox GL JS** is a JavaScript library for interactive, customizable vector maps on the web. It takes map styles that conform to the -[Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec), applies them to vector tiles that +[Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/), applies them to vector tiles that conform to the [Mapbox Vector Tile Specification](https://github.com/mapbox/vector-tile-spec), and renders them using WebGL. Mapbox GL JS is part of the [cross-platform Mapbox GL ecosystem](https://www.mapbox.com/maps/), which also includes -compatible native SDKs for applications on [Android](https://www.mapbox.com/android-sdk/), -[iOS](https://www.mapbox.com/ios-sdk/), [macOS](http://mapbox.github.io/mapbox-gl-native/macos), +compatible native SDKs for applications on [Android](https://docs.mapbox.com/android/maps/overview/), +[iOS](https://docs.mapbox.com/ios/maps/overview/), [macOS](http://mapbox.github.io/mapbox-gl-native/macos), [Qt](https://github.com/mapbox/mapbox-gl-native/tree/master/platform/qt), and [React Native](https://github.com/mapbox/react-native-mapbox-gl/). Mapbox provides building blocks to add location features like maps, search, and navigation into any experience you create. To get started with GL JS or any of our other building blocks, [sign up for a Mapbox account](https://www.mapbox.com/signup/). @@ -16,13 +16,12 @@ In addition to GL JS, this repository contains code, issues, and test fixtures t native SDKs. For code and issues specific to the native SDKs, see the [mapbox/mapbox-gl-native](https://github.com/mapbox/mapbox-gl-native/) repository. -- [Getting started with Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/) -- [Tutorials](https://www.mapbox.com/help/tutorials/#web-apps) -- [API documentation](https://www.mapbox.com/mapbox-gl-js/api/) -- [Examples](https://www.mapbox.com/mapbox-gl-js/examples/) -- [Style documentation](https://www.mapbox.com/mapbox-gl-js/style-spec/) +- [Getting started with Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/overview/) +- [Tutorials](https://docs.mapbox.com/help/tutorials/#web-apps) +- [API documentation](https://docs.mapbox.com/mapbox-gl-js/api/) +- [Examples](https://docs.mapbox.com/mapbox-gl-js/examples/) +- [Style documentation](https://docs.mapbox.com/mapbox-gl-js/style-spec/) - [Open source styles](https://github.com/mapbox/mapbox-gl-styles) -- [Roadmap](https://www.mapbox.com/mapbox-gl-js/roadmap/) - [Contributor documentation](https://github.com/mapbox/mapbox-gl-js/blob/master/CONTRIBUTING.md) [Mapbox GL gallery](https://www.mapbox.com/gallery/) diff --git a/bench/benchmarks/expressions.js b/bench/benchmarks/expressions.js index 01ed5784780..fc2a4e63cac 100644 --- a/bench/benchmarks/expressions.js +++ b/bench/benchmarks/expressions.js @@ -71,7 +71,7 @@ class ExpressionBenchmark extends Benchmark { } } -class FunctionCreate extends ExpressionBenchmark { +export class FunctionCreate extends ExpressionBenchmark { bench() { for (const {rawValue, propertySpec} of this.data) { createFunction(rawValue, propertySpec); @@ -79,7 +79,7 @@ class FunctionCreate extends ExpressionBenchmark { } } -class FunctionEvaluate extends ExpressionBenchmark { +export class FunctionEvaluate extends ExpressionBenchmark { bench() { for (const {compiledFunction} of this.data) { compiledFunction.evaluate({zoom: 0}); @@ -87,7 +87,7 @@ class FunctionEvaluate extends ExpressionBenchmark { } } -class FunctionConvert extends ExpressionBenchmark { +export class FunctionConvert extends ExpressionBenchmark { bench() { for (const {rawValue, propertySpec} of this.data) { convertFunction(rawValue, propertySpec); @@ -95,7 +95,7 @@ class FunctionConvert extends ExpressionBenchmark { } } -class ExpressionCreate extends ExpressionBenchmark { +export class ExpressionCreate extends ExpressionBenchmark { bench() { for (const {rawExpression, propertySpec} of this.data) { createPropertyExpression(rawExpression, propertySpec); @@ -103,18 +103,10 @@ class ExpressionCreate extends ExpressionBenchmark { } } -class ExpressionEvaluate extends ExpressionBenchmark { +export class ExpressionEvaluate extends ExpressionBenchmark { bench() { for (const {compiledExpression} of this.data) { compiledExpression.evaluate({zoom: 0}); } } } - -export default [ - FunctionCreate, - FunctionConvert, - FunctionEvaluate, - ExpressionCreate, - ExpressionEvaluate -]; diff --git a/bench/benchmarks/layers.js b/bench/benchmarks/layers.js index 4cd5bb67e27..a63e25e40ef 100644 --- a/bench/benchmarks/layers.js +++ b/bench/benchmarks/layers.js @@ -15,7 +15,7 @@ function generateLayers(layer) { return generated; } -class LayerBenchmark extends Benchmark { +export class LayerBenchmark extends Benchmark { setup() { return createMap({ zoom: 16, @@ -37,7 +37,7 @@ class LayerBenchmark extends Benchmark { } } -class LayerBackground extends LayerBenchmark { +export class LayerBackground extends LayerBenchmark { constructor() { super(); @@ -50,7 +50,7 @@ class LayerBackground extends LayerBenchmark { } } -class LayerCircle extends LayerBenchmark { +export class LayerCircle extends LayerBenchmark { constructor() { super(); @@ -65,7 +65,7 @@ class LayerCircle extends LayerBenchmark { } } -class LayerFill extends LayerBenchmark { +export class LayerFill extends LayerBenchmark { constructor() { super(); @@ -84,7 +84,7 @@ class LayerFill extends LayerBenchmark { } } -class LayerFillExtrusion extends LayerBenchmark { +export class LayerFillExtrusion extends LayerBenchmark { constructor() { super(); @@ -102,7 +102,7 @@ class LayerFillExtrusion extends LayerBenchmark { } } -class LayerHeatmap extends LayerBenchmark { +export class LayerHeatmap extends LayerBenchmark { setup() { return fetch('/bench/data/naturalearth-land.json') .then(response => response.json()) @@ -144,7 +144,7 @@ class LayerHeatmap extends LayerBenchmark { } } -class LayerHillshade extends LayerBenchmark { +export class LayerHillshade extends LayerBenchmark { constructor() { super(); @@ -164,7 +164,7 @@ class LayerHillshade extends LayerBenchmark { } } -class LayerLine extends LayerBenchmark { +export class LayerLine extends LayerBenchmark { constructor() { super(); @@ -179,7 +179,7 @@ class LayerLine extends LayerBenchmark { } } -class LayerRaster extends LayerBenchmark { +export class LayerRaster extends LayerBenchmark { constructor() { super(); @@ -200,7 +200,7 @@ class LayerRaster extends LayerBenchmark { } } -class LayerSymbol extends LayerBenchmark { +export class LayerSymbol extends LayerBenchmark { constructor() { super(); @@ -218,16 +218,3 @@ class LayerSymbol extends LayerBenchmark { }); } } - - -export default [ - LayerBackground, - LayerCircle, - LayerFill, - LayerFillExtrusion, - LayerHeatmap, - LayerHillshade, - LayerLine, - LayerRaster, - LayerSymbol -]; diff --git a/bench/benchmarks/layout.js b/bench/benchmarks/layout.js index 32554f9c3ee..debd61d8663 100644 --- a/bench/benchmarks/layout.js +++ b/bench/benchmarks/layout.js @@ -10,16 +10,12 @@ export default class Layout extends Benchmark { tiles: Array<{tileID: OverscaledTileID, buffer: ArrayBuffer}>; parser: TileParser; style: string | StyleSpecification; - locations: Array; + tileIDs: Array; - constructor(style: string | StyleSpecification, locations: ?Array) { + constructor(style: string | StyleSpecification, tileIDs: ?Array) { super(); this.style = style; - this.locations = locations || this.tileIDs(); - } - - tileIDs(): Array { - return [ + this.tileIDs = tileIDs || [ new OverscaledTileID(12, 0, 12, 655, 1583), new OverscaledTileID(8, 0, 8, 40, 98), new OverscaledTileID(4, 0, 4, 3, 6), @@ -34,7 +30,7 @@ export default class Layout extends Benchmark { return this.parser.setup(); }) .then(() => { - return Promise.all(this.locations.map(tileID => this.parser.fetchTile(tileID))); + return Promise.all(this.tileIDs.map(tileID => this.parser.fetchTile(tileID))); }) .then((tiles) => { this.tiles = tiles; diff --git a/bench/benchmarks/remove_paint_state.js b/bench/benchmarks/remove_paint_state.js index a67f9b32f6a..191bf243f6c 100644 --- a/bench/benchmarks/remove_paint_state.js +++ b/bench/benchmarks/remove_paint_state.js @@ -68,7 +68,7 @@ class RemovePaintState extends Benchmark { } } -class PropertyLevelRemove extends RemovePaintState { +export class PropertyLevelRemove extends RemovePaintState { bench() { for (let i = 0; i < this.numFeatures; i += 50) { @@ -82,7 +82,7 @@ class PropertyLevelRemove extends RemovePaintState { } } -class FeatureLevelRemove extends RemovePaintState { +export class FeatureLevelRemove extends RemovePaintState { bench() { for (let i = 0; i < this.numFeatures; i += 50) { @@ -96,7 +96,7 @@ class FeatureLevelRemove extends RemovePaintState { } } -class SourceLevelRemove extends RemovePaintState { +export class SourceLevelRemove extends RemovePaintState { bench() { for (let i = 0; i < this.numFeatures; i += 50) { @@ -109,9 +109,3 @@ class SourceLevelRemove extends RemovePaintState { } } - -export default [ - PropertyLevelRemove, - FeatureLevelRemove, - SourceLevelRemove -]; diff --git a/bench/benchmarks/worker_transfer.js b/bench/benchmarks/worker_transfer.js index 2feb7b9c2a8..e1245ca6808 100644 --- a/bench/benchmarks/worker_transfer.js +++ b/bench/benchmarks/worker_transfer.js @@ -84,5 +84,5 @@ export default class WorkerTransfer extends Benchmark { function barePayload(obj) { // strip all transferables from a worker payload, because we can't transfer them repeatedly in the bench: // as soon as it's transfered once, it's no longer available on the main thread - return JSON.parse(JSON.stringify(obj, (key, value) => ArrayBuffer.isView(value) ? {} : value)); + return JSON.parse(JSON.stringify(obj, (key, value) => ArrayBuffer.isView(value) ? {} : value) || '{}'); } diff --git a/bench/benchmarks_view.js b/bench/benchmarks_view.js index f3cc6cc62d6..b6ce6a080c8 100644 --- a/bench/benchmarks_view.js +++ b/bench/benchmarks_view.js @@ -1,12 +1,89 @@ import React from 'react'; import ReactDOM from 'react-dom'; import * as d3 from 'd3'; -import Axis from './lib/axis'; -import { kde, probabilitiesOfSuperiority } from './lib/statistics'; +import { kde, probabilitiesOfSuperiority, summaryStatistics, regression } from './lib/statistics'; const versionColor = d3.scaleOrdinal(['#1b9e77', '#7570b3', '#d95f02']); const formatSample = d3.format(".3r"); +function identity(x) { + return x; +} +function translateX(x) { + return `translate(${x + 0.5},0)`; +} +function translateY(y) { + return `translate(0,${y + 0.5})`; +} +function number(scale) { + return function(d) { + return +scale(d); + }; +} +function center(scale) { + let offset = Math.max(0, scale.bandwidth() - 1) / 2; // Adjust for 0.5px offset. + if (scale.round()) offset = Math.round(offset); + return function(d) { + return +scale(d) + offset; + }; +} + +class Axis extends React.Component { + render() { + const scale = this.props.scale; + const orient = this.props.orientation || 'left'; + const tickArguments = this.props.ticks ? [].concat(this.props.ticks) : []; + const tickValues = this.props.tickValues || null; + const tickFormat = this.props.tickFormat || null; + const tickSizeInner = this.props.tickSize || this.props.tickSizeInner || 6; + const tickSizeOuter = this.props.tickSize || this.props.tickSizeOuter || 6; + const tickPadding = this.props.tickPadding || 3; + + const k = orient === 'top' || orient === 'left' ? -1 : 1; + const x = orient === 'left' || orient === 'right' ? 'x' : 'y'; + const transform = orient === 'top' || orient === 'bottom' ? translateX : translateY; + + const values = tickValues == null ? (scale.ticks ? scale.ticks(...tickArguments) : scale.domain()) : tickValues; + const format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat(...tickArguments) : identity) : tickFormat; + const spacing = Math.max(tickSizeInner, 0) + tickPadding; + const range = scale.range(); + const range0 = +range[0] + 0.5; + const range1 = +range[range.length - 1] + 0.5; + const position = (scale.bandwidth ? center : number)(scale.copy()); + + return ( + + + {values.map((d, i) => + + + {format(d)} + + )} + {this.props.children} + + ); + } +} + class StatisticsPlot extends React.Component { constructor(props) { super(props); @@ -377,19 +454,12 @@ class BenchmarkRow extends React.Component { } class BenchmarksTable extends React.Component { - constructor(props) { - super(props); - this.state = {sharing: false}; - this.share = this.share.bind(this); - } - render() { return (
- {this.state.sharing && }

Mapbox GL JS Benchmarks – { this.props.finished ? - Finished : + Finished : Running}

{this.props.benchmarks.map((benchmark, i) => { return ; @@ -397,29 +467,9 @@ class BenchmarksTable extends React.Component {
); } - - share() { - document.querySelectorAll('script').forEach(e => e.remove()); - const share = document.querySelector('.share'); - share.style.display = 'none'; - - const body = JSON.stringify({ - "public": true, - "files": { - "index.html": { - "content": document.body.parentElement.outerHTML - } - } - }); - this.setState({sharing: true}); - - fetch('https://api.github.com/gists', { method: 'POST', body }) - .then(response => response.json()) - .then(json => { window.location = `https://bl.ocks.org/anonymous/raw/${json.id}/`; }); - } } -export default function updateUI(benchmarks, finished) { +function updateUI(benchmarks, finished) { finished = !!finished; ReactDOM.render( @@ -427,3 +477,51 @@ export default function updateUI(benchmarks, finished) { document.getElementById('benchmarks') ); } + +export function run(benchmarks) { + const filter = window.location.hash.substr(1); + if (filter) benchmarks = benchmarks.filter(({name}) => name === filter); + + for (const benchmark of benchmarks) { + for (const version of benchmark.versions) { + version.status = 'waiting'; + version.logs = []; + version.samples = []; + version.summary = {}; + } + } + + updateUI(benchmarks); + + let promise = Promise.resolve(); + + benchmarks.forEach(bench => { + bench.versions.forEach(version => { + promise = promise.then(() => { + version.status = 'running'; + updateUI(benchmarks); + + return version.bench.run() + .then(measurements => { + // scale measurements down by iteration count, so that + // they represent (average) time for a single iteration + const samples = measurements.map(({time, iterations}) => time / iterations); + version.status = 'ended'; + version.samples = samples; + version.summary = summaryStatistics(samples); + version.regression = regression(measurements); + updateUI(benchmarks); + }) + .catch(error => { + version.status = 'errored'; + version.error = error; + updateUI(benchmarks); + }); + }); + }); + }); + + promise = promise.then(() => { + updateUI(benchmarks, true); + }); +} diff --git a/bench/lib/axis.js b/bench/lib/axis.js deleted file mode 100644 index a1872a5bac1..00000000000 --- a/bench/lib/axis.js +++ /dev/null @@ -1,85 +0,0 @@ -import React from 'react'; - -function identity(x) { - return x; -} - -function translateX(x) { - return `translate(${x + 0.5},0)`; -} - -function translateY(y) { - return `translate(0,${y + 0.5})`; -} - -function number(scale) { - return function(d) { - return +scale(d); - }; -} - -function center(scale) { - let offset = Math.max(0, scale.bandwidth() - 1) / 2; // Adjust for 0.5px offset. - if (scale.round()) offset = Math.round(offset); - return function(d) { - return +scale(d) + offset; - }; -} - -class Axis extends React.Component { - render() { - const scale = this.props.scale; - const orient = this.props.orientation || 'left'; - const tickArguments = this.props.ticks ? [].concat(this.props.ticks) : []; - const tickValues = this.props.tickValues || null; - const tickFormat = this.props.tickFormat || null; - const tickSizeInner = this.props.tickSize || this.props.tickSizeInner || 6; - const tickSizeOuter = this.props.tickSize || this.props.tickSizeOuter || 6; - const tickPadding = this.props.tickPadding || 3; - - const k = orient === 'top' || orient === 'left' ? -1 : 1; - const x = orient === 'left' || orient === 'right' ? 'x' : 'y'; - const transform = orient === 'top' || orient === 'bottom' ? translateX : translateY; - - const values = tickValues == null ? (scale.ticks ? scale.ticks(...tickArguments) : scale.domain()) : tickValues; - const format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat(...tickArguments) : identity) : tickFormat; - const spacing = Math.max(tickSizeInner, 0) + tickPadding; - const range = scale.range(); - const range0 = +range[0] + 0.5; - const range1 = +range[range.length - 1] + 0.5; - const position = (scale.bandwidth ? center : number)(scale.copy()); - - return ( - - - {values.map((d, i) => - - - {format(d)} - - )} - {this.props.children} - - ); - } -} - -export default Axis; diff --git a/bench/lib/style_locations.js b/bench/lib/style_locations.js index 2366bc565ce..77b2515314e 100644 --- a/bench/lib/style_locations.js +++ b/bench/lib/style_locations.js @@ -1,94 +1,23 @@ +import styleBenchmarkLocations from '@mapbox/gazetteer/mapbox-streets/style-benchmark-locations.json'; +import MercatorCoordinate from '../../src/geo/mercator_coordinate'; import { OverscaledTileID } from '../../src/source/tile_id'; -export default [ - { - "description": "Road labels – Houston, z12", - "tileID": [new OverscaledTileID(12, 0, 12, 962, 1692)], - "zoom": 12, - "center": [-95.392263, 29.799396] - }, - { - "description": "Road labels – Houston, z13", - "tileID": [new OverscaledTileID(13, 0, 13, 1925, 3386)], - "zoom": 13, - "center": [-95.38116, 29.74916] - }, - { - "description": "High zoom labels (also: buildings, roads) – New York City, z16", - "tileID": [new OverscaledTileID(16, 0, 16, 19299, 24629)], - "zoom": 16, - "center": [-73.984682, 40.757660] - }, - { - "description": "High zoom labels (also: buildings, roads) – New York City, z17", - "tileID": [new OverscaledTileID(17, 0, 17, 19299, 24629)], - "zoom": 17, - "center": [-73.984682, 40.757660] - }, - { - "description": "High zoom cjk labels, when using local lang (also: buildings, roads) – Tokyo, z16", - "tileID": [new OverscaledTileID(16, 0, 16, 58210, 25803)], - "zoom": 16, - "center": [139.759860, 35.69522] - }, - { - "description": "High zoom cjk labels, when using local lang (also: buildings, roads) – Tokyo, z17", - "tileID": [new OverscaledTileID(17, 0, 17, 58210, 25803)], - "zoom": 17, - "center": [139.759860, 35.69522] - }, - { - "description": "Water – Finland, z10", - "tileID": [new OverscaledTileID(10, 0, 10, 590, 288)], - "zoom": 10, - "center": [27.602348, 61.520945] - }, - { - "description": "Landuse – Paris, z11", - "tileID": [new OverscaledTileID(11, 0, 11, 1036, 705)], - "zoom": 11, - "center": [2.209530, 48.745030] - }, - { - "description": "Buildings – LA, z16", - "tileID": [new OverscaledTileID(16, 0, 16, 11229, 26180)], - "zoom": 6, - "center": [-118.314417, 33.995654] - }, - { - "description": "High zoom (roads, paths, landuse, labels) – Paris, 15", - "tileID": [new OverscaledTileID(15, 0, 15, 16594, 11271)], - "zoom": 15, - "center": [2.315725, 48.866517] - }, - { - "description": "High zoom (pedestrian polygon fills, roads, paths, landuse, labels) – Paris, z16.25", - "tileID": [new OverscaledTileID(17, 0, 17, 33189, 22543)], - "zoom": 16.25, - "center": [2.315725, 48.866517] - }, - { - "description": "Hillshading – Switzerland, z9", - "tileID": [new OverscaledTileID(9, 0, 9, 268, 181)], - "zoom": 9, - "center": [8.835221, 46.317157] - }, - { - "description": "Hillshading and contours – Switzerland, z12", - "tileID": [new OverscaledTileID(12, 0, 12, 2148, 1452)], - "zoom": 12, - "center": [8.835221, 46.317157] - }, - { - "description": "Landcover – Germany z6", - "tileID": [new OverscaledTileID(6, 0, 6, 33, 21)], - "zoom": 6, - "center": [8.429493, 51.056406] - }, - { - "description": "Landcover – Germany z8", - "tileID": [new OverscaledTileID(8, 0, 8, 133, 86)], - "zoom": 8, - "center": [7.762074, 50.322133] - } -]; +export default styleBenchmarkLocations.features.map(feature => { + const { coordinates } = feature.geometry; + const { zoom } = feature.properties; + const { x, y } = MercatorCoordinate.fromLngLat({ + lng: coordinates[0], + lat: coordinates[1] + }); + + const scale = Math.pow(2, zoom); + const tileX = Math.floor(x * scale); + const tileY = Math.floor(y * scale); + + return { + description: feature.properties['place_name'], + tileID: [new OverscaledTileID(zoom, 0, zoom, tileX, tileY)], + zoom, + center: coordinates + }; +}); diff --git a/bench/rollup_config_benchmarks.js b/bench/rollup_config_benchmarks.js new file mode 100644 index 00000000000..fd690cd11e2 --- /dev/null +++ b/bench/rollup_config_benchmarks.js @@ -0,0 +1,60 @@ +import fs from 'fs'; +import sourcemaps from 'rollup-plugin-sourcemaps'; +import replace from 'rollup-plugin-replace'; +import {plugins} from '../build/rollup_plugins'; + +let styles = ['mapbox://styles/mapbox/streets-v10']; + +if (process.env.MAPBOX_STYLES) { + styles = process.env.MAPBOX_STYLES + .split(',') + .map(style => style.match(/\.json$/) ? require(style) : style); +} + +const replaceConfig = { + 'process.env.BENCHMARK_VERSION': JSON.stringify(process.env.BENCHMARK_VERSION), + 'process.env.MAPBOX_ACCESS_TOKEN': JSON.stringify(process.env.MAPBOX_ACCESS_TOKEN), + 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken), + 'process.env.MAPBOX_STYLES': JSON.stringify(styles), + 'process.env.NODE_ENV': JSON.stringify('production') +}; + +const allPlugins = plugins(true, true).concat(replace(replaceConfig)); +const intro = fs.readFileSync('rollup/bundle_prelude.js', 'utf8'); + +const splitConfig = (name) => [{ + input: [`bench/${name}/benchmarks.js`, 'src/source/worker.js'], + output: { + dir: `rollup/build/benchmarks/${name}`, + format: 'amd', + indent: false, + sourcemap: 'inline', + chunkFileNames: 'shared.js' + }, + plugins: allPlugins +}, { + input: `rollup/benchmarks_${name}.js`, + output: { + file: `bench/${name}/benchmarks_generated.js`, + format: 'umd', + indent: false, + sourcemap: true, + intro + }, + treeshake: false, + plugins: [sourcemaps()], +}]; + +const viewConfig = { + input: 'bench/benchmarks_view.js', + output: { + name: 'Benchmarks', + file: 'bench/benchmarks_view_generated.js', + format: 'umd', + indent: false, + sourcemap: true + }, + plugins: allPlugins +}; + +export default splitConfig('versions').concat(splitConfig('styles')).concat(viewConfig); diff --git a/bench/styles/benchmarks.js b/bench/styles/benchmarks.js index e0ccdac9ea2..05f3905cba7 100644 --- a/bench/styles/benchmarks.js +++ b/bench/styles/benchmarks.js @@ -1,40 +1,6 @@ import mapboxgl from '../../src'; import accessToken from '../lib/access_token'; import locations from '../lib/style_locations'; -import { summaryStatistics, regression } from '../lib/statistics'; -import updateUI from '../benchmarks_view'; - -mapboxgl.accessToken = accessToken; - -const benchmarks = []; -const filter = window.location.hash.substr(1); - -function register(Benchmark, locations, options) { - const name = Benchmark.name; - - if (filter && name !== filter) - return; - - const benchmark = { - name: Benchmark.name, - versions: [] - }; - - if (options) Object.assign(benchmark, options); - - process.env.MAPBOX_STYLES.forEach(style => { - const { name } = style; - benchmark.versions.push({ - name: name ? name : style.replace('mapbox://styles/', ''), - bench: new Benchmark(style, locations), - status: 'waiting', - logs: [], - samples: [], - summary: {} - }); - }); - benchmarks.push(benchmark); -} import StyleLayerCreate from '../benchmarks/style_layer_create'; import Validate from '../benchmarks/style_validate'; @@ -43,52 +9,37 @@ import Paint from '../benchmarks/paint'; import QueryPoint from '../benchmarks/query_point'; import QueryBox from '../benchmarks/query_box'; -register(StyleLayerCreate); -register(Validate); -locations.forEach(location => register(Layout, location.tileID, {location})); -locations.forEach(location => register(Paint, [location], {location})); -register(QueryPoint, locations); -register(QueryBox, locations); - import getWorkerPool from '../../src/util/global_worker_pool'; -let promise = Promise.resolve(); +mapboxgl.accessToken = accessToken; + +const benchmarks = window.benchmarks = []; + +function register(name, Benchmark, locations, location) { + const versions = []; + + for (const style of process.env.MAPBOX_STYLES) { + versions.push({ + name: style.name || style.replace('mapbox://styles/', ''), + bench: new Benchmark(style, locations) + }); + } + benchmarks.push({name, versions, location}); +} -promise = promise.then(() => { +register('StyleLayerCreate', StyleLayerCreate); +register('Validate', Validate); +locations.forEach(location => register('Layout', Layout, location.tileID, location)); +locations.forEach(location => register('Paint', Paint, [location], location)); +register('QueryPoint', QueryPoint, locations); +register('QueryBox', QueryBox, locations); + +Promise.resolve().then(() => { // Ensure the global worker pool is never drained. Browsers have resource limits // on the max number of workers that can be created per page. // We do this async to avoid creating workers before the worker bundle blob // URL has been set up, which happens after this module is executed. getWorkerPool().acquire(-1); }); -benchmarks.forEach(bench => { - bench.versions.forEach(version => { - promise = promise.then(() => { - version.status = 'running'; - updateUI(benchmarks); - - return version.bench.run() - .then(measurements => { - // scale measurements down by iteration count, so that - // they represent (average) time for a single iteration - const samples = measurements.map(({time, iterations}) => time / iterations); - version.status = 'ended'; - version.samples = samples; - version.summary = summaryStatistics(samples); - version.regression = regression(measurements); - updateUI(benchmarks); - }) - .catch(error => { - version.status = 'errored'; - version.error = error; - updateUI(benchmarks); - }); - }); - }); - - promise = promise.then(() => { - updateUI(benchmarks, true); - }); -}); export default mapboxgl; diff --git a/bench/styles/index.html b/bench/styles/index.html index cb828dde442..4344efa5444 100644 --- a/bench/styles/index.html +++ b/bench/styles/index.html @@ -8,12 +8,15 @@ -
+ + diff --git a/bench/styles/rollup_config_benchmarks.js b/bench/styles/rollup_config_benchmarks.js deleted file mode 100644 index 93dbd8f2b04..00000000000 --- a/bench/styles/rollup_config_benchmarks.js +++ /dev/null @@ -1,47 +0,0 @@ -import fs from 'fs'; -import sourcemaps from 'rollup-plugin-sourcemaps'; -import replace from 'rollup-plugin-replace'; -import {plugins as basePlugins} from '../../build/rollup_plugins'; - -let styles = ['mapbox://styles/mapbox/streets-v10']; - -if (process.env.MAPBOX_STYLES) { - styles = process.env.MAPBOX_STYLES - .split(',') - .map(style => style.match(/\.json$/) ? require(style) : style); -} - -const plugins = () => basePlugins().concat( - replace({ - 'process.env.BENCHMARK_VERSION': JSON.stringify(process.env.BENCHMARK_VERSION), - 'process.env.MAPBOX_ACCESS_TOKEN': JSON.stringify(process.env.MAPBOX_ACCESS_TOKEN), - 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken), - 'process.env.MAPBOX_STYLES': JSON.stringify(styles), - 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) - }) -); - -const config = [{ - input: [`bench/styles/benchmarks.js`, 'src/source/worker.js'], - output: { - dir: 'rollup/build/benchmarks/styles', - format: 'amd', - sourcemap: 'inline', - chunkFileNames: 'chunk1.js' - }, - experimentalCodeSplitting: true, - plugins: plugins() -}, { - input: 'rollup/style_benchmarks.js', - output: { - file: 'bench/styles/benchmarks_generated.js', - format: 'umd', - sourcemap: 'inline', - intro: fs.readFileSync(require.resolve('../../rollup/bundle_prelude.js'), 'utf8') - }, - treeshake: false, - indent: false, - plugins: [sourcemaps()], -}]; - -export default config; diff --git a/bench/versions/benchmarks.js b/bench/versions/benchmarks.js index f431bafd0ba..059d6591b38 100644 --- a/bench/versions/benchmarks.js +++ b/bench/versions/benchmarks.js @@ -1,68 +1,74 @@ import mapboxgl from '../../src'; import accessToken from '../lib/access_token'; -import { summaryStatistics, regression } from '../lib/statistics'; -import updateUI from '../benchmarks_view'; import styleLocations from '../lib/style_locations'; -mapboxgl.accessToken = accessToken; - -window.mapboxglBenchmarks = window.mapboxglBenchmarks || {}; - -const version = process.env.BENCHMARK_VERSION; - -function register(benchmark) { - const name = benchmark.constructor.name; - window.mapboxglBenchmarks[name] = window.mapboxglBenchmarks[name] || {}; - window.mapboxglBenchmarks[name][version] = benchmark; -} - import Layout from '../benchmarks/layout'; import LayoutDDS from '../benchmarks/layout_dds'; import SymbolLayout from '../benchmarks/symbol_layout'; import WorkerTransfer from '../benchmarks/worker_transfer'; import Paint from '../benchmarks/paint'; import PaintStates from '../benchmarks/paint_states'; -import RemovePaintStateBenchmarks from '../benchmarks/remove_paint_state'; -import LayerBenchmarks from '../benchmarks/layers'; +import {PropertyLevelRemove, FeatureLevelRemove, SourceLevelRemove} from '../benchmarks/remove_paint_state'; +import {LayerBackground, LayerCircle, LayerFill, LayerFillExtrusion, LayerHeatmap, LayerHillshade, LayerLine, LayerRaster, LayerSymbol} from '../benchmarks/layers'; import Load from '../benchmarks/map_load'; import Validate from '../benchmarks/style_validate'; import StyleLayerCreate from '../benchmarks/style_layer_create'; import QueryPoint from '../benchmarks/query_point'; import QueryBox from '../benchmarks/query_box'; -import ExpressionBenchmarks from '../benchmarks/expressions'; +import {FunctionCreate, FunctionEvaluate, FunctionConvert, ExpressionCreate, ExpressionEvaluate} from '../benchmarks/expressions'; import FilterCreate from '../benchmarks/filter_create'; import FilterEvaluate from '../benchmarks/filter_evaluate'; -const style = 'mapbox://styles/mapbox/streets-v10'; -const center = [-77.032194, 38.912753]; -const zooms = [4, 8, 11, 13, 15, 17]; -const locations = zooms.map(zoom => ({center, zoom})); +import getWorkerPool from '../../src/util/global_worker_pool'; -register(new Paint(style, locations)); -register(new QueryPoint(style, locations)); -register(new QueryBox(style, locations)); -register(new Layout(style)); -register(new Validate(style)); -register(new StyleLayerCreate(style)); -ExpressionBenchmarks.forEach((Bench) => register(new Bench(style))); -register(new WorkerTransfer(style)); -register(new PaintStates(center)); -RemovePaintStateBenchmarks.forEach((Bench) => register(new Bench(center))); -LayerBenchmarks.forEach((Bench) => register(new Bench())); -register(new Load()); -register(new LayoutDDS()); -register(new SymbolLayout(style, styleLocations.map(location => location.tileID[0]))); -register(new FilterCreate()); -register(new FilterEvaluate()); +mapboxgl.accessToken = accessToken; -import getWorkerPool from '../../src/util/global_worker_pool'; +window.mapboxglBenchmarks = window.mapboxglBenchmarks || {}; -const benchmarks = []; -const filter = window.location.hash.substr(1); +const version = process.env.BENCHMARK_VERSION; -let promise = Promise.resolve(); +function register(name, benchmark) { + window.mapboxglBenchmarks[name] = window.mapboxglBenchmarks[name] || {}; + window.mapboxglBenchmarks[name][version] = benchmark; +} -promise = promise.then(() => { +const style = 'mapbox://styles/mapbox/streets-v10'; +const center = [-77.032194, 38.912753]; +const zooms = [4, 8, 11, 13, 15, 17]; +const locations = zooms.map(zoom => ({center, zoom})); + +register('Paint', new Paint(style, locations)); +register('QueryPoint', new QueryPoint(style, locations)); +register('QueryBox', new QueryBox(style, locations)); +register('Layout', new Layout(style)); +register('Validate', new Validate(style)); +register('StyleLayerCreate', new StyleLayerCreate(style)); +register('FunctionCreate', new FunctionCreate(style)); +register('FunctionEvaluate', new FunctionEvaluate(style)); +register('FunctionConvert', new FunctionConvert(style)); +register('ExpressionCreate', new ExpressionCreate(style)); +register('ExpressionEvaluate', new ExpressionEvaluate(style)); +register('WorkerTransfer', new WorkerTransfer(style)); +register('PaintStates', new PaintStates(center)); +register('PropertyLevelRemove', new PropertyLevelRemove(center)); +register('FeatureLevelRemove', new FeatureLevelRemove(center)); +register('SourceLevelRemove', new SourceLevelRemove(center)); +register('LayerBackground', new LayerBackground()); +register('LayerCircle', new LayerCircle()); +register('LayerFill', new LayerFill()); +register('LayerFillExtrusion', new LayerFillExtrusion()); +register('LayerHeatmap', new LayerHeatmap()); +register('LayerHillshade', new LayerHillshade()); +register('LayerLine', new LayerLine()); +register('LayerRaster', new LayerRaster()); +register('LayerSymbol', new LayerSymbol()); +register('Load', new Load()); +register('LayoutDDS', new LayoutDDS()); +register('SymbolLayout', new SymbolLayout(style, styleLocations.map(location => location.tileID[0]))); +register('FilterCreate', new FilterCreate()); +register('FilterEvaluate', new FilterEvaluate()); + +Promise.resolve().then(() => { // Ensure the global worker pool is never drained. Browsers have resource limits // on the max number of workers that can be created per page. // We do this async to avoid creating workers before the worker bundle blob @@ -70,52 +76,4 @@ promise = promise.then(() => { getWorkerPool().acquire(-1); }); - -window.runBenchmarks = () => { - for (const name in window.mapboxglBenchmarks) { - if (filter && name !== filter) - continue; - - const benchmark = { name, versions: [] }; - benchmarks.push(benchmark); - - for (const test in window.mapboxglBenchmarks[name]) { - const version = { - name: test, - status: 'waiting', - logs: [], - samples: [], - summary: {} - }; - benchmark.versions.push(version); - - promise = promise.then(() => { - version.status = 'running'; - updateUI(benchmarks); - - return window.mapboxglBenchmarks[name][test].run() - .then(measurements => { - // scale measurements down by iteration count, so that - // they represent (average) time for a single iteration - const samples = measurements.map(({time, iterations}) => time / iterations); - version.status = 'ended'; - version.samples = samples; - version.summary = summaryStatistics(samples); - version.regression = regression(measurements); - updateUI(benchmarks); - }) - .catch(error => { - version.status = 'errored'; - version.error = error; - updateUI(benchmarks); - }); - }); - } - - promise = promise.then(() => { - updateUI(benchmarks, true); - }); - } -}; - export default mapboxgl; diff --git a/bench/versions/index.html b/bench/versions/index.html index cb338dd7103..2cfe9811552 100644 --- a/bench/versions/index.html +++ b/bench/versions/index.html @@ -8,11 +8,12 @@ - +
+ + + + + diff --git a/debug/threejs.html b/debug/threejs.html index cca332b4f4a..2587ec0348e 100644 --- a/debug/threejs.html +++ b/debug/threejs.html @@ -22,6 +22,7 @@ var map = window.map = new mapboxgl.Map({ container: 'map', + antialias: true, zoom: 16.5, center: [-79.390307, 43.658956], bearing: 20, diff --git a/debug/tinysdf.html b/debug/tinysdf.html index 5faa2b6d019..e4b7ad92658 100644 --- a/debug/tinysdf.html +++ b/debug/tinysdf.html @@ -60,7 +60,7 @@ layer.layout['text-field'] = "{name}"; } } - map.setStyle(style, map.style.glyphSource.localIdeographFontFamily); + map.setStyle(style); }); } @@ -69,7 +69,8 @@ zoom: 8.8, center: [121.574, 31.1489], style: 'mapbox://styles/mapbox/streets-v10', - hash: true + hash: true, + localIdeographFontFamily: false }); localizeLayers(originalMap); @@ -79,7 +80,7 @@ zoom: 8.8, center: [121.574, 31.1489], style: 'mapbox://styles/mapbox/streets-v10', - localIdeographFontFamily: '"Noto Sans", "Noto Sans CJK SC", sans-serif', + //Uses default localIdeographFontFamily 'sans-serif' hash: true }); diff --git a/docs/documentation.yml b/docs/documentation.yml index 04ea557cf56..968ab6085e0 100644 --- a/docs/documentation.yml +++ b/docs/documentation.yml @@ -11,6 +11,7 @@ toc: - CameraOptions - PaddingOptions - RequestParameters + - StyleImageInterface - CustomLayerInterface - name: Geography & Geometry description: | diff --git a/docs/img/src/add-image-animated.png b/docs/img/src/add-image-animated.png new file mode 100644 index 00000000000..6ef1d97aa7e Binary files /dev/null and b/docs/img/src/add-image-animated.png differ diff --git a/docs/img/src/add-image-missing-generated.png b/docs/img/src/add-image-missing-generated.png new file mode 100644 index 00000000000..918c105e12c Binary files /dev/null and b/docs/img/src/add-image-missing-generated.png differ diff --git a/docs/img/src/variable-label-placement.png b/docs/img/src/variable-label-placement.png new file mode 100644 index 00000000000..2f231e5cae8 Binary files /dev/null and b/docs/img/src/variable-label-placement.png differ diff --git a/docs/pages/example/add-image-animated.html b/docs/pages/example/add-image-animated.html new file mode 100644 index 00000000000..387cfbbf742 --- /dev/null +++ b/docs/pages/example/add-image-animated.html @@ -0,0 +1,85 @@ +
+ + diff --git a/docs/pages/example/add-image-animated.js b/docs/pages/example/add-image-animated.js new file mode 100644 index 00000000000..097a92010e2 --- /dev/null +++ b/docs/pages/example/add-image-animated.js @@ -0,0 +1,11 @@ +/*--- +title: Add an animated icon to the map +description: Add an animated icon to the map that was generated at runtime with a Canvas. +tags: + - styles + - layers +pathname: /mapbox-gl-js/example/add-image-animated/ +---*/ +import Example from '../../components/example'; +import html from './add-image-animated.html'; +export default Example(html); diff --git a/docs/pages/example/add-image-missing-generated.html b/docs/pages/example/add-image-missing-generated.html new file mode 100644 index 00000000000..f0247cb122f --- /dev/null +++ b/docs/pages/example/add-image-missing-generated.html @@ -0,0 +1,81 @@ +
+ + diff --git a/docs/pages/example/add-image-missing-generated.js b/docs/pages/example/add-image-missing-generated.js new file mode 100644 index 00000000000..19ad5b57baf --- /dev/null +++ b/docs/pages/example/add-image-missing-generated.js @@ -0,0 +1,11 @@ +/*--- +title: Generate and add a missing icon to the map +description: Dynamically generate a missing icon at runtime and add it to the map. +tags: + - styles + - layers +pathname: /mapbox-gl-js/example/add-image-missing-generated/ +---*/ +import Example from '../../components/example'; +import html from './add-image-missing-generated.html'; +export default Example(html); diff --git a/docs/pages/example/local-ideographs.js b/docs/pages/example/local-ideographs.js index 0357d6c6574..1763d2c44ce 100644 --- a/docs/pages/example/local-ideographs.js +++ b/docs/pages/example/local-ideographs.js @@ -10,10 +10,12 @@ description: >- 'Hangul Syllables' Unicode ranges. In these ranges, font settings from the map's style will be ignored in favor of the locally available font. Keywords in the fontstack defined in the map's style (light/regular/medium/bold) will - be translated into a CSS 'font-weight'. When using this setting, keep in mind - that the fonts you select may not be available on all users' devices. It is - best to specify at least one broadly available fallback font class such as - 'sans-serif'. + be translated into a CSS 'font-weight'. + + This setting is enabled by default to use the system 'sans-serif' font. When + overriding this setting, keep in mind that the fonts you select may not be available + on all users' devices. It is best to specify at least one broadly available + fallback font class such as 'sans-serif'. tags: - internationalization pathname: /mapbox-gl-js/example/local-ideographs/ diff --git a/docs/pages/example/variable-label-placement.html b/docs/pages/example/variable-label-placement.html new file mode 100644 index 00000000000..ee09db5bbc3 --- /dev/null +++ b/docs/pages/example/variable-label-placement.html @@ -0,0 +1,108 @@ +
+ + diff --git a/docs/pages/example/variable-label-placement.js b/docs/pages/example/variable-label-placement.js new file mode 100644 index 00000000000..798217e1c52 --- /dev/null +++ b/docs/pages/example/variable-label-placement.js @@ -0,0 +1,10 @@ +/*--- +title: Variable label placement +description: Use `text-variable-anchor` to allow high priority labels to shift position to stay on the map. +tags: + - layers +pathname: /mapbox-gl-js/example/variable-label-placement/ +---*/ +import Example from '../../components/example'; +import html from './variable-label-placement.html'; +export default Example(html); diff --git a/docs/pages/overview/index.md b/docs/pages/overview/index.md index 6cc105b1836..24c334bb9cd 100644 --- a/docs/pages/overview/index.md +++ b/docs/pages/overview/index.md @@ -4,6 +4,8 @@ description: Introduction to Mapbox GL JS, a JavaScript library that uses WebGL prependJs: - "import OverviewHeader from '@mapbox/dr-ui/overview-header';" - "import Quickstart from '../../components/quickstart';" + - "import Copyable from '../../components/copyable';" + - "import urls from '../../components/urls';" - "import {version} from '../../../package.json';" pathname: /mapbox-gl-js/overview/ contentType: API @@ -52,6 +54,16 @@ Requesting styles from Mapbox or other services will require additional directiv connect-src https://*.tiles.mapbox.com https://api.mapbox.com https://events.mapbox.com ``` +For strict CSP environments without worker-src blob: ; child-src blob: enabled, there's a separate Mapbox GL JS bundle (`mapbox-gl-csp.js` and `mapbox-gl-csp-worker.js`) which requires setting the path to the worker manually: + +{{ +{` +`} +}} + ## Mapbox CSS The CSS referenced in the Quickstart is used to style DOM elements created by Mapbox code. Without the CSS, elements like Popups and Markers won't work. diff --git a/package.json b/package.json index 34b4a58593b..9cf10122813 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mapbox-gl", "description": "A WebGL interactive maps library", - "version": "0.53.1", + "version": "0.54.0", "main": "dist/mapbox-gl.js", "style": "dist/mapbox-gl.css", "license": "SEE LICENSE IN LICENSE.txt", @@ -13,14 +13,10 @@ "node": ">=6.4.0" }, "dependencies": { - "@mapbox/appropriate-images-react": "^1.0.0", - "@mapbox/dr-ui": "0.6.0", "@mapbox/geojson-rewind": "^0.4.0", "@mapbox/geojson-types": "^1.0.2", "@mapbox/jsonlint-lines-primitives": "^2.0.2", "@mapbox/mapbox-gl-supported": "^1.4.0", - "@mapbox/mbx-assembly": "^0.28.2", - "@mapbox/mr-ui": "0.5.0", "@mapbox/point-geometry": "^0.1.0", "@mapbox/tiny-sdf": "^1.1.0", "@mapbox/unitbezier": "^0.0.0", @@ -28,7 +24,7 @@ "@mapbox/whoots-js": "^3.1.0", "csscolorparser": "~1.0.2", "earcut": "^2.1.5", - "esm": "^3.0.84", + "esm": "~3.0.84", "geojson-vt": "^3.2.1", "gl-matrix": "^3.0.0", "grid-index": "^1.1.0", @@ -44,38 +40,43 @@ }, "devDependencies": { "@mapbox/appropriate-images": "^2.0.0", + "@mapbox/appropriate-images-react": "^1.0.0", "@mapbox/batfish": "1.9.8", + "@mapbox/dr-ui": "0.6.0", "@mapbox/flow-remove-types": "^1.3.0-await.upstream.2", - "@mapbox/mapbox-gl-rtl-text": "^0.2.0", + "@mapbox/gazetteer": "^3.1.2", + "@mapbox/mapbox-gl-rtl-text": "^0.2.1", "@mapbox/mapbox-gl-test-suite": "file:test/integration", + "@mapbox/mbx-assembly": "^0.28.2", + "@mapbox/mr-ui": "0.5.0", "@octokit/rest": "^15.15.1", "babel-eslint": "^10.0.1", - "benchmark": "~2.1.0", - "browserify": "^16.1.0", + "benchmark": "^2.1.4", + "browserify": "^16.2.3", "d3": "^4.12.0", "documentation": "~9.1.1", "ejs": "^2.5.7", - "eslint": "^5.8.0", + "eslint": "^5.15.3", "eslint-config-mourner": "^3.0.0", - "eslint-plugin-flowtype": "^3.2.1", - "eslint-plugin-html": "^4.0.6", - "eslint-plugin-import": "^2.14.0", - "eslint-plugin-react": "^7.11.1", - "flow-bin": "^0.91.0", + "eslint-plugin-flowtype": "^3.4.2", + "eslint-plugin-html": "^5.0.3", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-react": "^7.12.4", + "flow-bin": "^0.95.1", "github-slugger": "1.2.1", - "gl": "^4.1.1", + "gl": "~4.1.1", "glob": "^7.0.3", "is-builtin-module": "^3.0.0", "jsdom": "^13.0.0", - "json-stringify-pretty-compact": "^1.0.4", + "json-stringify-pretty-compact": "^2.0.0", "jsonwebtoken": "^8.3.0", "mock-geolocation": "^1.0.11", - "npm-run-all": "^4.0.1", - "nyc": "^13.1.0", + "npm-run-all": "^4.1.5", + "nyc": "^13.3.0", "object.entries": "^1.1.0", - "pirates": "^3.0.2", - "pngjs": "^3.3.3", - "postcss-cli": "^5.0.0", + "pirates": "^4.0.1", + "pngjs": "^3.4.0", + "postcss-cli": "^6.1.2", "postcss-inline-svg": "^3.1.1", "pretty-bytes": "^5.1.0", "prismjs": "^1.15.0", @@ -83,27 +84,27 @@ "puppeteer": "^1.13.0", "raw-loader": "^1.0.0", "react": "^16.7.0", - "react-dom": "^16.7.0", + "react-dom": "16.3.3", "react-helmet": "^5.2.0", "remark": "^10.0.1", "remark-html": "^9.0.0", "remark-react": "^5.0.1", - "request": "^2.79.0", - "rollup": "^1.1.2", + "request": "^2.88.0", + "rollup": "^1.7.3", "rollup-plugin-buble": "^0.19.6", - "rollup-plugin-commonjs": "^9.2.0", - "rollup-plugin-json": "^3.1.0", - "rollup-plugin-node-resolve": "4.0.0", - "rollup-plugin-replace": "^2.1.0", + "rollup-plugin-commonjs": "^9.2.2", + "rollup-plugin-json": "^4.0.0", + "rollup-plugin-node-resolve": "^4.0.1", + "rollup-plugin-replace": "^2.1.1", "rollup-plugin-sourcemaps": "^0.4.2", - "rollup-plugin-terser": "^4.0.2", + "rollup-plugin-terser": "^4.0.4", "rollup-plugin-unassert": "^0.2.0", - "sinon": "^7.1.1", + "sinon": "^7.3.0", "slugg": "^1.2.1", - "st": "^1.2.0", - "stylelint": "^9.7.1", + "st": "^1.2.2", + "stylelint": "^9.10.1", "stylelint-config-standard": "^18.2.0", - "tap": "^12.0.1" + "tap": "~12.4.1" }, "browser": { "./src/shaders/index.js": "./src/shaders/shaders.js", @@ -116,18 +117,18 @@ "watch-dev": "rollup -c --environment BUILD:dev --watch", "build-prod": "rollup -c --environment BUILD:production", "build-prod-min": "rollup -c --environment BUILD:production,MINIFY:true", + "build-csp": "rollup -c rollup.config.csp.js", "build-flow-types": "cp build/mapbox-gl.js.flow dist/mapbox-gl.js.flow && cp build/mapbox-gl.js.flow dist/mapbox-gl-dev.js.flow", "build-css": "postcss -o dist/mapbox-gl.css src/css/mapbox-gl.css", "build-style-spec": "cd src/style-spec && npm run build && cd ../.. && mkdir -p dist/style-spec && cp src/style-spec/dist/* dist/style-spec", "watch-css": "postcss --watch -o dist/mapbox-gl.css src/css/mapbox-gl.css", "build-token": "node build/generate-access-token-script.js", "build-benchmarks": "BENCHMARK_VERSION=${BENCHMARK_VERSION:-\"$(git rev-parse --abbrev-ref HEAD) $(git rev-parse --short=7 HEAD)\"} rollup -c bench/versions/rollup_config_benchmarks.js", - "watch-benchmarks": "BENCHMARK_VERSION=${BENCHMARK_VERSION:-\"$(git rev-parse --abbrev-ref HEAD) $(git rev-parse --short=7 HEAD)\"} rollup -c bench/versions/rollup_config_benchmarks.js --watch", - "watch-style-benchmarks": "BENCHMARK_VERSION=${BENCHMARK_VERSION:-\"$(git rev-parse --abbrev-ref HEAD) $(git rev-parse --short=7 HEAD)\"} rollup -c bench/styles/rollup_config_benchmarks.js --watch", + "watch-benchmarks": "BENCHMARK_VERSION=${BENCHMARK_VERSION:-\"$(git rev-parse --abbrev-ref HEAD) $(git rev-parse --short=7 HEAD)\"} rollup -c bench/rollup_config_benchmarks.js -w", "start-server": "st --no-cache -H 0.0.0.0 --port 9966 --index index.html .", - "start": "run-p build-token watch-css watch-dev watch-benchmarks watch-style-benchmarks start-server", + "start": "run-p build-token watch-css watch-dev watch-benchmarks start-server", "start-debug": "run-p build-token watch-css watch-dev start-server", - "start-bench": "run-p build-token watch-benchmarks watch-style-benchmarks start-server", + "start-bench": "run-p build-token watch-benchmarks start-server", "build-docs": "documentation build --github --format json --config ./docs/documentation.yml --output docs/components/api.json src/index.js && npm run build-images", "build-images": "mkdir -p docs/img/dist && node docs/bin/build-image-config.js && node docs/bin/appropriate-images.js --all", "create-image": "node docs/bin/create-image", @@ -139,7 +140,7 @@ "open-changed-examples": "git diff --name-only publisher-production HEAD -- docs/pages/example/*.html | awk '{print \"http://127.0.0.1:4000/mapbox-gl-js/example/\" substr($0,33,length($0)-37)}' | xargs open", "test": "run-s lint lint-css test-flow test-unit", "test-suite": "run-s test-render test-query", - "test-suite-clean": "find test/integration/{render,query}-tests -mindepth 2 -type d -not \\( -exec test -e \"{}/style.json\" \\; \\) -print | xargs -t rm -r", + "test-suite-clean": "find test/integration/{render,query}-tests -mindepth 2 -type d -exec test -e \"{}/actual.png\" \\; -not \\( -exec test -e \"{}/style.json\" \\; \\) -print | xargs -t rm -r", "test-unit": "build/run-tap --reporter classic --no-coverage test/unit", "test-build": "build/run-tap --no-coverage test/build/**/*.test.js", "test-render": "node --max-old-space-size=2048 test/render.test.js", @@ -147,7 +148,7 @@ "test-expressions": "build/run-node test/expression.test.js", "test-flow": "build/run-node build/generate-flow-typed-style-spec && flow .", "test-cov": "nyc --require=@mapbox/flow-remove-types/register --reporter=text-summary --reporter=lcov --cache run-s test-unit test-expressions test-query test-render", - "prepublishOnly": "run-s build-flow-types build-dev build-prod-min build-prod build-css build-style-spec test-build", + "prepublishOnly": "run-s build-flow-types build-dev build-prod-min build-prod build-csp build-css build-style-spec test-build", "codegen": "build/run-node build/generate-style-code.js && build/run-node build/generate-struct-arrays.js" }, "files": [ diff --git a/rollup.config.csp.js b/rollup.config.csp.js new file mode 100644 index 00000000000..8e1aee8e5e2 --- /dev/null +++ b/rollup.config.csp.js @@ -0,0 +1,24 @@ +import {plugins} from './build/rollup_plugins'; +import banner from './build/banner'; + +// a config for generating a special GL JS bundle with static web worker code (in a separate file) +// https://github.com/mapbox/mapbox-gl-js/issues/6058 + +const config = (input, file, format) => ({ + input, + output: { + name: 'mapboxgl', + file, + format, + sourcemap: true, + indent: false, + banner + }, + treeshake: true, + plugins: plugins(true, true) +}); + +export default [ + config('src/index.js', 'dist/mapbox-gl-csp.js', 'umd'), + config('src/source/worker.js', 'dist/mapbox-gl-csp-worker.js', 'iife') +]; diff --git a/rollup.config.js b/rollup.config.js index f6db3ebd732..b103700d52c 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,8 +1,8 @@ import fs from 'fs'; import sourcemaps from 'rollup-plugin-sourcemaps'; import {plugins} from './build/rollup_plugins'; +import banner from './build/banner'; -const version = JSON.parse(fs.readFileSync('package.json')).version; const {BUILD, MINIFY} = process.env; const minified = MINIFY === 'true'; const production = BUILD === 'production'; @@ -10,7 +10,7 @@ const outputFile = !production ? 'dist/mapbox-gl-dev.js' : minified ? 'dist/mapbox-gl.js' : 'dist/mapbox-gl-unminified.js'; -const config = [{ +export default [{ // First, use code splitting to bundle GL JS into three "chunks": // - rollup/build/index.js: the main module, plus all its dependencies not shared by the worker module // - rollup/build/worker.js: the worker module, plus all dependencies not shared by the main module @@ -28,7 +28,7 @@ const config = [{ chunkFileNames: 'shared.js' }, treeshake: production, - plugins: plugins() + plugins: plugins(minified, production) }, { // Next, bundle together the three "chunks" produced in the previous pass // into a single, final bundle. See rollup/bundle_prelude.js and @@ -41,7 +41,7 @@ const config = [{ sourcemap: production ? true : 'inline', indent: false, intro: fs.readFileSync(require.resolve('./rollup/bundle_prelude.js'), 'utf8'), - banner: `/* Mapbox GL JS is licensed under the 3-Clause BSD License. Full text of license: https://github.com/mapbox/mapbox-gl-js/blob/v${version}/LICENSE.txt */` + banner }, treeshake: false, plugins: [ @@ -50,5 +50,3 @@ const config = [{ sourcemaps() ], }]; - -export default config diff --git a/rollup/style_benchmarks.js b/rollup/benchmarks_styles.js similarity index 67% rename from rollup/style_benchmarks.js rename to rollup/benchmarks_styles.js index b597fa66969..e845e179c23 100644 --- a/rollup/style_benchmarks.js +++ b/rollup/benchmarks_styles.js @@ -1,3 +1,3 @@ -import './build/benchmarks/styles/chunk1'; +import './build/benchmarks/styles/shared'; import './build/benchmarks/styles/worker'; import './build/benchmarks/styles/benchmarks'; diff --git a/rollup/benchmarks.js b/rollup/benchmarks_versions.js similarity index 67% rename from rollup/benchmarks.js rename to rollup/benchmarks_versions.js index 44eef330f90..5e7e4861d48 100644 --- a/rollup/benchmarks.js +++ b/rollup/benchmarks_versions.js @@ -1,3 +1,3 @@ -import './build/benchmarks/versions/chunk1'; +import './build/benchmarks/versions/shared'; import './build/benchmarks/versions/worker'; import './build/benchmarks/versions/benchmarks'; diff --git a/src/css/mapbox-gl.css b/src/css/mapbox-gl.css index 39fbadf00d4..276ef816d2b 100644 --- a/src/css/mapbox-gl.css +++ b/src/css/mapbox-gl.css @@ -56,7 +56,13 @@ .mapboxgl-ctrl-bottom-left { bottom: 0; left: 0; } .mapboxgl-ctrl-bottom-right { right: 0; bottom: 0; } -.mapboxgl-ctrl { clear: both; pointer-events: auto; } +.mapboxgl-ctrl { + clear: both; + pointer-events: auto; + + /* workaround for a Safari bug https://github.com/mapbox/mapbox-gl-js/issues/8185 */ + transform: translate(0, 0); +} .mapboxgl-ctrl-top-left .mapboxgl-ctrl { margin: 10px 0 0 10px; float: left; } .mapboxgl-ctrl-top-right .mapboxgl-ctrl { margin: 10px 10px 0 0; float: right; } .mapboxgl-ctrl-bottom-left .mapboxgl-ctrl { margin: 0 0 10px 10px; float: left; } @@ -111,6 +117,11 @@ padding: 5px; } +.mapboxgl-ctrl-icon.mapboxgl-ctrl-icon-disabled { + opacity: 0.25; + border-color: #373737; +} + .mapboxgl-ctrl-icon.mapboxgl-ctrl-zoom-out { background-image: svg-load('svg/mapboxgl-ctrl-zoom-out.svg'); } @@ -217,6 +228,8 @@ a.mapboxgl-ctrl-logo.mapboxgl-compact { @media screen { .mapboxgl-ctrl-attrib.mapboxgl-compact { + min-height: 20px; + padding: 0; margin: 10px; position: relative; background-color: #fff; @@ -226,6 +239,7 @@ a.mapboxgl-ctrl-logo.mapboxgl-compact { .mapboxgl-ctrl-attrib.mapboxgl-compact:hover { padding: 2px 24px 2px 4px; visibility: visible; + margin-top: 6px; } .mapboxgl-ctrl-top-left > .mapboxgl-ctrl-attrib.mapboxgl-compact:hover, diff --git a/src/data/array_types.js b/src/data/array_types.js index 68f83333693..aa22f10cd21 100644 --- a/src/data/array_types.js +++ b/src/data/array_types.js @@ -393,32 +393,38 @@ register('StructArrayLayout2i2i2i12', StructArrayLayout2i2i2i12); /** * Implementation of the StructArray layout: * [0]: Uint8[2] + * [4]: Float32[2] * * @private */ -class StructArrayLayout2ub4 extends StructArray { +class StructArrayLayout2ub2f12 extends StructArray { uint8: Uint8Array; + float32: Float32Array; _refreshViews() { this.uint8 = new Uint8Array(this.arrayBuffer); + this.float32 = new Float32Array(this.arrayBuffer); } - emplaceBack(v0: number, v1: number) { + emplaceBack(v0: number, v1: number, v2: number, v3: number) { const i = this.length; this.resize(i + 1); - return this.emplace(i, v0, v1); + return this.emplace(i, v0, v1, v2, v3); } - emplace(i: number, v0: number, v1: number) { - const o1 = i * 4; + emplace(i: number, v0: number, v1: number, v2: number, v3: number) { + const o1 = i * 12; + const o4 = i * 3; this.uint8[o1 + 0] = v0; this.uint8[o1 + 1] = v1; + this.float32[o4 + 1] = v2; + this.float32[o4 + 2] = v3; return i; } } -StructArrayLayout2ub4.prototype.bytesPerElement = 4; -register('StructArrayLayout2ub4', StructArrayLayout2ub4); +StructArrayLayout2ub2f12.prototype.bytesPerElement = 12; +register('StructArrayLayout2ub2f12', StructArrayLayout2ub2f12); /** @@ -429,10 +435,11 @@ register('StructArrayLayout2ub4', StructArrayLayout2ub4); * [20]: Uint16[3] * [28]: Float32[2] * [36]: Uint8[2] + * [40]: Uint32[1] * * @private */ -class StructArrayLayout2i2ui3ul3ui2f2ub40 extends StructArray { +class StructArrayLayout2i2ui3ul3ui2f2ub1ul44 extends StructArray { uint8: Uint8Array; int16: Int16Array; uint16: Uint16Array; @@ -447,16 +454,16 @@ class StructArrayLayout2i2ui3ul3ui2f2ub40 extends StructArray { this.float32 = new Float32Array(this.arrayBuffer); } - emplaceBack(v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number) { + emplaceBack(v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number, v14: number) { const i = this.length; this.resize(i + 1); - return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); + return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14); } - emplace(i: number, v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number) { - const o2 = i * 20; - const o4 = i * 10; - const o1 = i * 40; + emplace(i: number, v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number, v14: number) { + const o2 = i * 22; + const o4 = i * 11; + const o1 = i * 44; this.int16[o2 + 0] = v0; this.int16[o2 + 1] = v1; this.uint16[o2 + 2] = v2; @@ -471,50 +478,54 @@ class StructArrayLayout2i2ui3ul3ui2f2ub40 extends StructArray { this.float32[o4 + 8] = v11; this.uint8[o1 + 36] = v12; this.uint8[o1 + 37] = v13; + this.uint32[o4 + 10] = v14; return i; } } -StructArrayLayout2i2ui3ul3ui2f2ub40.prototype.bytesPerElement = 40; -register('StructArrayLayout2i2ui3ul3ui2f2ub40', StructArrayLayout2i2ui3ul3ui2f2ub40); +StructArrayLayout2i2ui3ul3ui2f2ub1ul44.prototype.bytesPerElement = 44; +register('StructArrayLayout2i2ui3ul3ui2f2ub1ul44', StructArrayLayout2i2ui3ul3ui2f2ub1ul44); /** * Implementation of the StructArray layout: - * [0]: Int16[4] - * [8]: Uint16[9] - * [28]: Uint32[1] + * [0]: Int16[6] + * [12]: Uint16[9] + * [32]: Uint32[1] + * [36]: Float32[2] * * @private */ -class StructArrayLayout4i9ui1ul32 extends StructArray { +class StructArrayLayout6i9ui1ul2f44 extends StructArray { uint8: Uint8Array; int16: Int16Array; uint16: Uint16Array; uint32: Uint32Array; + float32: Float32Array; _refreshViews() { this.uint8 = new Uint8Array(this.arrayBuffer); this.int16 = new Int16Array(this.arrayBuffer); this.uint16 = new Uint16Array(this.arrayBuffer); this.uint32 = new Uint32Array(this.arrayBuffer); + this.float32 = new Float32Array(this.arrayBuffer); } - emplaceBack(v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number) { + emplaceBack(v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number, v14: number, v15: number, v16: number, v17: number) { const i = this.length; this.resize(i + 1); - return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13); + return this.emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17); } - emplace(i: number, v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number) { - const o2 = i * 16; - const o4 = i * 8; + emplace(i: number, v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number, v8: number, v9: number, v10: number, v11: number, v12: number, v13: number, v14: number, v15: number, v16: number, v17: number) { + const o2 = i * 22; + const o4 = i * 11; this.int16[o2 + 0] = v0; this.int16[o2 + 1] = v1; this.int16[o2 + 2] = v2; this.int16[o2 + 3] = v3; - this.uint16[o2 + 4] = v4; - this.uint16[o2 + 5] = v5; + this.int16[o2 + 4] = v4; + this.int16[o2 + 5] = v5; this.uint16[o2 + 6] = v6; this.uint16[o2 + 7] = v7; this.uint16[o2 + 8] = v8; @@ -522,13 +533,17 @@ class StructArrayLayout4i9ui1ul32 extends StructArray { this.uint16[o2 + 10] = v10; this.uint16[o2 + 11] = v11; this.uint16[o2 + 12] = v12; - this.uint32[o4 + 7] = v13; + this.uint16[o2 + 13] = v13; + this.uint16[o2 + 14] = v14; + this.uint32[o4 + 8] = v15; + this.float32[o4 + 9] = v16; + this.float32[o4 + 10] = v17; return i; } } -StructArrayLayout4i9ui1ul32.prototype.bytesPerElement = 32; -register('StructArrayLayout4i9ui1ul32', StructArrayLayout4i9ui1ul32); +StructArrayLayout6i9ui1ul2f44.prototype.bytesPerElement = 44; +register('StructArrayLayout6i9ui1ul2f44', StructArrayLayout6i9ui1ul2f44); /** @@ -878,6 +893,7 @@ class PlacedSymbolStruct extends Struct { lineOffsetY: number; writingMode: number; hidden: number; + crossTileID: number; get anchorX() { return this._structArray.int16[this._pos2 + 0]; } set anchorX(x) { this._structArray.int16[this._pos2 + 0] = x; } get anchorY() { return this._structArray.int16[this._pos2 + 1]; } @@ -906,9 +922,11 @@ class PlacedSymbolStruct extends Struct { set writingMode(x) { this._structArray.uint8[this._pos1 + 36] = x; } get hidden() { return this._structArray.uint8[this._pos1 + 37]; } set hidden(x) { this._structArray.uint8[this._pos1 + 37] = x; } + get crossTileID() { return this._structArray.uint32[this._pos4 + 10]; } + set crossTileID(x) { this._structArray.uint32[this._pos4 + 10] = x; } } -PlacedSymbolStruct.prototype.size = 40; +PlacedSymbolStruct.prototype.size = 44; export type PlacedSymbol = PlacedSymbolStruct; @@ -916,7 +934,7 @@ export type PlacedSymbol = PlacedSymbolStruct; /** * @private */ -export class PlacedSymbolArray extends StructArrayLayout2i2ui3ul3ui2f2ub40 { +export class PlacedSymbolArray extends StructArrayLayout2i2ui3ul3ui2f2ub1ul44 { /** * Return the PlacedSymbolStruct at the given location in the array. * @param {number} index The index of the element. @@ -933,7 +951,9 @@ class SymbolInstanceStruct extends Struct { _structArray: SymbolInstanceArray; anchorX: number; anchorY: number; - horizontalPlacedTextSymbolIndex: number; + rightJustifiedTextSymbolIndex: number; + centerJustifiedTextSymbolIndex: number; + leftJustifiedTextSymbolIndex: number; verticalPlacedTextSymbolIndex: number; key: number; textBoxStartIndex: number; @@ -941,41 +961,51 @@ class SymbolInstanceStruct extends Struct { iconBoxStartIndex: number; iconBoxEndIndex: number; featureIndex: number; - numGlyphVertices: number; + numHorizontalGlyphVertices: number; numVerticalGlyphVertices: number; numIconVertices: number; crossTileID: number; + textBoxScale: number; + radialTextOffset: number; get anchorX() { return this._structArray.int16[this._pos2 + 0]; } set anchorX(x) { this._structArray.int16[this._pos2 + 0] = x; } get anchorY() { return this._structArray.int16[this._pos2 + 1]; } set anchorY(x) { this._structArray.int16[this._pos2 + 1] = x; } - get horizontalPlacedTextSymbolIndex() { return this._structArray.int16[this._pos2 + 2]; } - set horizontalPlacedTextSymbolIndex(x) { this._structArray.int16[this._pos2 + 2] = x; } - get verticalPlacedTextSymbolIndex() { return this._structArray.int16[this._pos2 + 3]; } - set verticalPlacedTextSymbolIndex(x) { this._structArray.int16[this._pos2 + 3] = x; } - get key() { return this._structArray.uint16[this._pos2 + 4]; } - set key(x) { this._structArray.uint16[this._pos2 + 4] = x; } - get textBoxStartIndex() { return this._structArray.uint16[this._pos2 + 5]; } - set textBoxStartIndex(x) { this._structArray.uint16[this._pos2 + 5] = x; } - get textBoxEndIndex() { return this._structArray.uint16[this._pos2 + 6]; } - set textBoxEndIndex(x) { this._structArray.uint16[this._pos2 + 6] = x; } - get iconBoxStartIndex() { return this._structArray.uint16[this._pos2 + 7]; } - set iconBoxStartIndex(x) { this._structArray.uint16[this._pos2 + 7] = x; } - get iconBoxEndIndex() { return this._structArray.uint16[this._pos2 + 8]; } - set iconBoxEndIndex(x) { this._structArray.uint16[this._pos2 + 8] = x; } - get featureIndex() { return this._structArray.uint16[this._pos2 + 9]; } - set featureIndex(x) { this._structArray.uint16[this._pos2 + 9] = x; } - get numGlyphVertices() { return this._structArray.uint16[this._pos2 + 10]; } - set numGlyphVertices(x) { this._structArray.uint16[this._pos2 + 10] = x; } - get numVerticalGlyphVertices() { return this._structArray.uint16[this._pos2 + 11]; } - set numVerticalGlyphVertices(x) { this._structArray.uint16[this._pos2 + 11] = x; } - get numIconVertices() { return this._structArray.uint16[this._pos2 + 12]; } - set numIconVertices(x) { this._structArray.uint16[this._pos2 + 12] = x; } - get crossTileID() { return this._structArray.uint32[this._pos4 + 7]; } - set crossTileID(x) { this._structArray.uint32[this._pos4 + 7] = x; } + get rightJustifiedTextSymbolIndex() { return this._structArray.int16[this._pos2 + 2]; } + set rightJustifiedTextSymbolIndex(x) { this._structArray.int16[this._pos2 + 2] = x; } + get centerJustifiedTextSymbolIndex() { return this._structArray.int16[this._pos2 + 3]; } + set centerJustifiedTextSymbolIndex(x) { this._structArray.int16[this._pos2 + 3] = x; } + get leftJustifiedTextSymbolIndex() { return this._structArray.int16[this._pos2 + 4]; } + set leftJustifiedTextSymbolIndex(x) { this._structArray.int16[this._pos2 + 4] = x; } + get verticalPlacedTextSymbolIndex() { return this._structArray.int16[this._pos2 + 5]; } + set verticalPlacedTextSymbolIndex(x) { this._structArray.int16[this._pos2 + 5] = x; } + get key() { return this._structArray.uint16[this._pos2 + 6]; } + set key(x) { this._structArray.uint16[this._pos2 + 6] = x; } + get textBoxStartIndex() { return this._structArray.uint16[this._pos2 + 7]; } + set textBoxStartIndex(x) { this._structArray.uint16[this._pos2 + 7] = x; } + get textBoxEndIndex() { return this._structArray.uint16[this._pos2 + 8]; } + set textBoxEndIndex(x) { this._structArray.uint16[this._pos2 + 8] = x; } + get iconBoxStartIndex() { return this._structArray.uint16[this._pos2 + 9]; } + set iconBoxStartIndex(x) { this._structArray.uint16[this._pos2 + 9] = x; } + get iconBoxEndIndex() { return this._structArray.uint16[this._pos2 + 10]; } + set iconBoxEndIndex(x) { this._structArray.uint16[this._pos2 + 10] = x; } + get featureIndex() { return this._structArray.uint16[this._pos2 + 11]; } + set featureIndex(x) { this._structArray.uint16[this._pos2 + 11] = x; } + get numHorizontalGlyphVertices() { return this._structArray.uint16[this._pos2 + 12]; } + set numHorizontalGlyphVertices(x) { this._structArray.uint16[this._pos2 + 12] = x; } + get numVerticalGlyphVertices() { return this._structArray.uint16[this._pos2 + 13]; } + set numVerticalGlyphVertices(x) { this._structArray.uint16[this._pos2 + 13] = x; } + get numIconVertices() { return this._structArray.uint16[this._pos2 + 14]; } + set numIconVertices(x) { this._structArray.uint16[this._pos2 + 14] = x; } + get crossTileID() { return this._structArray.uint32[this._pos4 + 8]; } + set crossTileID(x) { this._structArray.uint32[this._pos4 + 8] = x; } + get textBoxScale() { return this._structArray.float32[this._pos4 + 9]; } + set textBoxScale(x) { this._structArray.float32[this._pos4 + 9] = x; } + get radialTextOffset() { return this._structArray.float32[this._pos4 + 10]; } + set radialTextOffset(x) { this._structArray.float32[this._pos4 + 10] = x; } } -SymbolInstanceStruct.prototype.size = 32; +SymbolInstanceStruct.prototype.size = 44; export type SymbolInstance = SymbolInstanceStruct; @@ -983,7 +1013,7 @@ export type SymbolInstance = SymbolInstanceStruct; /** * @private */ -export class SymbolInstanceArray extends StructArrayLayout4i9ui1ul32 { +export class SymbolInstanceArray extends StructArrayLayout6i9ui1ul2f44 { /** * Return the SymbolInstanceStruct at the given location in the array. * @param {number} index The index of the element. @@ -1108,9 +1138,9 @@ export { StructArrayLayout1ul4, StructArrayLayout6i1ul2ui2i24, StructArrayLayout2i2i2i12, - StructArrayLayout2ub4, - StructArrayLayout2i2ui3ul3ui2f2ub40, - StructArrayLayout4i9ui1ul32, + StructArrayLayout2ub2f12, + StructArrayLayout2i2ui3ul3ui2f2ub1ul44, + StructArrayLayout6i9ui1ul2f44, StructArrayLayout1f4, StructArrayLayout3i6, StructArrayLayout1ul2ui8, @@ -1132,7 +1162,7 @@ export { StructArrayLayout1ul4 as SymbolOpacityArray, StructArrayLayout2i2i2i12 as CollisionBoxLayoutArray, StructArrayLayout2i2i2i12 as CollisionCircleLayoutArray, - StructArrayLayout2ub4 as CollisionVertexArray, + StructArrayLayout2ub2f12 as CollisionVertexArray, StructArrayLayout3ui6 as TriangleIndexArray, StructArrayLayout2ui4 as LineIndexArray, StructArrayLayout1ui2 as LineStripIndexArray diff --git a/src/data/bucket/fill_extrusion_bucket.js b/src/data/bucket/fill_extrusion_bucket.js index 9299e3428c8..ef04143db45 100644 --- a/src/data/bucket/fill_extrusion_bucket.js +++ b/src/data/bucket/fill_extrusion_bucket.js @@ -8,6 +8,8 @@ import { ProgramConfigurationSet } from '../program_configuration'; import { TriangleIndexArray } from '../index_array_type'; import EXTENT from '../extent'; import earcut from 'earcut'; +import mvt from '@mapbox/vector-tile'; +const vectorTileFeatureTypes = mvt.VectorTileFeature.types; import classifyRings from '../../util/classify_rings'; import assert from 'assert'; const EARCUT_MAX_RINGS = 500; @@ -219,6 +221,11 @@ class FillExtrusionBucket implements Bucket { segment = this.segments.prepareSegment(numVertices, this.layoutVertexArray, this.indexArray); } + //Only triangulate and draw the area of the feature if it is a polygon + //Other feature types (e.g. LineString) do not have area, so triangulation is pointless / undefined + if (vectorTileFeatureTypes[feature.type] !== 'Polygon') + continue; + const flattened = []; const holeIndices = []; const triangleIndex = segment.vertexLength; diff --git a/src/data/bucket/symbol_attributes.js b/src/data/bucket/symbol_attributes.js index ea07cbd61cb..dfe10cbdaed 100644 --- a/src/data/bucket/symbol_attributes.js +++ b/src/data/bucket/symbol_attributes.js @@ -16,8 +16,9 @@ export const placementOpacityAttributes = createLayout([ ], 4); export const collisionVertexAttributes = createLayout([ - { name: 'a_placed', components: 2, type: 'Uint8' } -], 4); + { name: 'a_placed', components: 2, type: 'Uint8' }, + { name: 'a_shift', components: 2, type: 'Float32'} +]); export const collisionBox = createLayout([ // the box is centered around the anchor point @@ -70,13 +71,16 @@ export const placement = createLayout([ { type: 'Float32', name: 'lineOffsetX' }, { type: 'Float32', name: 'lineOffsetY' }, { type: 'Uint8', name: 'writingMode' }, - { type: 'Uint8', name: 'hidden' } + { type: 'Uint8', name: 'hidden' }, + { type: 'Uint32', name: 'crossTileID'} ]); export const symbolInstance = createLayout([ { type: 'Int16', name: 'anchorX' }, { type: 'Int16', name: 'anchorY' }, - { type: 'Int16', name: 'horizontalPlacedTextSymbolIndex' }, + { type: 'Int16', name: 'rightJustifiedTextSymbolIndex' }, + { type: 'Int16', name: 'centerJustifiedTextSymbolIndex' }, + { type: 'Int16', name: 'leftJustifiedTextSymbolIndex' }, { type: 'Int16', name: 'verticalPlacedTextSymbolIndex' }, { type: 'Uint16', name: 'key' }, { type: 'Uint16', name: 'textBoxStartIndex' }, @@ -84,10 +88,12 @@ export const symbolInstance = createLayout([ { type: 'Uint16', name: 'iconBoxStartIndex' }, { type: 'Uint16', name: 'iconBoxEndIndex' }, { type: 'Uint16', name: 'featureIndex' }, - { type: 'Uint16', name: 'numGlyphVertices' }, + { type: 'Uint16', name: 'numHorizontalGlyphVertices' }, { type: 'Uint16', name: 'numVerticalGlyphVertices' }, { type: 'Uint16', name: 'numIconVertices' }, - { type: 'Uint32', name: 'crossTileID' } + { type: 'Uint32', name: 'crossTileID' }, + { type: 'Float32', name: 'textBoxScale'}, + { type: 'Float32', name: 'radialTextOffset'} ]); export const glyphOffset = createLayout([ diff --git a/src/data/bucket/symbol_bucket.js b/src/data/bucket/symbol_bucket.js index 311123af722..b333170761f 100644 --- a/src/data/bucket/symbol_bucket.js +++ b/src/data/bucket/symbol_bucket.js @@ -1,8 +1,24 @@ // @flow -import { symbolLayoutAttributes, collisionVertexAttributes, collisionBoxLayout, collisionCircleLayout, dynamicLayoutAttributes } from './symbol_attributes'; +import { symbolLayoutAttributes, + collisionVertexAttributes, + collisionBoxLayout, + collisionCircleLayout, + dynamicLayoutAttributes +} from './symbol_attributes'; + +import { SymbolLayoutArray, + SymbolDynamicLayoutArray, + SymbolOpacityArray, + CollisionBoxLayoutArray, + CollisionCircleLayoutArray, + CollisionVertexArray, + PlacedSymbolArray, + SymbolInstanceArray, + GlyphOffsetArray, + SymbolLineVertexArray +} from '../array_types'; -import { SymbolLayoutArray, SymbolDynamicLayoutArray, SymbolOpacityArray, CollisionBoxLayoutArray, CollisionCircleLayoutArray, CollisionVertexArray, PlacedSymbolArray, SymbolInstanceArray, GlyphOffsetArray, SymbolLineVertexArray } from '../array_types'; import Point from '@mapbox/point-geometry'; import SegmentVector from '../segment'; import { ProgramConfigurationSet } from '../program_configuration'; @@ -539,7 +555,9 @@ class SymbolBucket implements Bucket { lineStartIndex, lineLength, (labelAnchor.segment: any), sizeVertex ? sizeVertex[0] : 0, sizeVertex ? sizeVertex[1] : 0, lineOffset[0], lineOffset[1], - writingMode, (false: any)); + writingMode, (false: any), + // The crossTileID is only filled/used on the foreground for dynamic text anchors + 0); arrays.programConfigurations.populatePaintArrays(arrays.layoutVertexArray.length, feature, feature.index, {}); } @@ -731,9 +749,19 @@ class SymbolBucket implements Bucket { const symbolInstance = this.symbolInstances.get(i); this.featureSortOrder.push(symbolInstance.featureIndex); - if (symbolInstance.horizontalPlacedTextSymbolIndex >= 0) { - this.addIndicesForPlacedTextSymbol(symbolInstance.horizontalPlacedTextSymbolIndex); - } + [ + symbolInstance.rightJustifiedTextSymbolIndex, + symbolInstance.centerJustifiedTextSymbolIndex, + symbolInstance.leftJustifiedTextSymbolIndex + ].forEach((index, i, array) => { + // Only add a given index the first time it shows up, + // to avoid duplicate opacity entries when multiple justifications + // share the same glyphs. + if (index >= 0 && array.indexOf(index) === i) { + this.addIndicesForPlacedTextSymbol(index); + } + }); + if (symbolInstance.verticalPlacedTextSymbolIndex >= 0) { this.addIndicesForPlacedTextSymbol(symbolInstance.verticalPlacedTextSymbolIndex); } diff --git a/src/data/program_configuration.js b/src/data/program_configuration.js index 62323770265..d37baf45ba2 100644 --- a/src/data/program_configuration.js +++ b/src/data/program_configuration.js @@ -14,7 +14,6 @@ import { Uniform1f, UniformColor, Uniform4f, - type UniformBindings, type UniformLocations } from '../render/uniform_binding'; @@ -34,6 +33,12 @@ import type { import type {PossiblyEvaluated} from '../style/properties'; import type {FeatureStates} from '../source/source_state'; +export type BinderUniform = { + name: string, + property: string, + binding: Uniform +}; + function packColor(color: Color): [number, number] { return [ packUint8ToFloat(255 * color.r, 255 * color.g), @@ -659,26 +664,25 @@ export default class ProgramConfiguration { return this._buffers; } - getUniforms(context: Context, locations: UniformLocations): UniformBindings { - const result = {}; + getUniforms(context: Context, locations: UniformLocations): Array { + const uniforms = []; for (const property in this.binders) { const binder = this.binders[property]; for (const name of binder.uniformNames) { - result[name] = binder.getBinding(context, locations[name]); + if (locations[name]) { + const binding = binder.getBinding(context, locations[name]); + uniforms.push({name, property, binding}); + } } } - return result; + return uniforms; } - setUniforms(context: Context, uniformBindings: UniformBindings, properties: PossiblyEvaluated, globals: GlobalProperties) { + setUniforms(context: Context, binderUniforms: Array, properties: PossiblyEvaluated, globals: GlobalProperties) { // Uniform state bindings are owned by the Program, but we set them // from within the ProgramConfiguraton's binder members. - - for (const property in this.binders) { - const binder = this.binders[property]; - for (const uniformName of binder.uniformNames) { - binder.setUniforms(context, uniformBindings[uniformName], globals, properties.get(property), uniformName); - } + for (const {name, property, binding} of binderUniforms) { + this.binders[property].setUniforms(context, binding, globals, properties.get(property), name); } } diff --git a/src/geo/transform.js b/src/geo/transform.js index bccffa27774..2707af82fda 100644 --- a/src/geo/transform.js +++ b/src/geo/transform.js @@ -37,6 +37,8 @@ class Transform { alignedProjMatrix: Float64Array; pixelMatrix: Float64Array; pixelMatrixInverse: Float64Array; + glCoordMatrix: Float32Array; + labelPlaneMatrix: Float32Array; _fov: number; _pitch: number; _zoom: number; @@ -568,11 +570,19 @@ class Transform { mat4.translate(alignedM, alignedM, [ dx > 0.5 ? dx - 1 : dx, dy > 0.5 ? dy - 1 : dy, 0 ]); this.alignedProjMatrix = alignedM; - // matrix for conversion from location to screen coordinates m = mat4.create(); mat4.scale(m, m, [this.width / 2, -this.height / 2, 1]); mat4.translate(m, m, [1, -1, 0]); - this.pixelMatrix = mat4.multiply(new Float64Array(16), m, this.projMatrix); + this.labelPlaneMatrix = m; + + m = mat4.create(); + mat4.scale(m, m, [1, -1, 1]); + mat4.translate(m, m, [-1, -1, 0]); + mat4.scale(m, m, [2 / this.width, 2 / this.height, 1]); + this.glCoordMatrix = m; + + // matrix for conversion from location to screen coordinates + this.pixelMatrix = mat4.multiply(new Float64Array(16), this.labelPlaneMatrix, this.projMatrix); // inverse matrix for conversion from screen coordinaes to location m = mat4.invert(new Float64Array(16), this.pixelMatrix); diff --git a/src/render/draw_custom.js b/src/render/draw_custom.js index e9dd3328e2b..a4a90bae2ec 100644 --- a/src/render/draw_custom.js +++ b/src/render/draw_custom.js @@ -4,7 +4,6 @@ export default drawCustom; import DepthMode from '../gl/depth_mode'; import StencilMode from '../gl/stencil_mode'; -import {prepareOffscreenFramebuffer, drawOffscreenTexture} from './offscreen'; import type Painter from './painter'; import type SourceCache from '../source/source_cache'; @@ -20,6 +19,7 @@ function drawCustom(painter: Painter, sourceCache: SourceCache, layer: CustomSty const prerender = implementation.prerender; if (prerender) { painter.setCustomLayerDefaults(); + context.setColorMode(painter.colorModeForRenderPass()); prerender.call(implementation, context.gl, painter.transform.customLayerMatrix()); @@ -27,35 +27,23 @@ function drawCustom(painter: Painter, sourceCache: SourceCache, layer: CustomSty painter.setBaseState(); } - if (implementation.renderingMode === '3d') { - painter.setCustomLayerDefaults(); - - prepareOffscreenFramebuffer(painter, layer); - implementation.render(context.gl, painter.transform.customLayerMatrix()); - - context.setDirty(); - painter.setBaseState(); - } - } else if (painter.renderPass === 'translucent') { - if (implementation.renderingMode === '3d') { - drawOffscreenTexture(painter, layer, 1); + painter.setCustomLayerDefaults(); - } else { - painter.setCustomLayerDefaults(); + context.setColorMode(painter.colorModeForRenderPass()); + context.setStencilMode(StencilMode.disabled); - context.setColorMode(painter.colorModeForRenderPass()); - context.setStencilMode(StencilMode.disabled); + const depthMode = implementation.renderingMode === '3d' ? + new DepthMode(painter.context.gl.LEQUAL, DepthMode.ReadWrite, painter.depthRangeFor3D) : + painter.depthModeForSublayer(0, DepthMode.ReadOnly); - const depthMode = painter.depthModeForSublayer(0, DepthMode.ReadOnly); - context.setDepthMode(depthMode); + context.setDepthMode(depthMode); - implementation.render(context.gl, painter.transform.customLayerMatrix()); + implementation.render(context.gl, painter.transform.customLayerMatrix()); - context.setDirty(); - painter.setBaseState(); - context.bindFramebuffer.set(null); - } + context.setDirty(); + painter.setBaseState(); + context.bindFramebuffer.set(null); } } diff --git a/src/render/draw_debug.js b/src/render/draw_debug.js index f3921b7ec40..58266cf6f10 100644 --- a/src/render/draw_debug.js +++ b/src/render/draw_debug.js @@ -40,7 +40,10 @@ function drawDebugTile(painter, sourceCache, coord) { debugUniformValues(posMatrix, Color.red), id, painter.debugBuffer, painter.tileBorderIndexBuffer, painter.debugSegments); - const vertices = createTextVertices(coord.toString(), 50, 200, 5); + const tileRawData = sourceCache.getTileByID(coord.key).latestRawTileData; + const tileByteLength = (tileRawData && tileRawData.byteLength) || 0; + const tileSizeKb = Math.floor(tileByteLength / 1024); + const vertices = createTextVertices(`${coord.toString()} ${tileSizeKb}kb`, 50, 200, 5); const debugTextArray = new PosArray(); const debugTextIndices = new LineIndexArray(); for (let v = 0; v < vertices.length; v += 2) { diff --git a/src/render/draw_fill.js b/src/render/draw_fill.js index 9a55a8df978..43881296ab9 100644 --- a/src/render/draw_fill.js +++ b/src/render/draw_fill.js @@ -29,7 +29,8 @@ function drawFill(painter: Painter, sourceCache: SourceCache, layer: FillStyleLa const colorMode = painter.colorModeForRenderPass(); const pattern = layer.paint.get('fill-pattern'); - const pass = (!pattern.constantOr((1: any)) && + const pass = painter.opaquePassEnabledForLayer() && + (!pattern.constantOr((1: any)) && color.constantOr(Color.transparent).a === 1 && opacity.constantOr(0) === 1) ? 'opaque' : 'translucent'; diff --git a/src/render/draw_fill_extrusion.js b/src/render/draw_fill_extrusion.js index 40f1f03dac1..444f3d8d914 100644 --- a/src/render/draw_fill_extrusion.js +++ b/src/render/draw_fill_extrusion.js @@ -2,12 +2,12 @@ import DepthMode from '../gl/depth_mode'; import StencilMode from '../gl/stencil_mode'; +import ColorMode from '../gl/color_mode'; import CullFaceMode from '../gl/cull_face_mode'; import { fillExtrusionUniformValues, fillExtrusionPatternUniformValues, } from './program/fill_extrusion_program'; -import {prepareOffscreenFramebuffer, drawOffscreenTexture} from './offscreen'; import type Painter from './painter'; import type SourceCache from '../source/source_cache'; @@ -18,21 +18,32 @@ import type {OverscaledTileID} from '../source/tile_id'; export default draw; function draw(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array) { - if (layer.paint.get('fill-extrusion-opacity') === 0) { + const opacity = layer.paint.get('fill-extrusion-opacity'); + if (opacity === 0) { return; } - if (painter.renderPass === 'offscreen') { - prepareOffscreenFramebuffer(painter, layer); - - const depthMode = new DepthMode(painter.context.gl.LEQUAL, DepthMode.ReadWrite, [0, 1]), - stencilMode = StencilMode.disabled, - colorMode = painter.colorModeForRenderPass(); - - drawExtrusionTiles(painter, source, layer, coords, depthMode, stencilMode, colorMode); - - } else if (painter.renderPass === 'translucent') { - drawOffscreenTexture(painter, layer, layer.paint.get('fill-extrusion-opacity')); + if (painter.renderPass === 'translucent') { + const depthMode = new DepthMode(painter.context.gl.LEQUAL, DepthMode.ReadWrite, painter.depthRangeFor3D); + + if (opacity === 1 && !layer.paint.get('fill-extrusion-pattern').constantOr((1: any))) { + const colorMode = painter.colorModeForRenderPass(); + drawExtrusionTiles(painter, source, layer, coords, depthMode, StencilMode.disabled, colorMode); + + } else { + // Draw transparent buildings in two passes so that only the closest surface is drawn. + // First draw all the extrusions into only the depth buffer. No colors are drawn. + drawExtrusionTiles(painter, source, layer, coords, depthMode, + StencilMode.disabled, + ColorMode.disabled); + + // Then draw all the extrusions a second type, only coloring fragments if they have the + // same depth value as the closest fragment in the previous pass. Use the stencil buffer + // to prevent the second draw in cases where we have coincident polygons. + drawExtrusionTiles(painter, source, layer, coords, depthMode, + painter.stencilModeFor3D(), + painter.colorModeForRenderPass()); + } } } @@ -42,6 +53,7 @@ function drawExtrusionTiles(painter, source, layer, coords, depthMode, stencilMo const patternProperty = layer.paint.get('fill-extrusion-pattern'); const image = patternProperty.constantOr((1: any)); const crossfade = layer.getCrossfadeParameters(); + const opacity = layer.paint.get('fill-extrusion-opacity'); for (const coord of coords) { const tile = source.getTile(coord); @@ -72,8 +84,8 @@ function drawExtrusionTiles(painter, source, layer, coords, depthMode, stencilMo const shouldUseVerticalGradient = layer.paint.get('fill-extrusion-vertical-gradient'); const uniformValues = image ? - fillExtrusionPatternUniformValues(matrix, painter, shouldUseVerticalGradient, coord, crossfade, tile) : - fillExtrusionUniformValues(matrix, painter, shouldUseVerticalGradient); + fillExtrusionPatternUniformValues(matrix, painter, shouldUseVerticalGradient, opacity, coord, crossfade, tile) : + fillExtrusionUniformValues(matrix, painter, shouldUseVerticalGradient, opacity); program.draw(context, context.gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.backCCW, diff --git a/src/render/draw_symbol.js b/src/render/draw_symbol.js index 26b9fca165b..39ebba4caf7 100644 --- a/src/render/draw_symbol.js +++ b/src/render/draw_symbol.js @@ -1,5 +1,6 @@ // @flow +import Point from '@mapbox/point-geometry'; import drawCollisionDebug from './draw_collision_debug'; import SegmentVector from '../data/segment'; @@ -13,6 +14,12 @@ const symbolLayoutProperties = properties.layout; import StencilMode from '../gl/stencil_mode'; import DepthMode from '../gl/depth_mode'; import CullFaceMode from '../gl/cull_face_mode'; +import {addDynamicAttributes} from '../data/bucket/symbol_bucket'; + +import { getAnchorAlignment } from '../symbol/shaping'; +import ONE_EM from '../symbol/one_em'; +import { evaluateRadialOffset } from '../symbol/symbol_layout'; + import { symbolIconUniformValues, symbolSDFUniformValues @@ -26,6 +33,7 @@ import type Texture from '../render/texture'; import type {OverscaledTileID} from '../source/tile_id'; import type {UniformValues} from './uniform_binding'; import type {SymbolSDFUniformsType} from '../render/program/symbol_program'; +import type { CrossTileID, VariableOffset } from '../symbol/placement'; export default drawSymbols; @@ -43,7 +51,7 @@ type SymbolTileRenderState = { } }; -function drawSymbols(painter: Painter, sourceCache: SourceCache, layer: SymbolStyleLayer, coords: Array) { +function drawSymbols(painter: Painter, sourceCache: SourceCache, layer: SymbolStyleLayer, coords: Array, variableOffsets: {[CrossTileID]: VariableOffset}) { if (painter.renderPass !== 'translucent') return; // Disable the stencil test so that labels aren't clipped to tile boundaries. @@ -57,7 +65,7 @@ function drawSymbols(painter: Painter, sourceCache: SourceCache, layer: SymbolSt layer.layout.get('icon-rotation-alignment'), layer.layout.get('icon-pitch-alignment'), layer.layout.get('icon-keep-upright'), - stencilMode, colorMode + stencilMode, colorMode, variableOffsets ); } @@ -68,7 +76,7 @@ function drawSymbols(painter: Painter, sourceCache: SourceCache, layer: SymbolSt layer.layout.get('text-rotation-alignment'), layer.layout.get('text-pitch-alignment'), layer.layout.get('text-keep-upright'), - stencilMode, colorMode + stencilMode, colorMode, variableOffsets ); } @@ -77,8 +85,63 @@ function drawSymbols(painter: Painter, sourceCache: SourceCache, layer: SymbolSt } } +function calculateVariableRenderShift(anchor, width, height, radialOffset, textBoxScale, renderTextSize): Point { + const {horizontalAlign, verticalAlign} = getAnchorAlignment(anchor); + const shiftX = -(horizontalAlign - 0.5) * width; + const shiftY = -(verticalAlign - 0.5) * height; + const offset = evaluateRadialOffset(anchor, radialOffset); + return new Point( + (shiftX / textBoxScale + offset[0]) * renderTextSize, + (shiftY / textBoxScale + offset[1]) * renderTextSize + ); +} + +function updateVariableAnchors(bucket, rotateWithMap, pitchWithMap, variableOffsets, symbolSize, + transform, labelPlaneMatrix, posMatrix, tileScale, size) { + const placedSymbols = bucket.text.placedSymbolArray; + const dynamicLayoutVertexArray = bucket.text.dynamicLayoutVertexArray; + dynamicLayoutVertexArray.clear(); + for (let s = 0; s < placedSymbols.length; s++) { + const symbol: any = placedSymbols.get(s); + const variableOffset = (!symbol.hidden && symbol.crossTileID) ? variableOffsets[symbol.crossTileID] : null; + if (!variableOffset) { + // These symbols are from a justification that is not being used, or a label that wasn't placed + // so we don't need to do the extra math to figure out what incremental shift to apply. + symbolProjection.hideGlyphs(symbol.numGlyphs, dynamicLayoutVertexArray); + } else { + const tileAnchor = new Point(symbol.anchorX, symbol.anchorY); + const projectedAnchor = symbolProjection.project(tileAnchor, pitchWithMap ? posMatrix : labelPlaneMatrix); + const perspectiveRatio = 0.5 + 0.5 * (transform.cameraToCenterDistance / projectedAnchor.signedDistanceFromCamera); + let renderTextSize = symbolSize.evaluateSizeForFeature(bucket.textSizeData, size, symbol) * perspectiveRatio / ONE_EM; + if (pitchWithMap) { + // Go from size in pixels to equivalent size in tile units + renderTextSize *= bucket.tilePixelRatio / tileScale; + } + + const { width, height, radialOffset, textBoxScale } = variableOffset; + + const shift = calculateVariableRenderShift( + variableOffset.anchor, width, height, radialOffset, textBoxScale, renderTextSize); + + // Usual case is that we take the projected anchor and add the pixel-based shift + // calculated above. In the (somewhat weird) case of pitch-aligned text, we add an equivalent + // tile-unit based shift to the anchor before projecting to the label plane. + const shiftedAnchor = pitchWithMap ? + symbolProjection.project(tileAnchor.add(shift), labelPlaneMatrix).point : + projectedAnchor.point.add(rotateWithMap ? + shift.rotate(-transform.angle) : + shift); + + for (let g = 0; g < symbol.numGlyphs; g++) { + addDynamicAttributes(dynamicLayoutVertexArray, shiftedAnchor, 0); + } + } + } + bucket.text.dynamicLayoutVertexBuffer.updateData(dynamicLayoutVertexArray); +} + function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate, translateAnchor, - rotationAlignment, pitchAlignment, keepUpright, stencilMode, colorMode) { + rotationAlignment, pitchAlignment, keepUpright, stencilMode, colorMode, variableOffsets) { const context = painter.context; const gl = context.gl; @@ -98,6 +161,7 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate let program; let size; + const variablePlacement = layer.layout.get('text-variable-anchor'); const tileRenderState: Array = []; @@ -145,10 +209,14 @@ function drawLayerSymbols(painter, sourceCache, layer, coords, isText, translate if (alongLine) { symbolProjection.updateLineLabels(bucket, coord.posMatrix, painter, isText, labelPlaneMatrix, glCoordMatrix, pitchWithMap, keepUpright); + } else if (isText && size && variablePlacement) { + const tileScale = Math.pow(2, tr.zoom - tile.tileID.overscaledZ); + updateVariableAnchors(bucket, rotateWithMap, pitchWithMap, variableOffsets, symbolSize, + tr, labelPlaneMatrix, coord.posMatrix, tileScale, size); } const matrix = painter.translatePosMatrix(coord.posMatrix, tile, translate, translateAnchor), - uLabelPlaneMatrix = alongLine ? identityMat4 : labelPlaneMatrix, + uLabelPlaneMatrix = (alongLine || (isText && variablePlacement)) ? identityMat4 : labelPlaneMatrix, uglCoordMatrix = painter.translatePosMatrix(glCoordMatrix, tile, translate, translateAnchor, true); const hasHalo = isSDF && layer.paint.get(isText ? 'text-halo-width' : 'icon-halo-width').constantOr(1) !== 0; @@ -223,4 +291,3 @@ function drawSymbolElements(buffers, segments, layer, painter, program, depthMod painter.transform.zoom, buffers.programConfigurations.get(layer.id), buffers.dynamicLayoutVertexBuffer, buffers.opacityVertexBuffer); } - diff --git a/src/render/image_atlas.js b/src/render/image_atlas.js index 8bb25e12d8a..51ad8c729e7 100644 --- a/src/render/image_atlas.js +++ b/src/render/image_atlas.js @@ -5,6 +5,8 @@ import { register } from '../util/web_worker_transfer'; import potpack from 'potpack'; import type {StyleImage} from '../style/style_image'; +import type ImageManager from './image_manager'; +import type Texture from './texture'; const padding = 1; @@ -19,10 +21,12 @@ type Rect = { export class ImagePosition { paddedRect: Rect; pixelRatio: number; + version: number; - constructor(paddedRect: Rect, {pixelRatio}: StyleImage) { + constructor(paddedRect: Rect, {pixelRatio, version}: StyleImage) { this.paddedRect = paddedRect; this.pixelRatio = pixelRatio; + this.version = version; } get tl(): [number, number] { @@ -55,35 +59,17 @@ export default class ImageAtlas { image: RGBAImage; iconPositions: {[string]: ImagePosition}; patternPositions: {[string]: ImagePosition}; + haveRenderCallbacks: Array; uploaded: ?boolean; constructor(icons: {[string]: StyleImage}, patterns: {[string]: StyleImage}) { const iconPositions = {}, patternPositions = {}; + this.haveRenderCallbacks = []; const bins = []; - for (const id in icons) { - const src = icons[id]; - const bin = { - x: 0, - y: 0, - w: src.data.width + 2 * padding, - h: src.data.height + 2 * padding, - }; - bins.push(bin); - iconPositions[id] = new ImagePosition(bin, src); - } - for (const id in patterns) { - const src = patterns[id]; - const bin = { - x: 0, - y: 0, - w: src.data.width + 2 * padding, - h: src.data.height + 2 * padding, - }; - bins.push(bin); - patternPositions[id] = new ImagePosition(bin, src); - } + this.addImages(icons, iconPositions, bins); + this.addImages(patterns, patternPositions, bins); const {w, h} = potpack(bins); const image = new RGBAImage({width: w || 1, height: h || 1}); @@ -114,6 +100,43 @@ export default class ImageAtlas { this.iconPositions = iconPositions; this.patternPositions = patternPositions; } + + addImages(images: {[string]: StyleImage}, positions: {[string]: ImagePosition}, bins: Array) { + for (const id in images) { + const src = images[id]; + const bin = { + x: 0, + y: 0, + w: src.data.width + 2 * padding, + h: src.data.height + 2 * padding, + }; + bins.push(bin); + positions[id] = new ImagePosition(bin, src); + + if (src.hasRenderCallback) { + this.haveRenderCallbacks.push(id); + } + } + } + + patchUpdatedImages(imageManager: ImageManager, texture: Texture) { + imageManager.dispatchRenderCallbacks(this.haveRenderCallbacks); + for (const name in imageManager.updatedImages) { + this.patchUpdatedImage(this.iconPositions[name], imageManager.getImage(name), texture); + this.patchUpdatedImage(this.patternPositions[name], imageManager.getImage(name), texture); + } + } + + patchUpdatedImage(position: ?ImagePosition, image: ?StyleImage, texture: Texture) { + if (!position || !image) return; + + if (position.version === image.version) return; + + position.version = image.version; + const [x, y] = position.tl; + texture.update(image.data, undefined, {x, y}); + } + } register('ImagePosition', ImagePosition); diff --git a/src/render/image_manager.js b/src/render/image_manager.js index fee826e4155..dbb63aaa63d 100644 --- a/src/render/image_manager.js +++ b/src/render/image_manager.js @@ -2,10 +2,13 @@ import potpack from 'potpack'; +import { Event, Evented } from '../util/evented'; import { RGBAImage } from '../util/image'; import { ImagePosition } from './image_atlas'; import Texture from './texture'; import assert from 'assert'; +import {renderStyleImage} from '../style/style_image'; +import { warnOnce } from '../util/util'; import type {StyleImage} from '../style/style_image'; import type Context from '../gl/context'; @@ -24,17 +27,20 @@ type Pattern = { const padding = 1; /* - ImageManager does two things: + ImageManager does three things: 1. Tracks requests for icon images from tile workers and sends responses when the requests are fulfilled. 2. Builds a texture atlas for pattern images. + 3. Rerenders renderable images once per frame These are disparate responsibilities and should eventually be handled by different classes. When we implement data-driven support for `*-pattern`, we'll likely use per-bucket pattern atlases, and that would be a good time to refactor this. */ -class ImageManager { +class ImageManager extends Evented { images: {[string]: StyleImage}; + updatedImages: {[string]: boolean}; + callbackDispatchedThisFrame: {[string]: boolean}; loaded: boolean; requestors: Array<{ids: Array, callback: Callback<{[string]: StyleImage}>}>; @@ -44,7 +50,10 @@ class ImageManager { dirty: boolean; constructor() { + super(); this.images = {}; + this.updatedImages = {}; + this.callbackDispatchedThisFrame = {}; this.loaded = false; this.requestors = []; @@ -81,10 +90,25 @@ class ImageManager { this.images[id] = image; } + updateImage(id: string, image: StyleImage) { + const oldImage = this.images[id]; + assert(oldImage); + assert(oldImage.data.width === image.data.width); + assert(oldImage.data.height === image.data.height); + image.version = oldImage.version + 1; + this.images[id] = image; + this.updatedImages[id] = true; + } + removeImage(id: string) { assert(this.images[id]); + const image = this.images[id]; delete this.images[id]; delete this.patterns[id]; + + if (image.userImage && image.userImage.onRemove) { + image.userImage.onRemove(); + } } listImages(): Array { @@ -115,14 +139,21 @@ class ImageManager { const response = {}; for (const id of ids) { + if (!this.images[id]) { + this.fire(new Event('styleimagemissing', { id })); + } const image = this.images[id]; if (image) { // Clone the image so that our own copy of its ArrayBuffer doesn't get transferred. response[id] = { data: image.data.clone(), pixelRatio: image.pixelRatio, - sdf: image.sdf + sdf: image.sdf, + version: image.version, + hasRenderCallback: Boolean(image.userImage && image.userImage.render) }; + } else { + warnOnce(`Image "${id}" could not be loaded. Please make sure you have added the image with map.addImage() or a "sprite" property in your style. You can provide missing images by listening for the "styleimagemissing" map event.`); } } @@ -138,23 +169,29 @@ class ImageManager { getPattern(id: string): ?ImagePosition { const pattern = this.patterns[id]; - if (pattern) { - return pattern.position; - } const image = this.getImage(id); if (!image) { return null; } - const w = image.data.width + padding * 2; - const h = image.data.height + padding * 2; - const bin = {w, h, x: 0, y: 0}; - const position = new ImagePosition(bin, image); - this.patterns[id] = {bin, position}; + if (pattern && pattern.position.version === image.version) { + return pattern.position; + } + + if (!pattern) { + const w = image.data.width + padding * 2; + const h = image.data.height + padding * 2; + const bin = {w, h, x: 0, y: 0}; + const position = new ImagePosition(bin, image); + this.patterns[id] = {bin, position}; + } else { + pattern.position.version = image.version; + } + this._updatePatternAtlas(); - return position; + return this.patterns[id].position; } bind(context: Context) { @@ -199,6 +236,27 @@ class ImageManager { this.dirty = true; } + + beginFrame() { + this.callbackDispatchedThisFrame = {}; + } + + dispatchRenderCallbacks(ids: Array) { + for (const id of ids) { + + // the callback for the image was already dispatched for a different frame + if (this.callbackDispatchedThisFrame[id]) continue; + this.callbackDispatchedThisFrame[id] = true; + + const image = this.images[id]; + assert(image); + + const updated = renderStyleImage(image); + if (updated) { + this.updateImage(id, image); + } + } + } } export default ImageManager; diff --git a/src/render/offscreen.js b/src/render/offscreen.js deleted file mode 100644 index 30e7bb1ec64..00000000000 --- a/src/render/offscreen.js +++ /dev/null @@ -1,64 +0,0 @@ -// @flow - -import Texture from './texture'; -import Color from '../style-spec/util/color'; -import DepthMode from '../gl/depth_mode'; -import StencilMode from '../gl/stencil_mode'; -import CullFaceMode from '../gl/cull_face_mode'; -import {extrusionTextureUniformValues} from './program/fill_extrusion_program'; - -import type Painter from './painter'; -import type CustomStyleLayer from '../style/style_layer/custom_style_layer'; -import type FillExtrusionStyleLayer from '../style/style_layer/fill_extrusion_style_layer'; - -export function prepareOffscreenFramebuffer(painter: Painter, layer: CustomStyleLayer | FillExtrusionStyleLayer) { - const context = painter.context; - const gl = context.gl; - - let renderTarget = layer.viewportFrame; - - if (painter.depthRboNeedsClear) { - painter.setupOffscreenDepthRenderbuffer(); - } - - if (!renderTarget) { - const texture = new Texture(context, {width: painter.width, height: painter.height, data: null}, gl.RGBA); - texture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE); - - renderTarget = layer.viewportFrame = context.createFramebuffer(painter.width, painter.height); - renderTarget.colorAttachment.set(texture.texture); - } - - context.bindFramebuffer.set(renderTarget.framebuffer); - renderTarget.depthAttachment.set(painter.depthRbo); - - if (painter.depthRboNeedsClear) { - context.clear({ depth: 1 }); - painter.depthRboNeedsClear = false; - } - - context.clear({ color: Color.transparent }); - - context.setStencilMode(StencilMode.disabled); - context.setDepthMode(new DepthMode(gl.LEQUAL, DepthMode.ReadWrite, [0, 1])); - context.setColorMode(painter.colorModeForRenderPass()); -} - -export function drawOffscreenTexture(painter: Painter, layer: CustomStyleLayer | FillExtrusionStyleLayer, opacity: number) { - const renderedTexture = layer.viewportFrame; - if (!renderedTexture) return; - - const context = painter.context; - const gl = context.gl; - - context.activeTexture.set(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, renderedTexture.colorAttachment.get()); - - painter.useProgram('extrusionTexture').draw(context, gl.TRIANGLES, - DepthMode.disabled, StencilMode.disabled, - painter.colorModeForRenderPass(), - CullFaceMode.disabled, - extrusionTextureUniformValues(painter, opacity, 0), - layer.id, painter.viewportBuffer, painter.quadTriangleIndexBuffer, - painter.viewportSegments, layer.paint, painter.transform.zoom); -} diff --git a/src/render/painter.js b/src/render/painter.js index 2008c49e36c..6f749086f25 100644 --- a/src/render/painter.js +++ b/src/render/painter.js @@ -61,7 +61,7 @@ import type ImageManager from './image_manager'; import type GlyphManager from './glyph_manager'; import type VertexBuffer from '../gl/vertex_buffer'; import type IndexBuffer from '../gl/index_buffer'; -import type {DepthMaskType, DepthFuncType} from '../gl/types'; +import type {DepthRangeType, DepthMaskType, DepthFuncType} from '../gl/types'; export type RenderPass = 'offscreen' | 'opaque' | 'translucent'; @@ -108,9 +108,12 @@ class Painter { lineAtlas: LineAtlas; imageManager: ImageManager; glyphManager: GlyphManager; - depthRange: number; + depthRangeFor3D: DepthRangeType; + opaquePassCutoff: number; renderPass: RenderPass; currentLayer: number; + currentStencilSource: ?string; + nextStencilID: number; id: string; _showOverdrawInspector: boolean; cache: { [string]: Program<*> }; @@ -219,6 +222,9 @@ class Painter { const context = this.context; const gl = context.gl; + this.nextStencilID = 1; + this.currentStencilSource = undefined; + // As a temporary workaround for https://github.com/mapbox/mapbox-gl-js/issues/5490, // pending an upstream fix, we draw a fullscreen stencil=0 clipping mask here, // effectively clearing the stencil buffer: once an upstream patch lands, remove @@ -235,20 +241,28 @@ class Painter { this.quadTriangleIndexBuffer, this.viewportSegments); } - _renderTileClippingMasks(tileIDs: Array) { + _renderTileClippingMasks(layer: StyleLayer, tileIDs: Array) { + if (this.currentStencilSource === layer.source || !layer.isTileClipped() || !tileIDs || !tileIDs.length) return; + + this.currentStencilSource = layer.source; + const context = this.context; const gl = context.gl; + if (this.nextStencilID + tileIDs.length > 256) { + // we'll run out of fresh IDs so we need to clear and start from scratch + this.clearStencil(); + } + context.setColorMode(ColorMode.disabled); context.setDepthMode(DepthMode.disabled); const program = this.useProgram('clippingMask'); - let idNext = 1; this._tileClippingMaskIDs = {}; for (const tileID of tileIDs) { - const id = this._tileClippingMaskIDs[tileID.key] = idNext++; + const id = this._tileClippingMaskIDs[tileID.key] = this.nextStencilID++; program.draw(context, gl.TRIANGLES, DepthMode.disabled, // Tests will always pass, and ref value will be written to stencil buffer. @@ -259,6 +273,16 @@ class Painter { } } + stencilModeFor3D(): StencilMode { + if (this.nextStencilID + 1 > 256) { + this.clearStencil(); + } + + const id = this.nextStencilID++; + const gl = this.context.gl; + return new StencilMode({ func: gl.NOTEQUAL, mask: 0xFF }, id, 0xFF, gl.KEEP, gl.KEEP, gl.REPLACE); + } + stencilModeForClipping(tileID: OverscaledTileID): StencilMode { const gl = this.context.gl; return new StencilMode({ func: gl.EQUAL, mask: 0xFF }, this._tileClippingMaskIDs[tileID.key], 0x00, gl.KEEP, gl.KEEP, gl.REPLACE); @@ -278,11 +302,23 @@ class Painter { } } - depthModeForSublayer(n: number, mask: DepthMaskType, func: ?DepthFuncType): DepthMode { + depthModeForSublayer(n: number, mask: DepthMaskType, func: ?DepthFuncType): $ReadOnly { + if (!this.opaquePassEnabledForLayer()) return DepthMode.disabled; const depth = 1 - ((1 + this.currentLayer) * this.numSublayers + n) * this.depthEpsilon; return new DepthMode(func || this.context.gl.LEQUAL, mask, [depth, depth]); } + /* + * The opaque pass and 3D layers both use the depth buffer. + * Layers drawn above 3D layers need to be drawn using the + * painter's algorithm so that they appear above 3D features. + * This returns true for layers that can be drawn using the + * opaque pass. + */ + opaquePassEnabledForLayer() { + return this.currentLayer < this.opaquePassCutoff; + } + render(style: Style, options: PainterOptions) { this.style = style; this.options = options; @@ -293,6 +329,8 @@ class Painter { this.symbolFadeChange = style.placement.symbolFadeChange(browser.now()); + this.imageManager.beginFrame(); + const layerIds = this.style._order; const sourceCaches = this.style.sourceCaches; @@ -323,6 +361,15 @@ class Painter { updateTileMasks(visibleTiles, this.context); } + this.opaquePassCutoff = Infinity; + for (let i = 0; i < layerIds.length; i++) { + const layerId = layerIds[i]; + if (this.style._layers[layerId].is3D()) { + this.opaquePassCutoff = i; + break; + } + } + // Offscreen pass =============================================== // We first do all rendering that requires rendering to a separate // framebuffer, and then save those for rendering back to the map @@ -345,36 +392,29 @@ class Painter { // Clear buffers in preparation for drawing to the main framebuffer this.context.clear({ color: options.showOverdrawInspector ? Color.black : Color.transparent, depth: 1 }); + this.clearStencil(); this._showOverdrawInspector = options.showOverdrawInspector; - this.depthRange = (style._order.length + 2) * this.numSublayers * this.depthEpsilon; + this.depthRangeFor3D = [0, 1 - ((style._order.length + 2) * this.numSublayers * this.depthEpsilon)]; // Opaque pass =============================================== // Draw opaque layers top-to-bottom first. this.renderPass = 'opaque'; - let prevSourceId; for (this.currentLayer = layerIds.length - 1; this.currentLayer >= 0; this.currentLayer--) { const layer = this.style._layers[layerIds[this.currentLayer]]; const sourceCache = sourceCaches[layer.source]; const coords = coordsAscending[layer.source]; - if (layer.source !== prevSourceId && sourceCache) { - this.clearStencil(); - if (sourceCache.getSource().isTileClipped) { - this._renderTileClippingMasks(coords); - } - } - + this._renderTileClippingMasks(layer, coords); this.renderLayer(this, sourceCache, layer, coords); - prevSourceId = layer.source; } // Translucent pass =============================================== // Draw all other layers bottom-to-top. this.renderPass = 'translucent'; - for (this.currentLayer = 0, prevSourceId = null; this.currentLayer < layerIds.length; this.currentLayer++) { + for (this.currentLayer = 0; this.currentLayer < layerIds.length; this.currentLayer++) { const layer = this.style._layers[layerIds[this.currentLayer]]; const sourceCache = sourceCaches[layer.source]; @@ -383,15 +423,8 @@ class Painter { // separate clipping masks const coords = (layer.type === 'symbol' ? coordsDescendingSymbol : coordsDescending)[layer.source]; - if (layer.source !== prevSourceId && sourceCache) { - this.clearStencil(); - if (sourceCache.getSource().isTileClipped) { - this._renderTileClippingMasks(coordsAscending[layer.source]); - } - } - + this._renderTileClippingMasks(layer, coordsAscending[layer.source]); this.renderLayer(this, sourceCache, layer, coords); - prevSourceId = layer.source; } if (this.options.showTileBoundaries) { @@ -417,7 +450,7 @@ class Painter { if (layer.type !== 'background' && layer.type !== 'custom' && !coords.length) return; this.id = layer.id; - draw[layer.type](painter, sourceCache, layer, coords); + draw[layer.type](painter, sourceCache, layer, coords, this.style.placement.variableOffsets); } /** diff --git a/src/render/program.js b/src/render/program.js index 6f9960454b3..398eb6111c2 100644 --- a/src/render/program.js +++ b/src/render/program.js @@ -16,6 +16,7 @@ import type StencilMode from '../gl/stencil_mode'; import type ColorMode from '../gl/color_mode'; import type CullFaceMode from '../gl/cull_face_mode'; import type {UniformBindings, UniformValues, UniformLocations} from './uniform_binding'; +import type {BinderUniform} from '../data/program_configuration'; export type DrawMode = | $PropertyType @@ -27,7 +28,7 @@ class Program { attributes: {[string]: number}; numAttributes: number; fixedUniforms: Us; - binderUniforms: UniformBindings; + binderUniforms: Array; constructor(context: Context, source: {fragmentSource: string, vertexSource: string}, diff --git a/src/render/program/fill_extrusion_program.js b/src/render/program/fill_extrusion_program.js index 080420a9b37..dbf4a680d7a 100644 --- a/src/render/program/fill_extrusion_program.js +++ b/src/render/program/fill_extrusion_program.js @@ -10,7 +10,7 @@ import { UniformMatrix4f } from '../uniform_binding'; -import {mat3, vec3, mat4} from 'gl-matrix'; +import {mat3, vec3} from 'gl-matrix'; import { extend } from '../../util/util'; import type Context from '../../gl/context'; @@ -25,7 +25,8 @@ export type FillExtrusionUniformsType = {| 'u_lightpos': Uniform3f, 'u_lightintensity': Uniform1f, 'u_lightcolor': Uniform3f, - 'u_vertical_gradient': Uniform1f + 'u_vertical_gradient': Uniform1f, + 'u_opacity': Uniform1f |}; export type FillExtrusionPatternUniformsType = {| @@ -41,13 +42,7 @@ export type FillExtrusionPatternUniformsType = {| 'u_pixel_coord_upper': Uniform2f, 'u_pixel_coord_lower': Uniform2f, 'u_scale': Uniform4f, - 'u_fade': Uniform1f -|}; - -export type ExtrusionTextureUniformsType = {| - 'u_matrix': UniformMatrix4f, - 'u_world': Uniform2f, - 'u_image': Uniform1i, + 'u_fade': Uniform1f, 'u_opacity': Uniform1f |}; @@ -56,7 +51,8 @@ const fillExtrusionUniforms = (context: Context, locations: UniformLocations): F 'u_lightpos': new Uniform3f(context, locations.u_lightpos), 'u_lightintensity': new Uniform1f(context, locations.u_lightintensity), 'u_lightcolor': new Uniform3f(context, locations.u_lightcolor), - 'u_vertical_gradient': new Uniform1f(context, locations.u_vertical_gradient) + 'u_vertical_gradient': new Uniform1f(context, locations.u_vertical_gradient), + 'u_opacity': new Uniform1f(context, locations.u_opacity) }); const fillExtrusionPatternUniforms = (context: Context, locations: UniformLocations): FillExtrusionPatternUniformsType => ({ @@ -72,20 +68,15 @@ const fillExtrusionPatternUniforms = (context: Context, locations: UniformLocati 'u_pixel_coord_upper': new Uniform2f(context, locations.u_pixel_coord_upper), 'u_pixel_coord_lower': new Uniform2f(context, locations.u_pixel_coord_lower), 'u_scale': new Uniform4f(context, locations.u_scale), - 'u_fade': new Uniform1f(context, locations.u_fade) -}); - -const extrusionTextureUniforms = (context: Context, locations: UniformLocations): ExtrusionTextureUniformsType => ({ - 'u_matrix': new UniformMatrix4f(context, locations.u_matrix), - 'u_world': new Uniform2f(context, locations.u_world), - 'u_image': new Uniform1i(context, locations.u_image), + 'u_fade': new Uniform1f(context, locations.u_fade), 'u_opacity': new Uniform1f(context, locations.u_opacity) }); const fillExtrusionUniformValues = ( matrix: Float32Array, painter: Painter, - shouldUseVerticalGradient: boolean + shouldUseVerticalGradient: boolean, + opacity: number ): UniformValues => { const light = painter.style.light; const _lp = light.properties.get('position'); @@ -103,7 +94,8 @@ const fillExtrusionUniformValues = ( 'u_lightpos': lightPos, 'u_lightintensity': light.properties.get('intensity'), 'u_lightcolor': [lightColor.r, lightColor.g, lightColor.b], - 'u_vertical_gradient': +shouldUseVerticalGradient + 'u_vertical_gradient': +shouldUseVerticalGradient, + 'u_opacity': opacity }; }; @@ -111,40 +103,21 @@ const fillExtrusionPatternUniformValues = ( matrix: Float32Array, painter: Painter, shouldUseVerticalGradient: boolean, + opacity: number, coord: OverscaledTileID, crossfade: CrossfadeParameters, tile: Tile ): UniformValues => { - return extend(fillExtrusionUniformValues(matrix, painter, shouldUseVerticalGradient), + return extend(fillExtrusionUniformValues(matrix, painter, shouldUseVerticalGradient, opacity), patternUniformValues(crossfade, painter, tile), { 'u_height_factor': -Math.pow(2, coord.overscaledZ) / tile.tileSize / 8 }); }; -const extrusionTextureUniformValues = ( - painter: Painter, - opacity: number, - textureUnit: number -): UniformValues => { - const matrix = mat4.create(); - mat4.ortho(matrix, 0, painter.width, painter.height, 0, 0, 1); - - const gl = painter.context.gl; - - return { - 'u_matrix': matrix, - 'u_world': [gl.drawingBufferWidth, gl.drawingBufferHeight], - 'u_image': textureUnit, - 'u_opacity': opacity - }; -}; - export { fillExtrusionUniforms, fillExtrusionPatternUniforms, - extrusionTextureUniforms, fillExtrusionUniformValues, - fillExtrusionPatternUniformValues, - extrusionTextureUniformValues + fillExtrusionPatternUniformValues }; diff --git a/src/render/program/program_uniforms.js b/src/render/program/program_uniforms.js index 5dbf64cef07..34fafaa4993 100644 --- a/src/render/program/program_uniforms.js +++ b/src/render/program/program_uniforms.js @@ -1,6 +1,6 @@ // @flow -import { fillExtrusionUniforms, fillExtrusionPatternUniforms, extrusionTextureUniforms } from './fill_extrusion_program'; +import { fillExtrusionUniforms, fillExtrusionPatternUniforms } from './fill_extrusion_program'; import { fillUniforms, fillPatternUniforms, fillOutlineUniforms, fillOutlinePatternUniforms } from './fill_program'; import { circleUniforms } from './circle_program'; import { collisionUniforms } from './collision_program'; @@ -16,7 +16,6 @@ import { backgroundUniforms, backgroundPatternUniforms } from './background_prog export const programUniforms = { fillExtrusion: fillExtrusionUniforms, fillExtrusionPattern: fillExtrusionPatternUniforms, - extrusionTexture: extrusionTextureUniforms, fill: fillUniforms, fillPattern: fillPatternUniforms, fillOutline: fillOutlineUniforms, diff --git a/src/render/texture.js b/src/render/texture.js index 160266fa442..ef71a1a519a 100644 --- a/src/render/texture.js +++ b/src/render/texture.js @@ -49,9 +49,9 @@ class Texture { this.update(image, options); } - update(image: TextureImage, options: ?{premultiply?: boolean, useMipmap?: boolean}) { + update(image: TextureImage, options: ?{premultiply?: boolean, useMipmap?: boolean}, position?: { x: number, y: number }) { const {width, height} = image; - const resize = !this.size || this.size[0] !== width || this.size[1] !== height; + const resize = (!this.size || this.size[0] !== width || this.size[1] !== height) && !position; const {context} = this; const {gl} = context; @@ -72,10 +72,11 @@ class Texture { } } else { + const {x, y} = position || { x: 0, y: 0}; if (image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof HTMLVideoElement || image instanceof ImageData) { - gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, image); + gl.texSubImage2D(gl.TEXTURE_2D, 0, x, y, gl.RGBA, gl.UNSIGNED_BYTE, image); } else { - gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, image.data); + gl.texSubImage2D(gl.TEXTURE_2D, 0, x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, image.data); } } diff --git a/src/shaders/README.md b/src/shaders/README.md index 266c8e987bc..3da88d3e7d1 100644 --- a/src/shaders/README.md +++ b/src/shaders/README.md @@ -37,6 +37,6 @@ When using pragmas, the following requirements apply. - `initialize` pragmas must be in function scope - all pragma-defined variables defined and initialized in the fragment shader must also be defined and initialized in the vertex shader because `attribute`s are not accessible from the fragment shader -## Util +## Prelude -The `util.glsl` file is automatically included in all shaders by the compiler. +The `_prelude.fragment.glsl` and `_prelude.vertex.glsl` files are automatically included in all shaders by the compiler. diff --git a/src/shaders/collision_box.vertex.glsl b/src/shaders/collision_box.vertex.glsl index 902efce076b..8fa4bfc025d 100644 --- a/src/shaders/collision_box.vertex.glsl +++ b/src/shaders/collision_box.vertex.glsl @@ -2,6 +2,7 @@ attribute vec2 a_pos; attribute vec2 a_anchor_pos; attribute vec2 a_extrude; attribute vec2 a_placed; +attribute vec2 a_shift; uniform mat4 u_matrix; uniform vec2 u_extrude_scale; @@ -19,7 +20,7 @@ void main() { 4.0); gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0); - gl_Position.xy += a_extrude * u_extrude_scale * gl_Position.w * collision_perspective_ratio; + gl_Position.xy += (a_extrude + a_shift) * u_extrude_scale * gl_Position.w * collision_perspective_ratio; v_placed = a_placed.x; v_notUsed = a_placed.y; diff --git a/src/shaders/extrusion_texture.fragment.glsl b/src/shaders/extrusion_texture.fragment.glsl deleted file mode 100644 index d857c50b894..00000000000 --- a/src/shaders/extrusion_texture.fragment.glsl +++ /dev/null @@ -1,11 +0,0 @@ -uniform sampler2D u_image; -uniform float u_opacity; -varying vec2 v_pos; - -void main() { - gl_FragColor = texture2D(u_image, v_pos) * u_opacity; - -#ifdef OVERDRAW_INSPECTOR - gl_FragColor = vec4(0.0); -#endif -} diff --git a/src/shaders/extrusion_texture.vertex.glsl b/src/shaders/extrusion_texture.vertex.glsl deleted file mode 100644 index 0e57d0faaf7..00000000000 --- a/src/shaders/extrusion_texture.vertex.glsl +++ /dev/null @@ -1,11 +0,0 @@ -uniform mat4 u_matrix; -uniform vec2 u_world; -attribute vec2 a_pos; -varying vec2 v_pos; - -void main() { - gl_Position = u_matrix * vec4(a_pos * u_world, 0, 1); - - v_pos.x = a_pos.x; - v_pos.y = 1.0 - a_pos.y; -} diff --git a/src/shaders/fill_extrusion.vertex.glsl b/src/shaders/fill_extrusion.vertex.glsl index df1b8556227..7a771b6dc97 100644 --- a/src/shaders/fill_extrusion.vertex.glsl +++ b/src/shaders/fill_extrusion.vertex.glsl @@ -3,6 +3,7 @@ uniform vec3 u_lightcolor; uniform lowp vec3 u_lightpos; uniform lowp float u_lightintensity; uniform float u_vertical_gradient; +uniform lowp float u_opacity; attribute vec2 a_pos; attribute vec4 a_normal_ed; @@ -61,4 +62,5 @@ void main() { v_color.r += clamp(color.r * directional * u_lightcolor.r, mix(0.0, 0.3, 1.0 - u_lightcolor.r), 1.0); v_color.g += clamp(color.g * directional * u_lightcolor.g, mix(0.0, 0.3, 1.0 - u_lightcolor.g), 1.0); v_color.b += clamp(color.b * directional * u_lightcolor.b, mix(0.0, 0.3, 1.0 - u_lightcolor.b), 1.0); + v_color *= u_opacity; } diff --git a/src/shaders/fill_extrusion_pattern.vertex.glsl b/src/shaders/fill_extrusion_pattern.vertex.glsl index 4c314f19bff..2761d56b6a9 100644 --- a/src/shaders/fill_extrusion_pattern.vertex.glsl +++ b/src/shaders/fill_extrusion_pattern.vertex.glsl @@ -4,6 +4,7 @@ uniform vec2 u_pixel_coord_lower; uniform float u_height_factor; uniform vec4 u_scale; uniform float u_vertical_gradient; +uniform lowp float u_opacity; uniform vec3 u_lightcolor; uniform lowp vec3 u_lightpos; @@ -71,4 +72,5 @@ void main() { } v_lighting.rgb += clamp(directional * u_lightcolor, mix(vec3(0.0), vec3(0.3), 1.0 - u_lightcolor), vec3(1.0)); + v_lighting *= u_opacity; } diff --git a/src/shaders/shaders.js b/src/shaders/shaders.js index 7c569fda562..85c9e058349 100644 --- a/src/shaders/shaders.js +++ b/src/shaders/shaders.js @@ -34,8 +34,6 @@ import fillExtrusionFrag from './fill_extrusion.fragment.glsl'; import fillExtrusionVert from './fill_extrusion.vertex.glsl'; import fillExtrusionPatternFrag from './fill_extrusion_pattern.fragment.glsl'; import fillExtrusionPatternVert from './fill_extrusion_pattern.vertex.glsl'; -import extrusionTextureFrag from './extrusion_texture.fragment.glsl'; -import extrusionTextureVert from './extrusion_texture.vertex.glsl'; import hillshadePrepareFrag from './hillshade_prepare.fragment.glsl'; import hillshadePrepareVert from './hillshade_prepare.vertex.glsl'; import hillshadeFrag from './hillshade.fragment.glsl'; @@ -71,7 +69,6 @@ export const fillOutlinePattern = compile(fillOutlinePatternFrag, fillOutlinePat export const fillPattern = compile(fillPatternFrag, fillPatternVert); export const fillExtrusion = compile(fillExtrusionFrag, fillExtrusionVert); export const fillExtrusionPattern = compile(fillExtrusionPatternFrag, fillExtrusionPatternVert); -export const extrusionTexture = compile(extrusionTextureFrag, extrusionTextureVert); export const hillshadePrepare = compile(hillshadePrepareFrag, hillshadePrepareVert); export const hillshade = compile(hillshadeFrag, hillshadeVert); export const line = compile(lineFrag, lineVert); diff --git a/src/source/canvas_source.js b/src/source/canvas_source.js index 0710c3c3864..f21785cb50a 100644 --- a/src/source/canvas_source.js +++ b/src/source/canvas_source.js @@ -130,7 +130,10 @@ class CanvasSource extends ImageSource { }; this.pause = function() { - this._playing = false; + if (this._playing) { + this.prepare(); + this._playing = false; + } }; this._finishLoading(); diff --git a/src/source/source_cache.js b/src/source/source_cache.js index 76a5cb2660d..b501eaa2d95 100644 --- a/src/source/source_cache.js +++ b/src/source/source_cache.js @@ -169,7 +169,9 @@ class SourceCache extends Evented { this._state.coalesceChanges(this._tiles, this.map ? this.map.painter : null); for (const i in this._tiles) { - this._tiles[i].upload(context); + const tile = this._tiles[i]; + tile.upload(context); + tile.prepare(this.map.style.imageManager); } } diff --git a/src/source/source_state.js b/src/source/source_state.js index 2881432c5a7..0ef77cfce65 100644 --- a/src/source/source_state.js +++ b/src/source/source_state.js @@ -123,8 +123,10 @@ class SourceFeatureState { const layerStates = {}; if (this.deletedStates[sourceLayer] === null) { - for (const ft in this.state[sourceLayer]) layerStates[ft] = {}; - this.state[sourceLayer] = {}; + for (const ft in this.state[sourceLayer]) { + layerStates[ft] = {}; + this.state[sourceLayer][ft] = {}; + } } else { for (const feature in this.deletedStates[sourceLayer]) { const deleteWholeFeatureState = this.deletedStates[sourceLayer][feature] === null; diff --git a/src/source/tile.js b/src/source/tile.js index c5e80a046b9..f04e3fb993b 100644 --- a/src/source/tile.js +++ b/src/source/tile.js @@ -25,6 +25,7 @@ import type {WorkerTileResult} from './worker_source'; import type DEMData from '../data/dem_data'; import type {AlphaImage} from '../util/image'; import type ImageAtlas from '../render/image_atlas'; +import type ImageManager from '../render/image_manager'; import type Mask from '../render/tile_mask'; import type Context from '../gl/context'; import type IndexBuffer from '../gl/index_buffer'; @@ -254,6 +255,12 @@ class Tile { } } + prepare(imageManager: ImageManager) { + if (this.imageAtlas) { + this.imageAtlas.patchUpdatedImages(imageManager, this.imageAtlasTexture); + } + } + // Queries non-symbol features rendered for this tile. // Symbol features are queried globally queryRenderedFeatures(layers: {[string]: StyleLayer}, diff --git a/src/style-spec/expression/definitions/coercion.js b/src/style-spec/expression/definitions/coercion.js index 03bd1afb923..d56bc3881b0 100644 --- a/src/style-spec/expression/definitions/coercion.js +++ b/src/style-spec/expression/definitions/coercion.js @@ -84,7 +84,7 @@ class Coercion implements Expression { } } } - throw new RuntimeError(error || `Could not parse color from value '${typeof input === 'string' ? input : JSON.stringify(input)}'`); + throw new RuntimeError(error || `Could not parse color from value '${typeof input === 'string' ? input : String(JSON.stringify(input))}'`); } else if (this.type.kind === 'number') { let value = null; for (const arg of this.args) { diff --git a/src/style-spec/feature_filter/README.md b/src/style-spec/feature_filter/README.md index 5faa93f2db2..6501c01a0f9 100644 --- a/src/style-spec/feature_filter/README.md +++ b/src/style-spec/feature_filter/README.md @@ -21,7 +21,7 @@ passes its test. ### Usage ``` javascript -var ff = require('feature-filter'); +var ff = require('@mapbox/mapbox-gl-style-spec').featureFilter; // will match a feature with class of street_limited, // AND an admin_level less than or equal to 3, diff --git a/src/style-spec/package.json b/src/style-spec/package.json index 37bf3e139f2..0323d6339b9 100644 --- a/src/style-spec/package.json +++ b/src/style-spec/package.json @@ -30,7 +30,7 @@ "@mapbox/jsonlint-lines-primitives": "~2.0.2", "@mapbox/unitbezier": "^0.0.0", "csscolorparser": "~1.0.2", - "json-stringify-pretty-compact": "^1.2.0", + "json-stringify-pretty-compact": "^2.0.0", "minimist": "0.0.8", "rw": "^1.3.3", "sort-object": "^0.3.2" diff --git a/src/style-spec/reference/v8.json b/src/style-spec/reference/v8.json index ff1076b3c1a..cdd03c76393 100644 --- a/src/style-spec/reference/v8.json +++ b/src/style-spec/reference/v8.json @@ -964,7 +964,7 @@ }, "symbol-sort-key": { "type": "number", - "doc": "Sorts features in ascending order based on this value. Features with a higher sort key will appear above features with a lower sort key wehn they overlap. Features with a lower sort key will have priority over other features when doing placement.", + "doc": "Sorts features in ascending order based on this value. Features with a higher sort key will appear above features with a lower sort key when they overlap. Features with a lower sort key will have priority over other features when doing placement.", "sdk-support": { "js": "0.53.0" }, @@ -1748,6 +1748,9 @@ "text-justify": { "type": "enum", "values": { + "auto": { + "doc": "The text is aligned towards the anchor position." + }, "left": { "doc": "The text is aligned to the left." }, @@ -1775,6 +1778,12 @@ "android": "5.2.0", "ios": "3.7.0", "macos": "0.6.0" + }, + "auto": { + "js": "next", + "android": "Not yet supported", + "ios": "Not yet supported", + "macos": "Not yet supported" } }, "expression": { @@ -1786,8 +1795,98 @@ }, "property-type": "data-driven" }, + "text-radial-offset": { + "type": "number", + "units": "ems", + "default": 0, + "doc": "Radial offset of text, in the direction of the symbol's anchor. Useful in combination with `text-variable-anchor`, which doesn't support the two-dimensional `text-offset`.", + "requires": [ + { + "!" : "text-offset" + } + ], + "property-type": "data-driven", + "expression": { + "interpolated": true, + "parameters": [ + "zoom", + "feature" + ] + } + }, + "text-variable-anchor": { + "type": "array", + "value": "enum", + "values": { + "center": { + "doc": "The center of the text is placed closest to the anchor." + }, + "left": { + "doc": "The left side of the text is placed closest to the anchor." + }, + "right": { + "doc": "The right side of the text is placed closest to the anchor." + }, + "top": { + "doc": "The top of the text is placed closest to the anchor." + }, + "bottom": { + "doc": "The bottom of the text is placed closest to the anchor." + }, + "top-left": { + "doc": "The top left corner of the text is placed closest to the anchor." + }, + "top-right": { + "doc": "The top right corner of the text is placed closest to the anchor." + }, + "bottom-left": { + "doc": "The bottom left corner of the text is placed closest to the anchor." + }, + "bottom-right": { + "doc": "The bottom right corner of the text is placed closest to the anchor." + } + }, + "requires": [ + { + "!": "text-anchor" + }, + { + "!": "text-offset" + }, + { + "symbol-placement": [ + "point" + ] + } + ], + "doc": "To increase the chance of placing high-priority labels on the map, you can provide an array of `text-anchor` locations: the render will attempt to place the label at each location, in order, before moving onto the next label. Use `text-justify: auto` to choose justification based on anchor position. To apply an offset, use the `text-radial-offset` instead of the two-dimensional `text-offset`.", + "sdk-support": { + "basic functionality": { + "js": "next", + "android": "Not yet supported", + "ios": "Not yet supported", + "macos": "Not yet supported" + }, + "data-driven styling": { + "js": "Not yet supported", + "android": "Not yet supported", + "ios": "Not yet supported", + "macos": "Not yet supported" + } + }, + "expression": { + "interpolated": false, + "parameters": [ + "zoom" + ] + }, + "property-type": "data-constant" + }, "text-anchor": { "type": "enum", + "requires": { + "!": "text-variable-anchor" + }, "values": { "center": { "doc": "The center of the text is placed closest to the anchor." @@ -2019,7 +2118,10 @@ 0 ], "requires": [ - "text-field" + "text-field", + { + "!": "text-radial-offset" + } ], "sdk-support": { "basic functionality": { diff --git a/src/style-spec/types.js b/src/style-spec/types.js index 4b0ddc77395..64ce4049ee4 100644 --- a/src/style-spec/types.js +++ b/src/style-spec/types.js @@ -237,7 +237,9 @@ export type SymbolLayerSpecification = {| "text-max-width"?: DataDrivenPropertyValueSpecification, "text-line-height"?: PropertyValueSpecification, "text-letter-spacing"?: DataDrivenPropertyValueSpecification, - "text-justify"?: DataDrivenPropertyValueSpecification<"left" | "center" | "right">, + "text-justify"?: DataDrivenPropertyValueSpecification<"auto" | "left" | "center" | "right">, + "text-radial-offset"?: DataDrivenPropertyValueSpecification, + "text-variable-anchor"?: PropertyValueSpecification>, "text-anchor"?: DataDrivenPropertyValueSpecification<"center" | "left" | "right" | "top" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right">, "text-max-angle"?: PropertyValueSpecification, "text-rotate"?: DataDrivenPropertyValueSpecification, diff --git a/src/style-spec/validate/validate_array.js b/src/style-spec/validate/validate_array.js index 10829d6f2bf..2f5638a61ac 100644 --- a/src/style-spec/validate/validate_array.js +++ b/src/style-spec/validate/validate_array.js @@ -24,7 +24,8 @@ export default function validateArray(options) { } let arrayElementSpec = { - "type": arraySpec.value + "type": arraySpec.value, + "values": arraySpec.values }; if (styleSpec.$version < 7) { diff --git a/src/style/pauseable_placement.js b/src/style/pauseable_placement.js index 2417e19c7c6..713a024173f 100644 --- a/src/style/pauseable_placement.js +++ b/src/style/pauseable_placement.js @@ -43,9 +43,10 @@ class PauseablePlacement { forceFullPlacement: boolean, showCollisionBoxes: boolean, fadeDuration: number, - crossSourceCollisions: boolean) { + crossSourceCollisions: boolean, + prevPlacement?: Placement) { - this.placement = new Placement(transform, fadeDuration, crossSourceCollisions); + this.placement = new Placement(transform, fadeDuration, crossSourceCollisions, prevPlacement); this._currentPlacementIndex = order.length - 1; this._forceFullPlacement = forceFullPlacement; this._showCollisionBoxes = showCollisionBoxes; @@ -94,8 +95,8 @@ class PauseablePlacement { this._done = true; } - commit(previousPlacement: ?Placement, now: number) { - this.placement.commit(previousPlacement, now); + commit(now: number) { + this.placement.commit(now); return this.placement; } } diff --git a/src/style/style.js b/src/style/style.js index a71f4e9c9f0..45417adefce 100644 --- a/src/style/style.js +++ b/src/style/style.js @@ -136,6 +136,7 @@ class Style extends Evented { this.map = map; this.dispatcher = new Dispatcher(getWorkerPool(), this); this.imageManager = new ImageManager(); + this.imageManager.setEventedParent(this); this.glyphManager = new GlyphManager(map._transformRequest, options.localIdeographFontFamily); this.lineAtlas = new LineAtlas(256, 512); this.crossTileSymbolIndex = new CrossTileSymbolIndex(); @@ -465,6 +466,10 @@ class Style extends Evented { this.fire(new Event('data', {dataType: 'style'})); } + updateImage(id: string, image: StyleImage) { + this.imageManager.updateImage(id, image); + } + getImage(id: string): ?StyleImage { return this.imageManager.getImage(id); } @@ -873,12 +878,12 @@ class Style extends Evented { return; } - if (target.id && isNaN(featureId) || featureId < 0) { + if (target.id !== undefined && isNaN(featureId) || featureId < 0) { this.fire(new ErrorEvent(new Error(`The feature id parameter must be non-negative.`))); return; } - if (key && !target.id) { + if (key && (typeof target.id !== 'string' && typeof target.id !== 'number')) { this.fire(new ErrorEvent(new Error(`A feature id is requred to remove its specific state property.`))); return; } @@ -1196,7 +1201,7 @@ class Style extends Evented { const forceFullPlacement = this._layerOrderChanged || fadeDuration === 0; if (forceFullPlacement || !this.pauseablePlacement || (this.pauseablePlacement.isDone() && !this.placement.stillRecent(browser.now()))) { - this.pauseablePlacement = new PauseablePlacement(transform, this._order, forceFullPlacement, showCollisionBoxes, fadeDuration, crossSourceCollisions); + this.pauseablePlacement = new PauseablePlacement(transform, this._order, forceFullPlacement, showCollisionBoxes, fadeDuration, crossSourceCollisions, this.placement); this._layerOrderChanged = false; } @@ -1210,7 +1215,7 @@ class Style extends Evented { this.pauseablePlacement.continuePlacement(this._order, this._layers, layerTiles); if (this.pauseablePlacement.isDone()) { - this.placement = this.pauseablePlacement.commit(this.placement, browser.now()); + this.placement = this.pauseablePlacement.commit(browser.now()); placementCommitted = true; } diff --git a/src/style/style_image.js b/src/style/style_image.js index 90e8b6317e1..fdb62515301 100644 --- a/src/style/style_image.js +++ b/src/style/style_image.js @@ -1,9 +1,129 @@ // @flow -import type {RGBAImage} from '../util/image'; +import {RGBAImage} from '../util/image'; + +import type Map from '../ui/map'; export type StyleImage = { data: RGBAImage, pixelRatio: number, - sdf: boolean + sdf: boolean, + version: number, + hasRenderCallback?: boolean, + userImage?: StyleImageInterface +}; + +export type StyleImageInterface = { + width: number, + height: number, + data: Uint8Array | Uint8ClampedArray, + render?: () => void, + onAdd?: (map: Map, id: string) => void, + onRemove?: () => void }; + +export function renderStyleImage(image: StyleImage) { + const {userImage} = image; + if (userImage && userImage.render) { + const updated = userImage.render(); + if (updated) { + image.data.replace(new Uint8Array(userImage.data.buffer)); + return true; + } + } + return false; +} + +/** + * Interface for dynamically generated style images. This is a specification for + * implementers to model: it is not an exported method or class. + * + * Images implementing this interface can be redrawn for every frame. They can be used to animate + * icons and patterns or make them respond to user input. Style images can implement a + * {@link StyleImageInterface#render} method. The method is called every frame and + * can be used to update the image. + * + * @interface StyleImageInterface + * @property {number} width + * @property {number} height + * @property {Uint8Array | Uint8ClampedArray} data + * + * @see [Add an animated icon to the map.](https://docs.mapbox.com/mapbox-gl-js/example/add-image-animated/) + * + * @example + * var flashingSquare = { + * width: 64, + * height: 64, + * data: new Uint8Array(64 * 64 * 4), + * + * onAdd: function(map) { + * this.map = map; + * }, + * + * render: function() { + * // keep repainting while the icon is on the map + * this.map.triggerRepaint(); + * + * // alternate between black and white based on the time + * var value = Math.round(Date.now() / 1000) % 2 === 0 ? 255 : 0; + * + * // check if image needs to be changed + * if (value !== this.previousValue) { + * this.previousValue = value; + * + * var bytesPerPixel = 4; + * for (var x = 0; x < this.width; x++) { + * for (var y = 0; y < this.height; y++) { + * var offset = (y * this.width + x) * bytesPerPixel; + * this.data[offset + 0] = value; + * this.data[offset + 1] = value; + * this.data[offset + 2] = value; + * this.data[offset + 3] = 255; + * } + * } + * + * // return true to indicate that the image changed + * return true; + * } + * } + * } + * + * map.addImage('flashing_square', flashingSquare); + */ + +/** + * This method is called once before every frame where the icon will be used. + * The method can optionally update the image's `data` member with a new image. + * + * If the method updates the image it must return `true` to commit the change. + * If the method returns `false` or nothing the image is assumed to not have changed. + * + * If updates are infrequent it maybe easier to use {@link Map#updateImage} to update + * the image instead of implementing this method. + * + * @function + * @memberof StyleImageInterface + * @instance + * @name render + * @return {boolean} `true` if this method updated the image. `false` if the image was not changed. + */ + +/** + * Optional method called when the layer has been added to the Map with {@link Map#addImage}. + * + * @function + * @memberof StyleImageInterface + * @instance + * @name onAdd + * @param {Map} map The Map this custom layer was just added to. + */ + +/** + * Optional method called when the icon is removed from the map with {@link Map#removeImage}. + * This gives the image a chance to clean up resources and event listeners. + * + * @function + * @memberof StyleImageInterface + * @instance + * @name onRemove + */ diff --git a/src/style/style_layer.js b/src/style/style_layer.js index 131f055aedf..9cfd91bd62f 100644 --- a/src/style/style_layer.js +++ b/src/style/style_layer.js @@ -39,7 +39,7 @@ class StyleLayer extends Evented { minzoom: ?number; maxzoom: ?number; filter: FilterSpecification | void; - visibility: 'visible' | 'none'; + visibility: 'visible' | 'none' | void; _crossfadeParameters: CrossfadeParameters; _unevaluatedLayout: Layout; @@ -69,7 +69,6 @@ class StyleLayer extends Evented { this.id = layer.id; this.type = layer.type; - this.visibility = 'visible'; this._featureFilter = () => true; if (layer.type === 'custom') return; @@ -116,7 +115,7 @@ class StyleLayer extends Evented { return this._unevaluatedLayout.getValue(name); } - setLayoutProperty(name: string, value: mixed, options: StyleSetterOptions = {}) { + setLayoutProperty(name: string, value: any, options: StyleSetterOptions = {}) { if (value !== null && value !== undefined) { const key = `layers.${this.id}.layout.${name}`; if (this._validate(validateLayoutProperty, key, name, value, options)) { @@ -125,7 +124,7 @@ class StyleLayer extends Evented { } if (name === 'visibility') { - this.visibility = value === 'none' ? value : 'visible'; + this.visibility = value; return; } @@ -210,9 +209,9 @@ class StyleLayer extends Evented { 'paint': this._transitionablePaint && this._transitionablePaint.serialize() }; - if (this.visibility === 'none') { + if (this.visibility) { output.layout = output.layout || {}; - output.layout.visibility = 'none'; + output.layout.visibility = this.visibility; } return filterObject(output, (value, key) => { @@ -237,6 +236,14 @@ class StyleLayer extends Evented { })); } + is3D() { + return false; + } + + isTileClipped() { + return false; + } + hasOffscreenPass() { return false; } @@ -262,5 +269,3 @@ class StyleLayer extends Evented { } export default StyleLayer; - - diff --git a/src/style/style_layer/custom_style_layer.js b/src/style/style_layer/custom_style_layer.js index ebb88deedb5..3fea0df7e95 100644 --- a/src/style/style_layer/custom_style_layer.js +++ b/src/style/style_layer/custom_style_layer.js @@ -1,7 +1,6 @@ // @flow import StyleLayer from '../style_layer'; -import type Framebuffer from '../../gl/framebuffer'; import type Map from '../../ui/map'; import assert from 'assert'; @@ -21,6 +20,11 @@ type CustomRenderMethod = (gl: WebGLRenderingContext, matrix: Array) => * and they should appropriately handle {@link Map.event:webglcontextlost} and * {@link Map.event:webglcontextrestored}. * + * The `renderingMode` property controls whether the layer is treated as a `"2d"` or `"3d"` map layer. Use: + * - `"renderingMode": "3d"` to use the depth buffer and share it with other layers + * - `"renderingMode": "2d"` to add a layer with no depth. If you need to use the depth buffer for a `"2d"` layer you must use an offscreen + * framebuffer and {@link CustomLayerInterface#prerender} + * * @interface CustomLayerInterface * @property {string} id A unique layer id. * @property {string} type The layer's type. Must be `"custom"`. @@ -123,6 +127,12 @@ type CustomRenderMethod = (gl: WebGLRenderingContext, matrix: Array) => * If the layer needs to render to a texture, it should implement the `prerender` method * to do this and only use the `render` method for drawing directly into the main framebuffer. * + * The blend function is set to `gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)`. This expects + * colors to be provided in premultiplied alpha form where the `r`, `g` and `b` values are already + * multiplied by the `a` value. If you are unable to provide colors in premultiplied form you + * may want to change the blend function to + * `gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA)`. + * * @function * @memberof CustomLayerInterface * @instance @@ -175,16 +185,18 @@ export function validateCustomStyleLayer(layerObject: CustomLayerInterface) { class CustomStyleLayer extends StyleLayer { implementation: CustomLayerInterface; - viewportFrame: ?Framebuffer; constructor(implementation: CustomLayerInterface) { super(implementation, {}); this.implementation = implementation; } + is3D() { + return this.implementation.renderingMode === '3d'; + } hasOffscreenPass() { - return this.implementation.prerender !== undefined || this.implementation.renderingMode === '3d'; + return this.implementation.prerender !== undefined; } recalculate() {} @@ -195,13 +207,6 @@ class CustomStyleLayer extends StyleLayer { assert(false, "Custom layers cannot be serialized"); } - resize() { - if (this.viewportFrame) { - this.viewportFrame.destroy(); - this.viewportFrame = null; - } - } - onAdd(map: Map) { if (this.implementation.onAdd) { this.implementation.onAdd(map, map.painter.context.gl); diff --git a/src/style/style_layer/fill_extrusion_style_layer.js b/src/style/style_layer/fill_extrusion_style_layer.js index 1bfb784d641..9e90893e7b3 100644 --- a/src/style/style_layer/fill_extrusion_style_layer.js +++ b/src/style/style_layer/fill_extrusion_style_layer.js @@ -13,7 +13,6 @@ import Point from '@mapbox/point-geometry'; import type { FeatureState } from '../../style-spec/expression'; import type {BucketParameters} from '../../data/bucket'; import type {PaintProps} from './fill_extrusion_style_layer_properties'; -import type Framebuffer from '../../gl/framebuffer'; import type Transform from '../../geo/transform'; import type {LayerSpecification} from '../../style-spec/types'; @@ -21,7 +20,6 @@ class FillExtrusionStyleLayer extends StyleLayer { _transitionablePaint: Transitionable; _transitioningPaint: Transitioning; paint: PossiblyEvaluated; - viewportFrame: ?Framebuffer; constructor(layer: LayerSpecification) { super(layer, properties); @@ -35,6 +33,10 @@ class FillExtrusionStyleLayer extends StyleLayer { return translateDistance(this.paint.get('fill-extrusion-translate')); } + is3D(): boolean { + return true; + } + queryIntersectsFeature(queryGeometry: Array, feature: VectorTileFeature, featureState: FeatureState, @@ -59,17 +61,6 @@ class FillExtrusionStyleLayer extends StyleLayer { const projectedTop = projected[1]; return checkIntersection(projectedBase, projectedTop, projectedQueryGeometry); } - - hasOffscreenPass() { - return this.paint.get('fill-extrusion-opacity') !== 0 && this.visibility !== 'none'; - } - - resize() { - if (this.viewportFrame) { - this.viewportFrame.destroy(); - this.viewportFrame = null; - } - } } function dot(a, b) { diff --git a/src/style/style_layer/fill_style_layer.js b/src/style/style_layer/fill_style_layer.js index 9d46e9cad1b..c7a555676d5 100644 --- a/src/style/style_layer/fill_style_layer.js +++ b/src/style/style_layer/fill_style_layer.js @@ -55,6 +55,10 @@ class FillStyleLayer extends StyleLayer { transform.angle, pixelsToTileUnits); return polygonIntersectsMultiPolygon(translatedPolygon, geometry); } + + isTileClipped() { + return true; + } } export default FillStyleLayer; diff --git a/src/style/style_layer/line_style_layer.js b/src/style/style_layer/line_style_layer.js index 224836e4ebb..63ce50f1c4b 100644 --- a/src/style/style_layer/line_style_layer.js +++ b/src/style/style_layer/line_style_layer.js @@ -110,6 +110,10 @@ class LineStyleLayer extends StyleLayer { } return polygonIntersectsBufferedMultiLine(translatedPolygon, geometry, halfWidth); } + + isTileClipped() { + return true; + } } export default LineStyleLayer; diff --git a/src/style/style_layer/symbol_style_layer_properties.js b/src/style/style_layer/symbol_style_layer_properties.js index 90ced3407a3..d5cdeb55f4b 100644 --- a/src/style/style_layer/symbol_style_layer_properties.js +++ b/src/style/style_layer/symbol_style_layer_properties.js @@ -45,7 +45,9 @@ export type LayoutProps = {| "text-max-width": DataDrivenProperty, "text-line-height": DataConstantProperty, "text-letter-spacing": DataDrivenProperty, - "text-justify": DataDrivenProperty<"left" | "center" | "right">, + "text-justify": DataDrivenProperty<"auto" | "left" | "center" | "right">, + "text-radial-offset": DataDrivenProperty, + "text-variable-anchor": DataConstantProperty>, "text-anchor": DataDrivenProperty<"center" | "left" | "right" | "top" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right">, "text-max-angle": DataConstantProperty, "text-rotate": DataDrivenProperty, @@ -87,6 +89,8 @@ const layout: Properties = new Properties({ "text-line-height": new DataConstantProperty(styleSpec["layout_symbol"]["text-line-height"]), "text-letter-spacing": new DataDrivenProperty(styleSpec["layout_symbol"]["text-letter-spacing"]), "text-justify": new DataDrivenProperty(styleSpec["layout_symbol"]["text-justify"]), + "text-radial-offset": new DataDrivenProperty(styleSpec["layout_symbol"]["text-radial-offset"]), + "text-variable-anchor": new DataConstantProperty(styleSpec["layout_symbol"]["text-variable-anchor"]), "text-anchor": new DataDrivenProperty(styleSpec["layout_symbol"]["text-anchor"]), "text-max-angle": new DataConstantProperty(styleSpec["layout_symbol"]["text-max-angle"]), "text-rotate": new DataDrivenProperty(styleSpec["layout_symbol"]["text-rotate"]), diff --git a/src/symbol/one_em.js b/src/symbol/one_em.js new file mode 100644 index 00000000000..7e20115bd96 --- /dev/null +++ b/src/symbol/one_em.js @@ -0,0 +1,4 @@ +// @flow +// ONE_EM constant used to go between "em" units used in style spec and "points" used internally for layout + +export default 24; diff --git a/src/symbol/placement.js b/src/symbol/placement.js index eb877898113..482f25ca1d0 100644 --- a/src/symbol/placement.js +++ b/src/symbol/placement.js @@ -1,22 +1,25 @@ // @flow import CollisionIndex from './collision_index'; - import EXTENT from '../data/extent'; import * as symbolSize from './symbol_size'; import * as projection from './projection'; +import { getAnchorJustification, evaluateRadialOffset } from './symbol_layout'; +import { getAnchorAlignment } from './shaping'; import symbolLayerProperties from '../style/style_layer/symbol_style_layer_properties'; import assert from 'assert'; import pixelsToTileUnits from '../source/pixels_to_tile_units'; - +import Point from '@mapbox/point-geometry'; import type Transform from '../geo/transform'; import type StyleLayer from '../style/style_layer'; + import type Tile from '../source/tile'; -import type SymbolBucket from '../data/bucket/symbol_bucket'; +import type SymbolBucket, { SingleCollisionBox } from '../data/bucket/symbol_bucket'; import type {mat4} from 'gl-matrix'; -import type {CollisionBoxArray, CollisionVertexArray} from '../data/array_types'; +import type {CollisionBoxArray, CollisionVertexArray, SymbolInstance} from '../data/array_types'; import type FeatureIndex from '../data/feature_index'; import type {OverscaledTileID} from '../source/tile_id'; +import type {TextAnchor} from './symbol_layout'; class OpacityState { opacity: number; @@ -81,8 +84,10 @@ export class RetainedQueryData { } } +type CollisionGroup = { ID: number, predicate?: any }; + class CollisionGroups { - collisionGroups: { [groupName: string]: { ID: number, predicate?: any }}; + collisionGroups: {[groupName: string]: CollisionGroup}; maxGroupID: number; crossSourceCollisions: boolean; @@ -114,28 +119,78 @@ class CollisionGroups { } +function calculateVariableLayoutOffset(anchor: TextAnchor, width: number, height: number, radialOffset: number, textBoxScale: number): Point { + const {horizontalAlign, verticalAlign} = getAnchorAlignment(anchor); + const shiftX = -(horizontalAlign - 0.5) * width; + const shiftY = -(verticalAlign - 0.5) * height; + const offset = evaluateRadialOffset(anchor, radialOffset); + return new Point( + shiftX + offset[0] * textBoxScale, + shiftY + offset[1] * textBoxScale + ); +} + +function shiftVariableCollisionBox(collisionBox: SingleCollisionBox, + shiftX: number, shiftY: number, + rotateWithMap: boolean, pitchWithMap: boolean, + angle: number) { + const {x1, x2, y1, y2, anchorPointX, anchorPointY} = collisionBox; + const rotatedOffset = new Point(shiftX, shiftY); + if (rotateWithMap) { + rotatedOffset._rotate(pitchWithMap ? angle : -angle); + } + return { + x1: x1 + rotatedOffset.x, + y1: y1 + rotatedOffset.y, + x2: x2 + rotatedOffset.x, + y2: y2 + rotatedOffset.y, + // symbol anchor point stays the same regardless of text-anchor + anchorPointX, + anchorPointY + }; +} + +export type VariableOffset = { + radialOffset: number, + width: number, + height: number, + anchor: TextAnchor, + textBoxScale: number, + prevAnchor?: TextAnchor +}; + +export type CrossTileID = string | number; + export class Placement { transform: Transform; collisionIndex: CollisionIndex; - placements: { [string | number]: JointPlacement }; - opacities: { [string | number]: JointOpacityState }; + placements: { [CrossTileID]: JointPlacement }; + opacities: { [CrossTileID]: JointOpacityState }; + variableOffsets: {[CrossTileID]: VariableOffset }; commitTime: number; lastPlacementChangeTime: number; stale: boolean; fadeDuration: number; retainedQueryData: {[number]: RetainedQueryData}; collisionGroups: CollisionGroups; + prevPlacement: ?Placement; - constructor(transform: Transform, fadeDuration: number, crossSourceCollisions: boolean) { + constructor(transform: Transform, fadeDuration: number, crossSourceCollisions: boolean, prevPlacement?: Placement) { this.transform = transform.clone(); this.collisionIndex = new CollisionIndex(this.transform); this.placements = {}; this.opacities = {}; + this.variableOffsets = {}; this.stale = false; this.commitTime = 0; this.fadeDuration = fadeDuration; this.retainedQueryData = {}; this.collisionGroups = new CollisionGroups(crossSourceCollisions); + + this.prevPlacement = prevPlacement; + if (prevPlacement) { + prevPlacement.prevPlacement = undefined; // Only hold on to one placement back + } } placeLayerTile(styleLayer: StyleLayer, tile: Tile, showCollisionBoxes: boolean, seenCrossTileIDs: { [string | number]: boolean }) { @@ -174,21 +229,54 @@ export class Placement { symbolBucket.index, tile.tileID ); - this.placeLayerBucket(symbolBucket, posMatrix, textLabelPlaneMatrix, iconLabelPlaneMatrix, scale, textPixelRatio, showCollisionBoxes, tile.holdingForFade(), seenCrossTileIDs, collisionBoxArray); } + attemptAnchorPlacement(anchor: TextAnchor, textBox: SingleCollisionBox, width: number, height: number, + radialTextOffset: number, textBoxScale: number, rotateWithMap: boolean, + pitchWithMap: boolean, textPixelRatio: number, posMatrix: mat4, collisionGroup: CollisionGroup, + textAllowOverlap: boolean, symbolInstance: SymbolInstance, bucket: SymbolBucket) { + + const shift = calculateVariableLayoutOffset(anchor, width, height, radialTextOffset, textBoxScale); + + const placedGlyphBoxes = this.collisionIndex.placeCollisionBox( + shiftVariableCollisionBox( + textBox, shift.x, shift.y, + rotateWithMap, pitchWithMap, this.transform.angle), + textAllowOverlap, textPixelRatio, posMatrix, collisionGroup.predicate); + + if (placedGlyphBoxes.box.length > 0) { + let prevAnchor; + // If this label was placed in the previous placement, record the anchor position + // to allow us to animate the transition + if (this.prevPlacement && + this.prevPlacement.variableOffsets[symbolInstance.crossTileID] && + this.prevPlacement.placements[symbolInstance.crossTileID] && + this.prevPlacement.placements[symbolInstance.crossTileID].text) { + prevAnchor = this.prevPlacement.variableOffsets[symbolInstance.crossTileID].anchor; + } + assert(symbolInstance.crossTileID !== 0); + this.variableOffsets[symbolInstance.crossTileID] = { + radialOffset: radialTextOffset, + width, + height, + anchor, + textBoxScale, + prevAnchor + }; + this.markUsedJustification(bucket, anchor, symbolInstance); + return placedGlyphBoxes; + } + } + placeLayerBucket(bucket: SymbolBucket, posMatrix: mat4, textLabelPlaneMatrix: mat4, iconLabelPlaneMatrix: mat4, scale: number, textPixelRatio: number, showCollisionBoxes: boolean, holdingForFade: boolean, seenCrossTileIDs: { [string | number]: boolean }, collisionBoxArray: ?CollisionBoxArray) { const layout = bucket.layers[0].layout; - const partiallyEvaluatedTextSize = symbolSize.evaluateSizeForZoom(bucket.textSizeData, this.transform.zoom, symbolLayerProperties.layout.properties['text-size']); - const textOptional = layout.get('text-optional'); const iconOptional = layout.get('icon-optional'); - const textAllowOverlap = layout.get('text-allow-overlap'); const iconAllowOverlap = layout.get('icon-allow-overlap'); // This logic is similar to the "defaultOpacityState" logic below in updateBucketOpacities @@ -210,6 +298,9 @@ export class Placement { const collisionGroup = this.collisionGroups.get(bucket.sourceID); + const rotateWithMap = layout.get('text-rotation-alignment') === 'map'; + const pitchWithMap = layout.get('text-pitch-alignment') === 'map'; + if (!bucket.collisionArrays && collisionBoxArray) { bucket.deserializeCollisionBoxes(collisionBoxArray); } @@ -231,7 +322,6 @@ export class Placement { let placedGlyphBoxes = null; let placedGlyphCircles = null; let placedIconBoxes = null; - let textFeatureIndex = 0; let iconFeatureIndex = 0; @@ -240,15 +330,56 @@ export class Placement { if (collisionArrays.textFeatureIndex) { textFeatureIndex = collisionArrays.textFeatureIndex; } - if (collisionArrays.textBox) { - placedGlyphBoxes = this.collisionIndex.placeCollisionBox(collisionArrays.textBox, - layout.get('text-allow-overlap'), textPixelRatio, posMatrix, collisionGroup.predicate); - placeText = placedGlyphBoxes.box.length > 0; - offscreen = offscreen && placedGlyphBoxes.offscreen; + + const textBox = collisionArrays.textBox; + if (textBox) { + if (!layout.get('text-variable-anchor')) { + placedGlyphBoxes = this.collisionIndex.placeCollisionBox(textBox, + layout.get('text-allow-overlap'), textPixelRatio, posMatrix, collisionGroup.predicate); + placeText = placedGlyphBoxes.box.length > 0; + } else { + const width = textBox.x2 - textBox.x1; + const height = textBox.y2 - textBox.y1; + const textBoxScale = symbolInstance.textBoxScale; + let anchors = layout.get('text-variable-anchor'); + + // If we this symbol was in the last placement, shift the previously used + // anchor to the front of the anchor list. + if (this.prevPlacement && this.prevPlacement.variableOffsets[symbolInstance.crossTileID]) { + const prevOffsets = this.prevPlacement.variableOffsets[symbolInstance.crossTileID]; + if (anchors[0] !== prevOffsets.anchor) { + anchors = anchors.filter(anchor => anchor !== prevOffsets.anchor); + anchors.unshift(prevOffsets.anchor); + } + } + + for (const anchor of anchors) { + placedGlyphBoxes = this.attemptAnchorPlacement( + anchor, textBox, width, height, symbolInstance.radialTextOffset, + textBoxScale, rotateWithMap, pitchWithMap, textPixelRatio, posMatrix, + collisionGroup, textAllowOverlap, symbolInstance, bucket); + if (placedGlyphBoxes) { + placeText = true; + break; + } + } + + // If we didn't get placed, we still need to copy our position from the last placement for + // fade animations + if (!this.variableOffsets[symbolInstance.crossTileID] && this.prevPlacement) { + const prevOffset = this.prevPlacement.variableOffsets[symbolInstance.crossTileID]; + if (prevOffset) { + this.variableOffsets[symbolInstance.crossTileID] = prevOffset; + this.markUsedJustification(bucket, prevOffset.anchor, symbolInstance); + } + } + } } + + offscreen = placedGlyphBoxes && placedGlyphBoxes.offscreen; const textCircles = collisionArrays.textCircles; if (textCircles) { - const placedSymbol = bucket.text.placedSymbolArray.get(symbolInstance.horizontalPlacedTextSymbolIndex); + const placedSymbol = bucket.text.placedSymbolArray.get(symbolInstance.centerJustifiedTextSymbolIndex); const fontSize = symbolSize.evaluateSizeForFeature(bucket.textSizeData, partiallyEvaluatedTextSize, placedSymbol); placedGlyphCircles = this.collisionIndex.placeCollisionCircles(textCircles, layout.get('text-allow-overlap'), @@ -261,7 +392,7 @@ export class Placement { posMatrix, textLabelPlaneMatrix, showCollisionBoxes, - layout.get('text-pitch-alignment') === 'map', + pitchWithMap, collisionGroup.predicate); // If text-allow-overlap is set, force "placedCircles" to true // In theory there should always be at least one circle placed @@ -281,7 +412,8 @@ export class Placement { offscreen = offscreen && placedIconBoxes.offscreen; } - const iconWithoutText = textOptional || (symbolInstance.numGlyphVertices === 0 && symbolInstance.numVerticalGlyphVertices === 0); + const iconWithoutText = textOptional || + (symbolInstance.numHorizontalGlyphVertices === 0 && symbolInstance.numVerticalGlyphVertices === 0); const textWithoutIcon = iconOptional || symbolInstance.numIconVertices === 0; // Combine the scales for icons and text. @@ -317,9 +449,32 @@ export class Placement { bucket.justReloaded = false; } - commit(prevPlacement: ?Placement, now: number): void { + markUsedJustification(bucket: SymbolBucket, placedAnchor: TextAnchor, symbolInstance: SymbolInstance) { + const justifications = { + "left": symbolInstance.leftJustifiedTextSymbolIndex, + "center": symbolInstance.centerJustifiedTextSymbolIndex, + "right": symbolInstance.rightJustifiedTextSymbolIndex + }; + const autoIndex = justifications[getAnchorJustification(placedAnchor)]; + + for (const justification in justifications) { + const index = justifications[justification]; + if (index >= 0) { + if (autoIndex >= 0 && index !== autoIndex) { + // There are multiple justifications and this one isn't it: shift offscreen + bucket.text.placedSymbolArray.get(index).crossTileID = 0; + } else { + // Either this is the chosen justification or the justification is hardwired: use this one + bucket.text.placedSymbolArray.get(index).crossTileID = symbolInstance.crossTileID; + } + } + } + } + + commit(now: number): void { this.commitTime = now; + const prevPlacement = this.prevPlacement; let placementChanged = false; const increment = (prevPlacement && this.fadeDuration !== 0) ? @@ -327,7 +482,7 @@ export class Placement { 1; const prevOpacities = prevPlacement ? prevPlacement.opacities : {}; - + const prevOffsets = prevPlacement ? prevPlacement.variableOffsets : {}; // add the opacities from the current placement, and copy their current values from the previous placement for (const crossTileID in this.placements) { const jointPlacement = this.placements[crossTileID]; @@ -354,6 +509,11 @@ export class Placement { } } } + for (const crossTileID in prevOffsets) { + if (!this.variableOffsets[crossTileID] && this.opacities[crossTileID] && !this.opacities[crossTileID].isHidden()) { + this.variableOffsets[crossTileID] = prevOffsets[crossTileID]; + } + } // this.lastPlacementChangeTime is the time of the last commit() that // resulted in a placement change -- in other words, the start time of @@ -368,7 +528,6 @@ export class Placement { updateLayerOpacities(styleLayer: StyleLayer, tiles: Array) { const seenCrossTileIDs = {}; - for (const tile of tiles) { const symbolBucket = ((tile.getBucket(styleLayer): any): SymbolBucket); if (symbolBucket && tile.latestFeatureIndex && styleLayer.id === symbolBucket.layerIds[0]) { @@ -387,6 +546,9 @@ export class Placement { const duplicateOpacityState = new JointOpacityState(null, 0, false, false, true); const textAllowOverlap = layout.get('text-allow-overlap'); const iconAllowOverlap = layout.get('icon-allow-overlap'); + const variablePlacement = layout.get('text-variable-anchor'); + const rotateWithMap = layout.get('text-rotation-alignment') === 'map'; + const pitchWithMap = layout.get('text-pitch-alignment') === 'map'; // If allow-overlap is true, we can show symbols before placement runs on them // But we have to wait for placement if we potentially depend on a paired icon/text // with allow-overlap: false. @@ -402,38 +564,55 @@ export class Placement { for (let s = 0; s < bucket.symbolInstances.length; s++) { const symbolInstance = bucket.symbolInstances.get(s); - const isDuplicate = seenCrossTileIDs[symbolInstance.crossTileID]; + const { + numHorizontalGlyphVertices, + numVerticalGlyphVertices, + crossTileID + } = symbolInstance; - let opacityState = this.opacities[symbolInstance.crossTileID]; + const isDuplicate = seenCrossTileIDs[crossTileID]; + + let opacityState = this.opacities[crossTileID]; if (isDuplicate) { opacityState = duplicateOpacityState; } else if (!opacityState) { opacityState = defaultOpacityState; // store the state so that future placements use it as a starting point - this.opacities[symbolInstance.crossTileID] = opacityState; + this.opacities[crossTileID] = opacityState; } - seenCrossTileIDs[symbolInstance.crossTileID] = true; + seenCrossTileIDs[crossTileID] = true; - const hasText = symbolInstance.numGlyphVertices > 0 || symbolInstance.numVerticalGlyphVertices > 0; + const hasText = numHorizontalGlyphVertices > 0 || numVerticalGlyphVertices > 0; const hasIcon = symbolInstance.numIconVertices > 0; if (hasText) { const packedOpacity = packOpacity(opacityState.text); // Vertical text fades in/out on collision the same way as corresponding // horizontal text. Switch between vertical/horizontal should be instantaneous - const opacityEntryCount = (symbolInstance.numGlyphVertices + symbolInstance.numVerticalGlyphVertices) / 4; + const opacityEntryCount = (numHorizontalGlyphVertices + numVerticalGlyphVertices) / 4; for (let i = 0; i < opacityEntryCount; i++) { bucket.text.opacityVertexArray.emplaceBack(packedOpacity); } // If this label is completely faded, mark it so that we don't have to calculate - // its position at render time - bucket.text.placedSymbolArray.get(symbolInstance.horizontalPlacedTextSymbolIndex).hidden = - (opacityState.text.isHidden(): any); + // its position at render time. If this layer has variable placement, shift the various + // symbol instances appropriately so that symbols from buckets that have yet to be placed + // offset appropriately. + const hidden = opacityState.text.isHidden() ? 1 : 0; + [ + symbolInstance.rightJustifiedTextSymbolIndex, + symbolInstance.centerJustifiedTextSymbolIndex, + symbolInstance.leftJustifiedTextSymbolIndex, + symbolInstance.verticalPlacedTextSymbolIndex + ].forEach(index => { + if (index >= 0) { + bucket.text.placedSymbolArray.get(index).hidden = hidden; + } + }); - if (symbolInstance.verticalPlacedTextSymbolIndex >= 0) { - bucket.text.placedSymbolArray.get(symbolInstance.verticalPlacedTextSymbolIndex).hidden = - (opacityState.text.isHidden(): any); + const prevOffset = this.variableOffsets[symbolInstance.crossTileID]; + if (prevOffset) { + this.markUsedJustification(bucket, prevOffset.anchor, symbolInstance); } } @@ -446,11 +625,37 @@ export class Placement { (opacityState.icon.isHidden(): any); } + if (bucket.hasCollisionBoxData() || bucket.hasCollisionCircleData()) { const collisionArrays = bucket.collisionArrays[s]; if (collisionArrays) { if (collisionArrays.textBox) { - updateCollisionVertices(bucket.collisionBox.collisionVertexArray, opacityState.text.placed, false); + let shift = new Point(0, 0); + let used = true; + if (variablePlacement) { + const variableOffset = this.variableOffsets[crossTileID]; + if (variableOffset) { + // This will show either the currently placed position or the last + // successfully placed position (so you can visualize what collision + // just made the symbol disappear, and the most likely place for the + // symbol to come back) + shift = calculateVariableLayoutOffset(variableOffset.anchor, + variableOffset.width, + variableOffset.height, + variableOffset.radialOffset, + variableOffset.textBoxScale); + if (rotateWithMap) { + shift._rotate(pitchWithMap ? this.transform.angle : -this.transform.angle); + } + } else { + // No offset -> this symbol hasn't been placed since coming on-screen + // No single box is particularly meaningful and all of them would be too noisy + // Use the center box just to show something's there, but mark it "not used" + used = false; + } + } + + updateCollisionVertices(bucket.collisionBox.collisionVertexArray, opacityState.text.placed, !used, shift.x, shift.y); } if (collisionArrays.iconBox) { @@ -510,11 +715,11 @@ export class Placement { } } -function updateCollisionVertices(collisionVertexArray: CollisionVertexArray, placed: boolean, notUsed: boolean) { - collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0); - collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0); - collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0); - collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0); +function updateCollisionVertices(collisionVertexArray: CollisionVertexArray, placed: boolean, notUsed: boolean, shiftX?: number, shiftY?: number) { + collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0, shiftX || 0, shiftY || 0); + collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0, shiftX || 0, shiftY || 0); + collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0, shiftX || 0, shiftY || 0); + collisionVertexArray.emplaceBack(placed ? 1 : 0, notUsed ? 1 : 0, shiftX || 0, shiftY || 0); } // All four vertices for a glyph will have the same opacity state diff --git a/src/symbol/projection.js b/src/symbol/projection.js index d565b1ff025..51ea3b8d3aa 100644 --- a/src/symbol/projection.js +++ b/src/symbol/projection.js @@ -18,7 +18,7 @@ import type { } from '../data/array_types'; import { WritingMode } from '../symbol/shaping'; -export { updateLineLabels, getLabelPlaneMatrix, getGlCoordMatrix, project, placeFirstAndLastGlyph, xyTransformMat4 }; +export { updateLineLabels, hideGlyphs, getLabelPlaneMatrix, getGlCoordMatrix, project, placeFirstAndLastGlyph, xyTransformMat4 }; /* * # Overview of coordinate spaces @@ -73,17 +73,14 @@ function getLabelPlaneMatrix(posMatrix: mat4, rotateWithMap: boolean, transform: Transform, pixelsToTileUnits: number) { - const m = mat4.identity(new Float32Array(16)); + const m = mat4.create(); if (pitchWithMap) { - mat4.identity(m); mat4.scale(m, m, [1 / pixelsToTileUnits, 1 / pixelsToTileUnits, 1]); if (!rotateWithMap) { mat4.rotateZ(m, m, transform.angle); } } else { - mat4.scale(m, m, [transform.width / 2, -transform.height / 2, 1]); - mat4.translate(m, m, [1, -1, 0]); - mat4.multiply(m, m, posMatrix); + mat4.multiply(m, transform.labelPlaneMatrix, posMatrix); } return m; } @@ -96,19 +93,16 @@ function getGlCoordMatrix(posMatrix: mat4, rotateWithMap: boolean, transform: Transform, pixelsToTileUnits: number) { - const m = mat4.identity(new Float32Array(16)); if (pitchWithMap) { - mat4.multiply(m, m, posMatrix); + const m = mat4.clone(posMatrix); mat4.scale(m, m, [pixelsToTileUnits, pixelsToTileUnits, 1]); if (!rotateWithMap) { mat4.rotateZ(m, m, -transform.angle); } + return m; } else { - mat4.scale(m, m, [1, -1, 1]); - mat4.translate(m, m, [-1, -1, 0]); - mat4.scale(m, m, [2 / transform.width, 2 / transform.height, 1]); + return transform.glCoordMatrix; } - return m; } function project(point: Point, matrix: mat4) { @@ -261,8 +255,8 @@ function requiresOrientationChange(writingMode, firstPoint, lastPoint, aspectRat function placeGlyphsAlongLine(symbol, fontSize, flip, keepUpright, posMatrix, labelPlaneMatrix, glCoordMatrix, glyphOffsetArray, lineVertexArray, dynamicLayoutVertexArray, anchorPoint, tileAnchorPoint, projectionCache, aspectRatio) { const fontScale = fontSize / 24; - const lineOffsetX = symbol.lineOffsetX * fontSize; - const lineOffsetY = symbol.lineOffsetY * fontSize; + const lineOffsetX = symbol.lineOffsetX * fontScale; + const lineOffsetY = symbol.lineOffsetY * fontScale; let placedGlyphs; if (symbol.numGlyphs > 1) { diff --git a/src/symbol/quads.js b/src/symbol/quads.js index 45465bf6eb4..4e5cfb453d7 100644 --- a/src/symbol/quads.js +++ b/src/symbol/quads.js @@ -46,7 +46,7 @@ export function getIconQuads(anchor: Anchor, shapedIcon: PositionedIcon, layer: SymbolStyleLayer, alongLine: boolean, - shapedText: Shaping, + shapedText: Shaping | null, feature: Feature): Array { const image = shapedIcon.image; const layout = layer.layout; @@ -116,14 +116,13 @@ export function getIconQuads(anchor: Anchor, */ export function getGlyphQuads(anchor: Anchor, shaping: Shaping, + textOffset: [number, number], layer: SymbolStyleLayer, alongLine: boolean, feature: Feature, positions: {[string]: {[number]: GlyphPosition}}): Array { - const oneEm = 24; const textRotate = layer.layout.get('text-rotate').evaluate(feature, {}) * Math.PI / 180; - const textOffset = layer.layout.get('text-offset').evaluate(feature, {}).map((t) => t * oneEm); const positionedGlyphs = shaping.positionedGlyphs; const quads = []; diff --git a/src/symbol/shaping.js b/src/symbol/shaping.js index b4390a7aadf..68f27369157 100644 --- a/src/symbol/shaping.js +++ b/src/symbol/shaping.js @@ -6,6 +6,7 @@ import { } from '../util/script_detection'; import verticalizePunctuation from '../util/verticalize_punctuation'; import { plugin as rtlTextPlugin } from '../source/rtl_text_plugin'; +import ONE_EM from './one_em'; import type {StyleGlyph} from '../style/style_glyph'; import type {ImagePosition} from '../render/image_atlas'; @@ -17,7 +18,7 @@ const WritingMode = { horizontalOnly: 3 }; -export { shapeText, shapeIcon, WritingMode }; +export { shapeText, shapeIcon, getAnchorAlignment, WritingMode }; // The position of a glyph relative to the text's anchor point. export type PositionedGlyph = { @@ -36,11 +37,13 @@ export type Shaping = { bottom: number, left: number, right: number, - writingMode: 1 | 2 + writingMode: 1 | 2, + lineCount: number, + text: string }; -type SymbolAnchor = 'center' | 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; -type TextJustify = 'left' | 'center' | 'right'; +export type SymbolAnchor = 'center' | 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; +export type TextJustify = 'left' | 'center' | 'right'; class TaggedString { text: string; @@ -143,7 +146,6 @@ function shapeText(text: Formatted, textJustify: TextJustify, spacing: number, translate: [number, number], - verticalHeight: number, writingMode: 1 | 2): Shaping | false { const logicalInput = TaggedString.fromFeature(text, defaultFontStack); @@ -151,17 +153,6 @@ function shapeText(text: Formatted, logicalInput.verticalizePunctuation(); } - const positionedGlyphs = []; - const shaping = { - positionedGlyphs, - text: logicalInput, - top: translate[1], - bottom: translate[1], - left: translate[0], - right: translate[0], - writingMode - }; - let lines: Array; const {processBidirectionalText, processStyledBidirectionalText} = rtlTextPlugin; @@ -199,12 +190,21 @@ function shapeText(text: Formatted, lines = breakLines(logicalInput, determineLineBreaks(logicalInput, spacing, maxWidth, glyphs)); } - shapeLines(shaping, glyphs, lines, lineHeight, textAnchor, textJustify, writingMode, spacing, verticalHeight); + const positionedGlyphs = []; + const shaping = { + positionedGlyphs, + text: logicalInput.toString(), + top: translate[1], + bottom: translate[1], + left: translate[0], + right: translate[0], + writingMode, + lineCount: lines.length + }; - if (!positionedGlyphs.length) - return false; + shapeLines(shaping, glyphs, lines, lineHeight, textAnchor, textJustify, writingMode, spacing); + if (!positionedGlyphs.length) return false; - shaping.text = shaping.text.toString(); return shaping; } @@ -430,8 +430,7 @@ function shapeLines(shaping: Shaping, textAnchor: SymbolAnchor, textJustify: TextJustify, writingMode: 1 | 2, - spacing: number, - verticalHeight: number) { + spacing: number) { // the y offset *should* be part of the font metadata const yOffset = -17; @@ -473,7 +472,7 @@ function shapeLines(shaping: Shaping, x += glyph.metrics.advance * section.scale + spacing; } else { positionedGlyphs.push({glyph: codePoint, x, y: baselineOffset, vertical: true, scale: section.scale, fontStack: section.fontStack}); - x += verticalHeight * section.scale + spacing; + x += ONE_EM * section.scale + spacing; } } diff --git a/src/symbol/symbol_layout.js b/src/symbol/symbol_layout.js index 01c49ea416e..5f3135ed2ef 100644 --- a/src/symbol/symbol_layout.js +++ b/src/symbol/symbol_layout.js @@ -18,8 +18,9 @@ import EXTENT from '../data/extent'; import SymbolBucket from '../data/bucket/symbol_bucket'; import EvaluationParameters from '../style/evaluation_parameters'; import {SIZE_PACK_FACTOR} from './symbol_size'; +import ONE_EM from './one_em'; -import type {Shaping, PositionedIcon} from './shaping'; +import type {Shaping, PositionedIcon, TextJustify} from './shaping'; import type {CollisionBoxArray} from '../data/array_types'; import type {SymbolFeature} from '../data/bucket/symbol_bucket'; import type {StyleImage} from '../style/style_image'; @@ -54,6 +55,57 @@ type Sizes = { compositeIconSizes: [PossiblyEvaluatedPropertyValue, PossiblyEvaluatedPropertyValue], // (5) }; +export type TextAnchor = 'center' | 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'; + +// The radial offset is to the edge of the text box +// In the horizontal direction, the edge of the text box is where glyphs start +// But in the vertical direction, the glyphs appear to "start" at the baseline +// We don't actually load baseline data, but we assume an offset of ONE_EM - 17 +// (see "yOffset" in shaping.js) +const baselineOffset = 7; + +export function evaluateRadialOffset(anchor: TextAnchor, radialOffset: number) { + let x = 0, y = 0; + // solve for r where r^2 + r^2 = radialOffset^2 + const hypotenuse = radialOffset / Math.sqrt(2); + + switch (anchor) { + case 'top-right': + case 'top-left': + y = hypotenuse - baselineOffset; + break; + case 'bottom-right': + case 'bottom-left': + y = -hypotenuse + baselineOffset; + break; + case 'bottom': + y = -radialOffset + baselineOffset; + break; + case 'top': + y = radialOffset - baselineOffset; + break; + } + + switch (anchor) { + case 'top-right': + case 'bottom-right': + x = -hypotenuse; + break; + case 'top-left': + case 'bottom-left': + x = hypotenuse; + break; + case 'left': + x = radialOffset; + break; + case 'right': + x = -radialOffset; + break; + } + + return [x, y]; +} + export function performSymbolLayout(bucket: SymbolBucket, glyphMap: {[string]: {[number]: ?StyleGlyph}}, glyphPositions: {[string]: {[number]: GlyphPosition}}, @@ -92,8 +144,7 @@ export function performSymbolLayout(bucket: SymbolBucket, sizes.layoutIconSize = unevaluatedLayoutValues['icon-size'].possiblyEvaluate(new EvaluationParameters(bucket.zoom + 1)); sizes.textMaxSize = unevaluatedLayoutValues['text-size'].possiblyEvaluate(new EvaluationParameters(18)); - const oneEm = 24; - const lineHeight = layout.get('text-line-height') * oneEm; + const lineHeight = layout.get('text-line-height') * ONE_EM; const textAlongLine = layout.get('text-rotation-alignment') === 'map' && layout.get('symbol-placement') !== 'point'; const keepUpright = layout.get('text-keep-upright'); @@ -102,23 +153,80 @@ export function performSymbolLayout(bucket: SymbolBucket, const fontstack = layout.get('text-font').evaluate(feature, {}).join(','); const glyphPositionMap = glyphPositions; - const shapedTextOrientations = {}; + const shapedTextOrientations = { + horizontal: {}, + vertical: undefined + }; const text = feature.text; + let textOffset: [number, number] = [0, 0]; if (text) { const unformattedText = text.toString(); - const textOffset: [number, number] = (layout.get('text-offset').evaluate(feature, {}).map((t) => t * oneEm): any); - const spacing = layout.get('text-letter-spacing').evaluate(feature, {}) * oneEm; + const spacing = layout.get('text-letter-spacing').evaluate(feature, {}) * ONE_EM; const spacingIfAllowed = allowsLetterSpacing(unformattedText) ? spacing : 0; + const textAnchor = layout.get('text-anchor').evaluate(feature, {}); - const textJustify = layout.get('text-justify').evaluate(feature, {}); + const variableTextAnchor = layout.get('text-variable-anchor'); + const radialOffset = layout.get('text-radial-offset').evaluate(feature, {}); + + if (!variableTextAnchor) { + // Layers with variable anchors use the `text-radial-offset` property and the [x, y] offset vector + // is calculated at placement time instead of layout time + if (radialOffset) { + // The style spec says don't use `text-offset` and `text-radial-offset` together + // but doesn't actually specify what happens if you use both. We go with the radial offset. + textOffset = evaluateRadialOffset(textAnchor, radialOffset * ONE_EM); + } else { + textOffset = (layout.get('text-offset').evaluate(feature, {}).map(t => t * ONE_EM): any); + } + } + + let textJustify = textAlongLine ? + "center" : + layout.get('text-justify').evaluate(feature, {}); + const maxWidth = layout.get('symbol-placement') === 'point' ? - layout.get('text-max-width').evaluate(feature, {}) * oneEm : + layout.get('text-max-width').evaluate(feature, {}) * ONE_EM : 0; - shapedTextOrientations.horizontal = shapeText(text, glyphMap, fontstack, maxWidth, lineHeight, textAnchor, textJustify, spacingIfAllowed, textOffset, oneEm, WritingMode.horizontal); - if (allowsVerticalWritingMode(unformattedText) && textAlongLine && keepUpright) { - shapedTextOrientations.vertical = shapeText(text, glyphMap, fontstack, maxWidth, lineHeight, textAnchor, textJustify, spacingIfAllowed, textOffset, oneEm, WritingMode.vertical); + // If this layer uses text-variable-anchor, generate shapings for all justification possibilities. + if (!textAlongLine && variableTextAnchor) { + const justifications = textJustify === "auto" ? + variableTextAnchor.map(a => getAnchorJustification(a)) : + [textJustify]; + + let singleLine = false; + for (let i = 0; i < justifications.length; i++) { + const justification: TextJustify = justifications[i]; + if (shapedTextOrientations.horizontal[justification]) continue; + if (singleLine) { + // If the shaping for the first justification was only a single line, we + // can re-use it for the other justifications + shapedTextOrientations.horizontal[justification] = shapedTextOrientations.horizontal[0]; + } else { + // If using text-variable-anchor for the layer, we use a center anchor for all shapings and apply + // the offsets for the anchor in the placement step. + const shaping = shapeText(text, glyphMap, fontstack, maxWidth, lineHeight, 'center', + justification, spacingIfAllowed, textOffset, WritingMode.horizontal); + if (shaping) { + shapedTextOrientations.horizontal[justification] = shaping; + singleLine = shaping.lineCount === 1; + } + } + } + } else { + if (textJustify === "auto") { + textJustify = getAnchorJustification(textAnchor); + } + const shaping = shapeText(text, glyphMap, fontstack, maxWidth, lineHeight, textAnchor, textJustify, spacingIfAllowed, + textOffset, WritingMode.horizontal); + if (shaping) shapedTextOrientations.horizontal[textJustify] = shaping; + + if (allowsVerticalWritingMode(unformattedText) && textAlongLine && keepUpright) { + shapedTextOrientations.vertical = shapeText(text, glyphMap, fontstack, maxWidth, lineHeight, textAnchor, textJustify, + spacingIfAllowed, textOffset, WritingMode.vertical); + } } + } let shapedIcon; @@ -142,8 +250,8 @@ export function performSymbolLayout(bucket: SymbolBucket, } } - if (shapedTextOrientations.horizontal || shapedIcon) { - addFeature(bucket, feature, shapedTextOrientations, shapedIcon, glyphPositionMap, sizes); + if (Object.keys(shapedTextOrientations.horizontal).length || shapedIcon) { + addFeature(bucket, feature, shapedTextOrientations, shapedIcon, glyphPositionMap, sizes, textOffset); } } @@ -152,6 +260,20 @@ export function performSymbolLayout(bucket: SymbolBucket, } } +// Choose the justification that matches the direction of the TextAnchor +export function getAnchorJustification(anchor: TextAnchor): TextJustify { + switch (anchor) { + case 'right': + case 'top-right': + case 'bottom-right': + return 'right'; + case 'left': + case 'top-left': + case 'bottom-left': + return 'left'; + } + return 'center'; +} /** * Given a feature and its shaped text and icon data, add a 'symbol @@ -165,7 +287,8 @@ function addFeature(bucket: SymbolBucket, shapedTextOrientations: any, shapedIcon: PositionedIcon | void, glyphPositionMap: {[string]: {[number]: GlyphPosition}}, - sizes: Sizes) { + sizes: Sizes, + textOffset: [number, number]) { const layoutTextSize = sizes.layoutTextSize.evaluate(feature, {}); const layoutIconSize = sizes.layoutIconSize.evaluate(feature, {}); @@ -179,9 +302,8 @@ function addFeature(bucket: SymbolBucket, } const layout = bucket.layers[0].layout; - const textOffset = layout.get('text-offset').evaluate(feature, {}); const iconOffset = layout.get('icon-offset').evaluate(feature, {}); - + const defaultHorizontalShaping = getDefaultHorizontalShaping(shapedTextOrientations.horizontal); const glyphSize = 24, fontScale = layoutTextSize / glyphSize, textBoxScale = bucket.tilePixelRatio * fontScale, @@ -217,7 +339,7 @@ function addFeature(bucket: SymbolBucket, line, symbolMinDistance, textMaxAngle, - shapedTextOrientations.vertical || shapedTextOrientations.horizontal, + shapedTextOrientations.vertical || defaultHorizontalShaping, shapedIcon, glyphSize, textMaxBoxScale, @@ -225,7 +347,7 @@ function addFeature(bucket: SymbolBucket, EXTENT ); for (const anchor of anchors) { - const shapedText = shapedTextOrientations.horizontal; + const shapedText = defaultHorizontalShaping; if (!shapedText || !anchorIsTooClose(bucket, shapedText.text, textRepeatDistance, anchor)) { addSymbolAtAnchor(line, anchor); } @@ -239,7 +361,7 @@ function addFeature(bucket: SymbolBucket, const anchor = getCenterAnchor( line, textMaxAngle, - shapedTextOrientations.vertical || shapedTextOrientations.horizontal, + shapedTextOrientations.vertical || defaultHorizontalShaping, shapedIcon, glyphSize, textMaxBoxScale); @@ -279,10 +401,11 @@ function addTextVertices(bucket: SymbolBucket, textOffset: [number, number], lineArray: {lineStartIndex: number, lineLength: number}, writingMode: number, - placedTextSymbolIndices: Array, + placementTypes: Array<'vertical' | 'center' | 'left' | 'right'>, + placedTextSymbolIndices: {[string]: number}, glyphPositionMap: {[string]: {[number]: GlyphPosition}}, sizes: Sizes) { - const glyphQuads = getGlyphQuads(anchor, shapedText, + const glyphQuads = getGlyphQuads(anchor, shapedText, textOffset, layer, textAlongLine, feature, glyphPositionMap); const sizeData = bucket.textSizeData; @@ -319,11 +442,22 @@ function addTextVertices(bucket: SymbolBucket, // The placedSymbolArray is used at render time in drawTileSymbols // These indices allow access to the array at collision detection time - placedTextSymbolIndices.push(bucket.text.placedSymbolArray.length - 1); + for (const placementType of placementTypes) { + placedTextSymbolIndices[placementType] = bucket.text.placedSymbolArray.length - 1; + } return glyphQuads.length * 4; } +function getDefaultHorizontalShaping(horizontalShaping: {[TextJustify]: Shaping}): Shaping | null { + // We don't care which shaping we get because this is used for collision purposes + // and all the justifications have the same collision box + for (const justification: any in horizontalShaping) { + return horizontalShaping[justification]; + } + return null; +} + /** * Add a single label & icon placement. @@ -356,20 +490,39 @@ function addSymbol(bucket: SymbolBucket, let textCollisionFeature, iconCollisionFeature; let numIconVertices = 0; - let numGlyphVertices = 0; + let numHorizontalGlyphVertices = 0; let numVerticalGlyphVertices = 0; - const key = murmur3(shapedTextOrientations.horizontal ? shapedTextOrientations.horizontal.text : ''); - const placedTextSymbolIndices = []; - if (shapedTextOrientations.horizontal) { - // As a collision approximation, we can use either the vertical or the horizontal version of the feature - // We're counting on the two versions having similar dimensions - const textRotate = layer.layout.get('text-rotate').evaluate(feature, {}); - textCollisionFeature = new CollisionFeature(collisionBoxArray, line, anchor, featureIndex, sourceLayerIndex, bucketIndex, shapedTextOrientations.horizontal, textBoxScale, textPadding, textAlongLine, bucket.overscaling, textRotate); - numGlyphVertices += addTextVertices(bucket, anchor, shapedTextOrientations.horizontal, layer, textAlongLine, feature, textOffset, lineArray, shapedTextOrientations.vertical ? WritingMode.horizontal : WritingMode.horizontalOnly, placedTextSymbolIndices, glyphPositionMap, sizes); - - if (shapedTextOrientations.vertical) { - numVerticalGlyphVertices += addTextVertices(bucket, anchor, shapedTextOrientations.vertical, layer, textAlongLine, feature, textOffset, lineArray, WritingMode.vertical, placedTextSymbolIndices, glyphPositionMap, sizes); + const placedTextSymbolIndices = {}; + let key = murmur3(''); + const radialTextOffset = (layer.layout.get('text-radial-offset').evaluate(feature, {}) || 0) * ONE_EM; + + for (const justification: any in shapedTextOrientations.horizontal) { + const shaping = shapedTextOrientations.horizontal[justification]; + + if (!textCollisionFeature) { + key = murmur3(shaping.text); + const textRotate = layer.layout.get('text-rotate').evaluate(feature, {}); + // As a collision approximation, we can use either the vertical or any of the horizontal versions of the feature + // We're counting on all versions having similar dimensions + textCollisionFeature = new CollisionFeature(collisionBoxArray, line, anchor, featureIndex, sourceLayerIndex, bucketIndex, shaping, textBoxScale, textPadding, textAlongLine, bucket.overscaling, textRotate); } + + const singleLine = shaping.lineCount === 1; + numHorizontalGlyphVertices += addTextVertices( + bucket, anchor, shaping, layer, textAlongLine, feature, textOffset, lineArray, + shapedTextOrientations.vertical ? WritingMode.horizontal : WritingMode.horizontalOnly, + singleLine ? (Object.keys(shapedTextOrientations.horizontal): any) : [justification], + placedTextSymbolIndices, glyphPositionMap, sizes); + + if (singleLine) { + break; + } + } + + if (shapedTextOrientations.vertical) { + numVerticalGlyphVertices += addTextVertices( + bucket, anchor, shapedTextOrientations.vertical, layer, textAlongLine, feature, + textOffset, lineArray, WritingMode.vertical, ['vertical'], placedTextSymbolIndices, glyphPositionMap, sizes); } const textBoxStartIndex = textCollisionFeature ? textCollisionFeature.boxStartIndex : bucket.collisionBoxArray.length; @@ -377,7 +530,7 @@ function addSymbol(bucket: SymbolBucket, if (shapedIcon) { const iconQuads = getIconQuads(anchor, shapedIcon, layer, - iconAlongLine, shapedTextOrientations.horizontal, + iconAlongLine, getDefaultHorizontalShaping(shapedTextOrientations.horizontal), feature); const iconRotate = layer.layout.get('icon-rotate').evaluate(feature, {}); iconCollisionFeature = new CollisionFeature(collisionBoxArray, line, anchor, featureIndex, sourceLayerIndex, bucketIndex, shapedIcon, iconBoxScale, iconPadding, /*align boxes to line*/false, bucket.overscaling, iconRotate); @@ -427,18 +580,22 @@ function addSymbol(bucket: SymbolBucket, bucket.symbolInstances.emplaceBack( anchor.x, anchor.y, - placedTextSymbolIndices.length > 0 ? placedTextSymbolIndices[0] : -1, - placedTextSymbolIndices.length > 1 ? placedTextSymbolIndices[1] : -1, + placedTextSymbolIndices.right >= 0 ? placedTextSymbolIndices.right : -1, + placedTextSymbolIndices.center >= 0 ? placedTextSymbolIndices.center : -1, + placedTextSymbolIndices.left >= 0 ? placedTextSymbolIndices.left : -1, + placedTextSymbolIndices.vertical || -1, key, textBoxStartIndex, textBoxEndIndex, iconBoxStartIndex, iconBoxEndIndex, featureIndex, - numGlyphVertices, + numHorizontalGlyphVertices, numVerticalGlyphVertices, numIconVertices, - 0); + 0, + textBoxScale, + radialTextOffset); } function anchorIsTooClose(bucket: any, text: string, repeatDistance: number, anchor: Point) { diff --git a/src/ui/camera.js b/src/ui/camera.js index b95230d19b5..fd73a4dbd20 100644 --- a/src/ui/camera.js +++ b/src/ui/camera.js @@ -108,7 +108,7 @@ class Camera extends Evented { * @memberof Map# * @returns The map's geographical centerpoint. */ - getCenter(): LngLat { return this.transform.center; } + getCenter(): LngLat { return new LngLat(this.transform.center.lng, this.transform.center.lat); } /** * Sets the map's geographical centerpoint. Equivalent to `jumpTo({center: center})`. diff --git a/src/ui/control/attribution_control.js b/src/ui/control/attribution_control.js index 6491a8bb76c..2d4a972b7c6 100644 --- a/src/ui/control/attribution_control.js +++ b/src/ui/control/attribution_control.js @@ -104,6 +104,7 @@ class AttributionControl { return acc; }, `?`); editLink.href = `${config.FEEDBACK_URL}/${paramString}${this._map._hash ? this._map._hash.getHashString(true) : ''}`; + editLink.rel = "noopener"; } } diff --git a/src/ui/control/fullscreen_control.js b/src/ui/control/fullscreen_control.js index c5c6fbb3bb9..6ede36b8efa 100644 --- a/src/ui/control/fullscreen_control.js +++ b/src/ui/control/fullscreen_control.js @@ -87,12 +87,18 @@ class FullscreenControl { _setupUI() { const button = this._fullscreenButton = DOM.create('button', (`${this._className}-icon ${this._className}-fullscreen`), this._controlContainer); - button.setAttribute("aria-label", "Toggle fullscreen"); button.type = 'button'; + this._updateTitle(); this._fullscreenButton.addEventListener('click', this._onClickFullscreen); window.document.addEventListener(this._fullscreenchange, this._changeIcon); } + _updateTitle() { + const title = this._isFullscreen() ? "Exit fullscreen" : "Enter fullscreen"; + this._fullscreenButton.setAttribute("aria-label", title); + this._fullscreenButton.title = title; + } + _isFullscreen() { return this._fullscreen; } @@ -108,6 +114,7 @@ class FullscreenControl { this._fullscreen = !this._fullscreen; this._fullscreenButton.classList.toggle(`${this._className}-shrink`); this._fullscreenButton.classList.toggle(`${this._className}-fullscreen`); + this._updateTitle(); } } diff --git a/src/ui/control/geolocate_control.js b/src/ui/control/geolocate_control.js index 8d6c8effbab..ae51ae93ef5 100644 --- a/src/ui/control/geolocate_control.js +++ b/src/ui/control/geolocate_control.js @@ -187,8 +187,10 @@ class GeolocateControl extends Evented { _updateCamera(position: Position) { const center = new LngLat(position.coords.longitude, position.coords.latitude); const radius = position.coords.accuracy; + const bearing = this._map.getBearing(); + const options = extend({bearing}, this.options.fitBoundsOptions); - this._map.fitBounds(center.toBounds(radius), this.options.fitBoundsOptions, { + this._map.fitBounds(center.toBounds(radius), options, { geolocateSource: true // tag this camera change so it won't cause the control to change to background state }); } diff --git a/src/ui/control/logo_control.js b/src/ui/control/logo_control.js index 4466945ff8a..2d067c54c2d 100644 --- a/src/ui/control/logo_control.js +++ b/src/ui/control/logo_control.js @@ -29,6 +29,7 @@ class LogoControl { this._container = DOM.create('div', 'mapboxgl-ctrl'); const anchor = DOM.create('a', 'mapboxgl-ctrl-logo'); anchor.target = "_blank"; + anchor.rel = "noopener"; anchor.href = "https://www.mapbox.com/"; anchor.setAttribute("aria-label", "Mapbox logo"); anchor.setAttribute("rel", "noopener"); diff --git a/src/ui/control/navigation_control.js b/src/ui/control/navigation_control.js index 395fefd2e45..a2fe2afc781 100644 --- a/src/ui/control/navigation_control.js +++ b/src/ui/control/navigation_control.js @@ -46,6 +46,9 @@ class NavigationControl { this._container.addEventListener('contextmenu', (e) => e.preventDefault()); if (this.options.showZoom) { + bindAll([ + '_updateZoomButtons' + ], this); this._zoomInButton = this._createButton('mapboxgl-ctrl-icon mapboxgl-ctrl-zoom-in', 'Zoom in', () => this._map.zoomIn()); this._zoomOutButton = this._createButton('mapboxgl-ctrl-icon mapboxgl-ctrl-zoom-out', 'Zoom out', () => this._map.zoomOut()); } @@ -58,6 +61,12 @@ class NavigationControl { } } + _updateZoomButtons() { + const zoom = this._map.getZoom(); + this._zoomInButton.classList.toggle('mapboxgl-ctrl-icon-disabled', zoom === this._map.getMaxZoom()); + this._zoomOutButton.classList.toggle('mapboxgl-ctrl-icon-disabled', zoom === this._map.getMinZoom()); + } + _rotateCompassArrow() { const rotate = `rotate(${this._map.transform.angle * (180 / Math.PI)}deg)`; this._compassArrow.style.transform = rotate; @@ -65,6 +74,10 @@ class NavigationControl { onAdd(map: Map) { this._map = map; + if (this.options.showZoom) { + this._map.on('zoom', this._updateZoomButtons); + this._updateZoomButtons(); + } if (this.options.showCompass) { this._map.on('rotate', this._rotateCompassArrow); this._rotateCompassArrow(); @@ -77,6 +90,9 @@ class NavigationControl { onRemove() { DOM.remove(this._container); + if (this.options.showZoom) { + this._map.off('zoom', this._updateZoomButtons); + } if (this.options.showCompass) { this._map.off('rotate', this._rotateCompassArrow); DOM.removeEventListener(this._compass, 'mousedown', this._handler.onMouseDown); diff --git a/src/ui/events.js b/src/ui/events.js index 82968ccf8ba..3206c1226b3 100644 --- a/src/ui/events.js +++ b/src/ui/events.js @@ -778,6 +778,20 @@ export type MapEvent = */ | 'sourcedataloading' + /** + * Fired when an icon or pattern needed by the style is missing. The missing image can + * be added with {@link Map#addImage} within this event listener callback to prevent the image from + * being skipped. This event can be used to dynamically generate icons and patterns. + * + * @event styleimagemissing + * @memberof Map + * @instance + * @property {string} id The id of the missing image. + * + * @see [Generate and add a missing icon to the map](https://mapbox.com/mapbox-gl-js/example/add-image-missing-generated/) + */ + | 'styleimagemissing' + /** * @event style.load * @memberof Map diff --git a/src/ui/map.js b/src/ui/map.js index 3ccbb935011..a7154296376 100755 --- a/src/ui/map.js +++ b/src/ui/map.js @@ -34,6 +34,7 @@ import type {RequestParameters} from '../util/ajax'; import type {StyleOptions, StyleSetterOptions} from '../style/style'; import type {MapEvent, MapDataEvent} from './events'; import type {CustomLayerInterface} from '../style/style_layer/custom_style_layer'; +import type {StyleImageInterface} from '../style/style_image'; import type ScrollZoomHandler from './handler/scroll_zoom'; import type BoxZoomHandler from './handler/box_zoom'; @@ -75,6 +76,7 @@ type MapOptions = { logoPosition?: ControlPosition, failIfMajorPerformanceCaveat?: boolean, preserveDrawingBuffer?: boolean, + antialias?: boolean, refreshExpiredTiles?: boolean, maxBounds?: LngLatBoundsLike, scrollZoom?: boolean, @@ -128,6 +130,7 @@ const defaultOptions = { renderWorldCopies: true, refreshExpiredTiles: true, maxTileCacheSize: null, + localIdeographFontFamily: 'sans-serif', transformRequest: null, fadeDuration: 300, crossSourceCollisions: true @@ -183,6 +186,7 @@ const defaultOptions = { * @param {boolean} [options.failIfMajorPerformanceCaveat=false] If `true`, map creation will fail if the performance of Mapbox * GL JS would be dramatically worse than expected (i.e. a software renderer would be used). * @param {boolean} [options.preserveDrawingBuffer=false] If `true`, the map's canvas can be exported to a PNG using `map.getCanvas().toDataURL()`. This is `false` by default as a performance optimization. + * @param {boolean} [options.antialias] If `true`, the gl context will be created with MSAA antialiasing, which can be useful for antialiasing custom layers. this is `false` by default as a performance optimization. * @param {boolean} [options.refreshExpiredTiles=true] If `false`, the map won't attempt to re-request tiles once they expire per their HTTP `cacheControl`/`expires` headers. * @param {LngLatBoundsLike} [options.maxBounds] If set, the map will be constrained to the given bounds. * @param {boolean|Object} [options.scrollZoom=true] If `true`, the "scroll to zoom" interaction is enabled. An `Object` value is passed as options to {@link ScrollZoomHandler#enable}. @@ -198,12 +202,13 @@ const defaultOptions = { * @param {number} [options.bearing=0] The initial bearing (rotation) of the map, measured in degrees counter-clockwise from north. If `bearing` is not specified in the constructor options, Mapbox GL JS will look for it in the map's style object. If it is not specified in the style, either, it will default to `0`. * @param {number} [options.pitch=0] The initial pitch (tilt) of the map, measured in degrees away from the plane of the screen (0-60). If `pitch` is not specified in the constructor options, Mapbox GL JS will look for it in the map's style object. If it is not specified in the style, either, it will default to `0`. * @param {LngLatBoundsLike} [options.bounds] The initial bounds of the map. If `bounds` is specified, it overrides `center` and `zoom` constructor options. - * @param {Object} [options.fitBoundsOptions] A [`fitBounds`](#Map#fitBounds) options object to use _only_ when fitting the initial `bounds` provided above. + * @param {Object} [options.fitBoundsOptions] A [`fitBounds`](#map#fitbounds) options object to use _only_ when fitting the initial `bounds` provided above. * @param {boolean} [options.renderWorldCopies=true] If `true`, multiple copies of the world will be rendered, when zoomed out. * @param {number} [options.maxTileCacheSize=null] The maximum number of tiles stored in the tile cache for a given source. If omitted, the cache will be dynamically sized based on the current viewport. - * @param {string} [options.localIdeographFontFamily=null] If specified, defines a CSS font-family - * for locally overriding generation of glyphs in the 'CJK Unified Ideographs' and 'Hangul Syllables' ranges. + * @param {string} [options.localIdeographFontFamily='sans-serif'] Defines a CSS + * font-family for locally overriding generation of glyphs in the 'CJK Unified Ideographs' and 'Hangul Syllables' ranges. * In these ranges, font settings from the map's style will be ignored, except for font-weight keywords (light/regular/medium/bold). + * Set to `false`, to enable font settings from the map's style for these glyph ranges. * The purpose of this option is to avoid bandwidth-intensive glyph server requests. (see [Use locally generated ideographs](https://www.mapbox.com/mapbox-gl-js/example/local-ideographs)) * @param {RequestTransformFunction} [options.transformRequest=null] A callback run before the Map makes a request for an external URL. The callback can be used to modify the url, set headers, or set the credentials property for cross-origin requests. * Expected to return an object with a `url` property and optionally `headers` and `credentials` properties. @@ -255,6 +260,7 @@ class Map extends Camera { _trackResize: boolean; _preserveDrawingBuffer: boolean; _failIfMajorPerformanceCaveat: boolean; + _antialias: boolean; _refreshExpiredTiles: boolean; _hash: Hash; _delegatedListeners: any; @@ -265,6 +271,7 @@ class Map extends Camera { _renderTaskQueue: TaskQueue; _controls: Array; _mapId: number; + _localIdeographFontFamily: string; /** * The map's {@link ScrollZoomHandler}, which implements zooming in and out with a scroll wheel or trackpad. @@ -317,6 +324,7 @@ class Map extends Camera { this._maxTileCacheSize = options.maxTileCacheSize; this._failIfMajorPerformanceCaveat = options.failIfMajorPerformanceCaveat; this._preserveDrawingBuffer = options.preserveDrawingBuffer; + this._antialias = options.antialias; this._trackResize = options.trackResize; this._bearingSnap = options.bearingSnap; this._refreshExpiredTiles = options.refreshExpiredTiles; @@ -390,6 +398,7 @@ class Map extends Camera { this.resize(); + this._localIdeographFontFamily = options.localIdeographFontFamily; if (options.style) this.setStyle(options.style, { localIdeographFontFamily: options.localIdeographFontFamily }); if (options.attributionControl) @@ -681,22 +690,22 @@ class Map extends Camera { * a visible portion of the specified layer from outside that layer or outside the map canvas. `mouseleave` * and `mouseout` events are triggered when the cursor leaves a visible portion of the specified layer, or leaves * the map canvas. - * @param {string} layer The ID of a style layer. Only events whose location is within a visible + * @param {string} layerId The ID of a style layer. Only events whose location is within a visible * feature in this layer will trigger the listener. The event will have a `features` property containing * an array of the matching features. * @param {Function} listener The function to be called when the event is fired. * @returns {Map} `this` */ - on(type: MapEvent, layer: any, listener: any) { + on(type: MapEvent, layerId: any, listener: any) { if (listener === undefined) { - return super.on(type, layer); + return super.on(type, layerId); } const delegatedListener = (() => { if (type === 'mouseenter' || type === 'mouseover') { let mousein = false; const mousemove = (e) => { - const features = this.getLayer(layer) ? this.queryRenderedFeatures(e.point, {layers: [layer]}) : []; + const features = this.getLayer(layerId) ? this.queryRenderedFeatures(e.point, {layers: [layerId]}) : []; if (!features.length) { mousein = false; } else if (!mousein) { @@ -707,11 +716,11 @@ class Map extends Camera { const mouseout = () => { mousein = false; }; - return {layer, listener, delegates: {mousemove, mouseout}}; + return {layer: layerId, listener, delegates: {mousemove, mouseout}}; } else if (type === 'mouseleave' || type === 'mouseout') { let mousein = false; const mousemove = (e) => { - const features = this.getLayer(layer) ? this.queryRenderedFeatures(e.point, {layers: [layer]}) : []; + const features = this.getLayer(layerId) ? this.queryRenderedFeatures(e.point, {layers: [layerId]}) : []; if (features.length) { mousein = true; } else if (mousein) { @@ -725,10 +734,10 @@ class Map extends Camera { listener.call(this, new MapMouseEvent(type, this, e.originalEvent)); } }; - return {layer, listener, delegates: {mousemove, mouseout}}; + return {layer: layerId, listener, delegates: {mousemove, mouseout}}; } else { const delegate = (e) => { - const features = this.getLayer(layer) ? this.queryRenderedFeatures(e.point, {layers: [layer]}) : []; + const features = this.getLayer(layerId) ? this.queryRenderedFeatures(e.point, {layers: [layerId]}) : []; if (features.length) { // Here we need to mutate the original event, so that preventDefault works as expected. e.features = features; @@ -736,7 +745,7 @@ class Map extends Camera { delete e.features; } }; - return {layer, listener, delegates: {[type]: delegate}}; + return {layer: layerId, listener, delegates: {[type]: delegate}}; } })(); @@ -767,20 +776,20 @@ class Map extends Camera { * Removes an event listener for layer-specific events previously added with `Map#on`. * * @param {string} type The event type previously used to install the listener. - * @param {string} layer The layer ID previously used to install the listener. + * @param {string} layerId The layer ID previously used to install the listener. * @param {Function} listener The function previously installed as a listener. * @returns {Map} `this` */ - off(type: MapEvent, layer: any, listener: any) { + off(type: MapEvent, layerId: any, listener: any) { if (listener === undefined) { - return super.off(type, layer); + return super.off(type, layerId); } if (this._delegatedListeners && this._delegatedListeners[type]) { const listeners = this._delegatedListeners[type]; for (let i = 0; i < listeners.length; i++) { const delegatedListener = listeners[i]; - if (delegatedListener.layer === layer && delegatedListener.listener === listener) { + if (delegatedListener.layer === layerId && delegatedListener.listener === listener) { for (const event in delegatedListener.delegates) { this.off((event: any), delegatedListener.delegates[event]); } @@ -906,7 +915,7 @@ class Map extends Camera { * [Feature objects](https://tools.ietf.org/html/rfc7946#section-3.2) * representing features within the specified vector tile or GeoJSON source that satisfy the query parameters. * - * @param {string} sourceID The ID of the vector tile or GeoJSON source to query. + * @param {string} sourceId The ID of the vector tile or GeoJSON source to query. * @param {Object} [parameters] * @param {string} [parameters.sourceLayer] The name of the vector tile layer to query. *For vector tile * sources, this parameter is required.* For GeoJSON sources, it is ignored. @@ -932,8 +941,8 @@ class Map extends Camera { * @see [Filter features within map view](https://www.mapbox.com/mapbox-gl-js/example/filter-features-within-map-view/) * @see [Highlight features containing similar data](https://www.mapbox.com/mapbox-gl-js/example/query-similar-features/) */ - querySourceFeatures(sourceID: string, parameters: ?{sourceLayer: ?string, filter: ?Array}) { - return this.style.querySourceFeatures(sourceID, parameters); + querySourceFeatures(sourceId: string, parameters: ?{sourceLayer: ?string, filter: ?Array}) { + return this.style.querySourceFeatures(sourceId, parameters); } /** @@ -946,17 +955,22 @@ class Map extends Camera { * @param {Object} [options] * @param {boolean} [options.diff=true] If false, force a 'full' update, removing the current style * and building the given one instead of attempting a diff-based update. - * @param {string} [options.localIdeographFontFamily=null] If non-null, defines a css font-family - * for locally overriding generation of glyphs in the 'CJK Unified Ideographs' and 'Hangul Syllables' - * ranges. Forces a full update. + * @param {string} [options.localIdeographFontFamily='sans-serif'] Defines a CSS + * font-family for locally overriding generation of glyphs in the 'CJK Unified Ideographs' and 'Hangul Syllables' ranges. + * In these ranges, font settings from the map's style will be ignored, except for font-weight keywords (light/regular/medium/bold). + * Set to `false`, to enable font settings from the map's style for these glyph ranges. + * Forces a full update. * @returns {Map} `this` * @see [Change a map's style](https://www.mapbox.com/mapbox-gl-js/example/setstyle/) */ setStyle(style: StyleSpecification | string | null, options?: {diff?: boolean} & StyleOptions) { - if ((!options || (options.diff !== false && !options.localIdeographFontFamily)) && this.style && style) { + options = extend({}, { localIdeographFontFamily: defaultOptions.localIdeographFontFamily}, options); + + if ((options.diff !== false && options.localIdeographFontFamily === this._localIdeographFontFamily) && this.style && style) { this._diffStyle(style, options); return this; } else { + this._localIdeographFontFamily = options.localIdeographFontFamily; return this._updateStyle(style, options); } } @@ -1141,23 +1155,75 @@ class Map extends Camera { * @param options.sdf Whether the image should be interpreted as an SDF image */ addImage(id: string, - image: HTMLImageElement | ImageData | {width: number, height: number, data: Uint8Array | Uint8ClampedArray}, + image: HTMLImageElement | ImageData | {width: number, height: number, data: Uint8Array | Uint8ClampedArray} | StyleImageInterface, {pixelRatio = 1, sdf = false}: {pixelRatio?: number, sdf?: boolean} = {}) { + + const version = 0; + if (image instanceof HTMLImageElement) { const {width, height, data} = browser.getImageData(image); - this.style.addImage(id, { data: new RGBAImage({width, height}, data), pixelRatio, sdf }); + this.style.addImage(id, { data: new RGBAImage({width, height}, data), pixelRatio, sdf, version }); } else if (image.width === undefined || image.height === undefined) { return this.fire(new ErrorEvent(new Error( 'Invalid arguments to map.addImage(). The second argument must be an `HTMLImageElement`, `ImageData`, ' + 'or object with `width`, `height`, and `data` properties with the same format as `ImageData`'))); } else { const {width, height, data} = image; - this.style.addImage(id, { data: new RGBAImage({width, height}, new Uint8Array(data)), pixelRatio, sdf }); + const userImage = ((image: any): StyleImageInterface); + + this.style.addImage(id, { + data: new RGBAImage({width, height}, new Uint8Array(data)), + pixelRatio, + sdf, + version, + userImage + }); + + if (userImage.onAdd) { + userImage.onAdd(this, id); + } } } /** - * Define wether the image has been added or not + * Update an existing style image. This image can be used in `icon-image`, + * `background-pattern`, `fill-pattern`, and `line-pattern`. + * + * @param id The ID of the image. + * @param image The image as an `HTMLImageElement`, `ImageData`, or object with `width`, `height`, and `data` + * properties with the same format as `ImageData`. + */ + updateImage(id: string, + image: HTMLImageElement | ImageData | {width: number, height: number, data: Uint8Array | Uint8ClampedArray} | StyleImageInterface) { + + const existingImage = this.style.getImage(id); + if (!existingImage) { + return this.fire(new ErrorEvent(new Error( + 'The map has no image with that id. If you are adding a new image use `map.addImage(...)` instead.'))); + } + + const imageData = image instanceof HTMLImageElement ? browser.getImageData(image) : image; + const {width, height, data} = imageData; + + if (width === undefined || height === undefined) { + return this.fire(new ErrorEvent(new Error( + 'Invalid arguments to map.updateImage(). The second argument must be an `HTMLImageElement`, `ImageData`, ' + + 'or object with `width`, `height`, and `data` properties with the same format as `ImageData`'))); + } + + if (width !== existingImage.data.width || height !== existingImage.data.height) { + return this.fire(new ErrorEvent(new Error( + 'The width and height of the updated image must be that same as the previous version of the image'))); + } + + const copy = !(image instanceof HTMLImageElement); + existingImage.data.replace(data, copy); + + this.style.updateImage(id, existingImage); + } + + /** + * Define whether the image has been added or not * * @param id The ID of the image. */ @@ -1209,15 +1275,15 @@ class Map extends Camera { * * @param {Object | CustomLayerInterface} layer The style layer to add, conforming to the Mapbox Style Specification's * [layer definition](https://www.mapbox.com/mapbox-gl-style-spec/#layers). - * @param {string} [before] The ID of an existing layer to insert the new layer before. + * @param {string} [beforeId] The ID of an existing layer to insert the new layer before. * If this argument is omitted, the layer will be appended to the end of the layers array. * @returns {Map} `this` * @see [Create and style clusters](https://www.mapbox.com/mapbox-gl-js/example/cluster/) * @see [Add a vector tile source](https://www.mapbox.com/mapbox-gl-js/example/vector-source/) * @see [Add a WMS source](https://www.mapbox.com/mapbox-gl-js/example/wms/) */ - addLayer(layer: LayerSpecification | CustomLayerInterface, before?: string) { - this.style.addLayer(layer, before); + addLayer(layer: LayerSpecification | CustomLayerInterface, beforeId?: string) { + this.style.addLayer(layer, beforeId); return this._update(true); } @@ -1263,7 +1329,7 @@ class Map extends Camera { /** * Sets the filter for the specified style layer. * - * @param {string} layer The ID of the layer to which the filter will be applied. + * @param {string} layerId The ID of the layer to which the filter will be applied. * @param {Array | null | undefined} filter The filter, conforming to the Mapbox Style Specification's * [filter definition](https://www.mapbox.com/mapbox-gl-js/style-spec/#other-filter). If `null` or `undefined` is provided, the function removes any existing filter from the layer. * @param {Object} [options] @@ -1276,8 +1342,8 @@ class Map extends Camera { * @see [Highlight features containing similar data](https://www.mapbox.com/mapbox-gl-js/example/query-similar-features/) * @see [Create a timeline animation](https://www.mapbox.com/mapbox-gl-js/example/timeline-animation/) */ - setFilter(layer: string, filter: ?FilterSpecification, options: StyleSetterOptions = {}) { - this.style.setFilter(layer, filter, options); + setFilter(layerId: string, filter: ?FilterSpecification, options: StyleSetterOptions = {}) { + this.style.setFilter(layerId, filter, options); return this._update(true); } @@ -1299,19 +1365,19 @@ class Map extends Camera { /** * Returns the filter applied to the specified style layer. * - * @param {string} layer The ID of the style layer whose filter to get. + * @param {string} layerId The ID of the style layer whose filter to get. * @returns {Array} The layer's filter. */ - getFilter(layer: string) { - return this.style.getFilter(layer); + getFilter(layerId: string) { + return this.style.getFilter(layerId); } /** * Sets the value of a paint property in the specified style layer. * - * @param {string} layer The ID of the layer to set the paint property in. + * @param {string} layerId The ID of the layer to set the paint property in. * @param {string} name The name of the paint property to set. - * @param {*} value The value of the paint propery to set. + * @param {*} value The value of the paint property to set. * Must be of a type appropriate for the property, as defined in the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/). * @param {Object} [options] * @param {boolean} [options.validate=true] Whether to check if `value` conforms to the Mapbox GL Style Specification. Disabling validation is a performance optimization that should only be used if you have previously validated the values you will be passing to this function. @@ -1322,48 +1388,48 @@ class Map extends Camera { * @see [Adjust a layer's opacity](https://www.mapbox.com/mapbox-gl-js/example/adjust-layer-opacity/) * @see [Create a draggable point](https://www.mapbox.com/mapbox-gl-js/example/drag-a-point/) */ - setPaintProperty(layer: string, name: string, value: any, options: StyleSetterOptions = {}) { - this.style.setPaintProperty(layer, name, value, options); + setPaintProperty(layerId: string, name: string, value: any, options: StyleSetterOptions = {}) { + this.style.setPaintProperty(layerId, name, value, options); return this._update(true); } /** * Returns the value of a paint property in the specified style layer. * - * @param {string} layer The ID of the layer to get the paint property from. + * @param {string} layerId The ID of the layer to get the paint property from. * @param {string} name The name of a paint property to get. * @returns {*} The value of the specified paint property. */ - getPaintProperty(layer: string, name: string) { - return this.style.getPaintProperty(layer, name); + getPaintProperty(layerId: string, name: string) { + return this.style.getPaintProperty(layerId, name); } /** * Sets the value of a layout property in the specified style layer. * - * @param {string} layer The ID of the layer to set the layout property in. + * @param {string} layerId The ID of the layer to set the layout property in. * @param {string} name The name of the layout property to set. - * @param {*} value The value of the layout propery. Must be of a type appropriate for the property, as defined in the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/). + * @param {*} value The value of the layout property. Must be of a type appropriate for the property, as defined in the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/). * @param {Object} [options] * @param {boolean} [options.validate=true] Whether to check if `value` conforms to the Mapbox GL Style Specification. Disabling validation is a performance optimization that should only be used if you have previously validated the values you will be passing to this function. * @returns {Map} `this` * @example * map.setLayoutProperty('my-layer', 'visibility', 'none'); */ - setLayoutProperty(layer: string, name: string, value: any, options: StyleSetterOptions = {}) { - this.style.setLayoutProperty(layer, name, value, options); + setLayoutProperty(layerId: string, name: string, value: any, options: StyleSetterOptions = {}) { + this.style.setLayoutProperty(layerId, name, value, options); return this._update(true); } /** * Returns the value of a layout property in the specified style layer. * - * @param {string} layer The ID of the layer to get the layout property from. + * @param {string} layerId The ID of the layer to get the layout property from. * @param {string} name The name of the layout property to get. * @returns {*} The value of the specified layout property. */ - getLayoutProperty(layer: string, name: string) { - return this.style.getLayoutProperty(layer, name); + getLayoutProperty(layerId: string, name: string) { + return this.style.getLayoutProperty(layerId, name); } /** @@ -1547,10 +1613,11 @@ class Map extends Camera { } _setupPainter() { - const attributes = extend({ + const attributes = extend({}, isSupported.webGLContextAttributes, { failIfMajorPerformanceCaveat: this._failIfMajorPerformanceCaveat, - preserveDrawingBuffer: this._preserveDrawingBuffer - }, isSupported.webGLContextAttributes); + preserveDrawingBuffer: this._preserveDrawingBuffer, + antialias: this._antialias || false + }); const gl = this._canvas.getContext('webgl', attributes) || this._canvas.getContext('experimental-webgl', attributes); diff --git a/src/ui/marker.js b/src/ui/marker.js index 2d65e484d6f..68c88d0384b 100644 --- a/src/ui/marker.js +++ b/src/ui/marker.js @@ -79,6 +79,7 @@ export default class Marker extends Evented { // create default map marker SVG const svg = DOM.createNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttributeNS(null, 'display', 'block'); svg.setAttributeNS(null, 'height', '41px'); svg.setAttributeNS(null, 'width', '27px'); svg.setAttributeNS(null, 'viewBox', '0 0 27 41'); @@ -181,6 +182,10 @@ export default class Marker extends Evented { } this._element.classList.add('mapboxgl-marker'); + this._element.addEventListener('dragstart', (e: DragEvent) => { + e.preventDefault(); + }); + applyAnchorClass(this._element, this._anchor, 'marker'); this._popup = null; } @@ -345,7 +350,6 @@ export default class Marker extends Evented { } DOM.setTransform(this._element, `${anchorTranslate[this._anchor]} translate(${this._pos.x}px, ${this._pos.y}px)`); - applyAnchorClass(this._element, this._anchor, 'marker'); } /** diff --git a/src/ui/popup.js b/src/ui/popup.js index 44fd0261250..bfa7319ea48 100644 --- a/src/ui/popup.js +++ b/src/ui/popup.js @@ -16,7 +16,8 @@ import type {PointLike} from '@mapbox/point-geometry'; const defaultOptions = { closeButton: true, closeOnClick: true, - className: '' + className: '', + maxWidth: "240px" }; export type Offset = number | PointLike | {[Anchor]: PointLike}; @@ -26,7 +27,8 @@ export type PopupOptions = { closeOnClick?: boolean, anchor?: Anchor, offset?: Offset, - className?: string + className?: string, + maxWidth?: string }; /** @@ -50,6 +52,7 @@ export type PopupOptions = { * - an object of {@link Point}s specifing an offset for each anchor position * Negative offsets indicate left and up. * @param {string} [options.className] Space-separated CSS class names to add to popup container + * @param {string} [options.maxWidth] A string that sets the CSS property of the popup's maxWidth in pixels, eg "300px" * @example * var markerHeight = 50, markerRadius = 10, linearOffset = 25; * var popupOffsets = { @@ -65,6 +68,7 @@ export type PopupOptions = { * var popup = new mapboxgl.Popup({offset: popupOffsets, className: 'my-class'}) * .setLngLat(e.lngLat) * .setHTML("

Hello World!

") + * .setMaxWidth("300px") * .addTo(map); * @see [Display a popup](https://www.mapbox.com/mapbox-gl-js/example/popup/) * @see [Display a popup on hover](https://www.mapbox.com/mapbox-gl-js/example/popup-on-hover/) @@ -231,6 +235,27 @@ export default class Popup extends Evented { return this.setDOMContent(frag); } + /** + * Returns the popup's max width. + * + * @returns {string} The max width of the popup. + */ + getMaxWidth() { + return this._container.style.maxWidth; + } + + /** + * Sets the popup's max width. This is setting the CSS property maxWidth. It expects a string in "Npx" format, where N is some number. + * + * @param maxWidth A string representing the pixel value for the maximum width. + * @returns {Popup} `this` + */ + setMaxWidth(maxWidth: string) { + this.options.maxWidth = maxWidth; + this._update(); + return this; + } + /** * Sets the popup's content to the element provided as a DOM node. * @@ -275,13 +300,16 @@ export default class Popup extends Evented { this._container = DOM.create('div', 'mapboxgl-popup', this._map.getContainer()); this._tip = DOM.create('div', 'mapboxgl-popup-tip', this._container); this._container.appendChild(this._content); - if (this.options.className) { this.options.className.split(' ').forEach(name => this._container.classList.add(name)); } } + if (this.options.maxWidth && this._container.style.maxWidth !== this.options.maxWidth) { + this._container.style.maxWidth = this.options.maxWidth; + } + if (this._map.transform.renderWorldCopies) { this._lngLat = smartWrap(this._lngLat, this._pos, this._map.transform); } diff --git a/src/util/actor.js b/src/util/actor.js index e663f5e261a..edeb8b53e70 100644 --- a/src/util/actor.js +++ b/src/util/actor.js @@ -102,7 +102,7 @@ class Actor { if (cancelable && this.callbacks[data.id] === null) { // Only add the cancelable callback if the done callback wasn't already called. // Otherwise we will never be able to delete it. - this.callbacks[data.id] = cancelable; + this.callbacks[data.id] = cancelable.cancel; } } else if (typeof data.id !== 'undefined' && this.parent.getWorkerSource) { // data.type == sourcetype.method diff --git a/src/util/ajax.js b/src/util/ajax.js index dff48a7294c..086cefe0f7c 100644 --- a/src/util/ajax.js +++ b/src/util/ajax.js @@ -165,10 +165,12 @@ export const makeRequest = function(requestParameters: RequestParameters, callba // We're trying to use the Fetch API if possible. However, in some situations we can't use it: // - IE11 doesn't support it at all. In this case, we dispatch the request to the main thread so // that we can get an accruate referrer header. + // - Safari exposes window.AbortController, but it doesn't work actually abort any requests in + // some versions (see https://bugs.webkit.org/show_bug.cgi?id=174980#c2) // - Requests for resources with the file:// URI scheme don't work with the Fetch API either. In // this case we unconditionally use XHR on the current thread since referrers don't matter. if (!/^file:/.test(requestParameters.url)) { - if (window.fetch && window.Request && window.AbortController) { + if (window.fetch && window.Request && window.AbortController && window.Request.prototype.hasOwnProperty('signal')) { return makeFetchRequest(requestParameters, callback); } if (isWorker() && self.worker && self.worker.actor) { diff --git a/src/util/browser.js b/src/util/browser.js index 70036884a76..ec18d8f6fba 100755 --- a/src/util/browser.js +++ b/src/util/browser.js @@ -17,6 +17,8 @@ const cancel = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame; +let linkEl; + /** * @private */ @@ -45,9 +47,9 @@ const exported = { }, resolveURL(path: string) { - const a = window.document.createElement('a'); - a.href = path; - return a.href; + if (!linkEl) linkEl = window.document.createElement('a'); + linkEl.href = path; + return linkEl.href; }, hardwareConcurrency: window.navigator.hardwareConcurrency || 4, diff --git a/src/util/classify_rings.js b/src/util/classify_rings.js index 55ce3ba4404..90a32fceada 100644 --- a/src/util/classify_rings.js +++ b/src/util/classify_rings.js @@ -34,7 +34,7 @@ export default function classifyRings(rings: Array>, maxRings: numb } if (polygon) polygons.push(polygon); - // Earcut performance degrages with the # of rings in a polygon. For this + // Earcut performance degrades with the # of rings in a polygon. For this // reason, we limit strip out all but the `maxRings` largest rings. if (maxRings > 1) { for (let j = 0; j < polygons.length; j++) { diff --git a/src/util/image.js b/src/util/image.js index 2e356bfe4c2..fd3a4395ae2 100644 --- a/src/util/image.js +++ b/src/util/image.js @@ -115,6 +115,14 @@ export class RGBAImage { resizeImage(this, size, 4); } + replace(data: Uint8Array | Uint8ClampedArray, copy?: boolean) { + if (copy) { + this.data.set(data); + } else { + this.data = data; + } + } + clone() { return new RGBAImage({width: this.width, height: this.height}, new Uint8Array(this.data)); } diff --git a/test/expected/text-shaping-default.json b/test/expected/text-shaping-default.json index 4ba26796ccf..c682db02896 100644 --- a/test/expected/text-shaping-default.json +++ b/test/expected/text-shaping-default.json @@ -46,5 +46,6 @@ "bottom": 12, "left": -32.5, "right": 32.5, - "writingMode": 1 + "writingMode": 1, + "lineCount": 1 } diff --git a/test/expected/text-shaping-linebreak.json b/test/expected/text-shaping-linebreak.json index 2be83dac03a..0739d684711 100644 --- a/test/expected/text-shaping-linebreak.json +++ b/test/expected/text-shaping-linebreak.json @@ -86,5 +86,6 @@ "bottom": 24, "left": -32.5, "right": 32.5, - "writingMode": 1 + "writingMode": 1, + "lineCount": 2 } diff --git a/test/expected/text-shaping-newline.json b/test/expected/text-shaping-newline.json index 977e3a5f42e..8c0bdc2197b 100644 --- a/test/expected/text-shaping-newline.json +++ b/test/expected/text-shaping-newline.json @@ -86,5 +86,6 @@ "bottom": 24, "left": -32.5, "right": 32.5, - "writingMode": 1 + "writingMode": 1, + "lineCount": 2 } diff --git a/test/expected/text-shaping-newlines-in-middle.json b/test/expected/text-shaping-newlines-in-middle.json index 8a22ba5c720..fc0c28e9769 100644 --- a/test/expected/text-shaping-newlines-in-middle.json +++ b/test/expected/text-shaping-newlines-in-middle.json @@ -86,5 +86,6 @@ "bottom": 36, "left": -32.5, "right": 32.5, - "writingMode": 1 + "writingMode": 1, + "lineCount": 3 } diff --git a/test/expected/text-shaping-null.json b/test/expected/text-shaping-null.json index 242ef1c7a9d..b54d9a56abb 100644 --- a/test/expected/text-shaping-null.json +++ b/test/expected/text-shaping-null.json @@ -22,5 +22,6 @@ "bottom": 12, "left": -10, "right": 10, - "writingMode": 1 + "writingMode": 1, + "lineCount": 1 } diff --git a/test/expected/text-shaping-spacing.json b/test/expected/text-shaping-spacing.json index 5e8872e0f6f..b65ce97d03d 100644 --- a/test/expected/text-shaping-spacing.json +++ b/test/expected/text-shaping-spacing.json @@ -46,5 +46,6 @@ "bottom": 12, "left": -38.5, "right": 38.5, - "writingMode": 1 + "writingMode": 1, + "lineCount": 1 } diff --git a/test/ignores.json b/test/ignores.json index ab5dfad74d0..4c970fe041e 100644 --- a/test/ignores.json +++ b/test/ignores.json @@ -12,5 +12,13 @@ "render-tests/regressions/mapbox-gl-js#3682": "skip - true", "render-tests/runtime-styling/image-update-icon": "skip - https://github.com/mapbox/mapbox-gl-js/issues/4804", "render-tests/runtime-styling/image-update-pattern": "skip - https://github.com/mapbox/mapbox-gl-js/issues/4804", - "render-tests/mixed-zoom/z10-z11": "current behavior conflicts with https://github.com/mapbox/mapbox-gl-js/pull/6803. can be fixed when https://github.com/mapbox/api-maps/issues/1480 is done" + "render-tests/mixed-zoom/z10-z11": "current behavior conflicts with https://github.com/mapbox/mapbox-gl-js/pull/6803. can be fixed when https://github.com/mapbox/api-maps/issues/1480 is done", + "render-tests/fill-extrusion-pattern/tile-buffer": "https://github.com/mapbox/mapbox-gl-js/issues/4403", + "render-tests/runtime-styling/paint-property-overriden-default-to-expression": "skip - https://github.com/mapbox/mapbox-gl-js/issues/8045", + "render-tests/runtime-styling/paint-property-overriden-default-to-literal": "skip - https://github.com/mapbox/mapbox-gl-js/issues/8045", + "render-tests/runtime-styling/paint-property-overriden-expression-to-literal": "skip - https://github.com/mapbox/mapbox-gl-js/issues/8045", + "render-tests/text-field/formatted-text-color-overrides": "skip - https://github.com/mapbox/mapbox-gl-js/issues/8045", + "render-tests/text-field/formatted-text-color": "skip - https://github.com/mapbox/mapbox-gl-js/issues/8045", + "render-tests/runtime-styling/layout-property-override-paint-property-expression": "skip - https://github.com/mapbox/mapbox-gl-js/issues/8045", + "render-tests/runtime-styling/layout-property-override-paint-property-literal": "skip - https://github.com/mapbox/mapbox-gl-js/issues/8045" } diff --git a/test/integration/expression-tests/result_item.html.tmpl b/test/integration/expression-tests/result_item.html.tmpl index 63e6daa257a..c975529605f 100644 --- a/test/integration/expression-tests/result_item.html.tmpl +++ b/test/integration/expression-tests/result_item.html.tmpl @@ -1,22 +1,16 @@ - - -

 

-
<%- r.expression %>
- - -

<%- r.id %> <% if (!r.ok) { %>(<%=r.status%>)<% } %>

- <% if (r.error) { %>
error: <%- r.error.message %>
<% } %> -
<%= r.difference %>
- - -

 

-
-<% if (r.serialized) { %> - Serialized: -
-<%- r.serialized %>
-            
-<% } %> -
- - +
+

<%- r.status %> <%- r.id %>

+
<%- r.expression %>
+ + <% if (r.error) { %>

Error: <%- r.error.message %>

<% } %> + + <% if (r.difference) { %> + Difference: +
<%- r.difference %>
+ <% } %> + + <% if (r.serialized) { %> + Serialized: +
<%- r.serialized %>
+ <% } %> +
diff --git a/test/integration/image/1.png b/test/integration/image/1.png new file mode 100644 index 00000000000..d319b4de66a Binary files /dev/null and b/test/integration/image/1.png differ diff --git a/test/integration/lib/harness.js b/test/integration/lib/harness.js index 89d088902c1..9b248413ada 100644 --- a/test/integration/lib/harness.js +++ b/test/integration/lib/harness.js @@ -179,10 +179,15 @@ export default function (directory, implementation, options, run) { const resultsTemplate = template(fs.readFileSync(path.join(__dirname, '..', 'results.html.tmpl'), 'utf8')); const itemTemplate = template(fs.readFileSync(path.join(directory, 'result_item.html.tmpl'), 'utf8')); + const stats = {}; + for (const test of tests) { + stats[test.status] = (stats[test.status] || 0) + 1; + } + const unsuccessful = tests.filter(test => test.status === 'failed' || test.status === 'errored'); - const resultsShell = resultsTemplate({ unsuccessful, tests, shuffle: options.shuffle, seed: options.seed }) + const resultsShell = resultsTemplate({ unsuccessful, tests, stats, shuffle: options.shuffle, seed: options.seed }) .split(''); const p = path.join(directory, options.recycleMap ? 'index-recycle-map.html' : 'index.html'); diff --git a/test/integration/lib/render.js b/test/integration/lib/render.js index cbfb11bd06a..77117fd4707 100644 --- a/test/integration/lib/render.js +++ b/test/integration/lib/render.js @@ -5,45 +5,6 @@ import harness from './harness'; import pixelmatch from 'pixelmatch'; import * as glob from 'glob'; -function compare(actualPath, expectedPaths, diffPath, callback) { - - const actualImg = fs.createReadStream(actualPath).pipe(new PNG()).on('parsed', doneReading); - - const expectedImgs = []; - for (const path of expectedPaths) { - expectedImgs.push(fs.createReadStream(path).pipe(new PNG()).on('parsed', doneReading)); - } - - let read = 0; - - function doneReading() { - if (++read < expectedPaths.length + 1) return; - - // if we have multiple expected images, we'll compare against each one and pick the one with - // the least amount of difference; this is useful for covering features that render differently - // depending on platform, i.e. heatmaps use half-float textures for improved rendering where supported - - let minNumPixels = Infinity; - let minDiff, minIndex; - - for (let i = 0; i < expectedImgs.length; i++) { - const diff = new PNG({width: actualImg.width, height: actualImg.height}); - const numPixels = pixelmatch(actualImg.data, expectedImgs[i].data, - diff.data, actualImg.width, actualImg.height, {threshold: 0.13}); - - if (numPixels < minNumPixels) { - minNumPixels = numPixels; - minDiff = diff; - minIndex = i; - } - } - - minDiff.pack().pipe(fs.createWriteStream(diffPath)).on('finish', () => { - callback(null, minNumPixels / (minDiff.width * minDiff.height), expectedPaths[minIndex]); - }); - } -} - /** * Run the render test suite, compute differences to expected values (making exceptions based on * implementation vagaries), print results to standard output, write test artifacts to the @@ -127,18 +88,17 @@ export function run(implementation, ignores, render) { try { stats = fs.statSync(dir, fs.R_OK | fs.W_OK); if (!stats.isDirectory()) throw new Error(); - } catch (e) { + } catch (e) { fs.mkdirSync(dir); } - const expected = path.join(dir, 'expected.png'); - const actual = path.join(dir, 'actual.png'); - const diff = path.join(dir, 'diff.png'); + const expectedPath = path.join(dir, 'expected.png'); + const actualPath = path.join(dir, 'actual.png'); + const diffPath = path.join(dir, 'diff.png'); - const png = new PNG({ - width: Math.floor(params.width * params.pixelRatio), - height: Math.floor(params.height * params.pixelRatio) - }); + const width = Math.floor(params.width * params.pixelRatio); + const height = Math.floor(params.height * params.pixelRatio); + const actualImg = new PNG({width, height}); // PNG data must be unassociated (not premultiplied) for (let i = 0; i < data.length; i++) { @@ -149,8 +109,7 @@ export function run(implementation, ignores, render) { data[i * 4 + 2] /= a; } } - - png.data = data; + actualImg.data = data; // there may be multiple expected images, covering different platforms const expectedPaths = glob.sync(path.join(dir, 'expected*.png')); @@ -160,27 +119,46 @@ export function run(implementation, ignores, render) { } if (process.env.UPDATE) { - png.pack() - .pipe(fs.createWriteStream(expected)) - .on('finish', done); + fs.writeFileSync(expectedPath, PNG.sync.write(actualImg)); + } else { - png.pack() - .pipe(fs.createWriteStream(actual)) - .on('finish', () => { - compare(actual, expectedPaths, diff, (err, difference, expected) => { - if (err) return done(err); - - params.difference = difference; - params.ok = difference <= params.allowed; - - params.actual = fs.readFileSync(actual).toString('base64'); - params.expected = fs.readFileSync(expected).toString('base64'); - params.diff = fs.readFileSync(diff).toString('base64'); - - done(); - }); - }); + // if we have multiple expected images, we'll compare against each one and pick the one with + // the least amount of difference; this is useful for covering features that render differently + // depending on platform, i.e. heatmaps use half-float textures for improved rendering where supported + let minDiff = Infinity; + let minDiffImg, minExpectedBuf; + + for (const path of expectedPaths) { + const expectedBuf = fs.readFileSync(path); + const expectedImg = PNG.sync.read(expectedBuf); + const diffImg = new PNG({width, height}); + + const diff = pixelmatch( + actualImg.data, expectedImg.data, diffImg.data, + width, height, {threshold: 0.13}) / (width * height); + + if (diff < minDiff) { + minDiff = diff; + minDiffImg = diffImg; + minExpectedBuf = expectedBuf; + } + } + + const diffBuf = PNG.sync.write(minDiffImg, {filterType: 4}); + const actualBuf = PNG.sync.write(actualImg, {filterType: 4}); + + fs.writeFileSync(diffPath, diffBuf); + fs.writeFileSync(actualPath, actualBuf); + + params.difference = minDiff; + params.ok = minDiff <= params.allowed; + + params.actual = actualBuf.toString('base64'); + params.expected = minExpectedBuf.toString('base64'); + params.diff = diffBuf.toString('base64'); } + + done(); }); }); } diff --git a/test/integration/query-tests/result_item.html.tmpl b/test/integration/query-tests/result_item.html.tmpl index bef44bd50e9..cd3a5d80867 100644 --- a/test/integration/query-tests/result_item.html.tmpl +++ b/test/integration/query-tests/result_item.html.tmpl @@ -1,17 +1,10 @@ - - - <% if (r.status !== 'errored') { %><% } %> - - -

<%- r.id %> <% if (!r.ok) { %>(<%=r.status%>)<% } %>

-
    - <% if (r.error) { %>
  • error: <%- r.error.message %>
  • <% } %> -
  • diff: <%- r.difference %>
  • -
  • zoom: <%- r.zoom %>
  • -
  • center: <%- r.center %>
  • -
  • bearing: <%- r.bearing %>
  • -
  • width: <%- r.width %>
  • -
  • height: <%- r.height %>
  • -
- - +
+

<%- r.status %> <%- r.id %>

+ <% if (r.status !== 'errored') { %> + + <% } %> + <% if (r.error) { %>

Error: <%- r.error.message %>

<% } %> + <% if (r.difference) { %> +
<%- r.difference.trim() %>
+ <% } %> +
diff --git a/test/integration/render-tests/canvas/update/expected.png b/test/integration/render-tests/canvas/update/expected.png new file mode 100644 index 00000000000..f042d98788b Binary files /dev/null and b/test/integration/render-tests/canvas/update/expected.png differ diff --git a/test/integration/render-tests/canvas/update/style.json b/test/integration/render-tests/canvas/update/style.json new file mode 100644 index 00000000000..680adeaff81 --- /dev/null +++ b/test/integration/render-tests/canvas/update/style.json @@ -0,0 +1,57 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 64, + "height": 64, + "addFakeCanvas": { + "id": "fake-canvas", + "image": "./image/0.png" + }, + "operations": [ + ["wait"], + ["updateFakeCanvas", "canvas", "./image/1.png", "./image/0.png"] + ] + } + }, + "center": [ + -122.514426, + 37.562984 + ], + "zoom": 14, + "sources": { + "canvas": { + "type": "canvas", + "animate": false, + "coordinates": [ + [ + -122.51596391201019, + 37.56238816766053 + ], + [ + -122.51467645168304, + 37.56410183312965 + ], + [ + -122.51309394836426, + 37.563391708549425 + ], + [ + -122.51423120498657, + 37.56161849366671 + ] + ], + "canvas": "fake-canvas" + } + }, + "layers": [ + { + "id": "canvas", + "type": "raster", + "source": "canvas", + "paint": { + "raster-fade-duration": 0 + } + } + ] +} diff --git a/test/integration/render-tests/custom-layer-js/tent-3d/expected.png b/test/integration/render-tests/custom-layer-js/tent-3d/expected.png index c6ee90d6690..cae223d5c02 100644 Binary files a/test/integration/render-tests/custom-layer-js/tent-3d/expected.png and b/test/integration/render-tests/custom-layer-js/tent-3d/expected.png differ diff --git a/test/integration/render-tests/debug/tile/expected.png b/test/integration/render-tests/debug/tile/expected.png index b047d9a6feb..03993d0c483 100644 Binary files a/test/integration/render-tests/debug/tile/expected.png and b/test/integration/render-tests/debug/tile/expected.png differ diff --git a/test/integration/render-tests/debug/tile/style.json b/test/integration/render-tests/debug/tile/style.json index 5eb5388d2ec..cd2240afff3 100644 --- a/test/integration/render-tests/debug/tile/style.json +++ b/test/integration/render-tests/debug/tile/style.json @@ -7,8 +7,8 @@ } }, "center": [ - 13.418056, - 52.499167 + 13.425481, + 52.496057 ], "zoom": 14, "sources": { @@ -49,4 +49,4 @@ } } ] -} \ No newline at end of file +} diff --git a/test/integration/render-tests/fill-extrusion-geometry/linestring/expected.png b/test/integration/render-tests/fill-extrusion-geometry/linestring/expected.png new file mode 100644 index 00000000000..c779eb413f3 Binary files /dev/null and b/test/integration/render-tests/fill-extrusion-geometry/linestring/expected.png differ diff --git a/test/integration/render-tests/fill-extrusion-geometry/linestring/style.json b/test/integration/render-tests/fill-extrusion-geometry/linestring/style.json new file mode 100644 index 00000000000..b90ae6f2704 --- /dev/null +++ b/test/integration/render-tests/fill-extrusion-geometry/linestring/style.json @@ -0,0 +1,91 @@ +{ + "version": 8, + "metadata": { + "test": { + "width" : 32, + "height": 128 + } + }, + "sources": { + "geojson": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [ + -0.0003, + -0.0003 + ], + [ + -0.0003, + 0.0003 + ], + [ + 0.000, + 0.0003 + ], + [ + 0.000, + -0.0003 + ], + [ + -0.0003, + -0.0003 + ] + ] + ] + } + }, + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -0.000, + -0.0003 + ], + [ + -0.000, + 0.0003 + ], + [ + 0.0003, + 0.0003 + ], + [ + 0.0003, + -0.0003 + ], + [ + -0.0003, + -0.0003 + ] + ] + ] + } + } + ] + } + } + }, + "pitch": 0, + "zoom": 15, + "layers": [ + { + "id": "extrusion", + "type": "fill-extrusion", + "source": "geojson", + "paint": { + "fill-extrusion-height": 0 + } + } + ] +} diff --git a/test/integration/render-tests/fill-extrusion-pattern/@2x/expected.png b/test/integration/render-tests/fill-extrusion-pattern/@2x/expected.png index c7bdf3b886e..2994ade87fc 100644 Binary files a/test/integration/render-tests/fill-extrusion-pattern/@2x/expected.png and b/test/integration/render-tests/fill-extrusion-pattern/@2x/expected.png differ diff --git a/test/integration/render-tests/fill-extrusion-pattern/@2x/style.json b/test/integration/render-tests/fill-extrusion-pattern/@2x/style.json index d68b7d32b03..91ff69322a3 100644 --- a/test/integration/render-tests/fill-extrusion-pattern/@2x/style.json +++ b/test/integration/render-tests/fill-extrusion-pattern/@2x/style.json @@ -9,6 +9,7 @@ "sources": { "geojson": { "type": "geojson", + "buffer": 0, "data": { "type": "FeatureCollection", "features": [ @@ -96,4 +97,4 @@ } } ] -} \ No newline at end of file +} diff --git a/test/integration/render-tests/fill-extrusion-pattern/feature-expression/expected.png b/test/integration/render-tests/fill-extrusion-pattern/feature-expression/expected.png index aa2ef97b9d5..d7573106f76 100644 Binary files a/test/integration/render-tests/fill-extrusion-pattern/feature-expression/expected.png and b/test/integration/render-tests/fill-extrusion-pattern/feature-expression/expected.png differ diff --git a/test/integration/render-tests/fill-extrusion-pattern/feature-expression/style.json b/test/integration/render-tests/fill-extrusion-pattern/feature-expression/style.json index 360934bf306..8e408e81f55 100644 --- a/test/integration/render-tests/fill-extrusion-pattern/feature-expression/style.json +++ b/test/integration/render-tests/fill-extrusion-pattern/feature-expression/style.json @@ -8,6 +8,7 @@ "sources": { "geojson": { "type": "geojson", + "buffer": 0, "data": { "type": "FeatureCollection", "features": [ diff --git a/test/integration/render-tests/fill-extrusion-pattern/function-2/expected.png b/test/integration/render-tests/fill-extrusion-pattern/function-2/expected.png index 367f73f7545..cd86e8dccfe 100644 Binary files a/test/integration/render-tests/fill-extrusion-pattern/function-2/expected.png and b/test/integration/render-tests/fill-extrusion-pattern/function-2/expected.png differ diff --git a/test/integration/render-tests/fill-extrusion-pattern/function-2/style.json b/test/integration/render-tests/fill-extrusion-pattern/function-2/style.json index 3b51dc820f6..fcde2e7bab0 100644 --- a/test/integration/render-tests/fill-extrusion-pattern/function-2/style.json +++ b/test/integration/render-tests/fill-extrusion-pattern/function-2/style.json @@ -9,6 +9,7 @@ "sources": { "geojson": { "type": "geojson", + "buffer": 0, "data": { "type": "FeatureCollection", "features": [ diff --git a/test/integration/render-tests/fill-extrusion-pattern/function/expected.png b/test/integration/render-tests/fill-extrusion-pattern/function/expected.png index 753a82851c4..e60cd56c3a6 100644 Binary files a/test/integration/render-tests/fill-extrusion-pattern/function/expected.png and b/test/integration/render-tests/fill-extrusion-pattern/function/expected.png differ diff --git a/test/integration/render-tests/fill-extrusion-pattern/function/style.json b/test/integration/render-tests/fill-extrusion-pattern/function/style.json index 9849b8ae27a..8ff57ee9568 100644 --- a/test/integration/render-tests/fill-extrusion-pattern/function/style.json +++ b/test/integration/render-tests/fill-extrusion-pattern/function/style.json @@ -8,6 +8,7 @@ "sources": { "geojson": { "type": "geojson", + "buffer": 0, "data": { "type": "FeatureCollection", "features": [ @@ -107,4 +108,4 @@ } } ] -} \ No newline at end of file +} diff --git a/test/integration/render-tests/fill-extrusion-pattern/literal/expected.png b/test/integration/render-tests/fill-extrusion-pattern/literal/expected.png index 753a82851c4..8f4c7eb60d7 100644 Binary files a/test/integration/render-tests/fill-extrusion-pattern/literal/expected.png and b/test/integration/render-tests/fill-extrusion-pattern/literal/expected.png differ diff --git a/test/integration/render-tests/fill-extrusion-pattern/literal/style.json b/test/integration/render-tests/fill-extrusion-pattern/literal/style.json index 48abec51f93..39209caf993 100644 --- a/test/integration/render-tests/fill-extrusion-pattern/literal/style.json +++ b/test/integration/render-tests/fill-extrusion-pattern/literal/style.json @@ -8,6 +8,7 @@ "sources": { "geojson": { "type": "geojson", + "buffer": 0, "data": { "type": "FeatureCollection", "features": [ @@ -95,4 +96,4 @@ } } ] -} \ No newline at end of file +} diff --git a/test/integration/render-tests/fill-extrusion-pattern/opacity/expected.png b/test/integration/render-tests/fill-extrusion-pattern/opacity/expected.png index 09f7eb3e18d..31f8fb76e34 100644 Binary files a/test/integration/render-tests/fill-extrusion-pattern/opacity/expected.png and b/test/integration/render-tests/fill-extrusion-pattern/opacity/expected.png differ diff --git a/test/integration/render-tests/fill-extrusion-pattern/opacity/style.json b/test/integration/render-tests/fill-extrusion-pattern/opacity/style.json index f8694f44428..f0435da36db 100644 --- a/test/integration/render-tests/fill-extrusion-pattern/opacity/style.json +++ b/test/integration/render-tests/fill-extrusion-pattern/opacity/style.json @@ -8,6 +8,7 @@ "sources": { "geojson": { "type": "geojson", + "buffer": 0, "data": { "type": "FeatureCollection", "features": [ @@ -96,4 +97,4 @@ } } ] -} \ No newline at end of file +} diff --git a/test/integration/render-tests/fill-extrusion-pattern/tile-buffer/expected.png b/test/integration/render-tests/fill-extrusion-pattern/tile-buffer/expected.png new file mode 100644 index 00000000000..8b08b54ea97 Binary files /dev/null and b/test/integration/render-tests/fill-extrusion-pattern/tile-buffer/expected.png differ diff --git a/test/integration/render-tests/fill-extrusion-pattern/tile-buffer/style.json b/test/integration/render-tests/fill-extrusion-pattern/tile-buffer/style.json new file mode 100644 index 00000000000..dd60969401c --- /dev/null +++ b/test/integration/render-tests/fill-extrusion-pattern/tile-buffer/style.json @@ -0,0 +1,98 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256 + } + }, + "sources": { + "geojson": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "property": 20 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -0.0004, + 0 + ], + [ + -0.0002, + 0.0002 + ], + [ + 0, + 0 + ], + [ + -0.0002, + -0.0002 + ], + [ + -0.0004, + 0 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "property": 20 + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + 0, + -0.0002 + ], + [ + 0, + 0.0002 + ], + [ + 0.0003, + 0.0002 + ], + [ + 0.0003, + -0.0002 + ], + [ + 0, + -0.0002 + ] + ] + ] + } + } + ] + } + } + }, + "sprite": "local://sprites/emerald", + "pitch": 60, + "zoom": 18, + "layers": [ + { + "id": "extrusion", + "type": "fill-extrusion", + "source": "geojson", + "paint": { + "fill-extrusion-pattern": "generic_icon", + "fill-extrusion-height": 10 + } + } + ] +} diff --git a/test/integration/render-tests/regressions/mapbox-gl-js#8026/expected.png b/test/integration/render-tests/regressions/mapbox-gl-js#8026/expected.png new file mode 100644 index 00000000000..4cb77303dde Binary files /dev/null and b/test/integration/render-tests/regressions/mapbox-gl-js#8026/expected.png differ diff --git a/test/integration/render-tests/regressions/mapbox-gl-js#8026/style.json b/test/integration/render-tests/regressions/mapbox-gl-js#8026/style.json new file mode 100644 index 00000000000..b5790d49bb6 --- /dev/null +++ b/test/integration/render-tests/regressions/mapbox-gl-js#8026/style.json @@ -0,0 +1,81 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 64, + "height": 64, + "operations": [ + [ + "setFeatureState", + { + "source": "geojson", + "id": "1" + }, + { + "color": "red" + } + ], + [ + "wait" + ], + [ + "setZoom", 3 + ] + , + [ + "wait" + ], + [ + "removeFeatureState", + { + "source": "geojson" + } + ], + [ + "wait" + ], + [ + "setZoom", 2 + ], + [ + "wait" + ] + ] + } + }, + "zoom": 2, + "sources": { + "geojson": { + "type": "geojson", + "data": { + "type": "Feature", + "id": "1", + "geometry": { + "type": "Point", + "coordinates": [ + 0, + 0 + ] + } + } + } + }, + "layers": [ + { + "id": "circle", + "type": "circle", + "source": "geojson", + "paint": { + "circle-radius": 5, + "circle-color": [ + "coalesce", + [ + "feature-state", + "color" + ], + "black" + ] + } + } + ] +} \ No newline at end of file diff --git a/test/integration/render-tests/result_item.html.tmpl b/test/integration/render-tests/result_item.html.tmpl index cf34e43ce3b..cb4a544dff3 100644 --- a/test/integration/render-tests/result_item.html.tmpl +++ b/test/integration/render-tests/result_item.html.tmpl @@ -1,23 +1,8 @@ - - - -<% if (r.status !== 'errored') { %> - - -<% } else { %> - -<% } %> - -

<%- r.id %> <% if (!r.ok) { %>(<%=r.status%>)<% } %>

-
    - <% if (r.error) { %>
  • error: <%- r.error.message %>
  • <% } %> -
  • diff: <%- r.difference %>
  • - <% if (r.zoom) { %>
  • zoom: <%- r.zoom %>
  • <% } %> - <% if (r.center) { %>
  • center: <%- r.center %>
  • <% } %> - <% if (r.bearing) { %>
  • bearing: <%- r.bearing %>
  • <% } %> - <% if (r.pitch) { %>
  • pitch: <%- r.pitch %>
  • <% } %> -
  • width: <%- r.width %>
  • -
  • height: <%- r.height %>
  • -
- - +
+

<%- r.status %> <%- r.id %>

+ <% if (r.status !== 'errored') { %> + + <% } %> + <% if (r.error) { %>

Error: <%- r.error.message %>

<% } %> + <% if (r.difference) { %>

Diff: <%- r.difference %>

<% } %> +
diff --git a/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-expression/expected.png b/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-expression/expected.png new file mode 100644 index 00000000000..65504b23ad2 Binary files /dev/null and b/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-expression/expected.png differ diff --git a/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-expression/style.json b/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-expression/style.json new file mode 100644 index 00000000000..0ec02feab35 --- /dev/null +++ b/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-expression/style.json @@ -0,0 +1,66 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 64, + "width": 64, + "operations": [ + [ + "setLayoutProperty", + "text", + "text-field", + ["format", ["get", "name_en"], {"text-color": "#5F4B8B"}] + ], + [ + "wait" + ] + ] + } + }, + "transition": { + "duration": 0 + }, + "center": [ 0, 0 ], + "zoom": 0, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "name_en": "Ultra Violet", + "default_color": "hsl(0, 0%, 0%)" + }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": "{name_en}", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-size": 18, + "text-max-width": 1 + }, + "paint": { + "text-color": ["get", "default_color"] + } + } + ] +} diff --git a/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-literal/expected.png b/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-literal/expected.png new file mode 100644 index 00000000000..eee145e190c Binary files /dev/null and b/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-literal/expected.png differ diff --git a/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-literal/style.json b/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-literal/style.json new file mode 100644 index 00000000000..e7f75bbf901 --- /dev/null +++ b/test/integration/render-tests/runtime-styling/layout-property-override-paint-property-literal/style.json @@ -0,0 +1,65 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 64, + "width": 64, + "operations": [ + [ + "setLayoutProperty", + "text", + "text-field", + ["format", ["get", "name_en"], {"text-color": "#FA7268"}] + ], + [ + "wait" + ] + ] + } + }, + "transition": { + "duration": 0 + }, + "center": [ 0, 0 ], + "zoom": 0, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "name_en": "Living Coral" + }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": "{name_en}", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-size": 18, + "text-max-width": 1 + }, + "paint": { + "text-color": "hsl(0, 0%, 0%)" + } + } + ] +} diff --git a/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-expression/expected.png b/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-expression/expected.png new file mode 100644 index 00000000000..262d9e2ed21 Binary files /dev/null and b/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-expression/expected.png differ diff --git a/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-expression/style.json b/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-expression/style.json new file mode 100644 index 00000000000..f2db1738641 --- /dev/null +++ b/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-expression/style.json @@ -0,0 +1,65 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 64, + "width": 64, + "operations": [ + [ + "setPaintProperty", + "text", + "text-color", + ["get", "color"] + ], + [ + "wait" + ] + ] + } + }, + "transition": { + "duration": 0 + }, + "center": [ 0, 0 ], + "zoom": 0, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "color": "green" + }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": ["format", + "Blue", { "text-color": "blue" }, + "\n", {}, + "Green", {} + ], + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-size": 20 + } + } + ] +} diff --git a/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-literal/expected.png b/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-literal/expected.png new file mode 100644 index 00000000000..063ee2b6040 Binary files /dev/null and b/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-literal/expected.png differ diff --git a/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-literal/style.json b/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-literal/style.json new file mode 100644 index 00000000000..6cc9acd19e2 --- /dev/null +++ b/test/integration/render-tests/runtime-styling/paint-property-overriden-default-to-literal/style.json @@ -0,0 +1,62 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 64, + "width": 64, + "operations": [ + [ + "setPaintProperty", + "text", + "text-color", + "red" + ], + [ + "wait" + ] + ] + } + }, + "transition": { + "duration": 0 + }, + "center": [ 0, 0 ], + "zoom": 0, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": ["format", + "Blue", { "text-color": "blue" }, + "\n", {}, + "Red", {} + ], + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-size": 20 + } + } + ] +} diff --git a/test/integration/render-tests/runtime-styling/paint-property-overriden-expression-to-literal/expected.png b/test/integration/render-tests/runtime-styling/paint-property-overriden-expression-to-literal/expected.png new file mode 100644 index 00000000000..f9a9c369ebb Binary files /dev/null and b/test/integration/render-tests/runtime-styling/paint-property-overriden-expression-to-literal/expected.png differ diff --git a/test/integration/render-tests/runtime-styling/paint-property-overriden-expression-to-literal/style.json b/test/integration/render-tests/runtime-styling/paint-property-overriden-expression-to-literal/style.json new file mode 100644 index 00000000000..1f855a61795 --- /dev/null +++ b/test/integration/render-tests/runtime-styling/paint-property-overriden-expression-to-literal/style.json @@ -0,0 +1,68 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 64, + "width": 64, + "operations": [ + [ + "setPaintProperty", + "text", + "text-color", + "orange" + ], + [ + "wait" + ] + ] + } + }, + "transition": { + "duration": 0 + }, + "center": [ 0, 0 ], + "zoom": 0, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "color": "blue" + }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": ["format", + "Blue", { "text-color": "blue" }, + "\n", {}, + "Orange", {} + ], + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-size": 18 + }, + "paint": { + "text-color": ["get", "color"] + } + } + ] +} diff --git a/test/integration/render-tests/text-field/formatted-text-color-overrides/expected.png b/test/integration/render-tests/text-field/formatted-text-color-overrides/expected.png new file mode 100644 index 00000000000..a38c2d1a070 Binary files /dev/null and b/test/integration/render-tests/text-field/formatted-text-color-overrides/expected.png differ diff --git a/test/integration/render-tests/text-field/formatted-text-color-overrides/style.json b/test/integration/render-tests/text-field/formatted-text-color-overrides/style.json new file mode 100644 index 00000000000..7c9b5a5c802 --- /dev/null +++ b/test/integration/render-tests/text-field/formatted-text-color-overrides/style.json @@ -0,0 +1,51 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 64, + "width": 64 + } + }, + "center": [ 0, 0 ], + "zoom": 0, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": ["format", + "Color", { "text-color": "black" }, + "\n", {}, + "Turquoise", {} + ], + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-size": 12 + }, + "paint": { + "text-color": "turquoise" + } + } + ] +} diff --git a/test/integration/render-tests/text-field/formatted-text-color/expected.png b/test/integration/render-tests/text-field/formatted-text-color/expected.png new file mode 100644 index 00000000000..41c8bde1166 Binary files /dev/null and b/test/integration/render-tests/text-field/formatted-text-color/expected.png differ diff --git a/test/integration/render-tests/text-field/formatted-text-color/style.json b/test/integration/render-tests/text-field/formatted-text-color/style.json new file mode 100644 index 00000000000..38cd74424f7 --- /dev/null +++ b/test/integration/render-tests/text-field/formatted-text-color/style.json @@ -0,0 +1,55 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 128, + "width": 128 + } + }, + "center": [ 0, 0 ], + "zoom": 0, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "name": "Napoli", + "name_en": "Naples", + "name_color": "blue" + }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": ["format", + ["get", "name_en"], { "font-scale": 1.5, "text-color": "#009246" }, + "Italy", { "font-scale": 0.5, "text-color": "#ce2b37"} , + "\n", {}, + ["get", "name"], { "font-scale": 0.5, "text-color": ["get", "name_color"], "text-font": ["literal", [ "NotoCJK" ]] }, + "Italia", {} + ], + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-size": 20 + } + } + ] +} diff --git a/test/integration/render-tests/text-justify/auto/expected.png b/test/integration/render-tests/text-justify/auto/expected.png new file mode 100644 index 00000000000..a973bb9cfd7 Binary files /dev/null and b/test/integration/render-tests/text-justify/auto/expected.png differ diff --git a/test/integration/render-tests/text-justify/auto/style.json b/test/integration/render-tests/text-justify/auto/style.json new file mode 100644 index 00000000000..c35d4270497 --- /dev/null +++ b/test/integration/render-tests/text-justify/auto/style.json @@ -0,0 +1,115 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256, + "width": 256 + } + }, + "center": [ 0, 0 ], + "zoom": 2, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { "x": "bottom-right" }, + "geometry": { + "type": "Point", + "coordinates": [ -10, 10 ] + } + }, + { + "type": "Feature", + "properties": { "x": "bottom" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 10 ] + } + }, + { + "type": "Feature", + "properties": { "x": "bottom-left" }, + "geometry": { + "type": "Point", + "coordinates": [ 10, 10 ] + } + }, + { + "type": "Feature", + "properties": { "x": "right" }, + "geometry": { + "type": "Point", + "coordinates": [ -10, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "center" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "left" }, + "geometry": { + "type": "Point", + "coordinates": [ 10, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "top-right" }, + "geometry": { + "type": "Point", + "coordinates": [ -10, -10 ] + } + }, + { + "type": "Feature", + "properties": { "x": "top" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, -10 ] + } + }, + { + "type": "Feature", + "properties": { "x": "top-left" }, + "geometry": { + "type": "Point", + "coordinates": [ 10, -10 ] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": "Justified Text", + "text-max-width": 5, + "text-anchor": { + "type": "identity", + "property": "x" + }, + "text-justify": "auto", + "text-allow-overlap": true, + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ] + } + } + ] +} diff --git a/test/integration/render-tests/text-radial-offset/basic/expected.png b/test/integration/render-tests/text-radial-offset/basic/expected.png new file mode 100644 index 00000000000..2eea3af04c3 Binary files /dev/null and b/test/integration/render-tests/text-radial-offset/basic/expected.png differ diff --git a/test/integration/render-tests/text-radial-offset/basic/style.json b/test/integration/render-tests/text-radial-offset/basic/style.json new file mode 100644 index 00000000000..2e762ebe3f0 --- /dev/null +++ b/test/integration/render-tests/text-radial-offset/basic/style.json @@ -0,0 +1,134 @@ +{ + "version": 8, + "metadata": { + "test": { + "description": "For radial offsets, we try to make the distance from the anchor to the first pixels of the text even in all positions. But we don't actually know where the pixels in the glyph are, so we approximate based on where we think the baseline of the glyph is. The circle in this test is a way to check that our approximation works visually.", + "height": 256, + "width": 256 + } + }, + "center": [ 0, 0 ], + "zoom": 0, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { "x": "bottom-right" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "bottom" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "bottom-left" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "right" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "center" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "left" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "top-right" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "top" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "properties": { "x": "top-left" }, + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "circle", + "type": "circle", + "source": "point", + "paint": { + "circle-radius": 40, + "circle-color": "aqua", + "circle-translate": [0, 4] + } + }, + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": "x", + "text-size": 40, + "text-anchor": { + "type": "identity", + "property": "x" + }, + "text-radial-offset": 1, + "text-allow-overlap": true, + "text-padding": 0, + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ] + } + } + ] +} diff --git a/test/integration/render-tests/text-variable-anchor/all-anchors-offset/expected.png b/test/integration/render-tests/text-variable-anchor/all-anchors-offset/expected.png new file mode 100644 index 00000000000..a820ca32692 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/all-anchors-offset/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/all-anchors-offset/style.json b/test/integration/render-tests/text-variable-anchor/all-anchors-offset/style.json new file mode 100644 index 00000000000..254adef41cf --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/all-anchors-offset/style.json @@ -0,0 +1,121 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256, + "width": 256 + } + }, + "center": [ 0, 0 ], + "zoom": 0, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + }, + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ 0, 0 ] + } + } + ] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": "x", + "text-size": 20, + "text-justify": "auto", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ], + "text-radial-offset": 1.5, + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ] + } + }, + { + "id": "anchor", + "type": "circle", + "source": "point", + "paint" :{ + "circle-radius": 2 + } + } + ] +} diff --git a/test/integration/render-tests/text-variable-anchor/all-anchors/expected.png b/test/integration/render-tests/text-variable-anchor/all-anchors/expected.png new file mode 100644 index 00000000000..ff745f4b6ab Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/all-anchors/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/all-anchors/style.json b/test/integration/render-tests/text-variable-anchor/all-anchors/style.json new file mode 100644 index 00000000000..1b59ab11477 --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/all-anchors/style.json @@ -0,0 +1,63 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256 + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "layout": { + "text-field": "Test Test Test", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 5, + "text-justify": "auto", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ] + } + }] +} diff --git a/test/integration/render-tests/text-variable-anchor/icon-image-all-anchors/expected.png b/test/integration/render-tests/text-variable-anchor/icon-image-all-anchors/expected.png new file mode 100644 index 00000000000..d34b633c084 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/icon-image-all-anchors/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/icon-image-all-anchors/style.json b/test/integration/render-tests/text-variable-anchor/icon-image-all-anchors/style.json new file mode 100644 index 00000000000..ad9f14b2cc7 --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/icon-image-all-anchors/style.json @@ -0,0 +1,74 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 128, + "width": 128 + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "sources": { + "geojson": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "image": "bank-12" + }, + "geometry": { + "type": "Point", + "coordinates": [ + 0, + -10 + ] + } + }, + { + "type": "Feature", + "properties": { + "image": "bakery-12" + }, + "geometry": { + "type": "Point", + "coordinates": [ + 0, + 10 + ] + } + } + ] + } + } + }, + "sprite": "local://sprites/sprite", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "geojson", + "layout": { + "icon-image": ["get", "image"], + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-justify": "auto", + "text-variable-anchor" : [ + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ], + "text-radial-offset": 0.5, + "text-field": ["get", "image"] + } + } + ] +} diff --git a/test/integration/render-tests/text-variable-anchor/icon-image/expected.png b/test/integration/render-tests/text-variable-anchor/icon-image/expected.png new file mode 100644 index 00000000000..6838e331d53 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/icon-image/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/icon-image/style.json b/test/integration/render-tests/text-variable-anchor/icon-image/style.json new file mode 100644 index 00000000000..453f579a7b9 --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/icon-image/style.json @@ -0,0 +1,65 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 128, + "width": 128 + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "sources": { + "geojson": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "image": "bank-12" + }, + "geometry": { + "type": "Point", + "coordinates": [ + 0, + -10 + ] + } + }, + { + "type": "Feature", + "properties": { + "image": "bakery-12" + }, + "geometry": { + "type": "Point", + "coordinates": [ + 0, + 10 + ] + } + } + ] + } + } + }, + "sprite": "local://sprites/sprite", + "layers": [ + { + "id": "text", + "type": "symbol", + "source": "geojson", + "layout": { + "icon-image": ["get", "image"], + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-justify": "auto", + "text-variable-anchor" : ["top-left", "bottom-right"], + "text-radial-offset": 0.5, + "text-field": ["get", "image"] + } + } + ] +} diff --git a/test/integration/render-tests/text-variable-anchor/no-animate-zoom/expected.png b/test/integration/render-tests/text-variable-anchor/no-animate-zoom/expected.png new file mode 100644 index 00000000000..510aedcc7b8 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/no-animate-zoom/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/no-animate-zoom/style.json b/test/integration/render-tests/text-variable-anchor/no-animate-zoom/style.json new file mode 100644 index 00000000000..8c2e9f85513 --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/no-animate-zoom/style.json @@ -0,0 +1,90 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256, + "width": 256, + "fadeDuration": 100, + "description": "Start with space for two labels. Zoom out so that second has to switch anchors. Render after half a fade duration, but verify that label has moved the whole way.", + "operations": [ + ["wait", 100], + ["wait", 100], + ["setZoom", 0.5], + ["wait"], + ["wait", 100], + [ + "wait", + 50 + ] + ] + } + }, + "center": [ 0, 0 ], + "zoom": 1.5, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "name": "First" + }, + "geometry": { + "type": "Point", + "coordinates": [ 10, 0 ] + } + }, + { + "type": "Feature", + "properties": { + "name": "Second" + }, + "geometry": { + "type": "Point", + "coordinates": [ -10, 0 ] + } + }] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": ["get", "name"], + "text-size": 20, + "text-justify": "auto", + "text-variable-anchor": [ + "left", + "right" + ], + "text-radial-offset": 0.5, + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ] + } + }, + { + "id": "anchor", + "type": "circle", + "source": "point", + "paint" :{ + "circle-radius": 2 + } + } + ] +} diff --git a/test/integration/render-tests/text-variable-anchor/pitched-offset/expected.png b/test/integration/render-tests/text-variable-anchor/pitched-offset/expected.png new file mode 100644 index 00000000000..3e604dfa069 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/pitched-offset/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/pitched-offset/style.json b/test/integration/render-tests/text-variable-anchor/pitched-offset/style.json new file mode 100644 index 00000000000..1a703237465 --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/pitched-offset/style.json @@ -0,0 +1,65 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256 + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14, + "pitch": 60, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "layout": { + "text-field": "Test Test Test", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 5, + "text-justify": "auto", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ], + "text-radial-offset": 5 + } + }] +} diff --git a/test/integration/render-tests/text-variable-anchor/pitched-rotated-debug/expected.png b/test/integration/render-tests/text-variable-anchor/pitched-rotated-debug/expected.png new file mode 100644 index 00000000000..56bcdfc2ff1 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/pitched-rotated-debug/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/pitched-rotated-debug/style.json b/test/integration/render-tests/text-variable-anchor/pitched-rotated-debug/style.json new file mode 100644 index 00000000000..defbcbd35ff --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/pitched-rotated-debug/style.json @@ -0,0 +1,66 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256, + "collisionDebug": true + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14, + "pitch": 60, + "bearing": 90, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "layout": { + "text-field": "Test Test Test", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 5, + "text-justify": "auto", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ] + } + }] +} diff --git a/test/integration/render-tests/text-variable-anchor/pitched-with-map/expected.png b/test/integration/render-tests/text-variable-anchor/pitched-with-map/expected.png new file mode 100644 index 00000000000..8b0da17d945 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/pitched-with-map/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/pitched-with-map/style.json b/test/integration/render-tests/text-variable-anchor/pitched-with-map/style.json new file mode 100644 index 00000000000..b3ba095fffe --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/pitched-with-map/style.json @@ -0,0 +1,65 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256 + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14, + "pitch": 60, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "layout": { + "text-field": "Test Test Test", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 5, + "text-justify": "auto", + "text-pitch-alignment": "map", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ] + } + }] +} diff --git a/test/integration/render-tests/text-variable-anchor/pitched/expected.png b/test/integration/render-tests/text-variable-anchor/pitched/expected.png new file mode 100644 index 00000000000..e3fe46e38a5 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/pitched/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/pitched/style.json b/test/integration/render-tests/text-variable-anchor/pitched/style.json new file mode 100644 index 00000000000..f8fb7342720 --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/pitched/style.json @@ -0,0 +1,64 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256 + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14, + "pitch": 60, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "layout": { + "text-field": "Test Test Test", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 5, + "text-justify": "auto", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ] + } + }] +} diff --git a/test/integration/render-tests/text-variable-anchor/remember-last-placement/expected.png b/test/integration/render-tests/text-variable-anchor/remember-last-placement/expected.png new file mode 100644 index 00000000000..cec609f73f7 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/remember-last-placement/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/remember-last-placement/style.json b/test/integration/render-tests/text-variable-anchor/remember-last-placement/style.json new file mode 100644 index 00000000000..644c8c366c6 --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/remember-last-placement/style.json @@ -0,0 +1,95 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256, + "width": 256, + "fadeDuration": 100, + "description": "Start with space for both labels to show with left anchor. Zoom out so that second has to switch to top anchor. Zoom out further so that second is forced to collide out. Zoom all the way back in so that the second label _could_ show in original position, but instead uses the last successfully placed one.", + "operations": [ + ["wait", 100], + ["wait", 100], + ["setZoom", 0.6], + ["wait"], + ["wait", 100], + ["wait", 100], + ["setZoom", 0], + ["wait"], + ["wait", 100], + ["wait", 100], + ["setZoom", 1.7], + ["wait"], + ["wait", 100], + ["wait", 100] + ] + } + }, + "center": [ 0, 0 ], + "zoom": 1.5, + "sources": { + "point": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "name": "First" + }, + "geometry": { + "type": "Point", + "coordinates": [ -10, 0 ] + } + }, + { + "type": "Feature", + "properties": { + "name": "Second" + }, + "geometry": { + "type": "Point", + "coordinates": [ 10, -7 ] + } + }] + } + } + }, + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "text", + "type": "symbol", + "source": "point", + "layout": { + "text-field": ["get", "name"], + "text-size": 20, + "text-justify": "auto", + "text-variable-anchor": [ + "left", + "top" + ], + "text-radial-offset": 0.3, + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ] + } + }, + { + "id": "anchor", + "type": "circle", + "source": "point", + "paint" :{ + "circle-radius": 2 + } + } + ] +} diff --git a/test/integration/render-tests/text-variable-anchor/rotated-offset/expected.png b/test/integration/render-tests/text-variable-anchor/rotated-offset/expected.png new file mode 100644 index 00000000000..d056626fe08 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/rotated-offset/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/rotated-offset/style.json b/test/integration/render-tests/text-variable-anchor/rotated-offset/style.json new file mode 100644 index 00000000000..8d7446a43ca --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/rotated-offset/style.json @@ -0,0 +1,65 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256 + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14, + "bearing": 90, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "layout": { + "text-field": "Test Test Test", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 5, + "text-justify": "auto", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ], + "text-radial-offset": 5 + } + }] +} diff --git a/test/integration/render-tests/text-variable-anchor/rotated-with-map/expected.png b/test/integration/render-tests/text-variable-anchor/rotated-with-map/expected.png new file mode 100644 index 00000000000..a7598d9d6fd Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/rotated-with-map/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/rotated-with-map/style.json b/test/integration/render-tests/text-variable-anchor/rotated-with-map/style.json new file mode 100644 index 00000000000..93a25a04953 --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/rotated-with-map/style.json @@ -0,0 +1,66 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256, + "description": "Note that there are collisions in this example. This is because of the limitation that collision boxes don't rotate; however, their position should still be correct." + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14, + "bearing": 90, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "layout": { + "text-field": "Test Test Test", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 5, + "text-justify": "auto", + "text-rotation-alignment": "map", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ] + } + }] +} diff --git a/test/integration/render-tests/text-variable-anchor/rotated/expected.png b/test/integration/render-tests/text-variable-anchor/rotated/expected.png new file mode 100644 index 00000000000..63403973742 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/rotated/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/rotated/style.json b/test/integration/render-tests/text-variable-anchor/rotated/style.json new file mode 100644 index 00000000000..a537687788a --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/rotated/style.json @@ -0,0 +1,64 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256 + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14, + "bearing": 90, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "layout": { + "text-field": "Test Test Test", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 5, + "text-justify": "auto", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ] + } + }] +} diff --git a/test/integration/render-tests/text-variable-anchor/single-justification/expected.png b/test/integration/render-tests/text-variable-anchor/single-justification/expected.png new file mode 100644 index 00000000000..69134ba5af1 Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/single-justification/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/single-justification/style.json b/test/integration/render-tests/text-variable-anchor/single-justification/style.json new file mode 100644 index 00000000000..c2483ae8211 --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/single-justification/style.json @@ -0,0 +1,63 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256 + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "layout": { + "text-field": "Test Test Test", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 5, + "text-justify": "left", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ] + } + }] +} diff --git a/test/integration/render-tests/text-variable-anchor/single-line/expected.png b/test/integration/render-tests/text-variable-anchor/single-line/expected.png new file mode 100644 index 00000000000..d1fc7c117ad Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/single-line/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/single-line/style.json b/test/integration/render-tests/text-variable-anchor/single-line/style.json new file mode 100644 index 00000000000..2c9c085b376 --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/single-line/style.json @@ -0,0 +1,64 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256, + "description": "Single line labels render differently because they use the same glyphs for all justifications." + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "layout": { + "text-field": "Test", + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-max-width": 5, + "text-justify": "auto", + "text-variable-anchor": [ + "center", + "top", + "bottom", + "left", + "right", + "top-left", + "top-right", + "bottom-left", + "bottom-right" + ] + } + }] +} diff --git a/test/integration/render-tests/text-variable-anchor/top-bottom-left-right/expected.png b/test/integration/render-tests/text-variable-anchor/top-bottom-left-right/expected.png new file mode 100644 index 00000000000..a8d622d10ee Binary files /dev/null and b/test/integration/render-tests/text-variable-anchor/top-bottom-left-right/expected.png differ diff --git a/test/integration/render-tests/text-variable-anchor/top-bottom-left-right/style.json b/test/integration/render-tests/text-variable-anchor/top-bottom-left-right/style.json new file mode 100644 index 00000000000..97a90905a0c --- /dev/null +++ b/test/integration/render-tests/text-variable-anchor/top-bottom-left-right/style.json @@ -0,0 +1,69 @@ +{ + "version": 8, + "metadata": { + "test": { + "height": 256 + } + }, + "center": [ + 13.418056, + 52.499167 + ], + "zoom": 14.5, + "sources": { + "mapbox": { + "type": "vector", + "maxzoom": 14, + "tiles": [ + "local://tiles/{z}-{x}-{y}.mvt" + ] + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "background", + "type": "background", + "paint": { + "background-color": "white" + } + }, + { + "id": "top", + "type": "symbol", + "source": "mapbox", + "source-layer": "poi_label", + "filter": ["all", [ + "==", + "maki", + "restaurant" + ] + ], + "layout": { + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-field": ["get", "name"], + "text-size": 12, + "text-justify": "auto", + "text-variable-anchor": ["top", "bottom", "left", "right" ] + } + }, + { + "id": "circles", + "type": "circle", + "source": "mapbox", + "source-layer": "poi_label", + "filter": [ + "==", + "maki", + "restaurant" + ], + "paint": { + "circle-radius": 2 + } + } + ] +} diff --git a/test/integration/results.html.tmpl b/test/integration/results.html.tmpl index 21750c0be37..37432be176a 100644 --- a/test/integration/results.html.tmpl +++ b/test/integration/results.html.tmpl @@ -1,76 +1,73 @@ - -<% if (shuffle) { %> -
Shuffle seed: <%- seed %>
-<% } %> <% if (unsuccessful.length) { %> -
- Failed Tests: - <% for (const r of unsuccessful) { %><%- r.id %> <% } %> -
+

+ <%- unsuccessful.length %> tests failed. <% } else { %> -
All tests passed!
+

+ All tests passed! <% } %> -<% if (tests.length) { %> - -

+ +

<%- Object.keys(stats).map(status => stats[status] + ' ' + status).join(', ') + '.' %>

+ +
+ <% if (unsuccessful.length) { %> +

Failed tests: + <% for (const r of unsuccessful) { %><%- r.id %> <% } %>

+ <% } %> + +

Test sequence: + <% for (const s of tests) { %><%- s.id %> <% } %>

+ + <% if (shuffle) { %>

Shuffle seed: <%- seed %>

<% } %>
-<% } %> - - + - - - - - - + +
-
Actual / ExpectedDiffInfo
+ diff --git a/test/suite_implementation.js b/test/suite_implementation.js index c11d28faaf7..bc9554002df 100644 --- a/test/suite_implementation.js +++ b/test/suite_implementation.js @@ -52,6 +52,7 @@ module.exports = function(style, options, _callback) { // eslint-disable-line im axonometric: options.axonometric || false, skew: options.skew || [0, 0], fadeDuration: options.fadeDuration || 0, + localIdeographFontFamily: options.localIdeographFontFamily || false, crossSourceCollisions: typeof options.crossSourceCollisions === "undefined" ? true : options.crossSourceCollisions }); @@ -156,7 +157,21 @@ module.exports = function(style, options, _callback) { // eslint-disable-line im map.addLayer(new customLayerImplementations[operation[1]](), operation[2]); map._render(); applyOperations(map, operations.slice(1), callback); - + } else if (operation[0] === 'updateFakeCanvas') { + const canvasSource = map.getSource(operation[1]); + canvasSource.play(); + // update before pause should be rendered + updateFakeCanvas(window.document, options.addFakeCanvas.id, operation[2]); + canvasSource.pause(); + // update after pause should not be rendered + updateFakeCanvas(window.document, options.addFakeCanvas.id, operation[3]); + map._render(); + applyOperations(map, operations.slice(1), callback); + } else if (operation[0] === 'setStyle') { + // Disable local ideograph generation (enabled by default) for + // consistent local ideograph rendering using fixtures in all runs of the test suite. + map.setStyle(operation[1], { localIdeographFontFamily: false }); + applyOperations(map, operations.slice(1), callback); } else { map[operation[0]](...operation.slice(1)); applyOperations(map, operations.slice(1), callback); @@ -173,3 +188,9 @@ function createFakeCanvas(document, id, imagePath) { fakeCanvas.height = image.height; return fakeCanvas; } + +function updateFakeCanvas(document, id, imagePath) { + const fakeCanvas = document.getElementById(id); + const image = PNG.sync.read(fs.readFileSync(path.join(__dirname, './integration', imagePath))); + fakeCanvas.data = image.data; +} diff --git a/test/unit/style/style_layer.test.js b/test/unit/style/style_layer.test.js index 29b241107af..f8450010fc3 100644 --- a/test/unit/style/style_layer.test.js +++ b/test/unit/style/style_layer.test.js @@ -315,6 +315,33 @@ test('StyleLayer#serialize', (t) => { t.end(); }); + t.test('serializes "visibility" of "visible"', (t) => { + const layer = createStyleLayer(createSymbolLayer()); + layer.setLayoutProperty('visibility', 'visible'); + + t.equal(layer.serialize().layout['visibility'], 'visible'); + + t.end(); + }); + + t.test('serializes "visibility" of "none"', (t) => { + const layer = createStyleLayer(createSymbolLayer()); + layer.setLayoutProperty('visibility', 'none'); + + t.equal(layer.serialize().layout['visibility'], 'none'); + + t.end(); + }); + + t.test('serializes "visibility" of undefined', (t) => { + const layer = createStyleLayer(createSymbolLayer()); + layer.setLayoutProperty('visibility', undefined); + + t.equal(layer.serialize().layout['visibility'], undefined); + + t.end(); + }); + t.end(); }); diff --git a/test/unit/symbol/shaping.test.js b/test/unit/symbol/shaping.test.js index 1e915bc5829..8dc110dd77b 100644 --- a/test/unit/symbol/shaping.test.js +++ b/test/unit/symbol/shaping.test.js @@ -21,50 +21,50 @@ test('shaping', (t) => { JSON.parse('{}'); - shaped = shaping.shapeText(Formatted.fromString(`hi${String.fromCharCode(0)}`), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], oneEm, WritingMode.horizontal); + shaped = shaping.shapeText(Formatted.fromString(`hi${String.fromCharCode(0)}`), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], WritingMode.horizontal); if (UPDATE) fs.writeFileSync(path.join(__dirname, '/../../expected/text-shaping-null.json'), JSON.stringify(shaped, null, 2)); t.deepEqual(shaped, JSON.parse(fs.readFileSync(path.join(__dirname, '/../../expected/text-shaping-null.json')))); // Default shaping. - shaped = shaping.shapeText(Formatted.fromString('abcde'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], oneEm, WritingMode.horizontal); + shaped = shaping.shapeText(Formatted.fromString('abcde'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], WritingMode.horizontal); if (UPDATE) fs.writeFileSync(path.join(__dirname, '/../../expected/text-shaping-default.json'), JSON.stringify(shaped, null, 2)); t.deepEqual(shaped, JSON.parse(fs.readFileSync(path.join(__dirname, '/../../expected/text-shaping-default.json')))); // Letter spacing. - shaped = shaping.shapeText(Formatted.fromString('abcde'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0.125 * oneEm, [0, 0], oneEm, WritingMode.horizontal); + shaped = shaping.shapeText(Formatted.fromString('abcde'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0.125 * oneEm, [0, 0], WritingMode.horizontal); if (UPDATE) fs.writeFileSync(path.join(__dirname, '/../../expected/text-shaping-spacing.json'), JSON.stringify(shaped, null, 2)); t.deepEqual(shaped, JSON.parse(fs.readFileSync(path.join(__dirname, '/../../expected/text-shaping-spacing.json')))); // Line break. - shaped = shaping.shapeText(Formatted.fromString('abcde abcde'), glyphs, fontStack, 4 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], oneEm, WritingMode.horizontal); + shaped = shaping.shapeText(Formatted.fromString('abcde abcde'), glyphs, fontStack, 4 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], WritingMode.horizontal); if (UPDATE) fs.writeFileSync(path.join(__dirname, '/../../expected/text-shaping-linebreak.json'), JSON.stringify(shaped, null, 2)); t.deepEqual(shaped, require('../../expected/text-shaping-linebreak.json')); const expectedNewLine = JSON.parse(fs.readFileSync(path.join(__dirname, '/../../expected/text-shaping-newline.json'))); - shaped = shaping.shapeText(Formatted.fromString('abcde\nabcde'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0, [0, 0], oneEm, WritingMode.horizontal); + shaped = shaping.shapeText(Formatted.fromString('abcde\nabcde'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0, [0, 0], WritingMode.horizontal); if (UPDATE) fs.writeFileSync(path.join(__dirname, '/../../expected/text-shaping-newline.json'), JSON.stringify(shaped, null, 2)); t.deepEqual(shaped, expectedNewLine); - shaped = shaping.shapeText(Formatted.fromString('abcde\r\nabcde'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0, [0, 0], oneEm, WritingMode.horizontal); + shaped = shaping.shapeText(Formatted.fromString('abcde\r\nabcde'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0, [0, 0], WritingMode.horizontal); t.deepEqual(shaped.positionedGlyphs, expectedNewLine.positionedGlyphs); const expectedNewLinesInMiddle = JSON.parse(fs.readFileSync(path.join(__dirname, '/../../expected/text-shaping-newlines-in-middle.json'))); - shaped = shaping.shapeText(Formatted.fromString('abcde\n\nabcde'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0, [0, 0], oneEm, WritingMode.horizontal); + shaped = shaping.shapeText(Formatted.fromString('abcde\n\nabcde'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0, [0, 0], WritingMode.horizontal); if (UPDATE) fs.writeFileSync(path.join(__dirname, '/../../expected/text-shaping-newlines-in-middle.json'), JSON.stringify(shaped, null, 2)); t.deepEqual(shaped, expectedNewLinesInMiddle); // Null shaping. - shaped = shaping.shapeText(Formatted.fromString(''), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], oneEm, WritingMode.horizontal); + shaped = shaping.shapeText(Formatted.fromString(''), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], WritingMode.horizontal); t.equal(false, shaped); - shaped = shaping.shapeText(Formatted.fromString(String.fromCharCode(0)), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], oneEm, WritingMode.horizontal); + shaped = shaping.shapeText(Formatted.fromString(String.fromCharCode(0)), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], WritingMode.horizontal); t.equal(false, shaped); // https://github.com/mapbox/mapbox-gl-js/issues/3254 - shaped = shaping.shapeText(Formatted.fromString(' foo bar\n'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], oneEm, WritingMode.horizontal); - const shaped2 = shaping.shapeText(Formatted.fromString('foo bar'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], oneEm, WritingMode.horizontal); + shaped = shaping.shapeText(Formatted.fromString(' foo bar\n'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], WritingMode.horizontal); + const shaped2 = shaping.shapeText(Formatted.fromString('foo bar'), glyphs, fontStack, 15 * oneEm, oneEm, 'center', 'center', 0 * oneEm, [0, 0], WritingMode.horizontal); t.same(shaped.positionedGlyphs, shaped2.positionedGlyphs); t.end(); diff --git a/test/unit/ui/control/geolocate.test.js b/test/unit/ui/control/geolocate.test.js index 4738f35e3ad..d6954f68467 100644 --- a/test/unit/ui/control/geolocate.test.js +++ b/test/unit/ui/control/geolocate.test.js @@ -116,6 +116,32 @@ test('GeolocateControl geolocate fitBoundsOptions', (t) => { geolocation.send({latitude: 10, longitude: 20, accuracy: 1}); }); +test('GeolocateControl non-zero bearing', (t) => { + t.plan(3); + + const map = createMap(t); + map.setBearing(45); + const geolocate = new GeolocateControl({ + fitBoundsOptions: { + linear: true, + duration: 0, + maxZoom: 10 + } + }); + map.addControl(geolocate); + + const click = new window.Event('click'); + + map.once('moveend', () => { + t.deepEqual(lngLatAsFixed(map.getCenter(), 4), { lat: 10, lng: 20 }, 'map centered on location'); + t.equal(map.getBearing(), 45, 'map bearing retained'); + t.equal(map.getZoom(), 10, 'geolocate fitBounds maxZoom'); + t.end(); + }); + geolocate._geolocateButton.dispatchEvent(click); + geolocation.send({latitude: 10, longitude: 20, accuracy: 1}); +}); + test('GeolocateControl no watching map camera on geolocation', (t) => { t.plan(6); diff --git a/test/unit/ui/map.test.js b/test/unit/ui/map.test.js index 55fa4eb7b24..8cd3605fb49 100755 --- a/test/unit/ui/map.test.js +++ b/test/unit/ui/map.test.js @@ -1524,6 +1524,27 @@ test('Map', (t) => { t.end(); }); }); + t.test('remove properties for zero-based feature IDs.', (t) => { + const map = createMap(t, { + style: { + "version": 8, + "sources": { + "geojson": createStyleSource() + }, + "layers": [] + } + }); + map.on('load', () => { + map.setFeatureState({ source: 'geojson', id: 0}, {'hover': true, 'foo': true}); + map.removeFeatureState({ source: 'geojson', id: 0}); + + const fState = map.getFeatureState({ source: 'geojson', id: 0}); + t.equal(fState.hover, undefined); + t.equal(fState.foo, undefined); + + t.end(); + }); + }); t.test('other properties persist when removing specific property', (t) => { const map = createMap(t, { style: { @@ -1945,6 +1966,26 @@ test('Map', (t) => { t.end(); }); + t.test('map fires `styleimagemissing` for missing icons', (t) => { + const map = createMap(t); + + const id = "missing-image"; + + let called; + map.on('styleimagemissing', e => { + map.addImage(e.id, {width: 1, height: 1, data: new Uint8Array(4)}); + called = e.id; + }); + + t.notok(map.hasImage(id)); + + map.style.imageManager.getImages([id], () => { + t.equals(called, id); + t.ok(map.hasImage(id)); + t.end(); + }); + }); + t.end(); }); diff --git a/test/unit/ui/popup.test.js b/test/unit/ui/popup.test.js index 93697d93577..16a8606fca9 100644 --- a/test/unit/ui/popup.test.js +++ b/test/unit/ui/popup.test.js @@ -134,6 +134,43 @@ test('Popup content can be set via setHTML', (t) => { t.end(); }); +test('Popup width maximum defaults to 240px', (t) => { + const map = createMap(t); + + const popup = new Popup({closeButton: false}) + .setLngLat([0, 0]) + .addTo(map) + .setHTML("Test"); + + t.equal(popup.getMaxWidth(), "240px"); + t.end(); +}); + +test('Popup width maximum can be set via using maxWidth option', (t) => { + const map = createMap(t); + + const popup = new Popup({closeButton: false, maxWidth: "5px"}) + .setLngLat([0, 0]) + .addTo(map) + .setHTML("Test"); + + t.equal(popup.getMaxWidth(), "5px"); + t.end(); +}); + +test('Popup width maximum can be set via maxWidth', (t) => { + const map = createMap(t); + + const popup = new Popup({closeButton: false}) + .setLngLat([0, 0]) + .setHTML("Test") + .setMaxWidth("5px") + .addTo(map); + + t.equal(popup.getMaxWidth(), "5px"); + t.end(); +}); + test('Popup content can be set via setDOMContent', (t) => { const map = createMap(t); const content = window.document.createElement('span'); diff --git a/yarn.lock b/yarn.lock index 8060301424e..5f5adbe3d5f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8,6 +8,26 @@ dependencies: "@babel/highlight" "^7.0.0" +"@babel/core@>=7.1.0": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.2.2.tgz#07adba6dde27bb5ad8d8672f15fde3e08184a687" + integrity sha512-59vB0RWt09cAct5EIe58+NzGP4TFSD3Bz//2/ELy3ZeTeKF6VTD1AXlH8BGGbCX0PuobZBsIzO7IAI9PH67eKw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/generator" "^7.2.2" + "@babel/helpers" "^7.2.0" + "@babel/parser" "^7.2.2" + "@babel/template" "^7.2.2" + "@babel/traverse" "^7.2.2" + "@babel/types" "^7.2.2" + convert-source-map "^1.1.0" + debug "^4.1.0" + json5 "^2.1.0" + lodash "^4.17.10" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + "@babel/core@^7.1.2": version "7.1.2" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.1.2.tgz#f8d2a9ceb6832887329a7b60f9d035791400ba4e" @@ -48,6 +68,17 @@ source-map "^0.5.0" trim-right "^1.0.1" +"@babel/generator@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e" + integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg== + dependencies: + "@babel/types" "^7.3.4" + jsesc "^2.5.1" + lodash "^4.17.11" + source-map "^0.5.0" + trim-right "^1.0.1" + "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" @@ -227,6 +258,15 @@ "@babel/traverse" "^7.1.0" "@babel/types" "^7.1.2" +"@babel/helpers@^7.2.0": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.3.1.tgz#949eec9ea4b45d3210feb7dc1c22db664c9e44b9" + integrity sha512-Q82R3jKsVpUV99mgX50gOPCWwco9Ec5Iln/8Vyu4osNIOQgSrd9RFrQeUvmvddFNoLwMyOUWU+5ckioEKpDoGA== + dependencies: + "@babel/template" "^7.1.2" + "@babel/traverse" "^7.1.5" + "@babel/types" "^7.3.0" + "@babel/highlight@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" @@ -244,6 +284,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.1.tgz#8f4ffd45f779e6132780835ffa7a215fa0b2d181" integrity sha512-ATz6yX/L8LEnC3dtLQnIx4ydcPxhLcoy9Vl6re00zb2w5lG6itY6Vhnr1KFRPq/FHNsgl/gh2mjNN20f9iJTTA== +"@babel/parser@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c" + integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ== + "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" @@ -913,6 +958,21 @@ globals "^11.1.0" lodash "^4.17.10" +"@babel/traverse@^7.1.5", "@babel/traverse@^7.2.2": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06" + integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/generator" "^7.3.4" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.0.0" + "@babel/parser" "^7.3.4" + "@babel/types" "^7.3.4" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.11" + "@babel/types@^7.0.0", "@babel/types@^7.1.2", "@babel/types@^7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.1.3.tgz#3a767004567060c2f40fca49a304712c525ee37d" @@ -930,6 +990,15 @@ lodash "^4.17.10" to-fast-properties "^2.0.0" +"@babel/types@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.4.tgz#bf482eaeaffb367a28abbf9357a94963235d90ed" + integrity sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ== + dependencies: + esutils "^2.0.2" + lodash "^4.17.11" + to-fast-properties "^2.0.0" + "@mapbox/appropriate-images-get-url@^0.1.1": version "0.1.1" resolved "https://registry.yarnpkg.com/@mapbox/appropriate-images-get-url/-/appropriate-images-get-url-0.1.1.tgz#2841bc4ee767862ff0f997a93e4510537b9c47b8" @@ -1093,6 +1162,11 @@ pirates "^3.0.2" vlq "^0.2.1" +"@mapbox/gazetteer@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@mapbox/gazetteer/-/gazetteer-3.1.2.tgz#f4e3d08c5b4a6d0c3eea16950257259fa002fa58" + integrity sha512-0zjK+bPITX0CAGrNc18KCWylKibG12U+mfDmzfACgjyUwt5xzkG2QwEKKYjVUrm9guTulAaw6D6HcLX7c4My5g== + "@mapbox/geojson-area@0.2.2": version "0.2.2" resolved "https://registry.yarnpkg.com/@mapbox/geojson-area/-/geojson-area-0.2.2.tgz#18d7814aa36bf23fbbcc379f8e26a22927debf10" @@ -1176,9 +1250,10 @@ version "1.0.0" resolved "https://registry.yarnpkg.com/@mapbox/link-to-location/-/link-to-location-1.0.0.tgz#484a4d922e3e6f7b54fd7964d8035bcb00bbf59a" -"@mapbox/mapbox-gl-rtl-text@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-rtl-text/-/mapbox-gl-rtl-text-0.2.0.tgz#332fa991dcf6913be369c21f4c20c6c73b5d1c8c" +"@mapbox/mapbox-gl-rtl-text@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-rtl-text/-/mapbox-gl-rtl-text-0.2.1.tgz#bb1a1d9f20c36ec4a43fd7c582b050d0c8bc7e54" + integrity sha512-YhVsCLNgy1lUXqfEFqt89E+JRRviFjkSwrYTnL7sXgwwS6dx/39YRNugBPXTZyNVzmriWedf0J4tu9+xbDGXbw== "@mapbox/mapbox-gl-supported@^1.4.0": version "1.4.0" @@ -1302,6 +1377,11 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + "@octokit/rest@^15.15.1": version "15.16.1" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-15.16.1.tgz#399b06660fe16852cf432059c845d4cdcaf77f5a" @@ -1320,27 +1400,57 @@ version "0.7.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" -"@sinonjs/commons@^1.2.0": +"@sinonjs/commons@^1", "@sinonjs/commons@^1.0.2": version "1.3.0" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.3.0.tgz#50a2754016b6f30a994ceda6d9a0a8c36adda849" + integrity sha512-j4ZwhaHmwsCb4DlDOIWnI5YyKDNMoNThsmwEpfHx6a1EpsGZ9qYLxP++LMlmBRjtGptGHFsGItJ768snllFWpA== dependencies: type-detect "4.0.8" -"@sinonjs/formatio@3.0.0", "@sinonjs/formatio@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.0.0.tgz#9d282d81030a03a03fa0c5ce31fd8786a4da311a" +"@sinonjs/commons@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.4.0.tgz#7b3ec2d96af481d7a0321252e7b1c94724ec5a78" + integrity sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw== + dependencies: + type-detect "4.0.8" + +"@sinonjs/formatio@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.1.0.tgz#6ac9d1eb1821984d84c4996726e45d1646d8cce5" + integrity sha512-ZAR2bPHOl4Xg6eklUGpsdiIJ4+J1SNag1DHHrG/73Uz/nVwXqjgUtRPLoS+aVyieN9cSbc0E4LsU984tWcDyNg== dependencies: - "@sinonjs/samsam" "2.1.0" + "@sinonjs/samsam" "^2 || ^3" -"@sinonjs/samsam@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-2.1.0.tgz#b8b8f5b819605bd63601a6ede459156880f38ea3" +"@sinonjs/formatio@^3.2.1": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.2.1.tgz#52310f2f9bcbc67bdac18c94ad4901b95fde267e" + integrity sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ== + dependencies: + "@sinonjs/commons" "^1" + "@sinonjs/samsam" "^3.1.0" + +"@sinonjs/samsam@^2 || ^3": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.0.2.tgz#304fb33bd5585a0b2df8a4c801fcb47fa84d8e43" + integrity sha512-m08g4CS3J6lwRQk1pj1EO+KEVWbrbXsmi9Pw0ySmrIbcVxVaedoFgLvFsV8wHLwh01EpROVz3KvVcD1Jmks9FQ== dependencies: + "@sinonjs/commons" "^1.0.2" array-from "^2.1.1" + lodash.get "^4.4.2" -"@sinonjs/samsam@^2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-2.1.2.tgz#16947fce5f57258d01f1688fdc32723093c55d3f" +"@sinonjs/samsam@^3.1.0", "@sinonjs/samsam@^3.3.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-3.3.1.tgz#e88c53fbd9d91ad9f0f2b0140c16c7c107fe0d07" + integrity sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw== + dependencies: + "@sinonjs/commons" "^1.0.2" + array-from "^2.1.1" + lodash "^4.17.11" + +"@sinonjs/text-encoding@^0.7.1": + version "0.7.1" + resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5" + integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ== "@types/estree@0.0.39": version "0.0.39" @@ -1350,6 +1460,11 @@ version "9.4.6" resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.6.tgz#d8176d864ee48753d053783e4e463aec86b8d82e" +"@types/node@^11.11.6": + version "11.11.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-11.11.6.tgz#df929d1bb2eee5afdda598a41930fe50b43eaa6a" + integrity sha512-Exw4yUWMBXM3X+8oqzJNRqZSwUAaS4+7NdvHqQuFi/d+synz++xmX3QIf+BFqneW8N31R8Ky+sikfZUXq07ggQ== + "@types/q@^1.5.1": version "1.5.1" resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18" @@ -1411,11 +1526,9 @@ acorn-globals@^4.3.0: acorn "^6.0.1" acorn-walk "^6.0.1" -acorn-jsx@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-4.1.1.tgz#e8e41e48ea2fe0c896740610ab6a4ffd8add225e" - dependencies: - acorn "^5.0.3" +acorn-jsx@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" acorn-node@^1.2.0, acorn-node@^1.3.0: version "1.3.0" @@ -1440,10 +1553,6 @@ acorn@^5.0.0: version "5.5.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" -acorn@^5.0.3, acorn@^5.6.0: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - acorn@^5.2.1: version "5.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.4.1.tgz#fdc58d9d17f4a4e98d102ded826a9b9759125102" @@ -1457,10 +1566,10 @@ acorn@^6.0.1, acorn@^6.0.2: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.4.tgz#77377e7353b72ec5104550aa2d2097a2fd40b754" integrity sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg== -acorn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.0.5.tgz#81730c0815f3f3b34d8efa95cb7430965f4d887a" - integrity sha512-i33Zgp3XWtmZBMNvCr4azvOFeWVw1Rk6p3hfi3LUDvIFraOMywb1kAtrbi+med14m4Xfpqm3zRZMT+c0FNE7kg== +acorn@^6.0.7, acorn@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" + integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== address@^1.0.3: version "1.0.3" @@ -1518,6 +1627,16 @@ ajv@^6.5.3: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.9.1: + version "6.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" + integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -1536,9 +1655,10 @@ ansi-align@^2.0.0: dependencies: string-width "^2.0.0" -ansi-escapes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92" +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== ansi-gray@^0.1.1: version "0.1.1" @@ -1554,11 +1674,17 @@ ansi-html@^0.0.7: ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + ansi-styles@^2.0.1, ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -1605,12 +1731,6 @@ append-buffer@^1.0.2: dependencies: buffer-equal "^1.0.0" -append-transform@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" - dependencies: - default-require-extensions "^1.0.0" - append-transform@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" @@ -1651,6 +1771,11 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" +arg@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.0.tgz#583c518199419e0037abb74062c37f8519e575f0" + integrity sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1715,7 +1840,7 @@ array-reduce@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" -array-union@^1.0.1: +array-union@^1.0.1, array-union@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" dependencies: @@ -1742,7 +1867,7 @@ arraybuffer.slice@~0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" -arrify@^1.0.0, arrify@^1.0.1: +arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -1790,6 +1915,10 @@ assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + astw@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/astw/-/astw-2.2.0.tgz#7bd41784d32493987aeb239b6b4e1c57a873b917" @@ -1819,7 +1948,7 @@ async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" -async@1.5.2, async@^1.4.0: +async@1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -1971,7 +2100,7 @@ babel-eslint@^10.0.1: eslint-scope "3.7.1" eslint-visitor-keys "^1.0.0" -babel-generator@^6.18.0, babel-generator@^6.26.0: +babel-generator@^6.26.0: version "6.26.1" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" dependencies: @@ -2503,7 +2632,7 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: core-js "^2.4.0" regenerator-runtime "^0.11.0" -babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: +babel-template@^6.24.1, babel-template@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" dependencies: @@ -2513,7 +2642,7 @@ babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0: babylon "^6.18.0" lodash "^4.17.4" -babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0: +babel-traverse@^6.24.1, babel-traverse@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" dependencies: @@ -2527,7 +2656,7 @@ babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0: invariant "^2.2.2" lodash "^4.17.4" -babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: +babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" dependencies: @@ -2604,9 +2733,10 @@ before-after-hook@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-1.1.0.tgz#83165e15a59460d13702cb8febd6a1807896db5a" -benchmark@~2.1.0: +benchmark@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629" + integrity sha1-CfPeMckWQl1JjMLuVloOvzwqVik= dependencies: lodash "^4.17.4" platform "^1.3.3" @@ -2863,6 +2993,11 @@ browser-process-hrtime@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e" +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + browser-resolve@^1.11.0, browser-resolve@^1.7.0: version "1.11.2" resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" @@ -2976,9 +3111,10 @@ browserify-zlib@^0.2.0, browserify-zlib@~0.2.0: dependencies: pako "~1.0.5" -browserify@^16.1.0: - version "16.1.0" - resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.1.0.tgz#00b86844f89482bbd0d5d1b584b324762ef3f698" +browserify@^16.2.3: + version "16.2.3" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-16.2.3.tgz#7ee6e654ba4f92bce6ab3599c3485b1cc7a0ad0b" + integrity sha512-zQt/Gd1+W+IY+h/xX2NYMW4orQWhqSwyV+xsblycTtpOuB27h1fZhhNQuipJ4t79ohw4P4mMem0jp/ZkISQtjQ== dependencies: JSONStream "^1.0.3" assert "^1.4.0" @@ -3018,7 +3154,7 @@ browserify@^16.1.0: shell-quote "^1.6.1" stream-browserify "^2.0.0" stream-http "^2.0.0" - string_decoder "~1.0.0" + string_decoder "^1.1.1" subarg "^1.0.0" syntax-error "^1.1.1" through2 "^2.0.0" @@ -3026,7 +3162,7 @@ browserify@^16.1.0: tty-browserify "0.0.1" url "~0.11.0" util "~0.10.1" - vm-browserify "~0.0.1" + vm-browserify "^1.0.0" xtend "^4.0.0" browserslist@^2.1.2: @@ -3117,6 +3253,7 @@ buffer-fill@^1.0.0: buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== buffer-shims@^1.0.0: version "1.0.0" @@ -3227,22 +3364,15 @@ cached-path-relative@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7" -caching-transform@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" - dependencies: - md5-hex "^1.2.0" - mkdirp "^0.5.1" - write-file-atomic "^1.1.4" - -caching-transform@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-2.0.0.tgz#e1292bd92d35b6e8b1ed7075726724b3bd64eea0" +caching-transform@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-3.0.2.tgz#601d46b91eca87687a281e71cef99791b0efca70" + integrity sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w== dependencies: - make-dir "^1.0.0" - md5-hex "^2.0.0" - package-hash "^2.0.0" - write-file-atomic "^2.0.0" + hasha "^3.0.0" + make-dir "^2.0.0" + package-hash "^3.0.0" + write-file-atomic "^2.4.2" call-matcher@^1.0.1: version "1.0.1" @@ -3257,19 +3387,14 @@ call-me-maybe@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - dependencies: - callsites "^0.2.0" - callsite@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" +callsites@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" + integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== camel-case@3.0.x, camel-case@^3.0.0: version "3.0.0" @@ -3534,10 +3659,6 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -3689,6 +3810,7 @@ coa@~2.0.1: code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= collapse-white-space@^1.0.0, collapse-white-space@^1.0.2: version "1.0.3" @@ -3831,6 +3953,7 @@ concat-map@0.0.1: concat-stream@1.6.2, concat-stream@^1.4.6, concat-stream@^1.4.7, concat-stream@^1.5.1: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== dependencies: buffer-from "^1.0.0" inherits "^2.0.3" @@ -3974,18 +4097,17 @@ core-js@^2.0.0, core-js@^2.4.0, core-js@^2.5.0: core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cosmiconfig@^2.1.0, cosmiconfig@^2.1.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.2.2.tgz#6173cebd56fac042c1f4390edf7af6c07c7cb892" +cosmiconfig@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" + integrity sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ== dependencies: is-directory "^0.3.1" - js-yaml "^3.4.3" - minimist "^1.2.0" - object-assign "^4.1.0" - os-homedir "^1.0.1" - parse-json "^2.2.0" - require-from-string "^1.1.0" + js-yaml "^3.9.0" + parse-json "^4.0.0" + require-from-string "^2.0.1" cosmiconfig@^5.0.0: version "5.0.6" @@ -3995,16 +4117,17 @@ cosmiconfig@^5.0.0: js-yaml "^3.9.0" parse-json "^4.0.0" -coveralls@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.2.tgz#f5a0bcd90ca4e64e088b710fa8dda640aea4884f" +coveralls@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.0.3.tgz#83b1c64aea1c6afa69beaf50b55ac1bc4d13e2b8" + integrity sha512-viNfeGlda2zJr8Gj1zqXpDMRjw9uM54p7wzZdvLRyOgnAfCe974Dq4veZkjJdxQXbmdppu6flEajFYseHYaUhg== dependencies: growl "~> 1.10.0" js-yaml "^3.11.0" lcov-parse "^0.0.10" log-driver "^1.2.7" minimist "^1.2.0" - request "^2.85.0" + request "^2.86.0" cp-file@^6.0.0: version "6.0.0" @@ -4066,7 +4189,7 @@ cross-spawn@^4: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^5.0.1, cross-spawn@^5.1.0: +cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" dependencies: @@ -4486,10 +4609,6 @@ debounce@^1.1.0, debounce@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" -debug-log@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" - debug@2.6.9, debug@^2.1.2, debug@^2.1.3, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -4508,7 +4627,7 @@ debug@^4.0.0, debug@^4.0.1: dependencies: ms "^2.1.1" -debug@^4.1.0: +debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -4522,7 +4641,7 @@ decamelize-keys@^1.0.0: decamelize "^1.1.0" map-obj "^1.0.0" -decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2: +decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -4670,12 +4789,6 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" -default-require-extensions@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" - dependencies: - strip-bom "^2.0.0" - default-require-extensions@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" @@ -4726,18 +4839,6 @@ del-cli@^1.1.0: meow "^3.6.0" update-notifier "^2.1.0" -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - del@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5" @@ -4765,9 +4866,10 @@ depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" -dependency-graph@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.7.0.tgz#8fc7991ad236e47f0d5742701b5e307b83d7c0d0" +dependency-graph@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/dependency-graph/-/dependency-graph-0.8.0.tgz#2da2d35ed852ecc24a5d6c17788ba57c3708755b" + integrity sha512-DCvzSq2UiMsuLnj/9AL484ummEgLtZIcRS7YvtO38QnpX3vqh9nJ8P+zhu8Ja+SmLrBHO2iDbva20jq38qvBkQ== deps-sort@^2.0.0: version "2.0.0" @@ -4828,7 +4930,7 @@ diff@^1.3.2, diff@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" -diff@^3.5.0: +diff@^3.1.0, diff@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -4847,6 +4949,13 @@ dir-glob@^2.0.0: arrify "^1.0.1" path-type "^3.0.0" +dir-glob@^2.2.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" + integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== + dependencies: + path-type "^3.0.0" + disparity@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/disparity/-/disparity-2.0.0.tgz#57ddacb47324ae5f58d2cc0da886db4ce9eeb718" @@ -4873,6 +4982,13 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + documentation@~9.1.1: version "9.1.1" resolved "https://registry.yarnpkg.com/documentation/-/documentation-9.1.1.tgz#20da422be82a04a2d356d720d55d4cad25bb235b" @@ -5086,10 +5202,6 @@ duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" -duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - duplexify@^3.2.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -5195,6 +5307,11 @@ elliptic@^6.0.0: version "6.1.1" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -5300,7 +5417,7 @@ error@^7.0.0: string-template "~0.2.1" xtend "~4.0.0" -es-abstract@^1.12.0: +es-abstract@^1.11.0, es-abstract@^1.12.0: version "1.13.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" dependencies: @@ -5460,57 +5577,64 @@ eslint-config-mourner@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/eslint-config-mourner/-/eslint-config-mourner-3.0.0.tgz#2cb7df3a14889e70409bbc3250ef0373285e7430" -eslint-import-resolver-node@^0.3.1: +eslint-import-resolver-node@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" + integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== dependencies: debug "^2.6.9" resolve "^1.5.0" -eslint-module-utils@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz#b270362cd88b1a48ad308976ce7fa54e98411746" +eslint-module-utils@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz#546178dab5e046c8b562bbb50705e2456d7bda49" + integrity sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w== dependencies: debug "^2.6.8" - pkg-dir "^1.0.0" + pkg-dir "^2.0.0" -eslint-plugin-flowtype@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-3.2.1.tgz#45e032aee54e695dfc41a891e92b7afedfc62c77" - integrity sha512-1lymqM8Cawxu5xsS8TaCrLWJYUmUdoG4hCfa7yWOhCf0qZn/CvI8FxqkhdOP6bAosBn5zeYxKe3Q/4rfKN8a+A== +eslint-plugin-flowtype@^3.4.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-3.4.2.tgz#55475e10b05fd714d60bceebbbed596cb8706b16" + integrity sha512-sv6O6fiN3dIwhU4qRxfcyIpbKGVvsxwIQ6vgBLudpQKjH1rEyEFEOjGzGEUBTQP9J8LdTZm37OjiqZ0ZeFOa6g== dependencies: - lodash "^4.17.10" + lodash "^4.17.11" -eslint-plugin-html@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-4.0.6.tgz#724bb9272efb4df007dfee8dfb269ed83577e5b4" +eslint-plugin-html@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-5.0.3.tgz#3db133995e49a73596f6a473c16a1b83634deffd" + integrity sha512-46ruAnp3jVQP/5Bi5eEIOooscjUTPFU3vxCxHe/OG6ORdM7Xv5c25/Nz9fAbHklzCpiXuIiH4/mV/XBkm7MINw== dependencies: - htmlparser2 "^3.8.2" + htmlparser2 "^3.10.0" -eslint-plugin-import@^2.14.0: - version "2.14.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz#6b17626d2e3e6ad52cfce8807a845d15e22111a8" +eslint-plugin-import@^2.16.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz#97ac3e75d0791c4fac0e15ef388510217be7f66f" + integrity sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A== dependencies: contains-path "^0.1.0" - debug "^2.6.8" + debug "^2.6.9" doctrine "1.5.0" - eslint-import-resolver-node "^0.3.1" - eslint-module-utils "^2.2.0" - has "^1.0.1" - lodash "^4.17.4" - minimatch "^3.0.3" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.3.0" + has "^1.0.3" + lodash "^4.17.11" + minimatch "^3.0.4" read-pkg-up "^2.0.0" - resolve "^1.6.0" + resolve "^1.9.0" -eslint-plugin-react@^7.11.1: - version "7.11.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.11.1.tgz#c01a7af6f17519457d6116aa94fc6d2ccad5443c" +eslint-plugin-react@^7.12.4: + version "7.12.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz#b1ecf26479d61aee650da612e425c53a99f48c8c" + integrity sha512-1puHJkXJY+oS1t467MjbqjvX53uQ05HXwjqDgdbGBqf5j9eeydI54G3KwiJmWciQ0HTBacIKw2jgwSBSH3yfgQ== dependencies: array-includes "^3.0.3" doctrine "^2.1.0" has "^1.0.3" jsx-ast-utils "^2.0.1" + object.fromentries "^2.0.0" prop-types "^15.6.2" + resolve "^1.9.0" eslint-scope@3.7.1: version "3.7.1" @@ -5519,9 +5643,10 @@ eslint-scope@3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-scope@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.0.tgz#50bf3071e9338bcdc43331794a0cb533f0136172" +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" @@ -5534,59 +5659,61 @@ eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" -eslint@^5.8.0: - version "5.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.8.0.tgz#91fbf24f6e0471e8fdf681a4d9dd1b2c9f28309b" +eslint@^5.15.3: + version "5.15.3" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.15.3.tgz#c79c3909dc8a7fa3714fb340c11e30fd2526b8b5" + integrity sha512-vMGi0PjCHSokZxE0NLp2VneGw5sio7SSiDNgIUn2tC0XkWJRNOIoHIg3CliLVfXnJsiHxGAYrkw0PieAu8+KYQ== dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.5.3" + ajv "^6.9.1" chalk "^2.1.0" cross-spawn "^6.0.5" debug "^4.0.1" - doctrine "^2.1.0" - eslint-scope "^4.0.0" + doctrine "^3.0.0" + eslint-scope "^4.0.3" eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" - espree "^4.0.0" + espree "^5.0.1" esquery "^1.0.1" esutils "^2.0.2" - file-entry-cache "^2.0.0" + file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" glob "^7.1.2" globals "^11.7.0" ignore "^4.0.6" + import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^6.1.0" - is-resolvable "^1.1.0" + inquirer "^6.2.2" js-yaml "^3.12.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" - lodash "^4.17.5" + lodash "^4.17.11" minimatch "^3.0.4" mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" - pluralize "^7.0.0" progress "^2.0.0" regexpp "^2.0.1" - require-uncached "^1.0.3" semver "^5.5.1" strip-ansi "^4.0.0" strip-json-comments "^2.0.1" - table "^5.0.2" + table "^5.2.3" text-table "^0.2.0" -esm@^3.0.84: +esm@~3.0.84: version "3.0.84" resolved "https://registry.yarnpkg.com/esm/-/esm-3.0.84.tgz#bb108989f4673b32d4f62406869c28eed3815a63" + integrity sha512-SzSGoZc17S7P+12R9cg21Bdb7eybX25RnIeRZ80xZs+VZ3kdQKzqTp2k4hZJjR7p9l0186TTXSgrxzlMDBktlw== -espree@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-4.0.0.tgz#253998f20a0f82db5d866385799d912a83a36634" +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== dependencies: - acorn "^5.6.0" - acorn-jsx "^4.1.1" + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" esprima@^3.1.3: version "3.1.3" @@ -5632,6 +5759,11 @@ estree-walker@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.2.tgz#d3850be7529c9580d815600b53126515e146dd39" +estree-walker@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.0.tgz#5d865327c44a618dde5699f763891ae31f257dae" + integrity sha512-peq1RfVAVzr3PU/jL31RaOjUKLoZJpObQWJJ+LgfcxDUifyLZ1RjPQZTl0pzj2uJ45b7A7XpyppXvxdEqzo4rw== + esutils@^2.0.0, esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -5647,18 +5779,6 @@ event-emitter@~0.3.5: d "1" es5-ext "~0.10.14" -event-stream@~3.3.0: - version "3.3.4" - resolved "http://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" - dependencies: - duplexer "~0.1.1" - from "~0" - map-stream "~0.1.0" - pause-stream "0.0.11" - split "0.3" - stream-combiner "~0.0.4" - through "~2.3.1" - eventemitter3@1.x.x: version "1.2.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" @@ -5800,12 +5920,6 @@ expand-template@^2.0.3: resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - dependencies: - homedir-polyfill "^1.0.1" - expect.js@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.2.0.tgz#1028533d2c1c363f74a6796ff57ec0520ded2be1" @@ -5847,9 +5961,10 @@ extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" -external-editor@^3.0.0: +external-editor@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.0.3.tgz#5866db29a97826dbe4bf3afd24070ead9ea43a27" + integrity sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA== dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -5920,6 +6035,18 @@ fast-glob@^2.0.2: merge2 "^1.2.1" micromatch "^3.1.8" +fast-glob@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.6.tgz#a5d5b697ec8deda468d85a74035290a025a95295" + integrity sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w== + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.3" + micromatch "^3.1.10" + fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -5982,12 +6109,19 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" +file-entry-cache@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-4.0.0.tgz#633567d15364aefe0b299e1e217735e8f3a9f6e8" + integrity sha512-AVSwsnbV8vH/UVbvgEhf3saVQXORNv0ZzSkvkhQIaia5Tia+JhGTaa/ePUSVoPHQyGayQNmYfkzFi3WZV5zcpA== dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" + flat-cache "^2.0.1" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" file-loader@^1.1.11: version "1.1.11" @@ -6089,14 +6223,6 @@ finalhandler@1.1.0: statuses "~1.3.1" unpipe "~1.0.0" -find-cache-dir@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" - dependencies: - commondir "^1.0.1" - mkdirp "^0.5.1" - pkg-dir "^1.0.0" - find-cache-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" @@ -6159,19 +6285,24 @@ first-chunk-stream@^1.0.0: resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" integrity sha1-Wb+1DNkF9g18OUzT2ayqtOatk04= -flat-cache@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.0.tgz#d3030b32b38154f4e3b7e9c709f490f7ef97c481" +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== dependencies: - circular-json "^0.3.1" - del "^2.0.2" - graceful-fs "^4.1.2" - write "^0.2.1" + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" + integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== -flow-bin@^0.91.0: - version "0.91.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.91.0.tgz#f5c89729f74b2ccbd47df6fbfadbdcc89cc1e478" - integrity sha512-j+L+xNiUYnZZ27MjVI0y2c9474ZHOvdSQq0Tjwh56mEA7tfxYqp5Dcb6aZSwvs3tGMTjCrZow9aUlZf3OoRyDQ== +flow-bin@^0.95.1: + version "0.95.1" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.95.1.tgz#633113831ccff4b7ee70a2730f63fc43b69ba85f" + integrity sha512-06IOC/pqPMNRYtC6AMZEWYR9Fi6UdBC7gImGinPuNUpPZFnP5E9/0cBCl3DWrH4zz/gSM2HdDilU7vPGpYIr2w== flush-write-stream@^1.0.0: version "1.0.2" @@ -6220,7 +6351,7 @@ foreach@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" -foreground-child@^1.3.3, foreground-child@^1.5.3, foreground-child@^1.5.6: +foreground-child@^1.3.3, foreground-child@^1.5.6: version "1.5.6" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" dependencies: @@ -6272,10 +6403,6 @@ from2@^2.1.0, from2@^2.1.1: inherits "^2.0.1" readable-stream "^2.0.0" -from@~0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" - front-matter@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/front-matter/-/front-matter-2.3.0.tgz#7203af896ce357ee04e2aa45169ea91ed7f67504" @@ -6304,9 +6431,10 @@ fs-extra@3.0.1: jsonfile "^3.0.0" universalify "^0.1.0" -fs-extra@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" +fs-extra@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== dependencies: graceful-fs "^4.1.2" jsonfile "^4.0.0" @@ -6432,10 +6560,6 @@ get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" -get-stdin@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" - get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" @@ -6503,9 +6627,10 @@ gl-matrix@^3.0.0: resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.0.0.tgz#888301ac7650e148c3865370e13ec66d08a8381f" integrity sha512-PD4mVH/C/Zs64kOozeFnKY8ybhgwxXXQYGWdB4h68krAHknWJgk9uKOn6z8YElh5//vs++90pb6csrTIDWnexA== -gl@^4.1.1: +gl@~4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/gl/-/gl-4.1.1.tgz#999383a9ec2863c6d9db9c61866ddb96b4be1998" + integrity sha512-2SeT0193YonCMR0wjKuZm3GNq52qcRD7S1LsRvs3U9c5lnDceQjEw0sUgpEukIe4tS0F/6wL5q+/CWH4Zf58OA== dependencies: bindings "^1.2.1" bit-twiddle "^1.0.2" @@ -6578,7 +6703,7 @@ glob@^5.0.14, glob@^5.0.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2: +glob@^7.0.3, glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -6606,23 +6731,21 @@ global-dirs@^0.1.0: dependencies: ini "^1.3.4" -global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" +global-modules@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" + global-prefix "^3.0.0" -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" globals-docs@^2.4.0: version "2.4.0" @@ -6636,17 +6759,6 @@ globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -6657,18 +6769,7 @@ globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globby@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" - dependencies: - array-union "^1.0.1" - dir-glob "^2.0.0" - glob "^7.1.2" - ignore "^3.3.5" - pify "^3.0.0" - slash "^1.0.0" - -globby@^8.0.0, globby@^8.0.1: +globby@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.1.tgz#b5ad48b8aa80b35b814fc1281ecc851f1d2b5b50" dependencies: @@ -6680,6 +6781,19 @@ globby@^8.0.0, globby@^8.0.1: pify "^3.0.0" slash "^1.0.0" +globby@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-9.0.0.tgz#3800df736dc711266df39b4ce33fe0d481f94c23" + integrity sha512-q0qiO/p1w/yJ0hk8V9x1UXlgsXUxlGd0AHUOXZVXBO6aznDtpx7M8D1kBrCAItoPm+4l8r6ATXV1JpjY2SBQOw== + dependencies: + array-union "^1.0.2" + dir-glob "^2.2.1" + fast-glob "^2.2.6" + glob "^7.1.3" + ignore "^4.0.3" + pify "^4.0.1" + slash "^2.0.0" + globjoin@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43" @@ -6793,7 +6907,7 @@ graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -graceful-fs@^4.1.10: +graceful-fs@^4.1.10, graceful-fs@^4.1.15: version "4.1.15" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== @@ -6878,9 +6992,10 @@ gulplog@^1.0.0: dependencies: glogg "^1.0.0" -handlebars@^4.0.11: - version "4.0.12" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.12.tgz#2c15c8a96d46da5e266700518ba8cb8d919d5bc5" +handlebars@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.0.tgz#0d6a6f34ff1f63cecec8423aa4169827bf787c3a" + integrity sha512-l2jRuU1NAWK6AW5qqcTATWQJvNPEwkM7NEKSiv/gqOsoSQbVoWyqVEY5GS+XPQ88zLNmqASRpzfdm8d79hJS+w== dependencies: async "^2.5.0" optimist "^0.6.1" @@ -6888,16 +7003,6 @@ handlebars@^4.0.11: optionalDependencies: uglify-js "^3.1.4" -handlebars@^4.0.3: - version "4.0.11" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" - dependencies: - async "^1.4.0" - optimist "^0.6.1" - source-map "^0.4.4" - optionalDependencies: - uglify-js "^2.6" - har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" @@ -6950,6 +7055,7 @@ has-flag@^1.0.0: has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= has-flag@^3.0.0: version "3.0.0" @@ -7222,12 +7328,6 @@ home-or-tmp@^2.0.0: os-homedir "^1.0.0" os-tmpdir "^1.0.1" -homedir-polyfill@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" - dependencies: - parse-passwd "^1.0.0" - hosted-git-info@^2.1.4: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" @@ -7279,7 +7379,19 @@ htmlescape@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" -htmlparser2@^3.8.2, htmlparser2@^3.9.0, htmlparser2@^3.9.1, htmlparser2@^3.9.2: +htmlparser2@^3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.0.tgz#5f5e422dcf6119c0d983ed36260ce9ded0bee464" + integrity sha512-J1nEUGv+MkXS0weHNWVKJJ+UrLfePxRWpN3C9bEi9fLxL2+ggW94DQvgYVXsaT30PGwYRIZKNZXuyMhp3Di4bQ== + dependencies: + domelementtype "^1.3.0" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.0.6" + +htmlparser2@^3.9.0, htmlparser2@^3.9.1: version "3.9.2" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" dependencies: @@ -7395,10 +7507,15 @@ ignore@^3.3.5: version "3.3.7" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" -ignore@^4.0.0, ignore@^4.0.6: +ignore@^4.0.3, ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" +ignore@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.4.tgz#33168af4a21e99b00c5d41cbadb6a6cb49903a45" + integrity sha512-WLsTMEhsQuXpCiG173+f3aymI43SXa+fB1rSfbzyP4GkPP+ZFVuO0/3sFUGNBtifisPeDcl/uD/Y2NxZ7xFq4g== + imagemin-mozjpeg@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/imagemin-mozjpeg/-/imagemin-mozjpeg-8.0.0.tgz#d2ca4e8c982c7c6eda55069af89dee4c1cebcdfd" @@ -7443,15 +7560,37 @@ immutable@^3: version "3.8.2" resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" -import-lazy@^2.1.0: +import-cwd@^2.0.0: version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - -import-lazy@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" + resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" + integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= + dependencies: + import-from "^2.1.0" -imurmurhash@^0.1.4: +import-fresh@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.0.0.tgz#a3d897f420cab0e671236897f75bc14b4885c390" + integrity sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-from@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" + integrity sha1-M1238qev/VOqpHHUuAId7ja387E= + dependencies: + resolve-from "^3.0.0" + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + +import-lazy@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" + +imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -7492,7 +7631,7 @@ inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" -ini@^1.3.3, ini@^1.3.4, ini@~1.3.0: +ini@^1.3.3, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" @@ -7502,22 +7641,23 @@ inline-source-map@~0.6.0: dependencies: source-map "~0.5.3" -inquirer@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.0.tgz#51adcd776f661369dc1e894859c2560a224abdd8" +inquirer@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406" + integrity sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA== dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" + ansi-escapes "^3.2.0" + chalk "^2.4.2" cli-cursor "^2.1.0" cli-width "^2.0.0" - external-editor "^3.0.0" + external-editor "^3.0.3" figures "^2.0.0" - lodash "^4.17.10" + lodash "^4.17.11" mute-stream "0.0.7" run-async "^2.2.0" - rxjs "^6.1.0" + rxjs "^6.4.0" string-width "^2.1.0" - strip-ansi "^4.0.0" + strip-ansi "^5.0.0" through "^2.3.6" insert-module-globals@^7.0.0: @@ -7554,6 +7694,11 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + ip-regex@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" @@ -7737,6 +7882,7 @@ is-finite@^1.0.0: is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" @@ -7915,10 +8061,6 @@ is-relative@^1.0.0: dependencies: is-unc-path "^1.0.0" -is-resolvable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - is-retry-allowed@^1.0.0, is-retry-allowed@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" @@ -8008,6 +8150,7 @@ isarray@0.0.1, isarray@~0.0.1: isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isarray@2.0.1: version "2.0.1" @@ -8038,102 +8181,57 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -istanbul-lib-coverage@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.2.tgz#4113c8ff6b7a40a1ef7350b01016331f63afde14" - -istanbul-lib-coverage@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0" - -istanbul-lib-coverage@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#2aee0e073ad8c5f6a0b00e0dfbf52b4667472eda" - -istanbul-lib-hook@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.1.0.tgz#8538d970372cb3716d53e55523dd54b557a8d89b" - dependencies: - append-transform "^0.4.0" +istanbul-lib-coverage@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#0b891e5ad42312c2b9488554f603795f9a2211ba" + integrity sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw== -istanbul-lib-hook@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.1.tgz#918a57b75a0f951d552a08487ca1fa5336433d72" +istanbul-lib-hook@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz#e0e581e461c611be5d0e5ef31c5f0109759916fb" + integrity sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA== dependencies: append-transform "^1.0.0" -istanbul-lib-instrument@^1.10.0: - version "1.10.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca" - dependencies: - babel-generator "^6.18.0" - babel-template "^6.16.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" - babylon "^6.18.0" - istanbul-lib-coverage "^1.2.1" - semver "^5.3.0" - -istanbul-lib-instrument@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.0.0.tgz#b5f066b2a161f75788be17a9d556f40a0cf2afc9" +istanbul-lib-instrument@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz#a2b5484a7d445f1f311e93190813fa56dfb62971" + integrity sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA== dependencies: "@babel/generator" "^7.0.0" "@babel/parser" "^7.0.0" "@babel/template" "^7.0.0" "@babel/traverse" "^7.0.0" "@babel/types" "^7.0.0" - istanbul-lib-coverage "^2.0.1" + istanbul-lib-coverage "^2.0.3" semver "^5.5.0" -istanbul-lib-report@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.3.tgz#2df12188c0fa77990c0d2176d2d0ba3394188259" - dependencies: - istanbul-lib-coverage "^1.1.2" - mkdirp "^0.5.1" - path-parse "^1.0.5" - supports-color "^3.1.2" - -istanbul-lib-report@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.2.tgz#430a2598519113e1da7af274ba861bd42dd97535" +istanbul-lib-report@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.4.tgz#bfd324ee0c04f59119cb4f07dab157d09f24d7e4" + integrity sha512-sOiLZLAWpA0+3b5w5/dq0cjm2rrNdAfHWaGhmn7XEFW6X++IV9Ohn+pnELAl9K3rfpaeBfbmH9JU5sejacdLeA== dependencies: - istanbul-lib-coverage "^2.0.1" + istanbul-lib-coverage "^2.0.3" make-dir "^1.3.0" - supports-color "^5.4.0" - -istanbul-lib-source-maps@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.3.tgz#20fb54b14e14b3fb6edb6aca3571fd2143db44e6" - dependencies: - debug "^3.1.0" - istanbul-lib-coverage "^1.1.2" - mkdirp "^0.5.1" - rimraf "^2.6.1" - source-map "^0.5.3" + supports-color "^6.0.0" -istanbul-lib-source-maps@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-2.0.1.tgz#ce8b45131d8293fdeaa732f4faf1852d13d0a97e" +istanbul-lib-source-maps@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz#f1e817229a9146e8424a28e5d69ba220fda34156" + integrity sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ== dependencies: - debug "^3.1.0" - istanbul-lib-coverage "^2.0.1" + debug "^4.1.1" + istanbul-lib-coverage "^2.0.3" make-dir "^1.3.0" rimraf "^2.6.2" source-map "^0.6.1" -istanbul-reports@^1.4.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a" - dependencies: - handlebars "^4.0.3" - -istanbul-reports@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.0.1.tgz#fb8d6ea850701a3984350b977a969e9a556116a7" +istanbul-reports@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.1.1.tgz#72ef16b4ecb9a4a7bd0e2001e00f95d1eec8afa9" + integrity sha512-FzNahnidyEPBCI0HcufJoSEoKykesRlFcSzQqjH9x0+LC8tnnE/p/90PBLu8iZTxr8yYZNyTtiAujUqyN+CIxw== dependencies: - handlebars "^4.0.11" + handlebars "^4.1.0" isurl@^1.0.0-alpha5: version "1.0.0" @@ -8142,10 +8240,10 @@ isurl@^1.0.0-alpha5: has-to-string-tag-x "^1.2.0" is-object "^1.0.1" -jest-worker@^24.0.0-alpha.9: - version "24.0.0-alpha.13" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0-alpha.13.tgz#388d2136af6bdda63e27d5f0f5a09c671cccda3e" - integrity sha512-euVesuF7gpHuwsKPnUdVeB8yHcfgPKK/UF45WuvBjuJS5YD0sT+y1ngdubKrPeGGkxbWgSuU80jPtSnoHlO0fQ== +jest-worker@^24.0.0: + version "24.0.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.0.0.tgz#3d3483b077bf04f412f47654a27bba7e947f8b6d" + integrity sha512-s64/OThpfQvoCeHG963MiEZOAAxu8kHsaL/rCMF7lpdzo7vgF0CtPml9hfguOMgykgH/eOm4jFP4ibfHLruytg== dependencies: merge-stream "^1.0.1" supports-color "^6.1.0" @@ -8181,9 +8279,10 @@ js-yaml@^3.11.0, js-yaml@^3.12.0: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^3.4.3: - version "3.11.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" +js-yaml@^3.12.1: + version "3.13.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.0.tgz#38ee7178ac0eea2c97ff6d96fff4b18c7d8cf98e" + integrity sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -8279,6 +8378,11 @@ json-stringify-pretty-compact@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-1.1.0.tgz#4fa5b898f61a287d64828691baa822a41f3ad5ab" +json-stringify-pretty-compact@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/json-stringify-pretty-compact/-/json-stringify-pretty-compact-2.0.0.tgz#e77c419f52ff00c45a31f07f4c820c2433143885" + integrity sha512-WRitRfs6BGq4q8gTgOy4ek7iPFXjbra0H3PmDLKm2xnZ+Gh1HUhiKGgCZkSPNULlP7mvfu6FV/mOLhCarspADQ== + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -8287,6 +8391,13 @@ json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" +json5@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.0.tgz#e7a0c62c48285c628d20a10b85c89bb807c32850" + integrity sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ== + dependencies: + minimist "^1.2.0" + jsonfile@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" @@ -8336,9 +8447,10 @@ jsx-ast-utils@^2.0.1: dependencies: array-includes "^3.0.3" -just-extend@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-3.0.0.tgz#cee004031eaabf6406da03a7b84e4fe9d78ef288" +just-extend@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.0.2.tgz#f3f47f7dfca0f989c55410a7ebc8854b07108afc" + integrity sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw== jwa@^1.1.5: version "1.1.6" @@ -8389,9 +8501,10 @@ kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" -known-css-properties@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.9.0.tgz#28f8a7134cfa3b0aa08b1e5edf64a57f64fc23af" +known-css-properties@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.11.0.tgz#0da784f115ea77c76b81536d7052e90ee6c86a8a" + integrity sha512-bEZlJzXo5V/ApNNa5z375mJC6Nrz4vG43UgcSCrg2OHC+yuB6j0iDSrY7RQ/+PRofFB03wNIIt9iXIVLr4wc7w== labeled-stream-splicer@^2.0.0: version "2.0.0" @@ -8407,11 +8520,6 @@ latest-version@^3.0.0: dependencies: package-json "^4.0.0" -lave@^1.1.10: - version "1.1.10" - resolved "https://registry.yarnpkg.com/lave/-/lave-1.1.10.tgz#062207652c5502d7c6ff096c9de3995401f634d5" - integrity sha1-BiIHZSxVAtfG/wlsneOZVAH2NNU= - lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" @@ -8439,6 +8547,13 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + dependencies: + invert-kv "^2.0.0" + lcov-parse@^0.0.10: version "0.0.10" resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" @@ -8812,9 +8927,10 @@ lolex@^2.3.2: version "2.6.0" resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.6.0.tgz#cf9166f3c9dece3cdeb5d6b01fce50f14a1203e3" -lolex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-3.0.0.tgz#f04ee1a8aa13f60f1abd7b0e8f4213ec72ec193e" +lolex@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-3.1.0.tgz#1a7feb2fefd75b3e3a7f79f0e110d9476e294434" + integrity sha512-zFo5MgCJ0rZ7gQg69S4pqBsLURbFw11X68C18OcJjJQbqaXm2NoTrGl1IMM3TIz0/BnN1tIs2tzmmqvCsOMMjw== longest-streak@^2.0.1: version "2.0.2" @@ -8880,6 +8996,13 @@ magic-string@^0.25.1: dependencies: sourcemap-codec "^1.4.1" +magic-string@^0.25.2: + version "0.25.2" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.2.tgz#139c3a729515ec55e96e69e82a11fe890a293ad9" + integrity sha512-iLs9mPjh9IuTtRsqqhNGYcZXGei0Nh/A4xirrsqW7c+QhKVFL2vm7U09ru6cHRD22azaP/wMDgI+HCqbETMTtg== + dependencies: + sourcemap-codec "^1.4.4" + make-dir@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.2.0.tgz#6d6a49eead4aae296c53bbf3a1a008bd6c89469b" @@ -8893,6 +9016,26 @@ make-dir@^1.2.0, make-dir@^1.3.0: dependencies: pify "^3.0.0" +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-error@^1.1.1: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== + +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + map-cache@^0.2.0, map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -8905,10 +9048,6 @@ map-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" -map-stream@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" - map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -8939,22 +9078,6 @@ mathml-tag-names@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/mathml-tag-names/-/mathml-tag-names-2.0.1.tgz#8d41268168bf86d1102b98109e28e531e7a34578" -md5-hex@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" - dependencies: - md5-o-matic "^0.1.1" - -md5-hex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" - dependencies: - md5-o-matic "^0.1.1" - -md5-o-matic@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" - md5.js@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" @@ -9044,6 +9167,15 @@ mem@^1.1.0: dependencies: mimic-fn "^1.0.0" +mem@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.1.0.tgz#aeb9be2d21f47e78af29e4ac5978e8afa2ca5b8a" + integrity sha512-I5u6Q1x7wxO0kdOpYBB28xueHADYps5uty/zg936CiG8NTe5sJL8EjrCuLneuDW3PlMdZBGDIn8BirEVdovZvg== + dependencies: + map-age-cleaner "^0.1.1" + mimic-fn "^1.0.0" + p-is-promise "^2.0.0" + memory-fs@^0.4.0, memory-fs@~0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" @@ -9102,6 +9234,11 @@ merge2@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.1.tgz#271d2516ff52d4af7f7b710b8bf3e16e183fef66" +merge2@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" + integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== + micromatch@2.3.11, micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -9217,7 +9354,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -9246,6 +9383,7 @@ minimist@1.1.x: minimist@1.2.0, minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= minimist@~0.0.1: version "0.0.10" @@ -9257,17 +9395,17 @@ minipass@^2.2.0, minipass@^2.2.1: dependencies: yallist "^3.0.0" -minipass@^2.3.0, minipass@^2.3.4: - version "2.3.5" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" - integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== +minipass@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" -minipass@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" +minipass@^2.3.4, minipass@^2.3.5: + version "2.3.5" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" + integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" @@ -9480,15 +9618,16 @@ nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" -nise@^1.4.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/nise/-/nise-1.4.6.tgz#76cc3915925056ae6c405dd8ad5d12bde570c19f" +nise@^1.4.10: + version "1.4.10" + resolved "https://registry.yarnpkg.com/nise/-/nise-1.4.10.tgz#ae46a09a26436fae91a38a60919356ae6db143b6" + integrity sha512-sa0RRbj53dovjc7wombHmVli9ZihXbXCQ2uH3TNm03DyvOSIQbxg+pbqDKrk2oxMK1rtLGVlKxcB9rrc6X5YjA== dependencies: - "@sinonjs/formatio" "3.0.0" - just-extend "^3.0.0" + "@sinonjs/formatio" "^3.1.0" + "@sinonjs/text-encoding" "^0.7.1" + just-extend "^4.0.2" lolex "^2.3.2" path-to-regexp "^1.7.0" - text-encoding "^0.6.4" no-case@^2.2.0: version "2.3.2" @@ -9699,16 +9838,17 @@ npm-packlist@^1.1.6: ignore-walk "^3.0.1" npm-bundled "^1.0.1" -npm-run-all@^4.0.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.2.tgz#90d62d078792d20669139e718621186656cea056" +npm-run-all@^4.1.5: + version "4.1.5" + resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" + integrity sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ== dependencies: - ansi-styles "^3.2.0" - chalk "^2.1.0" - cross-spawn "^5.1.0" + ansi-styles "^3.2.1" + chalk "^2.4.1" + cross-spawn "^6.0.5" memorystream "^0.3.1" minimatch "^3.0.4" - ps-tree "^1.1.0" + pidtree "^0.3.0" read-pkg "^3.0.0" shell-quote "^1.6.1" string.prototype.padend "^3.0.0" @@ -9748,72 +9888,41 @@ num2fraction@^1.2.2: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= nwsapi@^2.0.9: version "2.0.9" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.9.tgz#77ac0cdfdcad52b6a1151a84e73254edc33ed016" -nyc@^11.8.0: - version "11.9.0" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.9.0.tgz#4106e89e8fbe73623a1fc8b6ecb7abaa271ae1e4" - dependencies: - archy "^1.0.0" - arrify "^1.0.1" - caching-transform "^1.0.0" - convert-source-map "^1.5.1" - debug-log "^1.0.1" - default-require-extensions "^1.0.0" - find-cache-dir "^0.1.1" - find-up "^2.1.0" - foreground-child "^1.5.3" - glob "^7.0.6" - istanbul-lib-coverage "^1.1.2" - istanbul-lib-hook "^1.1.0" - istanbul-lib-instrument "^1.10.0" - istanbul-lib-report "^1.1.3" - istanbul-lib-source-maps "^1.2.3" - istanbul-reports "^1.4.0" - md5-hex "^1.2.0" - merge-source-map "^1.1.0" - micromatch "^3.1.10" - mkdirp "^0.5.0" - resolve-from "^2.0.0" - rimraf "^2.6.2" - signal-exit "^3.0.1" - spawn-wrap "^1.4.2" - test-exclude "^4.2.0" - yargs "11.1.0" - yargs-parser "^8.0.0" - -nyc@^13.1.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-13.1.0.tgz#463665c7ff6b5798e322624a5eb449a678db90e3" +nyc@^13.1.0, nyc@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-13.3.0.tgz#da4dbe91a9c8b9ead3f4f3344c76f353e3c78c75" + integrity sha512-P+FwIuro2aFG6B0Esd9ZDWUd51uZrAEoGutqZxzrVmYl3qSfkLgcQpBPBjtDFsUQLFY1dvTQJPOyeqr8S9GF8w== dependencies: archy "^1.0.0" arrify "^1.0.1" - caching-transform "^2.0.0" + caching-transform "^3.0.1" convert-source-map "^1.6.0" - debug-log "^1.0.1" find-cache-dir "^2.0.0" find-up "^3.0.0" foreground-child "^1.5.6" glob "^7.1.3" - istanbul-lib-coverage "^2.0.1" - istanbul-lib-hook "^2.0.1" - istanbul-lib-instrument "^3.0.0" - istanbul-lib-report "^2.0.2" - istanbul-lib-source-maps "^2.0.1" - istanbul-reports "^2.0.1" + istanbul-lib-coverage "^2.0.3" + istanbul-lib-hook "^2.0.3" + istanbul-lib-instrument "^3.1.0" + istanbul-lib-report "^2.0.4" + istanbul-lib-source-maps "^3.0.2" + istanbul-reports "^2.1.1" make-dir "^1.3.0" merge-source-map "^1.1.0" resolve-from "^4.0.0" - rimraf "^2.6.2" + rimraf "^2.6.3" signal-exit "^3.0.2" spawn-wrap "^1.4.2" - test-exclude "^5.0.0" + test-exclude "^5.1.0" uuid "^3.3.2" - yargs "11.1.0" - yargs-parser "^9.0.2" + yargs "^12.0.5" + yargs-parser "^11.1.1" oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" @@ -9886,6 +9995,16 @@ object.entries@^1.1.0: function-bind "^1.1.1" has "^1.0.3" +object.fromentries@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.0.tgz#49a543d92151f8277b3ac9600f1e930b189d30ab" + integrity sha512-9iLiI6H083uiqUuvzyY6qrlmc/Gz8hLQFOcb/Ri/0xXFkSNS3ctV+CbE6yM2+AnkYfOB3dGjdzC0wrMLIhQICA== + dependencies: + define-properties "^1.1.2" + es-abstract "^1.11.0" + function-bind "^1.1.1" + has "^1.0.1" + object.getownpropertydescriptors@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" @@ -9938,9 +10057,10 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -opener@^1.4.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" +opener@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" + integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== openurl@1.1.1: version "1.1.1" @@ -10032,6 +10152,15 @@ os-locale@^2.0.0: lcid "^1.0.0" mem "^1.1.0" +os-locale@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + os-name@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/os-name/-/os-name-2.0.1.tgz#b9a386361c17ae3a21736ef0599405c9a8c5dc5e" @@ -10069,6 +10198,11 @@ p-cancelable@^0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + p-event@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-event/-/p-event-1.3.0.tgz#8e6b4f4f65c72bc5b6fe28b75eda874f96a4a085" @@ -10091,6 +10225,11 @@ p-is-promise@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" +p-is-promise@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.0.0.tgz#7554e3d572109a87e1f3f53f6a7d85d1b194f4c5" + integrity sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg== + p-limit@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c" @@ -10161,13 +10300,14 @@ p-try@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" -package-hash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-2.0.0.tgz#78ae326c89e05a4d813b68601977af05c00d2a0d" +package-hash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-3.0.0.tgz#50183f2d36c9e3e528ea0a8605dff57ce976f88e" + integrity sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA== dependencies: - graceful-fs "^4.1.11" + graceful-fs "^4.1.15" + hasha "^3.0.0" lodash.flattendeep "^4.4.0" - md5-hex "^2.0.0" release-zalgo "^1.0.0" package-json@^4.0.0: @@ -10197,6 +10337,13 @@ param-case@2.1.x: dependencies: no-case "^2.2.0" +parent-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.0.tgz#df250bdc5391f4a085fb589dad761f5ad6b865b5" + integrity sha512-8Mf5juOMmiE4FcmzYc4IaiS9L3+9paz2KOiXzkRviCP6aDmN49Hz6EMWz0lGNp9pX80GvvAuLADtyGfW/Em3TA== + dependencies: + callsites "^3.0.0" + parents@^1.0.0, parents@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" @@ -10280,10 +10427,6 @@ parse-node-version@^1.0.0: resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - parse-url@^1.3.0: version "1.3.11" resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-1.3.11.tgz#57c15428ab8a892b1f43869645c711d0e144b554" @@ -10407,12 +10550,6 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" -pause-stream@0.0.11: - version "0.0.11" - resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" - dependencies: - through "~2.3" - pbf@^3.0.5: version "3.1.0" resolved "https://registry.yarnpkg.com/pbf/-/pbf-3.1.0.tgz#f70004badcb281761eabb1e76c92f179f08189e9" @@ -10443,6 +10580,11 @@ performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" +pidtree@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.3.0.tgz#f6fada10fccc9f99bf50e90d0b23d72c9ebc2e6b" + integrity sha512-9CT4NFlDcosssyg8KVFltgokyKZIFjoBxw8CTGy+5F38Y1eQWrt8tRayiUOXE+zVKQnYu5BR8JjCtvK3BcnBhg== + pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -10471,18 +10613,19 @@ pirates@^3.0.2: dependencies: node-modules-regexp "^1.0.0" +pirates@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== + dependencies: + node-modules-regexp "^1.0.0" + pixelmatch@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854" dependencies: pngjs "^3.0.0" -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - dependencies: - find-up "^1.0.0" - pkg-dir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" @@ -10499,10 +10642,6 @@ platform@^1.3.3: version "1.3.5" resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444" -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - pn@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" @@ -10511,9 +10650,10 @@ pngjs@^3.0.0: version "3.3.2" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.2.tgz#097c3c2a75feb223eadddea6bc9f0050cf830bc3" -pngjs@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.3.tgz#85173703bde3edac8998757b96e5821d0966a21b" +pngjs@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" + integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== pngquant-bin@^4.0.0: version "4.0.0" @@ -10540,22 +10680,23 @@ posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" -postcss-cli@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-5.0.0.tgz#3d6aee7652b8dc6566f0189dd90d11bb0a535a20" +postcss-cli@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/postcss-cli/-/postcss-cli-6.1.2.tgz#9c24174614f4d2f6b5b6de8676fed992766173bc" + integrity sha512-jIWfIkqt8cTThSpH8DBaNxHlBf99OKSem2RseRpfVPqWayxHKQB0IWdS/IF5XSGeFU5QslSDTdVHnw6qggXGkA== dependencies: chalk "^2.1.0" chokidar "^2.0.0" - dependency-graph "^0.7.0" - fs-extra "^5.0.0" - get-stdin "^5.0.1" - globby "^7.1.1" - postcss "^6.0.1" - postcss-load-config "^1.1.0" - postcss-reporter "^5.0.0" + dependency-graph "^0.8.0" + fs-extra "^7.0.0" + get-stdin "^6.0.0" + globby "^9.0.0" + postcss "^7.0.0" + postcss-load-config "^2.0.0" + postcss-reporter "^6.0.0" pretty-hrtime "^1.0.3" read-cache "^1.0.0" - yargs "^11.0.0" + yargs "^12.0.1" postcss-csso@^3.0.0: version "3.0.0" @@ -10590,11 +10731,12 @@ postcss-discard-unused@^2.2.3: postcss "^5.0.14" uniqs "^2.0.0" -postcss-html@^0.34.0: - version "0.34.0" - resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.34.0.tgz#9bfd637ad8c3d3a43625b5ef844dc804b3370868" +postcss-html@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/postcss-html/-/postcss-html-0.36.0.tgz#b40913f94eaacc2453fd30a1327ad6ee1f88b204" + integrity sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw== dependencies: - htmlparser2 "^3.9.2" + htmlparser2 "^3.10.0" postcss-inline-svg@^3.1.1: version "3.1.1" @@ -10613,48 +10755,34 @@ postcss-js@^1.0.1: camelcase-css "^1.0.1" postcss "^6.0.11" -postcss-jsx@^0.35.0: - version "0.35.0" - resolved "https://registry.yarnpkg.com/postcss-jsx/-/postcss-jsx-0.35.0.tgz#1d6cb82393994cdc7e9aa421648e3f0f3f98209b" +postcss-jsx@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/postcss-jsx/-/postcss-jsx-0.36.0.tgz#b7685ed3d070a175ef0aa48f83d9015bd772c82d" + integrity sha512-/lWOSXSX5jlITCKFkuYU2WLFdrncZmjSVyNpHAunEgirZXLwI8RjU556e3Uz4mv0WVHnJA9d3JWb36lK9Yx99g== dependencies: - "@babel/core" "^7.1.2" - optionalDependencies: - postcss-styled ">=0.34.0" + "@babel/core" ">=7.1.0" -postcss-less@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.0.2.tgz#9cf94e2cc90f8566858939e278fb9f0b713908df" +postcss-less@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-less/-/postcss-less-3.1.1.tgz#87347038bf9cdec9c47722ecf97648bacd171cc3" + integrity sha512-yVa0hb03p7xj914Z4qDDA/PGwXYvCEfjJizWVYQvnEQr8SgJ098qejCvbCGk1dDYQpQEGKkvYHQCo66DwTocjg== dependencies: postcss "^7.0.3" -postcss-load-config@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-1.2.0.tgz#539e9afc9ddc8620121ebf9d8c3673e0ce50d28a" - dependencies: - cosmiconfig "^2.1.0" - object-assign "^4.1.0" - postcss-load-options "^1.2.0" - postcss-load-plugins "^2.3.0" - -postcss-load-options@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postcss-load-options/-/postcss-load-options-1.2.0.tgz#b098b1559ddac2df04bc0bb375f99a5cfe2b6d8c" - dependencies: - cosmiconfig "^2.1.0" - object-assign "^4.1.0" - -postcss-load-plugins@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz#745768116599aca2f009fad426b00175049d8d92" +postcss-load-config@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.0.0.tgz#f1312ddbf5912cd747177083c5ef7a19d62ee484" + integrity sha512-V5JBLzw406BB8UIfsAWSK2KSwIJ5yoEIVFb4gVkXci0QdKgA24jLmHZ/ghe/GgX0lJ0/D1uUK1ejhzEY94MChQ== dependencies: - cosmiconfig "^2.1.1" - object-assign "^4.1.0" + cosmiconfig "^4.0.0" + import-cwd "^2.0.0" -postcss-markdown@^0.34.0: - version "0.34.0" - resolved "https://registry.yarnpkg.com/postcss-markdown/-/postcss-markdown-0.34.0.tgz#7a043e6eee3ab846a4cefe3ab43d141038e2da79" +postcss-markdown@^0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/postcss-markdown/-/postcss-markdown-0.36.0.tgz#7f22849ae0e3db18820b7b0d5e7833f13a447560" + integrity sha512-rl7fs1r/LNSB2bWRhyZ+lM/0bwKv9fhl38/06gF6mKMo/NPnp55+K1dSTosSVjFZc0e1ppBlu+WT91ba0PMBfQ== dependencies: - remark "^9.0.0" + remark "^10.0.1" unist-util-find-all-after "^1.0.2" postcss-media-query-parser@^0.2.3: @@ -10689,9 +10817,10 @@ postcss-safe-parser@^4.0.0: dependencies: postcss "^7.0.0" -postcss-sass@^0.3.0: - version "0.3.3" - resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.3.3.tgz#bec188ac285d21ac8feba194c2f327fdda31e671" +postcss-sass@^0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/postcss-sass/-/postcss-sass-0.3.5.tgz#6d3e39f101a53d2efa091f953493116d32beb68c" + integrity sha512-B5z2Kob4xBxFjcufFnhQ2HqJQ2y/Zs/ic5EZbCywCkxKd756Q40cIQ/veRDwSrw1BF6+4wUgmpm0sBASqVi65A== dependencies: gonzales-pe "^4.2.3" postcss "^7.0.1" @@ -10710,13 +10839,10 @@ postcss-selector-parser@^3.1.0, postcss-selector-parser@^3.1.1: indexes-of "^1.0.1" uniq "^1.0.1" -postcss-styled@>=0.34.0, postcss-styled@^0.34.0: - version "0.34.0" - resolved "https://registry.yarnpkg.com/postcss-styled/-/postcss-styled-0.34.0.tgz#07d47bcb13707289782aa058605fd9feaf84391d" - -postcss-syntax@^0.34.0: - version "0.34.0" - resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.34.0.tgz#4a85c022f1cdecea72102775c91af1e7f506d83a" +postcss-syntax@^0.36.2: + version "0.36.2" + resolved "https://registry.yarnpkg.com/postcss-syntax/-/postcss-syntax-0.36.2.tgz#f08578c7d95834574e5593a82dfbfa8afae3b51c" + integrity sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w== postcss-url@^8.0.0: version "8.0.0" @@ -10883,6 +11009,7 @@ process-nextick-args@^1.0.6, process-nextick-args@~1.0.6: process-nextick-args@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + integrity sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw== process@^0.11.10, process@~0.11.0: version "0.11.10" @@ -10965,12 +11092,6 @@ prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" -ps-tree@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.1.0.tgz#b421b24140d6203f1ed3c76996b4427b08e8c014" - dependencies: - event-stream "~3.3.0" - pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -11196,14 +11317,15 @@ react-displace@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/react-displace/-/react-displace-2.3.0.tgz#6915f8f2f279a29a7b58442405c26edc3d441429" -react-dom@^16.7.0: - version "16.7.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.7.0.tgz#a17b2a7ca89ee7390bc1ed5eb81783c7461748b8" +react-dom@16.3.3: + version "16.3.3" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.3.3.tgz#af4c2aef9f6a66251a46da50253c860a67ae66d9" + integrity sha512-ALCp7ZbSGkqRDtQoZozKVNgwXMxbxf/IGOUMC2A0yF6JHeZrS8e2cOotPT87Vf4b7PKCuUVKU4/RDEXxToA/yA== dependencies: + fbjs "^0.8.16" loose-envify "^1.1.0" object-assign "^4.1.1" - prop-types "^15.6.2" - scheduler "^0.12.0" + prop-types "^15.6.0" react-helmet@^5.2.0: version "5.2.0" @@ -11327,7 +11449,7 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -"readable-stream@1 || 2", readable-stream@^2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3: +"readable-stream@1 || 2", readable-stream@^2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.3.3: version "2.3.4" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.4.tgz#c946c3f47fa7d8eabc0b6150f4a12f69a4574071" dependencies: @@ -11348,7 +11470,7 @@ readable-stream@1.0, "readable-stream@>=1.0.33-1 <1.1.0-0": isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.3.0: +readable-stream@^2.2.2, readable-stream@^2.3.0: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -11361,6 +11483,15 @@ readable-stream@^2.3.0: string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.0.6: + version "3.1.1" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.1.1.tgz#ed6bbc6c5ba58b090039ff18ce670515795aeb06" + integrity sha512-DkN66hPyqDhnIQ6Jcsvx9bFjhw214O4poMBcIMgPVpQvNy9a0e0Uhg5SqySyDKAmUlwt8LonTBz1ezOnM8pUdA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@~1.1.0, readable-stream@~1.1.9: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" @@ -11786,7 +11917,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.0" tough-cookie ">=2.3.3" -request@2, request@^2.79.0: +request@2: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" dependencies: @@ -11840,7 +11971,7 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" -request@^2.85.0, request@^2.88.0: +request@^2.86.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" dependencies: @@ -11869,39 +12000,22 @@ require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" -require-from-string@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" +require-from-string@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" -require-uncached@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - requires-port@1.x.x: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" -resolve-dir@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.0.0" - -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - -resolve-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" resolve-from@^4.0.0: version "4.0.0" @@ -11933,19 +12047,19 @@ resolve@^1.1.3, resolve@^1.1.4, resolve@^1.4.0, resolve@^1.5.0: dependencies: path-parse "^1.0.5" -resolve@^1.3.2, resolve@^1.6.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - dependencies: - path-parse "^1.0.5" - -resolve@^1.8.1: +resolve@^1.10.0, resolve@^1.8.1, resolve@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== dependencies: path-parse "^1.0.6" +resolve@^1.3.2: + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + dependencies: + path-parse "^1.0.5" + resp-modifier@6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/resp-modifier/-/resp-modifier-6.0.2.tgz#b124de5c4fbafcba541f48ffa73970f4aa456b4f" @@ -11982,7 +12096,7 @@ rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2. dependencies: glob "^7.0.5" -rimraf@^2.2.6: +rimraf@2.6.3, rimraf@^2.2.6, rimraf@^2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -12004,40 +12118,39 @@ rollup-plugin-buble@^0.19.6: buble "^0.19.6" rollup-pluginutils "^2.3.3" -rollup-plugin-commonjs@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.2.0.tgz#4604e25069e0c78a09e08faa95dc32dec27f7c89" - integrity sha512-0RM5U4Vd6iHjL6rLvr3lKBwnPsaVml+qxOGaaNUWN1lSq6S33KhITOfHmvxV3z2vy9Mk4t0g4rNlVaJJsNQPWA== +rollup-plugin-commonjs@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-9.2.2.tgz#4959f3ff0d9706c132e5247b47ab385f11d9aae6" + integrity sha512-FXBgY+IvZIV2AZVT/0CPMsP+b1dKkxE+F6SHI9wddqKDV9KCGDA2cV5e/VsJLwXKFgrtliqMr7Rq3QBfPiJ8Xg== dependencies: - estree-walker "^0.5.2" - magic-string "^0.25.1" - resolve "^1.8.1" - rollup-pluginutils "^2.3.3" + estree-walker "^0.6.0" + magic-string "^0.25.2" + resolve "^1.10.0" + rollup-pluginutils "^2.5.0" -rollup-plugin-json@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-3.1.0.tgz#7c1daf60c46bc21021ea016bd00863561a03321b" - integrity sha512-BlYk5VspvGpjz7lAwArVzBXR60JK+4EKtPkCHouAWg39obk9S61hZYJDBfMK+oitPdoe11i69TlxKlMQNFC/Uw== +rollup-plugin-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz#a18da0a4b30bf5ca1ee76ddb1422afbb84ae2b9e" + integrity sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow== dependencies: - rollup-pluginutils "^2.3.1" + rollup-pluginutils "^2.5.0" -rollup-plugin-node-resolve@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.0.0.tgz#9bc6b8205e9936cc0e26bba2415f1ecf1e64d9b2" - integrity sha512-7Ni+/M5RPSUBfUaP9alwYQiIKnKeXCOHiqBpKUl9kwp3jX5ZJtgXAait1cne6pGEVUUztPD6skIKH9Kq9sNtfw== +rollup-plugin-node-resolve@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-4.0.1.tgz#f95765d174e5daeef9ea6268566141f53aa9d422" + integrity sha512-fSS7YDuCe0gYqKsr5OvxMloeZYUSgN43Ypi1WeRZzQcWtHgFayV5tUSPYpxuaioIIWaBXl6NrVk0T2/sKwueLg== dependencies: builtin-modules "^3.0.0" is-module "^1.0.0" - resolve "^1.8.1" + resolve "^1.10.0" -rollup-plugin-replace@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-replace/-/rollup-plugin-replace-2.1.0.tgz#f9c07a4a89a2f8be912ee54b3f0f68d91e9ed0ae" - integrity sha512-SxrAIgpH/B5/W4SeULgreOemxcpEgKs2gcD42zXw50bhqGWmcnlXneVInQpAqzA/cIly4bJrOpeelmB9p4YXSQ== +rollup-plugin-replace@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-replace/-/rollup-plugin-replace-2.1.1.tgz#e49cb8d07d6f91a7bf28b90b66692f2c8c0b9bba" + integrity sha512-IS5ZYBb3px0UfbDCYzKaKxelLd5dbPHhfplEXbymfvGlz9Ok44At4AjTOWe2qEax73bE8+pnMZN9C7PcVpFNlw== dependencies: - magic-string "^0.25.1" - minimatch "^3.0.2" - rollup-pluginutils "^2.0.1" + magic-string "^0.25.2" + rollup-pluginutils "^2.4.1" rollup-plugin-sourcemaps@^0.4.2: version "0.4.2" @@ -12046,15 +12159,14 @@ rollup-plugin-sourcemaps@^0.4.2: rollup-pluginutils "^2.0.1" source-map-resolve "^0.5.0" -rollup-plugin-terser@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-4.0.2.tgz#78936d182ae7c4ecb313403ff5d5faad1b69e2aa" - integrity sha512-M2vY7NPMa3N77/avJSJyBva4nyBTiUM0kgMoWwEAeo2Edl3MW/GoM0069FzVrfMYP3xDqcVrDbaIOqVaBD8lHQ== +rollup-plugin-terser@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-4.0.4.tgz#6f661ef284fa7c27963d242601691dc3d23f994e" + integrity sha512-wPANT5XKVJJ8RDUN0+wIr7UPd0lIXBo4UdJ59VmlPCtlFsE20AM+14pe+tk7YunCsWEiuzkDBY3QIkSCjtrPXg== dependencies: "@babel/code-frame" "^7.0.0" - escodegen "^1.11.0" - jest-worker "^24.0.0-alpha.9" - lave "^1.1.10" + jest-worker "^24.0.0" + serialize-javascript "^1.6.1" terser "^3.14.1" rollup-plugin-unassert@^0.2.0: @@ -12075,7 +12187,7 @@ rollup-pluginutils@^2.0.1: estree-walker "^0.3.0" micromatch "^2.3.11" -rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.3.3: +rollup-pluginutils@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.3.3.tgz#3aad9b1eb3e7fe8262820818840bf091e5ae6794" integrity sha512-2XZwja7b6P5q4RZ5FhyX1+f46xi1Z3qBKigLRZ6VTZjwbN0K1IFGMlwm06Uu0Emcre2Z63l77nq/pzn+KxIEoA== @@ -12083,14 +12195,22 @@ rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.3.3: estree-walker "^0.5.2" micromatch "^2.3.11" -rollup@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.1.2.tgz#8d094b85683b810d0c05a16bd7618cf70d48eba7" - integrity sha512-OkdMxqMl8pWoQc5D8y1cIinYQPPLV8ZkfLgCzL6SytXeNA2P7UHynEQXI9tYxuAjAMsSyvRaWnyJDLHMxq0XAg== +rollup-pluginutils@^2.4.1, rollup-pluginutils@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.5.0.tgz#23be0f05ac3972ea7b08fc7870cb91fde5b23a09" + integrity sha512-9Muh1H+XB5f5ONmKMayUoTYR1EZwHbwJJ9oZLrKT5yuTf/RLIQ5mYIGsrERquVucJmjmaAW0Y7+6Qo1Ep+5w3Q== + dependencies: + estree-walker "^0.6.0" + micromatch "^3.1.10" + +rollup@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.7.3.tgz#cade518b92e23efa72026e264e29d9a56cbf8eb9" + integrity sha512-U3/HaZujvGofNZQldfIknKoaNFNRS+j8/uCS/jSy3FrxF9t0FBsgZW4+VXLHG7l1daTgE6+jEy0Dv7cVCB2NPg== dependencies: "@types/estree" "0.0.39" - "@types/node" "*" - acorn "^6.0.5" + "@types/node" "^11.11.6" + acorn "^6.1.1" run-async@^2.2.0: version "2.3.0" @@ -12118,17 +12238,19 @@ rxjs@^5.5.6: dependencies: symbol-observable "1.0.1" -rxjs@^6.1.0: - version "6.3.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.3.tgz#3c6a7fa420e844a81390fb1158a9ec614f4bad55" +rxjs@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" + integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== dependencies: tslib "^1.9.0" -safe-buffer@5.1.2, safe-buffer@^5.1.2: +safe-buffer@5.1.2, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -12263,6 +12385,11 @@ serialize-javascript@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.4.0.tgz#7c958514db6ac2443a8abc062dc9f7886a7f6005" +serialize-javascript@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-1.6.1.tgz#4d1f697ec49429a847ca6f442a2a755126c4d879" + integrity sha512-A5MOagrPFga4YaKQSWHryl7AXvbQkEqpw4NNYMTNYUNV51bA8ABHgYFpqKx+YFFrw59xMV1qGH1R4AgoNIVgCw== + serve-index@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" @@ -12409,7 +12536,7 @@ shuffle-seed@^1.1.6: dependencies: seedrandom "^2.4.2" -signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: +signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -12441,19 +12568,18 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" -sinon@^7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.1.1.tgz#1202f317aa14d93cb9b69ff50b6bd49c0e05ffc9" +sinon@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.3.0.tgz#fd409432bf2ef8ee6a302cf47ca1b0c95fd4de38" + integrity sha512-0pYvgRv46fODzT/PByqb79MVNpyxsxf38WEiXTABOF8RfIMcIARfZ+1ORuxwAmHkreZ/jST3UDBdKCRhUy/e1A== dependencies: - "@sinonjs/commons" "^1.2.0" - "@sinonjs/formatio" "^3.0.0" - "@sinonjs/samsam" "^2.1.2" + "@sinonjs/commons" "^1.4.0" + "@sinonjs/formatio" "^3.2.1" + "@sinonjs/samsam" "^3.3.0" diff "^3.5.0" - lodash.get "^4.4.2" - lolex "^3.0.0" - nise "^1.4.6" + lolex "^3.1.0" + nise "^1.4.10" supports-color "^5.5.0" - type-detect "^4.0.8" sitemap-static@^0.4.4: version "0.4.4" @@ -12466,15 +12592,24 @@ slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + slice-ansi@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" dependencies: is-fullwidth-code-point "^2.0.0" -slide@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" slugg@^1.2.1: version "1.2.1" @@ -12639,16 +12774,16 @@ source-map-support@^0.4.15: dependencies: source-map "^0.5.6" -source-map-support@^0.5.6, source-map-support@~0.5.6: - version "0.5.9" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" +source-map-support@^0.5.10, source-map-support@^0.5.9: + version "0.5.10" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" dependencies: buffer-from "^1.0.0" source-map "^0.6.0" -source-map-support@^0.5.9: - version "0.5.10" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.10.tgz#2214080bc9d51832511ee2bab96e3c2f9353120c" +source-map-support@^0.5.6, source-map-support@~0.5.6: + version "0.5.9" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -12667,17 +12802,11 @@ source-map@^0.1.34: dependencies: amdefine ">=0.0.4" -source-map@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - dependencies: - amdefine ">=0.0.4" - source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" -sourcemap-codec@^1.4.1: +sourcemap-codec@^1.4.1, sourcemap-codec@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.4.tgz#c63ea927c029dd6bd9a2b7fa03b3fec02ad56e9f" integrity sha512-CYAPYdBu34781kLHkaW3m6b/uUSyMOC2R61gcYMWooeuaGtjof86ZA/8T+qVPPt7np1085CR9hmMGrySwEc8Xg== @@ -12728,12 +12857,6 @@ split-string@^3.0.1, split-string@^3.0.2: dependencies: extend-shallow "^3.0.0" -split@0.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" - dependencies: - through "2" - split@~0.2.10: version "0.2.10" resolved "https://registry.yarnpkg.com/split/-/split-0.2.10.tgz#67097c601d697ce1368f418f06cd201cf0521a57" @@ -12774,7 +12897,7 @@ ssri@^5.2.4: dependencies: safe-buffer "^5.1.1" -st@^1.1.0, st@^1.2.0: +st@^1.1.0, st@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/st/-/st-1.2.2.tgz#b95554f41b457bf0ed1c48f2bad8fccff894b14f" dependencies: @@ -12790,9 +12913,10 @@ stable@~0.1.6: version "0.1.8" resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" -stack-utils@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" +stack-utils@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" + integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== stat-mode@^0.2.0: version "0.2.2" @@ -12846,12 +12970,6 @@ stream-combiner2@^1.1.1: duplexer2 "~0.1.0" readable-stream "^2.0.2" -stream-combiner@~0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - dependencies: - duplexer "~0.1.1" - stream-each@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.2.tgz#8e8c463f91da8991778765873fe4d960d8f616bd" @@ -12905,6 +13023,7 @@ string-template@~0.2.1: string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" @@ -12917,6 +13036,15 @@ string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + string.prototype.padend@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/string.prototype.padend/-/string.prototype.padend-3.0.0.tgz#f3aaef7c1719f170c5eab1c32bf780d96e21f2f0" @@ -12929,9 +13057,17 @@ string_decoder@0.10, string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" -string_decoder@^1.0.0, string_decoder@~1.0.0, string_decoder@~1.0.3: +string_decoder@^1.0.0, string_decoder@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ== + dependencies: + safe-buffer "~5.1.0" + +string_decoder@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" + integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== dependencies: safe-buffer "~5.1.0" @@ -12984,6 +13120,13 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.0.0, strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + strip-bom-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" @@ -13071,9 +13214,10 @@ stylelint-config-standard@^18.2.0: dependencies: stylelint-config-recommended "^2.1.0" -stylelint@^9.7.1: - version "9.7.1" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-9.7.1.tgz#522f8795832a9f7e062e5e4105c0e05fb53f827f" +stylelint@^9.10.1: + version "9.10.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-9.10.1.tgz#5f0ee3701461dff1d68284e1386efe8f0677a75d" + integrity sha512-9UiHxZhOAHEgeQ7oLGwrwoDR8vclBKlSX7r4fH0iuu0SfPwFaLkb1c7Q2j1cqg9P7IDXeAV2TvQML/fRQzGBBQ== dependencies: autoprefixer "^9.0.0" balanced-match "^1.0.0" @@ -13081,43 +13225,43 @@ stylelint@^9.7.1: cosmiconfig "^5.0.0" debug "^4.0.0" execall "^1.0.0" - file-entry-cache "^2.0.0" + file-entry-cache "^4.0.0" get-stdin "^6.0.0" - global-modules "^1.0.0" - globby "^8.0.0" + global-modules "^2.0.0" + globby "^9.0.0" globjoin "^0.1.4" html-tags "^2.0.0" - ignore "^4.0.0" + ignore "^5.0.4" import-lazy "^3.1.0" imurmurhash "^0.1.4" - known-css-properties "^0.9.0" + known-css-properties "^0.11.0" leven "^2.1.0" lodash "^4.17.4" log-symbols "^2.0.0" mathml-tag-names "^2.0.1" meow "^5.0.0" - micromatch "^2.3.11" + micromatch "^3.1.10" normalize-selector "^0.2.0" pify "^4.0.0" - postcss "^7.0.0" - postcss-html "^0.34.0" - postcss-jsx "^0.35.0" - postcss-less "^3.0.1" - postcss-markdown "^0.34.0" + postcss "^7.0.13" + postcss-html "^0.36.0" + postcss-jsx "^0.36.0" + postcss-less "^3.1.0" + postcss-markdown "^0.36.0" postcss-media-query-parser "^0.2.3" postcss-reporter "^6.0.0" postcss-resolve-nested-selector "^0.1.1" postcss-safe-parser "^4.0.0" - postcss-sass "^0.3.0" + postcss-sass "^0.3.5" postcss-scss "^2.0.0" postcss-selector-parser "^3.1.0" - postcss-styled "^0.34.0" - postcss-syntax "^0.34.0" + postcss-syntax "^0.36.2" postcss-value-parser "^3.3.0" resolve-from "^4.0.0" signal-exit "^3.0.2" + slash "^2.0.0" specificity "^0.4.1" - string-width "^2.1.0" + string-width "^3.0.0" style-search "^0.1.0" sugarss "^2.0.0" svg-tags "^1.0.0" @@ -13161,7 +13305,7 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^3.1.2, supports-color@^3.2.3: +supports-color@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: @@ -13170,6 +13314,7 @@ supports-color@^3.1.2, supports-color@^3.2.3: supports-color@^4.2.1: version "4.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + integrity sha1-vnoN5ITexcXN34s9WRJQRJEvY1s= dependencies: has-flag "^2.0.0" @@ -13191,7 +13336,7 @@ supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^6.1.0: +supports-color@^6.0.0, supports-color@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== @@ -13246,7 +13391,7 @@ tabbable@^3.1.0, tabbable@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-3.1.2.tgz#f2d16cccd01f400e38635c7181adfe0ad965a4a2" -table@^5.0.0, table@^5.0.2: +table@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/table/-/table-5.1.0.tgz#69a54644f6f01ad1628f8178715b408dc6bf11f7" dependencies: @@ -13255,9 +13400,20 @@ table@^5.0.0, table@^5.0.2: slice-ansi "1.0.0" string-width "^2.1.1" +table@^5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" + integrity sha512-N2RsDAMvDLvYwFcwbPyF3VmVSSkuF+G1e+8inhBLtHpvwXGw4QRPEZhihQNeEN0i1up6/f6ObCJXNdlRG3YVyQ== + dependencies: + ajv "^6.9.1" + lodash "^4.17.11" + slice-ansi "^2.1.0" + string-width "^3.0.0" + tap-mocha-reporter@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/tap-mocha-reporter/-/tap-mocha-reporter-3.0.7.tgz#235e57893b500861ea5d0924965dadfb2f05eaa7" + version "3.0.9" + resolved "https://registry.yarnpkg.com/tap-mocha-reporter/-/tap-mocha-reporter-3.0.9.tgz#ea41e741149a94c278d106cbcccc37fec2dfeeaa" + integrity sha512-VO07vhC9EG27EZdOe7bWBj1ldbK+DL9TnRadOgdQmiQOVZjFpUEQuuqO7+rNSO2kfmkq5hWeluYXDWNG/ytXTQ== dependencies: color-support "^1.1.0" debug "^2.1.3" @@ -13287,37 +13443,42 @@ tap-parser@^7.0.0: js-yaml "^3.2.7" minipass "^2.2.0" -tap@^12.0.1: - version "12.0.1" - resolved "https://registry.yarnpkg.com/tap/-/tap-12.0.1.tgz#748f103d3ae84dce21e555b7112ec5a19adeb6d0" +tap@~12.4.1: + version "12.4.1" + resolved "https://registry.yarnpkg.com/tap/-/tap-12.4.1.tgz#0c50480291c8bfffe889e448a847b66a8f2fd809" + integrity sha512-hWh6V5cIIHwvXwmNb3fL/3athC9NyZuL4ZoiyHUHXqRAJJ6/SBmGX7IOfzj/Pf7EzFy9JwDCw/64eOyKx8XikA== dependencies: bind-obj-methods "^2.0.0" - bluebird "^3.5.1" + browser-process-hrtime "^1.0.0" + capture-stack-trace "^1.0.0" clean-yaml-object "^0.1.0" color-support "^1.1.0" - coveralls "^3.0.1" + coveralls "^3.0.2" + domain-browser "^1.2.0" foreground-child "^1.3.3" fs-exists-cached "^1.0.0" function-loop "^1.0.1" - glob "^7.0.0" + glob "^7.1.3" isexe "^2.0.0" - js-yaml "^3.11.0" - minipass "^2.3.0" + js-yaml "^3.12.1" + minipass "^2.3.5" mkdirp "^0.5.1" - nyc "^11.8.0" - opener "^1.4.1" + nyc "^13.1.0" + opener "^1.5.1" os-homedir "^1.0.2" own-or "^1.0.0" own-or-env "^1.0.1" - rimraf "^2.6.2" + rimraf "^2.6.3" signal-exit "^3.0.0" - source-map-support "^0.5.6" - stack-utils "^1.0.0" + source-map-support "^0.5.10" + stack-utils "^1.0.2" tap-mocha-reporter "^3.0.7" tap-parser "^7.0.0" tmatch "^4.0.0" trivial-deferred "^1.0.1" - tsame "^2.0.0" + ts-node "^8.0.1" + tsame "^2.0.1" + typescript "^3.2.4" write-file-atomic "^2.3.0" yapool "^1.0.0" @@ -13457,29 +13618,16 @@ terser@^3.14.1: source-map "~0.6.1" source-map-support "~0.5.6" -test-exclude@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.0.tgz#07e3613609a362c74516a717515e13322ab45b3c" - dependencies: - arrify "^1.0.1" - micromatch "^2.3.11" - object-assign "^4.1.0" - read-pkg-up "^1.0.1" - require-main-filename "^1.0.1" - -test-exclude@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.0.0.tgz#cdce7cece785e0e829cd5c2b27baf18bc583cfb7" +test-exclude@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.1.0.tgz#6ba6b25179d2d38724824661323b73e03c0c1de1" + integrity sha512-gwf0S2fFsANC55fSeSqpb8BYk6w3FDvwZxfNjeF6FRgvFa43r+7wRiA/Q0IxoRU37wB/LE8IQ4221BsNucTaCA== dependencies: arrify "^1.0.1" minimatch "^3.0.4" read-pkg-up "^4.0.0" require-main-filename "^1.0.1" -text-encoding@^0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" - text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -13513,7 +13661,7 @@ through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@~2.0.0: readable-stream "^2.1.5" xtend "~4.0.1" -through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4: +through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8, through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -13710,9 +13858,21 @@ trough@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.1.tgz#a9fd8b0394b0ae8fff82e0633a0a36ccad5b5f86" -tsame@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tsame/-/tsame-2.0.0.tgz#4923c805cbd789775eca33b9d0c67b358a7d86a8" +ts-node@^8.0.1: + version "8.0.3" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.0.3.tgz#aa60b836a24dafd8bf21b54766841a232fdbc641" + integrity sha512-2qayBA4vdtVRuDo11DEFSsD/SFsBXQBRZZhbRGSIkmYmVkWjULn/GGMdG10KVqkaGndljfaTD8dKjWgcejO8YA== + dependencies: + arg "^4.1.0" + diff "^3.1.0" + make-error "^1.1.1" + source-map-support "^0.5.6" + yn "^3.0.0" + +tsame@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tsame/-/tsame-2.0.1.tgz#70410ddbefcd29c61e2d68549b3347b0444d613f" + integrity sha512-jxyxgKVKa4Bh5dPcO42TJL22lIvfd9LOVJwdovKOnJa4TLLrHxquK+DlGm4rkGmrcur+GRx+x4oW00O2pY/fFw== tslib@^1.9.0: version "1.9.3" @@ -13747,13 +13907,19 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@4.0.8, type-detect@^4.0.8: +type-detect@4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" typedarray@^0.0.6, typedarray@~0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +typescript@^3.2.4: + version "3.3.3333" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.3.3333.tgz#171b2c5af66c59e9431199117a3bcadc66fdcfd6" + integrity sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw== ua-parser-js@0.7.17, ua-parser-js@^0.7.9: version "0.7.17" @@ -13773,7 +13939,7 @@ uglify-js@3.3.x: commander "~2.14.1" source-map "~0.6.1" -uglify-js@^2.6, uglify-js@^2.8.29: +uglify-js@^2.8.29: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" dependencies: @@ -14013,8 +14179,9 @@ unist-util-remove-position@^1.0.0: unist-util-visit "^1.1.0" unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.1.tgz#3ccbdc53679eed6ecf3777dd7f5e3229c1b6aa3c" + version "1.1.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" + integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== unist-util-visit-parents@^2.0.0: version "2.0.1" @@ -14148,9 +14315,10 @@ use@^2.0.0: isobject "^3.0.0" lazy-cache "^2.0.2" -util-deprecate@~1.0.1: +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util.promisify@1.0.0, util.promisify@~1.0.0: version "1.0.0" @@ -14220,8 +14388,9 @@ vfile-location@^2.0.0: resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.2.tgz#d3675c59c877498e492b4756ff65e4af1a752255" vfile-message@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.0.0.tgz#a6adb0474ea400fa25d929f1d673abea6a17e359" + version "1.1.1" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-1.1.1.tgz#5833ae078a1dfa2d96e9647886cd32993ab313e1" + integrity sha512-1WmsopSGhWt5laNir+633LszXvZ+Z/lxveBf6yhGsqnQIhlhzooZae7zV6YVM1Sdkw68dtAW3ow0pOdPANugvA== dependencies: unist-util-stringify-position "^1.1.1" @@ -14247,12 +14416,14 @@ vfile-sort@^2.1.2: integrity sha512-RgxLXVWrJBWb2GuP8FsSkqK7HmbjXjnI8qx3nD6NTWhsWaelaKvJuxfh1F1d1lkCPD7imo4zzi8cf6IOMgaTnQ== vfile-statistics@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vfile-statistics/-/vfile-statistics-1.1.0.tgz#02104c60fdeed1d11b1f73ad65330b7634b3d895" + version "1.1.2" + resolved "https://registry.yarnpkg.com/vfile-statistics/-/vfile-statistics-1.1.2.tgz#c50132627e4669a3afa07c64ff1e7aa7695e8151" + integrity sha512-16wAC9eEGXdsD35LX9m/iXCRIZyX5LIrDgDtAF92rbATSqsBRbC4n05e0Rj5vt3XRpcKu0UJeWnTxWsSyvNZ+w== vfile@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/vfile/-/vfile-2.3.0.tgz#e62d8e72b20e83c324bc6c67278ee272488bf84a" + integrity sha512-ASt4mBUHcTpMKD/l5Q+WJXNtshlWxOogYyGYYrg4lt/vuRjC1EFQtlAofL5VmtVNIZJzWYFJjzGWZ0Gw8pzW1w== dependencies: is-buffer "^1.1.4" replace-ext "1.0.0" @@ -14391,12 +14562,17 @@ vlq@^1.0.0: resolved "https://registry.yarnpkg.com/vlq/-/vlq-1.0.0.tgz#8101be90843422954c2b13eb27f2f3122bdcc806" integrity sha512-o3WmXySo+oI5thgqr7Qy8uBkT/v9Zr+sRyrh1lr8aWPUkgDWdWt4Nae2WKBrLsocgE8BuWWD0jLc+VW8LeU+2g== -vm-browserify@0.0.4, vm-browserify@~0.0.1: +vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" dependencies: indexof "0.0.1" +vm-browserify@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.0.tgz#bd76d6a23323e2ca8ffa12028dc04559c75f9019" + integrity sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw== + vt-pbf@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/vt-pbf/-/vt-pbf-3.1.1.tgz#b0f627e39a10ce91d943b898ed2363d21899fb82" @@ -14562,9 +14738,10 @@ which@1, which@^1.2.9, which@^1.3.0: dependencies: isexe "^2.0.0" -which@^1.2.14: +which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" @@ -14637,25 +14814,27 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" -write-file-atomic@^1.1.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" +write-file-atomic@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" dependencies: graceful-fs "^4.1.11" imurmurhash "^0.1.4" - slide "^1.1.5" + signal-exit "^3.0.2" -write-file-atomic@^2.0.0, write-file-atomic@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" +write-file-atomic@^2.3.0, write-file-atomic@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.2.tgz#a7181706dfba17855d221140a9c06e15fcdd87b9" + integrity sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g== dependencies: graceful-fs "^4.1.11" imurmurhash "^0.1.4" signal-exit "^3.0.2" -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== dependencies: mkdirp "^0.5.1" @@ -14729,7 +14908,7 @@ y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" -y18n@^4.0.0: +"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" @@ -14751,6 +14930,14 @@ yargs-parser@^10.0.0: dependencies: camelcase "^4.1.0" +yargs-parser@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" + integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" @@ -14770,36 +14957,13 @@ yargs-parser@^7.0.0: dependencies: camelcase "^4.1.0" -yargs-parser@^8.0.0, yargs-parser@^8.1.0: +yargs-parser@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== dependencies: camelcase "^4.1.0" -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - dependencies: - camelcase "^4.1.0" - -yargs@11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - yargs@6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.4.0.tgz#816e1a866d5598ccf34e5596ddce22d92da490d4" @@ -14855,22 +15019,23 @@ yargs@^10.0.3: y18n "^3.2.1" yargs-parser "^8.1.0" -yargs@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.0.0.tgz#c052931006c5eee74610e5fc0354bedfd08a201b" +yargs@^12.0.1, yargs@^12.0.5: + version "12.0.5" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" + integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== dependencies: cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" + decamelize "^1.2.0" + find-up "^3.0.0" get-caller-file "^1.0.1" - os-locale "^2.0.0" + os-locale "^3.0.0" require-directory "^2.1.1" require-main-filename "^1.0.1" set-blocking "^2.0.0" string-width "^2.0.0" which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" + y18n "^3.2.1 || ^4.0.0" + yargs-parser "^11.1.1" yargs@^4.8.1: version "4.8.1" @@ -14955,6 +15120,11 @@ yeast@0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" +yn@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.0.0.tgz#0073c6b56e92aed652fbdfd62431f2d6b9a7a091" + integrity sha512-+Wo/p5VRfxUgBUGy2j/6KX2mj9AYJWOHuhMjMcbBFc3y54o9/4buK1ksBvuiK01C3kby8DH9lSmJdSxw+4G/2Q== + zwitch@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.2.tgz#9b059541bfa844799fe2d903bde609de2503a041"