gtfs-to-chart 1.0.1 → 2.0.2
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 +20 -0
- package/README.md +27 -12
- package/app/index.js +8 -7
- package/app/routes.js +11 -10
- package/bin/gtfs-to-chart.js +13 -11
- package/docs/images/gtfs-to-chart-logo.svg +18 -0
- package/index.js +1 -1
- package/lib/file-utils.js +19 -17
- package/lib/formatters.js +3 -3
- package/lib/gtfs-to-chart.js +28 -26
- package/lib/log-utils.js +21 -21
- package/lib/utils.js +37 -39
- package/package.json +15 -14
- package/views/chart/formatting_functions.pug +3 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
All notable changes to this project will be documented in this file.
|
|
3
|
+
|
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
### Updated
|
|
9
|
+
- Dependency updates
|
|
10
|
+
|
|
11
|
+
## [2.0.1] - 2021-08-17
|
|
12
|
+
### Updated
|
|
13
|
+
- Dependency updates
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Fixes for no shape_dist_traveled
|
|
17
|
+
|
|
18
|
+
## [2.0.0] - 2021-05-14
|
|
19
|
+
### Breaking Changes
|
|
20
|
+
- Converted to ES6 Module
|
package/README.md
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
➡️
|
|
3
|
+
<a href="#installation">Installation</a> |
|
|
4
|
+
<a href="#quick-start">Quick Start</a> |
|
|
5
|
+
<a href="#configuration">Configuration</a>
|
|
6
|
+
⬅️
|
|
7
|
+
<br /><br />
|
|
8
|
+
<img src="docs/images/gtfs-to-chart-logo.svg" alt="GTFS-to-Chart" />
|
|
9
|
+
<br /><br />
|
|
10
|
+
<a href="https://www.npmjs.com/package/gtfs-to-chart" rel="nofollow"><img src="https://img.shields.io/npm/v/gtfs-to-chart.svg?style=flat" style="max-width: 100%;"></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/gtfs-to-chart" rel="nofollow"><img src="https://img.shields.io/npm/dm/gtfs-to-chart.svg?style=flat" style="max-width: 100%;"></a>
|
|
12
|
+
<a href="https://github.com/BlinkTagInc/gtfs-to-chart/actions?query=workflow%3A%22Node+CI%22"><img src="https://img.shields.io/github/workflow/status/BlinkTagInc/gtfs-to-chart/Node%20CI.svg" alt="CircleCI" style="max-width: 100%;"></a>
|
|
13
|
+
<img src="https://img.shields.io/badge/License-MIT-yellow.svg">
|
|
14
|
+
<br /><br />
|
|
15
|
+
Generate stringline charts from GTFS transit data.
|
|
16
|
+
<br /><br />
|
|
17
|
+
<a href="https://nodei.co/npm/gtfs-to-chart/" rel="nofollow"><img src="https://nodei.co/npm/gtfs-to-chart.png?downloads=true" alt="NPM" style="max-width: 100%;"></a>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<hr>
|
|
9
21
|
|
|
10
22
|
`gtfs-to-chart` creates stringline charts showing all vehicles on a transit route from GTFS data.
|
|
11
23
|
|
|
@@ -52,15 +64,18 @@ If you would like to use this library as a command-line utility, you can install
|
|
|
52
64
|
|
|
53
65
|
If you are using this as a node module as part of an application, you can include it in your project's `package.json` file.
|
|
54
66
|
|
|
55
|
-
##
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
### Command-line example
|
|
56
70
|
|
|
57
71
|
gtfs-to-chart --configPath /path/to/your/custom-config.json
|
|
58
72
|
|
|
59
|
-
|
|
73
|
+
### Code example
|
|
60
74
|
|
|
61
75
|
```js
|
|
62
|
-
|
|
63
|
-
|
|
76
|
+
import gtfsToChart from 'gtfs-to-chart';
|
|
77
|
+
import { readFile } from 'fs/promises';
|
|
78
|
+
const config = JSON.parse(await readFile(new URL('./config.json', import.meta.url)));
|
|
64
79
|
|
|
65
80
|
gtfsToChart(config)
|
|
66
81
|
.then(() => {
|
package/app/index.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
import express from 'express';
|
|
5
|
+
import logger from 'morgan';
|
|
6
|
+
import slashes from 'connect-slashes';
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
import routes from './routes.js';
|
|
8
9
|
|
|
9
10
|
const app = express();
|
|
10
11
|
|
|
11
12
|
// View engine setup
|
|
12
|
-
app.set('views', path.join(
|
|
13
|
+
app.set('views', path.join(fileURLToPath(import.meta.url), '../views'));
|
|
13
14
|
app.set('view engine', 'pug');
|
|
14
15
|
|
|
15
16
|
app.use(logger('dev'));
|
|
16
|
-
app.use(express.static(path.join(
|
|
17
|
+
app.use(express.static(path.join(fileURLToPath(import.meta.url), '../../public')));
|
|
17
18
|
app.use(slashes());
|
|
18
19
|
|
|
19
20
|
app.use('/', routes);
|
package/app/routes.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
const express = require('express');
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
import { openDb, getRoutes } from 'gtfs';
|
|
4
|
+
import express from 'express';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import { setDefaultConfig, generateOverviewHTML, generateChartHTML } from '../lib/utils.js';
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const selectedConfig = JSON.parse(readFileSync(new URL('../config.json', import.meta.url)));
|
|
9
|
+
const config = setDefaultConfig(selectedConfig);
|
|
9
10
|
// Override noHead config option so full HTML pages are generated
|
|
10
11
|
config.noHead = false;
|
|
11
12
|
config.assetPath = '/';
|
|
@@ -16,15 +17,15 @@ config.isLocal = true;
|
|
|
16
17
|
|
|
17
18
|
const router = new express.Router();
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
openDb(config);
|
|
20
21
|
|
|
21
22
|
/*
|
|
22
23
|
* Show all routes
|
|
23
24
|
*/
|
|
24
25
|
router.get('/', async (request, response, next) => {
|
|
25
26
|
try {
|
|
26
|
-
const routes = await
|
|
27
|
-
const html = await
|
|
27
|
+
const routes = await getRoutes();
|
|
28
|
+
const html = await generateOverviewHTML(config, routes);
|
|
28
29
|
response.send(html);
|
|
29
30
|
} catch (error) {
|
|
30
31
|
next(error);
|
|
@@ -38,11 +39,11 @@ router.get('/charts/:routeId', async (request, response) => {
|
|
|
38
39
|
const { routeId } = request.params;
|
|
39
40
|
|
|
40
41
|
try {
|
|
41
|
-
const html = await
|
|
42
|
+
const html = await generateChartHTML(config, routeId);
|
|
42
43
|
response.send(html);
|
|
43
44
|
} catch (error) {
|
|
44
45
|
return response.render('error', { error });
|
|
45
46
|
}
|
|
46
47
|
});
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
export default router;
|
package/bin/gtfs-to-chart.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { readFile } from 'node:fs/promises';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
import yargs from 'yargs';
|
|
7
|
+
/* eslint-disable-next-line node/file-extension-in-import */
|
|
8
|
+
import { hideBin } from 'yargs/helpers';
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
import { formatError } from '../lib/log-utils.js';
|
|
11
|
+
import gtfsToChart from '../index.js';
|
|
12
|
+
|
|
13
|
+
const { argv } = yargs(hideBin(process.argv))
|
|
14
|
+
.usage('Usage: $0 --config ./config.json')
|
|
9
15
|
.help()
|
|
10
16
|
.option('c', {
|
|
11
17
|
alias: 'configPath',
|
|
@@ -24,20 +30,16 @@ const argv = require('yargs').usage('Usage: $0 --config ./config.json')
|
|
|
24
30
|
describe: 'Show only stops with a `timepoint` value in `stops.txt`',
|
|
25
31
|
type: 'boolean'
|
|
26
32
|
})
|
|
27
|
-
.default('showOnlyTimepoint', undefined)
|
|
28
|
-
.argv;
|
|
29
|
-
|
|
30
|
-
const logUtils = require('../lib/log-utils');
|
|
31
|
-
const gtfsToChart = require('..');
|
|
33
|
+
.default('showOnlyTimepoint', undefined);
|
|
32
34
|
|
|
33
35
|
function handleError(error) {
|
|
34
36
|
const text = error || 'Unknown Error';
|
|
35
|
-
process.stdout.write(`\n${
|
|
37
|
+
process.stdout.write(`\n${formatError(text)}\n`);
|
|
36
38
|
throw error;
|
|
37
39
|
}
|
|
38
40
|
|
|
39
41
|
const getConfig = async () => {
|
|
40
|
-
const data = await
|
|
42
|
+
const data = await readFile(path.resolve(argv.configPath), 'utf8').catch(() => {
|
|
41
43
|
throw new Error(`Cannot find configuration file at \`${argv.configPath}\`. Use config-sample.json as a starting point, pass --configPath option`);
|
|
42
44
|
});
|
|
43
45
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<svg width="280" height="311" viewBox="0 0 280 311" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M279.142 216.458V95.0263C279.142 82.9559 272.684 71.822 262.162 65.7868L156.951 5.01874C146.43 -1.01645 133.617 -1.01645 123.096 5.01874L17.8843 65.6828C7.36319 71.718 0.904663 82.8518 0.904663 95.0263V216.458C0.904663 228.529 7.36319 239.663 17.8843 245.698L123.096 306.362C133.617 312.397 146.43 312.397 156.951 306.362L262.267 245.594C272.684 239.663 279.142 228.529 279.142 216.458Z" fill="#B46030"/>
|
|
3
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M140.076 292.21C137.471 292.21 134.867 291.482 132.471 290.233L27.2597 229.465C22.572 226.76 19.6553 221.765 19.6553 216.354V95.0263C19.6553 89.6154 22.572 84.6208 27.1555 81.9154L132.471 21.1473C134.763 19.7945 137.367 19.1702 140.076 19.1702C142.784 19.1702 145.284 19.8986 147.68 21.1473L252.996 81.9154C257.683 84.6208 260.6 89.6154 260.6 95.0263V216.458C260.6 221.869 257.683 226.864 252.996 229.569L147.68 290.337C145.284 291.482 142.68 292.21 140.076 292.21Z" fill="#61A8FC"/>
|
|
4
|
+
<mask id="mask0_4_65" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="10" y="133" width="259" height="61">
|
|
5
|
+
<path d="M10.6458 133.301H268.646V193.301H10.6458V133.301Z" fill="white"/>
|
|
6
|
+
</mask>
|
|
7
|
+
<g mask="url(#mask0_4_65)">
|
|
8
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.6458 34.2317H268.646V292.232H10.6458V34.2317Z" fill="#B46030"/>
|
|
9
|
+
</g>
|
|
10
|
+
<mask id="mask1_4_65" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="122" y="244" width="36" height="35">
|
|
11
|
+
<path d="M122 244H157.139V278.037H122V244Z" fill="white"/>
|
|
12
|
+
</mask>
|
|
13
|
+
<g mask="url(#mask1_4_65)">
|
|
14
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M144.917 255.167L157.139 256.912L148.335 265.657L150.471 277.948L139.523 272.186L128.621 278.037L130.658 265.73L121.785 257.056L133.993 255.212L139.41 244L144.917 255.167Z" fill="white"/>
|
|
15
|
+
</g>
|
|
16
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M178.87 65.8803C178.87 64.6713 178.312 63.7413 177.289 63.0903C177.103 62.9973 176.824 62.8113 176.638 62.7183C176.638 59.6494 176.545 56.4875 176.359 53.3256C175.987 46.0718 172.174 42.5378 165.013 42.4448C158.782 42.4448 152.551 42.4448 146.32 42.4448C136.183 42.4448 126.139 42.3518 116.002 42.5378C106.702 42.7238 102.982 46.6297 102.982 55.9295C102.982 58.1614 102.982 60.3934 102.982 62.7183C102.424 62.9043 101.959 63.3693 101.587 63.8343C100.936 64.3923 100.75 65.2293 100.75 66.1592C100.75 70.4371 100.75 74.715 100.75 79.0859C100.75 80.3879 101.215 81.4109 102.331 82.0618C102.61 82.2478 102.796 82.3408 103.075 82.4338C103.075 91.6406 103.075 100.754 103.075 109.961C103.075 111.263 102.889 112.751 103.54 113.867C104.935 116.099 104.656 118.517 104.749 120.935C104.842 123.911 106.795 125.957 109.771 126.05C111.91 126.143 114.049 126.143 116.188 126.05C119.257 125.957 121.21 124.19 121.303 121.121C121.396 119.819 121.582 119.354 123.07 119.354C134.23 119.447 145.483 119.447 156.643 119.354C158.038 119.354 158.41 119.726 158.41 121.121C158.503 124.376 160.456 126.05 163.711 126.05C165.571 126.05 167.431 126.05 169.291 126.05C173.104 126.05 174.964 124.097 175.057 120.284C175.057 118.796 174.592 117.122 175.429 115.727C176.452 113.867 176.731 112.007 176.731 109.961C176.731 101.312 176.731 92.6636 176.731 82.4338C177.382 82.3408 177.94 81.7829 178.312 81.2249C178.777 80.6669 178.963 79.9229 178.963 79.1789C178.87 74.808 178.87 70.3441 178.87 65.8803ZM124.279 49.1407C129.859 49.1407 135.439 49.1407 140.926 49.1407C146.32 49.1407 151.714 49.1407 157.201 49.1407C159.619 49.1407 159.898 49.5127 159.991 52.3026C159.991 55.3715 159.712 55.8365 157.387 55.8365C146.32 55.8365 135.253 55.8365 124.279 55.8365C121.861 55.8365 121.396 55.2785 121.396 52.4886C121.303 49.6987 121.768 49.1407 124.279 49.1407ZM117.304 111.077C114.049 111.077 111.352 108.38 111.352 105.125C111.445 101.963 114.142 99.3594 117.211 99.3594C120.466 99.3594 122.884 101.87 122.884 105.218C122.977 108.473 120.466 111.077 117.304 111.077ZM116.467 90.9896C112.933 90.9896 111.352 89.3157 111.352 85.6888C111.352 79.1789 111.352 72.6691 111.352 66.1592C111.352 62.5323 112.84 61.0444 116.467 61.0444C124.279 61.0444 131.998 61.0444 139.81 61.0444C147.436 61.0444 155.062 61.0444 162.688 61.0444C166.78 61.0444 168.175 62.4393 168.175 66.4382C168.175 72.6691 168.175 78.8999 168.175 85.1308C168.175 88.8507 166.129 90.8966 162.409 90.9896C147.157 90.9896 131.812 90.9896 116.467 90.9896ZM162.409 111.077C159.247 111.077 156.736 108.566 156.643 105.311C156.643 101.963 159.061 99.4524 162.316 99.4524C165.571 99.4524 168.268 102.149 168.268 105.404C168.175 108.38 165.571 111.077 162.409 111.077Z" fill="white"/>
|
|
17
|
+
<path d="M43.9456 179.45C41.5456 179.45 39.7156 178.775 38.4556 177.425C37.1956 176.045 36.5656 174.08 36.5656 171.53V154.97C36.5656 152.42 37.1956 150.47 38.4556 149.12C39.7156 147.74 41.5456 147.05 43.9456 147.05C46.3456 147.05 48.1756 147.74 49.4356 149.12C50.6956 150.47 51.3256 152.42 51.3256 154.97V157.67H46.6456V154.655C46.6456 152.585 45.7906 151.55 44.0806 151.55C42.3706 151.55 41.5156 152.585 41.5156 154.655V171.89C41.5156 173.93 42.3706 174.95 44.0806 174.95C45.7906 174.95 46.6456 173.93 46.6456 171.89V165.725H44.1706V161.225H51.3256V171.53C51.3256 174.08 50.6956 176.045 49.4356 177.425C48.1756 178.775 46.3456 179.45 43.9456 179.45ZM58.3737 152H53.1987V147.5H68.4987V152H63.3237V179H58.3737V152ZM70.8953 147.5H83.9903V152H75.8453V160.775H82.2353V165.275H75.8453V179H70.8953V147.5ZM92.799 179.45C90.399 179.45 88.584 178.775 87.354 177.425C86.124 176.045 85.509 174.08 85.509 171.53V169.73H90.189V171.89C90.189 173.93 91.044 174.95 92.754 174.95C93.594 174.95 94.224 174.71 94.644 174.23C95.094 173.72 95.319 172.91 95.319 171.8C95.319 170.48 95.019 169.325 94.419 168.335C93.819 167.315 92.709 166.1 91.089 164.69C89.049 162.89 87.624 161.27 86.814 159.83C86.004 158.36 85.599 156.71 85.599 154.88C85.599 152.39 86.229 150.47 87.489 149.12C88.749 147.74 90.579 147.05 92.979 147.05C95.349 147.05 97.134 147.74 98.334 149.12C99.564 150.47 100.179 152.42 100.179 154.97V156.275H95.499V154.655C95.499 153.575 95.289 152.795 94.869 152.315C94.449 151.805 93.834 151.55 93.024 151.55C91.374 151.55 90.549 152.555 90.549 154.565C90.549 155.705 90.849 156.77 91.449 157.76C92.079 158.75 93.204 159.95 94.824 161.36C96.894 163.16 98.319 164.795 99.099 166.265C99.879 167.735 100.269 169.46 100.269 171.44C100.269 174.02 99.624 176 98.334 177.38C97.074 178.76 95.229 179.45 92.799 179.45ZM102.211 161H112.111V165.5H102.211V161ZM115.634 152H110.459V147.5H125.759V152H120.584V179H115.634V152ZM135.135 179.45C132.705 179.45 130.845 178.76 129.555 177.38C128.265 176 127.62 174.05 127.62 171.53V154.97C127.62 152.45 128.265 150.5 129.555 149.12C130.845 147.74 132.705 147.05 135.135 147.05C137.565 147.05 139.425 147.74 140.715 149.12C142.005 150.5 142.65 152.45 142.65 154.97V171.53C142.65 174.05 142.005 176 140.715 177.38C139.425 178.76 137.565 179.45 135.135 179.45ZM135.135 174.95C136.845 174.95 137.7 173.915 137.7 171.845V154.655C137.7 152.585 136.845 151.55 135.135 151.55C133.425 151.55 132.57 152.585 132.57 154.655V171.845C132.57 173.915 133.425 174.95 135.135 174.95ZM145.278 161H155.178V165.5H145.278V161ZM165.102 179.45C162.732 179.45 160.917 178.775 159.657 177.425C158.427 176.075 157.812 174.17 157.812 171.71V154.79C157.812 152.33 158.427 150.425 159.657 149.075C160.917 147.725 162.732 147.05 165.102 147.05C167.472 147.05 169.272 147.725 170.502 149.075C171.762 150.425 172.392 152.33 172.392 154.79V158.12H167.712V154.475C167.712 152.525 166.887 151.55 165.237 151.55C163.587 151.55 162.762 152.525 162.762 154.475V172.07C162.762 173.99 163.587 174.95 165.237 174.95C166.887 174.95 167.712 173.99 167.712 172.07V167.255H172.392V171.71C172.392 174.17 171.762 176.075 170.502 177.425C169.272 178.775 167.472 179.45 165.102 179.45ZM175.353 147.5H180.303V160.325H185.613V147.5H190.563V179H185.613V164.825H180.303V179H175.353V147.5ZM198.075 147.5H204.78L209.91 179H204.96L204.06 172.745V172.835H198.435L197.535 179H192.945L198.075 147.5ZM203.475 168.56L201.27 152.99H201.18L199.02 168.56H203.475ZM212.311 147.5H219.646C222.196 147.5 224.056 148.1 225.226 149.3C226.396 150.47 226.981 152.285 226.981 154.745V156.68C226.981 159.95 225.901 162.02 223.741 162.89V162.98C224.941 163.34 225.781 164.075 226.261 165.185C226.771 166.295 227.026 167.78 227.026 169.64V175.175C227.026 176.075 227.056 176.81 227.116 177.38C227.176 177.92 227.326 178.46 227.566 179H222.526C222.346 178.49 222.226 178.01 222.166 177.56C222.106 177.11 222.076 176.3 222.076 175.13V169.37C222.076 167.93 221.836 166.925 221.356 166.355C220.906 165.785 220.111 165.5 218.971 165.5H217.261V179H212.311V147.5ZM219.061 161C220.051 161 220.786 160.745 221.266 160.235C221.776 159.725 222.031 158.87 222.031 157.67V155.24C222.031 154.1 221.821 153.275 221.401 152.765C221.011 152.255 220.381 152 219.511 152H217.261V161H219.061ZM234.243 152H229.068V147.5H244.368V152H239.193V179H234.243V152Z" fill="white"/>
|
|
18
|
+
</svg>
|
package/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export { default } from './lib/gtfs-to-chart.js';
|
package/lib/file-utils.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { rm, mkdir } from 'node:fs/promises';
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
import copy from 'better-copy';
|
|
6
|
+
import beautify from 'js-beautify';
|
|
7
|
+
import { renderFile } from 'pug';
|
|
8
|
+
import untildify from 'untildify';
|
|
7
9
|
|
|
8
10
|
/*
|
|
9
11
|
* Get the full path of the template file for generating charts based on
|
|
@@ -14,32 +16,32 @@ function getTemplatePath(templateFileName, config) {
|
|
|
14
16
|
return path.join(untildify(config.templatePath), `${templateFileName}.pug`);
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
return path.join(
|
|
19
|
+
return path.join(fileURLToPath(import.meta.url), '../../views/chart', `${templateFileName}.pug`);
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
/*
|
|
21
23
|
* Prepare the specified directory for saving HTML charts by deleting
|
|
22
24
|
* everything and creating the expected folders.
|
|
23
25
|
*/
|
|
24
|
-
|
|
25
|
-
const staticAssetPath = path.join(
|
|
26
|
-
await
|
|
27
|
-
await
|
|
28
|
-
await
|
|
29
|
-
await
|
|
30
|
-
}
|
|
26
|
+
export async function prepDirectory(exportPath) {
|
|
27
|
+
const staticAssetPath = path.join(fileURLToPath(import.meta.url), '../../public');
|
|
28
|
+
await rm(exportPath, { recursive: true, force: true });
|
|
29
|
+
await mkdir(exportPath, { recursive: true });
|
|
30
|
+
await copy(path.join(staticAssetPath, 'css'), path.join(exportPath, 'css'));
|
|
31
|
+
await copy(path.join(staticAssetPath, 'js'), path.join(exportPath, 'js'));
|
|
32
|
+
}
|
|
31
33
|
|
|
32
34
|
/*
|
|
33
35
|
* Render the HTML for a chart based on the config.
|
|
34
36
|
*/
|
|
35
|
-
|
|
37
|
+
export async function renderTemplate(templateFileName, templateVars, config) {
|
|
36
38
|
const templatePath = getTemplatePath(templateFileName, config);
|
|
37
|
-
let html = await
|
|
39
|
+
let html = await renderFile(templatePath, templateVars);
|
|
38
40
|
|
|
39
41
|
// Beautify HTML if setting is set
|
|
40
42
|
if (config.beautify === true) {
|
|
41
|
-
html = await beautify(html, { indent_size: 2 });
|
|
43
|
+
html = await beautify.html_beautify(html, { indent_size: 2 });
|
|
42
44
|
}
|
|
43
45
|
|
|
44
46
|
return html;
|
|
45
|
-
}
|
|
47
|
+
}
|
package/lib/formatters.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Format a route name.
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
if (route.route_short_name !== '' && route.route_short_name !==
|
|
4
|
+
export function formatRouteName(route) {
|
|
5
|
+
if (route.route_short_name !== '' && route.route_short_name !== null) {
|
|
6
6
|
return route.route_short_name;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
return route.route_long_name;
|
|
10
|
-
}
|
|
10
|
+
}
|
package/lib/gtfs-to-chart.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const Timer = require('timer-machine');
|
|
4
|
+
import { clone, omit } from 'lodash-es';
|
|
5
|
+
import { openDb, importGtfs, getRoutes } from 'gtfs';
|
|
6
|
+
import sanitize from 'sanitize-filename';
|
|
7
|
+
import Timer from 'timer-machine';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
import { prepDirectory } from './file-utils.js';
|
|
10
|
+
import { log, logWarning, progressBar } from './log-utils.js';
|
|
11
|
+
import { setDefaultConfig, generateChartHTML, generateOverviewHTML } from './utils.js';
|
|
12
|
+
import { formatRouteName } from './formatters.js';
|
|
13
13
|
|
|
14
14
|
/*
|
|
15
15
|
* Generate HTML charts from GTFS
|
|
16
16
|
*/
|
|
17
|
-
|
|
18
|
-
const config =
|
|
19
|
-
config.log =
|
|
20
|
-
config.logWarning =
|
|
17
|
+
const gtfsToChart = async initialConfig => {
|
|
18
|
+
const config = setDefaultConfig(initialConfig);
|
|
19
|
+
config.log = log(config);
|
|
20
|
+
config.logWarning = logWarning(config);
|
|
21
21
|
|
|
22
|
-
await
|
|
22
|
+
await openDb(config);
|
|
23
23
|
|
|
24
24
|
if (!config.agencies || config.agencies.length === 0) {
|
|
25
25
|
throw new Error('No agencies defined in `config.json`');
|
|
@@ -35,21 +35,21 @@ module.exports = async initialConfig => {
|
|
|
35
35
|
|
|
36
36
|
timer.start();
|
|
37
37
|
|
|
38
|
-
const agencyConfig =
|
|
38
|
+
const agencyConfig = clone(omit(config, 'agencies'));
|
|
39
39
|
agencyConfig.agencies = [agency];
|
|
40
40
|
|
|
41
41
|
if (!config.skipImport) {
|
|
42
42
|
// Import GTFS
|
|
43
|
-
await
|
|
43
|
+
await importGtfs(agencyConfig);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
await
|
|
46
|
+
await prepDirectory(exportPath);
|
|
47
47
|
|
|
48
|
-
const routes = await
|
|
49
|
-
const bar =
|
|
48
|
+
const routes = await getRoutes();
|
|
49
|
+
const bar = progressBar(`${agencyKey}: Generating charts [:bar] :current/:total`, { total: routes.length }, config);
|
|
50
50
|
|
|
51
51
|
// Make directory if it doesn't exist
|
|
52
|
-
await
|
|
52
|
+
await mkdir(exportPath, { recursive: true });
|
|
53
53
|
config.assetPath = '';
|
|
54
54
|
|
|
55
55
|
/* eslint-disable no-await-in-loop */
|
|
@@ -57,9 +57,9 @@ module.exports = async initialConfig => {
|
|
|
57
57
|
outputStats.charts += 1;
|
|
58
58
|
|
|
59
59
|
try {
|
|
60
|
-
const html = await
|
|
61
|
-
const htmlPath = path.join(exportPath, sanitize(`${
|
|
62
|
-
await
|
|
60
|
+
const html = await generateChartHTML(config, route.route_id);
|
|
61
|
+
const htmlPath = path.join(exportPath, sanitize(`${formatRouteName(route)}.html`));
|
|
62
|
+
await writeFile(htmlPath, html);
|
|
63
63
|
} catch (error) {
|
|
64
64
|
config.logWarning(error.message);
|
|
65
65
|
}
|
|
@@ -70,8 +70,8 @@ module.exports = async initialConfig => {
|
|
|
70
70
|
|
|
71
71
|
// Generate route summary index.html
|
|
72
72
|
config.assetPath = '';
|
|
73
|
-
const html = await
|
|
74
|
-
await
|
|
73
|
+
const html = await generateOverviewHTML(config, routes);
|
|
74
|
+
await writeFile(path.join(exportPath, 'index.html'), html);
|
|
75
75
|
|
|
76
76
|
timer.stop();
|
|
77
77
|
|
|
@@ -82,3 +82,5 @@ module.exports = async initialConfig => {
|
|
|
82
82
|
config.log(`${agencyKey}: chart generation required ${seconds} seconds`);
|
|
83
83
|
}));
|
|
84
84
|
};
|
|
85
|
+
|
|
86
|
+
export default gtfsToChart;
|
package/lib/log-utils.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { clearLine, cursorTo } from 'node:readline';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { noop } from 'lodash-es';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ProgressBar from 'progress';
|
|
6
6
|
|
|
7
7
|
/*
|
|
8
8
|
* Returns a log function based on config settings
|
|
9
9
|
*/
|
|
10
|
-
|
|
10
|
+
export function log(config) {
|
|
11
11
|
if (config.verbose === false) {
|
|
12
|
-
return
|
|
12
|
+
return noop;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
if (config.logFunction) {
|
|
@@ -18,61 +18,61 @@ exports.log = config => {
|
|
|
18
18
|
|
|
19
19
|
return (text, overwrite) => {
|
|
20
20
|
if (overwrite === true && process.stdout.isTTY) {
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
clearLine(process.stdout, 0);
|
|
22
|
+
cursorTo(process.stdout, 0);
|
|
23
23
|
} else {
|
|
24
24
|
process.stdout.write('\n');
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
process.stdout.write(text);
|
|
28
28
|
};
|
|
29
|
-
}
|
|
29
|
+
}
|
|
30
30
|
|
|
31
31
|
/*
|
|
32
32
|
* Returns an warning log function based on config settings
|
|
33
33
|
*/
|
|
34
|
-
|
|
34
|
+
export function logWarning(config) {
|
|
35
35
|
if (config.logFunction) {
|
|
36
36
|
return config.logFunction;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
return text => {
|
|
40
|
-
process.stdout.write(`\n${
|
|
40
|
+
process.stdout.write(`\n${formatWarning(text)}\n`);
|
|
41
41
|
};
|
|
42
|
-
}
|
|
42
|
+
}
|
|
43
43
|
|
|
44
44
|
/*
|
|
45
45
|
* Returns an error log function based on config settings
|
|
46
46
|
*/
|
|
47
|
-
|
|
47
|
+
export function logError(config) {
|
|
48
48
|
if (config.logFunction) {
|
|
49
49
|
return config.logFunction;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
return text => {
|
|
53
|
-
process.stdout.write(`\n${
|
|
53
|
+
process.stdout.write(`\n${formatError(text)}\n`);
|
|
54
54
|
};
|
|
55
|
-
}
|
|
55
|
+
}
|
|
56
56
|
|
|
57
57
|
/*
|
|
58
58
|
* Format console warning text
|
|
59
59
|
*/
|
|
60
|
-
|
|
60
|
+
export function formatWarning(text) {
|
|
61
61
|
return `${chalk.yellow.underline('Warning')}${chalk.yellow(':')} ${chalk.yellow(text)}`;
|
|
62
|
-
}
|
|
62
|
+
}
|
|
63
63
|
|
|
64
64
|
/*
|
|
65
65
|
* Format console error text
|
|
66
66
|
*/
|
|
67
|
-
|
|
67
|
+
export function formatError(error) {
|
|
68
68
|
const message = error instanceof Error ? error.message : error;
|
|
69
69
|
return `${chalk.red.underline('Error')}${chalk.red(':')} ${chalk.red(message.replace('Error: ', ''))}`;
|
|
70
|
-
}
|
|
70
|
+
}
|
|
71
71
|
|
|
72
72
|
/*
|
|
73
73
|
* Print a progress bar to the console.
|
|
74
74
|
*/
|
|
75
|
-
|
|
75
|
+
export function progressBar(formatString, barOptions, config) {
|
|
76
76
|
if (barOptions.total === 0) {
|
|
77
77
|
return null;
|
|
78
78
|
}
|
|
@@ -110,4 +110,4 @@ exports.progressBar = (formatString, barOptions, config) => {
|
|
|
110
110
|
bar.tick();
|
|
111
111
|
}
|
|
112
112
|
};
|
|
113
|
-
}
|
|
113
|
+
}
|
package/lib/utils.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const gtfs = require('gtfs');
|
|
4
|
-
const sanitize = require('sanitize-filename');
|
|
5
|
-
const moment = require('moment');
|
|
6
|
-
const sqlString = require('sqlstring');
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
7
3
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
import { max, map, maxBy, size, every, uniq, groupBy, first, sortBy } from 'lodash-es';
|
|
5
|
+
import { getStops, openDb, getStoptimes, getAgencies, getRoutes } from 'gtfs';
|
|
6
|
+
import sanitize from 'sanitize-filename';
|
|
7
|
+
import moment from 'moment';
|
|
8
|
+
import sqlString from 'sqlstring';
|
|
9
|
+
|
|
10
|
+
import { renderTemplate } from './file-utils.js';
|
|
11
|
+
import { formatRouteName } from './formatters.js';
|
|
12
|
+
|
|
13
|
+
const { version } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url)));
|
|
11
14
|
|
|
12
15
|
/*
|
|
13
16
|
* Calculate the distance between two coordinates.
|
|
@@ -36,7 +39,7 @@ function calculateDistanceMi(lat1, lon1, lat2, lon2) {
|
|
|
36
39
|
* Reverse the distances between stations for opposite trip direction
|
|
37
40
|
*/
|
|
38
41
|
const reverseStationDistances = (stations, oppositeDirectionDistance) => {
|
|
39
|
-
const tripDistance =
|
|
42
|
+
const tripDistance = max(map(stations, 'distance'));
|
|
40
43
|
for (const station of stations) {
|
|
41
44
|
// Scale distances to match opposite direction total distance
|
|
42
45
|
station.distance = (tripDistance - station.distance) * oppositeDirectionDistance / tripDistance;
|
|
@@ -46,7 +49,7 @@ const reverseStationDistances = (stations, oppositeDirectionDistance) => {
|
|
|
46
49
|
/*
|
|
47
50
|
* Find longest trip
|
|
48
51
|
*/
|
|
49
|
-
const findLongestTrip = trips =>
|
|
52
|
+
const findLongestTrip = trips => maxBy(trips, trip => size(trip.stoptimes));
|
|
50
53
|
|
|
51
54
|
/*
|
|
52
55
|
* Determine if a stoptime is a timepoint.
|
|
@@ -61,7 +64,7 @@ const isTimepoint = stoptime => {
|
|
|
61
64
|
|
|
62
65
|
const getStationsFromTrip = async trip => {
|
|
63
66
|
const stops = await Promise.all(trip.stoptimes.map(async stoptime => {
|
|
64
|
-
const stops = await
|
|
67
|
+
const stops = await getStops({
|
|
65
68
|
stop_id: stoptime.stop_id
|
|
66
69
|
});
|
|
67
70
|
|
|
@@ -75,7 +78,7 @@ const getStationsFromTrip = async trip => {
|
|
|
75
78
|
let previousStationCoordinates;
|
|
76
79
|
return trip.stoptimes.map((stoptime, index) => {
|
|
77
80
|
const stop = stops[index];
|
|
78
|
-
const hasShapeDistance =
|
|
81
|
+
const hasShapeDistance = every(trip.stoptimes, stoptime => stoptime.shape_dist_traveled !== null);
|
|
79
82
|
|
|
80
83
|
if (!hasShapeDistance) {
|
|
81
84
|
if (index === 0) {
|
|
@@ -105,7 +108,7 @@ const getStationsFromTrip = async trip => {
|
|
|
105
108
|
* Get all trips and stoptimes for a given route
|
|
106
109
|
*/
|
|
107
110
|
const getDataforChart = async (config, routeId) => {
|
|
108
|
-
const db = await
|
|
111
|
+
const db = await openDb(config);
|
|
109
112
|
const notes = [];
|
|
110
113
|
const dayOfWeek = moment(config.chartDate, 'YYYYMMDD').format('dddd').toLowerCase();
|
|
111
114
|
const calendars = await db.all(`SELECT DISTINCT service_id FROM calendar WHERE start_date <= ? AND end_date >= ? AND ${sqlString.escapeId(dayOfWeek)} = 1`, [
|
|
@@ -127,14 +130,14 @@ const getDataforChart = async (config, routeId) => {
|
|
|
127
130
|
throw new Error(`No trips found for route ${routeId} on ${moment(config.chartDate, 'YYYYMMDD').format('MMM D, YYYY')}`);
|
|
128
131
|
}
|
|
129
132
|
|
|
130
|
-
const shapeIds =
|
|
133
|
+
const shapeIds = uniq(map(trips, 'shape_id'));
|
|
131
134
|
|
|
132
135
|
if (shapeIds.length === 0) {
|
|
133
136
|
throw new Error('Route has no shapes.');
|
|
134
137
|
}
|
|
135
138
|
|
|
136
139
|
await Promise.all(trips.map(async trip => {
|
|
137
|
-
const stoptimes = await
|
|
140
|
+
const stoptimes = await getStoptimes(
|
|
138
141
|
{
|
|
139
142
|
trip_id: trip.trip_id
|
|
140
143
|
},
|
|
@@ -155,11 +158,11 @@ const getDataforChart = async (config, routeId) => {
|
|
|
155
158
|
|
|
156
159
|
const longestTrip = findLongestTrip(trips);
|
|
157
160
|
let stations = await getStationsFromTrip(longestTrip);
|
|
158
|
-
const tripDistance =
|
|
159
|
-
const directionGroups =
|
|
161
|
+
const tripDistance = max(map(stations, 'distance'));
|
|
162
|
+
const directionGroups = groupBy(trips, 'direction_id');
|
|
160
163
|
|
|
161
164
|
// If there are two directions, get stops in other direction
|
|
162
|
-
if (
|
|
165
|
+
if (size(directionGroups) > 1) {
|
|
163
166
|
const oppositeDirection = longestTrip.direction_id === 1 ? '0' : '1';
|
|
164
167
|
const longestTripOppositeDirection = findLongestTrip(directionGroups[oppositeDirection]);
|
|
165
168
|
const stationsOppositeDirection = await getStationsFromTrip(longestTripOppositeDirection);
|
|
@@ -168,8 +171,7 @@ const getDataforChart = async (config, routeId) => {
|
|
|
168
171
|
|
|
169
172
|
stations = [...stations, ...stationsOppositeDirection];
|
|
170
173
|
}
|
|
171
|
-
|
|
172
|
-
const hasShapeDistance = _.every(longestTrip.stoptimes, stoptime => stoptime.shape_dist_traveled !== undefined);
|
|
174
|
+
const hasShapeDistance = every(longestTrip.stoptimes, stoptime => stoptime.shape_dist_traveled !== null);
|
|
173
175
|
if (!hasShapeDistance) {
|
|
174
176
|
notes.push('Distance between stops calculated assuming a straight line.');
|
|
175
177
|
}
|
|
@@ -184,7 +186,7 @@ const getDataforChart = async (config, routeId) => {
|
|
|
184
186
|
/*
|
|
185
187
|
* Initialize configuration with defaults.
|
|
186
188
|
*/
|
|
187
|
-
|
|
189
|
+
export function setDefaultConfig(initialConfig) {
|
|
188
190
|
const defaults = {
|
|
189
191
|
beautify: false,
|
|
190
192
|
gtfsToChartVersion: version,
|
|
@@ -193,40 +195,36 @@ exports.setDefaultConfig = initialConfig => {
|
|
|
193
195
|
};
|
|
194
196
|
|
|
195
197
|
return { ...defaults, ...initialConfig };
|
|
196
|
-
}
|
|
198
|
+
}
|
|
197
199
|
|
|
198
200
|
/*
|
|
199
201
|
* Generate the HTML for the agency overview page.
|
|
200
202
|
*/
|
|
201
|
-
|
|
202
|
-
const agencies = await
|
|
203
|
+
export async function generateOverviewHTML(config, routes) {
|
|
204
|
+
const agencies = await getAgencies();
|
|
203
205
|
if (agencies.length === 0) {
|
|
204
206
|
throw new Error('No agencies found');
|
|
205
207
|
}
|
|
206
208
|
|
|
207
|
-
const agency =
|
|
209
|
+
const agency = first(agencies);
|
|
208
210
|
|
|
209
211
|
for (const route of routes) {
|
|
210
|
-
|
|
211
|
-
route.relativePath = path.join('charts', sanitize(route.route_id));
|
|
212
|
-
} else {
|
|
213
|
-
route.relativePath = path.join('charts', sanitize(`${formatters.formatRouteName(route)}.html`));
|
|
214
|
-
}
|
|
212
|
+
route.relativePath = config.isLocal ? path.join('charts', sanitize(route.route_id)) : path.join('charts', sanitize(`${formatRouteName(route)}.html`));
|
|
215
213
|
}
|
|
216
214
|
|
|
217
215
|
const templateVars = {
|
|
218
216
|
agency,
|
|
219
217
|
config,
|
|
220
|
-
routes:
|
|
218
|
+
routes: sortBy(routes, r => Number.parseInt(r.route_short_name, 10))
|
|
221
219
|
};
|
|
222
|
-
return
|
|
223
|
-
}
|
|
220
|
+
return renderTemplate('overview_page', templateVars, config);
|
|
221
|
+
}
|
|
224
222
|
|
|
225
223
|
/*
|
|
226
224
|
* Generate the HTML for a chart.
|
|
227
225
|
*/
|
|
228
|
-
|
|
229
|
-
const routes = await
|
|
226
|
+
export async function generateChartHTML(config, routeId) {
|
|
227
|
+
const routes = await getRoutes({
|
|
230
228
|
route_id: routeId
|
|
231
229
|
});
|
|
232
230
|
|
|
@@ -236,10 +234,10 @@ exports.generateChartHTML = async (config, routeId) => {
|
|
|
236
234
|
|
|
237
235
|
const chartData = await getDataforChart(config, routeId);
|
|
238
236
|
|
|
239
|
-
return
|
|
237
|
+
return renderTemplate('chart_page', {
|
|
240
238
|
route: routes[0],
|
|
241
239
|
chartData,
|
|
242
240
|
config,
|
|
243
|
-
moment
|
|
241
|
+
moment
|
|
244
242
|
}, config);
|
|
245
|
-
}
|
|
243
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gtfs-to-chart",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Generate stringline charts of a transit routes from GTFS",
|
|
6
6
|
"keywords": [
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"repository": "git://github.com/blinktaginc/gtfs-to-chart",
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"author": "Brendan Nee <brendan@blinktag.com>",
|
|
20
|
-
"
|
|
20
|
+
"type": "module",
|
|
21
|
+
"main": "index.js",
|
|
21
22
|
"bin": {
|
|
22
23
|
"gtfs-to-chart": "bin/gtfs-to-chart.js"
|
|
23
24
|
},
|
|
@@ -42,29 +43,29 @@
|
|
|
42
43
|
"space": true
|
|
43
44
|
},
|
|
44
45
|
"dependencies": {
|
|
45
|
-
"
|
|
46
|
+
"better-copy": "^1.0.4",
|
|
47
|
+
"chalk": "^5.0.1",
|
|
46
48
|
"connect-slashes": "^1.4.0",
|
|
47
|
-
"express": "^4.
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"moment": "^2.29.1",
|
|
49
|
+
"express": "^4.18.1",
|
|
50
|
+
"gtfs": "^3.3.1",
|
|
51
|
+
"js-beautify": "^1.14.4",
|
|
52
|
+
"lodash-es": "^4.17.21",
|
|
53
|
+
"moment": "^2.29.3",
|
|
53
54
|
"morgan": "^1.10.0",
|
|
54
55
|
"progress": "^2.0.3",
|
|
55
56
|
"pug": "^3.0.2",
|
|
56
57
|
"sanitize-filename": "^1.6.3",
|
|
57
|
-
"simplify-geojson": "^1.0.
|
|
58
|
-
"sqlstring": "^2.3.
|
|
58
|
+
"simplify-geojson": "^1.0.5",
|
|
59
|
+
"sqlstring": "^2.3.3",
|
|
59
60
|
"timer-machine": "^1.1.0",
|
|
60
61
|
"untildify": "^4.0.0",
|
|
61
|
-
"yargs": "^
|
|
62
|
+
"yargs": "^17.5.1"
|
|
62
63
|
},
|
|
63
64
|
"devDependencies": {
|
|
64
|
-
"xo": "^0.
|
|
65
|
+
"xo": "^0.50.0"
|
|
65
66
|
},
|
|
66
67
|
"engines": {
|
|
67
|
-
"node": ">=
|
|
68
|
+
"node": ">= 14.x"
|
|
68
69
|
},
|
|
69
70
|
"false": {}
|
|
70
71
|
}
|
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
} = route;
|
|
7
7
|
let routeName = '';
|
|
8
8
|
|
|
9
|
-
if (shortName !== '' && shortName !==
|
|
9
|
+
if (shortName !== '' && shortName !== null) {
|
|
10
10
|
routeName += shortName;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
if (shortName !== '' && shortName !==
|
|
13
|
+
if (shortName !== '' && shortName !== null && longName !== '' && longName !== null) {
|
|
14
14
|
routeName += ' - ';
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
if (longName !== '' && longName !==
|
|
17
|
+
if (longName !== '' && longName !== null) {
|
|
18
18
|
routeName += longName;
|
|
19
19
|
}
|
|
20
20
|
|