gtfs-to-html 2.5.4 → 2.5.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,19 @@ 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.6] - 2023-08-23
9
+
10
+ ### Updated
11
+
12
+ - Dependency updates
13
+ - Use most common headsign for timetable name
14
+
15
+ ## [2.5.5] - 2023-07-18
16
+
17
+ ### Updated
18
+
19
+ - Dependency updates
20
+
8
21
  ## [2.5.4] - 2023-07-07
9
22
 
10
23
  ### Changed
package/lib/utils.js CHANGED
@@ -3,16 +3,21 @@ import { readFileSync } from 'node:fs';
3
3
  import {
4
4
  cloneDeep,
5
5
  compact,
6
+ countBy,
7
+ entries,
6
8
  every,
7
9
  find,
8
10
  findLast,
9
11
  first,
10
12
  flatMap,
11
13
  flattenDeep,
14
+ flow,
12
15
  isEqual,
13
16
  groupBy,
17
+ head,
14
18
  last,
15
19
  maxBy,
20
+ partialRight,
16
21
  reduce,
17
22
  size,
18
23
  some,
@@ -75,7 +80,7 @@ import {
75
80
  import { formatTripNameForCSV } from './template-functions.js';
76
81
 
77
82
  const { version } = JSON.parse(
78
- readFileSync(new URL('../package.json', import.meta.url))
83
+ readFileSync(new URL('../package.json', import.meta.url)),
79
84
  );
80
85
 
81
86
  /*
@@ -100,7 +105,7 @@ const getLongestTripStoptimes = (trips, config) => {
100
105
  const filteredTripStoptimes =
101
106
  config.showOnlyTimepoint === true
102
107
  ? trips.map((trip) =>
103
- trip.stoptimes.filter((stoptime) => isTimepoint(stoptime))
108
+ trip.stoptimes.filter((stoptime) => isTimepoint(stoptime)),
104
109
  )
105
110
  : trips.map((trip) => trip.stoptimes);
106
111
 
@@ -134,8 +139,8 @@ const findCommonStopId = (trips, config) => {
134
139
  trip.stoptimes.find(
135
140
  (tripStoptime) =>
136
141
  tripStoptime.stop_id === stoptime.stop_id &&
137
- tripStoptime.arrival_time !== null
138
- )
142
+ tripStoptime.arrival_time !== null,
143
+ ),
139
144
  );
140
145
  });
141
146
 
@@ -178,7 +183,7 @@ const deduplicateTrips = (trips, commonStopId) => {
178
183
  // Only add trip if no existing trip with the same set of timepoints has already been added.
179
184
  const tripIsUnique = every(similarTrips, (similarTrip) => {
180
185
  const similarTripStoptimes = similarTrip.stoptimes.map(
181
- (stoptime) => stoptime.departure_time
186
+ (stoptime) => stoptime.departure_time,
182
187
  );
183
188
  return !isEqual(stoptimes, similarTripStoptimes);
184
189
  });
@@ -227,7 +232,7 @@ const sortTrips = (trips, config) => {
227
232
  sortedTrips = sortBy(
228
233
  trips,
229
234
  ['firstStoptime', 'lastStoptime'],
230
- ['asc', 'asc']
235
+ ['asc', 'asc'],
231
236
  );
232
237
  } else if (config.sortingAlgorithm === 'end') {
233
238
  // Sort trips chronologically using last stoptime of each trip, which can be at different stops.
@@ -244,7 +249,7 @@ const sortTrips = (trips, config) => {
244
249
  sortedTrips = sortBy(
245
250
  trips,
246
251
  ['lastStoptime', 'firstStoptime'],
247
- ['asc', 'asc']
252
+ ['asc', 'asc'],
248
253
  );
249
254
  } else if (config.sortingAlgorithm === 'first') {
250
255
  // Sort trips chronologically using the stoptime of a the first stop of the longest trip.
@@ -281,7 +286,7 @@ const getCalendarDatesForTimetable = (timetable, config) => {
281
286
  service_id: timetable.service_ids,
282
287
  },
283
288
  [],
284
- [['date', 'ASC']]
289
+ [['date', 'ASC']],
285
290
  );
286
291
  const start = fromGTFSDate(timetable.start_date);
287
292
  const end = fromGTFSDate(timetable.end_date);
@@ -294,11 +299,11 @@ const getCalendarDatesForTimetable = (timetable, config) => {
294
299
  if (moment(calendarDate.date, 'YYYYMMDD').isBetween(start, end)) {
295
300
  if (calendarDate.exception_type === 1) {
296
301
  filteredCalendarDates.includedDates.push(
297
- formatDate(calendarDate, config.dateFormat)
302
+ formatDate(calendarDate, config.dateFormat),
298
303
  );
299
304
  } else if (calendarDate.exception_type === 2) {
300
305
  filteredCalendarDates.excludedDates.push(
301
- formatDate(calendarDate, config.dateFormat)
306
+ formatDate(calendarDate, config.dateFormat),
302
307
  );
303
308
  }
304
309
  }
@@ -340,14 +345,21 @@ const getDirectionHeadsignFromTimetable = (timetable) => {
340
345
  direction_id: timetable.direction_id,
341
346
  route_id: timetable.route_ids,
342
347
  },
343
- ['trip_headsign']
348
+ ['trip_headsign'],
344
349
  );
345
350
 
346
351
  if (trips.length === 0) {
347
352
  return '';
348
353
  }
349
354
 
350
- return first(trips).trip_headsign;
355
+ const mostCommonHeadsign = flow(
356
+ countBy,
357
+ entries,
358
+ partialRight(maxBy, last),
359
+ head,
360
+ )(compact(trips.map((trip) => trip.trip_headsign)));
361
+
362
+ return mostCommonHeadsign;
351
363
  };
352
364
 
353
365
  /*
@@ -394,13 +406,13 @@ const getTimetableNotesForTimetable = (timetable, config) => {
394
406
  // Note references with stop_sequence must also have stop_id.
395
407
  if (noteReference.stop_id === '' || noteReference.stop_id === null) {
396
408
  config.logWarning(
397
- `Timetable Note Reference for note_id=${noteReference.note_id} has a \`stop_sequence\` but no \`stop_id\` - ignoring`
409
+ `Timetable Note Reference for note_id=${noteReference.note_id} has a \`stop_sequence\` but no \`stop_id\` - ignoring`,
398
410
  );
399
411
  continue;
400
412
  }
401
413
 
402
414
  const stop = timetable.stops.find(
403
- (stop) => stop.stop_id === noteReference.stop_id
415
+ (stop) => stop.stop_id === noteReference.stop_id,
404
416
  );
405
417
 
406
418
  if (!stop) {
@@ -408,7 +420,7 @@ const getTimetableNotesForTimetable = (timetable, config) => {
408
420
  }
409
421
 
410
422
  const tripWithMatchingStopSequence = stop.trips.find(
411
- (trip) => trip.stop_sequence === noteReference.stop_sequence
423
+ (trip) => trip.stop_sequence === noteReference.stop_sequence,
412
424
  );
413
425
 
414
426
  if (tripWithMatchingStopSequence) {
@@ -472,7 +484,7 @@ const convertRouteToTimetablePage = (
472
484
  direction,
473
485
  calendars,
474
486
  calendarDates,
475
- config
487
+ config,
476
488
  ) => {
477
489
  const timetable = {
478
490
  route_ids: [route.route_id],
@@ -501,10 +513,12 @@ const convertRouteToTimetablePage = (
501
513
  Object.assign(timetable, getDaysFromCalendars(calendars));
502
514
 
503
515
  timetable.start_date = toGTFSDate(
504
- moment.min(calendars.map((calendar) => fromGTFSDate(calendar.start_date)))
516
+ moment.min(
517
+ calendars.map((calendar) => fromGTFSDate(calendar.start_date)),
518
+ ),
505
519
  );
506
520
  timetable.end_date = toGTFSDate(
507
- moment.max(calendars.map((calendar) => fromGTFSDate(calendar.end_date)))
521
+ moment.max(calendars.map((calendar) => fromGTFSDate(calendar.end_date))),
508
522
  );
509
523
  }
510
524
 
@@ -528,7 +542,7 @@ const convertRoutesToTimetablePages = (config) => {
528
542
  .prepare(
529
543
  `SELECT * FROM calendar_dates WHERE exception_type = 1 AND service_id NOT IN (${serviceIds
530
544
  .map((serviceId) => `'${serviceId}'`)
531
- .join(', ')})`
545
+ .join(', ')})`,
532
546
  )
533
547
  .all();
534
548
 
@@ -537,7 +551,7 @@ const convertRoutesToTimetablePages = (config) => {
537
551
  {
538
552
  route_id: route.route_id,
539
553
  },
540
- ['trip_headsign', 'direction_id']
554
+ ['trip_headsign', 'direction_id'],
541
555
  );
542
556
  const directions = uniqBy(trips, (trip) => trip.direction_id);
543
557
  const dayGroups = groupBy(calendars, calendarToCalendarCode);
@@ -545,7 +559,7 @@ const convertRoutesToTimetablePages = (config) => {
545
559
 
546
560
  return directions.map((direction) => [
547
561
  Object.values(dayGroups).map((calendars) =>
548
- convertRouteToTimetablePage(route, direction, calendars, null, config)
562
+ convertRouteToTimetablePage(route, direction, calendars, null, config),
549
563
  ),
550
564
  Object.values(calendarDateGroups).map((calendarDates) =>
551
565
  convertRouteToTimetablePage(
@@ -553,8 +567,8 @@ const convertRoutesToTimetablePages = (config) => {
553
567
  direction,
554
568
  null,
555
569
  calendarDates,
556
- config
557
- )
570
+ config,
571
+ ),
558
572
  ),
559
573
  ]);
560
574
  });
@@ -567,7 +581,7 @@ const convertRoutesToTimetablePages = (config) => {
567
581
  */
568
582
  const generateTripsByFrequencies = (trip, frequencies, config) => {
569
583
  const formattedFrequencies = frequencies.map((frequency) =>
570
- formatFrequency(frequency, config)
584
+ formatFrequency(frequency, config),
571
585
  );
572
586
  const resetTrip = resetStoptimesToMidnight(trip);
573
587
  const trips = [];
@@ -600,7 +614,7 @@ const generateTripsByFrequencies = (trip, frequencies, config) => {
600
614
  const duplicateStopsForDifferentArrivalDeparture = (
601
615
  stopIds,
602
616
  timetable,
603
- config
617
+ config,
604
618
  ) => {
605
619
  if (config.showArrivalOnDifference === null) {
606
620
  return stopIds;
@@ -610,7 +624,7 @@ const duplicateStopsForDifferentArrivalDeparture = (
610
624
  for (const stoptime of trip.stoptimes) {
611
625
  const timepointDifference = fromGTFSTime(stoptime.departure_time).diff(
612
626
  fromGTFSTime(stoptime.arrival_time),
613
- 'minutes'
627
+ 'minutes',
614
628
  );
615
629
 
616
630
  if (timepointDifference < config.showArrivalOnDifference) {
@@ -646,12 +660,12 @@ const getStopOrder = (timetable, config) => {
646
660
  timetable_id: timetable.timetable_id,
647
661
  },
648
662
  ['stop_id'],
649
- [['stop_sequence', 'ASC']]
663
+ [['stop_sequence', 'ASC']],
650
664
  );
651
665
 
652
666
  if (timetableStopOrders.length > 0) {
653
667
  return timetableStopOrders.map(
654
- (timetableStopOrder) => timetableStopOrder.stop_id
668
+ (timetableStopOrder) => timetableStopOrder.stop_id,
655
669
  );
656
670
  }
657
671
 
@@ -682,7 +696,7 @@ const getStopOrder = (timetable, config) => {
682
696
  return duplicateStopsForDifferentArrivalDeparture(
683
697
  stopIds,
684
698
  timetable,
685
- config
699
+ config,
686
700
  );
687
701
  } catch {
688
702
  // Ignore errors and move to next strategy.
@@ -691,7 +705,7 @@ const getStopOrder = (timetable, config) => {
691
705
  // Finally, fall back to using the stop order from the trip with the most stoptimes.
692
706
  const longestTripStoptimes = getLongestTripStoptimes(
693
707
  timetable.orderedTrips,
694
- config
708
+ config,
695
709
  );
696
710
  const stopIds = longestTripStoptimes.map((stoptime) => stoptime.stop_id);
697
711
 
@@ -714,7 +728,7 @@ const getStopsForTimetable = (timetable, config) => {
714
728
 
715
729
  if (stops.length === 0) {
716
730
  throw new Error(
717
- `No stop found found for stop_id=${stopId} in timetable_id=${timetable.timetable_id}`
731
+ `No stop found found for stop_id=${stopId} in timetable_id=${timetable.timetable_id}`,
718
732
  );
719
733
  }
720
734
 
@@ -743,7 +757,7 @@ const getStopsForTimetable = (timetable, config) => {
743
757
 
744
758
  for (const stopAttribute of stopAttributes) {
745
759
  const stop = orderedStops.find(
746
- (stop) => stop.stop_id === stopAttribute.stop_id
760
+ (stop) => stop.stop_id === stopAttribute.stop_id,
747
761
  );
748
762
 
749
763
  if (stop) {
@@ -782,7 +796,7 @@ const getCalendarsFromTimetable = (timetable) => {
782
796
 
783
797
  return memo;
784
798
  },
785
- []
799
+ [],
786
800
  );
787
801
 
788
802
  if (dayQueries.length > 0) {
@@ -814,8 +828,8 @@ const getCalendarDatesServiceIds = (startDate, endDate) => {
814
828
  const calendarDates = db
815
829
  .prepare(
816
830
  `SELECT DISTINCT service_id FROM calendar_dates WHERE ${whereClauses.join(
817
- ' AND '
818
- )}`
831
+ ' AND ',
832
+ )}`,
819
833
  )
820
834
  .all();
821
835
  return calendarDates.map((calendarDate) => calendarDate.service_id);
@@ -841,7 +855,7 @@ const getAllStationStopIds = (stopId) => {
841
855
  {
842
856
  parent_station: stop.parent_station,
843
857
  },
844
- ['stop_id']
858
+ ['stop_id'],
845
859
  );
846
860
 
847
861
  return [
@@ -859,7 +873,7 @@ const getTripsWithSameBlock = (trip, timetable) => {
859
873
  block_id: trip.block_id,
860
874
  service_id: timetable.service_ids,
861
875
  },
862
- ['trip_id', 'route_id']
876
+ ['trip_id', 'route_id'],
863
877
  );
864
878
 
865
879
  for (const blockTrip of trips) {
@@ -868,12 +882,12 @@ const getTripsWithSameBlock = (trip, timetable) => {
868
882
  trip_id: blockTrip.trip_id,
869
883
  },
870
884
  [],
871
- [['stop_sequence', 'ASC']]
885
+ [['stop_sequence', 'ASC']],
872
886
  );
873
887
 
874
888
  if (stopTimes.length === 0) {
875
889
  throw new Error(
876
- `No stoptimes found found for trip_id=${blockTrip.trip_id}`
890
+ `No stoptimes found found for trip_id=${blockTrip.trip_id}`,
877
891
  );
878
892
  }
879
893
 
@@ -906,7 +920,7 @@ const addTripContinuation = (trip, timetable) => {
906
920
  blockTrips,
907
921
  (blockTrip) =>
908
922
  blockTrip.lastStoptime.arrival_timestamp <=
909
- firstStoptime.departure_timestamp
923
+ firstStoptime.departure_timestamp,
910
924
  );
911
925
 
912
926
  /*
@@ -936,7 +950,7 @@ const addTripContinuation = (trip, timetable) => {
936
950
  blockTrips,
937
951
  (blockTrip) =>
938
952
  blockTrip.firstStoptime.departure_timestamp >=
939
- lastStoptime.arrival_timestamp
953
+ lastStoptime.arrival_timestamp,
940
954
  );
941
955
 
942
956
  // "Continues As" trips must be a different route_id.
@@ -993,7 +1007,7 @@ const filterTrips = (timetable) => {
993
1007
  const timetableStopIds = new Set(timetable.stops.map((stop) => stop.stop_id));
994
1008
  for (const trip of filteredTrips) {
995
1009
  trip.stoptimes = trip.stoptimes.filter((stoptime) =>
996
- timetableStopIds.has(stoptime.stop_id)
1010
+ timetableStopIds.has(stoptime.stop_id),
997
1011
  );
998
1012
  }
999
1013
 
@@ -1023,10 +1037,10 @@ const getTripsForTimetable = (timetable, calendars, config) => {
1023
1037
  if (trips.length === 0) {
1024
1038
  timetable.warnings.push(
1025
1039
  `No trips found for route_id=${timetable.route_ids.join(
1026
- '_'
1040
+ '_',
1027
1041
  )}, direction_id=${timetable.direction_id}, service_ids=${JSON.stringify(
1028
- timetable.service_ids
1029
- )}, timetable_id=${timetable.timetable_id}`
1042
+ timetable.service_ids,
1043
+ )}, timetable_id=${timetable.timetable_id}`,
1030
1044
  );
1031
1045
  }
1032
1046
 
@@ -1046,7 +1060,7 @@ const getTripsForTimetable = (timetable, calendars, config) => {
1046
1060
  trip_id: formattedTrip.trip_id,
1047
1061
  },
1048
1062
  [],
1049
- [['stop_sequence', 'ASC']]
1063
+ [['stop_sequence', 'ASC']],
1050
1064
  );
1051
1065
 
1052
1066
  if (formattedTrip.stoptimes.length === 0) {
@@ -1055,7 +1069,7 @@ const getTripsForTimetable = (timetable, calendars, config) => {
1055
1069
  formattedTrip.trip_id
1056
1070
  }, route_id=${timetable.route_ids.join('_')}, timetable_id=${
1057
1071
  timetable.timetable_id
1058
- }`
1072
+ }`,
1059
1073
  );
1060
1074
  }
1061
1075
 
@@ -1092,7 +1106,7 @@ const getTripsForTimetable = (timetable, calendars, config) => {
1092
1106
  }
1093
1107
 
1094
1108
  const tripFrequencies = frequencies.filter(
1095
- (frequency) => frequency.trip_id === trip.trip_id
1109
+ (frequency) => frequency.trip_id === trip.trip_id,
1096
1110
  );
1097
1111
 
1098
1112
  if (tripFrequencies.length === 0) {
@@ -1101,7 +1115,7 @@ const getTripsForTimetable = (timetable, calendars, config) => {
1101
1115
  const frequencyTrips = generateTripsByFrequencies(
1102
1116
  formattedTrip,
1103
1117
  frequencies,
1104
- config
1118
+ config,
1105
1119
  );
1106
1120
  formattedTrips.push(...frequencyTrips);
1107
1121
  timetable.frequencies = frequencies;
@@ -1124,13 +1138,13 @@ const getTripsForTimetable = (timetable, calendars, config) => {
1124
1138
  {
1125
1139
  stop_id: uniq(stopIds),
1126
1140
  },
1127
- ['parent_station', 'stop_id']
1141
+ ['parent_station', 'stop_id'],
1128
1142
  );
1129
1143
 
1130
1144
  for (const trip of formattedTrips) {
1131
1145
  for (const stoptime of trip.stoptimes) {
1132
1146
  const parentStationStop = stops.find(
1133
- (stop) => stop.stop_id === stoptime.stop_id
1147
+ (stop) => stop.stop_id === stoptime.stop_id,
1134
1148
  );
1135
1149
  stoptime.stop_id =
1136
1150
  parentStationStop.parent_station || parentStationStop.stop_id;
@@ -1155,7 +1169,7 @@ const formatTimetables = (timetables, config) => {
1155
1169
  if (timetable.include_exceptions === 1) {
1156
1170
  const calendarDatesServiceIds = getCalendarDatesServiceIds(
1157
1171
  timetable.start_date,
1158
- timetable.end_date
1172
+ timetable.end_date,
1159
1173
  );
1160
1174
  serviceIds = uniq([...serviceIds, ...calendarDatesServiceIds]);
1161
1175
  }
@@ -1205,7 +1219,7 @@ const formatTimetables = (timetables, config) => {
1205
1219
  }
1206
1220
 
1207
1221
  return formattedTimetables.filter(
1208
- (timetable) => timetable.orderedTrips.length > 0
1222
+ (timetable) => timetable.orderedTrips.length > 0,
1209
1223
  );
1210
1224
  };
1211
1225
 
@@ -1223,14 +1237,14 @@ export function getTimetablePagesForAgency(config) {
1223
1237
  const timetablePages = getTimetablePages(
1224
1238
  {},
1225
1239
  [],
1226
- [['timetable_page_id', 'ASC']]
1240
+ [['timetable_page_id', 'ASC']],
1227
1241
  );
1228
1242
 
1229
1243
  // Check if there are any timetable pages defined in `timetable_pages.txt`.
1230
1244
  if (timetablePages.length === 0) {
1231
1245
  // If no timetablepages, use timetables
1232
1246
  return timetables.map((timetable) =>
1233
- convertTimetableToTimetablePage(timetable, config)
1247
+ convertTimetableToTimetablePage(timetable, config),
1234
1248
  );
1235
1249
  }
1236
1250
 
@@ -1241,15 +1255,15 @@ export function getTimetablePagesForAgency(config) {
1241
1255
  timetablePage.timetables = sortBy(
1242
1256
  timetables.filter(
1243
1257
  (timetable) =>
1244
- timetable.timetable_page_id === timetablePage.timetable_page_id
1258
+ timetable.timetable_page_id === timetablePage.timetable_page_id,
1245
1259
  ),
1246
- 'timetable_sequence'
1260
+ 'timetable_sequence',
1247
1261
  );
1248
1262
 
1249
1263
  // Add routes for each timetable.
1250
1264
  for (const timetable of timetablePage.timetables) {
1251
1265
  timetable.routes = routes.filter((route) =>
1252
- timetable.route_ids.includes(route.route_id)
1266
+ timetable.route_ids.includes(route.route_id),
1253
1267
  );
1254
1268
  }
1255
1269
 
@@ -1270,7 +1284,7 @@ const getTimetablePageById = (timetablePageId, config) => {
1270
1284
 
1271
1285
  if (timetablePages.length > 1) {
1272
1286
  throw new Error(
1273
- `Multiple timetable_pages found for timetable_page_id=${timetablePageId}`
1287
+ `Multiple timetable_pages found for timetable_page_id=${timetablePageId}`,
1274
1288
  );
1275
1289
  }
1276
1290
 
@@ -1279,9 +1293,9 @@ const getTimetablePageById = (timetablePageId, config) => {
1279
1293
  const timetablePage = timetablePages[0];
1280
1294
  timetablePage.timetables = sortBy(
1281
1295
  timetables.filter(
1282
- (timetable) => timetable.timetable_page_id === timetablePageId
1296
+ (timetable) => timetable.timetable_page_id === timetablePageId,
1283
1297
  ),
1284
- 'timetable_sequence'
1298
+ 'timetable_sequence',
1285
1299
  );
1286
1300
 
1287
1301
  // Add routes for each timetable
@@ -1297,12 +1311,12 @@ const getTimetablePageById = (timetablePageId, config) => {
1297
1311
  if (timetables.length > 0) {
1298
1312
  // If no timetable_page, use timetable defined in `timetables.txt`.
1299
1313
  const timetablePageTimetables = timetables.filter(
1300
- (timetable) => timetable.timetable_id === timetablePageId
1314
+ (timetable) => timetable.timetable_id === timetablePageId,
1301
1315
  );
1302
1316
 
1303
1317
  if (timetablePageTimetables.length === 0) {
1304
1318
  throw new Error(
1305
- `No timetable found for timetable_page_id=${timetablePageId}`
1319
+ `No timetable found for timetable_page_id=${timetablePageId}`,
1306
1320
  );
1307
1321
  }
1308
1322
 
@@ -1335,13 +1349,13 @@ const getTimetablePageById = (timetablePageId, config) => {
1335
1349
  route_id: routeId,
1336
1350
  direction_id: directionId,
1337
1351
  },
1338
- ['trip_headsign', 'direction_id']
1352
+ ['trip_headsign', 'direction_id'],
1339
1353
  );
1340
1354
  const directions = uniqBy(trips, (trip) => trip.direction_id);
1341
1355
 
1342
1356
  if (directions.length === 0) {
1343
1357
  throw new Error(
1344
- `No trips found for timetable_page_id=${timetablePageId} route_id=${routeId} direction_id=${directionId}`
1358
+ `No trips found for timetable_page_id=${timetablePageId} route_id=${routeId} direction_id=${directionId}`,
1345
1359
  );
1346
1360
  }
1347
1361
 
@@ -1362,7 +1376,7 @@ const getTimetablePageById = (timetablePageId, config) => {
1362
1376
  directions[0],
1363
1377
  calendars,
1364
1378
  calendarDates,
1365
- config
1379
+ config,
1366
1380
  );
1367
1381
  };
1368
1382
 
@@ -1437,33 +1451,33 @@ export function getFormattedTimetablePage(timetablePageId, config) {
1437
1451
 
1438
1452
  timetablePage.consolidatedTimetables = formatTimetables(
1439
1453
  timetablePage.timetables,
1440
- config
1454
+ config,
1441
1455
  );
1442
1456
  timetablePage.timetable_page_label = formatTimetablePageLabel(timetablePage);
1443
1457
  timetablePage.dayList = formatDays(
1444
1458
  getDaysFromCalendars(timetablePage.consolidatedTimetables),
1445
- config
1459
+ config,
1446
1460
  );
1447
1461
  timetablePage.dayLists = uniq(
1448
- timetablePage.consolidatedTimetables.map((timetable) => timetable.dayList)
1462
+ timetablePage.consolidatedTimetables.map((timetable) => timetable.dayList),
1449
1463
  );
1450
1464
  timetablePage.route_ids = uniq(
1451
- flatMap(timetablePage.consolidatedTimetables, 'route_ids')
1465
+ flatMap(timetablePage.consolidatedTimetables, 'route_ids'),
1452
1466
  );
1453
1467
 
1454
1468
  const timetableRoutes = getRoutes(
1455
1469
  {
1456
1470
  route_id: timetablePage.route_ids,
1457
1471
  },
1458
- ['route_color', 'route_text_color', 'agency_id']
1472
+ ['route_color', 'route_text_color', 'agency_id'],
1459
1473
  );
1460
1474
 
1461
1475
  timetablePage.routeColors = timetableRoutes.map((route) => route.route_color);
1462
1476
  timetablePage.routeTextColors = timetableRoutes.map(
1463
- (route) => route.route_text_color
1477
+ (route) => route.route_text_color,
1464
1478
  );
1465
1479
  timetablePage.agency_ids = compact(
1466
- timetableRoutes.map((route) => route.agency_id)
1480
+ timetableRoutes.map((route) => route.agency_id),
1467
1481
  );
1468
1482
 
1469
1483
  // Set default filename.
@@ -1537,7 +1551,7 @@ export function generateTimetableCSV(timetable) {
1537
1551
  lines.push([
1538
1552
  '',
1539
1553
  ...timetable.orderedTrips.map((trip) =>
1540
- formatTripNameForCSV(trip, timetable)
1554
+ formatTripNameForCSV(trip, timetable),
1541
1555
  ),
1542
1556
  ]);
1543
1557
 
@@ -1592,7 +1606,7 @@ export function generateOverviewHTML(timetablePages, config) {
1592
1606
  ) {
1593
1607
  return Number.parseInt(
1594
1608
  timetablePage.consolidatedTimetables[0].routes[0].route_short_name,
1595
- 10
1609
+ 10,
1596
1610
  );
1597
1611
  }
1598
1612
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gtfs-to-html",
3
- "version": "2.5.4",
3
+ "version": "2.5.6",
4
4
  "private": false,
5
5
  "description": "Build human readable transit timetables as HTML, PDF or CSV from GTFS",
6
6
  "keywords": [
@@ -37,19 +37,19 @@
37
37
  "dependencies": {
38
38
  "@turf/helpers": "^6.5.0",
39
39
  "@turf/simplify": "^6.5.0",
40
- "archiver": "^5.3.1",
40
+ "archiver": "^6.0.0",
41
41
  "cli-table": "^0.3.11",
42
42
  "copy-dir": "^1.3.0",
43
43
  "csv-stringify": "^6.4.0",
44
44
  "express": "^4.18.2",
45
- "gtfs": "^4.4.1",
46
- "js-beautify": "^1.14.8",
45
+ "gtfs": "^4.5.0",
46
+ "js-beautify": "^1.14.9",
47
47
  "lodash-es": "^4.17.21",
48
48
  "moment": "^2.29.4",
49
49
  "morgan": "^1.10.0",
50
50
  "pretty-error": "^4.0.0",
51
51
  "pug": "^3.0.2",
52
- "puppeteer": "^20.8.0",
52
+ "puppeteer": "^21.1.0",
53
53
  "sanitize-filename": "^1.6.3",
54
54
  "sqlstring": "^2.3.3",
55
55
  "timer-machine": "^1.1.0",
@@ -60,11 +60,11 @@
60
60
  },
61
61
  "devDependencies": {
62
62
  "husky": "^8.0.3",
63
- "lint-staged": "^13.2.3",
64
- "prettier": "^3.0.0"
63
+ "lint-staged": "^14.0.1",
64
+ "prettier": "^3.0.2"
65
65
  },
66
66
  "engines": {
67
- "node": ">= 14.0.0"
67
+ "node": ">= 18.0.0"
68
68
  },
69
69
  "release-it": {
70
70
  "github": {
@@ -21,11 +21,11 @@ title: Related Libraries
21
21
 
22
22
  [`https://github.com/blinktaginc/gtfs-to-chart`](https://github.com/blinktaginc/gtfs-to-chart)
23
23
 
24
- ## Transit Arrivals Widget
24
+ ## Transit Departures Widget
25
25
 
26
- The [Transit Arrivals Widget](https://github.com/BlinkTagInc/transit-arrivals-widget) generates a user-friendly transit realtime arrival widget in HTML format directly from GTFS and GTFS-RT transit data. Most transit agencies have schedule data in GTFS format and many publish realtime arrivals using GTFS-RT. This project generates HTML, JS and CSS for use on a transit agency website to allow users to see when the next vehicle is arriving at a specific stop and includes features like caching, auto-refresh, url parameters and custom templates.
26
+ The [Transit Departures Widget](https://github.com/BlinkTagInc/transit-departures-widget) generates a user-friendly transit realtime departures widget in HTML format directly from GTFS and GTFS-RT transit data. Most transit agencies have schedule data in GTFS format and many publish realtime departure information using GTFS-RT. This project generates HTML, JS and CSS for use on a transit agency website to allow users to see when the next vehicle is departing from a specific stop and includes features like caching, auto-refresh, url parameters and custom templates.
27
27
 
28
- [`https://github.com/BlinkTagInc/transit-arrivals-widget`](https://github.com/BlinkTagInc/transit-arrivals-widget)
28
+ [`https://github.com/BlinkTagInc/transit-departures-widget`](https://github.com/BlinkTagInc/transit-departures-widget)
29
29
 
30
30
  ## GTFS Text-to-Speech Tester
31
31