Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.

## 2026-07

* Update to [Maplibre GL JS 6.0](https://github.com/maplibre/maplibre-gl-js/releases/tag/v6.0.0)
* Performance improvements for large maps
* Option to delete items from context menu

Expand Down
5 changes: 5 additions & 0 deletions app/javascript/controllers/feature/modal_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ export default class extends Controller {
dom.showElements(['#feature-desc-section', '#feature-desc'])
// https://github.com/Ionaru/easy-markdown-editor
await import('easymde') // import EasyMDE UMD bundle
// EasyMDE defaults to a broken font-awesome build from bootstrapcdn; load a working one ourselves
// (v4-shims maps EasyMDE's old "fa fa-*" classes to FA6 icons)
dom.loadStylesheet('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css')
dom.loadStylesheet('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/v4-shims.min.css')
if (easyMDE) { easyMDE.toTextArea() }
document.querySelector('#feature-desc-input').value = this.getSelectedFeature().properties.desc || ''
easyMDE = new window.EasyMDE({
Expand All @@ -303,6 +307,7 @@ export default class extends Controller {
toolbar: ["bold", "italic", "heading", "code", "table", "|", "unordered-list", "horizontal-rule", "|", "link", "image", "preview"],
minHeight: '4em',
spellChecker: false,
autoDownloadFontAwesome: false,
status: [{
className: 'autosave',
onUpdate: () => { this.updateDesc() }
Expand Down
5 changes: 5 additions & 0 deletions app/javascript/controllers/map/settings_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,17 @@ export default class extends Controller {
dom.showElements(['#map-description'])

await import('easymde') // import EasyMDE UMD bundle
// EasyMDE defaults to a broken font-awesome build from bootstrapcdn; load a working one ourselves
// (v4-shims maps EasyMDE's old "fa fa-*" classes to FA6 icons)
dom.loadStylesheet('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css')
dom.loadStylesheet('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/v4-shims.min.css')
descEasyMDE = new window.EasyMDE({
element: document.getElementById('map-description-input'),
placeholder: 'Add a description text',
toolbar: ["bold", "italic", "heading", "code", "table", "|", "unordered-list", "horizontal-rule", "|", "link", "image", "preview"],
minHeight: '4em',
spellChecker: false,
autoDownloadFontAwesome: false,
status: [{
className: 'autosave',
onUpdate: () => { this.updateDescription() }
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/deck.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { hexToRgb } from 'helpers/functions'
import { mapProperties, initializeMaplibreProperties } from 'maplibre/map'
import maplibregl from 'maplibre-gl'
import * as maplibregl from 'maplibre-gl'

// eslint expects variables to get imported, but we load the full lib in header
const deck = window.deck;
Expand Down
8 changes: 8 additions & 0 deletions app/javascript/helpers/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ export function scrollToId(elementId) {
}
}

export function loadStylesheet (href) {
if (document.querySelector(`link[href="${href}"]`)) return
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = href
document.head.appendChild(link)
}

export function isInputElement(target) {
return target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.tagName === 'SELECT' || target.isContentEditable
}
2 changes: 1 addition & 1 deletion app/javascript/maplibre/controls/geolocate.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as functions from 'helpers/functions'
import { status } from 'helpers/status'
import maplibregl from 'maplibre-gl'
import * as maplibregl from 'maplibre-gl'
import { map, mapProperties } from 'maplibre/map'

let isInFollowMode = false
Expand Down
10 changes: 4 additions & 6 deletions app/javascript/maplibre/controls/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as dom from 'helpers/dom'
import { animateElement, initTooltips } from 'helpers/dom'
import * as f from 'helpers/functions'
import * as functions from 'helpers/functions'
import MaplibreGeocoder from 'maplibre-gl-geocoder'
import MaplibreGeocoder from '@maplibre/maplibre-gl-geocoder'
import { hideContextMenu } from 'maplibre/controls/context_menu'
import { resetEditControls } from 'maplibre/controls/edit'
import { initializeGeoLocateControl } from 'maplibre/controls/geolocate'
Expand Down Expand Up @@ -437,11 +437,9 @@ export function initializeDefaultControls () {
maplibregl,
zoom: 16,
flyTo: { maxZoom: 16 },
clearAndBlurOnEsc: true,
// prioritize results near map center
proximity: {
latitude: () => { map.getCenter().lat }, longitude: () => { map.getCenter().lng }
}
clearAndBlurOnEsc: true
// trackProximity defaults to true, which already biases results toward
// the current map center — no need to wire up proximity manually
}), 'top-right'
)
const geocoderButton = document.querySelector('.maplibregl-ctrl-geocoder')
Expand Down
4 changes: 2 additions & 2 deletions app/javascript/maplibre/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import equal from 'fast-deep-equal'; // https://github.com/epoberezkin/fast-deep
import * as dom from 'helpers/dom';
import * as functions from 'helpers/functions';
import { status } from 'helpers/status';
import maplibregl from 'maplibre-gl';
import * as maplibregl from 'maplibre-gl';
import { AnimateLineAnimation, AnimatePointAnimation, AnimatePolygonAnimation, animateViewFromProperties } from 'maplibre/animations';
import { hideContextMenu, initContextMenu } from 'maplibre/controls/context_menu';
import { isGeolocateFollowModeActive } from 'maplibre/controls/geolocate';
Expand Down Expand Up @@ -100,7 +100,7 @@ export async function initializeMap (divId = 'maplibre-map') {

if (!!mapProperties.description?.trim()) { dom.showElements('#description-modal') }

map.on('styleimagemissing', loadImage)
map.setMissingStyleImageResolver(loadImage)

// TODO: remove once https://github.com/maplibre/maplibre-gl-js/issues/7752 is fixed (5.25)
window.addEventListener('error', (event) => {
Expand Down
14 changes: 13 additions & 1 deletion app/javascript/maplibre/routing/directions.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ class CustomMapLibreGlDirections extends MapLibreGlDirections {
this.buildRequest = orsBuildRequest
this.fetch = orsFetch.bind(this)
}

// queryRenderedFeatures only supports string/number properties; object-valued ones come
// back mangled, breaking the library's JSON.parse in onMove (hover-insert never fires).
const buildRoutelines = this.buildRoutelines
this.buildRoutelines = (...args) => {
const routelines = buildRoutelines(...args)
routelines.forEach(group => group.forEach(routeline => {
routeline.properties.departSnappointProperties = JSON.stringify(routeline.properties.departSnappointProperties)
routeline.properties.arriveSnappointProperties = JSON.stringify(routeline.properties.arriveSnappointProperties)
}))
return routelines
}
}

// Override onMove to be defensive - check if layer exists before querying
Expand Down Expand Up @@ -296,7 +308,7 @@ function updateTrack(feature) {
}

export function getDirectionsLayers () {
let layers = layersFactory()
let layers = layersFactory(1.2)
layers = layers.filter(layer => layer.id !== "maplibre-gl-directions-routeline")
layers = layers.filter(layer => layer.id !== "maplibre-gl-directions-routeline-casing")

Expand Down
2 changes: 1 addition & 1 deletion app/javascript/maplibre/styles/edit_styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function editStyles() {
return [
// removeSource(styles()['polygon-layer']), // gl-draw-polygon-fill-inactive
styles()['polygon-layer-outline'],
styles()['line-layer-outline'], // line outline below line, because it's a wider line
// styles()['line-layer-outline'], // line outline below line, because it's a wider line
// removeSource(styles()['line-layer']),

// active polygon outline
Expand Down
16 changes: 8 additions & 8 deletions app/javascript/maplibre/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,20 @@ export function clearImageState() {
// Reset labelFont to default when clearing state
export function resetLabelFont() { labelFont = [defaultFont] }

export async function loadImage (e) {
export async function loadImage (id) {
// Skip if already loading, loaded, or failed
if (imageState[e.id]) {
// console.log(`Skipped loading image '${e.id}'`, imageState[e.id])
if (imageState[id]) {
// console.log(`Skipped loading image '${id}'`, imageState[id])
return
}

const imageUrl = e.id
const imageUrl = id

if (imageUrl.startsWith('http') || imageUrl.startsWith('/')) {
try {
imageState[e.id] = 'loading'
imageState[id] = 'loading'
// Synchronously register a transparent 1x1 placeholder before any await, so
// MapLibre's getImage re-check (right after the styleimagemissing event fires)
// MapLibre's getImage re-check (right after the missing-image resolver is invoked)
// succeeds and skips the "Image could not be loaded" warning. The real image
// is swapped in below once it has loaded.
if (!map.hasImage(imageUrl)) {
Expand All @@ -94,14 +94,14 @@ export async function loadImage (e) {
// replace the placeholder (remove + add, since dimensions differ)
if (map.hasImage(imageUrl)) { map.removeImage(imageUrl) }
map.addImage(imageUrl, response.data)
imageState[e.id] = 'loaded'
imageState[id] = 'loaded'
} else {
console.warn(imageUrl + ' not found')
}
} catch (error) {
// Handle errors here
console.error(`Failed to load image ${imageUrl}: ` + error)
imageState[e.id] = 'error'
imageState[id] = 'error'
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions config/importmap.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Pin npm packages by running ./bin/importmap pin <npm module name>@<version> --from jspm|unpkg|jsdelivr --download
# Pin npm packages by running ./bin/importmap pin <npm module name>@<version> --from jspm|unpkg|jsdelivr
# https://github.com/rails/importmap-rails

pin "application"
Expand Down Expand Up @@ -27,9 +27,9 @@
under: "mapbox-gl-draw-paint-mode", preload: false

# https://github.com/maplibre/maplibre-gl-js
pin "maplibre-gl" # @5.24.0 — preloaded so the browser fetches during head parse
pin "maplibre-gl" # @6.0.0 — preloaded so the browser fetches during head parse
# https://github.com/maplibre/maplibre-gl-geocoder
pin "maplibre-gl-geocoder", to: "maplibre-gl-geocoder.js", preload: false
pin "@maplibre/maplibre-gl-geocoder", preload: false, to: "@maplibre--maplibre-gl-geocoder.js" # @1.9.4
# https://github.com/GIScience/openrouteservice-js?tab=readme-ov-file
pin "openrouteservice-js", preload: false # @0.4.1
# https://github.com/maplibre/maplibre-gl-directions/tree/main
Expand Down
2 changes: 1 addition & 1 deletion config/initializers/content_security_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
config.content_security_policy do |policy|
# policy.default_src :self, :https
policy.font_src :self, :https, :data
policy.img_src :self, :https, :data
policy.img_src :self, :https, :data, :blob
policy.object_src :none
# TODO: It seems not possible yet to use Turbo and csp without :unsafe_inline, :unsafe_eval
policy.script_src :self, :https, :blob, :unsafe_inline, :unsafe_eval
Expand Down
9 changes: 9 additions & 0 deletions config/initializers/mime_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,12 @@
Mime::Type.register("application/javascript", :mjs)

Rack::Mime::MIME_TYPES[".mjs"] = "application/javascript"

# Sprockets keeps its own mime type registry (separate from Rack's above) and only
# recognizes .js by default, so .mjs assets (e.g. maplibre-gl's split-out worker chunk)
# get served with no content type and browsers refuse to load them as modules.
Rails.application.config.assets.configure do |env|
# register_mime_type replaces the whole entry rather than merging, so re-list
# .js alongside .mjs to avoid dropping it from Sprockets' internal mime_types map.
env.register_mime_type "application/javascript", extensions: [ ".js", ".mjs" ], charset: :unicode
end
2 changes: 2 additions & 0 deletions vendor/javascript/@maplibre--maplibre-gl-directions.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading