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 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
- if (timetablePage.consolidatedTimetables.length === 1) {
516
- // Get label from first timetable if there is only one
517
- return timetablePage.consolidatedTimetables[0].timetable_label;
518
- } else {
519
- // Otherwise, use route names from all timetables
520
- const routes = uniqBy(
521
- flatMap(
522
- timetablePage.consolidatedTimetables,
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
- return timetablePageLabel.join(' and ');
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.9",
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.0",
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.0",
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.0.11",
64
+ "husky": "^9.1.1",
65
65
  "lint-staged": "^15.2.7",
66
- "prettier": "^3.3.2"
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
- /* Timetable Styles */
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: #aed9fb;
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 8px;
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
+ }
@@ -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('text-white bg-blue-600', $(element).is(':checked'));
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('text-white bg-blue-600', $(element).is(':checked'));
34
+ .toggleClass('btn-blue', $(element).is(':checked'));
38
35
  $(element)
39
36
  .parents('label')
40
- .toggleClass(
41
- 'text-gray-600 bg-gray-300',
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 formatRouteName(route) {
15
- const hasLongName = route.route_long_name !== '' && route.route_long_name !== null;
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) {
@@ -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
- .container.mx-4.h-screen.items-stretch(class="md:mx-auto md:flex")
3
+ .h-screen.items-stretch(class="md:flex")
4
4
  if !timetablePages || !timetablePages.length
5
- .flex.justify-center
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.pt-4.pb-2= `${formatAgencyName(timetablePageGroup.agency)} Routes`
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
- .flex.my-1.items-center.gap-1
17
- .route-color-swatch.flex-none(style=`background-color: ${formatRouteColor(route)}; color: ${formatRouteTextColor(route)};`)= route.route_short_name || ''
18
- .text-gray-600.leading-none= formatRouteName(route)
19
- .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
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.ml-4.h-full.w-full(id="system_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
- var geojson = !{JSON.stringify(geojson) || '\'\''};
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.3.0/mapbox-gl.js")
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.3.0/mapbox-gl.css" rel="stylesheet")
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.flex.items-center.justify-center.px-8.py-3.border.border-transparent.text-base.rounded-md.text-white.bg-blue-600(class="hover:bg-blue-700 md:py-4 md:text-lg md:px-10" href=`#timetable_id_${timetable.timetable_id}`)= timetable.timetable_label
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.cursor-pointer.mb-2.w-full.flex.items-center.justify-center.px-8.py-3.border.border-transparent.text-base.rounded-md(class=idx === 0 ? 'text-white bg-blue-600': 'text-gray-600 bg-gray-300')
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.cursor-pointer.mb-2.w-full.flex.items-center.justify-center.px-8.py-3.border.border-transparent.text-base.rounded-md(class=idx === 0 ? 'text-white bg-blue-600': 'text-gray-600 bg-gray-300')
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.mb-2= `Effective ${config.effectiveDate}`
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.3.0/mapbox-gl.js")
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.3.0/mapbox-gl.css" rel="stylesheet")
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