From 9a4ebee2d39d5c217d7236971f5b02d72c7f613a Mon Sep 17 00:00:00 2001 From: Jake Low Date: Wed, 29 Jul 2026 16:28:04 -0700 Subject: [PATCH] Rewrite overlay style generator; switch basemap to Sourdough tiles --- .github/workflows/deploy.yml | 18 +- .github/workflows/test_build.yml | 15 +- .gitignore | 4 +- CNAME | 1 - README.md | 36 +- biome.json | 48 + css/main.css | 161 +- embed.html | 65 + index.html | 63 +- js/accessExpressions.js | 309 +++ js/app.js | 11 + js/controls.js | 59 + js/controlsController.js | 55 - js/embed.js | 110 + js/hash.js | 78 + js/hashController.js | 93 - js/map.js | 272 +++ js/mapController.js | 604 ----- js/optionsData.js | 218 +- js/osm.js | 94 + js/osmController.js | 79 - js/sidebar.js | 303 +++ js/sidebarController.js | 307 --- js/state.js | 56 + js/stateController.js | 87 - js/styleGenerator.js | 1996 ++++------------- js/trailLabels.js | 118 + js/utils.js | 58 +- json/focus.json | 1 - package-lock.json | 1317 +++++++++++ package.json | 37 +- public/sprites/opentrailmap.json | 1 + public/sprites/opentrailmap.png | Bin 0 -> 33059 bytes public/sprites/opentrailmap@2x.json | 1 + public/sprites/opentrailmap@2x.png | Bin 0 -> 110711 bytes rollup.config.js | 17 - scripts/buildSprites.js | 142 ++ scripts/buildStaticStyles.js | 36 - scripts/buildStyle.js | 11 + scripts/validateStyles.js | 35 + serve.js | 52 - style/basestyle.json | 978 -------- style/constants.js | 28 + style/layers/background.js | 7 + style/layers/boundaries.js | 135 ++ style/layers/contours.js | 36 + style/layers/hillshade.js | 20 + style/layers/natural.js | 24 + style/layers/parks.js | 239 ++ style/layers/places.js | 113 + style/layers/pois.js | 443 ++++ style/layers/roads.js | 140 ++ style/layers/sidewalks.js | 66 + style/layers/structures.js | 34 + style/layers/trails.js | 125 ++ style/layers/water.js | 122 + style/sprites/circle.svg | 7 + style/sprites/icons/access_point.svg | 3 + style/sprites/icons/arrow_left.svg | 3 + style/sprites/icons/arrow_right.svg | 3 + style/sprites/icons/beaver_dam.svg | 3 + style/sprites/icons/binoculars.svg | 3 + style/sprites/icons/bird_refuge.svg | 3 + style/sprites/icons/bison_refuge.svg | 3 + style/sprites/icons/cairn.svg | 3 + style/sprites/icons/caravan.svg | 3 + style/sprites/icons/dam.svg | 3 + style/sprites/icons/forest_reserve.svg | 3 + style/sprites/icons/game_land.svg | 3 + style/sprites/icons/grassland_reserve.svg | 3 + style/sprites/icons/guidepost.svg | 3 + style/sprites/icons/hiker.svg | 9 + style/sprites/icons/information_board.svg | 3 + style/sprites/icons/information_map.svg | 3 + style/sprites/icons/lean_to.svg | 3 + style/sprites/icons/lock.svg | 3 + style/sprites/icons/map_pin_with_dot.svg | 3 + style/sprites/icons/nature_reserve.svg | 3 + style/sprites/icons/no_entry.svg | 3 + style/sprites/icons/park.svg | 3 + style/sprites/icons/protected_area.svg | 3 + style/sprites/icons/ranger_station.svg | 3 + style/sprites/icons/route_marker.svg | 3 + style/sprites/icons/slipway_canoe.svg | 3 + style/sprites/icons/slipway_canoe_trailer.svg | 3 + style/sprites/icons/streamgage.svg | 3 + style/sprites/icons/tent.svg | 3 + style/sprites/icons/triangle.svg | 3 + style/sprites/icons/waterfall.svg | 3 + style/sprites/icons/watershed_reserve.svg | 3 + style/sprites/icons/wilderness_preserve.svg | 3 + style/sprites/icons/wildlife_refuge.svg | 3 + style/sprites/opentrailmap.json | 1 - style/sprites/opentrailmap.png | Bin 16371 -> 0 bytes style/sprites/opentrailmap@2x.json | 1 - style/sprites/opentrailmap@2x.png | Bin 33458 -> 0 bytes style/sprites/roundrect.svg | 7 + style/sprites/svg/access_point-minor.svg | 10 - style/sprites/svg/access_point-noaccess.svg | 19 - style/sprites/svg/access_point.svg | 8 - style/sprites/svg/beaver_dam-canoeable.svg | 52 - style/sprites/svg/beaver_dam-hazard.svg | 52 - style/sprites/svg/beaver_dam.svg | 52 - style/sprites/svg/bird_refuge.svg | 8 - style/sprites/svg/bison_refuge.svg | 10 - style/sprites/svg/cairn.svg | 8 - style/sprites/svg/campground-noaccess.svg | 21 - style/sprites/svg/campground.svg | 9 - style/sprites/svg/campsite.svg | 8 - style/sprites/svg/caravan_site-noaccess.svg | 21 - style/sprites/svg/caravan_site.svg | 10 - style/sprites/svg/dam-canoeable.svg | 13 - style/sprites/svg/dam-hazard.svg | 13 - style/sprites/svg/dam.svg | 8 - style/sprites/svg/ferry-noaccess.svg | 24 - style/sprites/svg/ferry.svg | 17 - style/sprites/svg/fill-restricted-zone.svg | 10 - style/sprites/svg/forest_reserve.svg | 11 - style/sprites/svg/game_land.svg | 8 - style/sprites/svg/grassland_reserve.svg | 10 - style/sprites/svg/guidepost.svg | 8 - style/sprites/svg/lean_to.svg | 8 - style/sprites/svg/lock-canoeable.svg | 8 - style/sprites/svg/lock-hazard.svg | 8 - style/sprites/svg/lock.svg | 11 - style/sprites/svg/nature_reserve.svg | 8 - style/sprites/svg/oneway-arrow-left.svg | 8 - style/sprites/svg/oneway-arrow-right.svg | 8 - style/sprites/svg/oneway-arrows-leftright.svg | 8 - style/sprites/svg/park.svg | 10 - style/sprites/svg/peak.svg | 8 - style/sprites/svg/protected_area.svg | 12 - style/sprites/svg/question.svg | 9 - style/sprites/svg/ranger_station-noaccess.svg | 19 - style/sprites/svg/ranger_station.svg | 8 - style/sprites/svg/route_marker.svg | 7 - style/sprites/svg/slipway-canoe-noaccess.svg | 19 - .../svg/slipway-canoe-trailer-noaccess.svg | 19 - style/sprites/svg/slipway-canoe-trailer.svg | 8 - style/sprites/svg/slipway-canoe.svg | 8 - style/sprites/svg/streamgage.svg | 15 - .../sprites/svg/stroke-disallowed-stripes.svg | 8 - style/sprites/svg/trailhead-noaccess.svg | 19 - style/sprites/svg/trailhead.svg | 8 - style/sprites/svg/viewpoint.svg | 8 - style/sprites/svg/waterfall-canoeable.svg | 11 - style/sprites/svg/waterfall-hazard.svg | 11 - style/sprites/svg/waterfall.svg | 10 - style/sprites/svg/watershed_reserve.svg | 9 - style/sprites/svg/wilderness_preserve.svg | 12 - style/sprites/svg/wildlife_refuge.svg | 8 - style/style.js | 73 + vite.config.js | 14 + 153 files changed, 5524 insertions(+), 4891 deletions(-) delete mode 100644 CNAME create mode 100644 biome.json create mode 100644 embed.html create mode 100644 js/accessExpressions.js create mode 100644 js/app.js create mode 100644 js/controls.js delete mode 100644 js/controlsController.js create mode 100644 js/embed.js create mode 100644 js/hash.js delete mode 100644 js/hashController.js create mode 100644 js/map.js delete mode 100644 js/mapController.js create mode 100644 js/osm.js delete mode 100644 js/osmController.js create mode 100644 js/sidebar.js delete mode 100644 js/sidebarController.js create mode 100644 js/state.js delete mode 100644 js/stateController.js create mode 100644 js/trailLabels.js delete mode 100644 json/focus.json create mode 100644 package-lock.json create mode 100644 public/sprites/opentrailmap.json create mode 100644 public/sprites/opentrailmap.png create mode 100644 public/sprites/opentrailmap@2x.json create mode 100644 public/sprites/opentrailmap@2x.png delete mode 100644 rollup.config.js create mode 100644 scripts/buildSprites.js delete mode 100644 scripts/buildStaticStyles.js create mode 100644 scripts/buildStyle.js create mode 100644 scripts/validateStyles.js delete mode 100644 serve.js delete mode 100644 style/basestyle.json create mode 100644 style/constants.js create mode 100644 style/layers/background.js create mode 100644 style/layers/boundaries.js create mode 100644 style/layers/contours.js create mode 100644 style/layers/hillshade.js create mode 100644 style/layers/natural.js create mode 100644 style/layers/parks.js create mode 100644 style/layers/places.js create mode 100644 style/layers/pois.js create mode 100644 style/layers/roads.js create mode 100644 style/layers/sidewalks.js create mode 100644 style/layers/structures.js create mode 100644 style/layers/trails.js create mode 100644 style/layers/water.js create mode 100644 style/sprites/circle.svg create mode 100644 style/sprites/icons/access_point.svg create mode 100644 style/sprites/icons/arrow_left.svg create mode 100644 style/sprites/icons/arrow_right.svg create mode 100644 style/sprites/icons/beaver_dam.svg create mode 100644 style/sprites/icons/binoculars.svg create mode 100644 style/sprites/icons/bird_refuge.svg create mode 100644 style/sprites/icons/bison_refuge.svg create mode 100644 style/sprites/icons/cairn.svg create mode 100644 style/sprites/icons/caravan.svg create mode 100644 style/sprites/icons/dam.svg create mode 100644 style/sprites/icons/forest_reserve.svg create mode 100644 style/sprites/icons/game_land.svg create mode 100644 style/sprites/icons/grassland_reserve.svg create mode 100644 style/sprites/icons/guidepost.svg create mode 100644 style/sprites/icons/hiker.svg create mode 100644 style/sprites/icons/information_board.svg create mode 100644 style/sprites/icons/information_map.svg create mode 100644 style/sprites/icons/lean_to.svg create mode 100644 style/sprites/icons/lock.svg create mode 100644 style/sprites/icons/map_pin_with_dot.svg create mode 100644 style/sprites/icons/nature_reserve.svg create mode 100644 style/sprites/icons/no_entry.svg create mode 100644 style/sprites/icons/park.svg create mode 100644 style/sprites/icons/protected_area.svg create mode 100644 style/sprites/icons/ranger_station.svg create mode 100644 style/sprites/icons/route_marker.svg create mode 100644 style/sprites/icons/slipway_canoe.svg create mode 100644 style/sprites/icons/slipway_canoe_trailer.svg create mode 100644 style/sprites/icons/streamgage.svg create mode 100644 style/sprites/icons/tent.svg create mode 100644 style/sprites/icons/triangle.svg create mode 100644 style/sprites/icons/waterfall.svg create mode 100644 style/sprites/icons/watershed_reserve.svg create mode 100644 style/sprites/icons/wilderness_preserve.svg create mode 100644 style/sprites/icons/wildlife_refuge.svg delete mode 100644 style/sprites/opentrailmap.json delete mode 100644 style/sprites/opentrailmap.png delete mode 100644 style/sprites/opentrailmap@2x.json delete mode 100644 style/sprites/opentrailmap@2x.png create mode 100644 style/sprites/roundrect.svg delete mode 100644 style/sprites/svg/access_point-minor.svg delete mode 100644 style/sprites/svg/access_point-noaccess.svg delete mode 100644 style/sprites/svg/access_point.svg delete mode 100644 style/sprites/svg/beaver_dam-canoeable.svg delete mode 100644 style/sprites/svg/beaver_dam-hazard.svg delete mode 100644 style/sprites/svg/beaver_dam.svg delete mode 100644 style/sprites/svg/bird_refuge.svg delete mode 100644 style/sprites/svg/bison_refuge.svg delete mode 100644 style/sprites/svg/cairn.svg delete mode 100644 style/sprites/svg/campground-noaccess.svg delete mode 100644 style/sprites/svg/campground.svg delete mode 100644 style/sprites/svg/campsite.svg delete mode 100644 style/sprites/svg/caravan_site-noaccess.svg delete mode 100644 style/sprites/svg/caravan_site.svg delete mode 100644 style/sprites/svg/dam-canoeable.svg delete mode 100644 style/sprites/svg/dam-hazard.svg delete mode 100644 style/sprites/svg/dam.svg delete mode 100644 style/sprites/svg/ferry-noaccess.svg delete mode 100644 style/sprites/svg/ferry.svg delete mode 100644 style/sprites/svg/fill-restricted-zone.svg delete mode 100644 style/sprites/svg/forest_reserve.svg delete mode 100644 style/sprites/svg/game_land.svg delete mode 100644 style/sprites/svg/grassland_reserve.svg delete mode 100644 style/sprites/svg/guidepost.svg delete mode 100644 style/sprites/svg/lean_to.svg delete mode 100644 style/sprites/svg/lock-canoeable.svg delete mode 100644 style/sprites/svg/lock-hazard.svg delete mode 100644 style/sprites/svg/lock.svg delete mode 100644 style/sprites/svg/nature_reserve.svg delete mode 100644 style/sprites/svg/oneway-arrow-left.svg delete mode 100644 style/sprites/svg/oneway-arrow-right.svg delete mode 100644 style/sprites/svg/oneway-arrows-leftright.svg delete mode 100644 style/sprites/svg/park.svg delete mode 100644 style/sprites/svg/peak.svg delete mode 100644 style/sprites/svg/protected_area.svg delete mode 100644 style/sprites/svg/question.svg delete mode 100644 style/sprites/svg/ranger_station-noaccess.svg delete mode 100644 style/sprites/svg/ranger_station.svg delete mode 100644 style/sprites/svg/route_marker.svg delete mode 100644 style/sprites/svg/slipway-canoe-noaccess.svg delete mode 100644 style/sprites/svg/slipway-canoe-trailer-noaccess.svg delete mode 100644 style/sprites/svg/slipway-canoe-trailer.svg delete mode 100644 style/sprites/svg/slipway-canoe.svg delete mode 100644 style/sprites/svg/streamgage.svg delete mode 100644 style/sprites/svg/stroke-disallowed-stripes.svg delete mode 100644 style/sprites/svg/trailhead-noaccess.svg delete mode 100644 style/sprites/svg/trailhead.svg delete mode 100644 style/sprites/svg/viewpoint.svg delete mode 100644 style/sprites/svg/waterfall-canoeable.svg delete mode 100644 style/sprites/svg/waterfall-hazard.svg delete mode 100644 style/sprites/svg/waterfall.svg delete mode 100644 style/sprites/svg/watershed_reserve.svg delete mode 100644 style/sprites/svg/wilderness_preserve.svg delete mode 100644 style/sprites/svg/wildlife_refuge.svg create mode 100644 style/style.js create mode 100644 vite.config.js diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index edc012e..0ea216b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -27,23 +27,21 @@ jobs: steps: - name: Checkout uses: actions/checkout@v7 + - name: Setup Node + uses: actions/setup-node@v7 + with: + node-version: 22 + cache: npm - name: Setup Pages uses: actions/configure-pages@v6 - name: Install - run: npm install - - name: Build + run: npm ci + - name: Build run: npm run build - - name: Build static styles - run: npm run build-static-styles - - name: Generate directory listing pages - uses: jayanta525/github-pages-directory-listing@v4.0.0 - with: - FOLDER: '.' - name: Upload artifact uses: actions/upload-pages-artifact@v5 with: - # Upload entire repository - path: '.' + path: 'dist' # Deployment job deploy: diff --git a/.github/workflows/test_build.yml b/.github/workflows/test_build.yml index 332cc9b..8f427f7 100644 --- a/.github/workflows/test_build.yml +++ b/.github/workflows/test_build.yml @@ -17,9 +17,16 @@ jobs: steps: - name: Checkout uses: actions/checkout@v7 + - name: Setup Node + uses: actions/setup-node@v7 + with: + node-version: 22 + cache: npm - name: Install - run: npm install - - name: Build + run: npm ci + - name: Lint + run: npm run lint + - name: Validate styles + run: npm test + - name: Build run: npm run build - - name: Build static styles - run: npm run build-static-styles \ No newline at end of file diff --git a/.gitignore b/.gitignore index cdfa3cc..f06235c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ -.DS_Store node_modules -package-lock.json -dist \ No newline at end of file +dist diff --git a/CNAME b/CNAME deleted file mode 100644 index 6ed0cf7..0000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -opentrailmap.us \ No newline at end of file diff --git a/README.md b/README.md index 3bc2f9f..8282a0d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ _[opentrailmap.us](https://opentrailmap.us)_ This is a prototype web map application for viewing [OpenStreetMap](https://openstreetmap.org/about) (OSM) trail data. The tool is being developed in support of our [Trails Stewardship Initiative](https://openstreetmap.us/our-work/trails/), a community project to improve the quality of trail data in OSM. -⚠️ This tool is still in early development and serves as a proof-of-concept. OpenStreetMap US is seeking funding partners to build out the tool as the primary app for visualizing, updating, validating, and maintaining OpenStreetMap trail data in the United States. The app will close the feedback loop between trail users, trail managers, and trail mappers. If you or your organization are interested in supporting this tool, please [contact us](https://openstreetmap.us/contact/) or consider [donating](https://openstreetmap.app.neoncrm.com/forms/trails-stewardship-initiative). +> [!WARNING] +> This tool is still in early development and serves as a proof-of-concept. OpenStreetMap US is seeking funding partners to build out the tool as the primary app for visualizing, updating, validating, and maintaining OpenStreetMap trail data in the United States. The app will close the feedback loop between trail users, trail managers, and trail mappers. If you or your organization are interested in supporting this tool, please [contact us](https://openstreetmap.us/contact/) or consider [donating](https://openstreetmap.app.neoncrm.com/forms/trails-stewardship-initiative). ## Prototype functionality @@ -32,15 +33,21 @@ The following styles show allowed trail access for different travel modes. Dark - Cross-Country Ski Trails ([`ski:nordic`](https://wiki.openstreetmap.org/wiki/Key:ski:nordic) access) - Snowmobile Trails ([`snowmobile`](https://wiki.openstreetmap.org/wiki/Key:snowmobile) access) -The following styles highlight the presence and values of trail attribute tags. Purple lines mean an attribute is missing, incomplete, or needs review, while teal lines indicate the attribute is good to go. +Selecting a _lens_ highlights the presence and values of a single trail attribute tag. Purple lines mean an attribute is missing, incomplete, or needs review, while teal lines indicate the attribute is good to go. The set of lenses offered depends on the selected travel mode. - [`operator`](https://wiki.openstreetmap.org/wiki/Key:operator)/[`informal`](https://wiki.openstreetmap.org/wiki/Key:informal) - [`name`](https://wiki.openstreetmap.org/wiki/Key:name)/[`noname`](https://wiki.openstreetmap.org/wiki/Key:noname) - [`surface`](https://wiki.openstreetmap.org/wiki/Key:surface) - [`smoothness`](https://wiki.openstreetmap.org/wiki/Key:smoothness) - [`trail_visibility`](https://wiki.openstreetmap.org/wiki/Key:trail_visibility) +- [`sac_scale`](https://wiki.openstreetmap.org/wiki/Key:sac_scale) (hiking only) - [`width`](https://wiki.openstreetmap.org/wiki/Key:width) - [`incline`](https://wiki.openstreetmap.org/wiki/Key:incline) +- [`covered`](https://wiki.openstreetmap.org/wiki/Key:covered)/[`tunnel`](https://wiki.openstreetmap.org/wiki/Key:tunnel) +- [`lit`](https://wiki.openstreetmap.org/wiki/Key:lit) +- [`dog`](https://wiki.openstreetmap.org/wiki/Key:dog) +- [`maxspeed`](https://wiki.openstreetmap.org/wiki/Key:maxspeed) (wheeled modes only) +- [`oneway`](https://wiki.openstreetmap.org/wiki/Key:oneway) - [`fixme`](https://wiki.openstreetmap.org/wiki/Key:fixme)/[`todo`](https://wiki.openstreetmap.org/wiki/Key:todo) - [`check_date`](https://wiki.openstreetmap.org/wiki/Key:check_date)/[`survey:date`](https://wiki.openstreetmap.org/wiki/Key:survey:date) - Last Edited Date: the timestamp of the latest version of the feature @@ -71,11 +78,16 @@ The following water trail attribute styles are supported: - [`check_date`](https://wiki.openstreetmap.org/wiki/Key:check_date)/[`survey:date`](https://wiki.openstreetmap.org/wiki/Key:survey:date) - Last Edited Date: the timestamp of the latest version of the feature -### Map tiles -Trail vector tiles are rendered and hosted by OpenStreetMap US using the schema files [here](https://github.com/osmus/tileservice/blob/main/renderer/layers). Thank you to [@zelonewolf](https://github.com/zelonewolf) for setting up the vector tile pipeline. Render time is currently about 4 hours, so any changes you make will take 4 to 8 hours to appear on the map. Map tiles are not available for public use at this time. +### Static stylesheet -### Static stylesheets -OpenTrailMap has complex, parameter-driven styling. For performance, styles are generated at runtime. However, static stylesheets are also generated at build time for ease-of-use by other apps. You can browse the full list of available styles [here](https://opentrailmap.us/dist/styles/). Generated styles are subject to the same license as the rest of OpenTrailMap (see below). +The basemap is a general-purpose trail map in its own right, independent of the QA overlay. `npm run build` writes it to `dist/style.json` as a plain MapLibre stylesheet, published at [opentrailmap.us/style.json](https://opentrailmap.us/style.json), for use in other applications. The stylesheet is subject to the same license as the rest of OpenTrailMap (see below), but note that the tiles it points at are not currently available for public use. + +### Embedding + +An embeddable version of the basemap is served from [opentrailmap.us/embed.html](https://opentrailmap.us/embed.html), intended for use in an `