latlon-geohash
Advanced tools
Comparing version 1.1.0 to 2.0.0
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
/* Geohash encoding/decoding and associated functions (c) Chris Veness 2014-2016 / MIT Licence */ | ||
/* Geohash encoding/decoding and associated functions (c) Chris Veness 2014-2019 / MIT Licence */ | ||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
'use strict'; | ||
const base32 = '0123456789bcdefghjkmnpqrstuvwxyz'; // (geohash-specific) Base32 map | ||
/** | ||
* Geohash encode, decode, bounds, neighbours. | ||
* | ||
* @namespace | ||
* Geohash: Gustavo Niemeyer’s geocoding system. | ||
*/ | ||
var Geohash = {}; | ||
class Geohash { | ||
/* (Geohash-specific) Base32 map */ | ||
Geohash.base32 = '0123456789bcdefghjkmnpqrstuvwxyz'; | ||
/** | ||
* Encodes latitude/longitude to geohash, either to specified precision or to automatically | ||
* evaluated precision. | ||
* | ||
* @param {number} lat - Latitude in degrees. | ||
* @param {number} lon - Longitude in degrees. | ||
* @param {number} [precision] - Number of characters in resulting geohash. | ||
* @returns {string} Geohash of supplied latitude/longitude. | ||
* @throws Invalid geohash. | ||
* | ||
* @example | ||
* var geohash = Geohash.encode(52.205, 0.119, 7); // geohash: 'u120fxw' | ||
*/ | ||
Geohash.encode = function(lat, lon, precision) { | ||
// infer precision? | ||
if (typeof precision == 'undefined') { | ||
// refine geohash until it matches precision of supplied lat/lon | ||
for (var p=1; p<=12; p++) { | ||
var hash = Geohash.encode(lat, lon, p); | ||
var posn = Geohash.decode(hash); | ||
if (posn.lat==lat && posn.lon==lon) return hash; | ||
/** | ||
* Encodes latitude/longitude to geohash, either to specified precision or to automatically | ||
* evaluated precision. | ||
* | ||
* @param {number} lat - Latitude in degrees. | ||
* @param {number} lon - Longitude in degrees. | ||
* @param {number} [precision] - Number of characters in resulting geohash. | ||
* @returns {string} Geohash of supplied latitude/longitude. | ||
* @throws Invalid geohash. | ||
* | ||
* @example | ||
* const geohash = Geohash.encode(52.205, 0.119, 7); // => 'u120fxw' | ||
*/ | ||
static encode(lat, lon, precision) { | ||
// infer precision? | ||
if (typeof precision == 'undefined') { | ||
// refine geohash until it matches precision of supplied lat/lon | ||
for (let p=1; p<=12; p++) { | ||
const hash = Geohash.encode(lat, lon, p); | ||
const posn = Geohash.decode(hash); | ||
if (posn.lat==lat && posn.lon==lon) return hash; | ||
} | ||
precision = 12; // set to maximum | ||
} | ||
precision = 12; // set to maximum | ||
} | ||
lat = Number(lat); | ||
lon = Number(lon); | ||
precision = Number(precision); | ||
lat = Number(lat); | ||
lon = Number(lon); | ||
precision = Number(precision); | ||
if (isNaN(lat) || isNaN(lon) || isNaN(precision)) throw new Error('Invalid geohash'); | ||
if (isNaN(lat) || isNaN(lon) || isNaN(precision)) throw new Error('Invalid geohash'); | ||
var idx = 0; // index into base32 map | ||
var bit = 0; // each char holds 5 bits | ||
var evenBit = true; | ||
var geohash = ''; | ||
let idx = 0; // index into base32 map | ||
let bit = 0; // each char holds 5 bits | ||
let evenBit = true; | ||
let geohash = ''; | ||
var latMin = -90, latMax = 90; | ||
var lonMin = -180, lonMax = 180; | ||
let latMin = -90, latMax = 90; | ||
let lonMin = -180, lonMax = 180; | ||
while (geohash.length < precision) { | ||
if (evenBit) { | ||
// bisect E-W longitude | ||
var lonMid = (lonMin + lonMax) / 2; | ||
if (lon >= lonMid) { | ||
idx = idx*2 + 1; | ||
lonMin = lonMid; | ||
while (geohash.length < precision) { | ||
if (evenBit) { | ||
// bisect E-W longitude | ||
const lonMid = (lonMin + lonMax) / 2; | ||
if (lon >= lonMid) { | ||
idx = idx*2 + 1; | ||
lonMin = lonMid; | ||
} else { | ||
idx = idx*2; | ||
lonMax = lonMid; | ||
} | ||
} else { | ||
idx = idx*2; | ||
lonMax = lonMid; | ||
// bisect N-S latitude | ||
const latMid = (latMin + latMax) / 2; | ||
if (lat >= latMid) { | ||
idx = idx*2 + 1; | ||
latMin = latMid; | ||
} else { | ||
idx = idx*2; | ||
latMax = latMid; | ||
} | ||
} | ||
} else { | ||
// bisect N-S latitude | ||
var latMid = (latMin + latMax) / 2; | ||
if (lat >= latMid) { | ||
idx = idx*2 + 1; | ||
latMin = latMid; | ||
} else { | ||
idx = idx*2; | ||
latMax = latMid; | ||
evenBit = !evenBit; | ||
if (++bit == 5) { | ||
// 5 bits gives us a character: append it and start over | ||
geohash += base32.charAt(idx); | ||
bit = 0; | ||
idx = 0; | ||
} | ||
} | ||
evenBit = !evenBit; | ||
if (++bit == 5) { | ||
// 5 bits gives us a character: append it and start over | ||
geohash += Geohash.base32.charAt(idx); | ||
bit = 0; | ||
idx = 0; | ||
} | ||
return geohash; | ||
} | ||
return geohash; | ||
}; | ||
/** | ||
* Decode geohash to latitude/longitude (location is approximate centre of geohash cell, | ||
* to reasonable precision). | ||
* | ||
* @param {string} geohash - Geohash string to be converted to latitude/longitude. | ||
* @returns {{lat:number, lon:number}} (Center of) geohashed location. | ||
* @throws Invalid geohash. | ||
* | ||
* @example | ||
* const latlon = Geohash.decode('u120fxw'); // => { lat: 52.205, lon: 0.1188 } | ||
*/ | ||
static decode(geohash) { | ||
/** | ||
* Decode geohash to latitude/longitude (location is approximate centre of geohash cell, | ||
* to reasonable precision). | ||
* | ||
* @param {string} geohash - Geohash string to be converted to latitude/longitude. | ||
* @returns {{lat:number, lon:number}} (Center of) geohashed location. | ||
* @throws Invalid geohash. | ||
* | ||
* @example | ||
* var latlon = Geohash.decode('u120fxw'); // latlon: { lat: 52.205, lon: 0.1188 } | ||
*/ | ||
Geohash.decode = function(geohash) { | ||
const bounds = Geohash.bounds(geohash); // <-- the hard work | ||
// now just determine the centre of the cell... | ||
var bounds = Geohash.bounds(geohash); // <-- the hard work | ||
// now just determine the centre of the cell... | ||
const latMin = bounds.sw.lat, lonMin = bounds.sw.lon; | ||
const latMax = bounds.ne.lat, lonMax = bounds.ne.lon; | ||
var latMin = bounds.sw.lat, lonMin = bounds.sw.lon; | ||
var latMax = bounds.ne.lat, lonMax = bounds.ne.lon; | ||
// cell centre | ||
let lat = (latMin + latMax)/2; | ||
let lon = (lonMin + lonMax)/2; | ||
// cell centre | ||
var lat = (latMin + latMax)/2; | ||
var lon = (lonMin + lonMax)/2; | ||
// round to close to centre without excessive precision: ⌊2-log10(Δ°)⌋ decimal places | ||
lat = lat.toFixed(Math.floor(2-Math.log(latMax-latMin)/Math.LN10)); | ||
lon = lon.toFixed(Math.floor(2-Math.log(lonMax-lonMin)/Math.LN10)); | ||
// round to close to centre without excessive precision: ⌊2-log10(Δ°)⌋ decimal places | ||
lat = lat.toFixed(Math.floor(2-Math.log(latMax-latMin)/Math.LN10)); | ||
lon = lon.toFixed(Math.floor(2-Math.log(lonMax-lonMin)/Math.LN10)); | ||
return { lat: Number(lat), lon: Number(lon) }; | ||
} | ||
return { lat: Number(lat), lon: Number(lon) }; | ||
}; | ||
/** | ||
* Returns SW/NE latitude/longitude bounds of specified geohash. | ||
* | ||
* @param {string} geohash - Cell that bounds are required of. | ||
* @returns {{sw: {lat: number, lon: number}, ne: {lat: number, lon: number}}} | ||
* @throws Invalid geohash. | ||
*/ | ||
static bounds(geohash) { | ||
if (geohash.length == 0) throw new Error('Invalid geohash'); | ||
/** | ||
* Returns SW/NE latitude/longitude bounds of specified geohash. | ||
* | ||
* @param {string} geohash - Cell that bounds are required of. | ||
* @returns {{sw: {lat: number, lon: number}, ne: {lat: number, lon: number}}} | ||
* @throws Invalid geohash. | ||
*/ | ||
Geohash.bounds = function(geohash) { | ||
if (geohash.length === 0) throw new Error('Invalid geohash'); | ||
geohash = geohash.toLowerCase(); | ||
geohash = geohash.toLowerCase(); | ||
let evenBit = true; | ||
let latMin = -90, latMax = 90; | ||
let lonMin = -180, lonMax = 180; | ||
var evenBit = true; | ||
var latMin = -90, latMax = 90; | ||
var lonMin = -180, lonMax = 180; | ||
for (let i=0; i<geohash.length; i++) { | ||
const chr = geohash.charAt(i); | ||
const idx = base32.indexOf(chr); | ||
if (idx == -1) throw new Error('Invalid geohash'); | ||
for (var i=0; i<geohash.length; i++) { | ||
var chr = geohash.charAt(i); | ||
var idx = Geohash.base32.indexOf(chr); | ||
if (idx == -1) throw new Error('Invalid geohash'); | ||
for (var n=4; n>=0; n--) { | ||
var bitN = idx >> n & 1; | ||
if (evenBit) { | ||
// longitude | ||
var lonMid = (lonMin+lonMax) / 2; | ||
if (bitN == 1) { | ||
lonMin = lonMid; | ||
for (let n=4; n>=0; n--) { | ||
const bitN = idx >> n & 1; | ||
if (evenBit) { | ||
// longitude | ||
const lonMid = (lonMin+lonMax) / 2; | ||
if (bitN == 1) { | ||
lonMin = lonMid; | ||
} else { | ||
lonMax = lonMid; | ||
} | ||
} else { | ||
lonMax = lonMid; | ||
// latitude | ||
const latMid = (latMin+latMax) / 2; | ||
if (bitN == 1) { | ||
latMin = latMid; | ||
} else { | ||
latMax = latMid; | ||
} | ||
} | ||
} else { | ||
// latitude | ||
var latMid = (latMin+latMax) / 2; | ||
if (bitN == 1) { | ||
latMin = latMid; | ||
} else { | ||
latMax = latMid; | ||
} | ||
evenBit = !evenBit; | ||
} | ||
evenBit = !evenBit; | ||
} | ||
const bounds = { | ||
sw: { lat: latMin, lon: lonMin }, | ||
ne: { lat: latMax, lon: lonMax }, | ||
}; | ||
return bounds; | ||
} | ||
var bounds = { | ||
sw: { lat: latMin, lon: lonMin }, | ||
ne: { lat: latMax, lon: lonMax }, | ||
}; | ||
return bounds; | ||
}; | ||
/** | ||
* Determines adjacent cell in given direction. | ||
* | ||
* @param geohash - Cell to which adjacent cell is required. | ||
* @param direction - Direction from geohash (N/S/E/W). | ||
* @returns {string} Geocode of adjacent cell. | ||
* @throws Invalid geohash. | ||
*/ | ||
static adjacent(geohash, direction) { | ||
// based on github.com/davetroy/geohash-js | ||
geohash = geohash.toLowerCase(); | ||
direction = direction.toLowerCase(); | ||
/** | ||
* Determines adjacent cell in given direction. | ||
* | ||
* @param geohash - Cell to which adjacent cell is required. | ||
* @param direction - Direction from geohash (N/S/E/W). | ||
* @returns {string} Geocode of adjacent cell. | ||
* @throws Invalid geohash. | ||
*/ | ||
Geohash.adjacent = function(geohash, direction) { | ||
// based on github.com/davetroy/geohash-js | ||
if (geohash.length == 0) throw new Error('Invalid geohash'); | ||
if ('nsew'.indexOf(direction) == -1) throw new Error('Invalid direction'); | ||
geohash = geohash.toLowerCase(); | ||
direction = direction.toLowerCase(); | ||
const neighbour = { | ||
n: [ 'p0r21436x8zb9dcf5h7kjnmqesgutwvy', 'bc01fg45238967deuvhjyznpkmstqrwx' ], | ||
s: [ '14365h7k9dcfesgujnmqp0r2twvyx8zb', '238967debc01fg45kmstqrwxuvhjyznp' ], | ||
e: [ 'bc01fg45238967deuvhjyznpkmstqrwx', 'p0r21436x8zb9dcf5h7kjnmqesgutwvy' ], | ||
w: [ '238967debc01fg45kmstqrwxuvhjyznp', '14365h7k9dcfesgujnmqp0r2twvyx8zb' ], | ||
}; | ||
const border = { | ||
n: [ 'prxz', 'bcfguvyz' ], | ||
s: [ '028b', '0145hjnp' ], | ||
e: [ 'bcfguvyz', 'prxz' ], | ||
w: [ '0145hjnp', '028b' ], | ||
}; | ||
if (geohash.length === 0) throw new Error('Invalid geohash'); | ||
if ('nsew'.indexOf(direction) == -1) throw new Error('Invalid direction'); | ||
const lastCh = geohash.slice(-1); // last character of hash | ||
let parent = geohash.slice(0, -1); // hash without last character | ||
var neighbour = { | ||
n: [ 'p0r21436x8zb9dcf5h7kjnmqesgutwvy', 'bc01fg45238967deuvhjyznpkmstqrwx' ], | ||
s: [ '14365h7k9dcfesgujnmqp0r2twvyx8zb', '238967debc01fg45kmstqrwxuvhjyznp' ], | ||
e: [ 'bc01fg45238967deuvhjyznpkmstqrwx', 'p0r21436x8zb9dcf5h7kjnmqesgutwvy' ], | ||
w: [ '238967debc01fg45kmstqrwxuvhjyznp', '14365h7k9dcfesgujnmqp0r2twvyx8zb' ], | ||
}; | ||
var border = { | ||
n: [ 'prxz', 'bcfguvyz' ], | ||
s: [ '028b', '0145hjnp' ], | ||
e: [ 'bcfguvyz', 'prxz' ], | ||
w: [ '0145hjnp', '028b' ], | ||
}; | ||
const type = geohash.length % 2; | ||
var lastCh = geohash.slice(-1); // last character of hash | ||
var parent = geohash.slice(0, -1); // hash without last character | ||
// check for edge-cases which don't share common prefix | ||
if (border[direction][type].indexOf(lastCh) != -1 && parent != '') { | ||
parent = Geohash.adjacent(parent, direction); | ||
} | ||
var type = geohash.length % 2; | ||
// check for edge-cases which don't share common prefix | ||
if (border[direction][type].indexOf(lastCh) != -1 && parent !== '') { | ||
parent = Geohash.adjacent(parent, direction); | ||
// append letter for direction to parent | ||
return parent + base32.charAt(neighbour[direction][type].indexOf(lastCh)); | ||
} | ||
// append letter for direction to parent | ||
return parent + Geohash.base32.charAt(neighbour[direction][type].indexOf(lastCh)); | ||
}; | ||
/** | ||
* Returns all 8 adjacent cells to specified geohash. | ||
* | ||
* @param {string} geohash - Geohash neighbours are required of. | ||
* @returns {{n,ne,e,se,s,sw,w,nw: string}} | ||
* @throws Invalid geohash. | ||
*/ | ||
static neighbours(geohash) { | ||
return { | ||
'n': Geohash.adjacent(geohash, 'n'), | ||
'ne': Geohash.adjacent(Geohash.adjacent(geohash, 'n'), 'e'), | ||
'e': Geohash.adjacent(geohash, 'e'), | ||
'se': Geohash.adjacent(Geohash.adjacent(geohash, 's'), 'e'), | ||
's': Geohash.adjacent(geohash, 's'), | ||
'sw': Geohash.adjacent(Geohash.adjacent(geohash, 's'), 'w'), | ||
'w': Geohash.adjacent(geohash, 'w'), | ||
'nw': Geohash.adjacent(Geohash.adjacent(geohash, 'n'), 'w'), | ||
}; | ||
} | ||
/** | ||
* Returns all 8 adjacent cells to specified geohash. | ||
* | ||
* @param {string} geohash - Geohash neighbours are required of. | ||
* @returns {{n,ne,e,se,s,sw,w,nw: string}} | ||
* @throws Invalid geohash. | ||
*/ | ||
Geohash.neighbours = function(geohash) { | ||
return { | ||
'n': Geohash.adjacent(geohash, 'n'), | ||
'ne': Geohash.adjacent(Geohash.adjacent(geohash, 'n'), 'e'), | ||
'e': Geohash.adjacent(geohash, 'e'), | ||
'se': Geohash.adjacent(Geohash.adjacent(geohash, 's'), 'e'), | ||
's': Geohash.adjacent(geohash, 's'), | ||
'sw': Geohash.adjacent(Geohash.adjacent(geohash, 's'), 'w'), | ||
'w': Geohash.adjacent(geohash, 'w'), | ||
'nw': Geohash.adjacent(Geohash.adjacent(geohash, 'n'), 'w'), | ||
}; | ||
}; | ||
} | ||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
if (typeof module != 'undefined' && module.exports) module.exports = Geohash; // CommonJS, node.js | ||
export default Geohash; |
{ | ||
"name": "latlon-geohash", | ||
"description": "Gustavo Niemeyer’s geocoding system", | ||
"homepage": "http://www.movable-type.co.uk/scripts/geohash.html", | ||
"author": "Chris Veness", | ||
"version": "1.1.0", | ||
"version": "2.0.0", | ||
"license": "MIT", | ||
"homepage": "http://www.movable-type.co.uk/scripts/geohash.html", | ||
"type": "module", | ||
"main": "latlon-geohash.js", | ||
@@ -15,15 +16,22 @@ "repository": { | ||
"scripts": { | ||
"test": "mocha test.js", | ||
"test": "mocha --exit -r esm test.js", | ||
"lint": "eslint latlon-geohash.js" | ||
}, | ||
"devDependencies": { | ||
"chai": "^3.5.0", | ||
"eslint": "^3.5.0", | ||
"mocha": "^3.0.2" | ||
"chai": "^4.0.0", | ||
"eslint": "^6.0.0", | ||
"esm": "^3.0.0", | ||
"mocha": "^6.0.0" | ||
}, | ||
"eslintConfig": { | ||
"env": { | ||
"node": true, | ||
"mocha": true | ||
"browser": true, | ||
"es6": true, | ||
"mocha": true, | ||
"node": true | ||
}, | ||
"parserOptions": { | ||
"ecmaVersion": 6, | ||
"sourceType": "module" | ||
}, | ||
"extends": "eslint:recommended", | ||
@@ -33,12 +41,20 @@ "rules": { | ||
"comma-dangle": [ "error", "always-multiline" ], | ||
"comma-spacing": [ "error" ], | ||
"curly": [ "error", "multi-line" ], | ||
"indent": [ "error", 4, { "SwitchCase": 1 } ], | ||
"key-spacing": [ "error", { "align": "value" } ], | ||
"no-console": "warn", | ||
"keyword-spacing": [ "error" ], | ||
"no-case-declarations": "warn", | ||
"no-console": [ "warn", { "allow": [ "error", "info" ] } ], | ||
"no-irregular-whitespace": "warn", | ||
"no-redeclare": "warn", | ||
"no-shadow": "warn", | ||
"no-unused-vars": "warn", | ||
"no-var": "error", | ||
"object-curly-spacing": [ "error", "always" ], | ||
"prefer-const": "error", | ||
"quotes": [ "error", "single", "avoid-escape" ], | ||
"semi": [ "error", "always" ], | ||
"space-before-blocks": [ "error", "always" ], | ||
"space-in-parens": [ "error" ], | ||
"strict": [ "error", "global" ] | ||
@@ -45,0 +61,0 @@ } |
@@ -7,27 +7,8 @@ geohash | ||
Methods summary: | ||
Note this version 2 uses ES classes and modules: for older browsers (or Node.js <8.0.0), | ||
[v1.1.0](https://github.com/chrisveness/latlon-geohash/tree/v1.1.0) is ES5-based. | ||
- `encode`: latitude/longitude point to geohash | ||
- `decode`: geohash to latitude/longitude | ||
- `bounds` of a geohash cell | ||
- `adjacent` `neighbours` of a geohash | ||
API | ||
--- | ||
Install | ||
------- | ||
### in browser | ||
Download the JavaScript [source](https://raw.githubusercontent.com/chrisveness/geodesy/master/latlon-geohash.js) | ||
and reference in HTML page using: | ||
<script src="js/latlon-geohash.js"></script> | ||
### from npm | ||
npm install --save latlon-geohash | ||
Usage | ||
----- | ||
- `Geohash.encode(lat, lon, [precision])`: encode latitude/longitude point to geohash of given precision | ||
@@ -43,11 +24,48 @@ (number of characters in resulting geohash); if precision is not specified, it is inferred from | ||
var neighboursObj = Geohash.neighbours(geohash); | ||
var neighboursArr = Object.keys(neighboursObj).map(function(n) { return neighboursObj[n]; }); | ||
const neighboursObj = Geohash.neighbours(geohash); | ||
const neighboursArr = Object.keys(neighboursObj).map(n => neighboursObj[n]); | ||
Note that the parent of a geocode is simply `geocode.slice(0, -1)`. | ||
The parent of a geocode is simply `geocode.slice(0, -1)`. | ||
### Import within node.js | ||
If you want the geohash converted from Base32 to Base4, you can e.g.: | ||
var Geohash = require('latlon-geohash'); | ||
parseInt(Geohash.encode(52.20, 0.12, 6), 32).toString(4); | ||
Usage in browser | ||
---------------- | ||
Geohash can be used in the browser by taking a local copy, or loading it from | ||
[jsDelivr](https://www.jsdelivr.com/package/npm/latlon-geohash): for example, | ||
```html | ||
<!doctype html><title>geohash example</title><meta charset="utf-8"> | ||
<script type="module"> | ||
import Geohash from 'https://cdn.jsdelivr.net/npm/latlon-geohash@2.0.0'; | ||
const geohash = Geohash.encode(52.20, 0.12, 6); | ||
console.assert(geohash == 'u120fw'); | ||
const latlon = Geohash.decode('u120fw'); | ||
console.assert(JSON.stringify(latlon) == '{"lat":52.1988,"lon":0.115}'); | ||
</script> | ||
``` | ||
Usage in Node.js | ||
---------------- | ||
Geohash can be used in a Node.js app from [npm](https://www.npmjs.com/package/latlon-geohash) | ||
(currently the [esm](https://www.npmjs.com/package/esm) package is required to load ES-modules): | ||
```shell | ||
$ npm install latlon-geohash esm | ||
$ node -r esm | ||
> import Geohash from 'latlon-geohash'; | ||
> const geohash = Geohash.encode(52.20, 0.12, 6); | ||
> console.assert(geohash == 'u120fw'); | ||
> const latlon = Geohash.decode('u120fw'); | ||
> console.assert(JSON.stringify(latlon) == '{"lat":52.1988,"lon":0.115}'); | ||
``` | ||
Further details | ||
@@ -54,0 +72,0 @@ --------------- |
12
test.js
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
/* Geohash Test Harness (c) Chris Veness 2014-2016 / MIT Licence */ | ||
/* Geohash Test Harness (c) Chris Veness 2014-2019 / MIT Licence */ | ||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
'use strict' | ||
const chai = require('chai'); // BDD/TDD assertion library | ||
import Geohash from './latlon-geohash.js'; | ||
const Geohash = require('./latlon-geohash.js'); | ||
if (typeof window == 'undefined') { // node | ||
import('chai').then(chai => { global.should = chai.should(); }); | ||
} else { // browser | ||
window.should = chai.should(); | ||
} | ||
const should = chai.should(); | ||
@@ -12,0 +14,0 @@ describe('latlon-geohash', function() { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
15705
76
Yes
4
219