gtfs-to-html 2.9.3 → 2.9.4
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/dist/app/index.js +5 -2
- package/dist/app/index.js.map +1 -1
- package/dist/bin/gtfs-to-html.js +62 -41
- package/dist/bin/gtfs-to-html.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +62 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/views/default/css/timetable_styles.css +155 -1
- package/views/default/formatting_functions.pug +13 -12
- package/views/default/js/timetable-alerts.js +180 -0
- package/views/default/js/timetable-map.js +10 -5
- package/views/default/timetablepage.pug +9 -2
- package/views/default/timetablepage_full.pug +7 -6
- package/views/default/css/timetable_pdf_styles.css +0 -69
package/dist/bin/gtfs-to-html.js
CHANGED
|
@@ -14,7 +14,14 @@ import PrettyError from "pretty-error";
|
|
|
14
14
|
import { dirname, join, resolve } from "node:path";
|
|
15
15
|
import { createWriteStream } from "node:fs";
|
|
16
16
|
import { fileURLToPath } from "node:url";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
access,
|
|
19
|
+
cp,
|
|
20
|
+
copyFile,
|
|
21
|
+
mkdir,
|
|
22
|
+
readdir,
|
|
23
|
+
readFile
|
|
24
|
+
} from "node:fs/promises";
|
|
18
25
|
import _ from "lodash-es";
|
|
19
26
|
import archiver from "archiver";
|
|
20
27
|
import beautify from "js-beautify";
|
|
@@ -323,7 +330,7 @@ function formatTripNameForCSV(trip, timetable) {
|
|
|
323
330
|
}
|
|
324
331
|
|
|
325
332
|
// package.json
|
|
326
|
-
var version = "2.9.
|
|
333
|
+
var version = "2.9.3";
|
|
327
334
|
|
|
328
335
|
// src/lib/utils.ts
|
|
329
336
|
var isTimepoint = (stoptime) => {
|
|
@@ -1302,7 +1309,10 @@ function setDefaultConfig(initialConfig) {
|
|
|
1302
1309
|
config.menuType = "none";
|
|
1303
1310
|
}
|
|
1304
1311
|
config.hasGtfsRealtime = config.agencies.some(
|
|
1305
|
-
(agency) => agency.realtimeTripUpdates?.url || agency.realtimeVehiclePositions?.url
|
|
1312
|
+
(agency) => agency.realtimeTripUpdates?.url || agency.realtimeVehiclePositions?.url || agency.realtimeAlerts?.url
|
|
1313
|
+
);
|
|
1314
|
+
config.hasGtfsRealtimeAlerts = config.agencies.some(
|
|
1315
|
+
(agency) => agency.realtimeAlerts?.url
|
|
1306
1316
|
);
|
|
1307
1317
|
return config;
|
|
1308
1318
|
}
|
|
@@ -1829,25 +1839,34 @@ function getPathToTemplateFile(templateFileName, config) {
|
|
|
1829
1839
|
const fullTemplateFileName = config.noHead !== true ? `${templateFileName}_full.pug` : `${templateFileName}.pug`;
|
|
1830
1840
|
return join(getPathToViewsFolder(config), fullTemplateFileName);
|
|
1831
1841
|
}
|
|
1832
|
-
async function prepDirectory(
|
|
1833
|
-
await rm(exportPath, { recursive: true, force: true });
|
|
1842
|
+
async function prepDirectory(outputPath) {
|
|
1834
1843
|
try {
|
|
1835
|
-
await
|
|
1844
|
+
await access(outputPath);
|
|
1836
1845
|
} catch (error) {
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
)
|
|
1846
|
+
try {
|
|
1847
|
+
await mkdir(outputPath, { recursive: true });
|
|
1848
|
+
} catch (error2) {
|
|
1849
|
+
if (error2?.code === "ENOENT") {
|
|
1850
|
+
throw new Error(
|
|
1851
|
+
`Unable to write to ${outputPath}. Try running this command from a writable directory.`
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1854
|
+
throw error2;
|
|
1841
1855
|
}
|
|
1842
|
-
|
|
1856
|
+
}
|
|
1857
|
+
const files = await readdir(outputPath);
|
|
1858
|
+
if (files.length > 0) {
|
|
1859
|
+
throw new Error(
|
|
1860
|
+
`Output directory ${outputPath} is not empty. Please specify an empty directory.`
|
|
1861
|
+
);
|
|
1843
1862
|
}
|
|
1844
1863
|
}
|
|
1845
|
-
async function copyStaticAssets(config,
|
|
1864
|
+
async function copyStaticAssets(config, outputPath) {
|
|
1846
1865
|
const viewsFolderPath = getPathToViewsFolder(config);
|
|
1847
1866
|
const foldersToCopy = ["css", "js", "img"];
|
|
1848
1867
|
for (const folder of foldersToCopy) {
|
|
1849
1868
|
if (await access(join(viewsFolderPath, folder)).then(() => true).catch(() => false)) {
|
|
1850
|
-
await cp(join(viewsFolderPath, folder), join(
|
|
1869
|
+
await cp(join(viewsFolderPath, folder), join(outputPath, folder), {
|
|
1851
1870
|
recursive: true
|
|
1852
1871
|
});
|
|
1853
1872
|
}
|
|
@@ -1855,23 +1874,23 @@ async function copyStaticAssets(config, exportPath) {
|
|
|
1855
1874
|
if (config.hasGtfsRealtime) {
|
|
1856
1875
|
await copyFile(
|
|
1857
1876
|
"node_modules/pbf/dist/pbf.js",
|
|
1858
|
-
join(
|
|
1877
|
+
join(outputPath, "js/pbf.js")
|
|
1859
1878
|
);
|
|
1860
1879
|
await copyFile(
|
|
1861
1880
|
"node_modules/gtfs-realtime-pbf-js-module/gtfs-realtime.browser.proto.js",
|
|
1862
|
-
join(
|
|
1881
|
+
join(outputPath, "js/gtfs-realtime.browser.proto.js")
|
|
1863
1882
|
);
|
|
1864
1883
|
}
|
|
1865
1884
|
}
|
|
1866
|
-
function zipFolder(
|
|
1867
|
-
const output = createWriteStream(join(
|
|
1885
|
+
function zipFolder(outputPath) {
|
|
1886
|
+
const output = createWriteStream(join(outputPath, "timetables.zip"));
|
|
1868
1887
|
const archive = archiver("zip");
|
|
1869
1888
|
return new Promise((resolve2, reject) => {
|
|
1870
1889
|
output.on("close", resolve2);
|
|
1871
1890
|
archive.on("error", reject);
|
|
1872
1891
|
archive.pipe(output);
|
|
1873
1892
|
archive.glob("**/*.{txt,css,js,html}", {
|
|
1874
|
-
cwd:
|
|
1893
|
+
cwd: outputPath
|
|
1875
1894
|
});
|
|
1876
1895
|
archive.finalize();
|
|
1877
1896
|
});
|
|
@@ -2085,6 +2104,7 @@ import { map } from "lodash-es";
|
|
|
2085
2104
|
import { openDb as openDb2, importGtfs } from "gtfs";
|
|
2086
2105
|
import sanitize2 from "sanitize-filename";
|
|
2087
2106
|
import Timer from "timer-machine";
|
|
2107
|
+
import untildify2 from "untildify";
|
|
2088
2108
|
var gtfsToHtml = async (initialConfig) => {
|
|
2089
2109
|
const config = setDefaultConfig(initialConfig);
|
|
2090
2110
|
const timer = new Timer();
|
|
@@ -2111,8 +2131,8 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2111
2131
|
const agencyKey = config.agencies.map(
|
|
2112
2132
|
(agency) => agency.agencyKey ?? agency.agency_key ?? "unknown"
|
|
2113
2133
|
).join("-");
|
|
2114
|
-
const
|
|
2115
|
-
const
|
|
2134
|
+
const outputPath = config.outputPath ? untildify2(config.outputPath) : path.join(process.cwd(), "html", sanitize2(agencyKey));
|
|
2135
|
+
const stats = {
|
|
2116
2136
|
timetables: 0,
|
|
2117
2137
|
timetablePages: 0,
|
|
2118
2138
|
calendars: 0,
|
|
@@ -2126,9 +2146,9 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2126
2146
|
getTimetablePagesForAgency(config),
|
|
2127
2147
|
"timetable_page_id"
|
|
2128
2148
|
);
|
|
2129
|
-
await prepDirectory(
|
|
2149
|
+
await prepDirectory(outputPath);
|
|
2130
2150
|
if (config.noHead !== true && ["html", "pdf"].includes(config.outputFormat)) {
|
|
2131
|
-
await copyStaticAssets(config,
|
|
2151
|
+
await copyStaticAssets(config, outputPath);
|
|
2132
2152
|
}
|
|
2133
2153
|
const bar = progressBar(
|
|
2134
2154
|
`${agencyKey}: Generating ${config.outputFormat.toUpperCase()} timetables {bar} {value}/{total}`,
|
|
@@ -2143,7 +2163,7 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2143
2163
|
);
|
|
2144
2164
|
for (const timetable of timetablePage.timetables) {
|
|
2145
2165
|
for (const warning of timetable.warnings) {
|
|
2146
|
-
|
|
2166
|
+
stats.warnings.push(warning);
|
|
2147
2167
|
bar?.interrupt(warning);
|
|
2148
2168
|
}
|
|
2149
2169
|
}
|
|
@@ -2152,10 +2172,10 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2152
2172
|
`No timetables found for timetable_page_id=${timetablePage.timetable_page_id}`
|
|
2153
2173
|
);
|
|
2154
2174
|
}
|
|
2155
|
-
|
|
2156
|
-
|
|
2175
|
+
stats.timetables += timetablePage.consolidatedTimetables.length;
|
|
2176
|
+
stats.timetablePages += 1;
|
|
2157
2177
|
const datePath = generateFolderName(timetablePage);
|
|
2158
|
-
await mkdir2(path.join(
|
|
2178
|
+
await mkdir2(path.join(outputPath, datePath), { recursive: true });
|
|
2159
2179
|
config.assetPath = "../";
|
|
2160
2180
|
timetablePage.relativePath = path.join(
|
|
2161
2181
|
datePath,
|
|
@@ -2165,7 +2185,7 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2165
2185
|
for (const timetable of timetablePage.consolidatedTimetables) {
|
|
2166
2186
|
const csv = await generateTimetableCSV(timetable);
|
|
2167
2187
|
const csvPath = path.join(
|
|
2168
|
-
|
|
2188
|
+
outputPath,
|
|
2169
2189
|
datePath,
|
|
2170
2190
|
generateFileName(timetable, config, "csv")
|
|
2171
2191
|
);
|
|
@@ -2174,7 +2194,7 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2174
2194
|
} else {
|
|
2175
2195
|
const html = await generateTimetableHTML(timetablePage, config);
|
|
2176
2196
|
const htmlPath = path.join(
|
|
2177
|
-
|
|
2197
|
+
outputPath,
|
|
2178
2198
|
datePath,
|
|
2179
2199
|
sanitize2(timetablePage.filename)
|
|
2180
2200
|
);
|
|
@@ -2185,12 +2205,12 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2185
2205
|
}
|
|
2186
2206
|
timetablePages.push(timetablePage);
|
|
2187
2207
|
const timetableStats = generateStats(timetablePage);
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2208
|
+
stats.stops += timetableStats.stops;
|
|
2209
|
+
stats.routes += timetableStats.routes;
|
|
2210
|
+
stats.trips += timetableStats.trips;
|
|
2211
|
+
stats.calendars += timetableStats.calendars;
|
|
2192
2212
|
} catch (error) {
|
|
2193
|
-
|
|
2213
|
+
stats.warnings.push(error?.message);
|
|
2194
2214
|
bar?.interrupt(error.message);
|
|
2195
2215
|
}
|
|
2196
2216
|
bar?.increment();
|
|
@@ -2198,26 +2218,27 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2198
2218
|
if (config.outputFormat === "html") {
|
|
2199
2219
|
config.assetPath = "";
|
|
2200
2220
|
const html = await generateOverviewHTML(timetablePages, config);
|
|
2201
|
-
await writeFile(path.join(
|
|
2221
|
+
await writeFile(path.join(outputPath, "index.html"), html);
|
|
2202
2222
|
}
|
|
2203
|
-
const logText = generateLogText(
|
|
2204
|
-
await writeFile(path.join(
|
|
2223
|
+
const logText = generateLogText(stats, config);
|
|
2224
|
+
await writeFile(path.join(outputPath, "log.txt"), logText);
|
|
2205
2225
|
if (config.zipOutput) {
|
|
2206
|
-
await zipFolder(
|
|
2226
|
+
await zipFolder(outputPath);
|
|
2207
2227
|
}
|
|
2208
|
-
const
|
|
2209
|
-
|
|
2228
|
+
const fullOutputPath = path.join(
|
|
2229
|
+
outputPath,
|
|
2210
2230
|
config.zipOutput ? "/timetables.zip" : ""
|
|
2211
2231
|
);
|
|
2212
2232
|
config.log(
|
|
2213
|
-
`${agencyKey}: ${config.outputFormat.toUpperCase()} timetables created at ${
|
|
2233
|
+
`${agencyKey}: ${config.outputFormat.toUpperCase()} timetables created at ${fullOutputPath}`
|
|
2214
2234
|
);
|
|
2215
|
-
logStats(
|
|
2235
|
+
logStats(stats, config);
|
|
2216
2236
|
const seconds = Math.round(timer.time() / 1e3);
|
|
2217
2237
|
config.log(
|
|
2218
2238
|
`${agencyKey}: ${config.outputFormat.toUpperCase()} timetable generation required ${seconds} seconds`
|
|
2219
2239
|
);
|
|
2220
2240
|
timer.stop();
|
|
2241
|
+
return fullOutputPath;
|
|
2221
2242
|
};
|
|
2222
2243
|
var gtfs_to_html_default = gtfsToHtml;
|
|
2223
2244
|
|