diff --git a/docs/api/context.md b/docs/api/context.md index a5644c0e..86aa73f1 100644 --- a/docs/api/context.md +++ b/docs/api/context.md @@ -46,7 +46,7 @@ const center = context.mapProvider.getCenter() context.mapProvider.setView({ zoom: 10 }) ``` -#### `mapProvider.registerPatterns(patternConfigs, mapStyleId, patternRegistry)` +#### `mapProvider.addPatternsToMap(patternConfigs, mapStyleId, patternRegistry)` Rasterises and registers pattern fill images with the map engine. Plugin layer adapters call this instead of importing provider internals directly, keeping cross-package boundaries clean. @@ -56,12 +56,12 @@ Rasterises and registers pattern fill images with the map engine. Plugin layer a ```js // In a plugin's MapLibre layer adapter -await mapProvider.registerPatterns(getPatternConfigs(datasets, patternRegistry), mapStyleId, patternRegistry) +await mapProvider.addPatternsToMap(getPatternConfigs(datasets, patternRegistry), mapStyleId, patternRegistry) ``` --- -#### `mapProvider.registerSymbols(symbolConfigs, mapStyleId, symbolRegistry)` +#### `mapProvider.addSymbolsToMap(symbolConfigs, mapStyleId, symbolRegistry)` Rasterises and registers symbol images with the map engine. Plugin layer adapters call this instead of importing provider internals directly, keeping cross-package boundaries clean. @@ -71,7 +71,7 @@ Rasterises and registers symbol images with the map engine. Plugin layer adapter ```js // In a plugin's MapLibre layer adapter -await mapProvider.registerSymbols(getSymbolConfigs(datasets), mapStyleId, symbolRegistry) +await mapProvider.addSymbolsToMap(getSymbolConfigs(datasets), mapStyleId, symbolRegistry) ``` --- diff --git a/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js b/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js index 961c6b64..dd1e4f8e 100644 --- a/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js +++ b/plugins/beta/datasets/src/adapters/maplibre/maplibreLayerAdapter.js @@ -16,7 +16,7 @@ import { scaleFactor } from '../../../../../../src/config/appConfig.js' * - Style-change recovery (re-adding layers after basemap swap) * * Symbol image rasterisation is delegated to the map provider via - * `mapProvider.registerSymbols()`, keeping this adapter free of provider internals. + * `mapProvider.addSymbolsToMap()`, keeping this adapter free of provider internals. */ export default class MaplibreLayerAdapter { /** @@ -47,8 +47,8 @@ export default class MaplibreLayerAdapter { const mapStyleId = mapStyle.id const pixelRatio = this._pixelRatio await Promise.all([ - this._mapProvider.registerPatterns(getPatternConfigs(datasets, this._patternRegistry), mapStyleId, this._patternRegistry), - this._mapProvider.registerSymbols(getSymbolConfigs(datasets), mapStyle, this._symbolRegistry) + this._mapProvider.addPatternsToMap(getPatternConfigs(datasets, this._patternRegistry), mapStyleId, this._patternRegistry), + this._mapProvider.addSymbolsToMap(getSymbolConfigs(datasets), mapStyle, this._symbolRegistry) ]) this._symbolLayerIds.clear() datasets.forEach(dataset => this._addLayers(dataset, mapStyle, pixelRatio)) @@ -92,8 +92,8 @@ export default class MaplibreLayerAdapter { const newStyleId = newMapStyle.id const pixelRatio = this._pixelRatio await Promise.all([ - this._mapProvider.registerPatterns(getPatternConfigs(datasets, this._patternRegistry), newStyleId, this._patternRegistry), - this._mapProvider.registerSymbols(getSymbolConfigs(datasets), newMapStyle, this._symbolRegistry) + this._mapProvider.addPatternsToMap(getPatternConfigs(datasets, this._patternRegistry), newStyleId, this._patternRegistry), + this._mapProvider.addSymbolsToMap(getSymbolConfigs(datasets), newMapStyle, this._symbolRegistry) ]) this._symbolLayerIds.clear() datasets.forEach(dataset => this._addLayers(dataset, newMapStyle, pixelRatio)) @@ -121,8 +121,8 @@ export default class MaplibreLayerAdapter { async onSizeChange (datasets, mapStyle) { const pixelRatio = this._pixelRatio await Promise.all([ - this._mapProvider.registerSymbols(getSymbolConfigs(datasets), mapStyle, this._symbolRegistry), - this._mapProvider.registerPatterns(getPatternConfigs(datasets, this._patternRegistry), mapStyle.id, this._patternRegistry) + this._mapProvider.addSymbolsToMap(getSymbolConfigs(datasets), mapStyle, this._symbolRegistry), + this._mapProvider.addPatternsToMap(getPatternConfigs(datasets, this._patternRegistry), mapStyle.id, this._patternRegistry) ]) datasets.forEach(dataset => { getAllLayerIds(dataset).forEach(layerId => { @@ -279,8 +279,8 @@ export default class MaplibreLayerAdapter { this._symbolLayerIds.delete(layerId) }) await Promise.all([ - this._mapProvider.registerPatterns(getPatternConfigs([dataset], this._patternRegistry), mapStyleId, this._patternRegistry), - this._mapProvider.registerSymbols(getSymbolConfigs([dataset]), mapStyle, this._symbolRegistry) + this._mapProvider.addPatternsToMap(getPatternConfigs([dataset], this._patternRegistry), mapStyleId, this._patternRegistry), + this._mapProvider.addSymbolsToMap(getSymbolConfigs([dataset]), mapStyle, this._symbolRegistry) ]) this._addLayers(dataset, mapStyle, pixelRatio) } @@ -307,8 +307,8 @@ export default class MaplibreLayerAdapter { return } await Promise.all([ - this._mapProvider.registerPatterns(getPatternConfigs([dataset], this._patternRegistry), mapStyleId, this._patternRegistry), - this._mapProvider.registerSymbols(getSymbolConfigs([dataset]), mapStyle, this._symbolRegistry) + this._mapProvider.addPatternsToMap(getPatternConfigs([dataset], this._patternRegistry), mapStyleId, this._patternRegistry), + this._mapProvider.addSymbolsToMap(getSymbolConfigs([dataset]), mapStyle, this._symbolRegistry) ]) const sourceId = this._datasetSourceMap.get(dataset.id) const sourceLayer = dataset.tiles?.length ? dataset.sourceLayer : undefined diff --git a/plugins/beta/datasets/src/adapters/maplibre/patternImages.js b/plugins/beta/datasets/src/adapters/maplibre/patternImages.js index aab59610..4948c0bb 100644 --- a/plugins/beta/datasets/src/adapters/maplibre/patternImages.js +++ b/plugins/beta/datasets/src/adapters/maplibre/patternImages.js @@ -6,7 +6,7 @@ export { hasPattern, getPatternInnerContent, getPatternImageId, getKeyPatternPat /** * Returns a flat list of datasets and merged sublayers that require pattern images. - * Handles sublayer merging so callers (e.g. mapProvider.registerPatterns) receive ready-to-use configs. + * Handles sublayer merging so callers (e.g. mapProvider.addPatternsToMap) receive ready-to-use configs. * * @param {Object[]} datasets * @param {Object} patternRegistry diff --git a/plugins/beta/datasets/src/adapters/maplibre/symbolImages.js b/plugins/beta/datasets/src/adapters/maplibre/symbolImages.js index 5491f4ed..f0ffe90b 100644 --- a/plugins/beta/datasets/src/adapters/maplibre/symbolImages.js +++ b/plugins/beta/datasets/src/adapters/maplibre/symbolImages.js @@ -11,7 +11,7 @@ export { anchorToMaplibre, getSymbolImageId } from '../../../../../../providers/ /** * Returns a flat list of datasets and merged sublayers that require symbol images. - * Handles sublayer merging so callers (e.g. mapProvider.registerSymbols) receive ready-to-use configs. + * Handles sublayer merging so callers (e.g. mapProvider.addSymbolsToMap) receive ready-to-use configs. * * @param {Object[]} datasets * @returns {Object[]} diff --git a/providers/maplibre/src/maplibreProvider.js b/providers/maplibre/src/maplibreProvider.js index 0792bd06..d2995f41 100755 --- a/providers/maplibre/src/maplibreProvider.js +++ b/providers/maplibre/src/maplibreProvider.js @@ -13,8 +13,8 @@ import { createMapLabelNavigator } from './utils/labels.js' import { updateHighlightedFeatures } from './utils/highlightFeatures.js' import { queryFeatures } from './utils/queryFeatures.js' import { setupHoverCursor } from './utils/hoverCursor.js' -import { registerSymbols } from './utils/symbolImages.js' -import { registerPatterns } from './utils/patternImages.js' +import { addSymbolsToMap } from './utils/symbolImages.js' +import { addPatternsToMap } from './utils/patternImages.js' /** * MapLibre GL JS implementation of the MapProvider interface. @@ -316,9 +316,9 @@ export default class MapLibreProvider { * @param {Object} symbolRegistry * @returns {Promise} */ - async registerSymbols (symbolConfigs, mapStyle, symbolRegistry) { + async addSymbolsToMap (symbolConfigs, mapStyle, symbolRegistry) { const pixelRatio = (this.map.getPixelRatio() || 1) * (scaleFactor[this.mapSize] || 1) - return registerSymbols(this.map, symbolConfigs, mapStyle, symbolRegistry, pixelRatio) + return addSymbolsToMap(this.map, symbolConfigs, mapStyle, symbolRegistry, pixelRatio) } /** @@ -332,9 +332,9 @@ export default class MapLibreProvider { * @param {Object} patternRegistry * @returns {Promise} */ - async registerPatterns (patternConfigs, mapStyleId, patternRegistry) { + async addPatternsToMap (patternConfigs, mapStyleId, patternRegistry) { const pixelRatio = (this.map.getPixelRatio() || 1) * (scaleFactor[this.mapSize] || 1) - return registerPatterns(this.map, patternConfigs, mapStyleId, patternRegistry, pixelRatio) + return addPatternsToMap(this.map, patternConfigs, mapStyleId, patternRegistry, pixelRatio) } // ========================== diff --git a/providers/maplibre/src/maplibreProvider.test.js b/providers/maplibre/src/maplibreProvider.test.js index 67ee59c6..6ec52f01 100644 --- a/providers/maplibre/src/maplibreProvider.test.js +++ b/providers/maplibre/src/maplibreProvider.test.js @@ -4,8 +4,8 @@ import { attachAppEvents } from './appEvents.js' import { createMapLabelNavigator } from './utils/labels.js' import { updateHighlightedFeatures } from './utils/highlightFeatures.js' import { queryFeatures } from './utils/queryFeatures.js' -import { registerSymbols } from './utils/symbolImages.js' -import { registerPatterns } from './utils/patternImages.js' +import { addSymbolsToMap } from './utils/symbolImages.js' +import { addPatternsToMap } from './utils/patternImages.js' import { getAreaDimensions, getCardinalMove, getResolution, getPaddedBounds, isGeometryObscured } from './utils/spatial.js' jest.mock('./defaults.js', () => ({ @@ -35,8 +35,8 @@ jest.mock('./utils/labels.js', () => ({ })) jest.mock('./utils/highlightFeatures.js', () => ({ updateHighlightedFeatures: jest.fn(() => []) })) jest.mock('./utils/queryFeatures.js', () => ({ queryFeatures: jest.fn(() => []) })) -jest.mock('./utils/symbolImages.js', () => ({ registerSymbols: jest.fn(() => Promise.resolve()) })) -jest.mock('./utils/patternImages.js', () => ({ registerPatterns: jest.fn(() => Promise.resolve()) })) +jest.mock('./utils/symbolImages.js', () => ({ addSymbolsToMap: jest.fn(() => Promise.resolve()) })) +jest.mock('./utils/patternImages.js', () => ({ addPatternsToMap: jest.fn(() => Promise.resolve()) })) describe('MapLibreProvider', () => { let map, eventBus, maplibreModule, loadCallback @@ -250,63 +250,63 @@ describe('MapLibreProvider', () => { }) }) - test('registerSymbols delegates to utility with map instance', async () => { + test('addSymbolsToMap delegates to utility with map instance', async () => { const p = makeProvider() await doInitMap(p) const configs = [{ symbol: 'pin' }] const mapStyle = { id: 'test', selectedColor: '#0b0c0c' } const registry = {} - await p.registerSymbols(configs, mapStyle, registry) - expect(registerSymbols).toHaveBeenCalledWith(map, configs, mapStyle, registry, expect.any(Number)) + await p.addSymbolsToMap(configs, mapStyle, registry) + expect(addSymbolsToMap).toHaveBeenCalledWith(map, configs, mapStyle, registry, expect.any(Number)) }) - test('registerSymbols computes pixelRatio from getPixelRatio and mapSize scale factor', async () => { + test('addSymbolsToMap computes pixelRatio from getPixelRatio and mapSize scale factor', async () => { const p = makeProvider() await doInitMap(p) map.getPixelRatio.mockReturnValue(2) p.mapSize = 'medium' // scaleFactor['medium'] = 1.5 const registry = {} - await p.registerSymbols([], { id: 'test' }, registry) - expect(registerSymbols).toHaveBeenCalledWith(map, [], { id: 'test' }, registry, 3) // 2 * 1.5 + await p.addSymbolsToMap([], { id: 'test' }, registry) + expect(addSymbolsToMap).toHaveBeenCalledWith(map, [], { id: 'test' }, registry, 3) // 2 * 1.5 }) - test('registerSymbols falls back to pixelRatio 1 when getPixelRatio returns 0', async () => { + test('addSymbolsToMap falls back to pixelRatio 1 when getPixelRatio returns 0', async () => { const p = makeProvider() await doInitMap(p) map.getPixelRatio.mockReturnValue(0) p.mapSize = 'small' // scaleFactor['small'] = 1 const registry = {} - await p.registerSymbols([], { id: 'test' }, registry) - expect(registerSymbols).toHaveBeenCalledWith(map, [], { id: 'test' }, registry, 1) // (0 || 1) * 1 + await p.addSymbolsToMap([], { id: 'test' }, registry) + expect(addSymbolsToMap).toHaveBeenCalledWith(map, [], { id: 'test' }, registry, 1) // (0 || 1) * 1 }) - test('registerPatterns delegates to utility with map instance and pixelRatio', async () => { + test('addPatternsToMap delegates to utility with map instance and pixelRatio', async () => { const p = makeProvider() await doInitMap(p) const configs = [{ fillPattern: 'dot' }] const registry = {} - await p.registerPatterns(configs, 'test', registry) - expect(registerPatterns).toHaveBeenCalledWith(map, configs, 'test', registry, 1) // getPixelRatio()=1, mapSize unset → 1*1 + await p.addPatternsToMap(configs, 'test', registry) + expect(addPatternsToMap).toHaveBeenCalledWith(map, configs, 'test', registry, 1) // getPixelRatio()=1, mapSize unset → 1*1 }) - test('registerPatterns computes pixelRatio from getPixelRatio and mapSize scale factor', async () => { + test('addPatternsToMap computes pixelRatio from getPixelRatio and mapSize scale factor', async () => { const p = makeProvider() await doInitMap(p) map.getPixelRatio.mockReturnValue(2) p.mapSize = 'medium' // scaleFactor['medium'] = 1.5 const registry = {} - await p.registerPatterns([], 'test', registry) - expect(registerPatterns).toHaveBeenCalledWith(map, [], 'test', registry, 3) // 2 * 1.5 + await p.addPatternsToMap([], 'test', registry) + expect(addPatternsToMap).toHaveBeenCalledWith(map, [], 'test', registry, 3) // 2 * 1.5 }) - test('registerPatterns falls back to pixelRatio 1 when getPixelRatio returns 0', async () => { + test('addPatternsToMap falls back to pixelRatio 1 when getPixelRatio returns 0', async () => { const p = makeProvider() await doInitMap(p) map.getPixelRatio.mockReturnValue(0) p.mapSize = 'small' // scaleFactor['small'] = 1 const registry = {} - await p.registerPatterns([], 'test', registry) - expect(registerPatterns).toHaveBeenCalledWith(map, [], 'test', registry, 1) // (0 || 1) * 1 + await p.addPatternsToMap([], 'test', registry) + expect(addPatternsToMap).toHaveBeenCalledWith(map, [], 'test', registry, 1) // (0 || 1) * 1 }) describe('setHoverCursor', () => { diff --git a/providers/maplibre/src/utils/patternImages.js b/providers/maplibre/src/utils/patternImages.js index f08f44bb..490224e2 100644 --- a/providers/maplibre/src/utils/patternImages.js +++ b/providers/maplibre/src/utils/patternImages.js @@ -51,19 +51,19 @@ const rasterisePattern = async (dataset, mapStyleId, patternRegistry, pixelRatio * (see `getPatternConfigs` in the datasets plugin adapter). * * @param {Object} map - MapLibre map instance - * @param {Object[]} patternConfigs - Flat list of datasets/merged-sublayers with a pattern config + * @param {Object[]} styleArray - Flat list of datasets/merged-sublayers with a pattern config * @param {string} mapStyleId * @param {Object} patternRegistry * @param {number} pixelRatio * @returns {Promise} */ -export const registerPatterns = async (map, patternConfigs, mapStyleId, patternRegistry, pixelRatio) => { - if (!patternConfigs.length) { +export const addPatternsToMap = async (map, styleArray, mapStyleId, patternRegistry, pixelRatio) => { + if (!styleArray.length) { return } const effectiveRatio = Math.max(PATTERN_MIN_PIXEL_RATIO, pixelRatio) - await Promise.all(patternConfigs.map(async (config) => { + await Promise.all(styleArray.map(async (config) => { const imageId = getPatternImageId(config, mapStyleId, patternRegistry, pixelRatio) if (!imageId || map.hasImage(imageId)) { return diff --git a/providers/maplibre/src/utils/patternImages.test.js b/providers/maplibre/src/utils/patternImages.test.js index 7995e366..d816272a 100644 --- a/providers/maplibre/src/utils/patternImages.test.js +++ b/providers/maplibre/src/utils/patternImages.test.js @@ -1,4 +1,4 @@ -import { registerPatterns } from './patternImages.js' +import { addPatternsToMap } from './patternImages.js' const OUTDOOR = 'outdoor' @@ -34,13 +34,13 @@ const makePatternRegistry = (id = 'stripes', content = SVG_CONTENT) => ({ get: jest.fn((name) => name === id ? { svgContent: content } : undefined) }) -// ─── registerPatterns ───────────────────────────────────────────────────────── +// ─── addPatternsToMap ───────────────────────────────────────────────────────── -describe('registerPatterns — registration', () => { +describe('addPatternsToMap — registration', () => { it('returns early and does not touch map for empty configs', async () => { const map = makeMap() const registry = makePatternRegistry() - await registerPatterns(map, [], OUTDOOR, registry) + await addPatternsToMap(map, [], OUTDOOR, registry) expect(map.hasImage).not.toHaveBeenCalled() expect(map.addImage).not.toHaveBeenCalled() }) @@ -49,7 +49,7 @@ describe('registerPatterns — registration', () => { const map = makeMap() const registry = makePatternRegistry() const config = { fillPatternSvgContent: SVG_CONTENT } - await registerPatterns(map, [config], OUTDOOR, registry) + await addPatternsToMap(map, [config], OUTDOOR, registry) expect(map.addImage).toHaveBeenCalledTimes(1) }) @@ -60,21 +60,21 @@ describe('registerPatterns — registration', () => { const { getPatternImageId } = await import('../../../../src/utils/patternUtils.js') const existingId = getPatternImageId(config, OUTDOOR, registry, pixelRatio) const map = makeMap([existingId]) - await registerPatterns(map, [config], OUTDOOR, registry, pixelRatio) + await addPatternsToMap(map, [config], OUTDOOR, registry, pixelRatio) expect(map.addImage).not.toHaveBeenCalled() }) it('skips config when pattern has no inner content', async () => { const map = makeMap() const emptyRegistry = { get: jest.fn(() => undefined) } - await registerPatterns(map, [{ fillPattern: 'unknown' }], OUTDOOR, emptyRegistry) + await addPatternsToMap(map, [{ fillPattern: 'unknown' }], OUTDOOR, emptyRegistry) expect(map.addImage).not.toHaveBeenCalled() }) it('skips config when neither fillPattern nor fillPatternSvgContent is set', async () => { const map = makeMap() const registry = makePatternRegistry() - await registerPatterns(map, [{ fillColor: '#ff0000' }], OUTDOOR, registry) + await addPatternsToMap(map, [{ fillColor: '#ff0000' }], OUTDOOR, registry) expect(map.addImage).not.toHaveBeenCalled() }) @@ -87,17 +87,17 @@ describe('registerPatterns — registration', () => { return undefined }) } - await registerPatterns(map, [{ fillPattern: 'stripes' }, { fillPattern: 'dots' }], OUTDOOR, registry) + await addPatternsToMap(map, [{ fillPattern: 'stripes' }, { fillPattern: 'dots' }], OUTDOOR, registry) expect(map.addImage).toHaveBeenCalledTimes(2) }) }) -describe('registerPatterns — pixel ratio', () => { +describe('addPatternsToMap — pixel ratio', () => { it('encodes effectiveRatio in the image ID and passes it to addImage', async () => { const map = makeMap() const registry = makePatternRegistry() const config = { fillPattern: 'stripes' } - await registerPatterns(map, [config], OUTDOOR, registry, 2) + await addPatternsToMap(map, [config], OUTDOOR, registry, 2) expect(map.addImage).toHaveBeenCalledTimes(1) expect(map.addImage).toHaveBeenCalledWith( expect.stringMatching(/^pattern-[a-z0-9]+-2x$/), @@ -110,7 +110,7 @@ describe('registerPatterns — pixel ratio', () => { const map = makeMap() const registry = makePatternRegistry() const config = { fillPattern: 'stripes' } - await registerPatterns(map, [config], OUTDOOR, registry, 1) + await addPatternsToMap(map, [config], OUTDOOR, registry, 1) expect(map.addImage).toHaveBeenCalledWith( expect.stringMatching(/-2x$/), expect.any(Object), @@ -124,8 +124,8 @@ describe('registerPatterns — pixel ratio', () => { const registry = makePatternRegistry() const config = { fillPattern: 'stripes' } const hiDpi = 3 - await registerPatterns(map1, [config], OUTDOOR, registry, 2) - await registerPatterns(map2, [config], OUTDOOR, registry, hiDpi) + await addPatternsToMap(map1, [config], OUTDOOR, registry, 2) + await addPatternsToMap(map2, [config], OUTDOOR, registry, hiDpi) const [id2x] = map1.addImage.mock.calls[0] const [id3x] = map2.addImage.mock.calls[0] expect(id2x).not.toBe(id3x) @@ -134,12 +134,12 @@ describe('registerPatterns — pixel ratio', () => { }) }) -describe('registerPatterns — color resolution and caching', () => { +describe('addPatternsToMap — color resolution and caching', () => { it('applies foreground and background colors when resolving the SVG', async () => { const map = makeMap() const registry = makePatternRegistry() const getContextSpy = HTMLCanvasElement.prototype.getContext - await registerPatterns( + await addPatternsToMap( map, [{ fillPattern: 'stripes', fillPatternForegroundColor: '#aabbcc', fillPatternBackgroundColor: '#112233' }], OUTDOOR, @@ -156,9 +156,9 @@ describe('registerPatterns — color resolution and caching', () => { fillPattern: 'stripes', fillPatternForegroundColor: { outdoor: '#aabbcc', dark: '#112233' } } - await registerPatterns(map, [config], OUTDOOR, registry) + await addPatternsToMap(map, [config], OUTDOOR, registry) const map2 = makeMap() - await registerPatterns(map2, [config], 'dark', registry) + await addPatternsToMap(map2, [config], 'dark', registry) const [idOutdoor] = map.addImage.mock.calls[0] const [idDark] = map2.addImage.mock.calls[0] expect(idOutdoor).not.toBe(idDark) @@ -169,18 +169,18 @@ describe('registerPatterns — color resolution and caching', () => { const registry = makePatternRegistry() const config = { fillPattern: 'stripes', fillPatternForegroundColor: '#unique2' } const pixelRatio = 2 - await registerPatterns(map, [config], OUTDOOR, registry, pixelRatio) + await addPatternsToMap(map, [config], OUTDOOR, registry, pixelRatio) const { getPatternImageId } = await import('../../../../src/utils/patternUtils.js') const imageId = getPatternImageId(config, OUTDOOR, registry, pixelRatio) const map2 = makeMap([imageId]) - await registerPatterns(map2, [config], OUTDOOR, registry, pixelRatio) + await addPatternsToMap(map2, [config], OUTDOOR, registry, pixelRatio) expect(map2.addImage).not.toHaveBeenCalled() }) }) -describe('registerPatterns — null results', () => { +describe('addPatternsToMap — null results', () => { it('does not call addImage when innerContent becomes unavailable inside rasterisePattern', async () => { - // registry.get returns content on the first call (for getPatternImageId in registerPatterns) + // registry.get returns content on the first call (for getPatternImageId in addPatternsToMap) // but undefined on the second call (for getPatternInnerContent inside rasterisePattern) const registry = { get: jest.fn() @@ -188,13 +188,13 @@ describe('registerPatterns — null results', () => { .mockReturnValueOnce(undefined) } const map = makeMap() - await registerPatterns(map, [{ fillPattern: 'stripes' }], OUTDOOR, registry) + await addPatternsToMap(map, [{ fillPattern: 'stripes' }], OUTDOOR, registry) expect(map.addImage).not.toHaveBeenCalled() }) it('does not call addImage when imageId becomes unavailable inside rasterisePattern', async () => { // Three consecutive calls to registry.get: - // 1. getPatternImageId in registerPatterns → returns content → imageId is truthy + // 1. getPatternImageId in addPatternsToMap → returns content → imageId is truthy // 2. getPatternInnerContent directly in rasterisePattern → returns content → passes innerContent guard // 3. getPatternInnerContent inside getPatternImageId in rasterisePattern → returns undefined // → getPatternImageId returns null → hits the imageId null guard @@ -205,7 +205,7 @@ describe('registerPatterns — null results', () => { .mockReturnValueOnce(undefined) } const map = makeMap() - await registerPatterns(map, [{ fillPattern: 'stripes' }], OUTDOOR, registry) + await addPatternsToMap(map, [{ fillPattern: 'stripes' }], OUTDOOR, registry) expect(map.addImage).not.toHaveBeenCalled() }) }) diff --git a/providers/maplibre/src/utils/symbolImages.js b/providers/maplibre/src/utils/symbolImages.js index d7f5d59a..2d9e8357 100644 --- a/providers/maplibre/src/utils/symbolImages.js +++ b/providers/maplibre/src/utils/symbolImages.js @@ -113,21 +113,21 @@ const rasteriseSymbolImage = async (dataset, mapStyle, symbolRegistry, selected, * (see `getSymbolConfigs` in the datasets plugin adapter). * * @param {Object} map - MapLibre map instance - * @param {Object[]} symbolConfigs - Flat list of datasets/merged-sublayers that have a symbol config + * @param {Object[]} styleArray - Flat list of datasets/merged-sublayers that have a symbol config * @param {Object} mapStyle - Current map style config (provides id, selectedColor, haloColor) * @param {Object} symbolRegistry * @param {number} [pixelRatio=2] - Device pixel ratio × map size scale factor (computed by caller) * @returns {Promise} */ -export const registerSymbols = async (map, symbolConfigs, mapStyle, symbolRegistry, pixelRatio = 2) => { - if (!symbolConfigs.length) { +export const addSymbolsToMap = async (map, styleArray, mapStyle, symbolRegistry, pixelRatio = 2) => { + if (!styleArray.length) { return } // Reset the normal→selected image ID lookup so stale entries don't persist after a style change map._symbolImageMap = {} - await Promise.all(symbolConfigs.flatMap(config => { + await Promise.all(styleArray.flatMap(config => { const normalId = getSymbolImageId(config, mapStyle, symbolRegistry, false, pixelRatio) const selectedId = getSymbolImageId(config, mapStyle, symbolRegistry, true, pixelRatio) if (normalId && selectedId) { diff --git a/providers/maplibre/src/utils/symbolImages.test.js b/providers/maplibre/src/utils/symbolImages.test.js index b89bc5e7..8e64eddc 100644 --- a/providers/maplibre/src/utils/symbolImages.test.js +++ b/providers/maplibre/src/utils/symbolImages.test.js @@ -1,4 +1,4 @@ -import { anchorToMaplibre, getSymbolImageId, registerSymbols } from './symbolImages.js' +import { anchorToMaplibre, getSymbolImageId, addSymbolsToMap } from './symbolImages.js' import { symbolRegistry } from '../../../../src/services/symbolRegistry.js' const STYLE_ID = 'test' @@ -145,7 +145,7 @@ describe('getSymbolImageId', () => { }) }) -// ─── registerSymbols ────────────────────────────────────────────────────────── +// ─── addSymbolsToMap ────────────────────────────────────────────────────────── const makeMap = (existingIds = []) => ({ _symbolImageMap: {}, @@ -153,10 +153,10 @@ const makeMap = (existingIds = []) => ({ addImage: jest.fn() }) -describe('registerSymbols — registration', () => { +describe('addSymbolsToMap — registration', () => { it('returns early and does not touch map for empty configs', async () => { const map = makeMap() - await registerSymbols(map, [], mapStyle, symbolRegistry) + await addSymbolsToMap(map, [], mapStyle, symbolRegistry) expect(map.hasImage).not.toHaveBeenCalled() expect(map.addImage).not.toHaveBeenCalled() }) @@ -164,13 +164,13 @@ describe('registerSymbols — registration', () => { it('resets _symbolImageMap before processing', async () => { const map = makeMap() map._symbolImageMap = { stale: 'entry' } - await registerSymbols(map, [{ symbol: 'pin' }], mapStyle, symbolRegistry) + await addSymbolsToMap(map, [{ symbol: 'pin' }], mapStyle, symbolRegistry) expect(map._symbolImageMap).not.toHaveProperty('stale') }) it('calls addImage for normal and selected variants', async () => { const map = makeMap() - await registerSymbols(map, [{ symbol: 'pin' }], mapStyle, symbolRegistry) + await addSymbolsToMap(map, [{ symbol: 'pin' }], mapStyle, symbolRegistry) expect(map.addImage).toHaveBeenCalledTimes(2) expect(map.addImage).toHaveBeenCalledWith(expect.stringMatching(/^symbol-[a-z0-9]+-\d+(\.\d+)?x$/), expect.any(Object), { pixelRatio: 2 }) expect(map.addImage).toHaveBeenCalledWith(expect.stringMatching(/^symbol-sel-[a-z0-9]+-\d+(\.\d+)?x$/), expect.any(Object), { pixelRatio: 2 }) @@ -178,7 +178,7 @@ describe('registerSymbols — registration', () => { it('populates _symbolImageMap with normal → selected id pairs', async () => { const map = makeMap() - await registerSymbols(map, [{ symbol: 'pin' }], mapStyle, symbolRegistry) + await addSymbolsToMap(map, [{ symbol: 'pin' }], mapStyle, symbolRegistry) const normalId = getSymbolImageId({ symbol: 'pin' }, mapStyle, symbolRegistry, false) const selectedId = getSymbolImageId({ symbol: 'pin' }, mapStyle, symbolRegistry, true) expect(map._symbolImageMap[normalId]).toBe(selectedId) @@ -188,19 +188,19 @@ describe('registerSymbols — registration', () => { const normalId = getSymbolImageId({ symbol: 'circle' }, mapStyle, symbolRegistry, false) const selectedId = getSymbolImageId({ symbol: 'circle' }, mapStyle, symbolRegistry, true) const map = makeMap([normalId, selectedId]) - await registerSymbols(map, [{ symbol: 'circle' }], mapStyle, symbolRegistry) + await addSymbolsToMap(map, [{ symbol: 'circle' }], mapStyle, symbolRegistry) expect(map.addImage).not.toHaveBeenCalled() }) it('processes multiple configs independently', async () => { const map = makeMap() - await registerSymbols(map, [{ symbol: 'pin' }, { symbol: 'circle' }], mapStyle, symbolRegistry) + await addSymbolsToMap(map, [{ symbol: 'pin' }, { symbol: 'circle' }], mapStyle, symbolRegistry) expect(map.addImage).toHaveBeenCalledTimes(4) expect(Object.keys(map._symbolImageMap)).toHaveLength(2) }) }) -describe('registerSymbols — null results and caching', () => { +describe('addSymbolsToMap — null results and caching', () => { it('does not call addImage when rasteriseSymbolImage returns null', async () => { // getSymbolImageId (called twice — normal + selected) needs a real symbolDef to produce imageIds, // but rasteriseSymbolImage must get undefined from getSymbolDef so it returns null. @@ -213,14 +213,14 @@ describe('registerSymbols — null results and caching', () => { .mockReturnValueOnce(undefined) .mockReturnValueOnce(undefined) const map = makeMap() - await registerSymbols(map, [{ symbol: 'pin' }], mapStyle, symbolRegistry) + await addSymbolsToMap(map, [{ symbol: 'pin' }], mapStyle, symbolRegistry) expect(map.addImage).not.toHaveBeenCalled() getSpy.mockRestore() }) it('skips config when symbolDef cannot be resolved', async () => { const map = makeMap() - await registerSymbols(map, [{ symbol: 'no-such-symbol' }], mapStyle, symbolRegistry) + await addSymbolsToMap(map, [{ symbol: 'no-such-symbol' }], mapStyle, symbolRegistry) expect(map.addImage).not.toHaveBeenCalled() expect(map._symbolImageMap).toEqual({}) }) @@ -231,14 +231,14 @@ describe('registerSymbols — null results and caching', () => { const map1 = makeMap() const getContextCallsBefore = HTMLCanvasElement.prototype.getContext.mock.calls.length - await registerSymbols(map1, [{ symbol: 'pin' }], mapStyle, symbolRegistry, uniqueRatio) + await addSymbolsToMap(map1, [{ symbol: 'pin' }], mapStyle, symbolRegistry, uniqueRatio) const getContextCallsAfterFirst = HTMLCanvasElement.prototype.getContext.mock.calls.length // Rasterisation ran — canvas was used expect(getContextCallsAfterFirst).toBeGreaterThan(getContextCallsBefore) // Second call with a fresh map (hasImage → false) but same ratio → cache hit const map2 = makeMap() - await registerSymbols(map2, [{ symbol: 'pin' }], mapStyle, symbolRegistry, uniqueRatio) + await addSymbolsToMap(map2, [{ symbol: 'pin' }], mapStyle, symbolRegistry, uniqueRatio) const getContextCallsAfterSecond = HTMLCanvasElement.prototype.getContext.mock.calls.length // No new canvas — rasterisation was skipped via cache expect(getContextCallsAfterSecond).toBe(getContextCallsAfterFirst)