gtfs-to-html 2.3.5 → 2.4.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 +29 -0
- package/docker/Dockerfile +1 -1
- package/lib/geojson-utils.js +6 -1
- package/lib/log-utils.js +8 -7
- package/package.json +13 -13
- package/public/css/timetable_styles.css +4 -16
- package/public/js/system-map.js +408 -80
- package/public/js/timetable-map.js +72 -27
- package/views/default/layout.pug +2 -1
- package/views/default/overview.pug +2 -2
- package/views/default/timetablepage.pug +1 -1
- package/www/docs/configuration.md +1 -1
- package/www/docs/quick-start.md +29 -29
- package/www/docs/related-libraries.md +5 -0
- package/www/package.json +5 -5
- package/www/src/pages/index.js +55 -17
- package/www/yarn.lock +1841 -2011
|
@@ -63,6 +63,10 @@ function getBounds(geojson) {
|
|
|
63
63
|
|
|
64
64
|
function createMap(id, geojson, routes) {
|
|
65
65
|
const defaultRouteColor = '#FF4728';
|
|
66
|
+
const lineLayout = {
|
|
67
|
+
'line-join': 'round',
|
|
68
|
+
'line-cap': 'round',
|
|
69
|
+
};
|
|
66
70
|
|
|
67
71
|
if (!geojson || geojson.features.length === 0) {
|
|
68
72
|
$('#map_' + id).hide();
|
|
@@ -92,6 +96,9 @@ function createMap(id, geojson, routes) {
|
|
|
92
96
|
duration: 0,
|
|
93
97
|
});
|
|
94
98
|
|
|
99
|
+
// Turn of Points of Interest labels
|
|
100
|
+
map.setLayoutProperty('poi-label', 'visibility', 'none');
|
|
101
|
+
|
|
95
102
|
// Find the index of the first symbol layer in the map style
|
|
96
103
|
let firstSymbolId;
|
|
97
104
|
for (const layer of map.getStyle().layers) {
|
|
@@ -101,7 +108,40 @@ function createMap(id, geojson, routes) {
|
|
|
101
108
|
}
|
|
102
109
|
}
|
|
103
110
|
|
|
104
|
-
// Add route
|
|
111
|
+
// Add route drop shadow outline first
|
|
112
|
+
map.addLayer(
|
|
113
|
+
{
|
|
114
|
+
id: 'route-line-shadow',
|
|
115
|
+
type: 'line',
|
|
116
|
+
source: {
|
|
117
|
+
type: 'geojson',
|
|
118
|
+
data: geojson,
|
|
119
|
+
},
|
|
120
|
+
paint: {
|
|
121
|
+
'line-color': '#000000',
|
|
122
|
+
'line-opacity': 0.3,
|
|
123
|
+
'line-width': {
|
|
124
|
+
base: 12,
|
|
125
|
+
stops: [
|
|
126
|
+
[14, 20],
|
|
127
|
+
[18, 42],
|
|
128
|
+
],
|
|
129
|
+
},
|
|
130
|
+
'line-blur': {
|
|
131
|
+
base: 12,
|
|
132
|
+
stops: [
|
|
133
|
+
[14, 20],
|
|
134
|
+
[18, 42],
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
layout: lineLayout,
|
|
139
|
+
filter: ['!has', 'stop_id'],
|
|
140
|
+
},
|
|
141
|
+
firstSymbolId
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
// Add route line outline
|
|
105
145
|
map.addLayer(
|
|
106
146
|
{
|
|
107
147
|
id: 'route-line-outline',
|
|
@@ -113,17 +153,21 @@ function createMap(id, geojson, routes) {
|
|
|
113
153
|
paint: {
|
|
114
154
|
'line-color': '#FFFFFF',
|
|
115
155
|
'line-opacity': 1,
|
|
116
|
-
'line-width':
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
156
|
+
'line-width': {
|
|
157
|
+
base: 8,
|
|
158
|
+
stops: [
|
|
159
|
+
[14, 12],
|
|
160
|
+
[18, 32],
|
|
161
|
+
],
|
|
162
|
+
},
|
|
121
163
|
},
|
|
164
|
+
layout: lineLayout,
|
|
122
165
|
filter: ['!has', 'stop_id'],
|
|
123
166
|
},
|
|
124
167
|
firstSymbolId
|
|
125
168
|
);
|
|
126
169
|
|
|
170
|
+
// Add route line
|
|
127
171
|
map.addLayer(
|
|
128
172
|
{
|
|
129
173
|
id: 'route-line',
|
|
@@ -135,17 +179,21 @@ function createMap(id, geojson, routes) {
|
|
|
135
179
|
paint: {
|
|
136
180
|
'line-color': ['to-color', ['get', 'route_color'], defaultRouteColor],
|
|
137
181
|
'line-opacity': 1,
|
|
138
|
-
'line-width':
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
182
|
+
'line-width': {
|
|
183
|
+
base: 4,
|
|
184
|
+
stops: [
|
|
185
|
+
[14, 6],
|
|
186
|
+
[18, 16],
|
|
187
|
+
],
|
|
188
|
+
},
|
|
143
189
|
},
|
|
190
|
+
layout: lineLayout,
|
|
144
191
|
filter: ['!has', 'stop_id'],
|
|
145
192
|
},
|
|
146
193
|
firstSymbolId
|
|
147
194
|
);
|
|
148
195
|
|
|
196
|
+
// Add stops
|
|
149
197
|
map.addLayer(
|
|
150
198
|
{
|
|
151
199
|
id: 'stops',
|
|
@@ -155,22 +203,23 @@ function createMap(id, geojson, routes) {
|
|
|
155
203
|
data: geojson,
|
|
156
204
|
},
|
|
157
205
|
paint: {
|
|
206
|
+
'circle-color': '#fff',
|
|
158
207
|
'circle-radius': {
|
|
208
|
+
base: 1.75,
|
|
159
209
|
stops: [
|
|
160
|
-
[
|
|
161
|
-
[
|
|
162
|
-
[15, 6],
|
|
210
|
+
[12, 4],
|
|
211
|
+
[22, 100],
|
|
163
212
|
],
|
|
164
213
|
},
|
|
165
|
-
'circle-stroke-
|
|
166
|
-
'circle-stroke-
|
|
167
|
-
'circle-color': '#363636',
|
|
214
|
+
'circle-stroke-color': '#3f4a5c',
|
|
215
|
+
'circle-stroke-width': 2,
|
|
168
216
|
},
|
|
169
217
|
filter: ['has', 'stop_id'],
|
|
170
218
|
},
|
|
171
219
|
firstSymbolId
|
|
172
220
|
);
|
|
173
221
|
|
|
222
|
+
// Layer for highlighted stops
|
|
174
223
|
map.addLayer(
|
|
175
224
|
{
|
|
176
225
|
id: 'stops-highlighted',
|
|
@@ -180,16 +229,16 @@ function createMap(id, geojson, routes) {
|
|
|
180
229
|
data: geojson,
|
|
181
230
|
},
|
|
182
231
|
paint: {
|
|
232
|
+
'circle-color': '#fff',
|
|
183
233
|
'circle-radius': {
|
|
234
|
+
base: 1.75,
|
|
184
235
|
stops: [
|
|
185
|
-
[
|
|
186
|
-
[
|
|
187
|
-
[15, 7],
|
|
236
|
+
[12, 5],
|
|
237
|
+
[22, 125],
|
|
188
238
|
],
|
|
189
239
|
},
|
|
190
240
|
'circle-stroke-width': 2,
|
|
191
|
-
'circle-stroke-color': '#
|
|
192
|
-
'circle-color': '#888888',
|
|
241
|
+
'circle-stroke-color': '#3f4a5c',
|
|
193
242
|
},
|
|
194
243
|
filter: ['==', 'stop_id', ''],
|
|
195
244
|
},
|
|
@@ -216,7 +265,7 @@ function createMap(id, geojson, routes) {
|
|
|
216
265
|
[event.point.x + 5, event.point.y + 5],
|
|
217
266
|
];
|
|
218
267
|
const features = map.queryRenderedFeatures(bbox, {
|
|
219
|
-
layers: ['stops'],
|
|
268
|
+
layers: ['stops-highlighted', 'stops'],
|
|
220
269
|
});
|
|
221
270
|
|
|
222
271
|
if (!features || features.length === 0) {
|
|
@@ -234,14 +283,10 @@ function createMap(id, geojson, routes) {
|
|
|
234
283
|
|
|
235
284
|
function highlightStop(stopId) {
|
|
236
285
|
map.setFilter('stops-highlighted', ['==', 'stop_id', stopId]);
|
|
237
|
-
map.setPaintProperty('stops', 'circle-opacity', 0.5);
|
|
238
|
-
map.setPaintProperty('stops', 'circle-stroke-opacity', 0.5);
|
|
239
286
|
}
|
|
240
287
|
|
|
241
288
|
function unHighlightStop() {
|
|
242
289
|
map.setFilter('stops-highlighted', ['==', 'stop_id', '']);
|
|
243
|
-
map.setPaintProperty('stops', 'circle-opacity', 1);
|
|
244
|
-
map.setPaintProperty('stops', 'circle-stroke-opacity', 1);
|
|
245
290
|
}
|
|
246
291
|
|
|
247
292
|
// On table hover, highlight stop on map
|
package/views/default/layout.pug
CHANGED
|
@@ -3,12 +3,13 @@ html
|
|
|
3
3
|
head
|
|
4
4
|
title= title
|
|
5
5
|
meta(charset="utf-8")
|
|
6
|
-
link(rel="stylesheet" href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" crossorigin="anonymous")
|
|
7
6
|
link(rel="stylesheet" href=`${config.assetPath}css/timetable_styles.css`)
|
|
8
7
|
if config.outputFormat === 'pdf'
|
|
9
8
|
link(rel="stylesheet" href=`${config.assetPath}css/timetable_pdf_styles.css`)
|
|
10
9
|
meta(name="viewport" content="initial-scale=1.0, width=device-width")
|
|
11
10
|
|
|
11
|
+
script(src="https://cdn.tailwindcss.com")
|
|
12
|
+
|
|
12
13
|
block extraHeader
|
|
13
14
|
|
|
14
15
|
body
|
|
@@ -10,13 +10,13 @@ include formatting_functions.pug
|
|
|
10
10
|
h1.text-2xl.pt-4.pb-2= `${formatAgencyName(timetablePageGroup.agency)} Routes`
|
|
11
11
|
each timetablePage in timetablePageGroup.timetablePages
|
|
12
12
|
if config.allowEmptyTimetables || timetablePage.consolidatedTimetables.length > 0
|
|
13
|
-
a.
|
|
13
|
+
a.block.p-2.border-b.border-slate-200(class="hover:bg-slate-200 hover:no-underline" href=`${timetablePage.relativePath}` data-route-ids=`${timetablePage.route_ids ? timetablePage.route_ids.join(',') : ''}`)
|
|
14
14
|
.text-lg.text-gray-800.leading-none= timetablePage.timetable_page_label
|
|
15
15
|
each route in _.uniqBy(_.flatMap(timetablePage.consolidatedTimetables, timetable => timetable.routes), 'route_id')
|
|
16
16
|
.flex.my-1
|
|
17
17
|
.route-color-swatch.flex-none.mr-2(style=`background-color: #${route.route_color}; color: #${route.route_text_color};`)= route.route_short_name || ''
|
|
18
18
|
.mt-1.text-gray-600.leading-none= formatRouteName(route)
|
|
19
|
-
.text-
|
|
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
|
|
20
20
|
if config.showMap
|
|
21
21
|
.map.ml-4.h-full.w-full(id="system_map")
|
|
22
22
|
|
|
@@ -14,7 +14,7 @@ include formatting_functions.pug
|
|
|
14
14
|
include timetable_menu.pug
|
|
15
15
|
|
|
16
16
|
each timetable in timetablePage.consolidatedTimetables
|
|
17
|
-
.timetable.mb-
|
|
17
|
+
.timetable.mb-10(id=`timetable_id_${formatHtmlId(timetable.timetable_id)}` data-day-list=timetable.dayList data-direction-name=timetable.direction_name data-timetable-id=timetable.timetable_id data-direction-id=timetable.direction_id data-route-id=timetable.route_ids.join('_'))
|
|
18
18
|
if config.showRouteTitle
|
|
19
19
|
h2.text-xl= `${timetable.timetable_label} | ${timetable.dayListLong}`
|
|
20
20
|
each note in getNotesForTimetableLabel(timetable.notes)
|
|
@@ -490,7 +490,7 @@ The default trip-sorting algorithm is `common`.
|
|
|
490
490
|
|
|
491
491
|
### sqlitePath
|
|
492
492
|
|
|
493
|
-
{String} A path to an SQLite database. Optional, defaults to using an in-memory database with a value of `:memory:`. If you want the data imported to persist, you need to specify a value for `sqlitePath
|
|
493
|
+
{String} A path to an SQLite database. Optional, defaults to using an in-memory database with a value of `:memory:`. If you want the data imported to persist, you need to specify a value for `sqlitePath`. Supports tilde as part of the path, like `~/Documents/gtfs`.
|
|
494
494
|
|
|
495
495
|
```
|
|
496
496
|
"sqlitePath": "/tmp/gtfs"
|
package/www/docs/quick-start.md
CHANGED
|
@@ -29,7 +29,6 @@ Skips importing GTFS into SQLite. Useful if you are rerunning with an unchanged
|
|
|
29
29
|
|
|
30
30
|
gtfs-to-html --skipImport
|
|
31
31
|
|
|
32
|
-
|
|
33
32
|
### Processing very large GTFS files.
|
|
34
33
|
|
|
35
34
|
By default, node has a memory limit of 512 MB or 1 GB. If you have a very large GTFS file and want to use the option `showOnlyTimepoint` = `false` you may need to allocate more memory. Use the `max-old-space-size` option. For example to allocate 4 GB:
|
|
@@ -44,17 +43,17 @@ You can use both [`docker`](https://docker.com) and [`docker-compose`](https://d
|
|
|
44
43
|
|
|
45
44
|
A `Dockerfile` is available in the `docker` directory.
|
|
46
45
|
|
|
47
|
-
|
|
46
|
+
- Create a `config.json` file and save in the same directory as your `Dockerfile`. You can use `config-sample.json` from the project root as a starting point. For Docker usage, remove any `sqlitePath` and `templatePath` values from the config.json.
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
- Build the docker image:
|
|
50
49
|
|
|
51
50
|
docker build -t gtfs-to-html .
|
|
52
51
|
|
|
53
|
-
|
|
52
|
+
- Run the docker image:
|
|
54
53
|
|
|
55
54
|
docker run gtfs-to-html
|
|
56
55
|
|
|
57
|
-
|
|
56
|
+
- Copy the generated HTML out of the docker container
|
|
58
57
|
|
|
59
58
|
// Figure out what your container ID is
|
|
60
59
|
docker container ls -a
|
|
@@ -69,17 +68,16 @@ A `Dockerfile` is available in the `docker` directory.
|
|
|
69
68
|
|
|
70
69
|
Docker compose is used for multi-container Docker applications. In this context, it is just a convenient way to manage volumes. This allows (_i_) to get the generated HTML out of the docker container without explicitly copying with `docker cp`, and (_ii_) to tweak and run a new configuration without rebuilding the container from scratch.
|
|
71
70
|
|
|
72
|
-
|
|
71
|
+
- Create a `config.json` file and save in the same directory as your `Dockerfile` and `docker-compose.yml`;
|
|
73
72
|
|
|
74
|
-
|
|
73
|
+
- build and run the container:
|
|
75
74
|
|
|
76
75
|
docker-compose up
|
|
77
76
|
|
|
78
|
-
|
|
77
|
+
- the generated HTML will be available in the folder `html` next to docker files.
|
|
79
78
|
|
|
80
79
|
Do you want to change something? Just delete the old HTML, change your `config.json`, and finally run `docker-compose up` again.
|
|
81
80
|
|
|
82
|
-
|
|
83
81
|
## Usage as a node module
|
|
84
82
|
|
|
85
83
|
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.
|
|
@@ -87,22 +85,25 @@ If you are using this as a node module as part of an application, you can includ
|
|
|
87
85
|
### Code example
|
|
88
86
|
|
|
89
87
|
```javascript
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
88
|
+
import gtfsToHtml from 'gtfs-to-html';
|
|
89
|
+
import { readFile } from 'fs/promises';
|
|
90
|
+
const config = JSON.parse(
|
|
91
|
+
await readFile(new URL('./config.json', import.meta.url))
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
gtfsToHtml(config)
|
|
95
|
+
.then(() => {
|
|
96
|
+
console.log('HTML Generation Successful');
|
|
97
|
+
process.exit();
|
|
98
|
+
})
|
|
99
|
+
.catch((err) => {
|
|
100
|
+
console.error(err);
|
|
101
|
+
process.exit(1);
|
|
102
|
+
});
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
### Example Application
|
|
106
|
+
|
|
106
107
|
An example Express application that uses `gtfs-to-html` is included in the `app` folder. After an initial run of `gtfs-to-html`, the GTFS data will be downloaded and loaded into SQLite.
|
|
107
108
|
|
|
108
109
|
You can view an individual route HTML on demand by running the included Express app:
|
|
@@ -115,17 +116,16 @@ By default, `gtfs-to-html` will look for a `config.json` file in the project roo
|
|
|
115
116
|
|
|
116
117
|
Once running, you can view the HTML in your browser at [localhost:3000](http://localhost:3000)
|
|
117
118
|
|
|
118
|
-
|
|
119
119
|
## Usage as a hosted web app
|
|
120
120
|
|
|
121
121
|
A [hosted version of GTFS-to-HTML as a service](https://run.gtfstohtml.com) allows you to use it entirely within your browser - no downloads or command line necessary.
|
|
122
122
|
|
|
123
123
|
It provides:
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
- a web-based interface for finding GTFS feeds or ability to enter your own URL
|
|
126
|
+
- support for adding [custom configuration](/docs/configuration) as JSON
|
|
127
|
+
- creation of HTML timetables as a downloadable .zip file
|
|
128
|
+
- a preview of all timetables generated directly in your browser
|
|
129
129
|
|
|
130
130
|
[run.gtfstohtml.com](https://run.gtfstohtml.com)
|
|
131
131
|
|
|
@@ -136,8 +136,8 @@ Currently, it is limited to relatively small GTFS files and doesn't offer suppor
|
|
|
136
136
|
### SQLite3 unable to be installed with `Failed to exec install script`
|
|
137
137
|
|
|
138
138
|
For an error like:
|
|
139
|
-
|
|
139
|
+
`lifecycle sqlite3@5.0.0~install: Failed to exec install script`
|
|
140
140
|
|
|
141
141
|
Try installing `gtfs-to-html` using the following flags:
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
`npm install --unsafe-perm --allow-root -g`
|
|
@@ -33,3 +33,8 @@ The [GTFS Text-to-Speech Tester](https://github.com/BlinkTagInc/node-gtfs-tts) i
|
|
|
33
33
|
|
|
34
34
|
[`https://github.com/BlinkTagInc/node-gtfs-tts`](https://github.com/BlinkTagInc/node-gtfs-tts)
|
|
35
35
|
|
|
36
|
+
## `node-gtfs-realtime`
|
|
37
|
+
|
|
38
|
+
[GTFS-realtime](https://developers.google.com/transit/gtfs-realtime) transit data is in [protobuf format](https://developers.google.com/protocol-buffers) which means its not human-readable by default. `node-GTFS-Realtime` aims to make it fast and easy to inspect GTFS-realtime data by providing a one-line command for downloading [GTFS-realtime format](https://developers.google.com/transit/gtfs-realtime) data and converting to JSON. Try it by running `npx gtfs-realtime http://api.bart.gov/gtfsrt/tripupdate.aspx` in your terminal.
|
|
39
|
+
|
|
40
|
+
[`https://github.com/BlinkTagInc/node-gtfs-realtime`](https://github.com/BlinkTagInc/node-gtfs-realtime)
|
package/www/package.json
CHANGED
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"deploy": "docusaurus deploy"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@docusaurus/core": "^2.0.0-
|
|
13
|
-
"@docusaurus/preset-classic": "^2.0.0-
|
|
14
|
-
"clsx": "^1.
|
|
15
|
-
"react": "^18.
|
|
16
|
-
"react-dom": "^18.
|
|
12
|
+
"@docusaurus/core": "^2.0.0-rc.1",
|
|
13
|
+
"@docusaurus/preset-classic": "^2.0.0-rc.1",
|
|
14
|
+
"clsx": "^1.2.1",
|
|
15
|
+
"react": "^18.2.0",
|
|
16
|
+
"react-dom": "^18.2.0"
|
|
17
17
|
},
|
|
18
18
|
"browserslist": {
|
|
19
19
|
"production": [
|
package/www/src/pages/index.js
CHANGED
|
@@ -7,7 +7,6 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
|
7
7
|
import CodeBlock from '@theme/CodeBlock';
|
|
8
8
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
|
9
9
|
import styles from './styles.module.css';
|
|
10
|
-
import { hsl } from 'chalk';
|
|
11
10
|
|
|
12
11
|
const features = [
|
|
13
12
|
{
|
|
@@ -15,28 +14,32 @@ const features = [
|
|
|
15
14
|
imageUrl: 'img/undraw_proud_coder.svg',
|
|
16
15
|
description: (
|
|
17
16
|
<>
|
|
18
|
-
Most transit agencies have schedule data in GTFS format but need to show
|
|
17
|
+
Most transit agencies have schedule data in GTFS format but need to show
|
|
18
|
+
each route's schedule to users on a website.
|
|
19
19
|
</>
|
|
20
|
-
)
|
|
20
|
+
),
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
23
|
title: <>What?</>,
|
|
24
24
|
imageUrl: 'img/undraw_spreadsheets.svg',
|
|
25
25
|
description: (
|
|
26
26
|
<>
|
|
27
|
-
This tool automates the process of creating nicely formatted HTML
|
|
27
|
+
This tool automates the process of creating nicely formatted HTML
|
|
28
|
+
timetables for inclusion on a transit agency website.
|
|
28
29
|
</>
|
|
29
|
-
)
|
|
30
|
+
),
|
|
30
31
|
},
|
|
31
32
|
{
|
|
32
33
|
title: <>Automate schedule changes</>,
|
|
33
34
|
imageUrl: 'img/undraw_happy_music.svg',
|
|
34
35
|
description: (
|
|
35
36
|
<>
|
|
36
|
-
Automating timetable creation means that timetables can be kept up to
|
|
37
|
+
Automating timetable creation means that timetables can be kept up to
|
|
38
|
+
date and accurate when schedule changes happen and the likelihood of
|
|
39
|
+
errors is reduced.
|
|
37
40
|
</>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
41
|
+
),
|
|
42
|
+
},
|
|
40
43
|
];
|
|
41
44
|
|
|
42
45
|
function Feature({ imageUrl, title, description }) {
|
|
@@ -60,25 +63,35 @@ function Home() {
|
|
|
60
63
|
return (
|
|
61
64
|
<Layout
|
|
62
65
|
title="GTFS-to-HTML"
|
|
63
|
-
description="GTFS-to-HTML creates human-readable, user-friendly transit timetables in HTML format directly from GTFS transit data."
|
|
66
|
+
description="GTFS-to-HTML creates human-readable, user-friendly transit timetables in HTML format directly from GTFS transit data."
|
|
67
|
+
>
|
|
64
68
|
<header className={clsx('hero hero--dark', styles.heroBanner)}>
|
|
65
69
|
<div className="container">
|
|
66
70
|
<div className="row">
|
|
67
71
|
<div className="col col--4">
|
|
68
|
-
<img
|
|
72
|
+
<img
|
|
73
|
+
src="/img/gtfs-to-html-logo.svg"
|
|
74
|
+
style={{ maxWidth: '150px' }}
|
|
75
|
+
alt=""
|
|
76
|
+
/>
|
|
69
77
|
</div>
|
|
70
78
|
|
|
71
79
|
<div className="col col--8">
|
|
72
80
|
<h1 className="hero__title">{siteConfig.title}</h1>
|
|
73
81
|
<p className="hero__subtitle">{siteConfig.tagline}</p>
|
|
74
|
-
<img
|
|
82
|
+
<img
|
|
83
|
+
alt="npm"
|
|
84
|
+
src="https://img.shields.io/npm/v/gtfs-to-html?color=%2325c2a0&label=stable&style=for-the-badge"
|
|
85
|
+
className="margin-bottom--sm"
|
|
86
|
+
/>
|
|
75
87
|
<div className={styles.buttons}>
|
|
76
88
|
<Link
|
|
77
89
|
className={clsx(
|
|
78
90
|
'button button--outline button--secondary button--lg',
|
|
79
91
|
styles.heroButton
|
|
80
92
|
)}
|
|
81
|
-
to={useBaseUrl('docs/')}
|
|
93
|
+
to={useBaseUrl('docs/')}
|
|
94
|
+
>
|
|
82
95
|
Get Started
|
|
83
96
|
</Link>
|
|
84
97
|
</div>
|
|
@@ -99,19 +112,44 @@ function Home() {
|
|
|
99
112
|
</section>
|
|
100
113
|
)}
|
|
101
114
|
|
|
102
|
-
<section
|
|
115
|
+
<section
|
|
116
|
+
style={{ backgroundColor: 'hsl(0, 0%, 85%)' }}
|
|
117
|
+
className="padding--lg"
|
|
118
|
+
>
|
|
103
119
|
<div className="container">
|
|
104
120
|
<div className="row">
|
|
105
121
|
<div className="col"></div>
|
|
106
122
|
<div className="col">
|
|
107
123
|
<div className="avatar avatar--vertical margin-bottom--sm">
|
|
108
124
|
<div className="avatar__photo avatar__photo--xl">
|
|
109
|
-
<img
|
|
110
|
-
|
|
111
|
-
|
|
125
|
+
<img
|
|
126
|
+
src="https://avatars.githubusercontent.com/u/46612183?v=4"
|
|
127
|
+
alt="Brody"
|
|
128
|
+
width="200"
|
|
129
|
+
height="200"
|
|
130
|
+
style={{
|
|
131
|
+
width: '100%',
|
|
132
|
+
height: 'auto',
|
|
133
|
+
maxWidth: '100%',
|
|
134
|
+
marginBottom: '-4px',
|
|
135
|
+
}}
|
|
136
|
+
/>
|
|
137
|
+
</div>
|
|
138
|
+
<div className="avatar__intro padding-top--sm">
|
|
139
|
+
<div className="avatar__name">Brody</div>
|
|
140
|
+
<small className="avatar__subtitle">
|
|
141
|
+
<a href="https://github.com/transcollines">
|
|
142
|
+
Transcollines
|
|
143
|
+
</a>
|
|
144
|
+
</small>
|
|
112
145
|
</div>
|
|
113
146
|
</div>
|
|
114
|
-
<p className="text--center text--italic padding-horiz--md">
|
|
147
|
+
<p className="text--center text--italic padding-horiz--md">
|
|
148
|
+
It's been a huge success. Not only do the timetables look
|
|
149
|
+
fantastic, but I've had customer service agents tell me the
|
|
150
|
+
interactive timetables are a total game changer and they make
|
|
151
|
+
their jobs way easier.
|
|
152
|
+
</p>
|
|
115
153
|
</div>
|
|
116
154
|
<div className="col"></div>
|
|
117
155
|
</div>
|