gtfs-to-html 2.6.11 → 2.7.0

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.
@@ -0,0 +1,447 @@
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
+ /* Timetable Styles */
38
+
39
+ .timetable-page {
40
+ margin-left: 1rem;
41
+ margin-right: 1rem;
42
+ }
43
+
44
+ @media (min-width: 640px) {
45
+ .timetable-page {
46
+ max-width: 640px;
47
+ }
48
+ }
49
+
50
+ @media (min-width: 768px) {
51
+ .timetable-page {
52
+ max-width: 768px;
53
+ margin-left: auto;
54
+ margin-right: auto;
55
+ }
56
+ }
57
+
58
+ @media (min-width: 1024px) {
59
+ .timetable-page {
60
+ max-width: 1024px;
61
+ }
62
+ }
63
+
64
+ @media (min-width: 1280px) {
65
+ .timetable-page {
66
+ max-width: 1280px;
67
+ }
68
+ }
69
+
70
+ @media (min-width: 1536px) {
71
+ .timetable-page {
72
+ max-width: 1536px;
73
+ }
74
+ }
75
+
76
+ .timetable-page h1 {
77
+ font-size: 1.5rem;
78
+ line-height: 2rem;
79
+ padding-top: 1rem;
80
+ gap: 0.24rem;
81
+ display: flex;
82
+ align-items: center;
83
+ }
84
+
85
+ .timetable-page h2 {
86
+ font-size: 1.25rem;
87
+ line-height: 1.75rem;
88
+ }
89
+
90
+ .timetable-page h3 {
91
+ font-weight: 600;
92
+ margin-bottom: 0.25rem;
93
+ }
94
+
95
+ .timetable-page .effective-date {
96
+ margin-top: 0.5rem;
97
+ color: rgb(75 85 99);
98
+ }
99
+
100
+ .timetable-page .sr-only {
101
+ position: absolute;
102
+ width: 1px;
103
+ height: 1px;
104
+ padding: 0;
105
+ margin: -1px;
106
+ overflow: hidden;
107
+ clip: rect(0, 0, 0, 0);
108
+ white-space: nowrap;
109
+ border-width: 0;
110
+ }
111
+
112
+ .timetable-page .hidden {
113
+ display: none;
114
+ }
115
+
116
+ .timetable-page .timetable .timetable-label {
117
+ margin-bottom: 0.5rem;
118
+ }
119
+
120
+ .timetable-page .timetable .timetable-footer {
121
+ display: grid;
122
+ grid-template-columns: repeat(1, minmax(0, 1fr));
123
+ gap: 1rem;
124
+ }
125
+
126
+ @media (min-width: 768px) {
127
+ .timetable-page .timetable .timetable-footer {
128
+ grid-template-columns: repeat(3, minmax(0, 1fr));
129
+ }
130
+ }
131
+
132
+ /* Menu Styles */
133
+
134
+ .timetable-page .timetable-simple-menu {
135
+ margin-top: 0.75rem;
136
+ margin-bottom: 0.75rem;
137
+ }
138
+
139
+ .timetable-page .timetable-jump-menu {
140
+ margin-top: 0.75rem;
141
+ margin-bottom: 0.75rem;
142
+ display: grid;
143
+ grid-template-columns: repeat(1, minmax(0, 1fr));
144
+ gap: 1rem;
145
+ }
146
+
147
+ @media (min-width: 768px) {
148
+ .timetable-page .timetable-jump-menu {
149
+ grid-template-columns: repeat(3, minmax(0, 1fr));
150
+ }
151
+ }
152
+
153
+ .timetable-page .timetable-jump-menu a {
154
+ width: 100%;
155
+ margin-bottom: 0.5rem;
156
+ }
157
+
158
+ .timetable-page .timetable-radio-menu {
159
+ margin-top: 0.75rem;
160
+ margin-bottom: 0.75rem;
161
+ display: grid;
162
+ grid-template-columns: repeat(1, minmax(0, 1fr));
163
+ gap: 1rem;
164
+ }
165
+
166
+ @media (min-width: 768px) {
167
+ .timetable-page .timetable-radio-menu {
168
+ grid-template-columns: repeat(3, minmax(0, 1fr));
169
+ }
170
+ }
171
+
172
+ .timetable-page .timetable-radio-menu label {
173
+ width: 100%;
174
+ margin-bottom: 0.5rem;
175
+ }
176
+
177
+ .timetable-page .menu-type-radio .timetable {
178
+ display: none;
179
+ }
180
+
181
+ .timetable-page .btn-blue {
182
+ color: rgb(255 255 255);
183
+ padding: 0.75rem 1.5rem;
184
+ background-color: rgb(37 99 235);
185
+ border-radius: 0.375rem;
186
+ justify-content: center;
187
+ align-items: center;
188
+ display: inline-flex;
189
+ cursor: pointer;
190
+ text-decoration: none;
191
+ }
192
+
193
+ .timetable-page .btn-blue:hover {
194
+ background-color: rgb(29 78 216);
195
+ text-decoration: none;
196
+ }
197
+
198
+ .timetable-page .btn-gray {
199
+ color: rgb(75 85 99);
200
+ padding: 0.75rem 1.5rem;
201
+ background-color: rgb(209 213 219);
202
+ border-radius: 0.375rem;
203
+ justify-content: center;
204
+ align-items: center;
205
+ display: inline-flex;
206
+ cursor: pointer;
207
+ text-decoration: none;
208
+ }
209
+
210
+ .timetable-page .btn-gray:hover {
211
+ background-color: rgb(201, 206, 213);
212
+ text-decoration: none;
213
+ }
214
+
215
+ .timetable-page .btn-sm {
216
+ padding: 0.25rem 1rem;
217
+ border-radius: 0.25rem;
218
+ }
219
+
220
+ .timetable-page .timetable {
221
+ margin-bottom: 2.5rem;
222
+ }
223
+
224
+ .timetable-page .timetable .table-vertical .stop-header {
225
+ text-align: center;
226
+ }
227
+
228
+ .timetable-page .timetable .run-header {
229
+ text-align: center;
230
+ }
231
+
232
+ .timetable-page .timetable .run-footer {
233
+ text-align: center;
234
+ }
235
+
236
+ .timetable-page .timetable .run-footer .continues-as-route {
237
+ font-weight: bold;
238
+ }
239
+
240
+ .timetable-page .timetable .stop-code {
241
+ font-weight: normal;
242
+ }
243
+
244
+ .timetable-page .timetable .stop-time {
245
+ text-align: center;
246
+ }
247
+
248
+ .timetable-page .timetable .stop-time.pm {
249
+ font-weight: bold;
250
+ }
251
+
252
+ .timetable-page .timetable a.symbol {
253
+ padding-left: 4px;
254
+ color: #212529;
255
+ text-decoration: none;
256
+ }
257
+
258
+ .timetable-page .timetable .trip-frequency {
259
+ text-align: center;
260
+ font-weight: bold;
261
+ }
262
+
263
+ .timetable-page .timetable .city-row {
264
+ font-size: 1.5em;
265
+ color: #415d86;
266
+ }
267
+
268
+ .timetable-page .timetable th.city-column {
269
+ font-size: 1.5em;
270
+ text-align: center;
271
+ }
272
+
273
+ .timetable-page .timetable .table-container {
274
+ overflow-x: scroll;
275
+ margin: 20px 0;
276
+ }
277
+
278
+ .timetable-page .timetable .table-container::-webkit-scrollbar {
279
+ -webkit-appearance: none;
280
+ height: 8px;
281
+ }
282
+
283
+ .timetable-page .timetable .table-container::-webkit-scrollbar-track {
284
+ background-color: rgba(57, 57, 57, 0.2);
285
+ border-radius: 4px;
286
+ }
287
+
288
+ .timetable-page .timetable .table-container::-webkit-scrollbar-thumb {
289
+ border-radius: 4px;
290
+ background-color: rgba(156, 156, 156, 0.8);
291
+ }
292
+
293
+ .timetable-page .timetable .table-container table {
294
+ text-indent: 0;
295
+ border-color: inherit;
296
+ border-collapse: collapse;
297
+ }
298
+
299
+ .timetable-page .timetable thead tr {
300
+ background: #bae6fd;
301
+ }
302
+
303
+ .timetable-page .timetable thead tr,
304
+ .timetable-page .timetable thead tr a {
305
+ color: #222222;
306
+ }
307
+
308
+ .timetable-page .timetable th {
309
+ text-align: left;
310
+ }
311
+
312
+ .timetable-page .timetable td,
313
+ .timetable-page .timetable th {
314
+ padding: 0;
315
+ }
316
+
317
+ .timetable-page .timetable table > thead > tr > th,
318
+ .timetable-page .timetable table > tbody > tr > th,
319
+ .timetable-page .timetable table > tfoot > tr > th,
320
+ .timetable-page .timetable table > thead > tr > td,
321
+ .timetable-page .timetable table > tbody > tr > td,
322
+ .timetable-page .timetable table > tfoot > tr > td {
323
+ padding: 8px;
324
+ line-height: 1.42857143;
325
+ vertical-align: top;
326
+ border: 1px solid #dddddd;
327
+ }
328
+
329
+ .timetable-page .timetable table > thead > tr > th {
330
+ vertical-align: top;
331
+ border-bottom: 2px solid #dddddd;
332
+ }
333
+
334
+ .timetable-page .timetable table > caption + thead > tr:first-child > th,
335
+ .timetable-page .timetable table > colgroup + thead > tr:first-child > th,
336
+ .timetable-page .timetable table > thead:first-child > tr:first-child > th,
337
+ .timetable-page .timetable table > caption + thead > tr:first-child > td,
338
+ .timetable-page .timetable table > colgroup + thead > tr:first-child > td,
339
+ .timetable-page .timetable table > thead:first-child > tr:first-child > td {
340
+ border-top: 0;
341
+ }
342
+
343
+ .timetable-page .timetable table > tbody + tbody {
344
+ border-top: 2px solid #dddddd;
345
+ }
346
+
347
+ .timetable-page .timetable table > thead > tr > th,
348
+ .timetable-page .timetable table > thead > tr > td {
349
+ border-bottom-width: 2px;
350
+ }
351
+
352
+ .timetable-page .timetable table > tbody > tr:nth-of-type(odd) {
353
+ background-color: #f9f9f9;
354
+ }
355
+
356
+ .timetable-page .table-horizontal tbody tr th.stop-name-container {
357
+ min-width: 175px;
358
+ }
359
+
360
+ @media screen and (min-width: 768px) {
361
+ .timetable-page .table-horizontal tbody tr th.stop-name-container {
362
+ min-width: 250px;
363
+ }
364
+ }
365
+
366
+ .timetable-page .table-hourly {
367
+ width: auto;
368
+ }
369
+
370
+ .timetable-page .timetable .table-vertical .trip-row .trip-notes {
371
+ text-wrap: nowrap;
372
+ }
373
+
374
+ .timetable-page .route-color-swatch {
375
+ min-width: 34px;
376
+ height: 34px;
377
+ border-radius: 17px;
378
+ text-align: center;
379
+ line-height: 34px;
380
+ font-size: 14px;
381
+ letter-spacing: -0.5px;
382
+ padding: 0 5px;
383
+ flex: none;
384
+ flex-shrink: 0;
385
+ }
386
+
387
+ .timetable-page .route-color-swatch-large {
388
+ min-width: 46px;
389
+ height: 46px;
390
+ border-radius: 23px;
391
+ text-align: center;
392
+ line-height: 46px;
393
+ font-size: 20px;
394
+ font-weight: bold;
395
+ letter-spacing: -1px;
396
+ padding: 0 6px;
397
+ flex: none;
398
+ flex-shrink: 0;
399
+ }
400
+
401
+ /* Map Styles */
402
+
403
+ .timetable-page .map {
404
+ min-height: 350px;
405
+ }
406
+
407
+ @media screen and (min-width: 768px) {
408
+ .timetable-page .map {
409
+ min-height: 450px;
410
+ }
411
+ }
412
+
413
+ .timetable-page .map .mapboxgl-popup-content .popup-title {
414
+ margin: 0 20px 5px 0;
415
+ font-size: 1rem;
416
+ font-weight: 700;
417
+ line-height: 1;
418
+ }
419
+
420
+ .timetable-page .map .mapboxgl-popup-content .popup-label {
421
+ margin-right: 0.25rem;
422
+ }
423
+
424
+ .timetable-page .map .mapboxgl-popup-content .route-list {
425
+ margin-bottom: 0.5rem;
426
+ }
427
+
428
+ .timetable-page .map .mapboxgl-popup-content .map-route-item {
429
+ display: flex;
430
+ align-items: center;
431
+ font-size: 0.75rem;
432
+ line-height: 1;
433
+ margin-bottom: 0.5rem;
434
+ gap: 0.5rem;
435
+ }
436
+
437
+ .timetable-page .map .mapboxgl-popup-content .map-route-item:hover {
438
+ text-decoration: none;
439
+ }
440
+
441
+ .timetable-page .map .mapboxgl-popup-content a.map-route-item .underline-hover:hover {
442
+ text-decoration: underline;
443
+ }
444
+
445
+ .timetable-page .map .mapboxgl-popup-content .mapboxgl-popup-close-button {
446
+ padding: 0 5px;
447
+ }
@@ -1,11 +1,11 @@
1
1
  -
2
2
  function getTimetableSummary(timetable) {
3
- var summary = `This table shows schedules for a selection of key stops on the route for ${timetable.timetable_label} ${timetable.dayList}.`;
4
- if (timetable.orientation = 'vertical') {
3
+ let summary = `This table shows schedules for a selection of key stops on the route for ${timetable.timetable_label} ${timetable.dayList}.`;
4
+ if (timetable.orientation === 'vertical') {
5
5
  summary += ' Stops and their schedule times are listed in the columns.';
6
- } else if (timetable.orientation = 'horizontal') {
6
+ } else if (timetable.orientation === 'horizontal') {
7
7
  summary += ' Schedule times are listed in rows, starting with the stop name in the first cell of the row.';
8
- } else if (timetable.orientation = 'hourly') {
8
+ } else if (timetable.orientation === 'hourly') {
9
9
  summary += ' Schedule times are listed in rows, starting with the stop name in the first cell of the row and the minutes after the hour in the second row.';
10
10
  }
11
11
  return summary;
@@ -16,7 +16,7 @@
16
16
  }
17
17
 
18
18
  function formatFrequencyWarning(frequencies) {
19
- var warning = 'Trip times shown below are an example only. ';
19
+ let warning = 'Trip times shown below are an example only. ';
20
20
  frequencies.forEach((frequency, idx) => {
21
21
  if (idx === 0) {
22
22
  warning += 'This route runs every ';
@@ -90,3 +90,19 @@
90
90
  geojson: minifiedGeojson
91
91
  }
92
92
  }
93
+
94
+ function getRouteColorsAsCss (route) {
95
+ if (route && route.route_color) {
96
+ return `background: #${route.route_color}; color: #${route.route_text_color ?? 'ffffff'};`
97
+ }
98
+
99
+ return ''
100
+ }
101
+
102
+ function formatRouteName(route) {
103
+ if (isNullOrEmpty(route.route_long_name)) {
104
+ return `Route ${route.route_short_name}`;
105
+ }
106
+
107
+ return route.route_long_name;
108
+ }
@@ -1,5 +1,5 @@
1
1
  /* global window, document, _, $, mapboxgl */
2
- /* eslint no-var: "off", prefer-arrow-callback: "off", no-unused-vars: "off" */
2
+ /* eslint prefer-arrow-callback: "off", no-unused-vars: "off" */
3
3
 
4
4
  const maps = {};
5
5
 
@@ -13,27 +13,30 @@ function formatRouteTextColor(route) {
13
13
 
14
14
  function formatRoute(route) {
15
15
  const html = route.route_url
16
- ? $('<a>').attr('href', route.route_url).addClass('hover:no-underline')
16
+ ? $('<a>').attr('href', route.route_url)
17
17
  : $('<div>');
18
18
 
19
- html.addClass('route-item text-xs mb-2');
19
+ html.addClass('map-route-item');
20
+
21
+ // Only add color swatch if route has a color
22
+ const routeItemDivs = [];
20
23
 
21
24
  if (route.route_color) {
22
- // Only add color swatch if route has a color
23
- $('<div>')
24
- .addClass('flex items-center gap-2')
25
- .html([
26
- $('<div>')
27
- .addClass('route-color-swatch flex-shrink-0 text-white')
28
- .css('backgroundColor', formatRouteColor(route))
29
- .css('color', formatRouteTextColor(route))
30
- .text(route.route_short_name || ''),
31
- $('<div>')
32
- .addClass('hover:underline')
33
- .text(route.route_long_name || ''),
34
- ])
35
- .appendTo(html);
25
+ routeItemDivs.push(
26
+ $('<div>')
27
+ .addClass('route-color-swatch')
28
+ .css('backgroundColor', formatRouteColor(route))
29
+ .css('color', formatRouteTextColor(route))
30
+ .text(route.route_short_name ?? ''),
31
+ );
36
32
  }
33
+ routeItemDivs.push(
34
+ $('<div>')
35
+ .addClass('underline-hover')
36
+ .text(route.route_long_name ?? `Route ${route.route_short_name}`),
37
+ );
38
+
39
+ html.append(routeItemDivs);
37
40
 
38
41
  return html.prop('outerHTML');
39
42
  }
@@ -60,17 +63,24 @@ function formatStopPopup(feature) {
60
63
  .appendTo(html);
61
64
 
62
65
  if (feature.properties.stop_code ?? false) {
63
- $('<label>').addClass('mr-1').text('Stop Code:').appendTo(html);
64
-
65
- $('<strong>').text(feature.properties.stop_code).appendTo(html);
66
+ $('<div>')
67
+ .html([
68
+ $('<label>').addClass('popup-label').text('Stop Code:'),
69
+ $('<strong>').text(feature.properties.stop_code),
70
+ ])
71
+ .appendTo(html);
66
72
  }
67
73
 
68
- $('<label>').addClass('block').text('Routes Served:').appendTo(html);
74
+ $('<label>').text('Routes Served:').appendTo(html);
69
75
 
70
- $(html).append(routes.map((route) => formatRoute(route)));
76
+ $(html).append(
77
+ $('<div>')
78
+ .addClass('route-list')
79
+ .html(routes.map((route) => formatRoute(route))),
80
+ );
71
81
 
72
82
  $('<a>')
73
- .addClass('btn-blue btn-sm mt-2')
83
+ .addClass('btn-blue btn-sm')
74
84
  .prop(
75
85
  'href',
76
86
  `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`,
@@ -13,32 +13,30 @@ function formatRouteTextColor(route) {
13
13
 
14
14
  function formatRoute(route) {
15
15
  const html = route.route_url
16
- ? $('<a>').attr('href', route.route_url).addClass('hover:no-underline')
16
+ ? $('<a>').attr('href', route.route_url)
17
17
  : $('<div>');
18
18
 
19
- html.addClass('route-item text-xs mb-2');
19
+ html.addClass('map-route-item');
20
+
21
+ // Only add color swatch if route has a color
22
+ const routeItemDivs = [];
20
23
 
21
24
  if (route.route_color) {
22
- // Only add color swatch if route has a color
23
- $('<div>')
24
- .addClass('flex items-center gap-2')
25
- .html([
26
- $('<div>')
27
- .addClass('route-color-swatch flex-shrink-0 text-white')
28
- .css('backgroundColor', formatRouteColor(route))
29
- .css('color', formatRouteTextColor(route))
30
- .text(route.route_short_name || ''),
31
- $('<div>')
32
- .addClass('hover:underline')
33
- .text(route.route_long_name || ''),
34
- ])
35
- .appendTo(html);
36
- } else {
37
- $('<div>')
38
- .addClass('hover:underline')
39
- .text(route.route_long_name || '')
40
- .appendTo(html);
25
+ routeItemDivs.push(
26
+ $('<div>')
27
+ .addClass('route-color-swatch')
28
+ .css('backgroundColor', formatRouteColor(route))
29
+ .css('color', formatRouteTextColor(route))
30
+ .text(route.route_short_name ?? ''),
31
+ );
41
32
  }
33
+ routeItemDivs.push(
34
+ $('<div>')
35
+ .addClass('underline-hover')
36
+ .text(route.route_long_name ?? `Route ${route.route_short_name}`),
37
+ );
38
+
39
+ html.append(routeItemDivs);
42
40
 
43
41
  return html.prop('outerHTML');
44
42
  }
@@ -53,17 +51,24 @@ function formatStopPopup(feature, routes) {
53
51
  .appendTo(html);
54
52
 
55
53
  if (feature.properties.stop_code ?? false) {
56
- $('<label>').addClass('mr-1').text('Stop Code:').appendTo(html);
57
-
58
- $('<strong>').text(feature.properties.stop_code).appendTo(html);
54
+ $('<div>')
55
+ .html([
56
+ $('<label>').addClass('popup-label').text('Stop Code:'),
57
+ $('<strong>').text(feature.properties.stop_code),
58
+ ])
59
+ .appendTo(html);
59
60
  }
60
61
 
61
- $('<label>').addClass('block').text('Routes Served:').appendTo(html);
62
+ $('<label>').text('Routes Served:').appendTo(html);
62
63
 
63
- $(html).append(routeIds.map((routeId) => formatRoute(routes[routeId])));
64
+ $(html).append(
65
+ $('<div>')
66
+ .addClass('route-list')
67
+ .html(routeIds.map((routeId) => formatRoute(routes[routeId]))),
68
+ );
64
69
 
65
70
  $('<a>')
66
- .addClass('btn-blue btn-sm mt-2')
71
+ .addClass('btn-blue btn-sm')
67
72
  .prop(
68
73
  'href',
69
74
  `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`,
@@ -1,25 +1,25 @@
1
1
  include formatting_functions.pug
2
2
 
3
- .h-screen.items-stretch(class="md:flex")
3
+ .timetable-overview
4
4
  if !timetablePages || !timetablePages.length
5
- h1.text-2xl.mx-4.py-3 No timetables found
5
+ h1 No timetables found
6
6
  else
7
- .overview-list.flex-none(class="md:overflow-y-scroll md:max-w-96")
7
+ .overview-list
8
8
  each timetablePageGroup in getAgencyTimetableGroups(timetablePages, agencies)
9
- h1.text-2xl.mx-4.py-3= `${formatAgencyName(timetablePageGroup.agency)} Routes`
10
-
9
+ h1= `${formatAgencyName(timetablePageGroup.agency)} Routes`
11
10
  each timetablePage in timetablePageGroup.timetablePages
12
11
  if config.allowEmptyTimetables || timetablePage.consolidatedTimetables.length > 0
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(',') : ''}`)
14
- each route in _.uniqBy(_.flatMap(timetablePage.consolidatedTimetables, timetable => timetable.routes), 'route_id')
15
- .route-color-swatch-large.flex-none(style=`background-color: ${formatRouteColor(route)}; color: ${formatRouteTextColor(route)};`)= route.route_short_name || ''
12
+ a.timetable-page-link(href=`${timetablePage.relativePath}` data-route-ids=`${timetablePage.route_ids ? timetablePage.route_ids.join(',') : ''}`)
13
+ - const timetableRouteList = _.uniqBy(_.flatMap(timetablePage.consolidatedTimetables, timetable => timetable.routes), 'route_id')
14
+ each route in timetableRouteList
15
+ .route-color-swatch-large(style=`background-color: ${formatRouteColor(route)}; color: ${formatRouteTextColor(route)};`)= route.route_short_name || ''
16
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
17
+ .timetable-page-label= timetablePage.timetable_page_label || timetableRouteList.map(route => formatRouteName(route)).join(' and ')
18
+ .badge-gray= timetablePage.dayList
19
19
  if config.showMap
20
- .map.h-full.w-full(id="system_map")
20
+ #system_map.overview-map
21
21
 
22
- //- Use #{variable} format to inject values from pug to client side js
22
+ //- Use !{variable} format to inject values from pug to client side js
23
23
  script.
24
24
  (function() {
25
25
  const geojson = !{JSON.stringify(geojson) || '\'\''};