gtfs-to-html 2.5.8 → 2.5.9

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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.5.9] - 2024-01-24
9
+
10
+ ### Updated
11
+
12
+ - Move stop markers above map labels
13
+ - Update to Mapbox GL JS v3
14
+ - Dependency updates
15
+
16
+ ### Fixed
17
+
18
+ - Handle routes with no route_short_name in map marker popups
19
+
8
20
  ## [2.5.8] - 2024-01-02
9
21
 
10
22
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtfs-to-html",
3
- "version": "2.5.8",
3
+ "version": "2.5.9",
4
4
  "private": false,
5
5
  "description": "Build human readable transit timetables as HTML, PDF or CSV from GTFS",
6
6
  "keywords": [
@@ -42,14 +42,14 @@
42
42
  "copy-dir": "^1.3.0",
43
43
  "csv-stringify": "^6.4.5",
44
44
  "express": "^4.18.2",
45
- "gtfs": "^4.5.1",
45
+ "gtfs": "^4.6.0",
46
46
  "js-beautify": "^1.14.11",
47
47
  "lodash-es": "^4.17.21",
48
48
  "moment": "^2.30.1",
49
49
  "morgan": "^1.10.0",
50
50
  "pretty-error": "^4.0.0",
51
51
  "pug": "^3.0.2",
52
- "puppeteer": "^21.6.1",
52
+ "puppeteer": "^21.9.0",
53
53
  "sanitize-filename": "^1.6.3",
54
54
  "sqlstring": "^2.3.3",
55
55
  "timer-machine": "^1.1.0",
@@ -61,7 +61,7 @@
61
61
  "devDependencies": {
62
62
  "husky": "^8.0.3",
63
63
  "lint-staged": "^15.2.0",
64
- "prettier": "^3.1.1"
64
+ "prettier": "^3.2.4"
65
65
  },
66
66
  "engines": {
67
67
  "node": ">= 18.0.0"
@@ -3,6 +3,17 @@
3
3
 
4
4
  const maps = {};
5
5
 
6
+ function formatRouteName(route) {
7
+ let routeName = '';
8
+ if (route.route_short_name !== undefined) {
9
+ routeName += route.route_short_name;
10
+ } else if (route.route_long_name !== undefined) {
11
+ routeName += route.route_long_name;
12
+ }
13
+
14
+ return routeName;
15
+ }
16
+
6
17
  function formatRoute(route) {
7
18
  const html = route.route_url
8
19
  ? $('<a>').attr('href', route.route_url)
@@ -17,9 +28,7 @@ function formatRoute(route) {
17
28
  .appendTo(html);
18
29
  }
19
30
 
20
- $('<span>')
21
- .text(`${route.route_short_name} ${route.route_long_name}`)
22
- .appendTo(html);
31
+ $('<span>').text(formatRouteName(route)).appendTo(html);
23
32
 
24
33
  return html.prop('outerHTML');
25
34
  }
@@ -107,10 +116,10 @@ function createSystemMap(id, geojson) {
107
116
  duration: 0,
108
117
  });
109
118
 
110
- // Turn of Points of Interest labels
119
+ // Turn off Points of Interest labels
111
120
  map.setLayoutProperty('poi-label', 'visibility', 'none');
112
121
 
113
- // Find the index of the first symbol layer in the map style
122
+ // Find the index of the first symbol layer in the map style to put the route lines underneath
114
123
  let firstSymbolId;
115
124
  for (const layer of map.getStyle().layers) {
116
125
  if (layer.type === 'symbol') {
@@ -149,7 +158,7 @@ function createSystemMap(id, geojson) {
149
158
  layout: lineLayout,
150
159
  filter: ['!has', 'stop_id'],
151
160
  },
152
- firstSymbolId
161
+ firstSymbolId,
153
162
  );
154
163
 
155
164
  // Add highlighted route drop shadow outlines next
@@ -182,7 +191,7 @@ function createSystemMap(id, geojson) {
182
191
  layout: lineLayout,
183
192
  filter: ['==', ['get', 'route_id'], 'none'],
184
193
  },
185
- firstSymbolId
194
+ firstSymbolId,
186
195
  );
187
196
 
188
197
  // Add white outlines to routes next
@@ -208,7 +217,7 @@ function createSystemMap(id, geojson) {
208
217
  layout: lineLayout,
209
218
  filter: ['has', 'route_id'],
210
219
  },
211
- firstSymbolId
220
+ firstSymbolId,
212
221
  );
213
222
 
214
223
  // Add highlighted route white outlines next
@@ -234,7 +243,7 @@ function createSystemMap(id, geojson) {
234
243
  layout: lineLayout,
235
244
  filter: ['==', ['get', 'route_id'], 'none'],
236
245
  },
237
- firstSymbolId
246
+ firstSymbolId,
238
247
  );
239
248
 
240
249
  // Add route lines next
@@ -260,7 +269,7 @@ function createSystemMap(id, geojson) {
260
269
  layout: lineLayout,
261
270
  filter: ['has', 'route_id'],
262
271
  },
263
- firstSymbolId
272
+ firstSymbolId,
264
273
  );
265
274
 
266
275
  // Add highlighted route lines next
@@ -286,96 +295,74 @@ function createSystemMap(id, geojson) {
286
295
  layout: lineLayout,
287
296
  filter: ['==', ['get', 'route_id'], 'none'],
288
297
  },
289
- firstSymbolId
298
+ firstSymbolId,
290
299
  );
291
300
 
292
301
  // Add stops when zoomed in
293
- map.addLayer(
294
- {
295
- id: 'stops',
296
- type: 'circle',
297
- source: {
298
- type: 'geojson',
299
- data: geojson,
300
- },
301
- paint: {
302
- 'circle-color': '#fff',
303
- 'circle-radius': {
304
- base: 1.75,
305
- stops: [
306
- [12, 4],
307
- [22, 100],
308
- ],
309
- },
310
- 'circle-stroke-color': '#3F4A5C',
311
- 'circle-stroke-width': 2,
312
- 'circle-opacity': [
313
- 'interpolate',
314
- ['linear'],
315
- ['zoom'],
316
- 13,
317
- 0,
318
- 13.5,
319
- 1,
320
- ],
321
- 'circle-stroke-opacity': [
322
- 'interpolate',
323
- ['linear'],
324
- ['zoom'],
325
- 13,
326
- 0,
327
- 13.5,
328
- 1,
302
+ map.addLayer({
303
+ id: 'stops',
304
+ type: 'circle',
305
+ source: {
306
+ type: 'geojson',
307
+ data: geojson,
308
+ },
309
+ paint: {
310
+ 'circle-color': '#fff',
311
+ 'circle-radius': {
312
+ base: 1.75,
313
+ stops: [
314
+ [12, 4],
315
+ [22, 100],
329
316
  ],
330
317
  },
331
- filter: ['has', 'stop_id'],
318
+ 'circle-stroke-color': '#3F4A5C',
319
+ 'circle-stroke-width': 2,
320
+ 'circle-opacity': ['interpolate', ['linear'], ['zoom'], 13, 0, 13.5, 1],
321
+ 'circle-stroke-opacity': [
322
+ 'interpolate',
323
+ ['linear'],
324
+ ['zoom'],
325
+ 13,
326
+ 0,
327
+ 13.5,
328
+ 1,
329
+ ],
332
330
  },
333
- firstSymbolId
334
- );
331
+ filter: ['has', 'stop_id'],
332
+ });
335
333
 
336
334
  // Layer for highlighted stops
337
- map.addLayer(
338
- {
339
- id: 'stops-highlighted',
340
- type: 'circle',
341
- source: {
342
- type: 'geojson',
343
- data: geojson,
344
- },
345
- paint: {
346
- 'circle-color': '#fff',
347
- 'circle-radius': {
348
- base: 1.75,
349
- stops: [
350
- [12, 5],
351
- [22, 125],
352
- ],
353
- },
354
- 'circle-stroke-width': 2,
355
- 'circle-stroke-color': '#3f4a5c',
356
- 'circle-opacity': [
357
- 'interpolate',
358
- ['linear'],
359
- ['zoom'],
360
- 13,
361
- 0,
362
- 13.5,
363
- 1,
364
- ],
365
- 'circle-stroke-opacity': [
366
- 'interpolate',
367
- ['linear'],
368
- ['zoom'],
369
- 13,
370
- 0,
371
- 13.5,
372
- 1,
335
+ map.addLayer({
336
+ id: 'stops-highlighted',
337
+ type: 'circle',
338
+ source: {
339
+ type: 'geojson',
340
+ data: geojson,
341
+ },
342
+ paint: {
343
+ 'circle-color': '#fff',
344
+ 'circle-radius': {
345
+ base: 1.75,
346
+ stops: [
347
+ [12, 5],
348
+ [22, 125],
373
349
  ],
374
350
  },
375
- filter: ['==', 'stop_id', ''],
351
+ 'circle-stroke-width': 2,
352
+ 'circle-stroke-color': '#3f4a5c',
353
+ 'circle-opacity': ['interpolate', ['linear'], ['zoom'], 13, 0, 13.5, 1],
354
+ 'circle-stroke-opacity': [
355
+ 'interpolate',
356
+ ['linear'],
357
+ ['zoom'],
358
+ 13,
359
+ 0,
360
+ 13.5,
361
+ 1,
362
+ ],
376
363
  },
377
- firstSymbolId
378
- );
364
+ filter: ['==', 'stop_id', ''],
365
+ });
379
366
 
380
367
  // Add labels
381
368
  map.addLayer({
@@ -406,14 +393,14 @@ function createSystemMap(id, geojson) {
406
393
  map.getCanvas().style.cursor = 'pointer';
407
394
  highlightRoutes(
408
395
  _.compact(
409
- _.uniq(features.map((feature) => feature.properties.route_id))
410
- )
396
+ _.uniq(features.map((feature) => feature.properties.route_id)),
397
+ ),
411
398
  );
412
399
 
413
400
  if (features.some((feature) => feature.layer.id === 'stops')) {
414
401
  highlightStop(
415
402
  features.find((feature) => feature.layer.id === 'stops').properties
416
- .stop_id
403
+ .stop_id,
417
404
  );
418
405
  }
419
406
  } else {
@@ -451,10 +438,10 @@ function createSystemMap(id, geojson) {
451
438
  const routes = _.orderBy(
452
439
  _.uniqBy(
453
440
  routeFeatures,
454
- (feature) => feature.properties.route_short_name
441
+ (feature) => feature.properties.route_short_name,
455
442
  ),
456
443
  (feature) =>
457
- Number.parseInt(feature.properties.route_short_name, 10)
444
+ Number.parseInt(feature.properties.route_short_name, 10),
458
445
  );
459
446
 
460
447
  new mapboxgl.Popup()
@@ -505,11 +492,11 @@ function createSystemMap(id, geojson) {
505
492
  map.setPaintProperty(
506
493
  'route-line-shadows',
507
494
  'line-opacity',
508
- routeLineOpacity
495
+ routeLineOpacity,
509
496
  );
510
497
 
511
498
  const highlightedFeatures = geojson.features.filter((feature) =>
512
- routeIds.includes(feature.properties.route_id)
499
+ routeIds.includes(feature.properties.route_id),
513
500
  );
514
501
 
515
502
  if (highlightedFeatures.length > 0 && zoom) {
@@ -546,7 +533,7 @@ function createSystemMap(id, geojson) {
546
533
  map.setPaintProperty(
547
534
  'route-line-shadows',
548
535
  'line-opacity',
549
- routeLineOpacity
536
+ routeLineOpacity,
550
537
  );
551
538
 
552
539
  if (zoom) {
@@ -566,7 +553,7 @@ function createSystemMap(id, geojson) {
566
553
 
567
554
  $('.overview-list').hover(
568
555
  () => {},
569
- () => unHighlightRoutes(true)
556
+ () => unHighlightRoutes(true),
570
557
  );
571
558
  });
572
559
  });
@@ -3,6 +3,17 @@
3
3
 
4
4
  const maps = {};
5
5
 
6
+ function formatRouteName(route) {
7
+ let routeName = '';
8
+ if (route.route_short_name !== undefined) {
9
+ routeName += route.route_short_name;
10
+ } else if (route.route_long_name !== undefined) {
11
+ routeName += route.route_long_name;
12
+ }
13
+
14
+ return routeName;
15
+ }
16
+
6
17
  function formatRoute(route) {
7
18
  const html = route.route_url
8
19
  ? $('<a>').attr('href', route.route_url)
@@ -17,9 +28,7 @@ function formatRoute(route) {
17
28
  .appendTo(html);
18
29
  }
19
30
 
20
- $('<span>')
21
- .text(`${route.route_short_name} ${route.route_long_name}`)
22
- .appendTo(html);
31
+ $('<span>').text(formatRouteName(route)).appendTo(html);
23
32
 
24
33
  return html.prop('outerHTML');
25
34
  }
@@ -107,10 +116,10 @@ function createMap(id, geojson, routes) {
107
116
  duration: 0,
108
117
  });
109
118
 
110
- // Turn of Points of Interest labels
119
+ // Turn off Points of Interest labels
111
120
  map.setLayoutProperty('poi-label', 'visibility', 'none');
112
121
 
113
- // Find the index of the first symbol layer in the map style
122
+ // Find the index of the first symbol layer in the map style to put the route lines underneath
114
123
  let firstSymbolId;
115
124
  for (const layer of map.getStyle().layers) {
116
125
  if (layer.type === 'symbol') {
@@ -149,7 +158,7 @@ function createMap(id, geojson, routes) {
149
158
  layout: lineLayout,
150
159
  filter: ['!has', 'stop_id'],
151
160
  },
152
- firstSymbolId
161
+ firstSymbolId,
153
162
  );
154
163
 
155
164
  // Add route line outline
@@ -175,7 +184,7 @@ function createMap(id, geojson, routes) {
175
184
  layout: lineLayout,
176
185
  filter: ['!has', 'stop_id'],
177
186
  },
178
- firstSymbolId
187
+ firstSymbolId,
179
188
  );
180
189
 
181
190
  // Add route line
@@ -201,60 +210,54 @@ function createMap(id, geojson, routes) {
201
210
  layout: lineLayout,
202
211
  filter: ['!has', 'stop_id'],
203
212
  },
204
- firstSymbolId
213
+ firstSymbolId,
205
214
  );
206
215
 
207
216
  // Add stops
208
- map.addLayer(
209
- {
210
- id: 'stops',
211
- type: 'circle',
212
- source: {
213
- type: 'geojson',
214
- data: geojson,
215
- },
216
- paint: {
217
- 'circle-color': '#fff',
218
- 'circle-radius': {
219
- base: 1.75,
220
- stops: [
221
- [12, 4],
222
- [22, 100],
223
- ],
224
- },
225
- 'circle-stroke-color': '#3f4a5c',
226
- 'circle-stroke-width': 2,
217
+ map.addLayer({
218
+ id: 'stops',
219
+ type: 'circle',
220
+ source: {
221
+ type: 'geojson',
222
+ data: geojson,
223
+ },
224
+ paint: {
225
+ 'circle-color': '#fff',
226
+ 'circle-radius': {
227
+ base: 1.75,
228
+ stops: [
229
+ [12, 4],
230
+ [22, 100],
231
+ ],
227
232
  },
228
- filter: ['has', 'stop_id'],
233
+ 'circle-stroke-color': '#3f4a5c',
234
+ 'circle-stroke-width': 2,
229
235
  },
230
- firstSymbolId
231
- );
236
+ filter: ['has', 'stop_id'],
237
+ });
232
238
 
233
239
  // Layer for highlighted stops
234
- map.addLayer(
235
- {
236
- id: 'stops-highlighted',
237
- type: 'circle',
238
- source: {
239
- type: 'geojson',
240
- data: geojson,
241
- },
242
- paint: {
243
- 'circle-color': '#fff',
244
- 'circle-radius': {
245
- base: 1.75,
246
- stops: [
247
- [12, 5],
248
- [22, 125],
249
- ],
250
- },
251
- 'circle-stroke-width': 2,
252
- 'circle-stroke-color': '#3f4a5c',
240
+ map.addLayer({
241
+ id: 'stops-highlighted',
242
+ type: 'circle',
243
+ source: {
244
+ type: 'geojson',
245
+ data: geojson,
246
+ },
247
+ paint: {
248
+ 'circle-color': '#fff',
249
+ 'circle-radius': {
250
+ base: 1.75,
251
+ stops: [
252
+ [12, 5],
253
+ [22, 125],
254
+ ],
253
255
  },
254
- filter: ['==', 'stop_id', ''],
256
+ 'circle-stroke-width': 2,
257
+ 'circle-stroke-color': '#3f4a5c',
255
258
  },
256
- firstSymbolId
257
- );
259
+ filter: ['==', 'stop_id', ''],
260
+ });
258
261
 
259
262
  map.on('mousemove', (event) => {
260
263
  const features = map.queryRenderedFeatures(event.point, {
@@ -4,11 +4,11 @@ block content
4
4
 
5
5
  block extraHeader
6
6
  if config.showMap
7
- script(src="https://unpkg.com/jquery@3.6.0/dist/jquery.min.js" crossorigin="anonymous")
7
+ script(src="https://unpkg.com/jquery@3.7.1/dist/jquery.min.js" crossorigin="anonymous")
8
8
  script(src="https://unpkg.com/lodash@4.17.21/lodash.min.js" crossorigin="anonymous")
9
- script(src="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.js")
9
+ script(src="https://api.mapbox.com/mapbox-gl-js/v3.1.0/mapbox-gl.js")
10
10
  script.
11
11
  mapboxgl.accessToken = '#{config.mapboxAccessToken}';
12
12
  script(src=`${config.assetPath}js/system-map.js`)
13
13
 
14
- link(href="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.css" rel="stylesheet")
14
+ link(href="https://api.mapbox.com/mapbox-gl-js/v3.1.0/mapbox-gl.css" rel="stylesheet")
@@ -3,16 +3,16 @@ block content
3
3
  include timetablepage.pug
4
4
 
5
5
  block extraHeader
6
- script(src="https://unpkg.com/jquery@3.6.0/dist/jquery.min.js" crossorigin="anonymous")
6
+ script(src="https://unpkg.com/jquery@3.7.1/dist/jquery.min.js" crossorigin="anonymous")
7
7
 
8
8
  if config.menuType === 'radio'
9
9
  script(src=`${config.assetPath}js/timetable-menu.js`)
10
10
 
11
11
  if config.showMap
12
- script(src="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.js")
12
+ script(src="https://api.mapbox.com/mapbox-gl-js/v3.1.0/mapbox-gl.js")
13
13
  script.
14
14
  mapboxgl.accessToken = '#{config.mapboxAccessToken}';
15
15
  script(src=`${config.assetPath}js/timetable-map.js`)
16
16
 
17
- link(href="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.css" rel="stylesheet")
17
+ link(href="https://api.mapbox.com/mapbox-gl-js/v3.1.0/mapbox-gl.css" rel="stylesheet")
18
18
 
package/www/package.json CHANGED
@@ -9,8 +9,8 @@
9
9
  "deploy": "docusaurus deploy"
10
10
  },
11
11
  "dependencies": {
12
- "@docusaurus/core": "^3.0.1",
13
- "@docusaurus/preset-classic": "^3.0.1",
12
+ "@docusaurus/core": "^3.1.0",
13
+ "@docusaurus/preset-classic": "^3.1.0",
14
14
  "clsx": "^2.1.0",
15
15
  "react": "^18.2.0",
16
16
  "react-dom": "^18.2.0"