@trailstash/ultra 4.2.4 → 4.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ options:
6
6
  zoom: 15
7
7
  type: postpass
8
8
  ---
9
- SELECT osm_id, way, tags FROM planet_osm_point
10
- WHERE amenity = 'bicycle_repair_station'
11
- AND way && ST_MakeEnvelope({{wsen}}, 4326)
9
+ SELECT osm_id, osm_type, tags, geom
10
+ FROM postpass_point
11
+ WHERE tags->>'amenity'='fast_food'
12
+ AND geom && ST_MakeEnvelope({{wsen}},4326)
@@ -1,22 +1,29 @@
1
1
  import path from "path";
2
2
  import fs from "fs";
3
3
  import puppeteer from "puppeteer";
4
+ import minimist from "minimist";
4
5
 
5
- const exampleName = process.argv[2];
6
- const useLocalhost = process.argv.length > 3 && process.argv[3] === "serve";
6
+ const {
7
+ _: [exampleName],
8
+ useLocalhost,
9
+ height,
10
+ width,
11
+ waitTime,
12
+ output,
13
+ } = minimist(process.argv.slice(2))
7
14
 
8
15
  const browser = await puppeteer.launch({ headless: true });
9
16
 
10
17
  const page = await browser.newPage();
11
18
  // set viewport and double deviceScaleFactor to get a closer shot of the map
12
19
  await page.setViewport({
13
- width: 600,
14
- height: 250,
20
+ width: width || 600,
21
+ height: height || 250,
15
22
  deviceScaleFactor: 2,
16
23
  });
17
24
 
18
25
  async function createImage(exampleName) {
19
- if (!fs.existsSync(`./docs/assets/${path.dirname(exampleName)}`)) {
26
+ if (!output && !fs.existsSync(`./docs/assets/${path.dirname(exampleName)}`)) {
20
27
  fs.mkdirSync(`./docs/assets/${path.dirname(exampleName)}`);
21
28
  }
22
29
 
@@ -35,31 +42,28 @@ async function createImage(exampleName) {
35
42
  // Wait for map to load, then wait two more seconds for images, etc. to load.
36
43
  try {
37
44
  //await page.waitForFunction('map.loaded()');
38
- const waitTime = 10000;
39
- console.log(`waiting for ${waitTime} ms`);
40
- await new Promise((resolve) => setTimeout(resolve, waitTime));
45
+ console.log(`waiting for ${waitTime || 4000} ms`);
46
+ await new Promise((resolve) => setTimeout(resolve, waitTime || 4000));
41
47
  } catch (err) {
42
48
  // map.loaded() does not evaluate to true within 3 seconds, it's probably an animated example.
43
49
  // In this case we take the screenshot immediately.
44
50
  console.log(`Timed out waiting for map load on ${exampleName}.`);
45
51
  }
46
52
 
53
+ const filename = output || `./docs/assets/${exampleName.replace(".ultra", ".png")}`;
54
+
47
55
  await page
48
56
  .screenshot({
49
- path: `./docs/assets/${exampleName.replace(".ultra", ".png")}`,
57
+ path: filename,
50
58
  type: "png",
51
59
  clip: {
52
60
  x: 0,
53
61
  y: 0,
54
- width: 600,
55
- height: 250,
62
+ width: width || 600,
63
+ height: height || 250,
56
64
  },
57
65
  })
58
- .then(() =>
59
- console.log(
60
- `Created ./docs/assets/${exampleName.replace(".ultra", ".png")}`,
61
- ),
62
- )
66
+ .then(() => console.log(`Created ${filename}`))
63
67
  .catch((err) => {
64
68
  console.log(err);
65
69
  });
@@ -2,31 +2,54 @@ import { h, t } from "../lib/dom.js";
2
2
  import { style as buttonCSS } from "./button.js";
3
3
  import { normalizeCSS } from "../lib/normalize.js";
4
4
 
5
- const style = `margin: 10px 0; display: block; width: 100%; text-align: left;`;
5
+ const css = new CSSStyleSheet();
6
+ css.replaceSync(`
7
+ h3 {
8
+ margin: .5em 0 0;
9
+ }
10
+ h3 a {
11
+ color: black;
12
+ text-decoration: none;
13
+ }
14
+ button {
15
+ margin: 0.25em;
16
+ display: inline-block;
17
+ }
18
+ button img {
19
+ height: 125px;
20
+ width: 125px;
21
+ }
22
+ h3 img {
23
+ height: 2em;
24
+ width: 2em;
25
+ vertical-align: middle;
26
+ object-fit: contain;
27
+ }
28
+ `);
6
29
 
7
30
  const styles = [
8
31
  [
9
- "OpenFreeMap Liberty",
32
+ "Liberty",
10
33
  "https://tiles.openfreemap.org/styles/liberty",
11
34
  `<a href="https://openfreemap.org/">OpenFreeMap</a>`,
12
35
  ],
13
36
  [
14
- "OpenFreeMap Bright",
37
+ "Bright",
15
38
  "https://tiles.openfreemap.org/styles/bright",
16
39
  `<a href="https://openfreemap.org/">OpenFreeMap</a>`,
17
40
  ],
18
41
  [
19
- "OpenFreeMap Positron",
42
+ "Positron",
20
43
  "https://tiles.openfreemap.org/styles/positron",
21
44
  `<a href="https://openfreemap.org/">OpenFreeMap</a>`,
22
45
  ],
23
46
  [
24
- "Natural Earth Vector",
47
+ "Vectortiles",
25
48
  "https://trailstash.github.io/naturalearthtiles/maps/natural_earth.vector.json",
26
49
  `<a href="https://github.com/trailstash/naturalearthtiles">Natural Earth</a>`,
27
50
  ],
28
51
  [
29
- "MapLibre Demo Tiles",
52
+ "Demo Tiles",
30
53
  "https://demotiles.maplibre.org/style.json",
31
54
  `<a href="https://github.com/maplibre/demotiles">MapLibre</a>`,
32
55
  ],
@@ -47,7 +70,7 @@ export class StylePicker extends HTMLElement {
47
70
  return;
48
71
  }
49
72
 
50
- const div = h("div", { slot: "modal-content" });
73
+ const div = h("div", { slot: "modal-content", style: "max-width: 1055px;" });
51
74
  const button = h(
52
75
  "button-modal",
53
76
  { text: "Pick Style", icon: "paintbrush" },
@@ -55,23 +78,34 @@ export class StylePicker extends HTMLElement {
55
78
  );
56
79
  this.refs = { button, div };
57
80
 
58
- for (const [name, value, tiles] of this.styles) {
59
- const styleButton = h(
60
- "button",
61
- { style },
62
- t(name),
63
- // h("br"),
64
- // h("small", {}, `Tiles: ${tiles}`),
65
- );
66
- styleButton.addEventListener("click", (e) => {
67
- button.toggle();
68
- this.dispatchEvent(
69
- new CustomEvent("change", { detail: { value: value } }),
81
+ const stylesByProvider = {};
82
+ for (const [name, value, provider] of this.styles) {
83
+ if (!stylesByProvider[provider]) {
84
+ stylesByProvider[provider] = [];
85
+ }
86
+ stylesByProvider[provider].push({name, value});
87
+ }
88
+ for (const [provider, styles] of Object.entries(stylesByProvider)) {
89
+ const div2 = h("div", {style:"display:inline-block;margin-right:1.25em;"});
90
+ div.appendChild(div2);
91
+ div2.appendChild(h("h3", {}, provider));
92
+ for (const {name, value} of styles) {
93
+ const styleButton = h(
94
+ "button",
95
+ {},
96
+ name,
70
97
  );
71
- });
72
- div.appendChild(styleButton);
98
+ styleButton.addEventListener("click", (e) => {
99
+ button.toggle();
100
+ this.dispatchEvent(
101
+ new CustomEvent("change", { detail: { value: value } }),
102
+ );
103
+ });
104
+ div2.appendChild(styleButton);
105
+ }
73
106
  }
74
107
 
108
+ shadow.adoptedStyleSheets.push(css);
75
109
  shadow.appendChild(button);
76
110
  }
77
111
  }
package/docs/yaml.md CHANGED
@@ -254,6 +254,13 @@ Detected if
254
254
  An SQL query to be executed on a [Postpass](https://github.com/woodpeck/postpass) server. Server
255
255
  results are modified to have the same structure as [overpass](#overpass)
256
256
 
257
+ !!! warning
258
+
259
+ Postpass is in very early stages of development, so Ultra may lag behind as new versions of the
260
+ API are released. This provider defaults to the version 0.2 of the [GeoFabrik Postpass
261
+ API](https://github.com/woodpeck/postpass-ops) &
262
+ [Schema](https://github.com/woodpeck/postpass-ops/blob/main/SCHEMA.md)
263
+
257
264
  ## `options`
258
265
 
259
266
  When an Ultra query is run in "interactive map" mode, you can specify the
@@ -3,14 +3,6 @@ import { setQueryBounds } from "../bounds.js";
3
3
 
4
4
  import { layers, popupTemplate, popupContextBuilder } from "./osm.js";
5
5
 
6
- const nonTags = {
7
- osm_id: true,
8
- tags: true,
9
- // yes... these are not tags... but they are useful! so we're keeping them.
10
- // way_area: true,
11
- // z_order: true,
12
- };
13
-
14
6
  const flattenPropertiesAndInferIdAndType = (geoJSON) => {
15
7
  // prety major assumption basked into this as Postpass executes arbitrary SQL so the returned
16
8
  // data could be anything. This assumes that the query returns un-renamed columns.
@@ -18,12 +10,7 @@ const flattenPropertiesAndInferIdAndType = (geoJSON) => {
18
10
  const properties = {};
19
11
  if (f.properties.osm_id) {
20
12
  properties["@id"] = f.properties.osm_id;
21
- if (properties["@id"] < 0) {
22
- properties["@id"] = -properties["@id"];
23
- properties["@type"] = "relation";
24
- } else {
25
- properties["@type"] = f.geometry.type === "Point" ? "node" : "way";
26
- }
13
+ properties["@type"] = f.properties.osm_type;
27
14
  }
28
15
  if (f.properties.tags) {
29
16
  for (const [k, v] of Object.entries(f.properties.tags)) {
@@ -31,9 +18,7 @@ const flattenPropertiesAndInferIdAndType = (geoJSON) => {
31
18
  }
32
19
  }
33
20
  for (const [k, v] of Object.entries(f.properties)) {
34
- if (!nonTags[k]) {
35
- properties[k] = v;
36
- }
21
+ properties[k] = v;
37
22
  }
38
23
  return {
39
24
  ...f,
@@ -46,7 +31,7 @@ const flattenPropertiesAndInferIdAndType = (geoJSON) => {
46
31
  const postpass = {
47
32
  source: async function (query, controller, { server, bounds }) {
48
33
  if (!server) {
49
- server = "https://postpass.geofabrik.de/api/0.1/interpreter";
34
+ server = "https://postpass.geofabrik.de/api/0.2/interpreter";
50
35
  }
51
36
  const resp = await fetch(server, {
52
37
  method: "POST",
package/mkdocs.yml CHANGED
@@ -24,3 +24,7 @@ extra:
24
24
  extra:
25
25
  analytics:
26
26
  provider: custom
27
+ markdown_extensions:
28
+ - admonition
29
+ - pymdownx.details
30
+ - pymdownx.superfences
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "4.2.4",
6
+ "version": "4.2.6",
7
7
  "description": "A web based tool for making MapLibre GL maps with data from sources such as Overpass, GeoJSON, GPX, KML, TCX, etc",
8
8
  "main": "index.js",
9
9
  "scripts": {
@@ -47,6 +47,7 @@
47
47
  "esbuild-jest": "^0.5.0",
48
48
  "jest": "^29.7.0",
49
49
  "jest-environment-jsdom": "^29.7.0",
50
+ "minimist": "^1.2.8",
50
51
  "prettier": "^3.3.3",
51
52
  "puppeteer": "^23.4.0",
52
53
  "svg2png": "^4.1.1",