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/index.d.ts
CHANGED
|
@@ -7,8 +7,8 @@ interface IConfig {
|
|
|
7
7
|
exclude?: string[];
|
|
8
8
|
}[];
|
|
9
9
|
coordinatePrecision?: number;
|
|
10
|
-
outputType?: string;
|
|
11
10
|
outputFormat?: string;
|
|
11
|
+
outputPath?: string;
|
|
12
12
|
startDate?: string;
|
|
13
13
|
endDate?: string;
|
|
14
14
|
verbose?: boolean;
|
|
@@ -19,6 +19,6 @@ interface IConfig {
|
|
|
19
19
|
logError: (text: string) => void;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
declare const gtfsToHtml: (initialConfig: IConfig) => Promise<
|
|
22
|
+
declare const gtfsToHtml: (initialConfig: IConfig) => Promise<string>;
|
|
23
23
|
|
|
24
24
|
export { gtfsToHtml as default };
|
package/dist/index.js
CHANGED
|
@@ -11,12 +11,20 @@ import { map } from "lodash-es";
|
|
|
11
11
|
import { openDb as openDb2, importGtfs } from "gtfs";
|
|
12
12
|
import sanitize2 from "sanitize-filename";
|
|
13
13
|
import Timer from "timer-machine";
|
|
14
|
+
import untildify2 from "untildify";
|
|
14
15
|
|
|
15
16
|
// src/lib/file-utils.ts
|
|
16
17
|
import { dirname, join, resolve } from "node:path";
|
|
17
18
|
import { createWriteStream } from "node:fs";
|
|
18
19
|
import { fileURLToPath } from "node:url";
|
|
19
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
access,
|
|
22
|
+
cp,
|
|
23
|
+
copyFile,
|
|
24
|
+
mkdir,
|
|
25
|
+
readdir,
|
|
26
|
+
readFile
|
|
27
|
+
} from "node:fs/promises";
|
|
20
28
|
import _ from "lodash-es";
|
|
21
29
|
import archiver from "archiver";
|
|
22
30
|
import beautify from "js-beautify";
|
|
@@ -325,7 +333,7 @@ function formatTripNameForCSV(trip, timetable) {
|
|
|
325
333
|
}
|
|
326
334
|
|
|
327
335
|
// package.json
|
|
328
|
-
var version = "2.9.
|
|
336
|
+
var version = "2.9.3";
|
|
329
337
|
|
|
330
338
|
// src/lib/utils.ts
|
|
331
339
|
var isTimepoint = (stoptime) => {
|
|
@@ -1304,7 +1312,10 @@ function setDefaultConfig(initialConfig) {
|
|
|
1304
1312
|
config.menuType = "none";
|
|
1305
1313
|
}
|
|
1306
1314
|
config.hasGtfsRealtime = config.agencies.some(
|
|
1307
|
-
(agency) => agency.realtimeTripUpdates?.url || agency.realtimeVehiclePositions?.url
|
|
1315
|
+
(agency) => agency.realtimeTripUpdates?.url || agency.realtimeVehiclePositions?.url || agency.realtimeAlerts?.url
|
|
1316
|
+
);
|
|
1317
|
+
config.hasGtfsRealtimeAlerts = config.agencies.some(
|
|
1318
|
+
(agency) => agency.realtimeAlerts?.url
|
|
1308
1319
|
);
|
|
1309
1320
|
return config;
|
|
1310
1321
|
}
|
|
@@ -1806,25 +1817,34 @@ function getPathToTemplateFile(templateFileName, config) {
|
|
|
1806
1817
|
const fullTemplateFileName = config.noHead !== true ? `${templateFileName}_full.pug` : `${templateFileName}.pug`;
|
|
1807
1818
|
return join(getPathToViewsFolder(config), fullTemplateFileName);
|
|
1808
1819
|
}
|
|
1809
|
-
async function prepDirectory(
|
|
1810
|
-
await rm(exportPath, { recursive: true, force: true });
|
|
1820
|
+
async function prepDirectory(outputPath) {
|
|
1811
1821
|
try {
|
|
1812
|
-
await
|
|
1822
|
+
await access(outputPath);
|
|
1813
1823
|
} catch (error) {
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
)
|
|
1824
|
+
try {
|
|
1825
|
+
await mkdir(outputPath, { recursive: true });
|
|
1826
|
+
} catch (error2) {
|
|
1827
|
+
if (error2?.code === "ENOENT") {
|
|
1828
|
+
throw new Error(
|
|
1829
|
+
`Unable to write to ${outputPath}. Try running this command from a writable directory.`
|
|
1830
|
+
);
|
|
1831
|
+
}
|
|
1832
|
+
throw error2;
|
|
1818
1833
|
}
|
|
1819
|
-
|
|
1834
|
+
}
|
|
1835
|
+
const files = await readdir(outputPath);
|
|
1836
|
+
if (files.length > 0) {
|
|
1837
|
+
throw new Error(
|
|
1838
|
+
`Output directory ${outputPath} is not empty. Please specify an empty directory.`
|
|
1839
|
+
);
|
|
1820
1840
|
}
|
|
1821
1841
|
}
|
|
1822
|
-
async function copyStaticAssets(config,
|
|
1842
|
+
async function copyStaticAssets(config, outputPath) {
|
|
1823
1843
|
const viewsFolderPath = getPathToViewsFolder(config);
|
|
1824
1844
|
const foldersToCopy = ["css", "js", "img"];
|
|
1825
1845
|
for (const folder of foldersToCopy) {
|
|
1826
1846
|
if (await access(join(viewsFolderPath, folder)).then(() => true).catch(() => false)) {
|
|
1827
|
-
await cp(join(viewsFolderPath, folder), join(
|
|
1847
|
+
await cp(join(viewsFolderPath, folder), join(outputPath, folder), {
|
|
1828
1848
|
recursive: true
|
|
1829
1849
|
});
|
|
1830
1850
|
}
|
|
@@ -1832,23 +1852,23 @@ async function copyStaticAssets(config, exportPath) {
|
|
|
1832
1852
|
if (config.hasGtfsRealtime) {
|
|
1833
1853
|
await copyFile(
|
|
1834
1854
|
"node_modules/pbf/dist/pbf.js",
|
|
1835
|
-
join(
|
|
1855
|
+
join(outputPath, "js/pbf.js")
|
|
1836
1856
|
);
|
|
1837
1857
|
await copyFile(
|
|
1838
1858
|
"node_modules/gtfs-realtime-pbf-js-module/gtfs-realtime.browser.proto.js",
|
|
1839
|
-
join(
|
|
1859
|
+
join(outputPath, "js/gtfs-realtime.browser.proto.js")
|
|
1840
1860
|
);
|
|
1841
1861
|
}
|
|
1842
1862
|
}
|
|
1843
|
-
function zipFolder(
|
|
1844
|
-
const output = createWriteStream(join(
|
|
1863
|
+
function zipFolder(outputPath) {
|
|
1864
|
+
const output = createWriteStream(join(outputPath, "timetables.zip"));
|
|
1845
1865
|
const archive = archiver("zip");
|
|
1846
1866
|
return new Promise((resolve2, reject) => {
|
|
1847
1867
|
output.on("close", resolve2);
|
|
1848
1868
|
archive.on("error", reject);
|
|
1849
1869
|
archive.pipe(output);
|
|
1850
1870
|
archive.glob("**/*.{txt,css,js,html}", {
|
|
1851
|
-
cwd:
|
|
1871
|
+
cwd: outputPath
|
|
1852
1872
|
});
|
|
1853
1873
|
archive.finalize();
|
|
1854
1874
|
});
|
|
@@ -2082,8 +2102,8 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2082
2102
|
const agencyKey = config.agencies.map(
|
|
2083
2103
|
(agency) => agency.agencyKey ?? agency.agency_key ?? "unknown"
|
|
2084
2104
|
).join("-");
|
|
2085
|
-
const
|
|
2086
|
-
const
|
|
2105
|
+
const outputPath = config.outputPath ? untildify2(config.outputPath) : path.join(process.cwd(), "html", sanitize2(agencyKey));
|
|
2106
|
+
const stats = {
|
|
2087
2107
|
timetables: 0,
|
|
2088
2108
|
timetablePages: 0,
|
|
2089
2109
|
calendars: 0,
|
|
@@ -2097,9 +2117,9 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2097
2117
|
getTimetablePagesForAgency(config),
|
|
2098
2118
|
"timetable_page_id"
|
|
2099
2119
|
);
|
|
2100
|
-
await prepDirectory(
|
|
2120
|
+
await prepDirectory(outputPath);
|
|
2101
2121
|
if (config.noHead !== true && ["html", "pdf"].includes(config.outputFormat)) {
|
|
2102
|
-
await copyStaticAssets(config,
|
|
2122
|
+
await copyStaticAssets(config, outputPath);
|
|
2103
2123
|
}
|
|
2104
2124
|
const bar = progressBar(
|
|
2105
2125
|
`${agencyKey}: Generating ${config.outputFormat.toUpperCase()} timetables {bar} {value}/{total}`,
|
|
@@ -2114,7 +2134,7 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2114
2134
|
);
|
|
2115
2135
|
for (const timetable of timetablePage.timetables) {
|
|
2116
2136
|
for (const warning of timetable.warnings) {
|
|
2117
|
-
|
|
2137
|
+
stats.warnings.push(warning);
|
|
2118
2138
|
bar?.interrupt(warning);
|
|
2119
2139
|
}
|
|
2120
2140
|
}
|
|
@@ -2123,10 +2143,10 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2123
2143
|
`No timetables found for timetable_page_id=${timetablePage.timetable_page_id}`
|
|
2124
2144
|
);
|
|
2125
2145
|
}
|
|
2126
|
-
|
|
2127
|
-
|
|
2146
|
+
stats.timetables += timetablePage.consolidatedTimetables.length;
|
|
2147
|
+
stats.timetablePages += 1;
|
|
2128
2148
|
const datePath = generateFolderName(timetablePage);
|
|
2129
|
-
await mkdir2(path.join(
|
|
2149
|
+
await mkdir2(path.join(outputPath, datePath), { recursive: true });
|
|
2130
2150
|
config.assetPath = "../";
|
|
2131
2151
|
timetablePage.relativePath = path.join(
|
|
2132
2152
|
datePath,
|
|
@@ -2136,7 +2156,7 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2136
2156
|
for (const timetable of timetablePage.consolidatedTimetables) {
|
|
2137
2157
|
const csv = await generateTimetableCSV(timetable);
|
|
2138
2158
|
const csvPath = path.join(
|
|
2139
|
-
|
|
2159
|
+
outputPath,
|
|
2140
2160
|
datePath,
|
|
2141
2161
|
generateFileName(timetable, config, "csv")
|
|
2142
2162
|
);
|
|
@@ -2145,7 +2165,7 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2145
2165
|
} else {
|
|
2146
2166
|
const html = await generateTimetableHTML(timetablePage, config);
|
|
2147
2167
|
const htmlPath = path.join(
|
|
2148
|
-
|
|
2168
|
+
outputPath,
|
|
2149
2169
|
datePath,
|
|
2150
2170
|
sanitize2(timetablePage.filename)
|
|
2151
2171
|
);
|
|
@@ -2156,12 +2176,12 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2156
2176
|
}
|
|
2157
2177
|
timetablePages.push(timetablePage);
|
|
2158
2178
|
const timetableStats = generateStats(timetablePage);
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2179
|
+
stats.stops += timetableStats.stops;
|
|
2180
|
+
stats.routes += timetableStats.routes;
|
|
2181
|
+
stats.trips += timetableStats.trips;
|
|
2182
|
+
stats.calendars += timetableStats.calendars;
|
|
2163
2183
|
} catch (error) {
|
|
2164
|
-
|
|
2184
|
+
stats.warnings.push(error?.message);
|
|
2165
2185
|
bar?.interrupt(error.message);
|
|
2166
2186
|
}
|
|
2167
2187
|
bar?.increment();
|
|
@@ -2169,26 +2189,27 @@ var gtfsToHtml = async (initialConfig) => {
|
|
|
2169
2189
|
if (config.outputFormat === "html") {
|
|
2170
2190
|
config.assetPath = "";
|
|
2171
2191
|
const html = await generateOverviewHTML(timetablePages, config);
|
|
2172
|
-
await writeFile(path.join(
|
|
2192
|
+
await writeFile(path.join(outputPath, "index.html"), html);
|
|
2173
2193
|
}
|
|
2174
|
-
const logText = generateLogText(
|
|
2175
|
-
await writeFile(path.join(
|
|
2194
|
+
const logText = generateLogText(stats, config);
|
|
2195
|
+
await writeFile(path.join(outputPath, "log.txt"), logText);
|
|
2176
2196
|
if (config.zipOutput) {
|
|
2177
|
-
await zipFolder(
|
|
2197
|
+
await zipFolder(outputPath);
|
|
2178
2198
|
}
|
|
2179
|
-
const
|
|
2180
|
-
|
|
2199
|
+
const fullOutputPath = path.join(
|
|
2200
|
+
outputPath,
|
|
2181
2201
|
config.zipOutput ? "/timetables.zip" : ""
|
|
2182
2202
|
);
|
|
2183
2203
|
config.log(
|
|
2184
|
-
`${agencyKey}: ${config.outputFormat.toUpperCase()} timetables created at ${
|
|
2204
|
+
`${agencyKey}: ${config.outputFormat.toUpperCase()} timetables created at ${fullOutputPath}`
|
|
2185
2205
|
);
|
|
2186
|
-
logStats(
|
|
2206
|
+
logStats(stats, config);
|
|
2187
2207
|
const seconds = Math.round(timer.time() / 1e3);
|
|
2188
2208
|
config.log(
|
|
2189
2209
|
`${agencyKey}: ${config.outputFormat.toUpperCase()} timetable generation required ${seconds} seconds`
|
|
2190
2210
|
);
|
|
2191
2211
|
timer.stop();
|
|
2212
|
+
return fullOutputPath;
|
|
2192
2213
|
};
|
|
2193
2214
|
var gtfs_to_html_default = gtfsToHtml;
|
|
2194
2215
|
export {
|