From c19b45d0627e37f66d5a26e435429bf28df12dca Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Tue, 23 Jan 2024 15:32:05 +0800 Subject: [PATCH 1/7] apply all safe linting changes [#112] --- src/attribute.ts | 4 +- src/compat/json_style.ts | 50 ++++---- src/default_style/style.ts | 34 ++--- src/extra_styles/toner.ts | 24 ++-- src/frontends/leaflet.ts | 105 ++++++++-------- src/frontends/static.ts | 126 +++++++++---------- src/labeler.ts | 150 +++++++++++----------- src/line.ts | 38 +++--- src/painter.ts | 40 +++--- src/symbolizer.ts | 251 +++++++++++++++++++------------------ src/task.ts | 32 ++--- src/text.ts | 6 +- src/tilecache.ts | 84 ++++++------- src/view.ts | 97 +++++++------- src/xray.ts | 16 +-- test/attribute.test.ts | 20 +-- test/json_style.test.ts | 36 +++--- test/labeler.test.ts | 60 ++++----- test/symbolizer.test.ts | 2 +- test/test_helpers.ts | 2 +- test/text.test.ts | 16 +-- test/tilecache.test.ts | 18 +-- test/view.test.ts | 44 +++---- 23 files changed, 639 insertions(+), 616 deletions(-) diff --git a/src/attribute.ts b/src/attribute.ts index 98e03af0..96761f2c 100644 --- a/src/attribute.ts +++ b/src/attribute.ts @@ -24,7 +24,7 @@ export class NumberAttr { value: AttrOption; per_feature: boolean; - constructor(c: AttrOption | undefined, defaultValue: number = 1) { + constructor(c: AttrOption | undefined, defaultValue = 1) { this.value = c ?? defaultValue; this.per_feature = typeof this.value == "function" && this.value.length == 2; @@ -62,7 +62,7 @@ export class TextAttr { } else { label_props = this.label_props; } - for (let property of label_props) { + for (const property of label_props) { if ( f.props.hasOwnProperty(property) && typeof f.props[property] === "string" diff --git a/src/compat/json_style.ts b/src/compat/json_style.ts index f0cf8b0a..eccac21c 100644 --- a/src/compat/json_style.ts +++ b/src/compat/json_style.ts @@ -3,10 +3,10 @@ import { Feature, JsonValue } from "../tilecache"; import { CenteredTextSymbolizer, CircleSymbolizer, - exp, LineLabelSymbolizer, LineSymbolizer, PolygonSymbolizer, + exp, } from "./../symbolizer"; function number(val: JsonValue, defaultValue: number) { @@ -22,7 +22,7 @@ export function filterFn(arr: any[]): Filter { } else if (arr[0] == "!=") { return (z, f) => f.props[arr[1]] !== arr[2]; } else if (arr[0] == "!") { - let sub = filterFn(arr[1]); + const sub = filterFn(arr[1]); return (z, f) => !sub(z, f); } else if (arr[0] === "<") { return (z, f) => number(f.props[arr[1]], Infinity) < arr[2]; @@ -41,13 +41,13 @@ export function filterFn(arr: any[]): Filter { } else if (arr[0] === "!has") { return (z, f) => !f.props.hasOwnProperty(arr[1]); } else if (arr[0] === "all") { - let parts = arr.slice(1, arr.length).map((e) => filterFn(e)); + const parts = arr.slice(1, arr.length).map((e) => filterFn(e)); return (z, f) => parts.every((p) => { return p(z, f); }); } else if (arr[0] === "any") { - let parts = arr.slice(1, arr.length).map((e) => filterFn(e)); + const parts = arr.slice(1, arr.length).map((e) => filterFn(e)); return (z, f) => parts.some((p) => { return p(z, f); @@ -68,8 +68,8 @@ export function numberFn(obj: any): (z: number, f?: Feature) => number { obj[1][0] == "exponential" && obj[2] == "zoom" ) { - let slice = obj.slice(3); - let stops: number[][] = []; + const slice = obj.slice(3); + const stops: number[][] = []; for (var i = 0; i < slice.length; i += 2) { stops.push([slice[i], slice[i + 1]]); } @@ -77,10 +77,10 @@ export function numberFn(obj: any): (z: number, f?: Feature) => number { return exp(obj[1][1], stops)(z - 1); }; } else if (obj[0] == "step" && obj[1][0] == "get") { - let slice = obj.slice(2); - let prop = obj[1][1]; + const slice = obj.slice(2); + const prop = obj[1][1]; return (z: number, f?: Feature) => { - let val = f?.props[prop]; + const val = f?.props[prop]; if (typeof val === "number") { if (val < slice[1]) return slice[0]; for (i = 1; i < slice.length; i += 2) { @@ -97,7 +97,7 @@ export function numberFn(obj: any): (z: number, f?: Feature) => number { export function numberOrFn( obj: any, - defaultValue = 0 + defaultValue = 0, ): number | ((z: number, f?: Feature) => number) { if (!obj) return defaultValue; if (typeof obj == "number") { @@ -108,10 +108,10 @@ export function numberOrFn( } export function widthFn(width_obj: any, gap_obj: any) { - let w = numberOrFn(width_obj, 1); - let g = numberOrFn(gap_obj); + const w = numberOrFn(width_obj, 1); + const g = numberOrFn(gap_obj); return (z: number, f?: Feature) => { - let tmp = typeof w == "number" ? w : w(z, f); + const tmp = typeof w == "number" ? w : w(z, f); if (g) { return tmp + (typeof g == "number" ? g : g(z, f)); } @@ -126,15 +126,15 @@ interface FontSub { } export function getFont(obj: any, fontsubmap: any) { - let fontfaces: FontSub[] = []; - for (let wanted_face of obj["text-font"]) { + const fontfaces: FontSub[] = []; + for (const wanted_face of obj["text-font"]) { if (fontsubmap.hasOwnProperty(wanted_face)) { fontfaces.push(fontsubmap[wanted_face]); } } if (fontfaces.length === 0) fontfaces.push({ face: "sans-serif" }); - let text_size = obj["text-size"]; + const text_size = obj["text-size"]; // for fallbacks, use the weight and style of the first font var weight = ""; if (fontfaces.length && fontfaces[0].weight) @@ -151,14 +151,14 @@ export function getFont(obj: any, fontsubmap: any) { var base = 1.4; if (text_size.base) base = text_size.base; else text_size.base = base; - let t = numberFn(text_size); + const t = numberFn(text_size); return (z: number, f?: Feature) => { return `${style}${weight}${t(z, f)}px ${fontfaces .map((f) => f.face) .join(", ")}`; }; } else if (text_size[0] == "step") { - let t = numberFn(text_size); + const t = numberFn(text_size); return (z: number, f?: Feature) => { return `${style}${weight}${t(z, f)}px ${fontfaces .map((f) => f.face) @@ -171,9 +171,9 @@ export function getFont(obj: any, fontsubmap: any) { } export function json_style(obj: any, fontsubmap: Map) { - let paint_rules = []; - let label_rules = []; - let refs = new Map(); + const paint_rules = []; + const label_rules = []; + const refs = new Map(); for (var layer of obj.layers) { refs.set(layer.id, layer); @@ -183,14 +183,14 @@ export function json_style(obj: any, fontsubmap: Map) { } if (layer.ref) { - let referenced = refs.get(layer.ref); + const referenced = refs.get(layer.ref); layer.type = referenced.type; layer.filter = referenced.filter; layer.source = referenced["source"]; layer["source-layer"] = referenced["source-layer"]; } - let sourceLayer = layer["source-layer"]; + const sourceLayer = layer["source-layer"]; var symbolizer; var filter = undefined; @@ -227,7 +227,7 @@ export function json_style(obj: any, fontsubmap: Map) { symbolizer: new LineSymbolizer({ width: widthFn( layer.paint["line-width"], - layer.paint["line-gap-width"] + layer.paint["line-gap-width"], ), dash: layer.paint["line-dasharray"], dashColor: layer.paint["line-color"], @@ -241,7 +241,7 @@ export function json_style(obj: any, fontsubmap: Map) { color: layer.paint["line-color"], width: widthFn( layer.paint["line-width"], - layer.paint["line-gap-width"] + layer.paint["line-gap-width"], ), }), }); diff --git a/src/default_style/style.ts b/src/default_style/style.ts index b1723cf2..b55c1a69 100644 --- a/src/default_style/style.ts +++ b/src/default_style/style.ts @@ -4,7 +4,6 @@ import { Rule } from "../painter"; import { CenteredTextSymbolizer, CircleSymbolizer, - exp, FlexSymbolizer, GroupSymbolizer, LabelSymbolizer, @@ -14,6 +13,7 @@ import { PolygonLabelSymbolizer, PolygonSymbolizer, ShieldSymbolizer, + exp, } from "../symbolizer"; import { Feature } from "../tilecache"; @@ -53,10 +53,10 @@ export interface DefaultStyleParams { } const doShading = (params: DefaultStyleParams, shade: string) => { - let shadeHsl = parseToHsla(shade); - let outParams: any = { ...params }; + const shadeHsl = parseToHsla(shade); + const outParams: any = { ...params }; for (const [key, value] of Object.entries(params)) { - let o = parseToHsla(value); + const o = parseToHsla(value); outParams[key] = hsla(shadeHsl[0], shadeHsl[1], o[2], o[3]); } return outParams; @@ -64,7 +64,7 @@ const doShading = (params: DefaultStyleParams, shade: string) => { export const paintRules = ( params: DefaultStyleParams, - shade?: string + shade?: string, ): Rule[] => { if (shade) params = doShading(params, shade); return [ @@ -320,13 +320,13 @@ export const labelRules = ( params: DefaultStyleParams, shade?: string, language1?: string[], - language2?: string[] + language2?: string[], ): LabelRule[] => { if (shade) params = doShading(params, shade); var nametags = ["name"]; if (language1) nametags = language1; - let languageStack = (symbolizer: LabelSymbolizer, fill: string) => { + const languageStack = (symbolizer: LabelSymbolizer, fill: string) => { if (!language2) return symbolizer; if (symbolizer instanceof OffsetTextSymbolizer) { return new FlexSymbolizer([ @@ -361,7 +361,7 @@ export const labelRules = ( }, textTransform: "uppercase", }), - params.countryLabel + params.countryLabel, ), filter: (z, f) => { return f.props["pmap:kind"] == "country"; @@ -375,7 +375,7 @@ export const labelRules = ( fill: params.stateLabel, font: "300 16px sans-serif", }), - params.stateLabel + params.stateLabel, ), filter: (z, f) => { return f.props["pmap:kind"] == "state"; @@ -402,7 +402,7 @@ export const labelRules = ( } }, }), - params.cityLabel + params.cityLabel, ), sort: (a: any, b: any) => { return a["pmap:rank"] - b["pmap:rank"]; @@ -436,7 +436,7 @@ export const labelRules = ( } }, }), - params.cityLabel + params.cityLabel, ), ]), sort: (a: any, b: any) => { @@ -453,7 +453,7 @@ export const labelRules = ( font: "500 10px sans-serif", textTransform: "uppercase", }), - params.neighbourhoodLabel + params.neighbourhoodLabel, ), filter: (z, f) => { return f.props["pmap:kind"] == "neighbourhood"; @@ -467,7 +467,7 @@ export const labelRules = ( fill: params.landuseLabel, font: "300 12px sans-serif", }), - params.landuseLabel + params.landuseLabel, ), }, { @@ -478,7 +478,7 @@ export const labelRules = ( fill: params.waterLabel, font: "italic 600 12px sans-serif", }), - params.waterLabel + params.waterLabel, ), }, { @@ -489,7 +489,7 @@ export const labelRules = ( fill: params.naturalLabel, font: "italic 300 12px sans-serif", }), - params.naturalLabel + params.naturalLabel, ), }, { @@ -500,7 +500,7 @@ export const labelRules = ( fill: params.roadsLabel, font: "500 12px sans-serif", }), - params.roadsLabel + params.roadsLabel, ), minzoom: 12, }, @@ -532,7 +532,7 @@ export const labelRules = ( offsetY: 2, font: "300 10px sans-serif", }), - params.poisLabel + params.poisLabel, ), ]), }, diff --git a/src/extra_styles/toner.ts b/src/extra_styles/toner.ts index be03032e..fb63524a 100644 --- a/src/extra_styles/toner.ts +++ b/src/extra_styles/toner.ts @@ -1,16 +1,16 @@ -import { Justify } from "../symbolizer"; -import { Rule } from "../painter"; import { LabelRule } from "../labeler"; -import { Font, Sheet } from "../task"; -import { arr, exp, createPattern } from "../symbolizer"; +import { Rule } from "../painter"; +import { Justify } from "../symbolizer"; +import { arr, createPattern, exp } from "../symbolizer"; import { CircleSymbolizer, IconSymbolizer } from "../symbolizer"; import { - GroupSymbolizer, CenteredTextSymbolizer, + GroupSymbolizer, OffsetTextSymbolizer, } from "../symbolizer"; -import { LineSymbolizer, LineLabelSymbolizer } from "../symbolizer"; -import { PolygonSymbolizer, PolygonLabelSymbolizer } from "../symbolizer"; +import { LineLabelSymbolizer, LineSymbolizer } from "../symbolizer"; +import { PolygonLabelSymbolizer, PolygonSymbolizer } from "../symbolizer"; +import { Font, Sheet } from "../task"; // import icons from './toner-icons.html' // https://github.com/stamen/toner-carto/blob/master/map.mss @@ -31,7 +31,7 @@ import { PolygonSymbolizer, PolygonLabelSymbolizer } from "../symbolizer"; // } const Toner = (variant: string) => { - let halftone = createPattern(4, 4, (c) => { + const halftone = createPattern(4, 4, (c) => { var ctx = c.getContext("2d"); if (ctx) { ctx.beginPath(); @@ -47,10 +47,10 @@ const Toner = (variant: string) => { background = "#d9d9d9"; } - let lang = ["name:en", "name"]; + const lang = ["name:en", "name"]; // let sprites = Sprites(icons); - let paint_rules: Rule[] = [ + const paint_rules: Rule[] = [ { dataLayer: "earth", symbolizer: new PolygonSymbolizer({ @@ -192,7 +192,7 @@ const Toner = (variant: string) => { }, ]; - let label_rules: LabelRule[] = [ + const label_rules: LabelRule[] = [ { dataLayer: "places", symbolizer: new CenteredTextSymbolizer({ @@ -344,7 +344,7 @@ const Toner = (variant: string) => { Font( "Inter", "https://cdn.protomaps.com/fonts/woff2/Inter.var.woff2", - "100 900" + "100 900", ), ], paint_rules: paint_rules, diff --git a/src/frontends/leaflet.ts b/src/frontends/leaflet.ts index 04756581..fa0c991e 100644 --- a/src/frontends/leaflet.ts +++ b/src/frontends/leaflet.ts @@ -2,15 +2,15 @@ declare var L: any; import Point from "@mapbox/point-geometry"; -import { Zxy, TileCache } from "../tilecache"; -import { View, PreparedTile, sourcesToViews, SourceOptions } from "../view"; -import { painter, Rule } from "../painter"; -import { Labelers, LabelRule } from "../labeler"; -import { light } from "../default_style/light"; -import { dark } from "../default_style/dark"; -import { paintRules, labelRules } from "../default_style/style"; -import { xray_rules, XraySelection } from "../xray"; import { PMTiles } from "pmtiles"; +import { dark } from "../default_style/dark"; +import { light } from "../default_style/light"; +import { labelRules, paintRules } from "../default_style/style"; +import { LabelRule, Labelers } from "../labeler"; +import { Rule, painter } from "../painter"; +import { TileCache, Zxy } from "../tilecache"; +import { PreparedTile, SourceOptions, View, sourcesToViews } from "../view"; +import { XraySelection, xray_rules } from "../xray"; const timer = (duration: number) => { return new Promise((resolve, reject) => { @@ -35,7 +35,7 @@ const reflect = (promise: Promise) => { }, (error) => { return { status: "rejected", reason: error }; - } + }, ); }; @@ -75,7 +75,7 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { 'Protomaps © OpenStreetMap'; super(options); - let theme = options.dark ? dark : light; + const theme = options.dark ? dark : light; this.paint_rules = options.paint_rules || paintRules(theme, options.shade); this.label_rules = @@ -89,7 +89,7 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { this.views = sourcesToViews(options); this.debug = options.debug; - let scratch = document.createElement("canvas").getContext("2d"); + const scratch = document.createElement("canvas").getContext("2d"); this.scratch = scratch; this.onTilesInvalidated = (tiles: Set) => { tiles.forEach((t) => { @@ -100,7 +100,7 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { this.scratch, this.label_rules, 16, - this.onTilesInvalidated + this.onTilesInvalidated, ); this.tile_size = 256 * window.devicePixelRatio; this.tileDelay = options.tileDelay || 3; @@ -114,9 +114,9 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { darkOption: boolean, shade: string, language1: string[], - language2: string[] + language2: string[], ) { - let theme = darkOption ? dark : light; + const theme = darkOption ? dark : light; this.paint_rules = paintRules(theme, shade); this.label_rules = labelRules(theme, shade, language1, language2); } @@ -125,16 +125,16 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { coords: any, element: any, key: string, - done = () => {} + done = () => {}, ) { this.lastRequestedZ = coords.z; - let promises = []; + const promises = []; for (const [k, v] of this.views) { - let promise = v.getDisplayTile(coords); + const promise = v.getDisplayTile(coords); promises.push({ key: k, promise: promise }); } - let tile_responses = await Promise.all( + const tile_responses = await Promise.all( promises.map((o) => { return o.promise.then( (v: PreparedTile[]) => { @@ -142,12 +142,12 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { }, (error: Error) => { return { status: "rejected", reason: error, key: o.key }; - } + }, ); - }) + }), ); - let prepared_tilemap = new Map(); + const prepared_tilemap = new Map(); for (const tile_response of tile_responses) { if (tile_response.status === "fulfilled") { prepared_tilemap.set(tile_response.key, [tile_response.value]); @@ -168,38 +168,38 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { if (element.key != key) return; if (this.lastRequestedZ !== coords.z) return; - let layout_time = this.labelers.add(coords.z, prepared_tilemap); + const layout_time = this.labelers.add(coords.z, prepared_tilemap); if (element.key != key) return; if (this.lastRequestedZ !== coords.z) return; - let label_data = this.labelers.getIndex(coords.z); + const label_data = this.labelers.getIndex(coords.z); if (!this._map) return; // the layer has been removed from the map - let center = this._map.getCenter().wrap(); - let pixelBounds = this._getTiledPixelBounds(center), + const center = this._map.getCenter().wrap(); + const pixelBounds = this._getTiledPixelBounds(center), tileRange = this._pxBoundsToTileRange(pixelBounds), tileCenter = tileRange.getCenter(); - let priority = coords.distanceTo(tileCenter) * this.tileDelay; + const priority = coords.distanceTo(tileCenter) * this.tileDelay; await timer(priority); if (element.key != key) return; if (this.lastRequestedZ !== coords.z) return; - let BUF = 16; - let bbox = { + const BUF = 16; + const bbox = { minX: 256 * coords.x - BUF, minY: 256 * coords.y - BUF, maxX: 256 * (coords.x + 1) + BUF, maxY: 256 * (coords.y + 1) + BUF, }; - let origin = new Point(256 * coords.x, 256 * coords.y); + const origin = new Point(256 * coords.x, 256 * coords.y); element.width = this.tile_size; element.height = this.tile_size; - let ctx = element.getContext("2d"); + const ctx = element.getContext("2d"); ctx.setTransform(this.tile_size / 256, 0, 0, this.tile_size / 256, 0, 0); ctx.clearRect(0, 0, 256, 256); @@ -226,7 +226,7 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { bbox, origin, false, - this.debug + this.debug, ); if (this.debug) { @@ -237,12 +237,12 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { ctx.font = "12px sans-serif"; let ypos = 28; - for (let [k, v] of prepared_tilemap) { - let dt = v[0].data_tile; + for (const [k, v] of prepared_tilemap) { + const dt = v[0].data_tile; ctx.fillText( k + (k ? " " : "") + dt.z + " " + dt.x + " " + dt.y, 4, - ypos + ypos, ); ypos += 14; } @@ -276,9 +276,9 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { } public rerenderTile(key: string) { - for (let unwrapped_k in this._tiles) { - let wrapped_coord = this._wrapCoords( - this._keyToTileCoords(unwrapped_k) + for (const unwrapped_k in this._tiles) { + const wrapped_coord = this._wrapCoords( + this._keyToTileCoords(unwrapped_k), ); if (key === this._tileCoordsToKey(wrapped_coord)) { this.renderTile(wrapped_coord, this._tiles[unwrapped_k].el, key); @@ -291,25 +291,25 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { this.scratch, this.label_rules, 16, - this.onTilesInvalidated + this.onTilesInvalidated, ); } public rerenderTiles() { - for (let unwrapped_k in this._tiles) { - let wrapped_coord = this._wrapCoords( - this._keyToTileCoords(unwrapped_k) + for (const unwrapped_k in this._tiles) { + const wrapped_coord = this._wrapCoords( + this._keyToTileCoords(unwrapped_k), ); - let key = this._tileCoordsToKey(wrapped_coord); + const key = this._tileCoordsToKey(wrapped_coord); this.renderTile(wrapped_coord, this._tiles[unwrapped_k].el, key); } } public createTile(coords: any, showTile: any) { - let element = L.DomUtil.create("canvas", "leaflet-tile"); + const element = L.DomUtil.create("canvas", "leaflet-tile"); element.lang = this.lang; - let key = this._tileCoordsToKey(coords); + const key = this._tileCoordsToKey(coords); element.key = key; this.renderTile(coords, element, key, () => { @@ -320,7 +320,7 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { } public _removeTile(key: string) { - let tile = this._tiles[key]; + const tile = this._tiles[key]; if (!tile) { return; } @@ -337,11 +337,11 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { } public queryFeatures(lng: number, lat: number) { - let featuresBySourceName = new Map(); + const featuresBySourceName = new Map(); for (var [sourceName, view] of this.views) { featuresBySourceName.set( sourceName, - view.queryFeatures(lng, lat, this._map.getZoom()) + view.queryFeatures(lng, lat, this._map.getZoom()), ); } return featuresBySourceName; @@ -349,9 +349,12 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { public inspect(layer: LeafletLayer) { return (ev: any) => { - let typeGlyphs = ["◎", "⟍", "◻"]; - let wrapped = layer._map.wrapLatLng(ev.latlng); - let resultsBySourceName = layer.queryFeatures(wrapped.lng, wrapped.lat); + const typeGlyphs = ["◎", "⟍", "◻"]; + const wrapped = layer._map.wrapLatLng(ev.latlng); + const resultsBySourceName = layer.queryFeatures( + wrapped.lng, + wrapped.lat, + ); var content = ""; let firstRow = true; @@ -390,7 +393,7 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { .setContent( '
' + content + - "
" + "", ) .openOn(layer._map); }; diff --git a/src/frontends/static.ts b/src/frontends/static.ts index 0ae404d3..b9e54d38 100644 --- a/src/frontends/static.ts +++ b/src/frontends/static.ts @@ -1,30 +1,30 @@ import Point from "@mapbox/point-geometry"; -import { ZxySource, PmtilesSource, TileCache } from "../tilecache"; -import { View, PreparedTile, sourcesToViews, SourceOptions } from "../view"; -import { Rule, painter } from "../painter"; -import { LabelRule, Labeler } from "../labeler"; -import { light } from "../default_style/light"; +import { PMTiles } from "pmtiles"; import { dark } from "../default_style/dark"; -import { paintRules, labelRules } from "../default_style/style"; +import { light } from "../default_style/light"; +import { labelRules, paintRules } from "../default_style/style"; +import { LabelRule, Labeler } from "../labeler"; +import { Rule, painter } from "../painter"; +import { PmtilesSource, TileCache, ZxySource } from "../tilecache"; +import { PreparedTile, SourceOptions, View, sourcesToViews } from "../view"; import { XraySelection, xray_rules } from "../xray"; -import { PMTiles } from "pmtiles"; -let R = 6378137; -let MAX_LATITUDE = 85.0511287798; -let MAXCOORD = R * Math.PI; +const R = 6378137; +const MAX_LATITUDE = 85.0511287798; +const MAXCOORD = R * Math.PI; -let project = (latlng: Point): Point => { - let d = Math.PI / 180; - let constrained_lat = Math.max( +const project = (latlng: Point): Point => { + const d = Math.PI / 180; + const constrained_lat = Math.max( Math.min(MAX_LATITUDE, latlng.y), - -MAX_LATITUDE + -MAX_LATITUDE, ); - let sin = Math.sin(constrained_lat * d); + const sin = Math.sin(constrained_lat * d); return new Point(R * latlng.x * d, (R * Math.log((1 + sin) / (1 - sin))) / 2); }; -let unproject = (point: Point) => { +const unproject = (point: Point) => { var d = 180 / Math.PI; return { lat: (2 * Math.atan(Math.exp(point.y / R)) - Math.PI / 2) * d, @@ -32,32 +32,32 @@ let unproject = (point: Point) => { }; }; -let instancedProject = (origin: Point, display_zoom: number) => { +const instancedProject = (origin: Point, display_zoom: number) => { return (latlng: Point) => { - let projected = project(latlng); - let normalized = new Point( + const projected = project(latlng); + const normalized = new Point( (projected.x + MAXCOORD) / (MAXCOORD * 2), - 1 - (projected.y + MAXCOORD) / (MAXCOORD * 2) + 1 - (projected.y + MAXCOORD) / (MAXCOORD * 2), ); return normalized.mult((1 << display_zoom) * 256).sub(origin); }; }; -let instancedUnproject = (origin: Point, display_zoom: number) => { +const instancedUnproject = (origin: Point, display_zoom: number) => { return (point: Point) => { - let normalized = new Point(point.x, point.y) + const normalized = new Point(point.x, point.y) .add(origin) .div((1 << display_zoom) * 256); - let projected = new Point( + const projected = new Point( normalized.x * (MAXCOORD * 2) - MAXCOORD, - (1 - normalized.y) * (MAXCOORD * 2) - MAXCOORD + (1 - normalized.y) * (MAXCOORD * 2) - MAXCOORD, ); return unproject(projected); }; }; export const getZoom = (degrees_lng: number, css_pixels: number): number => { - let d = css_pixels * (360 / degrees_lng); + const d = css_pixels * (360 / degrees_lng); return Math.log2(d / 256); }; @@ -87,7 +87,7 @@ export class Static { xray?: XraySelection; constructor(options: StaticOptions) { - let theme = options.dark ? dark : light; + const theme = options.dark ? dark : light; this.paint_rules = options.paint_rules || paintRules(theme, options.shade); this.label_rules = options.label_rules || @@ -104,34 +104,34 @@ export class Static { width: number, height: number, latlng: Point, - display_zoom: number + display_zoom: number, ) { - let center = project(latlng); - let normalized_center = new Point( + const center = project(latlng); + const normalized_center = new Point( (center.x + MAXCOORD) / (MAXCOORD * 2), - 1 - (center.y + MAXCOORD) / (MAXCOORD * 2) + 1 - (center.y + MAXCOORD) / (MAXCOORD * 2), ); // the origin of the painter call in global Z coordinates - let origin = normalized_center + const origin = normalized_center .clone() .mult(Math.pow(2, display_zoom) * 256) .sub(new Point(width / 2, height / 2)); // the bounds of the painter call in global Z coordinates - let bbox = { + const bbox = { minX: origin.x, minY: origin.y, maxX: origin.x + width, maxY: origin.y + height, }; - let promises = []; + const promises = []; for (const [k, v] of this.views) { - let promise = v.getBbox(display_zoom, bbox); + const promise = v.getBbox(display_zoom, bbox); promises.push({ key: k, promise: promise }); } - let tile_responses = await Promise.all( + const tile_responses = await Promise.all( promises.map((o) => { return o.promise.then( (v: PreparedTile[]) => { @@ -139,28 +139,28 @@ export class Static { }, (error: Error) => { return { status: "rejected", value: [], reason: error, key: o.key }; - } + }, ); - }) + }), ); - let prepared_tilemap = new Map(); + const prepared_tilemap = new Map(); for (const tile_response of tile_responses) { if (tile_response.status === "fulfilled") { prepared_tilemap.set(tile_response.key, tile_response.value); } } - let start = performance.now(); - let labeler = new Labeler( + const start = performance.now(); + const labeler = new Labeler( display_zoom, ctx, this.label_rules, 16, - undefined + undefined, ); // because need ctx to measure - let layout_time = labeler.add(prepared_tilemap); + const layout_time = labeler.add(prepared_tilemap); if (this.backgroundColor) { ctx.save(); @@ -174,7 +174,7 @@ export class Static { paint_rules = xray_rules(prepared_tilemap, this.xray); } - let p = painter( + const p = painter( ctx, display_zoom, prepared_tilemap, @@ -183,7 +183,7 @@ export class Static { bbox, origin, true, - this.debug + this.debug, ); if (this.debug) { @@ -194,18 +194,18 @@ export class Static { ctx.font = "12px sans-serif"; let idx = 0; for (const [k, v] of prepared_tilemap) { - for (let prepared_tile of v) { + for (const prepared_tile of v) { ctx.strokeRect( prepared_tile.origin.x, prepared_tile.origin.y, prepared_tile.dim, - prepared_tile.dim + prepared_tile.dim, ); - let dt = prepared_tile.data_tile; + const dt = prepared_tile.data_tile; ctx.fillText( k + (k ? " " : "") + dt.z + " " + dt.x + " " + dt.y, prepared_tile.origin.x + 4, - prepared_tile.origin.y + 14 * (1 + idx) + prepared_tile.origin.y + 14 * (1 + idx), ); } idx++; @@ -225,17 +225,17 @@ export class Static { canvas: HTMLCanvasElement, latlng: Point, display_zoom: number, - options: StaticOptions = {} + options: StaticOptions = {}, ) { - let dpr = window.devicePixelRatio; - let width = canvas.clientWidth; - let height = canvas.clientHeight; + const dpr = window.devicePixelRatio; + const width = canvas.clientWidth; + const height = canvas.clientHeight; if (!(canvas.width == width * dpr && canvas.height == height * dpr)) { canvas.width = width * dpr; canvas.height = height * dpr; } if (options.lang) canvas.lang = options.lang; - let ctx = canvas.getContext("2d")!; + const ctx = canvas.getContext("2d")!; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); return this.drawContext(ctx, width, height, latlng, display_zoom); } @@ -245,19 +245,19 @@ export class Static { top_left: Point, bottom_right: Point, width: number, - height: number + height: number, ) { - let delta_degrees = bottom_right.x - top_left.x; - let center = new Point( + const delta_degrees = bottom_right.x - top_left.x; + const center = new Point( (top_left.x + bottom_right.x) / 2, - (top_left.y + bottom_right.y) / 2 + (top_left.y + bottom_right.y) / 2, ); return this.drawContext( ctx, width, height, center, - getZoom(delta_degrees, width) + getZoom(delta_degrees, width), ); } @@ -266,18 +266,18 @@ export class Static { top_left: Point, bottom_right: Point, width: number, - options: StaticOptions = {} + options: StaticOptions = {}, ) { - let delta_degrees = bottom_right.x - top_left.x; - let center = new Point( + const delta_degrees = bottom_right.x - top_left.x; + const center = new Point( (top_left.x + bottom_right.x) / 2, - (top_left.y + bottom_right.y) / 2 + (top_left.y + bottom_right.y) / 2, ); return this.drawCanvas( canvas, center, getZoom(delta_degrees, width), - options + options, ); } } diff --git a/src/labeler.ts b/src/labeler.ts index c1966ef5..d744e01c 100644 --- a/src/labeler.ts +++ b/src/labeler.ts @@ -51,20 +51,20 @@ export interface LabelRule { export const covering = ( display_zoom: number, tile_width: number, - bbox: Bbox + bbox: Bbox, ) => { - let res = 256; - let f = tile_width / res; + const res = 256; + const f = tile_width / res; - let minx = Math.floor(bbox.minX / res); - let miny = Math.floor(bbox.minY / res); - let maxx = Math.floor(bbox.maxX / res); - let maxy = Math.floor(bbox.maxY / res); - let leveldiff = Math.log2(f); + const minx = Math.floor(bbox.minX / res); + const miny = Math.floor(bbox.minY / res); + const maxx = Math.floor(bbox.maxX / res); + const maxy = Math.floor(bbox.maxY / res); + const leveldiff = Math.log2(f); - let retval = []; + const retval = []; for (let x = minx; x <= maxx; x++) { - let wrapped_x = x % (1 << display_zoom); + const wrapped_x = x % (1 << display_zoom); for (let y = miny; y <= maxy; y++) { retval.push({ display: toIndex({ z: display_zoom, x: wrapped_x, y: y }), @@ -93,7 +93,7 @@ export class Index { } public hasPrefix(tileKey: string): boolean { - for (let key of this.current.keys()) { + for (const key of this.current.keys()) { if (key.startsWith(tileKey)) return true; } return false; @@ -112,8 +112,8 @@ export class Index { } public searchBbox(bbox: Bbox, order: number): Set { - let labels = new Set(); - for (let match of this.tree.search(bbox)) { + const labels = new Set(); + for (const match of this.tree.search(bbox)) { if (match.indexed_label.order <= order) { labels.add(match.indexed_label); } @@ -122,9 +122,9 @@ export class Index { } public searchLabel(label: Label, order: number): Set { - let labels = new Set(); - for (let bbox of label.bboxes) { - for (let match of this.tree.search(bbox)) { + const labels = new Set(); + for (const bbox of label.bboxes) { + for (const match of this.tree.search(bbox)) { if (match.indexed_label.order <= order) { labels.add(match.indexed_label); } @@ -134,15 +134,15 @@ export class Index { } public bboxCollides(bbox: Bbox, order: number): boolean { - for (let match of this.tree.search(bbox)) { + for (const match of this.tree.search(bbox)) { if (match.indexed_label.order <= order) return true; } return false; } public labelCollides(label: Label, order: number): boolean { - for (let bbox of label.bboxes) { - for (let match of this.tree.search(bbox)) { + for (const bbox of label.bboxes) { + for (const match of this.tree.search(bbox)) { if (match.indexed_label.order <= order) return true; } } @@ -153,14 +153,14 @@ export class Index { // create a bbox around anchor to find potential matches. // this is depending on precondition: (anchor is contained within, or on boundary of, a label bbox) if (!label.deduplicationKey || !label.deduplicationDistance) return false; - let dist = label.deduplicationDistance; - let test_bbox = { + const dist = label.deduplicationDistance; + const test_bbox = { minX: label.anchor.x - dist, minY: label.anchor.y - dist, maxX: label.anchor.x + dist, maxY: label.anchor.y + dist, }; - for (let collision of this.tree.search(test_bbox)) { + for (const collision of this.tree.search(test_bbox)) { if (collision.indexed_label.deduplicationKey === label.deduplicationKey) { if (collision.indexed_label.anchor.dist(label.anchor) < dist) { return true; @@ -174,13 +174,13 @@ export class Index { if (this.current.get(tileKey)) { console.log("consistency error 1"); } - let newSet = new Set(); + const newSet = new Set(); this.current.set(tileKey, newSet); } // can put in multiple due to antimeridian wrapping public insert(label: Label, order: number, tileKey: string): void { - let indexed_label = { + const indexed_label = { anchor: label.anchor, bboxes: label.bboxes, draw: label.draw, @@ -191,7 +191,7 @@ export class Index { }; let entry = this.current.get(tileKey); if (!entry) { - let newSet = new Set(); + const newSet = new Set(); this.current.set(tileKey, newSet); entry = newSet; } @@ -199,7 +199,7 @@ export class Index { var wrapsLeft = false; var wrapsRight = false; - for (let bbox of label.bboxes) { + for (const bbox of label.bboxes) { var b: any = bbox; b.indexed_label = indexed_label; this.tree.insert(b); @@ -212,7 +212,7 @@ export class Index { var shift = wrapsLeft ? this.dim : -this.dim; var new_bboxes = []; - for (let bbox of label.bboxes) { + for (const bbox of label.bboxes) { new_bboxes.push({ minX: bbox.minX + shift, minY: bbox.minY, @@ -220,16 +220,16 @@ export class Index { maxY: bbox.maxY, }); } - let duplicate_label = { + const duplicate_label = { anchor: new Point(label.anchor.x + shift, label.anchor.y), bboxes: new_bboxes, draw: label.draw, order: order, tileKey: tileKey, }; - let entry = this.current.get(tileKey); + const entry = this.current.get(tileKey); if (entry) entry.add(duplicate_label); - for (let bbox of new_bboxes) { + for (const bbox of new_bboxes) { var b: any = bbox; b.indexed_label = duplicate_label; this.tree.insert(b); @@ -238,18 +238,18 @@ export class Index { } public pruneOrNoop(key_added: string) { - let added = key_added.split(":"); + const added = key_added.split(":"); let max_key = undefined; let max_dist = 0; let keys_for_ds = 0; for (var existing_key of this.current.keys()) { - let existing = existing_key.split(":"); + const existing = existing_key.split(":"); if (existing[3] === added[3]) { keys_for_ds++; - let dist = Math.sqrt( + const dist = Math.sqrt( Math.pow(+existing[0] - +added[0], 2) + - Math.pow(+existing[1] - +added[1], 2) + Math.pow(+existing[1] - +added[1], 2), ); if (dist > max_dist) { max_dist = dist; @@ -264,10 +264,10 @@ export class Index { } public pruneKey(keyToRemove: string): void { - let indexed_labels = this.current.get(keyToRemove); + const indexed_labels = this.current.get(keyToRemove); if (!indexed_labels) return; // TODO: not that clean... - let entries_to_delete = []; - for (let entry of this.tree.all()) { + const entries_to_delete = []; + for (const entry of this.tree.all()) { if (indexed_labels.has(entry.indexed_label)) { entries_to_delete.push(entry); } @@ -283,8 +283,8 @@ export class Index { // the duplicate label; but i am having a hard time // imagining where this will happen in practical usage public removeLabel(labelToRemove: IndexedLabel): void { - let entries_to_delete = []; - for (let entry of this.tree.all()) { + const entries_to_delete = []; + for (const entry of this.tree.all()) { if (labelToRemove == entry.indexed_label) { entries_to_delete.push(entry); } @@ -292,7 +292,7 @@ export class Index { entries_to_delete.forEach((entry) => { this.tree.remove(entry); }); - let c = this.current.get(labelToRemove.tileKey); + const c = this.current.get(labelToRemove.tileKey); if (c) c.delete(labelToRemove); } } @@ -309,7 +309,7 @@ export class Labeler { scratch: CanvasRenderingContext2D, labelRules: LabelRule[], maxLabeledTiles: number, - callback?: TileInvalidationCallback + callback?: TileInvalidationCallback, ) { this.index = new Index((256 * 1) << z, maxLabeledTiles); this.z = z; @@ -319,13 +319,13 @@ export class Labeler { } private layout(prepared_tilemap: Map): number { - let start = performance.now(); + const start = performance.now(); - let keys_adding = new Set(); + const keys_adding = new Set(); // if it already exists... short circuit - for (let [k, prepared_tiles] of prepared_tilemap) { - for (let prepared_tile of prepared_tiles) { - let key = toIndex(prepared_tile.data_tile) + ":" + k; + for (const [k, prepared_tiles] of prepared_tilemap) { + for (const prepared_tile of prepared_tiles) { + const key = toIndex(prepared_tile.data_tile) + ":" + k; if (!this.index.has(key)) { this.index.makeEntry(key); keys_adding.add(key); @@ -333,24 +333,24 @@ export class Labeler { } } - let tiles_invalidated = new Set(); - for (let [order, rule] of this.labelRules.entries()) { + const tiles_invalidated = new Set(); + for (const [order, rule] of this.labelRules.entries()) { if (rule.visible == false) continue; if (rule.minzoom && this.z < rule.minzoom) continue; if (rule.maxzoom && this.z > rule.maxzoom) continue; - let dsName = rule.dataSource || ""; - let prepared_tiles = prepared_tilemap.get(dsName); + const dsName = rule.dataSource || ""; + const prepared_tiles = prepared_tilemap.get(dsName); if (!prepared_tiles) continue; - for (let prepared_tile of prepared_tiles) { - let key = toIndex(prepared_tile.data_tile) + ":" + dsName; + for (const prepared_tile of prepared_tiles) { + const key = toIndex(prepared_tile.data_tile) + ":" + dsName; if (!keys_adding.has(key)) continue; - let layer = prepared_tile.data.get(rule.dataLayer); + const layer = prepared_tile.data.get(rule.dataLayer); if (layer === undefined) continue; - let feats = layer; + const feats = layer; if (rule.sort) feats.sort((a, b) => { if (rule.sort) { @@ -360,24 +360,24 @@ export class Labeler { return 0; }); - let layout = { + const layout = { index: this.index, zoom: this.z, scratch: this.scratch, order: order, overzoom: this.z - prepared_tile.data_tile.z, }; - for (let feature of feats) { + for (const feature of feats) { if (rule.filter && !rule.filter(this.z, feature)) continue; - let transformed = transformGeom( + const transformed = transformGeom( feature.geom, prepared_tile.scale, - prepared_tile.origin + prepared_tile.origin, ); - let labels = rule.symbolizer.place(layout, transformed, feature); + const labels = rule.symbolizer.place(layout, transformed, feature); if (!labels) continue; - for (let label of labels) { + for (const label of labels) { var label_added = false; if ( label.deduplicationKey && @@ -389,15 +389,15 @@ export class Labeler { // does the label collide with anything? if (this.index.labelCollides(label, Infinity)) { if (!this.index.labelCollides(label, order)) { - let conflicts = this.index.searchLabel(label, Infinity); - for (let conflict of conflicts) { + const conflicts = this.index.searchLabel(label, Infinity); + for (const conflict of conflicts) { this.index.removeLabel(conflict); - for (let bbox of conflict.bboxes) { + for (const bbox of conflict.bboxes) { this.findInvalidatedTiles( tiles_invalidated, prepared_tile.dim, bbox, - key + key, ); } } @@ -411,7 +411,7 @@ export class Labeler { } if (label_added) { - for (let bbox of label.bboxes) { + for (const bbox of label.bboxes) { if ( bbox.maxX > prepared_tile.origin.x + prepared_tile.dim || bbox.minX < prepared_tile.origin.x || @@ -422,7 +422,7 @@ export class Labeler { tiles_invalidated, prepared_tile.dim, bbox, - key + key, ); } } @@ -446,10 +446,10 @@ export class Labeler { tiles_invalidated: Set, dim: number, bbox: Bbox, - key: string + key: string, ) { - let touched = covering(this.z, dim, bbox); - for (let s of touched) { + const touched = covering(this.z, dim, bbox); + for (const s of touched) { if (s.key != key && this.index.hasPrefix(s.key)) { tiles_invalidated.add(s.display); } @@ -458,8 +458,8 @@ export class Labeler { public add(prepared_tilemap: Map): number { var all_added = true; - for (let [k, prepared_tiles] of prepared_tilemap) { - for (let prepared_tile of prepared_tiles) { + for (const [k, prepared_tiles] of prepared_tilemap) { + for (const prepared_tile of prepared_tiles) { if (!this.index.has(toIndex(prepared_tile.data_tile) + ":" + k)) all_added = false; } @@ -468,7 +468,7 @@ export class Labeler { if (all_added) { return 0; } else { - let timing = this.layout(prepared_tilemap); + const timing = this.layout(prepared_tilemap); return timing; } } @@ -485,7 +485,7 @@ export class Labelers { scratch: CanvasRenderingContext2D, labelRules: LabelRule[], maxLabeledTiles: number, - callback: TileInvalidationCallback + callback: TileInvalidationCallback, ) { this.labelers = new Map(); this.scratch = scratch; @@ -504,7 +504,7 @@ export class Labelers { this.scratch, this.labelRules, this.maxLabeledTiles, - this.callback + this.callback, ); this.labelers.set(z, labeler); return labeler.add(prepared_tilemap); @@ -512,7 +512,7 @@ export class Labelers { } public getIndex(z: number) { - let labeler = this.labelers.get(z); + const labeler = this.labelers.get(z); if (labeler) return labeler.index; // TODO cleanup } } diff --git a/src/line.ts b/src/line.ts index a5b7ec0e..1f5feac7 100644 --- a/src/line.ts +++ b/src/line.ts @@ -12,7 +12,7 @@ export interface LabelableSegment { const linelabel = ( pts: Point[], max_angle_delta: number, - targetLen: number + targetLen: number, ): LabelableSegment[] => { var chunks = []; var a, @@ -34,7 +34,7 @@ const linelabel = ( if (pts.length < 2) return []; if (pts.length === 2) { d = Math.sqrt( - Math.pow(pts[1].x - pts[0].x, 2) + Math.pow(pts[1].y - pts[0].y, 2) + Math.pow(pts[1].x - pts[0].x, 2) + Math.pow(pts[1].y - pts[0].y, 2), ); return [ @@ -49,7 +49,7 @@ const linelabel = ( } abmag = Math.sqrt( - Math.pow(pts[1].x - pts[0].x, 2) + Math.pow(pts[1].y - pts[0].y, 2) + Math.pow(pts[1].x - pts[0].x, 2) + Math.pow(pts[1].y - pts[0].y, 2), ); for (i = 1, n = pts.length - 1; i < n; i++) { a = pts[i - 1]; @@ -98,28 +98,28 @@ export function simpleLabel( mls: any, minimum: number, repeatDistance: number, - cellSize: number + cellSize: number, ): LabelCandidate[] { let longestStart; let longestEnd; - let longestLength = 0; + const longestLength = 0; - let candidates = []; + const candidates = []; var lastLabeledDistance = -Infinity; - for (let ls of mls) { - let segments = linelabel(ls, Math.PI / 45, minimum); // 4 degrees, close to a straight line - for (let segment of segments) { + for (const ls of mls) { + const segments = linelabel(ls, Math.PI / 45, minimum); // 4 degrees, close to a straight line + for (const segment of segments) { if (segment.length >= minimum + cellSize) { - let start = new Point( + const start = new Point( ls[segment.beginIndex].x, - ls[segment.beginIndex].y + ls[segment.beginIndex].y, ); - let end = ls[segment.endIndex - 1]; - let normalized = new Point( + const end = ls[segment.endIndex - 1]; + const normalized = new Point( (end.x - start.x) / segment.length, - (end.y - start.y) / segment.length + (end.y - start.y) / segment.length, ); // offset from the start by cellSize to allow streets that meet at right angles @@ -143,15 +143,15 @@ export function simpleLabel( export function lineCells(a: Point, b: Point, length: number, spacing: number) { // determine function of line - let dx = b.x - a.x; - let dy = b.y - a.y; - let dist = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2)); + const dx = b.x - a.x; + const dy = b.y - a.y; + const dist = Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2)); - let retval = []; + const retval = []; // starting from the anchor, generate square cells, // guaranteeing to cover the endpoint for (var i = 0; i < length + spacing; i += 2 * spacing) { - let factor = (i * 1) / dist; + const factor = (i * 1) / dist; retval.push({ x: a.x + factor * dx, y: a.y + factor * dy }); } return retval; diff --git a/src/painter.ts b/src/painter.ts index 02998d2e..4046ef27 100644 --- a/src/painter.ts +++ b/src/painter.ts @@ -1,8 +1,8 @@ import Point from "@mapbox/point-geometry"; -import { Zxy, Bbox, Feature } from "./tilecache"; -import { PreparedTile, transformGeom } from "./view"; -import { PaintSymbolizer } from "./symbolizer"; import { Index } from "./labeler"; +import { PaintSymbolizer } from "./symbolizer"; +import { Bbox, Feature, Zxy } from "./tilecache"; +import { PreparedTile, transformGeom } from "./view"; export type Filter = (zoom: number, feature: Feature) => boolean; @@ -25,35 +25,35 @@ export function painter( bbox: Bbox, origin: Point, clip: boolean, - debug?: string + debug?: string, ) { - let start = performance.now(); + const start = performance.now(); ctx.save(); ctx.miterLimit = 2; for (var rule of rules) { if (rule.minzoom && z < rule.minzoom) continue; if (rule.maxzoom && z > rule.maxzoom) continue; - let prepared_tiles = prepared_tilemap.get(rule.dataSource || ""); + const prepared_tiles = prepared_tilemap.get(rule.dataSource || ""); if (!prepared_tiles) continue; - for (let prepared_tile of prepared_tiles) { + for (const prepared_tile of prepared_tiles) { var layer = prepared_tile.data.get(rule.dataLayer); if (layer === undefined) continue; if (rule.symbolizer.before) rule.symbolizer.before(ctx, prepared_tile.z); - let po = prepared_tile.origin; - let dim = prepared_tile.dim; - let ps = prepared_tile.scale; + const po = prepared_tile.origin; + const dim = prepared_tile.dim; + const ps = prepared_tile.scale; ctx.save(); // apply clipping to the tile // find the smallest of all the origins if (clip) { ctx.beginPath(); - let minX = Math.max(po.x - origin.x, bbox.minX - origin.x); // - 0.5; - let minY = Math.max(po.y - origin.y, bbox.minY - origin.y); // - 0.5; - let maxX = Math.min(po.x - origin.x + dim, bbox.maxX - origin.x); // + 0.5; - let maxY = Math.min(po.y - origin.y + dim, bbox.maxY - origin.y); // + 0.5; + const minX = Math.max(po.x - origin.x, bbox.minX - origin.x); // - 0.5; + const minY = Math.max(po.y - origin.y, bbox.minY - origin.y); // - 0.5; + const maxX = Math.min(po.x - origin.x + dim, bbox.maxX - origin.x); // + 0.5; + const maxY = Math.min(po.y - origin.y + dim, bbox.maxY - origin.y); // + 0.5; ctx.rect(minX, minY, maxX - minX, maxY - minY); ctx.clip(); } @@ -70,7 +70,7 @@ export function painter( for (var feature of layer) { let geom = feature.geom; - let fbox = feature.bbox; + const fbox = feature.bbox; if ( fbox.maxX * ps + po.x < bbox.minX || fbox.minX * ps + po.x > bbox.maxX || @@ -95,13 +95,13 @@ export function painter( bbox.minX - origin.x, bbox.minY - origin.y, bbox.maxX - bbox.minX, - bbox.maxY - bbox.minY + bbox.maxY - bbox.minY, ); ctx.clip(); } if (label_data) { - let matches = label_data.searchBbox(bbox, Infinity); + const matches = label_data.searchBbox(bbox, Infinity); for (var label of matches) { ctx.save(); ctx.translate(label.anchor.x - origin.x, label.anchor.y - origin.y); @@ -116,14 +116,14 @@ export function painter( label.anchor.x - origin.x - 2, label.anchor.y - origin.y - 2, 4, - 4 + 4, ); - for (let bbox of label.bboxes) { + for (const bbox of label.bboxes) { ctx.strokeRect( bbox.minX - origin.x, bbox.minY - origin.y, bbox.maxX - bbox.minX, - bbox.maxY - bbox.minY + bbox.maxY - bbox.minY, ); } } diff --git a/src/symbolizer.ts b/src/symbolizer.ts index 7ab26a0a..c921c166 100644 --- a/src/symbolizer.ts +++ b/src/symbolizer.ts @@ -14,9 +14,9 @@ import { } from "./attribute"; import { Label, Layout } from "./labeler"; import { lineCells, simpleLabel } from "./line"; +import { Sheet } from "./task"; import { linebreak } from "./text"; import { Bbox, Feature, GeomType } from "./tilecache"; -import { Sheet } from "./task"; // https://bugs.webkit.org/show_bug.cgi?id=230751 const MAX_VERTICES_PER_DRAW_CALL = 5400; @@ -27,7 +27,7 @@ export interface PaintSymbolizer { ctx: CanvasRenderingContext2D, geom: Point[][], z: number, - feature: Feature + feature: Feature, ): void; } @@ -63,7 +63,7 @@ export interface LabelSymbolizer { export const createPattern = ( width: number, height: number, - fn: (canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D) => void + fn: (canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D) => void, ) => { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); @@ -110,7 +110,7 @@ export class PolygonSymbolizer implements PaintSymbolizer { ctx.globalAlpha = this.opacity.get(z); ctx.fillStyle = this.fill.get(z); ctx.strokeStyle = this.stroke.get(z); - let width = this.width.get(z); + const width = this.width.get(z); if (width > 0) this.do_stroke = true; ctx.lineWidth = width; } @@ -124,7 +124,7 @@ export class PolygonSymbolizer implements PaintSymbolizer { ctx: CanvasRenderingContext2D, geom: Point[][], z: number, - f: Feature + f: Feature, ) { var do_stroke = false; if (this.per_feature) { @@ -138,7 +138,7 @@ export class PolygonSymbolizer implements PaintSymbolizer { } } - let drawPath = () => { + const drawPath = () => { ctx.fill(); if (do_stroke || this.do_stroke) { ctx.stroke(); @@ -154,7 +154,7 @@ export class PolygonSymbolizer implements PaintSymbolizer { ctx.beginPath(); } for (var p = 0; p < poly.length; p++) { - let pt = poly[p]; + const pt = poly[p]; if (p == 0) ctx.moveTo(pt.x, pt.y); else ctx.lineTo(pt.x, pt.y); } @@ -166,7 +166,7 @@ export class PolygonSymbolizer implements PaintSymbolizer { export function arr(base: number, a: number[]): (z: number) => number { return (z) => { - let b = z - base; + const b = z - base; if (b >= 0 && b < a.length) { return a[b]; } @@ -188,7 +188,7 @@ function computeInterpolationFactor( z: number, idx: number, base: number, - stops: number[][] + stops: number[][], ): number { const difference = stops[idx + 1][0] - stops[idx][0]; const progress = z - stops[idx][0]; @@ -211,7 +211,7 @@ export function exp(base: number, stops: number[][]): (z: number) => number { export type Stop = [number, number] | [number, string] | [number, boolean]; export function step( output0: number | string | boolean, - stops: Stop[] + stops: Stop[], ): (z: number) => number | string | boolean { // Step computes discrete results by evaluating a piecewise-constant // function defined by stops. @@ -237,7 +237,7 @@ export function cubicBezier( y1: number, x2: number, y2: number, - stops: number[][] + stops: number[][], ): (z: number) => number { return (z) => { if (stops.length < 1) return 0; @@ -310,11 +310,11 @@ export class LineSymbolizer implements PaintSymbolizer { ctx: CanvasRenderingContext2D, geom: Point[][], z: number, - f: Feature + f: Feature, ) { if (this.skip) return; - let strokePath = () => { + const strokePath = () => { if (this.per_feature) { ctx.globalAlpha = this.opacity.get(z, f); ctx.lineCap = this.lineCap.get(z, f); @@ -351,7 +351,7 @@ export class LineSymbolizer implements PaintSymbolizer { ctx.beginPath(); } for (var p = 0; p < ls.length; p++) { - let pt = ls[p]; + const pt = ls[p]; if (p == 0) ctx.moveTo(pt.x, pt.y); else ctx.lineTo(pt.x, pt.y); } @@ -377,20 +377,20 @@ export class IconSymbolizer implements LabelSymbolizer { } public place(layout: Layout, geom: Point[][], feature: Feature) { - let pt = geom[0]; - let a = new Point(geom[0][0].x, geom[0][0].y); - let loc = this.sheet.get(this.name); - let width = loc.w / this.dpr; - let height = loc.h / this.dpr; + const pt = geom[0]; + const a = new Point(geom[0][0].x, geom[0][0].y); + const loc = this.sheet.get(this.name); + const width = loc.w / this.dpr; + const height = loc.h / this.dpr; - let bbox = { + const bbox = { minX: a.x - width / 2, minY: a.y - height / 2, maxX: a.x + width / 2, maxY: a.y + height / 2, }; - let draw = (ctx: CanvasRenderingContext2D) => { + const draw = (ctx: CanvasRenderingContext2D) => { ctx.globalAlpha = 1; ctx.drawImage( this.sheet.canvas, @@ -401,7 +401,7 @@ export class IconSymbolizer implements LabelSymbolizer { -loc.w / 2 / this.dpr, -loc.h / 2 / this.dpr, loc.w / 2, - loc.h / 2 + loc.h / 2, ); }; return [{ anchor: a, bboxes: [bbox], draw: draw }]; @@ -433,12 +433,12 @@ export class CircleSymbolizer implements LabelSymbolizer, PaintSymbolizer { ctx: CanvasRenderingContext2D, geom: Point[][], z: number, - f: Feature + f: Feature, ) { ctx.globalAlpha = this.opacity.get(z, f); - let radius = this.radius.get(z, f); - let width = this.width.get(z, f); + const radius = this.radius.get(z, f); + const width = this.width.get(z, f); if (width > 0) { ctx.strokeStyle = this.stroke.get(z, f); ctx.lineWidth = width; @@ -454,17 +454,17 @@ export class CircleSymbolizer implements LabelSymbolizer, PaintSymbolizer { } public place(layout: Layout, geom: Point[][], feature: Feature) { - let pt = geom[0]; - let a = new Point(geom[0][0].x, geom[0][0].y); - let radius = this.radius.get(layout.zoom, feature); - let bbox = { + const pt = geom[0]; + const a = new Point(geom[0][0].x, geom[0][0].y); + const radius = this.radius.get(layout.zoom, feature); + const bbox = { minX: a.x - radius, minY: a.y - radius, maxX: a.x + radius, maxY: a.y + radius, }; - let draw = (ctx: CanvasRenderingContext2D) => { + const draw = (ctx: CanvasRenderingContext2D) => { this.draw(ctx, [[new Point(0, 0)]], layout.zoom, feature); }; return [{ anchor: a, bboxes: [bbox], draw }]; @@ -484,7 +484,7 @@ export class ShieldSymbolizer implements LabelSymbolizer { background?: AttrOption; padding?: AttrOption; } & FontAttrOptions & - TextAttrOptions + TextAttrOptions, ) { this.font = new FontAttr(options); this.text = new TextAttr(options); @@ -494,34 +494,34 @@ export class ShieldSymbolizer implements LabelSymbolizer { } public place(layout: Layout, geom: Point[][], f: Feature) { - let property = this.text.get(layout.zoom, f); + const property = this.text.get(layout.zoom, f); if (!property) return undefined; - let font = this.font.get(layout.zoom, f); + const font = this.font.get(layout.zoom, f); layout.scratch.font = font; - let metrics = layout.scratch.measureText(property); + const metrics = layout.scratch.measureText(property); - let width = metrics.width; - let ascent = metrics.actualBoundingBoxAscent; - let descent = metrics.actualBoundingBoxDescent; + const width = metrics.width; + const ascent = metrics.actualBoundingBoxAscent; + const descent = metrics.actualBoundingBoxDescent; - let pt = geom[0]; - let a = new Point(geom[0][0].x, geom[0][0].y); - let p = this.padding.get(layout.zoom, f); - let bbox = { + const pt = geom[0]; + const a = new Point(geom[0][0].x, geom[0][0].y); + const p = this.padding.get(layout.zoom, f); + const bbox = { minX: a.x - width / 2 - p, minY: a.y - ascent - p, maxX: a.x + width / 2 + p, maxY: a.y + descent + p, }; - let draw = (ctx: CanvasRenderingContext2D) => { + const draw = (ctx: CanvasRenderingContext2D) => { ctx.globalAlpha = 1; ctx.fillStyle = this.background.get(layout.zoom, f); ctx.fillRect( -width / 2 - p, -ascent - p, width + 2 * p, - ascent + descent + 2 * p + ascent + descent + 2 * p, ); ctx.fillStyle = this.fill.get(layout.zoom, f); ctx.font = font; @@ -543,12 +543,12 @@ export class FlexSymbolizer implements LabelSymbolizer { var labels = this.list[0].place(layout, geom, feature); if (!labels) return undefined; var label = labels[0]; - let anchor = label.anchor; + const anchor = label.anchor; let bbox = label.bboxes[0]; - let height = bbox.maxY - bbox.minY; - let draws = [{ draw: label.draw, translate: { x: 0, y: 0 } }]; + const height = bbox.maxY - bbox.minY; + const draws = [{ draw: label.draw, translate: { x: 0, y: 0 } }]; - let newGeom = [[new Point(geom[0][0].x, geom[0][0].y + height)]]; + const newGeom = [[new Point(geom[0][0].x, geom[0][0].y + height)]]; for (let i = 1; i < this.list.length; i++) { labels = this.list[i].place(layout, newGeom, feature); if (labels) { @@ -558,8 +558,8 @@ export class FlexSymbolizer implements LabelSymbolizer { } } - let draw = (ctx: CanvasRenderingContext2D) => { - for (let sub of draws) { + const draw = (ctx: CanvasRenderingContext2D) => { + for (const sub of draws) { ctx.save(); ctx.translate(sub.translate.x, sub.translate.y); sub.draw(ctx); @@ -588,14 +588,14 @@ export class GroupSymbolizer implements LabelSymbolizer { } public place(layout: Layout, geom: Point[][], feature: Feature) { - let first = this.list[0]; + const first = this.list[0]; if (!first) return undefined; var labels = first.place(layout, geom, feature); if (!labels) return undefined; var label = labels[0]; - let anchor = label.anchor; + const anchor = label.anchor; let bbox = label.bboxes[0]; - let draws = [label.draw]; + const draws = [label.draw]; for (let i = 1; i < this.list.length; i++) { labels = this.list[i].place(layout, geom, feature); @@ -604,7 +604,7 @@ export class GroupSymbolizer implements LabelSymbolizer { bbox = mergeBbox(bbox, label.bboxes[0]); draws.push(label.draw); } - let draw = (ctx: CanvasRenderingContext2D) => { + const draw = (ctx: CanvasRenderingContext2D) => { draws.forEach((d) => d(ctx)); }; @@ -620,21 +620,21 @@ export class CenteredSymbolizer implements LabelSymbolizer { } public place(layout: Layout, geom: Point[][], feature: Feature) { - let a = geom[0][0]; - let placed = this.symbolizer.place(layout, [[new Point(0, 0)]], feature); + const a = geom[0][0]; + const placed = this.symbolizer.place(layout, [[new Point(0, 0)]], feature); if (!placed || placed.length == 0) return undefined; - let first_label = placed[0]; - let bbox = first_label.bboxes[0]; - let width = bbox.maxX - bbox.minX; - let height = bbox.maxY - bbox.minY; - let centered = { + const first_label = placed[0]; + const bbox = first_label.bboxes[0]; + const width = bbox.maxX - bbox.minX; + const height = bbox.maxY - bbox.minY; + const centered = { minX: a.x - width / 2, maxX: a.x + width / 2, minY: a.y - height / 2, maxY: a.y + height / 2, }; - let draw = (ctx: CanvasRenderingContext2D) => { + const draw = (ctx: CanvasRenderingContext2D) => { ctx.translate(-width / 2, height / 2 - bbox.maxY); first_label.draw(ctx, { justify: Justify.Center }); }; @@ -653,9 +653,9 @@ export class Padding implements LabelSymbolizer { } public place(layout: Layout, geom: Point[][], feature: Feature) { - let placed = this.symbolizer.place(layout, geom, feature); + const placed = this.symbolizer.place(layout, geom, feature); if (!placed || placed.length == 0) return undefined; - let padding = this.padding.get(layout.zoom, feature); + const padding = this.padding.get(layout.zoom, feature); for (var label of placed) { for (var bbox of label.bboxes) { bbox.minX -= padding; @@ -705,37 +705,37 @@ export class TextSymbolizer implements LabelSymbolizer { } public place(layout: Layout, geom: Point[][], feature: Feature) { - let property = this.text.get(layout.zoom, feature); + const property = this.text.get(layout.zoom, feature); if (!property) return undefined; - let font = this.font.get(layout.zoom, feature); + const font = this.font.get(layout.zoom, feature); layout.scratch.font = font; - let letterSpacing = this.letterSpacing.get(layout.zoom, feature); + const letterSpacing = this.letterSpacing.get(layout.zoom, feature); // line breaking - let lines = linebreak( + const lines = linebreak( property, - this.maxLineCodeUnits.get(layout.zoom, feature) + this.maxLineCodeUnits.get(layout.zoom, feature), ); var longestLine = ""; var longestLineLen = 0; - for (let line of lines) { + for (const line of lines) { if (line.length > longestLineLen) { longestLineLen = line.length; longestLine = line; } } - let metrics = layout.scratch.measureText(longestLine); - let width = metrics.width + letterSpacing * (longestLineLen - 1); + const metrics = layout.scratch.measureText(longestLine); + const width = metrics.width + letterSpacing * (longestLineLen - 1); - let ascent = metrics.actualBoundingBoxAscent; - let descent = metrics.actualBoundingBoxDescent; - let lineHeight = + const ascent = metrics.actualBoundingBoxAscent; + const descent = metrics.actualBoundingBoxDescent; + const lineHeight = (ascent + descent) * this.lineHeight.get(layout.zoom, feature); - let a = new Point(geom[0][0].x, geom[0][0].y); - let bbox = { + const a = new Point(geom[0][0].x, geom[0][0].y); + const bbox = { minX: a.x, minY: a.y - ascent, maxX: a.x + width, @@ -744,14 +744,14 @@ export class TextSymbolizer implements LabelSymbolizer { // inside draw, the origin is the anchor // and the anchor is the typographic baseline of the first line - let draw = (ctx: CanvasRenderingContext2D, extra?: DrawExtra) => { + const draw = (ctx: CanvasRenderingContext2D, extra?: DrawExtra) => { ctx.globalAlpha = 1; ctx.font = font; ctx.fillStyle = this.fill.get(layout.zoom, feature); - let textStrokeWidth = this.width.get(layout.zoom, feature); + const textStrokeWidth = this.width.get(layout.zoom, feature); var y = 0; - for (let line of lines) { + for (const line of lines) { var startX = 0; if ( this.justify == Justify.Center || @@ -814,7 +814,7 @@ export interface OffsetSymbolizerValues { export type DataDrivenOffsetSymbolizer = ( zoom: number, - feature: Feature + feature: Feature, ) => OffsetSymbolizerValues; export interface OffsetSymbolizerOptions { @@ -857,11 +857,11 @@ export class OffsetSymbolizer implements LabelSymbolizer { public place(layout: Layout, geom: Point[][], feature: Feature) { if (feature.geomType !== GeomType.Point) return undefined; - let anchor = geom[0][0]; - let placed = this.symbolizer.place(layout, [[new Point(0, 0)]], feature); + const anchor = geom[0][0]; + const placed = this.symbolizer.place(layout, [[new Point(0, 0)]], feature); if (!placed || placed.length == 0) return undefined; - let first_label = placed[0]; - let fb = first_label.bboxes[0]; + const first_label = placed[0]; + const fb = first_label.bboxes[0]; // Overwrite options values via the data driven function if exists let offsetXValue = this.offsetX; @@ -882,7 +882,7 @@ export class OffsetSymbolizer implements LabelSymbolizer { const offsetX = offsetXValue.get(layout.zoom, feature); const offsetY = offsetYValue.get(layout.zoom, feature); - let getBbox = (a: Point, o: Point) => { + const getBbox = (a: Point, o: Point) => { return { minX: a.x + o.x + fb.minX, minY: a.y + o.y + fb.minY, @@ -893,7 +893,7 @@ export class OffsetSymbolizer implements LabelSymbolizer { var origin = new Point(offsetX, offsetY); var justify: Justify; - let draw = (ctx: CanvasRenderingContext2D) => { + const draw = (ctx: CanvasRenderingContext2D) => { ctx.translate(origin.x, origin.y); first_label.draw(ctx, { justify: justify }); }; @@ -904,7 +904,7 @@ export class OffsetSymbolizer implements LabelSymbolizer { return [{ anchor: anchor, bboxes: [bbox], draw: draw }]; }; - for (let placement of placements) { + for (const placement of placements) { const xAxisOffset = this.computeXAxisOffset(offsetX, fb, placement); const yAxisOffset = this.computeYAxisOffset(offsetY, fb, placement); justify = this.computeJustify(justifyValue, placement); @@ -922,7 +922,7 @@ export class OffsetSymbolizer implements LabelSymbolizer { return offsetX - labelHalfWidth; if ( [TextPlacements.NW, TextPlacements.W, TextPlacements.SW].includes( - placement + placement, ) ) return offsetX - labelWidth; @@ -937,13 +937,13 @@ export class OffsetSymbolizer implements LabelSymbolizer { return offsetY - labelCenterHeight; if ( [TextPlacements.NW, TextPlacements.NE, TextPlacements.N].includes( - placement + placement, ) ) return offsetY - labelBottom; if ( [TextPlacements.SW, TextPlacements.SE, TextPlacements.S].includes( - placement + placement, ) ) return offsetY + labelHalfHeight; @@ -956,7 +956,7 @@ export class OffsetSymbolizer implements LabelSymbolizer { return Justify.Center; if ( [TextPlacements.NE, TextPlacements.E, TextPlacements.SE].includes( - placement + placement, ) ) return Justify.Left; @@ -970,7 +970,7 @@ export class OffsetTextSymbolizer implements LabelSymbolizer { constructor(options: OffsetSymbolizerOptions & TextSymbolizerOptions) { this.symbolizer = new OffsetSymbolizer( new TextSymbolizer(options), - options + options, ); } @@ -1008,7 +1008,7 @@ export class LineLabelSymbolizer implements LabelSymbolizer { repeatDistance?: AttrOption; position?: LineLabelPlacement; } & TextAttrOptions & - FontAttrOptions + FontAttrOptions, ) { this.font = new FontAttr(options); this.text = new TextAttr(options); @@ -1023,46 +1023,51 @@ export class LineLabelSymbolizer implements LabelSymbolizer { } public place(layout: Layout, geom: Point[][], feature: Feature) { - let name = this.text.get(layout.zoom, feature); + const name = this.text.get(layout.zoom, feature); if (!name) return undefined; if (name.length > this.maxLabelCodeUnits.get(layout.zoom, feature)) return undefined; - let MIN_LABELABLE_DIM = 20; - let fbbox = feature.bbox; + const MIN_LABELABLE_DIM = 20; + const fbbox = feature.bbox; if ( fbbox.maxY - fbbox.minY < MIN_LABELABLE_DIM && fbbox.maxX - fbbox.minX < MIN_LABELABLE_DIM ) return undefined; - let font = this.font.get(layout.zoom, feature); + const font = this.font.get(layout.zoom, feature); layout.scratch.font = font; - let metrics = layout.scratch.measureText(name); - let width = metrics.width; - let height = + const metrics = layout.scratch.measureText(name); + const width = metrics.width; + const height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent; var repeatDistance = this.repeatDistance.get(layout.zoom, feature); if (layout.overzoom > 4) repeatDistance *= 1 << (layout.overzoom - 4); - let cell_size = height * 2; + const cell_size = height * 2; - let label_candidates = simpleLabel(geom, width, repeatDistance, cell_size); + const label_candidates = simpleLabel( + geom, + width, + repeatDistance, + cell_size, + ); if (label_candidates.length == 0) return undefined; - let labels = []; - for (let candidate of label_candidates) { - let dx = candidate.end.x - candidate.start.x; - let dy = candidate.end.y - candidate.start.y; + const labels = []; + for (const candidate of label_candidates) { + const dx = candidate.end.x - candidate.start.x; + const dy = candidate.end.y - candidate.start.y; - let cells = lineCells( + const cells = lineCells( candidate.start, candidate.end, width, - cell_size / 2 + cell_size / 2, ); - let bboxes = cells.map((c) => { + const bboxes = cells.map((c) => { return { minX: c.x - cell_size / 2, minY: c.y - cell_size / 2, @@ -1071,7 +1076,7 @@ export class LineLabelSymbolizer implements LabelSymbolizer { }; }); - let draw = (ctx: CanvasRenderingContext2D) => { + const draw = (ctx: CanvasRenderingContext2D) => { ctx.globalAlpha = 1; // ctx.beginPath(); // ctx.moveTo(0, 0); @@ -1090,10 +1095,10 @@ export class LineLabelSymbolizer implements LabelSymbolizer { heightPlacement += height / 2; ctx.translate( 0, - heightPlacement - this.offset.get(layout.zoom, feature) + heightPlacement - this.offset.get(layout.zoom, feature), ); ctx.font = font; - let lineWidth = this.width.get(layout.zoom, feature); + const lineWidth = this.width.get(layout.zoom, feature); if (lineWidth) { ctx.lineWidth = lineWidth; ctx.strokeStyle = this.stroke.get(layout.zoom, feature); @@ -1123,30 +1128,30 @@ export class PolygonLabelSymbolizer implements LabelSymbolizer { } public place(layout: Layout, geom: Point[][], feature: Feature) { - let fbbox = feature.bbox; - let area = (fbbox.maxY - fbbox.minY) * (fbbox.maxX - fbbox.minX); // TODO needs to be based on zoom level/overzooming + const fbbox = feature.bbox; + const area = (fbbox.maxY - fbbox.minY) * (fbbox.maxX - fbbox.minX); // TODO needs to be based on zoom level/overzooming if (area < 20000) return undefined; - let placed = this.symbolizer.place(layout, [[new Point(0, 0)]], feature); + const placed = this.symbolizer.place(layout, [[new Point(0, 0)]], feature); if (!placed || placed.length == 0) return undefined; - let first_label = placed[0]; - let fb = first_label.bboxes[0]; + const first_label = placed[0]; + const fb = first_label.bboxes[0]; - let first_poly = geom[0]; - let found = polylabel([first_poly.map((c) => [c.x, c.y])]); - let a = new Point(found[0], found[1]); + const first_poly = geom[0]; + const found = polylabel([first_poly.map((c) => [c.x, c.y])]); + const a = new Point(found[0], found[1]); - let bbox = { + const bbox = { minX: a.x - (fb.maxX - fb.minX) / 2, minY: a.y - (fb.maxY - fb.minY) / 2, maxX: a.x + (fb.maxX - fb.minX) / 2, maxY: a.y + (fb.maxY - fb.minY) / 2, }; - let draw = (ctx: CanvasRenderingContext2D) => { + const draw = (ctx: CanvasRenderingContext2D) => { ctx.translate( first_label.anchor.x - (fb.maxX - fb.minX) / 2, - first_label.anchor.y + first_label.anchor.y, ); first_label.draw(ctx); }; diff --git a/src/task.ts b/src/task.ts index 0ca24683..79acbfbb 100644 --- a/src/task.ts +++ b/src/task.ts @@ -2,7 +2,7 @@ import potpack from "potpack"; // https://github.com/tangrams/tangram/blob/master/src/styles/text/font_manager.js export const Font = (name: string, url: string, weight: string) => { - let ff = new FontFace(name, "url(" + url + ")", { weight: weight }); + const ff = new FontFace(name, "url(" + url + ")", { weight: weight }); document.fonts.add(ff); return ff.load(); }; @@ -23,9 +23,9 @@ interface PotPackInput { img: HTMLImageElement; } -let mkimg = async (src: string): Promise => { +const mkimg = async (src: string): Promise => { return new Promise((resolve, reject) => { - let img = new Image(); + const img = new Image(); img.onload = () => resolve(img); img.onerror = () => reject("Invalid SVG"); img.src = src; @@ -57,17 +57,19 @@ export class Sheet { async load() { let src = this.src; - let scale = window.devicePixelRatio; + const scale = window.devicePixelRatio; if (src.endsWith(".html")) { - let c = await fetch(src); + const c = await fetch(src); src = await c.text(); } - let tree = new window.DOMParser().parseFromString(src, "text/html"); - let icons = Array.from(tree.body.children); + const tree = new window.DOMParser().parseFromString(src, "text/html"); + const icons = Array.from(tree.body.children); - let missingImg = await mkimg("data:image/svg+xml;base64," + btoa(MISSING)); + const missingImg = await mkimg( + "data:image/svg+xml;base64," + btoa(MISSING), + ); - let boxes: PotPackInput[] = [ + const boxes: PotPackInput[] = [ { w: missingImg.width * scale, h: missingImg.height * scale, @@ -76,11 +78,11 @@ export class Sheet { }, ]; - let serializer = new XMLSerializer(); - for (let ps of icons) { + const serializer = new XMLSerializer(); + for (const ps of icons) { var svg64 = btoa(serializer.serializeToString(ps)); var image64 = "data:image/svg+xml;base64," + svg64; - let img = await mkimg(image64); + const img = await mkimg(image64); boxes.push({ w: img.width * scale, h: img.height * scale, @@ -89,12 +91,12 @@ export class Sheet { }); } - let packresult = potpack(boxes); + const packresult = potpack(boxes); this.canvas.width = packresult.w; this.canvas.height = packresult.h; - let ctx = this.canvas.getContext("2d"); + const ctx = this.canvas.getContext("2d"); if (ctx) { - for (let box of boxes) { + for (const box of boxes) { if (box.x !== undefined && box.y !== undefined) { ctx.drawImage(box.img, box.x, box.y, box.w, box.h); if (box.id) diff --git a/src/text.ts b/src/text.ts index cb239ba8..4c7cff01 100644 --- a/src/text.ts +++ b/src/text.ts @@ -1,9 +1,9 @@ // TODO should be visual length in pixels, not strlen export function linebreak(str: string, maxUnits: number): string[] { if (str.length <= maxUnits) return [str]; - let endIndex = maxUnits - 1; - let space_before = str.lastIndexOf(" ", endIndex); - let space_after = str.indexOf(" ", endIndex); + const endIndex = maxUnits - 1; + const space_before = str.lastIndexOf(" ", endIndex); + const space_after = str.indexOf(" ", endIndex); if (space_before == -1 && space_after == -1) { return [str]; } diff --git a/src/tilecache.ts b/src/tilecache.ts index 8386fdf4..950245c4 100644 --- a/src/tilecache.ts +++ b/src/tilecache.ts @@ -95,21 +95,21 @@ const loadGeomAndBbox = (pbf: any, geometry: number, scale: number) => { function parseTile( buffer: ArrayBuffer, - tileSize: number + tileSize: number, ): Map { - let v = new VectorTile(new Protobuf(buffer)); - let result = new Map(); - for (let [key, value] of Object.entries(v.layers)) { - let features = []; - let layer = value as any; + const v = new VectorTile(new Protobuf(buffer)); + const result = new Map(); + for (const [key, value] of Object.entries(v.layers)) { + const features = []; + const layer = value as any; for (let i = 0; i < layer.length; i++) { - let loaded = loadGeomAndBbox( + const loaded = loadGeomAndBbox( layer.feature(i)._pbf, layer.feature(i)._geometry, - tileSize / layer.extent + tileSize / layer.extent, ); let numVertices = 0; - for (let part of loaded.geom) numVertices += part.length; + for (const part of loaded.geom) numVertices += part.length; features.push({ id: layer.feature(i).id, geomType: layer.feature(i).type, @@ -153,7 +153,7 @@ export class PmtilesSource implements TileSource { this.controllers.push([c.z, controller]); const signal = controller.signal; - let result = await this.p.getZxy(c.z, c.x, c.y, signal); + const result = await this.p.getZxy(c.z, c.x, c.y, signal); if (result) { return parseTile(result.data, tileSize); @@ -184,7 +184,7 @@ export class ZxySource implements TileSource { return true; }); } - let url = this.url + const url = this.url .replace("{z}", c.z.toString()) .replace("{x}", c.x.toString()) .replace("{y}", c.y.toString()); @@ -197,7 +197,7 @@ export class ZxySource implements TileSource { return resp.arrayBuffer(); }) .then((buffer) => { - let result = parseTile(buffer, tileSize); + const result = parseTile(buffer, tileSize); resolve(result); }) .catch((e) => { @@ -212,20 +212,20 @@ export interface CacheEntry { data: Map; } -let R = 6378137; -let MAX_LATITUDE = 85.0511287798; -let MAXCOORD = R * Math.PI; +const R = 6378137; +const MAX_LATITUDE = 85.0511287798; +const MAXCOORD = R * Math.PI; -let project = (latlng: number[]) => { - let d = Math.PI / 180; - let constrained_lat = Math.max( +const project = (latlng: number[]) => { + const d = Math.PI / 180; + const constrained_lat = Math.max( Math.min(MAX_LATITUDE, latlng[0]), - -MAX_LATITUDE + -MAX_LATITUDE, ); - let sin = Math.sin(constrained_lat * d); + const sin = Math.sin(constrained_lat * d); return new Point( R * latlng[1] * d, - (R * Math.log((1 + sin) / (1 - sin))) / 2 + (R * Math.log((1 + sin) / (1 - sin))) / 2, ); }; @@ -263,7 +263,7 @@ export function isInRing(point: Point, ring: Point[]): boolean { export function isCCW(ring: Point[]): boolean { var area = 0; for (var i = 0; i < ring.length; i++) { - let j = (i + 1) % ring.length; + const j = (i + 1) % ring.length; area += ring[i].x * ring[j].y; area -= ring[j].x * ring[i].y; } @@ -272,7 +272,7 @@ export function isCCW(ring: Point[]): boolean { export function pointInPolygon(point: Point, geom: Point[][]): boolean { var isInCurrentExterior = false; - for (let ring of geom) { + for (const ring of geom) { if (isCCW(ring)) { // it is an interior ring if (isInRing(point, ring)) isInCurrentExterior = false; @@ -287,8 +287,8 @@ export function pointInPolygon(point: Point, geom: Point[][]): boolean { export function pointMinDistToPoints(point: Point, geom: Point[][]): number { let min = Infinity; - for (let l of geom) { - let dist = Math.sqrt(dist2(point, l[0])); + for (const l of geom) { + const dist = Math.sqrt(dist2(point, l[0])); if (dist < min) min = dist; } return min; @@ -296,9 +296,9 @@ export function pointMinDistToPoints(point: Point, geom: Point[][]): number { export function pointMinDistToLines(point: Point, geom: Point[][]): number { let min = Infinity; - for (let l of geom) { + for (const l of geom) { for (var i = 0; i < l.length - 1; i++) { - let dist = Math.sqrt(distToSegmentSquared(point, l[i], l[i + 1])); + const dist = Math.sqrt(distToSegmentSquared(point, l[i], l[i + 1])); if (dist < min) min = dist; } } @@ -327,28 +327,28 @@ export class TileCache { lng: number, lat: number, zoom: number, - brushSize: number + brushSize: number, ): PickedFeature[] { - let projected = project([lat, lng]); + const projected = project([lat, lng]); var normalized = new Point( (projected.x + MAXCOORD) / (MAXCOORD * 2), - 1 - (projected.y + MAXCOORD) / (MAXCOORD * 2) + 1 - (projected.y + MAXCOORD) / (MAXCOORD * 2), ); if (normalized.x > 1) normalized.x = normalized.x - Math.floor(normalized.x); - let on_zoom = normalized.mult(1 << zoom); - let tile_x = Math.floor(on_zoom.x); - let tile_y = Math.floor(on_zoom.y); + const on_zoom = normalized.mult(1 << zoom); + const tile_x = Math.floor(on_zoom.x); + const tile_y = Math.floor(on_zoom.y); const idx = toIndex({ z: zoom, x: tile_x, y: tile_y }); - let retval: PickedFeature[] = []; - let entry = this.cache.get(idx); + const retval: PickedFeature[] = []; + const entry = this.cache.get(idx); if (entry) { const center = new Point( (on_zoom.x - tile_x) * this.tileSize, - (on_zoom.y - tile_y) * this.tileSize + (on_zoom.y - tile_y) * this.tileSize, ); - for (let [layer_name, layer_arr] of entry.data.entries()) { - for (let feature of layer_arr) { + for (const [layer_name, layer_arr] of entry.data.entries()) { + for (const feature of layer_arr) { // rough check by bbox // if ((query_bbox.maxX >= feature.bbox.minX && feature.bbox.maxX >= query_bbox.minX) && // (query_bbox.maxY >= feature.bbox.minY && feature.bbox.maxY >= query_bbox.minY)) { @@ -376,12 +376,12 @@ export class TileCache { public async get(c: Zxy): Promise> { const idx = toIndex(c); return new Promise((resolve, reject) => { - let entry = this.cache.get(idx); + const entry = this.cache.get(idx); if (entry) { entry.used = performance.now(); resolve(entry.data); } else { - let ifentry = this.inflight.get(idx); + const ifentry = this.inflight.get(idx); if (ifentry) { ifentry.push([resolve, reject]); } else { @@ -391,7 +391,7 @@ export class TileCache { .then((tile) => { this.cache.set(idx, { used: performance.now(), data: tile }); - let ifentry2 = this.inflight.get(idx); + const ifentry2 = this.inflight.get(idx); if (ifentry2) ifentry2.forEach((f) => f[0](tile)); this.inflight.delete(idx); resolve(tile); @@ -409,7 +409,7 @@ export class TileCache { } }) .catch((e) => { - let ifentry2 = this.inflight.get(idx); + const ifentry2 = this.inflight.get(idx); if (ifentry2) ifentry2.forEach((f) => f[1](e)); this.inflight.delete(idx); reject(e); diff --git a/src/view.ts b/src/view.ts index a36a6479..42d2d80e 100644 --- a/src/view.ts +++ b/src/view.ts @@ -1,13 +1,13 @@ import Point from "@mapbox/point-geometry"; +import { PMTiles } from "pmtiles"; import { - Zxy, - TileCache, - Feature, Bbox, - ZxySource, + Feature, PmtilesSource, + TileCache, + Zxy, + ZxySource, } from "./tilecache"; -import { PMTiles } from "pmtiles"; /* * PreparedTile @@ -37,12 +37,12 @@ export interface TileTransform { export const transformGeom = ( geom: Array>, scale: number, - translate: Point + translate: Point, ) => { - let retval = []; - for (let arr of geom) { - let loop = []; - for (let coord of arr) { + const retval = []; + for (const arr of geom) { + const loop = []; + for (const coord of arr) { loop.push(coord.clone().mult(scale).add(translate)); } retval.push(loop); @@ -51,7 +51,7 @@ export const transformGeom = ( }; export const wrap = (val: number, z: number) => { - let dim = 1 << z; + const dim = 1 << z; if (val < 0) val = dim + val; if (val >= dim) val = val % dim; return val; @@ -74,11 +74,11 @@ export class View { public dataTilesForBounds( display_zoom: number, - bounds: any + bounds: any, ): Array { - let fractional = + const fractional = Math.pow(2, display_zoom) / Math.pow(2, Math.ceil(display_zoom)); - let needed = []; + const needed = []; var scale = 1; var dim = this.tileCache.tileSize; if (display_zoom < this.levelDiff) { @@ -90,21 +90,21 @@ export class View { dim: dim * scale, }); } else if (display_zoom <= this.levelDiff + this.maxDataLevel) { - let f = 1 << this.levelDiff; + const f = 1 << this.levelDiff; - let basetile_size = 256 * fractional; + const basetile_size = 256 * fractional; - let data_zoom = Math.ceil(display_zoom) - this.levelDiff; + const data_zoom = Math.ceil(display_zoom) - this.levelDiff; - let mintile_x = Math.floor(bounds.minX / f / basetile_size); - let mintile_y = Math.floor(bounds.minY / f / basetile_size); - let maxtile_x = Math.floor(bounds.maxX / f / basetile_size); - let maxtile_y = Math.floor(bounds.maxY / f / basetile_size); + const mintile_x = Math.floor(bounds.minX / f / basetile_size); + const mintile_y = Math.floor(bounds.minY / f / basetile_size); + const maxtile_x = Math.floor(bounds.maxX / f / basetile_size); + const maxtile_y = Math.floor(bounds.maxY / f / basetile_size); for (var tx = mintile_x; tx <= maxtile_x; tx++) { for (var ty = mintile_y; ty <= maxtile_y; ty++) { - let origin = new Point( + const origin = new Point( tx * f * basetile_size, - ty * f * basetile_size + ty * f * basetile_size, ); needed.push({ data_tile: { @@ -119,17 +119,17 @@ export class View { } } } else { - let f = 1 << this.levelDiff; + const f = 1 << this.levelDiff; scale = (1 << (Math.ceil(display_zoom) - this.maxDataLevel - this.levelDiff)) * fractional; - let mintile_x = Math.floor(bounds.minX / f / 256 / scale); - let mintile_y = Math.floor(bounds.minY / f / 256 / scale); - let maxtile_x = Math.floor(bounds.maxX / f / 256 / scale); - let maxtile_y = Math.floor(bounds.maxY / f / 256 / scale); + const mintile_x = Math.floor(bounds.minX / f / 256 / scale); + const mintile_y = Math.floor(bounds.minY / f / 256 / scale); + const maxtile_x = Math.floor(bounds.maxX / f / 256 / scale); + const maxtile_y = Math.floor(bounds.maxY / f / 256 / scale); for (var tx = mintile_x; tx <= maxtile_x; tx++) { for (var ty = mintile_y; ty <= maxtile_y; ty++) { - let origin = new Point(tx * f * 256 * scale, ty * f * 256 * scale); + const origin = new Point(tx * f * 256 * scale, ty * f * 256 * scale); needed.push({ data_tile: { z: this.maxDataLevel, @@ -157,7 +157,7 @@ export class View { origin = new Point(0, 0); dim = dim * scale; } else if (display_tile.z <= this.levelDiff + this.maxDataLevel) { - let f = 1 << this.levelDiff; + const f = 1 << this.levelDiff; data_tile = { z: display_tile.z - this.levelDiff, x: Math.floor(display_tile.x / f), @@ -166,7 +166,7 @@ export class View { origin = new Point(data_tile.x * f * 256, data_tile.y * f * 256); } else { scale = 1 << (display_tile.z - this.maxDataLevel - this.levelDiff); - let f = 1 << this.levelDiff; + const f = 1 << this.levelDiff; data_tile = { z: this.maxDataLevel, x: Math.floor(display_tile.x / f / scale), @@ -174,7 +174,7 @@ export class View { }; origin = new Point( data_tile.x * f * scale * 256, - data_tile.y * f * scale * 256 + data_tile.y * f * scale * 256, ); dim = dim * scale; } @@ -183,14 +183,14 @@ export class View { public async getBbox( display_zoom: number, - bounds: Bbox + bounds: Bbox, ): Promise> { - let needed = this.dataTilesForBounds(display_zoom, bounds); - let result = await Promise.all( - needed.map((tt) => this.tileCache.get(tt.data_tile)) + const needed = this.dataTilesForBounds(display_zoom, bounds); + const result = await Promise.all( + needed.map((tt) => this.tileCache.get(tt.data_tile)), ); return result.map((data, i) => { - let tt = needed[i]; + const tt = needed[i]; return { data: data, z: display_zoom, @@ -203,7 +203,7 @@ export class View { } public async getDisplayTile(display_tile: Zxy): Promise { - let tt = this.dataTileForDisplayTile(display_tile); + const tt = this.dataTileForDisplayTile(display_tile); const data = await this.tileCache.get(tt.data_tile); return { data: data, @@ -216,9 +216,12 @@ export class View { } public queryFeatures(lng: number, lat: number, display_zoom: number) { - let rounded_zoom = Math.round(display_zoom); - let data_zoom = Math.min(rounded_zoom - this.levelDiff, this.maxDataLevel); - let brush_size = 16 / (1 << (rounded_zoom - data_zoom)); + const rounded_zoom = Math.round(display_zoom); + const data_zoom = Math.min( + rounded_zoom - this.levelDiff, + this.maxDataLevel, + ); + const brush_size = 16 / (1 << (rounded_zoom - data_zoom)); return this.tileCache.queryFeatures(lng, lat, data_zoom, brush_size); } } @@ -230,10 +233,10 @@ export interface SourceOptions { sources?: Record; } -export let sourcesToViews = (options: SourceOptions) => { - let sourceToViews = (o: SourceOptions): View => { - let level_diff = o.levelDiff === undefined ? 2 : o.levelDiff; - let maxDataZoom = o.maxDataZoom || 14; +export const sourcesToViews = (options: SourceOptions) => { + const sourceToViews = (o: SourceOptions): View => { + const level_diff = o.levelDiff === undefined ? 2 : o.levelDiff; + const maxDataZoom = o.maxDataZoom || 14; let source; if (typeof o.url === "string") { if (o.url.endsWith(".pmtiles")) { @@ -245,11 +248,11 @@ export let sourcesToViews = (options: SourceOptions) => { source = new PmtilesSource(o.url!, true); } - let cache = new TileCache(source, (256 * 1) << level_diff); + const cache = new TileCache(source, (256 * 1) << level_diff); return new View(cache, maxDataZoom, level_diff); }; - let sources = new Map(); + const sources = new Map(); if (options.sources) { for (const key in options.sources) { sources.set(key, sourceToViews(options.sources[key])); diff --git a/src/xray.ts b/src/xray.ts index 24d755c3..b9589f6f 100644 --- a/src/xray.ts +++ b/src/xray.ts @@ -1,10 +1,10 @@ -import { GeomType } from "./tilecache"; +import { Rule } from "./painter"; import { CircleSymbolizer, LineSymbolizer, PolygonSymbolizer, } from "./symbolizer"; -import { Rule } from "./painter"; +import { GeomType } from "./tilecache"; import { PreparedTile } from "./view"; export interface XraySelection { @@ -12,10 +12,10 @@ export interface XraySelection { dataLayer: string; } -let xray_symbolizers = ( +const xray_symbolizers = ( dataSource: string, dataLayer: string, - color: string + color: string, ): Rule[] => { return [ { @@ -58,9 +58,9 @@ let xray_symbolizers = ( ]; }; -export let xray_rules = ( +export const xray_rules = ( prepared_tilemap: Map, - xray: XraySelection // the highlighted layer + xray: XraySelection, // the highlighted layer ): Rule[] => { var rules: Rule[] = []; for (var [dataSource, tiles] of prepared_tilemap) { @@ -70,7 +70,7 @@ export let xray_rules = ( // do nothing since the highlighted layer should go last } else { rules = rules.concat( - xray_symbolizers(dataSource, dataLayer, "steelblue") + xray_symbolizers(dataSource, dataLayer, "steelblue"), ); } } @@ -79,7 +79,7 @@ export let xray_rules = ( // the highlighted layer rules = rules.concat( - xray_symbolizers(xray.dataSource || "", xray.dataLayer, "red") + xray_symbolizers(xray.dataSource || "", xray.dataLayer, "red"), ); return rules; }; diff --git a/test/attribute.test.ts b/test/attribute.test.ts index bdb6ca57..1cec30bb 100644 --- a/test/attribute.test.ts +++ b/test/attribute.test.ts @@ -125,12 +125,12 @@ test("textattr", async () => { ...emptyFeature, props: { "name:en": "Taipei", name: "臺北" }, }), - "Taipei" + "Taipei", ); t = new TextAttr({ label_props: ["name:en"], textTransform: "uppercase" }); assert.equal( t.get(0, { ...emptyFeature, props: { "name:en": "Taipei" } }), - "TAIPEI" + "TAIPEI", ); t = new TextAttr({ label_props: ["name:en"], textTransform: "lowercase" }); assert.equal( @@ -139,7 +139,7 @@ test("textattr", async () => { props: { "name:en": "Taipei" }, geomType: GeomType.Point, }), - "taipei" + "taipei", ); t = new TextAttr({ label_props: ["name:en"], textTransform: "capitalize" }); assert.equal( @@ -148,7 +148,7 @@ test("textattr", async () => { props: { "name:en": "from Berga to Taipei" }, geomType: GeomType.Point, }), - "From Berga To Taipei" + "From Berga To Taipei", ); t = new TextAttr({ label_props: ["name:en"], textTransform: "uppercase" }); assert.equal(t.get(0, { ...emptyFeature, props: {} }), undefined); @@ -163,7 +163,7 @@ test("textattr", async () => { props: { "name:en": "Taipei" }, geomType: GeomType.Point, }), - "TAIPEI" + "TAIPEI", ); t = new TextAttr({ label_props: ["name:en"], @@ -175,7 +175,7 @@ test("textattr", async () => { props: { "name:en": "Taipei" }, geomType: GeomType.Point, }), - "taipei" + "taipei", ); t = new TextAttr({ label_props: ["name:en"], @@ -187,7 +187,7 @@ test("textattr", async () => { props: { "name:en": "from Berga to Taipei" }, geomType: GeomType.Point, }), - "From Berga To Taipei" + "From Berga To Taipei", ); t = new TextAttr({ @@ -199,11 +199,11 @@ test("textattr", async () => { }); assert.equal( t.get(0, { ...emptyFeature, props: { name: "台北", abbr: "TPE" } }), - "TPE" + "TPE", ); assert.equal( t.get(9, { ...emptyFeature, props: { name: "台北", abbr: "TPE" } }), - "台北" + "台北", ); }); @@ -224,7 +224,7 @@ test("arrayattr", async () => { (z, f) => { return [z, z]; }, - [0] + [0], ); assert.equal(n.get(2)[0], 2); assert.equal(n.get(2)[1], 2); diff --git a/test/json_style.test.ts b/test/json_style.test.ts index be881e24..b607df94 100644 --- a/test/json_style.test.ts +++ b/test/json_style.test.ts @@ -96,7 +96,7 @@ test("numberFn constant", async () => { }); test("numberFn function", async () => { - let n = numberFn({ + const n = numberFn({ base: 1, stops: [ [14, 0], @@ -110,7 +110,15 @@ test("numberFn function", async () => { }); test("numberFn interpolate", async () => { - let n = numberFn(["interpolate", ["exponential", 1], ["zoom"], 14, 0, 16, 2]); + const n = numberFn([ + "interpolate", + ["exponential", 1], + ["zoom"], + 14, + 0, + 16, + 2, + ]); assert.equal(n.length, 1); assert.equal(n(15), 0); assert.equal(n(16), 1); @@ -118,7 +126,7 @@ test("numberFn interpolate", async () => { }); test("numberFn properties", async () => { - let n = numberFn(["step", ["get", "scalerank"], 0, 1, 2, 3, 4]); + const n = numberFn(["step", ["get", "scalerank"], 0, 1, 2, 3, 4]); assert.equal(n.length, 2); assert.equal(n(14, { ...emptyFeature, props: { scalerank: 0 } }), 0); assert.equal(n(14, { ...emptyFeature, props: { scalerank: 1 } }), 2); @@ -135,13 +143,13 @@ test("font", async () => { n = getFont( { "text-font": ["Noto"], "text-size": 15 }, - { Noto: { face: "serif" } } + { Noto: { face: "serif" } }, ); assert.equal(n(1), "15px serif"); n = getFont( { "text-font": ["Boto", "Noto"], "text-size": 15 }, - { Noto: { face: "serif" }, Boto: { face: "Comic Sans" } } + { Noto: { face: "serif" }, Boto: { face: "Comic Sans" } }, ); assert.equal(n(1), "15px Comic Sans, serif"); }); @@ -149,18 +157,18 @@ test("font", async () => { test("font weight and style", async () => { let n = getFont( { "text-font": ["Noto"], "text-size": 15 }, - { Noto: { face: "serif", weight: 100 } } + { Noto: { face: "serif", weight: 100 } }, ); assert.equal(n(1), "100 15px serif"); n = getFont( { "text-font": ["Noto"], "text-size": 15 }, - { Noto: { face: "serif", style: "italic" } } + { Noto: { face: "serif", style: "italic" } }, ); assert.equal(n(1), "italic 15px serif"); }); test("font size fn zoom", async () => { - let n = getFont( + const n = getFont( { "text-font": ["Noto"], "text-size": { @@ -171,7 +179,7 @@ test("font size fn zoom", async () => { ], }, }, - {} + {}, ); assert.equal(n(15), "1px sans-serif"); assert.equal(n(16), "2px sans-serif"); @@ -179,23 +187,23 @@ test("font size fn zoom", async () => { }); test("font size fn zoom props", async () => { - let n = getFont( + const n = getFont( { "text-font": ["Noto"], "text-size": ["step", ["get", "scalerank"], 0, 1, 12, 2, 10], }, - {} + {}, ); assert.equal( n(14, { ...emptyFeature, props: { scalerank: 0 } }), - "0px sans-serif" + "0px sans-serif", ); assert.equal( n(14, { ...emptyFeature, props: { scalerank: 1 } }), - "12px sans-serif" + "12px sans-serif", ); assert.equal( n(14, { ...emptyFeature, props: { scalerank: 2 } }), - "10px sans-serif" + "10px sans-serif", ); }); diff --git a/test/labeler.test.ts b/test/labeler.test.ts index b1d6a617..75004612 100644 --- a/test/labeler.test.ts +++ b/test/labeler.test.ts @@ -1,10 +1,10 @@ -import Point from "@mapbox/point-geometry"; -import { covering, Index } from "../src/labeler"; import assert from "assert"; import { test } from "node:test"; +import Point from "@mapbox/point-geometry"; +import { Index, covering } from "../src/labeler"; test("covering", async () => { - let result = covering(3, 1024, { + const result = covering(3, 1024, { minX: 256, minY: 256 * 2, maxX: 256 + 1, @@ -14,7 +14,7 @@ test("covering", async () => { }); test("covering with antimeridian crossing", async () => { - let result = covering(3, 1024, { + const result = covering(3, 1024, { minX: 2000, minY: 256 * 2, maxX: 2050, @@ -27,7 +27,7 @@ test("covering with antimeridian crossing", async () => { }); test("inserting label into index", async () => { - let index = new Index(1024); + const index = new Index(1024); index.insert( { anchor: new Point(100, 100), @@ -35,11 +35,11 @@ test("inserting label into index", async () => { draw: (c) => {}, }, 1, - "abcd" + "abcd", ); - let result = index.searchBbox( + const result = index.searchBbox( { minX: 90, maxX: 110, minY: 90, maxY: 110 }, - Infinity + Infinity, ); assert.equal(result.size, 1); }); @@ -53,11 +53,11 @@ test("inserting label with antimeridian wrapping", async () => { draw: (c) => {}, }, 1, - "abcd" + "abcd", ); let result = index.searchBbox( { minX: 0, maxX: 100, minY: 90, maxY: 110 }, - Infinity + Infinity, ); assert.equal(result.size, 1); @@ -69,17 +69,17 @@ test("inserting label with antimeridian wrapping", async () => { draw: (c) => {}, }, 1, - "abcd" + "abcd", ); result = index.searchBbox( { minX: 1000, maxX: 1024, minY: 90, maxY: 110 }, - Infinity + Infinity, ); assert.equal(result.size, 1); }); test("label with multiple bboxes", async () => { - let index = new Index(1024); + const index = new Index(1024); index.insert( { anchor: new Point(100, 100), @@ -90,17 +90,17 @@ test("label with multiple bboxes", async () => { draw: (c) => {}, }, 1, - "abcd" + "abcd", ); - let result = index.searchBbox( + const result = index.searchBbox( { minX: 90, maxX: 130, minY: 90, maxY: 110 }, - Infinity + Infinity, ); assert.equal(result.size, 1); }); test("label order", async () => { - let index = new Index(1024); + const index = new Index(1024); index.insert( { anchor: new Point(100, 100), @@ -108,11 +108,11 @@ test("label order", async () => { draw: (c) => {}, }, 2, - "abcd" + "abcd", ); let result = index.searchBbox( { minX: 90, maxX: 110, minY: 90, maxY: 110 }, - 1 + 1, ); assert.equal(result.size, 0); result = index.searchBbox({ minX: 90, maxX: 110, minY: 90, maxY: 110 }, 3); @@ -120,7 +120,7 @@ test("label order", async () => { }); test("pruning", async () => { - let index = new Index(1024); + const index = new Index(1024); index.insert( { anchor: new Point(100, 100), @@ -128,7 +128,7 @@ test("pruning", async () => { draw: (c) => {}, }, 1, - "abcd" + "abcd", ); assert.equal(index.tree.all().length, 1); assert.equal(index.has("abcd"), true); @@ -138,7 +138,7 @@ test("pruning", async () => { }); test("tile prefixes", async () => { - let index = new Index(1024); + const index = new Index(1024); assert.equal(index.hasPrefix("my_key"), false); index.insert( { @@ -147,13 +147,13 @@ test("tile prefixes", async () => { draw: (c) => {}, }, 1, - "my_key:123" + "my_key:123", ); assert.equal(index.hasPrefix("my_key"), true); }); test("remove an individual label", async () => { - let index = new Index(1024); + const index = new Index(1024); index.insert( { anchor: new Point(100, 100), @@ -161,11 +161,11 @@ test("remove an individual label", async () => { draw: (c) => {}, }, 1, - "abcd" + "abcd", ); assert.equal(index.tree.all().length, 1); assert.equal(index.current.get("abcd").size, 1); - let the_label = index.tree.all()[0].indexed_label; + const the_label = index.tree.all()[0].indexed_label; index.removeLabel(the_label); assert.equal(index.current.size, 1); assert.equal(index.current.get("abcd").size, 0); @@ -173,8 +173,8 @@ test("remove an individual label", async () => { }); test("basic label deduplication", async () => { - let index = new Index(1024); - let label1 = { + const index = new Index(1024); + const label1 = { anchor: new Point(100, 100), bboxes: [{ minX: 100, minY: 100, maxX: 110, maxY: 110 }], draw: (c) => {}, @@ -183,7 +183,7 @@ test("basic label deduplication", async () => { }; index.insert(label1, 1, "abcd"); - let repeated_label = { + const repeated_label = { anchor: new Point(200, 100), bboxes: [{ minX: 200, minY: 100, maxX: 210, maxY: 110 }], draw: (c) => {}, @@ -193,7 +193,7 @@ test("basic label deduplication", async () => { assert.equal(index.deduplicationCollides(repeated_label), false); - let tooclose_label = { + const tooclose_label = { anchor: new Point(199, 100), bboxes: [{ minX: 199, minY: 100, maxX: 210, maxY: 110 }], draw: (c) => {}, diff --git a/test/symbolizer.test.ts b/test/symbolizer.test.ts index 7aa38bd9..deb4bfc7 100644 --- a/test/symbolizer.test.ts +++ b/test/symbolizer.test.ts @@ -1,6 +1,6 @@ -import { exp, step, linear, cubicBezier } from "../src/symbolizer"; import assert from "assert"; import { test } from "node:test"; +import { cubicBezier, exp, linear, step } from "../src/symbolizer"; test("exp", async () => { let result = exp(1.4, [])(5); diff --git a/test/test_helpers.ts b/test/test_helpers.ts index 5903324e..f4fe4bee 100644 --- a/test/test_helpers.ts +++ b/test/test_helpers.ts @@ -1,4 +1,4 @@ -import { Zxy, TileSource, Feature } from "../src/tilecache"; +import { Feature, TileSource, Zxy } from "../src/tilecache"; export class StubSource implements TileSource { public async get(c: Zxy): Promise> { diff --git a/test/text.test.ts b/test/text.test.ts index 30b19315..6e57a1e4 100644 --- a/test/text.test.ts +++ b/test/text.test.ts @@ -3,26 +3,26 @@ import { test } from "node:test"; import { linebreak } from "../src/text"; test("trivial", async () => { - let lines = linebreak("foo", 15); + const lines = linebreak("foo", 15); assert.deepEqual(lines, ["foo"]); }); test("no break", async () => { - let lines = linebreak("'s-Hertogenbosch", 15); + const lines = linebreak("'s-Hertogenbosch", 15); assert.deepEqual(lines, ["'s-Hertogenbosch"]); }); test("break before", async () => { - let lines = linebreak("Idlewild Airport", 15); + const lines = linebreak("Idlewild Airport", 15); assert.deepEqual(lines, ["Idlewild", "Airport"]); }); test("break after", async () => { - let lines = linebreak("Idlewildgenbosch Airport", 15); + const lines = linebreak("Idlewildgenbosch Airport", 15); assert.deepEqual(lines, ["Idlewildgenbosch", "Airport"]); }); test("multiple breaks", async () => { - let lines = linebreak( + const lines = linebreak( "Idlewildgenbosch Idlewildgenbosch Idlewildgenbosch", - 15 + 15, ); assert.deepEqual(lines, [ "Idlewildgenbosch", @@ -32,9 +32,9 @@ test("multiple breaks", async () => { }); test("very long break", async () => { - let lines = linebreak( + const lines = linebreak( "Dorotheenstädtisch-Friedrichswerderscher und Französischer Friedhof", - 15 + 15, ); assert.deepEqual(lines, [ "Dorotheenstädtisch-Friedrichswerderscher", diff --git a/test/tilecache.test.ts b/test/tilecache.test.ts index 1f94f064..d1017dce 100644 --- a/test/tilecache.test.ts +++ b/test/tilecache.test.ts @@ -17,7 +17,7 @@ test("basic", async () => { test("point to point", async () => { assert.equal( pointMinDistToPoints({ x: 0, y: 0 }, [[{ x: 8, y: 0 }], [{ x: 4, y: 0 }]]), - 4 + 4, ); }); @@ -29,7 +29,7 @@ test("point to line", async () => { { x: 10, y: 0 }, ], ]), - 4 + 4, ); }); @@ -42,7 +42,7 @@ test("is in ring", async () => { { x: 10, y: 10 }, { x: 0, y: 10 }, { x: 0, y: 0 }, - ]) + ]), ); // works for CCW @@ -54,7 +54,7 @@ test("is in ring", async () => { { x: 10, y: 10 }, { x: 10, y: 0 }, { x: 0, y: 0 }, - ]) + ]), ); }); @@ -67,7 +67,7 @@ test("is ccw", async () => { { x: 10, y: 10 }, { x: 0, y: 10 }, { x: 0, y: 0 }, - ]) + ]), ); assert.equal( true, @@ -77,7 +77,7 @@ test("is ccw", async () => { { x: 10, y: 10 }, { x: 10, y: 0 }, { x: 0, y: 0 }, - ]) + ]), ); }); @@ -93,7 +93,7 @@ test("point in polygon", async () => { { x: 0, y: 10 }, { x: 0, y: 0 }, ], - ]) + ]), ); // multiple exterior rings @@ -114,7 +114,7 @@ test("point in polygon", async () => { { x: 20, y: 30 }, { x: 20, y: 20 }, ], - ]) + ]), ); // simple case with holes @@ -135,6 +135,6 @@ test("point in polygon", async () => { { x: 3, y: 7 }, { x: 7, y: 7 }, ], - ]) + ]), ); }); diff --git a/test/view.test.ts b/test/view.test.ts index f5094c9e..aef5476e 100644 --- a/test/view.test.ts +++ b/test/view.test.ts @@ -1,14 +1,14 @@ -import Point from "@mapbox/point-geometry"; import assert from "assert"; import { test } from "node:test"; +import Point from "@mapbox/point-geometry"; import { TileCache } from "../src/tilecache"; -import { View, wrap, sourcesToViews } from "../src/view"; +import { View, sourcesToViews, wrap } from "../src/view"; import { StubSource } from "./test_helpers"; -let cache = new TileCache(new StubSource(), 1024); +const cache = new TileCache(new StubSource(), 1024); test("basic, level diff = 0", async () => { - let view = new View(cache, 3, 0); + const view = new View(cache, 3, 0); let result = view.dataTileForDisplayTile({ z: 3, x: 4, y: 1 }); assert.deepEqual(result.data_tile, { z: 3, x: 4, y: 1 }); assert.equal(result.scale, 1); @@ -23,7 +23,7 @@ test("basic, level diff = 0", async () => { }); test("level diff = 1", async () => { - let view = new View(cache, 3, 1); + const view = new View(cache, 3, 1); let result = view.dataTileForDisplayTile({ z: 3, x: 4, y: 1 }); assert.deepEqual(result.data_tile, { z: 2, x: 2, y: 0 }); assert.equal(result.scale, 1); @@ -43,16 +43,16 @@ test("level diff = 1", async () => { }); test("level diff = 2", async () => { - let view = new View(cache, 3, 2); - let result = view.dataTileForDisplayTile({ z: 6, x: 9, y: 13 }); + const view = new View(cache, 3, 2); + const result = view.dataTileForDisplayTile({ z: 6, x: 9, y: 13 }); assert.deepEqual(result.data_tile, { z: 3, x: 1, y: 1 }); assert.equal(result.scale, 2); assert.deepEqual(result.origin, new Point(256 * 8, 256 * 8)); }); test("get center no level diff", async () => { - let view = new View(cache, 3, 0); - let result = view.dataTilesForBounds(3, { + const view = new View(cache, 3, 0); + const result = view.dataTilesForBounds(3, { minX: 100, minY: 100, maxX: 400, @@ -62,8 +62,8 @@ test("get center no level diff", async () => { }); test("get center level diff = 2", async () => { - let view = new View(cache, 3, 2); - let result = view.dataTilesForBounds(6, { + const view = new View(cache, 3, 2); + const result = view.dataTilesForBounds(6, { minX: 100, minY: 100, maxX: 400, @@ -73,8 +73,8 @@ test("get center level diff = 2", async () => { }); test("wrap tile coordinates", async () => { - let view = new View(cache, 3, 2); - let result = view.dataTilesForBounds(6, { + const view = new View(cache, 3, 2); + const result = view.dataTilesForBounds(6, { minX: -100, minY: 100, maxX: 400, @@ -91,12 +91,14 @@ test("wrap", async () => { }); test("sources to views", async () => { - let v = sourcesToViews({url:"http://example.com/{z}/{x}/{y}.mvt"}); - assert.equal(v.get('').levelDiff,2); - v = sourcesToViews({sources:{ - source1: { - url:"http://example.com/{z}/{x}/{y}.mvt" - } - }}); - assert.equal(v.get('source1').levelDiff,2); + let v = sourcesToViews({ url: "http://example.com/{z}/{x}/{y}.mvt" }); + assert.equal(v.get("").levelDiff, 2); + v = sourcesToViews({ + sources: { + source1: { + url: "http://example.com/{z}/{x}/{y}.mvt", + }, + }, + }); + assert.equal(v.get("source1").levelDiff, 2); }); From 77ee544e42e4e170c2208d8660c6df7f8a055a1e Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Tue, 23 Jan 2024 15:32:17 +0800 Subject: [PATCH 2/7] add biome for linting --- package-lock.json | 228 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 229 insertions(+) diff --git a/package-lock.json b/package-lock.json index 2db48add..35087986 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "rbush": "^3.0.1" }, "devDependencies": { + "@biomejs/biome": "^1.5.3", "@types/mapbox__point-geometry": "^0.1.2", "@types/mapbox__vector-tile": "^1.3.0", "@types/node": "^16.18.74", @@ -34,6 +35,161 @@ "typescript": "^4.3.5" } }, + "node_modules/@biomejs/biome": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.5.3.tgz", + "integrity": "sha512-yvZCa/g3akwTaAQ7PCwPWDCkZs3Qa5ONg/fgOUT9e6wAWsPftCjLQFPXBeGxPK30yZSSpgEmRCfpGTmVbUjGgg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.5.3", + "@biomejs/cli-darwin-x64": "1.5.3", + "@biomejs/cli-linux-arm64": "1.5.3", + "@biomejs/cli-linux-arm64-musl": "1.5.3", + "@biomejs/cli-linux-x64": "1.5.3", + "@biomejs/cli-linux-x64-musl": "1.5.3", + "@biomejs/cli-win32-arm64": "1.5.3", + "@biomejs/cli-win32-x64": "1.5.3" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.5.3.tgz", + "integrity": "sha512-ImU7mh1HghEDyqNmxEZBoMPr8SxekkZuYcs+gynKlNW+TALQs7swkERiBLkG9NR0K1B3/2uVzlvYowXrmlW8hw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.5.3.tgz", + "integrity": "sha512-vCdASqYnlpq/swErH7FD6nrFz0czFtK4k/iLgj0/+VmZVjineFPgevOb+Sr9vz0tk0GfdQO60bSpI74zU8M9Dw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.5.3.tgz", + "integrity": "sha512-cupBQv0sNF1OKqBfx7EDWMSsKwRrBUZfjXawT4s6hKV6ALq7p0QzWlxr/sDmbKMLOaLQtw2Qgu/77N9rm+f9Rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.3.tgz", + "integrity": "sha512-DYuMizUYUBYfS0IHGjDrOP1RGipqWfMGEvNEJ398zdtmCKLXaUvTimiox5dvx4X15mBK5M2m8wgWUgOP1giUpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.5.3.tgz", + "integrity": "sha512-YQrSArQvcv4FYsk7Q91Yv4uuu5F8hJyORVcv3zsjCLGkjIjx2RhjYLpTL733SNL7v33GmOlZY0eFR1ko38tuUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.3.tgz", + "integrity": "sha512-UUHiAnlDqr2Y/LpvshBFhUYMWkl2/Jn+bi3U6jKuav0qWbbBKU/ByHgR4+NBxpKBYoCtWxhnmatfH1bpPIuZMw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.5.3.tgz", + "integrity": "sha512-HxatYH7vf/kX9nrD+pDYuV2GI9GV8EFo6cfKkahAecTuZLPxryHx1WEfJthp5eNsE0+09STGkKIKjirP0ufaZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.*" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.5.3.tgz", + "integrity": "sha512-fMvbSouZEASU7mZH8SIJSANDm5OqsjgtVXlbUqxwed6BP7uuHRSs396Aqwh2+VoW8fwTpp6ybIUoC9FrzB0kyA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.*" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.15.18", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", @@ -651,6 +807,78 @@ } }, "dependencies": { + "@biomejs/biome": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.5.3.tgz", + "integrity": "sha512-yvZCa/g3akwTaAQ7PCwPWDCkZs3Qa5ONg/fgOUT9e6wAWsPftCjLQFPXBeGxPK30yZSSpgEmRCfpGTmVbUjGgg==", + "dev": true, + "requires": { + "@biomejs/cli-darwin-arm64": "1.5.3", + "@biomejs/cli-darwin-x64": "1.5.3", + "@biomejs/cli-linux-arm64": "1.5.3", + "@biomejs/cli-linux-arm64-musl": "1.5.3", + "@biomejs/cli-linux-x64": "1.5.3", + "@biomejs/cli-linux-x64-musl": "1.5.3", + "@biomejs/cli-win32-arm64": "1.5.3", + "@biomejs/cli-win32-x64": "1.5.3" + } + }, + "@biomejs/cli-darwin-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.5.3.tgz", + "integrity": "sha512-ImU7mh1HghEDyqNmxEZBoMPr8SxekkZuYcs+gynKlNW+TALQs7swkERiBLkG9NR0K1B3/2uVzlvYowXrmlW8hw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-darwin-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.5.3.tgz", + "integrity": "sha512-vCdASqYnlpq/swErH7FD6nrFz0czFtK4k/iLgj0/+VmZVjineFPgevOb+Sr9vz0tk0GfdQO60bSpI74zU8M9Dw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.5.3.tgz", + "integrity": "sha512-cupBQv0sNF1OKqBfx7EDWMSsKwRrBUZfjXawT4s6hKV6ALq7p0QzWlxr/sDmbKMLOaLQtw2Qgu/77N9rm+f9Rg==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-arm64-musl": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.5.3.tgz", + "integrity": "sha512-DYuMizUYUBYfS0IHGjDrOP1RGipqWfMGEvNEJ398zdtmCKLXaUvTimiox5dvx4X15mBK5M2m8wgWUgOP1giUpQ==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.5.3.tgz", + "integrity": "sha512-YQrSArQvcv4FYsk7Q91Yv4uuu5F8hJyORVcv3zsjCLGkjIjx2RhjYLpTL733SNL7v33GmOlZY0eFR1ko38tuUw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-linux-x64-musl": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.5.3.tgz", + "integrity": "sha512-UUHiAnlDqr2Y/LpvshBFhUYMWkl2/Jn+bi3U6jKuav0qWbbBKU/ByHgR4+NBxpKBYoCtWxhnmatfH1bpPIuZMw==", + "dev": true, + "optional": true + }, + "@biomejs/cli-win32-arm64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.5.3.tgz", + "integrity": "sha512-HxatYH7vf/kX9nrD+pDYuV2GI9GV8EFo6cfKkahAecTuZLPxryHx1WEfJthp5eNsE0+09STGkKIKjirP0ufaZA==", + "dev": true, + "optional": true + }, + "@biomejs/cli-win32-x64": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.5.3.tgz", + "integrity": "sha512-fMvbSouZEASU7mZH8SIJSANDm5OqsjgtVXlbUqxwed6BP7uuHRSs396Aqwh2+VoW8fwTpp6ybIUoC9FrzB0kyA==", + "dev": true, + "optional": true + }, "@esbuild/android-arm": { "version": "0.15.18", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", diff --git a/package.json b/package.json index 84a65df0..7492174d 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "source": "src/index.ts", "types": "dist/index.d.ts", "devDependencies": { + "@biomejs/biome": "^1.5.3", "@types/mapbox__point-geometry": "^0.1.2", "@types/mapbox__vector-tile": "^1.3.0", "@types/node": "^16.18.74", From 1547c137a3416898778ffc7f4fe96e39da37d653 Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Tue, 23 Jan 2024 16:07:20 +0800 Subject: [PATCH 3/7] linting changes for code correctness and maintainability [#112] --- src/attribute.ts | 20 +++++------ src/compat/json_style.ts | 48 ++++++++++++------------- src/default_style/style.ts | 44 +++++++++++------------ src/extra_styles/toner.ts | 4 +-- src/frontends/leaflet.ts | 20 +++++------ src/frontends/static.ts | 2 +- src/labeler.ts | 28 +++++++-------- src/line.ts | 22 ++++++------ src/symbolizer.ts | 72 +++++++++++++++++++------------------- src/task.ts | 4 +-- src/text.ts | 4 +-- src/tilecache.ts | 44 +++++++++++------------ src/view.ts | 20 +++++------ src/xray.ts | 14 ++++---- test/attribute.test.ts | 10 +++--- 15 files changed, 178 insertions(+), 178 deletions(-) diff --git a/src/attribute.ts b/src/attribute.ts index 96761f2c..e846e4da 100644 --- a/src/attribute.ts +++ b/src/attribute.ts @@ -8,7 +8,7 @@ export class StringAttr { constructor(c: AttrOption | undefined, defaultValue: T) { this.str = c ?? defaultValue; - this.per_feature = typeof this.str == "function" && this.str.length == 2; + this.per_feature = typeof this.str === "function" && this.str.length === 2; } public get(z: number, f?: Feature): T { @@ -27,11 +27,11 @@ export class NumberAttr { constructor(c: AttrOption | undefined, defaultValue = 1) { this.value = c ?? defaultValue; this.per_feature = - typeof this.value == "function" && this.value.length == 2; + typeof this.value === "function" && this.value.length === 2; } public get(z: number, f?: Feature): number { - if (typeof this.value == "function") { + if (typeof this.value === "function") { return this.value(z, f); } else { return this.value; @@ -57,7 +57,7 @@ export class TextAttr { let retval: string | undefined; let label_props: string[]; - if (typeof this.label_props == "function") { + if (typeof this.label_props === "function") { label_props = this.label_props(z, f); } else { label_props = this.label_props; @@ -124,7 +124,7 @@ export class FontAttr { return this.font; } } else { - var style = ""; + let style = ""; if (this.style) { if (typeof this.style === "function") { style = this.style(z, f) + " "; @@ -133,7 +133,7 @@ export class FontAttr { } } - var weight = ""; + let weight = ""; if (this.weight) { if (typeof this.weight === "function") { weight = this.weight(z, f) + " "; @@ -142,14 +142,14 @@ export class FontAttr { } } - var size; + let size; if (typeof this.size === "function") { size = this.size(z, f); } else { size = this.size; } - var family; + let family; if (typeof this.family === "function") { family = this.family(z, f); } else { @@ -168,11 +168,11 @@ export class ArrayAttr { constructor(c: AttrOption, defaultValue: T[] = []) { this.value = c ?? defaultValue; this.per_feature = - typeof this.value == "function" && this.value.length == 2; + typeof this.value === "function" && this.value.length === 2; } public get(z: number, f?: Feature): T[] { - if (typeof this.value == "function") { + if (typeof this.value === "function") { return this.value(z, f); } else { return this.value; diff --git a/src/compat/json_style.ts b/src/compat/json_style.ts index eccac21c..5564aae4 100644 --- a/src/compat/json_style.ts +++ b/src/compat/json_style.ts @@ -17,11 +17,11 @@ export function filterFn(arr: any[]): Filter { // hack around "$type" if (arr.includes("$type")) { return (z) => true; - } else if (arr[0] == "==") { + } else if (arr[0] === "==") { return (z, f) => f.props[arr[1]] === arr[2]; - } else if (arr[0] == "!=") { + } else if (arr[0] === "!=") { return (z, f) => f.props[arr[1]] !== arr[2]; - } else if (arr[0] == "!") { + } else if (arr[0] === "!") { const sub = filterFn(arr[1]); return (z, f) => !sub(z, f); } else if (arr[0] === "<") { @@ -64,13 +64,13 @@ export function numberFn(obj: any): (z: number, f?: Feature) => number { return exp(obj.base, obj.stops)(z - 1); }; } else if ( - obj[0] == "interpolate" && - obj[1][0] == "exponential" && - obj[2] == "zoom" + obj[0] === "interpolate" && + obj[1][0] === "exponential" && + obj[2] === "zoom" ) { const slice = obj.slice(3); const stops: number[][] = []; - for (var i = 0; i < slice.length; i += 2) { + for (let i = 0; i < slice.length; i += 2) { stops.push([slice[i], slice[i + 1]]); } return (z: number) => { @@ -83,7 +83,7 @@ export function numberFn(obj: any): (z: number, f?: Feature) => number { const val = f?.props[prop]; if (typeof val === "number") { if (val < slice[1]) return slice[0]; - for (i = 1; i < slice.length; i += 2) { + for (let i = 1; i < slice.length; i += 2) { if (val <= slice[i]) return slice[i + 1]; } } @@ -111,9 +111,9 @@ export function widthFn(width_obj: any, gap_obj: any) { const w = numberOrFn(width_obj, 1); const g = numberOrFn(gap_obj); return (z: number, f?: Feature) => { - const tmp = typeof w == "number" ? w : w(z, f); + const tmp = typeof w === "number" ? w : w(z, f); if (g) { - return tmp + (typeof g == "number" ? g : g(z, f)); + return tmp + (typeof g === "number" ? g : g(z, f)); } return tmp; }; @@ -136,10 +136,10 @@ export function getFont(obj: any, fontsubmap: any) { const text_size = obj["text-size"]; // for fallbacks, use the weight and style of the first font - var weight = ""; + let weight = ""; if (fontfaces.length && fontfaces[0].weight) weight = fontfaces[0].weight + " "; - var style = ""; + let style = ""; if (fontfaces.length && fontfaces[0].style) style = fontfaces[0].style + " "; if (typeof text_size == "number") { @@ -148,7 +148,7 @@ export function getFont(obj: any, fontsubmap: any) { .map((f) => f.face) .join(", ")}`; } else if (text_size.stops) { - var base = 1.4; + let base = 1.4; if (text_size.base) base = text_size.base; else text_size.base = base; const t = numberFn(text_size); @@ -157,7 +157,7 @@ export function getFont(obj: any, fontsubmap: any) { .map((f) => f.face) .join(", ")}`; }; - } else if (text_size[0] == "step") { + } else if (text_size[0] === "step") { const t = numberFn(text_size); return (z: number, f?: Feature) => { return `${style}${weight}${t(z, f)}px ${fontfaces @@ -175,10 +175,10 @@ export function json_style(obj: any, fontsubmap: Map) { const label_rules = []; const refs = new Map(); - for (var layer of obj.layers) { + for (const layer of obj.layers) { refs.set(layer.id, layer); - if (layer.layout && layer.layout.visibility == "none") { + if (layer.layout && layer.layout.visibility === "none") { continue; } @@ -191,15 +191,15 @@ export function json_style(obj: any, fontsubmap: Map) { } const sourceLayer = layer["source-layer"]; - var symbolizer; + let symbolizer; - var filter = undefined; + let filter = undefined; if (layer.filter) { filter = filterFn(layer.filter); } // ignore background-color? - if (layer.type == "fill") { + if (layer.type === "fill") { paint_rules.push({ dataLayer: layer["source-layer"], filter: filter, @@ -208,7 +208,7 @@ export function json_style(obj: any, fontsubmap: Map) { opacity: layer.paint["fill-opacity"], }), }); - } else if (layer.type == "fill-extrusion") { + } else if (layer.type === "fill-extrusion") { // simulate fill-extrusion with plain fill paint_rules.push({ dataLayer: layer["source-layer"], @@ -218,7 +218,7 @@ export function json_style(obj: any, fontsubmap: Map) { opacity: layer.paint["fill-extrusion-opacity"], }), }); - } else if (layer.type == "line") { + } else if (layer.type === "line") { // simulate gap-width if (layer.paint["line-dasharray"]) { paint_rules.push({ @@ -246,8 +246,8 @@ export function json_style(obj: any, fontsubmap: Map) { }), }); } - } else if (layer.type == "symbol") { - if (layer.layout["symbol-placement"] == "line") { + } else if (layer.type === "symbol") { + if (layer.layout["symbol-placement"] === "line") { label_rules.push({ dataLayer: layer["source-layer"], filter: filter, @@ -278,7 +278,7 @@ export function json_style(obj: any, fontsubmap: Map) { }), }); } - } else if (layer.type == "circle") { + } else if (layer.type === "circle") { paint_rules.push({ dataLayer: layer["source-layer"], filter: filter, diff --git a/src/default_style/style.ts b/src/default_style/style.ts index b55c1a69..fba2df8f 100644 --- a/src/default_style/style.ts +++ b/src/default_style/style.ts @@ -80,7 +80,7 @@ export const paintRules = ( fill: params.glacier, }), filter: (z, f) => { - return f.props.natural == "glacier"; + return f.props.natural === "glacier"; }, }, { @@ -90,7 +90,7 @@ export const paintRules = ( }), filter: (z, f) => { return ( - f.props.landuse == "residential" || f.props.place == "neighbourhood" + f.props.landuse === "residential" || f.props.place === "neighbourhood" ); }, }, @@ -100,7 +100,7 @@ export const paintRules = ( fill: params.hospital, }), filter: (z, f) => { - return f.props.amenity == "hospital"; + return f.props.amenity === "hospital"; }, }, { @@ -109,7 +109,7 @@ export const paintRules = ( fill: params.cemetery, }), filter: (z, f) => { - return f.props.landuse == "cemetery"; + return f.props.landuse === "cemetery"; }, }, { @@ -119,10 +119,10 @@ export const paintRules = ( }), filter: (z, f) => { return ( - f.props.amenity == "school" || - f.props.amenity == "kindergarten" || - f.props.amenity == "university" || - f.props.amenity == "college" + f.props.amenity === "school" || + f.props.amenity === "kindergarten" || + f.props.amenity === "university" || + f.props.amenity === "college" ); }, }, @@ -132,7 +132,7 @@ export const paintRules = ( fill: params.industrial, }), filter: (z, f) => { - return f.props.landuse == "industrial"; + return f.props.landuse === "industrial"; }, }, { @@ -141,7 +141,7 @@ export const paintRules = ( fill: params.wood, }), filter: (z, f) => { - return f.props.natural == "wood"; + return f.props.natural === "wood"; }, }, { @@ -150,7 +150,7 @@ export const paintRules = ( fill: params.grass, }), filter: (z, f) => { - return f.props.landuse == "grass"; + return f.props.landuse === "grass"; }, }, { @@ -159,7 +159,7 @@ export const paintRules = ( fill: params.park, }), filter: (z, f) => { - return f.props.leisure == "park"; + return f.props.leisure === "park"; }, }, { @@ -174,7 +174,7 @@ export const paintRules = ( fill: params.sand, }), filter: (z, f) => { - return f.props.natural == "sand"; + return f.props.natural === "sand"; }, }, { @@ -195,7 +195,7 @@ export const paintRules = ( ]), }), filter: (z, f) => { - return f.props["pmap:kind"] == "highway"; + return f.props["pmap:kind"] === "highway"; }, }, { @@ -210,7 +210,7 @@ export const paintRules = ( ]), }), filter: (z, f) => { - return f.props["pmap:kind"] == "major_road"; + return f.props["pmap:kind"] === "major_road"; }, }, { @@ -224,7 +224,7 @@ export const paintRules = ( ]), }), filter: (z, f) => { - return f.props["pmap:kind"] == "medium_road"; + return f.props["pmap:kind"] === "medium_road"; }, }, { @@ -238,7 +238,7 @@ export const paintRules = ( ]), }), filter: (z, f) => { - return f.props["pmap:kind"] == "minor_road"; + return f.props["pmap:kind"] === "minor_road"; }, }, { @@ -252,7 +252,7 @@ export const paintRules = ( ]), }), filter: (z, f) => { - return f.props["pmap:kind"] == "minor_road"; + return f.props["pmap:kind"] === "minor_road"; }, }, { @@ -266,7 +266,7 @@ export const paintRules = ( ]), }), filter: (z, f) => { - return f.props["pmap:kind"] == "medium_road"; + return f.props["pmap:kind"] === "medium_road"; }, }, { @@ -281,7 +281,7 @@ export const paintRules = ( ]), }), filter: (z, f) => { - return f.props["pmap:kind"] == "major_road"; + return f.props["pmap:kind"] === "major_road"; }, }, { @@ -296,7 +296,7 @@ export const paintRules = ( ]), }), filter: (z, f) => { - return f.props["pmap:kind"] == "highway"; + return f.props["pmap:kind"] === "highway"; }, }, { @@ -323,7 +323,7 @@ export const labelRules = ( language2?: string[], ): LabelRule[] => { if (shade) params = doShading(params, shade); - var nametags = ["name"]; + let nametags = ["name"]; if (language1) nametags = language1; const languageStack = (symbolizer: LabelSymbolizer, fill: string) => { diff --git a/src/extra_styles/toner.ts b/src/extra_styles/toner.ts index fb63524a..a62d6141 100644 --- a/src/extra_styles/toner.ts +++ b/src/extra_styles/toner.ts @@ -32,7 +32,7 @@ import { Font, Sheet } from "../task"; const Toner = (variant: string) => { const halftone = createPattern(4, 4, (c) => { - var ctx = c.getContext("2d"); + const ctx = c.getContext("2d"); if (ctx) { ctx.beginPath(); ctx.rect(0, 0, 1, 1); @@ -42,7 +42,7 @@ const Toner = (variant: string) => { } }); - var background = "black"; + let background = "black"; if (variant === "lite") { background = "#d9d9d9"; } diff --git a/src/frontends/leaflet.ts b/src/frontends/leaflet.ts index fa0c991e..cd35d317 100644 --- a/src/frontends/leaflet.ts +++ b/src/frontends/leaflet.ts @@ -1,4 +1,4 @@ -declare var L: any; +declare const L: any; import Point from "@mapbox/point-geometry"; @@ -160,17 +160,17 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { } } - if (element.key != key) return; + if (element.key !== key) return; if (this.lastRequestedZ !== coords.z) return; await Promise.all(this.tasks.map(reflect)); - if (element.key != key) return; + if (element.key !== key) return; if (this.lastRequestedZ !== coords.z) return; const layout_time = this.labelers.add(coords.z, prepared_tilemap); - if (element.key != key) return; + if (element.key !== key) return; if (this.lastRequestedZ !== coords.z) return; const label_data = this.labelers.getIndex(coords.z); @@ -185,7 +185,7 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { await timer(priority); - if (element.key != key) return; + if (element.key !== key) return; if (this.lastRequestedZ !== coords.z) return; const BUF = 16; @@ -210,7 +210,7 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { ctx.restore(); } - var painting_time = 0; + let painting_time = 0; let paint_rules = this.paint_rules; if (this.xray) { @@ -338,7 +338,7 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { public queryFeatures(lng: number, lat: number) { const featuresBySourceName = new Map(); - for (var [sourceName, view] of this.views) { + for (const [sourceName, view] of this.views) { featuresBySourceName.set( sourceName, view.queryFeatures(lng, lat, this._map.getZoom()), @@ -355,11 +355,11 @@ const leafletLayer = (options: LeafletLayerOptions = {}): any => { wrapped.lng, wrapped.lat, ); - var content = ""; + let content = ""; let firstRow = true; - for (var [sourceName, results] of resultsBySourceName) { - for (var result of results) { + for (const [sourceName, results] of resultsBySourceName) { + for (const result of results) { if (this.xray && this.xray !== true) { if ( !( diff --git a/src/frontends/static.ts b/src/frontends/static.ts index b9e54d38..55867de5 100644 --- a/src/frontends/static.ts +++ b/src/frontends/static.ts @@ -230,7 +230,7 @@ export class Static { const dpr = window.devicePixelRatio; const width = canvas.clientWidth; const height = canvas.clientHeight; - if (!(canvas.width == width * dpr && canvas.height == height * dpr)) { + if (!(canvas.width === width * dpr && canvas.height === height * dpr)) { canvas.width = width * dpr; canvas.height = height * dpr; } diff --git a/src/labeler.ts b/src/labeler.ts index d744e01c..020bec4e 100644 --- a/src/labeler.ts +++ b/src/labeler.ts @@ -197,10 +197,10 @@ export class Index { } entry.add(indexed_label); - var wrapsLeft = false; - var wrapsRight = false; + let wrapsLeft = false; + let wrapsRight = false; for (const bbox of label.bboxes) { - var b: any = bbox; + const b: any = bbox; b.indexed_label = indexed_label; this.tree.insert(b); @@ -209,9 +209,9 @@ export class Index { } if (wrapsLeft || wrapsRight) { - var shift = wrapsLeft ? this.dim : -this.dim; + const shift = wrapsLeft ? this.dim : -this.dim; - var new_bboxes = []; + const new_bboxes = []; for (const bbox of label.bboxes) { new_bboxes.push({ minX: bbox.minX + shift, @@ -230,7 +230,7 @@ export class Index { const entry = this.current.get(tileKey); if (entry) entry.add(duplicate_label); for (const bbox of new_bboxes) { - var b: any = bbox; + const b: any = bbox; b.indexed_label = duplicate_label; this.tree.insert(b); } @@ -243,7 +243,7 @@ export class Index { let max_dist = 0; let keys_for_ds = 0; - for (var existing_key of this.current.keys()) { + for (const existing_key of this.current.keys()) { const existing = existing_key.split(":"); if (existing[3] === added[3]) { keys_for_ds++; @@ -285,7 +285,7 @@ export class Index { public removeLabel(labelToRemove: IndexedLabel): void { const entries_to_delete = []; for (const entry of this.tree.all()) { - if (labelToRemove == entry.indexed_label) { + if (labelToRemove === entry.indexed_label) { entries_to_delete.push(entry); } } @@ -335,7 +335,7 @@ export class Labeler { const tiles_invalidated = new Set(); for (const [order, rule] of this.labelRules.entries()) { - if (rule.visible == false) continue; + if (rule.visible === false) continue; if (rule.minzoom && this.z < rule.minzoom) continue; if (rule.maxzoom && this.z > rule.maxzoom) continue; @@ -378,7 +378,7 @@ export class Labeler { if (!labels) continue; for (const label of labels) { - var label_added = false; + let label_added = false; if ( label.deduplicationKey && this.index.deduplicationCollides(label) @@ -432,7 +432,7 @@ export class Labeler { } } - for (var key of keys_adding) { + for (const key of keys_adding) { this.index.pruneOrNoop(key); } @@ -450,14 +450,14 @@ export class Labeler { ) { const touched = covering(this.z, dim, bbox); for (const s of touched) { - if (s.key != key && this.index.hasPrefix(s.key)) { + if (s.key !== key && this.index.hasPrefix(s.key)) { tiles_invalidated.add(s.display); } } } public add(prepared_tilemap: Map): number { - var all_added = true; + let all_added = true; for (const [k, prepared_tiles] of prepared_tilemap) { for (const prepared_tile of prepared_tiles) { if (!this.index.has(toIndex(prepared_tile.data_tile) + ":" + k)) @@ -495,7 +495,7 @@ export class Labelers { } public add(z: number, prepared_tilemap: Map): number { - var labeler = this.labelers.get(z); + let labeler = this.labelers.get(z); if (labeler) { return labeler.add(prepared_tilemap); } else { diff --git a/src/line.ts b/src/line.ts index 1f5feac7..f7a56429 100644 --- a/src/line.ts +++ b/src/line.ts @@ -14,22 +14,22 @@ const linelabel = ( max_angle_delta: number, targetLen: number, ): LabelableSegment[] => { - var chunks = []; - var a, + const chunks = []; + let a, b, c, i = 0, n = 0, d = 0; - var abmag = 0, + let abmag = 0, bcmag = 0; - var abx = 0, + let abx = 0, aby = 0; - var bcx = 0, + let bcx = 0, bcy = 0; - var dt = 0; - var i_start = 0; - var d_start = 0; + let dt = 0; + let i_start = 0; + let d_start = 0; if (pts.length < 2) return []; if (pts.length === 2) { @@ -106,7 +106,7 @@ export function simpleLabel( const candidates = []; - var lastLabeledDistance = -Infinity; + const lastLabeledDistance = -Infinity; for (const ls of mls) { const segments = linelabel(ls, Math.PI / 45, minimum); // 4 degrees, close to a straight line @@ -125,7 +125,7 @@ export function simpleLabel( // offset from the start by cellSize to allow streets that meet at right angles // to both be labeled. for ( - var i = cellSize; + let i = cellSize; i < segment.length - minimum; i += repeatDistance ) { @@ -150,7 +150,7 @@ export function lineCells(a: Point, b: Point, length: number, spacing: number) { const retval = []; // starting from the anchor, generate square cells, // guaranteeing to cover the endpoint - for (var i = 0; i < length + spacing; i += 2 * spacing) { + for (let i = 0; i < length + spacing; i += 2 * spacing) { const factor = (i * 1) / dist; retval.push({ x: a.x + factor * dx, y: a.y + factor * dy }); } diff --git a/src/symbolizer.ts b/src/symbolizer.ts index c921c166..a62d58a7 100644 --- a/src/symbolizer.ts +++ b/src/symbolizer.ts @@ -126,11 +126,11 @@ export class PolygonSymbolizer implements PaintSymbolizer { z: number, f: Feature, ) { - var do_stroke = false; + let do_stroke = false; if (this.per_feature) { ctx.globalAlpha = this.opacity.get(z, f); ctx.fillStyle = this.fill.get(z, f); - var width = this.width.get(z, f); + const width = this.width.get(z, f); if (width) { do_stroke = true; ctx.strokeStyle = this.stroke.get(z, f); @@ -145,17 +145,17 @@ export class PolygonSymbolizer implements PaintSymbolizer { } }; - var vertices_in_path = 0; + let vertices_in_path = 0; ctx.beginPath(); - for (var poly of geom) { + for (const poly of geom) { if (vertices_in_path + poly.length > MAX_VERTICES_PER_DRAW_CALL) { drawPath(); vertices_in_path = 0; ctx.beginPath(); } - for (var p = 0; p < poly.length; p++) { + for (let p = 0; p < poly.length; p++) { const pt = poly[p]; - if (p == 0) ctx.moveTo(pt.x, pt.y); + if (p === 0) ctx.moveTo(pt.x, pt.y); else ctx.lineTo(pt.x, pt.y); } vertices_in_path += poly.length; @@ -342,17 +342,17 @@ export class LineSymbolizer implements PaintSymbolizer { } }; - var vertices_in_path = 0; + let vertices_in_path = 0; ctx.beginPath(); - for (var ls of geom) { + for (const ls of geom) { if (vertices_in_path + ls.length > MAX_VERTICES_PER_DRAW_CALL) { strokePath(); vertices_in_path = 0; ctx.beginPath(); } - for (var p = 0; p < ls.length; p++) { + for (let p = 0; p < ls.length; p++) { const pt = ls[p]; - if (p == 0) ctx.moveTo(pt.x, pt.y); + if (p === 0) ctx.moveTo(pt.x, pt.y); else ctx.lineTo(pt.x, pt.y); } vertices_in_path += ls.length; @@ -540,9 +540,9 @@ export class FlexSymbolizer implements LabelSymbolizer { } public place(layout: Layout, geom: Point[][], feature: Feature) { - var labels = this.list[0].place(layout, geom, feature); + let labels = this.list[0].place(layout, geom, feature); if (!labels) return undefined; - var label = labels[0]; + let label = labels[0]; const anchor = label.anchor; let bbox = label.bboxes[0]; const height = bbox.maxY - bbox.minY; @@ -590,9 +590,9 @@ export class GroupSymbolizer implements LabelSymbolizer { public place(layout: Layout, geom: Point[][], feature: Feature) { const first = this.list[0]; if (!first) return undefined; - var labels = first.place(layout, geom, feature); + let labels = first.place(layout, geom, feature); if (!labels) return undefined; - var label = labels[0]; + let label = labels[0]; const anchor = label.anchor; let bbox = label.bboxes[0]; const draws = [label.draw]; @@ -622,7 +622,7 @@ export class CenteredSymbolizer implements LabelSymbolizer { public place(layout: Layout, geom: Point[][], feature: Feature) { const a = geom[0][0]; const placed = this.symbolizer.place(layout, [[new Point(0, 0)]], feature); - if (!placed || placed.length == 0) return undefined; + if (!placed || placed.length === 0) return undefined; const first_label = placed[0]; const bbox = first_label.bboxes[0]; const width = bbox.maxX - bbox.minX; @@ -654,10 +654,10 @@ export class Padding implements LabelSymbolizer { public place(layout: Layout, geom: Point[][], feature: Feature) { const placed = this.symbolizer.place(layout, geom, feature); - if (!placed || placed.length == 0) return undefined; + if (!placed || placed.length === 0) return undefined; const padding = this.padding.get(layout.zoom, feature); - for (var label of placed) { - for (var bbox of label.bboxes) { + for (const label of placed) { + for (const bbox of label.bboxes) { bbox.minX -= padding; bbox.minY -= padding; bbox.maxX += padding; @@ -717,8 +717,8 @@ export class TextSymbolizer implements LabelSymbolizer { property, this.maxLineCodeUnits.get(layout.zoom, feature), ); - var longestLine = ""; - var longestLineLen = 0; + let longestLine = ""; + let longestLineLen = 0; for (const line of lines) { if (line.length > longestLineLen) { longestLineLen = line.length; @@ -750,17 +750,17 @@ export class TextSymbolizer implements LabelSymbolizer { ctx.fillStyle = this.fill.get(layout.zoom, feature); const textStrokeWidth = this.width.get(layout.zoom, feature); - var y = 0; + let y = 0; for (const line of lines) { - var startX = 0; + let startX = 0; if ( - this.justify == Justify.Center || - (extra && extra.justify == Justify.Center) + this.justify === Justify.Center || + (extra && extra.justify === Justify.Center) ) { startX = (width - ctx.measureText(line).width) / 2; } else if ( - this.justify == Justify.Right || - (extra && extra.justify == Justify.Right) + this.justify === Justify.Right || + (extra && extra.justify === Justify.Right) ) { startX = width - ctx.measureText(line).width; } @@ -768,8 +768,8 @@ export class TextSymbolizer implements LabelSymbolizer { ctx.lineWidth = textStrokeWidth * 2; // centered stroke ctx.strokeStyle = this.stroke.get(layout.zoom, feature); if (letterSpacing > 0) { - var xPos = startX; - for (var letter of line) { + let xPos = startX; + for (const letter of line) { ctx.strokeText(letter, xPos, y); xPos += ctx.measureText(letter).width + letterSpacing; } @@ -778,8 +778,8 @@ export class TextSymbolizer implements LabelSymbolizer { } } if (letterSpacing > 0) { - var xPos = startX; - for (var letter of line) { + let xPos = startX; + for (const letter of line) { ctx.fillText(letter, xPos, y); xPos += ctx.measureText(letter).width + letterSpacing; } @@ -859,7 +859,7 @@ export class OffsetSymbolizer implements LabelSymbolizer { if (feature.geomType !== GeomType.Point) return undefined; const anchor = geom[0][0]; const placed = this.symbolizer.place(layout, [[new Point(0, 0)]], feature); - if (!placed || placed.length == 0) return undefined; + if (!placed || placed.length === 0) return undefined; const first_label = placed[0]; const fb = first_label.bboxes[0]; @@ -891,8 +891,8 @@ export class OffsetSymbolizer implements LabelSymbolizer { }; }; - var origin = new Point(offsetX, offsetY); - var justify: Justify; + let origin = new Point(offsetX, offsetY); + let justify: Justify; const draw = (ctx: CanvasRenderingContext2D) => { ctx.translate(origin.x, origin.y); first_label.draw(ctx, { justify: justify }); @@ -1043,7 +1043,7 @@ export class LineLabelSymbolizer implements LabelSymbolizer { const height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent; - var repeatDistance = this.repeatDistance.get(layout.zoom, feature); + let repeatDistance = this.repeatDistance.get(layout.zoom, feature); if (layout.overzoom > 4) repeatDistance *= 1 << (layout.overzoom - 4); const cell_size = height * 2; @@ -1054,7 +1054,7 @@ export class LineLabelSymbolizer implements LabelSymbolizer { repeatDistance, cell_size, ); - if (label_candidates.length == 0) return undefined; + if (label_candidates.length === 0) return undefined; const labels = []; for (const candidate of label_candidates) { @@ -1133,7 +1133,7 @@ export class PolygonLabelSymbolizer implements LabelSymbolizer { if (area < 20000) return undefined; const placed = this.symbolizer.place(layout, [[new Point(0, 0)]], feature); - if (!placed || placed.length == 0) return undefined; + if (!placed || placed.length === 0) return undefined; const first_label = placed[0]; const fb = first_label.bboxes[0]; diff --git a/src/task.ts b/src/task.ts index 79acbfbb..8287e4c4 100644 --- a/src/task.ts +++ b/src/task.ts @@ -80,8 +80,8 @@ export class Sheet { const serializer = new XMLSerializer(); for (const ps of icons) { - var svg64 = btoa(serializer.serializeToString(ps)); - var image64 = "data:image/svg+xml;base64," + svg64; + const svg64 = btoa(serializer.serializeToString(ps)); + const image64 = "data:image/svg+xml;base64," + svg64; const img = await mkimg(image64); boxes.push({ w: img.width * scale, diff --git a/src/text.ts b/src/text.ts index 4c7cff01..0d200c34 100644 --- a/src/text.ts +++ b/src/text.ts @@ -4,13 +4,13 @@ export function linebreak(str: string, maxUnits: number): string[] { const endIndex = maxUnits - 1; const space_before = str.lastIndexOf(" ", endIndex); const space_after = str.indexOf(" ", endIndex); - if (space_before == -1 && space_after == -1) { + if (space_before === -1 && space_after === -1) { return [str]; } let first: string; let after: string; if ( - space_after == -1 || + space_after === -1 || (space_before >= 0 && endIndex - space_before < space_after - endIndex) ) { first = str.substring(0, space_before); diff --git a/src/tilecache.ts b/src/tilecache.ts index 950245c4..fbd756c1 100644 --- a/src/tilecache.ts +++ b/src/tilecache.ts @@ -54,7 +54,7 @@ export interface TileSource { // so the general tile rendering case does not need rescaling. const loadGeomAndBbox = (pbf: any, geometry: number, scale: number) => { pbf.pos = geometry; - var end = pbf.readVarint() + pbf.pos, + let end = pbf.readVarint() + pbf.pos, cmd = 1, length = 0, x = 0, @@ -64,11 +64,11 @@ const loadGeomAndBbox = (pbf: any, geometry: number, scale: number) => { y1 = Infinity, y2 = -Infinity; - var lines: Point[][] = []; - var line: Point[] = []; + const lines: Point[][] = []; + let line: Point[] = []; while (pbf.pos < end) { if (length <= 0) { - var cmdLen = pbf.readVarint(); + const cmdLen = pbf.readVarint(); cmd = cmdLen & 0x7; length = cmdLen >> 3; } @@ -130,7 +130,7 @@ export class PmtilesSource implements TileSource { shouldCancelZooms: boolean; constructor(url: string | PMTiles, shouldCancelZooms: boolean) { - if (typeof url == "string") { + if (typeof url === "string") { this.p = new PMTiles(url); } else { this.p = url; @@ -142,7 +142,7 @@ export class PmtilesSource implements TileSource { public async get(c: Zxy, tileSize: number): Promise> { if (this.shouldCancelZooms) { this.controllers = this.controllers.filter((cont) => { - if (cont[0] != c.z) { + if (cont[0] !== c.z) { cont[1].abort(); return false; } @@ -177,7 +177,7 @@ export class ZxySource implements TileSource { public async get(c: Zxy, tileSize: number): Promise> { if (this.shouldCancelZooms) { this.controllers = this.controllers.filter((cont) => { - if (cont[0] != c.z) { + if (cont[0] !== c.z) { cont[1].abort(); return false; } @@ -238,22 +238,22 @@ function dist2(v: Point, w: Point) { } function distToSegmentSquared(p: Point, v: Point, w: Point) { - var l2 = dist2(v, w); + const l2 = dist2(v, w); if (l2 === 0) return dist2(p, v); - var t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; + let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2; t = Math.max(0, Math.min(1, t)); return dist2(p, new Point(v.x + t * (w.x - v.x), v.y + t * (w.y - v.y))); } export function isInRing(point: Point, ring: Point[]): boolean { - var inside = false; - for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) { - var xi = ring[i].x, + let inside = false; + for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) { + const xi = ring[i].x, yi = ring[i].y; - var xj = ring[j].x, + const xj = ring[j].x, yj = ring[j].y; - var intersect = - yi > point.y != yj > point.y && + const intersect = + yi > point.y !== yj > point.y && point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi; if (intersect) inside = !inside; } @@ -261,8 +261,8 @@ export function isInRing(point: Point, ring: Point[]): boolean { } export function isCCW(ring: Point[]): boolean { - var area = 0; - for (var i = 0; i < ring.length; i++) { + let area = 0; + for (let i = 0; i < ring.length; i++) { const j = (i + 1) % ring.length; area += ring[i].x * ring[j].y; area -= ring[j].x * ring[i].y; @@ -271,7 +271,7 @@ export function isCCW(ring: Point[]): boolean { } export function pointInPolygon(point: Point, geom: Point[][]): boolean { - var isInCurrentExterior = false; + let isInCurrentExterior = false; for (const ring of geom) { if (isCCW(ring)) { // it is an interior ring @@ -297,7 +297,7 @@ export function pointMinDistToPoints(point: Point, geom: Point[][]): number { export function pointMinDistToLines(point: Point, geom: Point[][]): number { let min = Infinity; for (const l of geom) { - for (var i = 0; i < l.length - 1; i++) { + for (let i = 0; i < l.length - 1; i++) { const dist = Math.sqrt(distToSegmentSquared(point, l[i], l[i + 1])); if (dist < min) min = dist; } @@ -330,7 +330,7 @@ export class TileCache { brushSize: number, ): PickedFeature[] { const projected = project([lat, lng]); - var normalized = new Point( + const normalized = new Point( (projected.x + MAXCOORD) / (MAXCOORD * 2), 1 - (projected.y + MAXCOORD) / (MAXCOORD * 2), ); @@ -354,11 +354,11 @@ export class TileCache { // (query_bbox.maxY >= feature.bbox.minY && feature.bbox.maxY >= query_bbox.minY)) { // } - if (feature.geomType == GeomType.Point) { + if (feature.geomType === GeomType.Point) { if (pointMinDistToPoints(center, feature.geom) < brushSize) { retval.push({ feature, layerName: layer_name }); } - } else if (feature.geomType == GeomType.Line) { + } else if (feature.geomType === GeomType.Line) { if (pointMinDistToLines(center, feature.geom) < brushSize) { retval.push({ feature, layerName: layer_name }); } diff --git a/src/view.ts b/src/view.ts index 42d2d80e..972b716e 100644 --- a/src/view.ts +++ b/src/view.ts @@ -79,8 +79,8 @@ export class View { const fractional = Math.pow(2, display_zoom) / Math.pow(2, Math.ceil(display_zoom)); const needed = []; - var scale = 1; - var dim = this.tileCache.tileSize; + let scale = 1; + const dim = this.tileCache.tileSize; if (display_zoom < this.levelDiff) { scale = (1 / (1 << (this.levelDiff - display_zoom))) * fractional; needed.push({ @@ -100,8 +100,8 @@ export class View { const mintile_y = Math.floor(bounds.minY / f / basetile_size); const maxtile_x = Math.floor(bounds.maxX / f / basetile_size); const maxtile_y = Math.floor(bounds.maxY / f / basetile_size); - for (var tx = mintile_x; tx <= maxtile_x; tx++) { - for (var ty = mintile_y; ty <= maxtile_y; ty++) { + for (let tx = mintile_x; tx <= maxtile_x; tx++) { + for (let ty = mintile_y; ty <= maxtile_y; ty++) { const origin = new Point( tx * f * basetile_size, ty * f * basetile_size, @@ -127,8 +127,8 @@ export class View { const mintile_y = Math.floor(bounds.minY / f / 256 / scale); const maxtile_x = Math.floor(bounds.maxX / f / 256 / scale); const maxtile_y = Math.floor(bounds.maxY / f / 256 / scale); - for (var tx = mintile_x; tx <= maxtile_x; tx++) { - for (var ty = mintile_y; ty <= maxtile_y; ty++) { + for (let tx = mintile_x; tx <= maxtile_x; tx++) { + for (let ty = mintile_y; ty <= maxtile_y; ty++) { const origin = new Point(tx * f * 256 * scale, ty * f * 256 * scale); needed.push({ data_tile: { @@ -147,10 +147,10 @@ export class View { } public dataTileForDisplayTile(display_tile: Zxy): TileTransform { - var data_tile: Zxy; - var scale = 1; - var dim = this.tileCache.tileSize; - var origin: Point; + let data_tile: Zxy; + let scale = 1; + let dim = this.tileCache.tileSize; + let origin: Point; if (display_tile.z < this.levelDiff) { data_tile = { z: 0, x: 0, y: 0 }; scale = 1 / (1 << (this.levelDiff - display_tile.z)); diff --git a/src/xray.ts b/src/xray.ts index b9589f6f..b9edf3eb 100644 --- a/src/xray.ts +++ b/src/xray.ts @@ -27,7 +27,7 @@ const xray_symbolizers = ( radius: 4, }), filter: (z, f) => { - return f.geomType == GeomType.Point; + return f.geomType === GeomType.Point; }, }, { @@ -39,7 +39,7 @@ const xray_symbolizers = ( width: 2, }), filter: (z, f) => { - return f.geomType == GeomType.Line; + return f.geomType === GeomType.Line; }, }, { @@ -52,7 +52,7 @@ const xray_symbolizers = ( width: 1, }), filter: (z, f) => { - return f.geomType == GeomType.Polygon; + return f.geomType === GeomType.Polygon; }, }, ]; @@ -62,10 +62,10 @@ export const xray_rules = ( prepared_tilemap: Map, xray: XraySelection, // the highlighted layer ): Rule[] => { - var rules: Rule[] = []; - for (var [dataSource, tiles] of prepared_tilemap) { - for (var tile of tiles) { - for (var dataLayer of tile.data.keys()) { + let rules: Rule[] = []; + for (const [dataSource, tiles] of prepared_tilemap) { + for (const tile of tiles) { + for (const dataLayer of tile.data.keys()) { if (dataSource === xray.dataSource && dataLayer === xray.dataLayer) { // do nothing since the highlighted layer should go last } else { diff --git a/test/attribute.test.ts b/test/attribute.test.ts index 1cec30bb..ab773be5 100644 --- a/test/attribute.test.ts +++ b/test/attribute.test.ts @@ -66,7 +66,7 @@ test("fontattr", async () => { f = new FontAttr({ font: (z) => { - return z == 1 ? "12px serif" : "14px serif"; + return z === 1 ? "12px serif" : "14px serif"; }, }); assert.equal(f.get(1), "12px serif"); @@ -85,7 +85,7 @@ test("fontattr", async () => { f = new FontAttr({ fontWeight: (z) => { - return z == 1 ? 400 : 600; + return z === 1 ? 400 : 600; }, }); assert.equal(f.get(1), "400 12px sans-serif"); @@ -93,7 +93,7 @@ test("fontattr", async () => { f = new FontAttr({ fontSize: (z) => { - return z == 1 ? 12 : 14; + return z === 1 ? 12 : 14; }, }); assert.equal(f.get(1), "12px sans-serif"); @@ -101,7 +101,7 @@ test("fontattr", async () => { f = new FontAttr({ fontStyle: (z) => { - return z == 1 ? "normal" : "italic"; + return z === 1 ? "normal" : "italic"; }, }); assert.equal(f.get(1), "normal 12px sans-serif"); @@ -109,7 +109,7 @@ test("fontattr", async () => { f = new FontAttr({ fontFamily: (z) => { - return z == 1 ? "sans-serif" : "serif"; + return z === 1 ? "sans-serif" : "serif"; }, }); assert.equal(f.get(1), "12px sans-serif"); From 4c0db9090f3ea9e1a211878a024832791dcf310e Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Tue, 23 Jan 2024 16:27:41 +0800 Subject: [PATCH 4/7] more linting --- src/compat/json_style.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compat/json_style.ts b/src/compat/json_style.ts index 5564aae4..41ee9504 100644 --- a/src/compat/json_style.ts +++ b/src/compat/json_style.ts @@ -76,7 +76,7 @@ export function numberFn(obj: any): (z: number, f?: Feature) => number { return (z: number) => { return exp(obj[1][1], stops)(z - 1); }; - } else if (obj[0] == "step" && obj[1][0] == "get") { + } else if (obj[0] === "step" && obj[1][0] === "get") { const slice = obj.slice(2); const prop = obj[1][1]; return (z: number, f?: Feature) => { @@ -100,7 +100,7 @@ export function numberOrFn( defaultValue = 0, ): number | ((z: number, f?: Feature) => number) { if (!obj) return defaultValue; - if (typeof obj == "number") { + if (typeof obj === "number") { return obj; } // If feature f is defined, use numberFn, otherwise use defaultValue @@ -142,7 +142,7 @@ export function getFont(obj: any, fontsubmap: any) { let style = ""; if (fontfaces.length && fontfaces[0].style) style = fontfaces[0].style + " "; - if (typeof text_size == "number") { + if (typeof text_size === "number") { return (z: number) => `${style}${weight}${text_size}px ${fontfaces .map((f) => f.face) From a8bbff7b758e146ee75a506e578b878984d5845c Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Tue, 23 Jan 2024 16:33:04 +0800 Subject: [PATCH 5/7] fix test duplication --- test/attribute.test.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/attribute.test.ts b/test/attribute.test.ts index ab773be5..52d33987 100644 --- a/test/attribute.test.ts +++ b/test/attribute.test.ts @@ -8,7 +8,14 @@ import { TextAttr, } from "../src/attribute"; import { GeomType } from "../src/tilecache"; -import { emptyFeature } from "./json_style.test"; + +export const emptyFeature = { + props: {}, + geomType: GeomType.Point, + numVertices: 0, + geom: [], + bbox: { minX: 0, minY: 0, maxX: 0, maxY: 0 }, +}; test("numberattr", async () => { let n = new NumberAttr(undefined, undefined); From 848c43d3d84182e6d1c9d7f9870314281e61f552 Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Tue, 23 Jan 2024 16:56:37 +0800 Subject: [PATCH 6/7] fix tests --- src/compat/json_style.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compat/json_style.ts b/src/compat/json_style.ts index 41ee9504..0b5dbc86 100644 --- a/src/compat/json_style.ts +++ b/src/compat/json_style.ts @@ -66,7 +66,7 @@ export function numberFn(obj: any): (z: number, f?: Feature) => number { } else if ( obj[0] === "interpolate" && obj[1][0] === "exponential" && - obj[2] === "zoom" + obj[2] === ["zoom"] ) { const slice = obj.slice(3); const stops: number[][] = []; From c0cccbe4646a550041bac3f44e1722c68beb3207 Mon Sep 17 00:00:00 2001 From: Brandon Liu Date: Tue, 23 Jan 2024 17:00:44 +0800 Subject: [PATCH 7/7] fix tests 2 --- src/compat/json_style.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compat/json_style.ts b/src/compat/json_style.ts index 0b5dbc86..ffb62ad9 100644 --- a/src/compat/json_style.ts +++ b/src/compat/json_style.ts @@ -66,7 +66,7 @@ export function numberFn(obj: any): (z: number, f?: Feature) => number { } else if ( obj[0] === "interpolate" && obj[1][0] === "exponential" && - obj[2] === ["zoom"] + obj[2][0] === "zoom" ) { const slice = obj.slice(3); const stops: number[][] = [];