gtfs-to-html 2.12.8 → 2.12.10
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 +8 -0
- package/dist/app/index.js +88 -72
- package/dist/app/index.js.map +1 -1
- package/dist/bin/gtfs-to-html.js +80 -64
- package/dist/bin/gtfs-to-html.js.map +1 -1
- package/dist/browser/THIRD_PARTY_LICENSES.txt +229 -0
- package/dist/browser/anchorme.min.js +1 -0
- package/dist/browser/gtfs-realtime.browser.proto.js +0 -0
- package/dist/browser/maplibre-gl-geocoder.css +284 -0
- package/dist/browser/maplibre-gl-geocoder.js +2786 -0
- package/dist/browser/maplibre-gl.css +1 -0
- package/dist/browser/maplibre-gl.js +59 -0
- package/dist/browser/maplibre-gl.js.map +1 -0
- package/dist/browser/pbf.js +1 -0
- package/dist/index.js +80 -64
- package/dist/index.js.map +1 -1
- package/package.json +20 -26
- package/scripts/copy-browser-assets.js +144 -0
- package/scripts/postinstall.js +0 -115
package/README.md
CHANGED
|
@@ -61,6 +61,7 @@ Many transit agencies use `gtfs-to-html` to generate the schedule pages used on
|
|
|
61
61
|
|
|
62
62
|
| Agency | Location |
|
|
63
63
|
| ----------------------------------------------------------------------------- | ----------------------------------- |
|
|
64
|
+
| [Asheville Rides Transit (ART)](https://www.ridetheart.com) | Asheville, North Carolina |
|
|
64
65
|
| [Basin Transit](https://basin-transit.com) | Morongo Basin, California |
|
|
65
66
|
| [Bayway Transit](https://www.baywaytransit.org) | Panama City, Florida |
|
|
66
67
|
| [Brockton Area Transit Authority](https://ridebat.com) | Brockton, Massachusetts |
|
|
@@ -120,6 +121,13 @@ Are you using `gtfs-to-html`? Let us know via email [gtfs@blinktag.com](mailto:g
|
|
|
120
121
|
|
|
121
122
|
Pull requests are welcome, as well as [feedback and reporting issues](https://github.com/blinktaginc/gtfs-to-html/issues).
|
|
122
123
|
|
|
124
|
+
### Development Setup
|
|
125
|
+
|
|
126
|
+
pnpm install
|
|
127
|
+
pnpm run build
|
|
128
|
+
|
|
129
|
+
`pnpm install` installs dependencies. `pnpm run build` compiles TypeScript and vendors browser-compatible libraries (maplibre-gl, pbf, anchorme, etc.) from devDependencies into `dist/browser` via `scripts/copy-browser-assets.js`. These vendored files are included in the published npm package so consumers don't need to run any postinstall steps.
|
|
130
|
+
|
|
123
131
|
## Tests
|
|
124
132
|
|
|
125
133
|
npm test
|
package/dist/app/index.js
CHANGED
|
@@ -188,7 +188,7 @@ import {
|
|
|
188
188
|
import { homedir } from "os";
|
|
189
189
|
import * as _ from "lodash-es";
|
|
190
190
|
import { uniqBy } from "lodash-es";
|
|
191
|
-
import
|
|
191
|
+
import { ZipArchive } from "archiver";
|
|
192
192
|
import beautify from "js-beautify";
|
|
193
193
|
import sanitizeHtml from "sanitize-html";
|
|
194
194
|
import { renderFile } from "pug";
|
|
@@ -330,27 +330,6 @@ function isGtfsToHtmlError(error) {
|
|
|
330
330
|
return candidate.name === "GtfsToHtmlError" && typeof candidate.message === "string" && typeof candidate.code === "string" && typeof candidate.category === "string" && typeof candidate.isOperational === "boolean";
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
-
// src/lib/log-utils.ts
|
|
334
|
-
import { clearLine, cursorTo } from "readline";
|
|
335
|
-
import { noop } from "lodash-es";
|
|
336
|
-
import * as colors from "yoctocolors";
|
|
337
|
-
import { getAgencies, getFeedInfo, isGtfsError as isGtfsError2, formatGtfsError } from "gtfs";
|
|
338
|
-
import Table from "cli-table";
|
|
339
|
-
function logWarning(config2) {
|
|
340
|
-
if (config2.logFunction) {
|
|
341
|
-
return config2.logFunction;
|
|
342
|
-
}
|
|
343
|
-
return (text) => {
|
|
344
|
-
process.stdout.write(`
|
|
345
|
-
${formatWarning(text)}
|
|
346
|
-
`);
|
|
347
|
-
};
|
|
348
|
-
}
|
|
349
|
-
function formatWarning(text) {
|
|
350
|
-
const warningMessage = `${colors.underline("Warning")}: ${text}`;
|
|
351
|
-
return colors.yellow(warningMessage);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
333
|
// src/lib/file-utils.ts
|
|
355
334
|
var homeDirectory = homedir();
|
|
356
335
|
function getPathToThisModuleFolder() {
|
|
@@ -426,6 +405,27 @@ import { getShapesAsGeoJSON, getStopsAsGeoJSON } from "gtfs";
|
|
|
426
405
|
import simplify from "@turf/simplify";
|
|
427
406
|
import { featureCollection, round } from "@turf/helpers";
|
|
428
407
|
|
|
408
|
+
// src/lib/log-utils.ts
|
|
409
|
+
import { clearLine, cursorTo } from "readline";
|
|
410
|
+
import { noop } from "lodash-es";
|
|
411
|
+
import * as colors from "yoctocolors";
|
|
412
|
+
import { getAgencies, getFeedInfo, isGtfsError as isGtfsError2, formatGtfsError } from "gtfs";
|
|
413
|
+
import Table from "cli-table";
|
|
414
|
+
function logWarning(config2) {
|
|
415
|
+
if (config2.logFunction) {
|
|
416
|
+
return config2.logFunction;
|
|
417
|
+
}
|
|
418
|
+
return (text) => {
|
|
419
|
+
process.stdout.write(`
|
|
420
|
+
${formatWarning(text)}
|
|
421
|
+
`);
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
function formatWarning(text) {
|
|
425
|
+
const warningMessage = `${colors.underline("Warning")}: ${text}`;
|
|
426
|
+
return colors.yellow(warningMessage);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
429
|
// src/lib/trip-id-utils.ts
|
|
430
430
|
var getBaseTripId = (tripId) => tripId.replace(/_freq_\d+$/, "");
|
|
431
431
|
var getBaseTripIds = (trips) => Array.from(new Set(trips.map((trip) => getBaseTripId(trip.trip_id))));
|
|
@@ -509,7 +509,7 @@ function getAgencyGeoJSON(config2) {
|
|
|
509
509
|
// package.json
|
|
510
510
|
var package_default = {
|
|
511
511
|
name: "gtfs-to-html",
|
|
512
|
-
version: "2.12.
|
|
512
|
+
version: "2.12.10",
|
|
513
513
|
private: false,
|
|
514
514
|
description: "Build human readable transit timetables as HTML, PDF or CSV from GTFS",
|
|
515
515
|
keywords: [
|
|
@@ -552,41 +552,36 @@ var package_default = {
|
|
|
552
552
|
"gtfs-to-html": "dist/bin/gtfs-to-html.js"
|
|
553
553
|
},
|
|
554
554
|
scripts: {
|
|
555
|
-
build: "tsup",
|
|
556
|
-
postbuild: "node scripts/postinstall.js",
|
|
555
|
+
build: "tsup && node scripts/copy-browser-assets.js",
|
|
557
556
|
start: "node ./dist/app",
|
|
558
|
-
prepare: "husky &&
|
|
559
|
-
|
|
557
|
+
prepare: "husky && pnpm run build",
|
|
558
|
+
prepack: "husky && pnpm run build"
|
|
560
559
|
},
|
|
561
560
|
dependencies: {
|
|
562
|
-
"@
|
|
563
|
-
"@turf/
|
|
564
|
-
|
|
565
|
-
anchorme: "^3.0.8",
|
|
566
|
-
archiver: "^7.0.1",
|
|
561
|
+
"@turf/helpers": "^7.3.5",
|
|
562
|
+
"@turf/simplify": "^7.3.5",
|
|
563
|
+
archiver: "^8.0.0",
|
|
567
564
|
"cli-table": "^0.3.11",
|
|
568
565
|
"css.escape": "^1.5.1",
|
|
569
566
|
"csv-stringify": "^6.7.0",
|
|
570
567
|
express: "^5.2.1",
|
|
571
568
|
gtfs: "^4.18.5",
|
|
572
|
-
"gtfs-realtime-pbf-js-module": "^1.0.0",
|
|
573
569
|
"js-beautify": "^1.15.4",
|
|
574
570
|
"lodash-es": "^4.18.1",
|
|
575
|
-
|
|
576
|
-
marked: "^18.0.0",
|
|
571
|
+
marked: "^18.0.3",
|
|
577
572
|
moment: "^2.30.1",
|
|
578
|
-
pbf: "^4.0.1",
|
|
579
573
|
"pretty-error": "^4.0.0",
|
|
580
574
|
pug: "^3.0.4",
|
|
581
|
-
puppeteer: "^24.
|
|
575
|
+
puppeteer: "^24.43.1",
|
|
582
576
|
"sanitize-filename": "^1.6.4",
|
|
583
|
-
"sanitize-html": "^2.17.
|
|
577
|
+
"sanitize-html": "^2.17.4",
|
|
584
578
|
sqlstring: "^2.3.3",
|
|
585
579
|
toposort: "^2.0.2",
|
|
586
580
|
yargs: "^18.0.0",
|
|
587
581
|
yoctocolors: "^2.1.2"
|
|
588
582
|
},
|
|
589
583
|
devDependencies: {
|
|
584
|
+
"@maplibre/maplibre-gl-geocoder": "^1.9.4",
|
|
590
585
|
"@types/archiver": "^7.0.0",
|
|
591
586
|
"@types/cli-table": "^0.3.4",
|
|
592
587
|
"@types/express": "^5.0.6",
|
|
@@ -598,15 +593,20 @@ var package_default = {
|
|
|
598
593
|
"@types/sqlstring": "^2.3.2",
|
|
599
594
|
"@types/toposort": "^2.0.7",
|
|
600
595
|
"@types/yargs": "^17.0.35",
|
|
596
|
+
anchorme: "^3.0.8",
|
|
597
|
+
"gtfs-realtime-pbf-js-module": "^1.0.0",
|
|
601
598
|
husky: "^9.1.7",
|
|
602
|
-
"lint-staged": "^
|
|
603
|
-
|
|
599
|
+
"lint-staged": "^17.0.5",
|
|
600
|
+
"maplibre-gl": "^5.24.0",
|
|
601
|
+
pbf: "^4.0.1",
|
|
602
|
+
prettier: "^3.8.3",
|
|
604
603
|
tsup: "^8.5.1",
|
|
605
|
-
typescript: "^6.0.
|
|
604
|
+
typescript: "^6.0.3"
|
|
606
605
|
},
|
|
607
606
|
engines: {
|
|
608
607
|
node: ">= 22"
|
|
609
608
|
},
|
|
609
|
+
packageManager: "pnpm@11.1.3",
|
|
610
610
|
"release-it": {
|
|
611
611
|
github: {
|
|
612
612
|
release: true
|
|
@@ -617,7 +617,7 @@ var package_default = {
|
|
|
617
617
|
}
|
|
618
618
|
},
|
|
619
619
|
hooks: {
|
|
620
|
-
"after:bump": "
|
|
620
|
+
"after:bump": "pnpm run build"
|
|
621
621
|
}
|
|
622
622
|
},
|
|
623
623
|
prettier: {
|
|
@@ -625,12 +625,6 @@ var package_default = {
|
|
|
625
625
|
},
|
|
626
626
|
"lint-staged": {
|
|
627
627
|
"*.{js,ts,json}": "prettier --write"
|
|
628
|
-
},
|
|
629
|
-
pnpm: {
|
|
630
|
-
onlyBuiltDependencies: [
|
|
631
|
-
"better-sqlite3",
|
|
632
|
-
"puppeteer"
|
|
633
|
-
]
|
|
634
628
|
}
|
|
635
629
|
};
|
|
636
630
|
|
|
@@ -1451,6 +1445,46 @@ var filterTrips = (timetable, calendars, config2) => {
|
|
|
1451
1445
|
if (config2.showDuplicateTrips === false) {
|
|
1452
1446
|
filteredTrips = deduplicateTrips(filteredTrips);
|
|
1453
1447
|
}
|
|
1448
|
+
const dayNames = [
|
|
1449
|
+
"monday",
|
|
1450
|
+
"tuesday",
|
|
1451
|
+
"wednesday",
|
|
1452
|
+
"thursday",
|
|
1453
|
+
"friday",
|
|
1454
|
+
"saturday",
|
|
1455
|
+
"sunday"
|
|
1456
|
+
];
|
|
1457
|
+
const timetableDays = dayNames.filter((day) => timetable[day] === 1);
|
|
1458
|
+
if (timetableDays.length > 1) {
|
|
1459
|
+
const warnedServiceIds = /* @__PURE__ */ new Set();
|
|
1460
|
+
for (const trip of filteredTrips) {
|
|
1461
|
+
const tripServiceIds = [
|
|
1462
|
+
trip.service_id,
|
|
1463
|
+
...trip.additional_service_ids ?? []
|
|
1464
|
+
];
|
|
1465
|
+
const tripCalendars = calendars.filter(
|
|
1466
|
+
(c) => tripServiceIds.includes(c.service_id)
|
|
1467
|
+
);
|
|
1468
|
+
if (tripCalendars.length === 0) {
|
|
1469
|
+
continue;
|
|
1470
|
+
}
|
|
1471
|
+
const tripDays = getDaysFromCalendars(tripCalendars);
|
|
1472
|
+
const missingDays = timetableDays.filter(
|
|
1473
|
+
(day) => (tripDays[day] ?? 0) !== 1
|
|
1474
|
+
);
|
|
1475
|
+
if (missingDays.length > 0) {
|
|
1476
|
+
const serviceIdKey = tripServiceIds.sort().join("|");
|
|
1477
|
+
if (!warnedServiceIds.has(serviceIdKey)) {
|
|
1478
|
+
warnedServiceIds.add(serviceIdKey);
|
|
1479
|
+
const tripDayList = formatDays(tripDays, config2);
|
|
1480
|
+
const timetableDayList = formatDays(timetable, config2);
|
|
1481
|
+
timetable.warnings.push(
|
|
1482
|
+
`Timetable ${timetable.timetable_id} (Routes: ${timetable.routes.map((route) => route.route_short_name).join(", ")}) covers ${timetableDayList} but some trips (service_id=${tripServiceIds.join(", ")}) only run on ${tripDayList}. This may indicate a data issue in the GTFS or that you should generate separate timetables for different days of the week.`
|
|
1483
|
+
);
|
|
1484
|
+
}
|
|
1485
|
+
}
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1454
1488
|
const formattedTrips = filteredTrips.map((trip) => {
|
|
1455
1489
|
const tripCalendars = calendars.filter((calendar) => {
|
|
1456
1490
|
return [
|
|
@@ -2411,30 +2445,12 @@ app.use((req, res, next) => {
|
|
|
2411
2445
|
});
|
|
2412
2446
|
var staticAssetPath = config.templatePath === void 0 ? getPathToViewsFolder(config) : untildify(config.templatePath);
|
|
2413
2447
|
app.use(express.static(staticAssetPath));
|
|
2414
|
-
var
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
route: "/js",
|
|
2421
|
-
package: "@maplibre/maplibre-gl-geocoder",
|
|
2422
|
-
subPath: "../dist"
|
|
2423
|
-
},
|
|
2424
|
-
{ route: "/css", package: "maplibre-gl", subPath: "../dist" },
|
|
2425
|
-
{
|
|
2426
|
-
route: "/css",
|
|
2427
|
-
package: "@maplibre/maplibre-gl-geocoder",
|
|
2428
|
-
subPath: "../dist"
|
|
2429
|
-
}
|
|
2430
|
-
];
|
|
2431
|
-
var resolvePackagePath = (packageName, subPath) => {
|
|
2432
|
-
const packagePath = dirname2(fileURLToPath2(import.meta.resolve(packageName)));
|
|
2433
|
-
return subPath ? join2(packagePath, subPath) : packagePath;
|
|
2434
|
-
};
|
|
2435
|
-
for (const { route, package: pkg, subPath } of frontendLibraryPaths) {
|
|
2436
|
-
app.use(route, express.static(resolvePackagePath(pkg, subPath)));
|
|
2437
|
-
}
|
|
2448
|
+
var browserAssetsPath = join2(
|
|
2449
|
+
dirname2(fileURLToPath2(import.meta.url)),
|
|
2450
|
+
"../browser"
|
|
2451
|
+
);
|
|
2452
|
+
app.use("/js", express.static(browserAssetsPath));
|
|
2453
|
+
app.use("/css", express.static(browserAssetsPath));
|
|
2438
2454
|
app.get("/", async (req, res, next) => {
|
|
2439
2455
|
try {
|
|
2440
2456
|
const timetablePages = [];
|