gtfs-to-html 2.6.9 → 2.6.11
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 +18 -0
- package/lib/formatters.js +9 -15
- package/lib/log-utils.js +1 -1
- package/package.json +5 -5
- package/public/css/overview_styles.css +242 -0
- package/public/css/timetable_styles.css +241 -8
- package/public/js/system-map.js +6 -3
- package/public/js/timetable-map.js +6 -3
- package/public/js/timetable-menu.js +7 -13
- package/views/default/formatting_functions.pug +2 -8
- package/views/default/layout.pug +0 -5
- package/views/default/overview.pug +12 -13
- package/views/default/overview_full.pug +4 -2
- package/views/default/timetable_menu.pug +6 -6
- package/views/default/timetablepage.pug +2 -2
- package/views/default/timetablepage_full.pug +6 -2
- package/www/static/img/favicon.ico +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.6.11] - 2024-07-24
|
|
9
|
+
|
|
10
|
+
### Updated
|
|
11
|
+
- Dependency updates
|
|
12
|
+
- Default template timetable styles
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
- Map route_text_color fix
|
|
16
|
+
|
|
17
|
+
## [2.6.10] - 2024-07-15
|
|
18
|
+
|
|
19
|
+
### Updated
|
|
20
|
+
- Better date format in timetable comment
|
|
21
|
+
- favicon
|
|
22
|
+
- Improved timetable_page_name fallback
|
|
23
|
+
- Overview template formatting
|
|
24
|
+
- Update mapbox version
|
|
25
|
+
|
|
8
26
|
## [2.6.9] - 2024-07-11
|
|
9
27
|
|
|
10
28
|
### Added
|
package/lib/formatters.js
CHANGED
|
@@ -512,22 +512,16 @@ export function formatTimetablePageLabel(timetablePage) {
|
|
|
512
512
|
timetablePage.consolidatedTimetables &&
|
|
513
513
|
timetablePage.consolidatedTimetables.length > 0
|
|
514
514
|
) {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
(timetable) => timetable.routes,
|
|
524
|
-
),
|
|
525
|
-
'route_id',
|
|
526
|
-
);
|
|
527
|
-
const timetablePageLabel = routes.map((route) => formatRouteName(route));
|
|
515
|
+
// Use route names from all timetables
|
|
516
|
+
const routes = uniqBy(
|
|
517
|
+
flatMap(
|
|
518
|
+
timetablePage.consolidatedTimetables,
|
|
519
|
+
(timetable) => timetable.routes,
|
|
520
|
+
),
|
|
521
|
+
'route_id',
|
|
522
|
+
);
|
|
528
523
|
|
|
529
|
-
|
|
530
|
-
}
|
|
524
|
+
return routes.map((route) => formatRouteName(route)).join(' and ');
|
|
531
525
|
}
|
|
532
526
|
|
|
533
527
|
return 'Unknown';
|
package/lib/log-utils.js
CHANGED
|
@@ -17,7 +17,7 @@ export function generateLogText(outputStats, config) {
|
|
|
17
17
|
const logText = [
|
|
18
18
|
`Feed Version: ${feedVersion}`,
|
|
19
19
|
`GTFS-to-HTML Version: ${config.gtfsToHtmlVersion}`,
|
|
20
|
-
`Date Generated: ${new Date()}`,
|
|
20
|
+
`Date Generated: ${new Date().toISOString()}`,
|
|
21
21
|
`Timetable Page Count: ${outputStats.timetablePages}`,
|
|
22
22
|
`Timetable Count: ${outputStats.timetables}`,
|
|
23
23
|
`Calendar Service ID Count: ${outputStats.calendars}`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gtfs-to-html",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.11",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Build human readable transit timetables as HTML, PDF or CSV from GTFS",
|
|
6
6
|
"keywords": [
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"copy-dir": "^1.3.0",
|
|
43
43
|
"csv-stringify": "^6.5.0",
|
|
44
44
|
"express": "^4.19.2",
|
|
45
|
-
"gtfs": "^4.13.
|
|
45
|
+
"gtfs": "^4.13.1",
|
|
46
46
|
"insane": "^2.6.2",
|
|
47
47
|
"js-beautify": "^1.15.1",
|
|
48
48
|
"lodash-es": "^4.17.21",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"morgan": "^1.10.0",
|
|
52
52
|
"pretty-error": "^4.0.0",
|
|
53
53
|
"pug": "^3.0.3",
|
|
54
|
-
"puppeteer": "^22.13.
|
|
54
|
+
"puppeteer": "^22.13.1",
|
|
55
55
|
"sanitize-filename": "^1.6.3",
|
|
56
56
|
"sqlstring": "^2.3.3",
|
|
57
57
|
"timer-machine": "^1.1.0",
|
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
"yoctocolors": "^2.1.1"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"husky": "^9.
|
|
64
|
+
"husky": "^9.1.1",
|
|
65
65
|
"lint-staged": "^15.2.7",
|
|
66
|
-
"prettier": "^3.3.
|
|
66
|
+
"prettier": "^3.3.3"
|
|
67
67
|
},
|
|
68
68
|
"engines": {
|
|
69
69
|
"node": ">= 20.11.0"
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/* Base styles */
|
|
2
|
+
body {
|
|
3
|
+
color: #666;
|
|
4
|
+
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
5
|
+
font-feature-settings: normal;
|
|
6
|
+
line-height: inherit;
|
|
7
|
+
margin: 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
*, ::before, ::after {
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
border-width: 0;
|
|
13
|
+
border-style: solid;
|
|
14
|
+
border-color: #e5e7eb;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
h1,
|
|
18
|
+
h2,
|
|
19
|
+
h3,
|
|
20
|
+
h4,
|
|
21
|
+
h5,
|
|
22
|
+
h6 {
|
|
23
|
+
line-height: inherit;
|
|
24
|
+
font-weight: inherit;
|
|
25
|
+
color: #333;
|
|
26
|
+
margin: 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
a {
|
|
30
|
+
text-decoration: none;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
a:hover {
|
|
34
|
+
text-decoration: underline;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Overview styles */
|
|
38
|
+
|
|
39
|
+
.route-color-swatch {
|
|
40
|
+
min-width: 34px;
|
|
41
|
+
height: 34px;
|
|
42
|
+
border-radius: 17px;
|
|
43
|
+
text-align: center;
|
|
44
|
+
line-height: 34px;
|
|
45
|
+
font-size: 14px;
|
|
46
|
+
letter-spacing: -0.5px;
|
|
47
|
+
padding: 0 5px;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.route-color-swatch-large {
|
|
51
|
+
min-width: 46px;
|
|
52
|
+
height: 46px;
|
|
53
|
+
border-radius: 23px;
|
|
54
|
+
text-align: center;
|
|
55
|
+
line-height: 46px;
|
|
56
|
+
font-size: 20px;
|
|
57
|
+
font-weight: bold;
|
|
58
|
+
letter-spacing: -1px;
|
|
59
|
+
padding: 0 6px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.btn-blue {
|
|
63
|
+
color: rgb(255 255 255);
|
|
64
|
+
padding: 0.75rem 2rem;
|
|
65
|
+
background-color: rgb(37 99 235);
|
|
66
|
+
border-radius: 0.375rem;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
align-items: center;
|
|
69
|
+
display: inline-flex;
|
|
70
|
+
cursor: pointer;
|
|
71
|
+
text-decoration: none;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.btn-blue:hover {
|
|
75
|
+
background-color: rgb(29 78 216);
|
|
76
|
+
text-decoration: none;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.btn-sm {
|
|
80
|
+
padding: 0.25rem 1rem;
|
|
81
|
+
border-radius: 0.25rem;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.mr-1 {
|
|
85
|
+
margin-right: 0.25rem;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.mx-4 {
|
|
89
|
+
margin-left: 1rem;
|
|
90
|
+
margin-right: 1rem;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.mb-2 {
|
|
94
|
+
margin-bottom: 0.5rem;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.block {
|
|
98
|
+
display: block;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.flex {
|
|
102
|
+
display: flex;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.inline-flex {
|
|
106
|
+
display: inline-flex;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.h-full {
|
|
110
|
+
height: 100%;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.h-screen {
|
|
114
|
+
height: 100vh;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.w-full {
|
|
118
|
+
width: 100%;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.flex-none {
|
|
122
|
+
flex: none;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.items-center {
|
|
126
|
+
align-items: center;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.items-stretch {
|
|
130
|
+
align-items: stretch;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.justify-center {
|
|
134
|
+
justify-content: center;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.gap-2 {
|
|
138
|
+
gap: 0.5rem;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.rounded-full {
|
|
142
|
+
border-radius: 9999px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.border-b {
|
|
146
|
+
border-bottom-width: 1px;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.border-slate-200 {
|
|
150
|
+
border-color: rgb(226 232 240);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.bg-slate-200 {
|
|
154
|
+
background-color: rgb(226 232 240);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.p-2 {
|
|
158
|
+
padding: 0.5rem;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.px-2 {
|
|
162
|
+
padding-left: 0.5rem;
|
|
163
|
+
padding-right: 0.5rem;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.py-1 {
|
|
167
|
+
padding-top: 0.25rem;
|
|
168
|
+
padding-bottom: 0.25rem;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.py-3 {
|
|
172
|
+
padding-top: 0.75rem;
|
|
173
|
+
padding-bottom: 0.75rem;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.text-2xl {
|
|
177
|
+
font-size: 1.5rem;
|
|
178
|
+
line-height: 2rem;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.text-xl {
|
|
182
|
+
font-size: 1.25rem;
|
|
183
|
+
line-height: 1.75rem;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.text-xs {
|
|
187
|
+
font-size: 0.75rem;
|
|
188
|
+
line-height: 1rem;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.font-bold {
|
|
192
|
+
font-weight: 700;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.leading-none {
|
|
196
|
+
line-height: 1;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.text-slate-800 {
|
|
200
|
+
color: rgb(30 41 59);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.hover\:bg-slate-100:hover {
|
|
204
|
+
background-color: rgb(241 245 249);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.hover\:no-underline:hover {
|
|
208
|
+
text-decoration-line: none;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
@media (min-width: 768px) {
|
|
212
|
+
.md\:flex {
|
|
213
|
+
display: flex;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.md\:max-w-96 {
|
|
217
|
+
max-width: 24rem;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
.md\:overflow-y-scroll {
|
|
221
|
+
overflow-y: scroll;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/* Map Styles */
|
|
226
|
+
|
|
227
|
+
.map .mapboxgl-popup-content .popup-title {
|
|
228
|
+
margin: 0 20px 5px 0;
|
|
229
|
+
font-size: 16px;
|
|
230
|
+
font-weight: bold;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.map .mapboxgl-popup-content .route-item {
|
|
234
|
+
display: flex;
|
|
235
|
+
align-items: center;
|
|
236
|
+
line-height: 1;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.map .mapboxgl-popup-content .mapboxgl-popup-close-button {
|
|
240
|
+
padding: 0 5px;
|
|
241
|
+
}
|
|
242
|
+
|
|
@@ -1,24 +1,251 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/* Base styles */
|
|
2
2
|
body {
|
|
3
3
|
color: #666;
|
|
4
|
+
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
5
|
+
font-feature-settings: normal;
|
|
6
|
+
line-height: inherit;
|
|
7
|
+
margin: 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
*, ::before, ::after {
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
border-width: 0;
|
|
13
|
+
border-style: solid;
|
|
14
|
+
border-color: #e5e7eb;
|
|
4
15
|
}
|
|
5
16
|
|
|
6
17
|
h1,
|
|
7
18
|
h2,
|
|
8
19
|
h3,
|
|
9
20
|
h4,
|
|
10
|
-
h5
|
|
21
|
+
h5,
|
|
22
|
+
h6 {
|
|
23
|
+
line-height: inherit;
|
|
24
|
+
font-weight: inherit;
|
|
11
25
|
color: #333;
|
|
26
|
+
margin: 0;
|
|
12
27
|
}
|
|
13
28
|
|
|
14
29
|
a:hover {
|
|
15
30
|
text-decoration: underline;
|
|
16
31
|
}
|
|
17
32
|
|
|
33
|
+
/* Timetable Styles */
|
|
34
|
+
|
|
35
|
+
.container {
|
|
36
|
+
width: 100%;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@media (min-width: 640px) {
|
|
40
|
+
.container {
|
|
41
|
+
max-width: 640px;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@media (min-width: 768px) {
|
|
46
|
+
.container {
|
|
47
|
+
max-width: 768px;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@media (min-width: 1024px) {
|
|
52
|
+
.container {
|
|
53
|
+
max-width: 1024px;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@media (min-width: 1280px) {
|
|
58
|
+
.container {
|
|
59
|
+
max-width: 1280px;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@media (min-width: 1536px) {
|
|
64
|
+
.container {
|
|
65
|
+
max-width: 1536px;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.sr-only {
|
|
70
|
+
position: absolute;
|
|
71
|
+
width: 1px;
|
|
72
|
+
height: 1px;
|
|
73
|
+
padding: 0;
|
|
74
|
+
margin: -1px;
|
|
75
|
+
overflow: hidden;
|
|
76
|
+
clip: rect(0, 0, 0, 0);
|
|
77
|
+
white-space: nowrap;
|
|
78
|
+
border-width: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.mr-1 {
|
|
82
|
+
margin-right: 0.25rem;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.mx-4 {
|
|
86
|
+
margin-left: 1rem;
|
|
87
|
+
margin-right: 1rem;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.my-3 {
|
|
91
|
+
margin-top: 0.75rem;
|
|
92
|
+
margin-bottom: 0.75rem;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.mb-10 {
|
|
96
|
+
margin-bottom: 2.5rem;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.mb-1 {
|
|
100
|
+
margin-bottom: 0.25rem;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.mb-2 {
|
|
104
|
+
margin-bottom: 0.5rem;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.mt-2 {
|
|
108
|
+
margin-top: 0.5rem;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.block {
|
|
112
|
+
display: block;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.flex {
|
|
116
|
+
display: flex;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.grid {
|
|
120
|
+
display: grid;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.hidden {
|
|
124
|
+
display: none;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.w-full {
|
|
128
|
+
width: 100%;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.flex-none {
|
|
132
|
+
flex: none;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.grid-cols-1 {
|
|
136
|
+
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.items-center {
|
|
140
|
+
align-items: center;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.justify-center {
|
|
144
|
+
justify-content: center;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.gap-2 {
|
|
148
|
+
gap: 0.5rem;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.gap-4 {
|
|
152
|
+
gap: 1rem;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.border {
|
|
156
|
+
border-width: 1px;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.py-3 {
|
|
160
|
+
padding-top: 0.75rem;
|
|
161
|
+
padding-bottom: 0.75rem;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.pt-4 {
|
|
165
|
+
padding-top: 1rem;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.text-xs {
|
|
169
|
+
font-size: 0.75rem;
|
|
170
|
+
line-height: 1rem;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.text-2xl {
|
|
174
|
+
font-size: 1.5rem;
|
|
175
|
+
line-height: 2rem;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.text-xl {
|
|
179
|
+
font-size: 1.25rem;
|
|
180
|
+
line-height: 1.75rem;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.font-bold {
|
|
184
|
+
font-weight: 700;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.text-gray-600 {
|
|
188
|
+
color: rgb(75 85 99);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.text-white {
|
|
192
|
+
color: rgb(255 255 255);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@media (min-width: 768px) {
|
|
196
|
+
.md\:mx-auto {
|
|
197
|
+
margin-left: auto;
|
|
198
|
+
margin-right: auto;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.md\:grid-cols-3 {
|
|
202
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
18
206
|
.menu-type-radio .timetable {
|
|
19
207
|
display: none;
|
|
20
208
|
}
|
|
21
209
|
|
|
210
|
+
.btn-blue {
|
|
211
|
+
color: rgb(255 255 255);
|
|
212
|
+
padding: 0.75rem 2rem;
|
|
213
|
+
background-color: rgb(37 99 235);
|
|
214
|
+
border-radius: 0.375rem;
|
|
215
|
+
justify-content: center;
|
|
216
|
+
align-items: center;
|
|
217
|
+
display: inline-flex;
|
|
218
|
+
cursor: pointer;
|
|
219
|
+
text-decoration: none;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.btn-blue:hover {
|
|
223
|
+
background-color: rgb(29 78 216);
|
|
224
|
+
text-decoration: none;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.btn-gray {
|
|
228
|
+
color: rgb(75 85 99);
|
|
229
|
+
padding: 0.75rem 2rem;
|
|
230
|
+
background-color: rgb(209 213 219);
|
|
231
|
+
border-radius: 0.375rem;
|
|
232
|
+
justify-content: center;
|
|
233
|
+
align-items: center;
|
|
234
|
+
display: inline-flex;
|
|
235
|
+
cursor: pointer;
|
|
236
|
+
text-decoration: none;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.btn-gray:hover {
|
|
240
|
+
background-color: rgb(201, 206, 213);
|
|
241
|
+
text-decoration: none;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.btn-sm {
|
|
245
|
+
padding: 0.25rem 1rem;
|
|
246
|
+
border-radius: 0.25rem;
|
|
247
|
+
}
|
|
248
|
+
|
|
22
249
|
.timetable .stop-header {
|
|
23
250
|
text-align: center;
|
|
24
251
|
}
|
|
@@ -73,10 +300,6 @@ a:hover {
|
|
|
73
300
|
margin: 20px 0;
|
|
74
301
|
}
|
|
75
302
|
|
|
76
|
-
.timetable .table-container .table {
|
|
77
|
-
margin-bottom: 0;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
303
|
.timetable .table-container::-webkit-scrollbar {
|
|
81
304
|
-webkit-appearance: none;
|
|
82
305
|
height: 8px;
|
|
@@ -92,8 +315,14 @@ a:hover {
|
|
|
92
315
|
background-color: rgba(156, 156, 156, 0.8);
|
|
93
316
|
}
|
|
94
317
|
|
|
318
|
+
.timetable .table-container table {
|
|
319
|
+
text-indent: 0;
|
|
320
|
+
border-color: inherit;
|
|
321
|
+
border-collapse: collapse;
|
|
322
|
+
}
|
|
323
|
+
|
|
95
324
|
.timetable thead tr {
|
|
96
|
-
background: #
|
|
325
|
+
background: #bae6fd;
|
|
97
326
|
}
|
|
98
327
|
|
|
99
328
|
.timetable thead tr,
|
|
@@ -186,7 +415,7 @@ a:hover {
|
|
|
186
415
|
font-size: 20px;
|
|
187
416
|
font-weight: bold;
|
|
188
417
|
letter-spacing: -1px;
|
|
189
|
-
padding: 0
|
|
418
|
+
padding: 0 6px;
|
|
190
419
|
}
|
|
191
420
|
|
|
192
421
|
@media screen and (max-width: 767px) {
|
|
@@ -262,3 +491,7 @@ a:hover {
|
|
|
262
491
|
align-items: center;
|
|
263
492
|
line-height: 1;
|
|
264
493
|
}
|
|
494
|
+
|
|
495
|
+
.map .mapboxgl-popup-content .mapboxgl-popup-close-button {
|
|
496
|
+
padding: 0 5px;
|
|
497
|
+
}
|
package/public/js/system-map.js
CHANGED
|
@@ -7,6 +7,10 @@ function formatRouteColor(route) {
|
|
|
7
7
|
return route.route_color || '#000000';
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
function formatRouteTextColor(route) {
|
|
11
|
+
return route.route_text_color || '#FFFFFF';
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
function formatRoute(route) {
|
|
11
15
|
const html = route.route_url
|
|
12
16
|
? $('<a>').attr('href', route.route_url).addClass('hover:no-underline')
|
|
@@ -22,6 +26,7 @@ function formatRoute(route) {
|
|
|
22
26
|
$('<div>')
|
|
23
27
|
.addClass('route-color-swatch flex-shrink-0 text-white')
|
|
24
28
|
.css('backgroundColor', formatRouteColor(route))
|
|
29
|
+
.css('color', formatRouteTextColor(route))
|
|
25
30
|
.text(route.route_short_name || ''),
|
|
26
31
|
$('<div>')
|
|
27
32
|
.addClass('hover:underline')
|
|
@@ -65,9 +70,7 @@ function formatStopPopup(feature) {
|
|
|
65
70
|
$(html).append(routes.map((route) => formatRoute(route)));
|
|
66
71
|
|
|
67
72
|
$('<a>')
|
|
68
|
-
.addClass(
|
|
69
|
-
'bg-blue-500 hover:bg-blue-700 text-white font-bold py-1.5 px-3 rounded inline-block hover:no-underline mt-2',
|
|
70
|
-
)
|
|
73
|
+
.addClass('btn-blue btn-sm mt-2')
|
|
71
74
|
.prop(
|
|
72
75
|
'href',
|
|
73
76
|
`https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&heading=0&pitch=0&fov=90`,
|
|
@@ -7,6 +7,10 @@ function formatRouteColor(route) {
|
|
|
7
7
|
return route.route_color || '#000000';
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
function formatRouteTextColor(route) {
|
|
11
|
+
return route.route_text_color || '#FFFFFF';
|
|
12
|
+
}
|
|
13
|
+
|
|
10
14
|
function formatRoute(route) {
|
|
11
15
|
const html = route.route_url
|
|
12
16
|
? $('<a>').attr('href', route.route_url).addClass('hover:no-underline')
|
|
@@ -22,6 +26,7 @@ function formatRoute(route) {
|
|
|
22
26
|
$('<div>')
|
|
23
27
|
.addClass('route-color-swatch flex-shrink-0 text-white')
|
|
24
28
|
.css('backgroundColor', formatRouteColor(route))
|
|
29
|
+
.css('color', formatRouteTextColor(route))
|
|
25
30
|
.text(route.route_short_name || ''),
|
|
26
31
|
$('<div>')
|
|
27
32
|
.addClass('hover:underline')
|
|
@@ -58,9 +63,7 @@ function formatStopPopup(feature, routes) {
|
|
|
58
63
|
$(html).append(routeIds.map((routeId) => formatRoute(routes[routeId])));
|
|
59
64
|
|
|
60
65
|
$('<a>')
|
|
61
|
-
.addClass(
|
|
62
|
-
'bg-blue-500 hover:bg-blue-700 text-white font-bold py-1.5 px-3 rounded inline-block hover:no-underline mt-2',
|
|
63
|
-
)
|
|
66
|
+
.addClass('btn-blue btn-sm mt-2')
|
|
64
67
|
.prop(
|
|
65
68
|
'href',
|
|
66
69
|
`https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${feature.geometry.coordinates[1]},${feature.geometry.coordinates[0]}&heading=0&pitch=0&fov=90`,
|
|
@@ -21,32 +21,26 @@ $(() => {
|
|
|
21
21
|
$('#day_list_selector input[name="dayList"]').each((index, element) => {
|
|
22
22
|
$(element)
|
|
23
23
|
.parents('label')
|
|
24
|
-
.toggleClass('
|
|
24
|
+
.toggleClass('btn-blue', $(element).is(':checked'));
|
|
25
25
|
$(element)
|
|
26
26
|
.parents('label')
|
|
27
|
-
.toggleClass(
|
|
28
|
-
'text-gray-600 bg-gray-300',
|
|
29
|
-
$(element).is(':not(:checked)')
|
|
30
|
-
);
|
|
27
|
+
.toggleClass('btn-gray', $(element).is(':not(:checked)'));
|
|
31
28
|
});
|
|
32
29
|
|
|
33
30
|
$('#direction_name_selector input[name="directionName"]').each(
|
|
34
31
|
(index, element) => {
|
|
35
32
|
$(element)
|
|
36
33
|
.parents('label')
|
|
37
|
-
.toggleClass('
|
|
34
|
+
.toggleClass('btn-blue', $(element).is(':checked'));
|
|
38
35
|
$(element)
|
|
39
36
|
.parents('label')
|
|
40
|
-
.toggleClass(
|
|
41
|
-
|
|
42
|
-
$(element).is(':not(:checked)')
|
|
43
|
-
);
|
|
44
|
-
}
|
|
37
|
+
.toggleClass('btn-gray', $(element).is(':not(:checked)'));
|
|
38
|
+
},
|
|
45
39
|
);
|
|
46
40
|
|
|
47
41
|
const dayList = $('#day_list_selector input[name="dayList"]:checked').val();
|
|
48
42
|
const directionName = $(
|
|
49
|
-
'#direction_name_selector input[name="directionName"]:checked'
|
|
43
|
+
'#direction_name_selector input[name="directionName"]:checked',
|
|
50
44
|
).val();
|
|
51
45
|
|
|
52
46
|
$('.timetable').hide();
|
|
@@ -55,7 +49,7 @@ $(() => {
|
|
|
55
49
|
dayList +
|
|
56
50
|
'"][data-direction-name="' +
|
|
57
51
|
directionName +
|
|
58
|
-
'"]'
|
|
52
|
+
'"]',
|
|
59
53
|
).attr('id');
|
|
60
54
|
showTimetable(id);
|
|
61
55
|
}
|
|
@@ -11,14 +11,8 @@
|
|
|
11
11
|
return summary;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if (hasLongName) {
|
|
18
|
-
return route.route_long_name;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return route.route_short_name;
|
|
14
|
+
function isNullOrEmpty(value) {
|
|
15
|
+
return value === null || value === '';
|
|
22
16
|
}
|
|
23
17
|
|
|
24
18
|
function formatFrequencyWarning(frequencies) {
|
package/views/default/layout.pug
CHANGED
|
@@ -3,13 +3,8 @@ html
|
|
|
3
3
|
head
|
|
4
4
|
title= title
|
|
5
5
|
meta(charset="utf-8")
|
|
6
|
-
link(rel="stylesheet" href=`${config.assetPath}css/timetable_styles.css`)
|
|
7
|
-
if config.outputFormat === 'pdf'
|
|
8
|
-
link(rel="stylesheet" href=`${config.assetPath}css/timetable_pdf_styles.css`)
|
|
9
6
|
meta(name="viewport" content="initial-scale=1.0, width=device-width")
|
|
10
7
|
|
|
11
|
-
script(src="https://cdn.tailwindcss.com")
|
|
12
|
-
|
|
13
8
|
block extraHeader
|
|
14
9
|
|
|
15
10
|
body
|
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
include formatting_functions.pug
|
|
2
2
|
|
|
3
|
-
.
|
|
3
|
+
.h-screen.items-stretch(class="md:flex")
|
|
4
4
|
if !timetablePages || !timetablePages.length
|
|
5
|
-
.
|
|
6
|
-
.bg-blue-700.text-white.font-bold.rounded-lg.border.shadow-lg.text-lg.p-8(class="w-1/2") No timetables found
|
|
5
|
+
h1.text-2xl.mx-4.py-3 No timetables found
|
|
7
6
|
else
|
|
8
|
-
.overview-list.flex-none(class="md:overflow-y-scroll")
|
|
7
|
+
.overview-list.flex-none(class="md:overflow-y-scroll md:max-w-96")
|
|
9
8
|
each timetablePageGroup in getAgencyTimetableGroups(timetablePages, agencies)
|
|
10
|
-
h1.text-2xl.
|
|
9
|
+
h1.text-2xl.mx-4.py-3= `${formatAgencyName(timetablePageGroup.agency)} Routes`
|
|
10
|
+
|
|
11
11
|
each timetablePage in timetablePageGroup.timetablePages
|
|
12
12
|
if config.allowEmptyTimetables || timetablePage.consolidatedTimetables.length > 0
|
|
13
|
-
a.block.p-2.border-b.border-slate-200(class="hover:bg-slate-100 hover:no-underline" href=`${timetablePage.relativePath}` data-route-ids=`${timetablePage.route_ids ? timetablePage.route_ids.join(',') : ''}`)
|
|
14
|
-
.text-lg.text-gray-800.leading-none= timetablePage.timetable_page_label
|
|
13
|
+
a.timetable-overview-label.flex.items-center.gap-2.block.p-2.border-b.border-slate-200(class="hover:bg-slate-100 hover:no-underline" href=`${timetablePage.relativePath}` data-route-ids=`${timetablePage.route_ids ? timetablePage.route_ids.join(',') : ''}`)
|
|
15
14
|
each route in _.uniqBy(_.flatMap(timetablePage.consolidatedTimetables, timetable => timetable.routes), 'route_id')
|
|
16
|
-
.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
.route-color-swatch-large.flex-none(style=`background-color: ${formatRouteColor(route)}; color: ${formatRouteTextColor(route)};`)= route.route_short_name || ''
|
|
16
|
+
div
|
|
17
|
+
.text-xl.leading-none.text-slate-800= timetablePage.timetable_page_label
|
|
18
|
+
.inline-flex.items-center.justify-center.px-2.py-1.text-xs.font-bold.leading-none.text-slate-800.bg-slate-200.rounded-full= timetablePage.dayList
|
|
20
19
|
if config.showMap
|
|
21
|
-
.map.
|
|
20
|
+
.map.h-full.w-full(id="system_map")
|
|
22
21
|
|
|
23
22
|
//- Use #{variable} format to inject values from pug to client side js
|
|
24
23
|
script.
|
|
25
24
|
(function() {
|
|
26
|
-
|
|
25
|
+
const geojson = !{JSON.stringify(geojson) || '\'\''};
|
|
27
26
|
createSystemMap('system_map', geojson);
|
|
28
27
|
})();
|
|
@@ -6,9 +6,11 @@ block extraHeader
|
|
|
6
6
|
if config.showMap
|
|
7
7
|
script(src="https://unpkg.com/jquery@3.7.1/dist/jquery.min.js" crossorigin="anonymous")
|
|
8
8
|
script(src="https://unpkg.com/lodash@4.17.21/lodash.min.js" crossorigin="anonymous")
|
|
9
|
-
script(src="https://api.mapbox.com/mapbox-gl-js/v3.
|
|
9
|
+
script(src="https://api.mapbox.com/mapbox-gl-js/v3.5.1/mapbox-gl.js")
|
|
10
10
|
script.
|
|
11
11
|
mapboxgl.accessToken = '#{config.mapboxAccessToken}';
|
|
12
12
|
script(src=`${config.assetPath}js/system-map.js`)
|
|
13
13
|
|
|
14
|
-
link(href="https://api.mapbox.com/mapbox-gl-js/v3.
|
|
14
|
+
link(href="https://api.mapbox.com/mapbox-gl-js/v3.5.1/mapbox-gl.css" rel="stylesheet")
|
|
15
|
+
|
|
16
|
+
link(rel="stylesheet" href=`${config.assetPath}css/overview_styles.css`)
|
|
@@ -26,24 +26,24 @@ if timetablePage.consolidatedTimetables.length > 1
|
|
|
26
26
|
.grid.grid-cols-1.gap-4(class="md:grid-cols-3")
|
|
27
27
|
each group, dayList in groupedTimetables
|
|
28
28
|
div
|
|
29
|
-
h3.font-bold= dayList
|
|
29
|
+
h3.font-bold.mb-1= dayList
|
|
30
30
|
each timetable in group
|
|
31
|
-
a.mb-2.w-full.
|
|
31
|
+
a.mb-2.w-full.btn-blue(href=`#timetable_id_${timetable.timetable_id}`)= timetable.timetable_label
|
|
32
32
|
|
|
33
33
|
if config.menuType === 'radio'
|
|
34
34
|
.grid.grid-cols-1.gap-4(class="md:grid-cols-3")
|
|
35
35
|
-var directionNames = _.uniq(timetablePage.consolidatedTimetables.map(timetable => timetable.direction_name));
|
|
36
36
|
div(hidden=directionNames.length <= 1)
|
|
37
37
|
#direction_name_selector
|
|
38
|
-
h3.font-bold Service Direction
|
|
38
|
+
h3.font-bold.mb-1 Service Direction
|
|
39
39
|
each directionName, idx in directionNames
|
|
40
|
-
label.
|
|
40
|
+
label.mb-2.w-full(class=idx === 0 ? 'btn-blue' : 'btn-gray')
|
|
41
41
|
input.hidden(type="radio" name="directionName" autocomplete="off" value=directionName checked=(idx === 0))
|
|
42
42
|
span= directionName
|
|
43
43
|
div(hidden=timetablePage.dayLists.length <= 1)
|
|
44
44
|
#day_list_selector
|
|
45
|
-
h3.font-bold Day of Week
|
|
45
|
+
h3.font-bold.mb-1 Day of Week
|
|
46
46
|
each dayList, idx in timetablePage.dayLists
|
|
47
|
-
label.
|
|
47
|
+
label.mb-2.w-full(class=idx === 0 ? 'btn-blue' : 'btn-gray')
|
|
48
48
|
input.hidden(type="radio" name="dayList" autocomplete="off" value=dayList checked=(idx === 0))
|
|
49
49
|
span= dayList
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
include formatting_functions.pug
|
|
2
2
|
|
|
3
|
-
<!-- Timetable generated on #{Date()} using GTFS-to-HTML version #{config.gtfsToHtmlVersion} -->
|
|
3
|
+
<!-- Timetable generated on #{new Date().toISOString()} using GTFS-to-HTML version #{config.gtfsToHtmlVersion} -->
|
|
4
4
|
.timetable-page(class=`menu-type-${config.menuType}`)
|
|
5
5
|
.container.mx-4(class="md:mx-auto")
|
|
6
6
|
if config.showRouteTitle
|
|
@@ -9,7 +9,7 @@ include formatting_functions.pug
|
|
|
9
9
|
.route-color-swatch-large.flex-none(style=`background-color: ${formatRouteColor(route)}; color: ${formatRouteTextColor(route)};`)= route.route_short_name || ''
|
|
10
10
|
div= timetablePage.timetable_page_label
|
|
11
11
|
if config.effectiveDate
|
|
12
|
-
.effective-date.text-gray-600.
|
|
12
|
+
.effective-date.text-gray-600.mt-2= `Effective ${config.effectiveDate}`
|
|
13
13
|
|
|
14
14
|
include timetable_menu.pug
|
|
15
15
|
|
|
@@ -9,10 +9,14 @@ block extraHeader
|
|
|
9
9
|
script(src=`${config.assetPath}js/timetable-menu.js`)
|
|
10
10
|
|
|
11
11
|
if config.showMap
|
|
12
|
-
script(src="https://api.mapbox.com/mapbox-gl-js/v3.
|
|
12
|
+
script(src="https://api.mapbox.com/mapbox-gl-js/v3.5.1/mapbox-gl.js")
|
|
13
13
|
script.
|
|
14
14
|
mapboxgl.accessToken = '#{config.mapboxAccessToken}';
|
|
15
15
|
script(src=`${config.assetPath}js/timetable-map.js`)
|
|
16
16
|
|
|
17
|
-
link(href="https://api.mapbox.com/mapbox-gl-js/v3.
|
|
17
|
+
link(href="https://api.mapbox.com/mapbox-gl-js/v3.5.1/mapbox-gl.css" rel="stylesheet")
|
|
18
|
+
|
|
19
|
+
link(rel="stylesheet" href=`${config.assetPath}css/timetable_styles.css`)
|
|
20
|
+
if config.outputFormat === 'pdf'
|
|
21
|
+
link(rel="stylesheet" href=`${config.assetPath}css/timetable_pdf_styles.css`)
|
|
18
22
|
|
|
Binary file
|