Lint
This commit is contained in:
parent
94f9c0d594
commit
5c3b87f2d5
69 changed files with 1334 additions and 213 deletions
|
|
@ -133,56 +133,59 @@ export const POI_DEFAULT_COLOR: [number, number, number] = [107, 114, 128];
|
|||
/** POI category → icon/logo URL for branded and transport categories */
|
||||
export const POI_CATEGORY_LOGOS: Record<string, string> = {
|
||||
Airport: '/assets/twemoji/2708.png',
|
||||
Aldi: 'https://geolytix.github.io/MapIcons/brands/aldi_24px.svg',
|
||||
Amazon: 'https://geolytix.github.io/MapIcons/brands/amazon_fresh_alt_24px.svg',
|
||||
Asda: 'https://geolytix.github.io/MapIcons/asda/asda_primary.svg',
|
||||
'Asda Express': 'https://geolytix.github.io/MapIcons/asda/asda_express_24px.svg',
|
||||
'Asda Living': 'https://geolytix.github.io/MapIcons/asda/asda_living_24px.svg',
|
||||
'Asda PFS': 'https://geolytix.github.io/MapIcons/asda/asda_pfs_24px.svg',
|
||||
Aldi: '/assets/poi-icons/logos/aldi.svg',
|
||||
Amazon: '/assets/poi-icons/brands_2024/amazon_fresh.svg',
|
||||
Asda: '/assets/poi-icons/logos/asda.svg',
|
||||
'Asda Express': '/assets/poi-icons/logos/asda.svg',
|
||||
'Asda Living': '/assets/poi-icons/logos/asda.svg',
|
||||
'Asda PFS': '/assets/poi-icons/logos/asda.svg',
|
||||
'Asda Supercentre': '/assets/poi-icons/logos/asda.svg',
|
||||
'Asda Supermarket': '/assets/poi-icons/logos/asda.svg',
|
||||
'Asda Superstore': '/assets/poi-icons/logos/asda.svg',
|
||||
Bakery: '/assets/twemoji/1f950.png',
|
||||
Booths: 'https://geolytix.github.io/MapIcons/brands/booths_24px.svg',
|
||||
Budgens: 'https://geolytix.github.io/MapIcons/brands/budgens_24px.svg',
|
||||
Booths: '/assets/poi-icons/brands_2024/booths.svg',
|
||||
Budgens: '/assets/poi-icons/brands_2024/budgens.svg',
|
||||
'Bus station': '/assets/twemoji/1f68c.png',
|
||||
'Bus stop': '/assets/twemoji/1f68f.png',
|
||||
'Butcher & Fishmonger': '/assets/twemoji/1f969.png',
|
||||
Centra: 'https://geolytix.github.io/MapIcons/brands/centra_24px.svg',
|
||||
'Co-op': 'https://geolytix.github.io/MapIcons/brands/coop_24px.svg',
|
||||
COOK: 'https://geolytix.github.io/MapIcons/brands/cook.svg',
|
||||
Centra: '/assets/poi-icons/logos/centra.svg',
|
||||
'Co-op': '/assets/poi-icons/logos/coop.svg',
|
||||
COOK: '/assets/poi-icons/brands_2024/cook.svg',
|
||||
'Convenience Store': '/assets/twemoji/1f3ea.png',
|
||||
Costco: 'https://geolytix.github.io/MapIcons/brands/costco_24px.svg',
|
||||
Costco: '/assets/poi-icons/brands/costco.svg',
|
||||
'Deli & Specialty': '/assets/twemoji/1f9c6.png',
|
||||
'Dunnes Stores': 'https://geolytix.github.io/MapIcons/brands/dunnes_stores_24px.svg',
|
||||
Farmfoods: 'https://geolytix.github.io/MapIcons/brands/farmfoods_updated_24px.svg',
|
||||
'Dunnes Stores': '/assets/poi-icons/brands_2024/dunnes_stores.svg',
|
||||
Farmfoods: '/assets/poi-icons/brands_2023/supermarkets/farmfoods.svg',
|
||||
Ferry: '/assets/twemoji/26f4.png',
|
||||
Greengrocer: '/assets/twemoji/1f96c.png',
|
||||
'Heron Foods': 'https://geolytix.github.io/MapIcons/brands/heron_24px.svg',
|
||||
Iceland: 'https://geolytix.github.io/MapIcons/brands/iceland_24px.svg',
|
||||
Lidl: 'https://geolytix.github.io/MapIcons/brands/lidl_24px.svg',
|
||||
Makro: 'https://geolytix.github.io/MapIcons/brands/makro_24px.svg',
|
||||
'M&S': 'https://geolytix.github.io/MapIcons/brands/mns_24px.svg',
|
||||
'M&S Clothing': 'https://geolytix.github.io/MapIcons/brands/mns_high_street_24px.svg',
|
||||
'M&S Food': 'https://geolytix.github.io/MapIcons/brands/mns_food_24px.svg',
|
||||
'M&S Hospital': 'https://geolytix.github.io/MapIcons/brands/mns_hospital_24px.svg',
|
||||
'M&S MSA': 'https://geolytix.github.io/MapIcons/brands/mns_moto_24px.svg',
|
||||
'M&S Outlet': 'https://geolytix.github.io/MapIcons/brands/mns_outlet_24px.svg',
|
||||
Morrisons: 'https://geolytix.github.io/MapIcons/brands/morrisons_24px.svg',
|
||||
'Morrisons Daily': 'https://geolytix.github.io/MapIcons/brands/morrisons_daily_24px.svg',
|
||||
'Heron Foods': '/assets/poi-icons/brands_2023/supermarkets/heron_foods.svg',
|
||||
Iceland: '/assets/poi-icons/logos/iceland.svg',
|
||||
Lidl: '/assets/poi-icons/logos/lidl.svg',
|
||||
Makro: '/assets/poi-icons/brands_2024/makro.svg',
|
||||
'M&S': '/assets/poi-icons/brands/mns.svg',
|
||||
'M&S Clothing': '/assets/poi-icons/brands/mns_high_street.svg',
|
||||
'M&S Food': '/assets/poi-icons/brands/mns_food.svg',
|
||||
'M&S Hospital': '/assets/poi-icons/brands/mns_hospital.svg',
|
||||
'M&S MSA': '/assets/poi-icons/brands/mns_moto.svg',
|
||||
'M&S Outlet': '/assets/poi-icons/brands/mns_outlet.svg',
|
||||
Morrisons: '/assets/poi-icons/logos/morrisons.svg',
|
||||
'Morrisons Daily': '/assets/poi-icons/brands_2024/morrisons_daily.svg',
|
||||
'Off-Licence': '/assets/twemoji/1f377.png',
|
||||
'Planet Organic': 'https://geolytix.github.io/MapIcons/logos/planet_organic_24px.svg',
|
||||
'Planet Organic': '/assets/poi-icons/logos/planet_organic.svg',
|
||||
'Rail station': '/assets/twemoji/1f686.png',
|
||||
"Sainsbury's": 'https://geolytix.github.io/MapIcons/brands/sainsburys_24px.svg',
|
||||
"Sainsbury's Local": 'https://geolytix.github.io/MapIcons/brands/sainsburys_local_24px.svg',
|
||||
Spar: 'https://geolytix.github.io/MapIcons/brands/spar_24px.svg',
|
||||
"Sainsbury's": '/assets/poi-icons/logos/sainsburys.svg',
|
||||
"Sainsbury's Local": '/assets/poi-icons/brands_2024/sainsburys_local.svg',
|
||||
Spar: '/assets/poi-icons/logos/spar.svg',
|
||||
Supermarket: '/assets/twemoji/1f6d2.png',
|
||||
Tesco: 'https://geolytix.github.io/MapIcons/brands/tesco_24px.svg',
|
||||
'Tesco Express': 'https://geolytix.github.io/MapIcons/brands/tesco_express_24px.svg',
|
||||
'Tesco Extra': 'https://geolytix.github.io/MapIcons/brands/tesco_extra_24px.svg',
|
||||
Tesco: '/assets/poi-icons/logos/tesco.svg',
|
||||
'Tesco Express': '/assets/poi-icons/logos/tesco_express.svg',
|
||||
'Tesco Extra': '/assets/poi-icons/logos/tesco_extra.svg',
|
||||
'Taxi rank': '/assets/twemoji/1f695.png',
|
||||
'The Food Warehouse': 'https://geolytix.github.io/MapIcons/brands/iceland_food_warehouse_24px.svg',
|
||||
'Tube station': 'https://geolytix.github.io/MapIcons/public_transport/london_tube.svg',
|
||||
Waitrose: 'https://geolytix.github.io/MapIcons/brands/waitrose_24px.svg',
|
||||
'Little Waitrose': 'https://geolytix.github.io/MapIcons/brands/little_waitrose_24px.svg',
|
||||
'Whole Foods Market': 'https://geolytix.github.io/MapIcons/brands/wholefoods_24px.svg',
|
||||
'The Food Warehouse': '/assets/poi-icons/logos/iceland.svg',
|
||||
'Tube station': '/assets/poi-icons/public_transport/london_tube.svg',
|
||||
Waitrose: '/assets/poi-icons/logos/waitrose.svg',
|
||||
'Little Waitrose': '/assets/poi-icons/brands/little_waitrose.svg',
|
||||
'Whole Foods Market': '/assets/poi-icons/brands_2024/wholefoods.svg',
|
||||
};
|
||||
|
||||
/** Categories only shown when zoomed in past MINOR_POI_ZOOM_THRESHOLD */
|
||||
|
|
|
|||
|
|
@ -62,8 +62,7 @@ function pointInPolygon(point: Point, polygon: Point[]): boolean {
|
|||
|
||||
if (current[1] > point[1] !== previous[1] > point[1]) {
|
||||
const x =
|
||||
((previous[0] - current[0]) * (point[1] - current[1])) /
|
||||
(previous[1] - current[1]) +
|
||||
((previous[0] - current[0]) * (point[1] - current[1])) / (previous[1] - current[1]) +
|
||||
current[0];
|
||||
if (point[0] < x) inside = !inside;
|
||||
}
|
||||
|
|
@ -92,9 +91,7 @@ export function hasMatchingHexagonAtResolution(
|
|||
hexagons: HexagonData[],
|
||||
resolution: number
|
||||
): boolean {
|
||||
return hexagons.some(
|
||||
(hexagon) => hexagon.count > 0 && getResolution(hexagon.h3) === resolution
|
||||
);
|
||||
return hexagons.some((hexagon) => hexagon.count > 0 && getResolution(hexagon.h3) === resolution);
|
||||
}
|
||||
|
||||
export function findOverlappingMatchingHexagon(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
import { existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
import {
|
||||
DENSITY_GRADIENT,
|
||||
ENUM_PALETTE,
|
||||
FEATURE_GRADIENT,
|
||||
POI_CATEGORY_LOGOS,
|
||||
SMALLEST_VISIBLE_HEXAGON_RESOLUTION,
|
||||
} from './consts';
|
||||
import {
|
||||
|
|
@ -52,12 +55,25 @@ describe('map utilities', () => {
|
|||
});
|
||||
|
||||
it('prefers POI category logos before falling back to emoji icons', () => {
|
||||
expect(getPoiIconUrl('Waitrose', '🛒')).toBe(
|
||||
'https://geolytix.github.io/MapIcons/brands/waitrose_24px.svg'
|
||||
expect(getPoiIconUrl('Waitrose', '🛒')).toBe('/assets/poi-icons/brands/waitrose_24px.svg');
|
||||
expect(getPoiIconUrl('Iceland', '🛒', 'The Food Warehouse')).toBe(
|
||||
'/assets/poi-icons/brands/iceland_food_warehouse_24px.svg'
|
||||
);
|
||||
expect(getPoiIconUrl("Sainsbury's", '🛒', undefined, 'Sainsburys Earlsfield Local')).toBe(
|
||||
'/assets/poi-icons/brands/sainsburys_local_24px.svg'
|
||||
);
|
||||
expect(getPoiIconUrl('Unknown category', '🛒')).toBe('/assets/twemoji/1f6d2.png');
|
||||
});
|
||||
|
||||
it('keeps POI icon URLs bundled locally', () => {
|
||||
expect(Object.values(POI_CATEGORY_LOGOS).filter((url) => /^https?:\/\//.test(url))).toEqual([]);
|
||||
expect(
|
||||
Object.values(POI_CATEGORY_LOGOS)
|
||||
.filter((url) => url.startsWith('/assets/poi-icons/'))
|
||||
.filter((url) => !existsSync(join(process.cwd(), 'public', url.slice(1))))
|
||||
).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns fallback, filtered, enum, feature, and density colors', () => {
|
||||
expect(
|
||||
getFeatureFillColor(
|
||||
|
|
|
|||
|
|
@ -241,7 +241,60 @@ export function emojiToTwemojiUrl(emoji: string): string {
|
|||
return `${TWEMOJI_BASE}${hex}.png`;
|
||||
}
|
||||
|
||||
export function getPoiIconUrl(category: string, emoji: string): string {
|
||||
function inferPoiIconCategory(category: string, name?: string): string | undefined {
|
||||
if (!name) return undefined;
|
||||
const text = `${category} ${name}`.toLowerCase();
|
||||
|
||||
switch (category) {
|
||||
case 'Asda':
|
||||
if (text.includes('asda express') || text.includes(' express')) return 'Asda Express';
|
||||
if (text.includes('asda living')) return 'Asda Living';
|
||||
if (text.includes('asda pfs') || /\bpfs\b/.test(text)) return 'Asda PFS';
|
||||
return undefined;
|
||||
case 'Iceland':
|
||||
return text.includes('food warehouse') ? 'The Food Warehouse' : undefined;
|
||||
case 'M&S':
|
||||
if (text.includes('hospital')) return 'M&S Hospital';
|
||||
if (text.includes('moto')) return 'M&S MSA';
|
||||
if (text.includes('outlet')) return 'M&S Outlet';
|
||||
if (
|
||||
text.includes('foodhall') ||
|
||||
text.includes('simply food') ||
|
||||
text.includes('food to go') ||
|
||||
text.includes(' bp') ||
|
||||
/\bsf\b/.test(text)
|
||||
) {
|
||||
return 'M&S Food';
|
||||
}
|
||||
if (text.includes('clothing')) return 'M&S Clothing';
|
||||
return undefined;
|
||||
case 'Morrisons':
|
||||
return text.includes('morrisons daily') || text.includes('morrisons dailly')
|
||||
? 'Morrisons Daily'
|
||||
: undefined;
|
||||
case "Sainsbury's":
|
||||
return text.includes('local') ? "Sainsbury's Local" : undefined;
|
||||
case 'Tesco':
|
||||
if (text.includes('tesco extra')) return 'Tesco Extra';
|
||||
if (text.includes('tesco express') || text.includes(' express')) return 'Tesco Express';
|
||||
return undefined;
|
||||
case 'Waitrose':
|
||||
return text.includes('little waitrose') ? 'Little Waitrose' : undefined;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export function getPoiIconUrl(
|
||||
category: string,
|
||||
emoji: string,
|
||||
iconCategory?: string,
|
||||
name?: string
|
||||
): string {
|
||||
const resolvedIconCategory = iconCategory || inferPoiIconCategory(category, name);
|
||||
if (resolvedIconCategory && POI_CATEGORY_LOGOS[resolvedIconCategory]) {
|
||||
return POI_CATEGORY_LOGOS[resolvedIconCategory];
|
||||
}
|
||||
return POI_CATEGORY_LOGOS[category] ?? emojiToTwemojiUrl(emoji);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import {
|
|||
import {
|
||||
SCHOOL_FILTER_NAME,
|
||||
createSchoolFilterKey,
|
||||
getSchoolBackendFeatureName,
|
||||
getSchoolFilterConfig,
|
||||
isSchoolFilterName,
|
||||
type SchoolDistance,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue