gtfs-to-html 2.11.1 → 2.11.3

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/README.md CHANGED
@@ -83,6 +83,7 @@ Many transit agencies use `gtfs-to-html` to generate the schedule pages used on
83
83
  | [MVgo](https://mvgo.org) | Mountain View, California |
84
84
  | [Petaluma Transit](https://transit.cityofpetaluma.net) | Petaluma, California |
85
85
  | [rabbittransit](https://www.rabbittransit.org) | York and Adams County, Pennsylvania |
86
+ | [River Valley Transit](https://rivervalleytransit.com) | Middletown, Connecticut |
86
87
  | [Rogue Valley Transportation District](https://rvtd.org) | Medford, Oregon |
87
88
  | [RTC Washoe](https://www.rtcwashoe.com) | Reno, Nevada |
88
89
  | [Santa Barbara Metropolitan Transit District](https://sbmtd.gov) | Santa Barbara, California |
package/dist/app/index.js CHANGED
@@ -40,6 +40,9 @@ function toGTFSTime(time) {
40
40
  return time.format("HH:mm:ss");
41
41
  }
42
42
  function calendarToCalendarCode(c) {
43
+ if (Object.values(c).every((value) => value === null)) {
44
+ return "";
45
+ }
43
46
  return `${c.monday}${c.tuesday}${c.wednesday}${c.thursday}${c.friday}${c.saturday}${c.sunday}`;
44
47
  }
45
48
  function calendarCodeToCalendar(code) {
@@ -287,7 +290,12 @@ function generateTimetablePageFileName(timetablePage, config2) {
287
290
  return sanitize(`${formatRouteNameForFilename(route).toLowerCase()}.html`);
288
291
  }
289
292
  const timetable = timetablePage.timetables[0];
290
- let filename = timetable.timetable_id ?? "";
293
+ if (timetable.timetable_id) {
294
+ return sanitize(
295
+ `${timetable.timetable_id.replace(/\|/g, "_").toLowerCase()}.html`
296
+ );
297
+ }
298
+ let filename = "";
291
299
  for (const route of timetable.routes) {
292
300
  filename += `_${formatRouteNameForFilename(route)}`;
293
301
  }
@@ -422,7 +430,7 @@ function getAgencyGeoJSON(config2) {
422
430
  // package.json
423
431
  var package_default = {
424
432
  name: "gtfs-to-html",
425
- version: "2.11.1",
433
+ version: "2.11.3",
426
434
  private: false,
427
435
  description: "Build human readable transit timetables as HTML, PDF or CSV from GTFS",
428
436
  keywords: [
@@ -484,7 +492,7 @@ var package_default = {
484
492
  pbf: "^4.0.1",
485
493
  "pretty-error": "^4.0.0",
486
494
  pug: "^3.0.3",
487
- puppeteer: "^24.21.0",
495
+ puppeteer: "^24.23.0",
488
496
  "sanitize-filename": "^1.6.3",
489
497
  "sanitize-html": "^2.17.0",
490
498
  sqlstring: "^2.3.3",
@@ -494,22 +502,23 @@ var package_default = {
494
502
  },
495
503
  devDependencies: {
496
504
  "@types/archiver": "^6.0.3",
505
+ "@types/cli-table": "^0.3.4",
497
506
  "@types/express": "^5.0.3",
498
507
  "@types/insane": "^1.0.0",
499
508
  "@types/js-beautify": "^1.14.3",
500
509
  "@types/lodash-es": "^4.17.12",
501
510
  "@types/morgan": "^1.9.10",
502
- "@types/node": "^22",
511
+ "@types/node": "^24",
503
512
  "@types/pug": "^2.0.10",
504
513
  "@types/sanitize-html": "^2.16.0",
505
514
  "@types/sqlstring": "^2.3.2",
506
515
  "@types/toposort": "^2.0.7",
507
516
  "@types/yargs": "^17.0.33",
508
517
  husky: "^9.1.7",
509
- "lint-staged": "^16.1.6",
518
+ "lint-staged": "^16.2.3",
510
519
  prettier: "^3.6.2",
511
520
  tsup: "^8.5.0",
512
- typescript: "^5.9.2"
521
+ typescript: "^5.9.3"
513
522
  },
514
523
  engines: {
515
524
  node: ">= 22"
@@ -636,9 +645,6 @@ var sortTrips = (trips, config2) => {
636
645
  const lastStopId = last(longestTripStoptimes).stop_id;
637
646
  sortedTrips = sortTripsByStoptimeAtStop(trips, lastStopId);
638
647
  }
639
- if (config2.showDuplicateTrips === false) {
640
- return deduplicateTrips(sortedTrips ?? []);
641
- }
642
648
  return sortedTrips ?? [];
643
649
  };
644
650
  var sortTripsByStoptimeAtStop = (trips, stopId) => sortBy(trips, (trip) => {
@@ -814,7 +820,15 @@ var createTimetable = ({
814
820
  ...calendars?.map((calendar) => calendar.service_id) ?? [],
815
821
  ...calendarDates?.map((calendarDate) => calendarDate.service_id) ?? []
816
822
  ]);
817
- const days2 = {};
823
+ const days2 = {
824
+ monday: null,
825
+ tuesday: null,
826
+ wednesday: null,
827
+ thursday: null,
828
+ friday: null,
829
+ saturday: null,
830
+ sunday: null
831
+ };
818
832
  let startDate = null;
819
833
  let endDate = null;
820
834
  if (calendars && calendars.length > 0) {
@@ -833,7 +847,8 @@ var createTimetable = ({
833
847
  const timetableId = formatTimetableId({
834
848
  routeIds: [route.route_id],
835
849
  directionId,
836
- days: days2
850
+ days: days2,
851
+ dates: calendarDates?.map((calendarDate) => calendarDate.date)
837
852
  });
838
853
  return {
839
854
  timetable_id: timetableId,
@@ -906,6 +921,9 @@ var convertRoutesToTimetablePages = (config2) => {
906
921
  }
907
922
  }
908
923
  }
924
+ if (timetables.length === 0) {
925
+ continue;
926
+ }
909
927
  if (config2.groupTimetablesIntoPages === true) {
910
928
  timetablePages.push(
911
929
  createTimetablePage({
@@ -1255,7 +1273,7 @@ var addTripContinuation = (trip, timetable) => {
1255
1273
  trip.continues_as_route = nextTrip;
1256
1274
  }
1257
1275
  };
1258
- var filterTrips = (timetable) => {
1276
+ var filterTrips = (timetable, config2) => {
1259
1277
  let filteredTrips = timetable.orderedTrips;
1260
1278
  for (const trip of filteredTrips) {
1261
1279
  const combinedStoptimes = [];
@@ -1279,6 +1297,9 @@ var filterTrips = (timetable) => {
1279
1297
  filteredTrips = filteredTrips.filter(
1280
1298
  (trip) => trip.stoptimes.length > 1
1281
1299
  );
1300
+ if (config2.showDuplicateTrips === false) {
1301
+ filteredTrips = deduplicateTrips(filteredTrips);
1302
+ }
1282
1303
  return filteredTrips;
1283
1304
  };
1284
1305
  var getTripsForTimetable = (timetable, calendars, config2) => {
@@ -1416,7 +1437,10 @@ var formatTimetables = (timetables, config2) => {
1416
1437
  if (config2.showMap) {
1417
1438
  timetable.geojson = getTimetableGeoJSON(timetable, config2);
1418
1439
  }
1419
- timetable.orderedTrips = filterTrips(timetable);
1440
+ timetable.trip_ids = uniq(
1441
+ timetable.orderedTrips.map((trip) => trip.trip_id)
1442
+ );
1443
+ timetable.orderedTrips = filterTrips(timetable, config2);
1420
1444
  timetable.stops = formatStops(timetable, config2);
1421
1445
  return timetable;
1422
1446
  });
@@ -1521,7 +1545,9 @@ var getTimetablePageById = (timetablePageId, config2) => {
1521
1545
  const timetablePages = getTimetablePages({
1522
1546
  timetable_page_id: timetablePageId
1523
1547
  });
1524
- const timetables = mergeTimetablesWithSameId(getTimetables());
1548
+ const timetables = mergeTimetablesWithSameId(
1549
+ getTimetables()
1550
+ );
1525
1551
  if (timetablePages.length > 1) {
1526
1552
  throw new Error(
1527
1553
  `Multiple timetable_pages found for timetable_page_id=${timetablePageId}`
@@ -1942,9 +1968,15 @@ function formatFrequency(frequency, config2) {
1942
1968
  function formatTimetableId({
1943
1969
  routeIds,
1944
1970
  directionId,
1945
- days: days2
1971
+ days: days2,
1972
+ dates
1946
1973
  }) {
1947
- let timetableId = `${routeIds.join("_")}|${calendarToCalendarCode(days2)}`;
1974
+ let timetableId = routeIds.join("_");
1975
+ if (calendarToCalendarCode(days2)) {
1976
+ timetableId += `|${calendarToCalendarCode(days2)}`;
1977
+ } else if (dates && dates.length > 0) {
1978
+ timetableId += `|${dates.join("_")}`;
1979
+ }
1948
1980
  if (!isNullOrEmpty(directionId)) {
1949
1981
  timetableId += `|${directionId}`;
1950
1982
  }