Lerry William S.

GPX Tracks and Sortable Data Tables — More GIS Goodies for Jekyll

April 05, 2016


After the map tag from yesterday, here are two more plugins I built to make this blog feel like a proper GIS tool.

One is for GPX tracks — drop a file from your GPS, get a map with the full track and an elevation profile. The other is for data tables — take a CSV or GeoJSON and get a sortable table without touching JavaScript.

Both work the same way: one Liquid tag, no scripts, no includes.

GPX Track with Elevation Profile

Here is a GPX track from a hike at Bukit Lima in Sibu — about 4.8km with ~280m of gain:

30m170m310m 1.9 km
Distance
1.85 km
Gain
+280 m
Loss
−280 m
Elevation
25–305 m
Bukit Lima Summit Trail, Sibu — a 4.8km loop with ~280m gain

That is just:

{% gpx_track file="/assets/datasets/demo_hike.gpx" caption="Bukit Lima Summit Trail..." %}

The map, the SVG elevation profile, and the stats (distance, gain, loss, elevation range) are all generated at build time. The elevation chart is an inline SVG — no JavaScript charting library needed.

The start and end points get circle markers so you can see which direction the track runs. The map auto-fits to the track bounds.

Sortable Data Table from CSV

If you work with field data, you know how tedious it is to copy-paste attribute tables into markdown. This tag reads a CSV file and gives you a sortable table:

Sarawak forest survey sites, 2024 field season
site_idnameland_coverelevation_mdate_surveyedspecies_countnotes
SG-01Bako National ParkMangrove122024-03-1547High proboscis monkey activity
SG-02Gunung GadingDipterocarp4502024-04-0282Rafflesia spotted at km 3.2
SG-03Kubah National ParkKerangas1802024-04-1863Orangutan nest count: 14
SG-04Santubong PeninsulaMixed dipterocarp3102024-05-1091Good canopy access via existing trails
SG-05Bako TerminalBeach forest52024-05-2228Erosion monitoring site
SG-06Lambir HillsLowland dipterocarp2652024-06-05124Long-term 52-ha plot
SG-07Similajau CoastBeach82024-06-2019Sea turtle landing site
SG-08Usun Apau PlateauMontane9802024-07-0156Accessible by logging road only
SG-09Mulu Summit trailLimestone forest12002024-07-1244Nepenthes rajah zone
SG-10Maludam PeninsulaPeat swamp32024-07-2535Rare stork colony

Click any column header to sort. Click again to reverse. Numeric columns like elevation and species count sort by value instead of alphabetically.

You can also filter which columns to show and pick a default sort:

Filtered to four columns, pre-sorted by species count (most diverse first)
site_idnameelevation_mspecies_count
SG-07Similajau Coast819
SG-05Bako Terminal528
SG-10Maludam Peninsula335
SG-09Mulu Summit trail120044
SG-01Bako National Park1247
SG-08Usun Apau Plateau98056
SG-03Kubah National Park18063
SG-02Gunung Gading45082
SG-04Santubong Peninsula31091
SG-06Lambir Hills265124

From GeoJSON Too

The same tag works with GeoJSON — the feature properties become the columns:

Borneo Kolomee Trail — waypoints from GeoJSON
overvieworderheadlinetextmediacaptioncredit
10The Great Sarawak Kolo Mee Trail<p>A (completely fictional) culinary expedition across Borneo in search of the perfect bowl of <em>kolo mee</em>. Five towns, five legends, zero calories counted. Buckle up — the noodles are calling.</p>https://en.wikipedia.org/wiki/Kolo_meeWarning: contains dramatised noodle facts.Ministry of Imaginary Cuisine
1Kuching — The Origin Bowl<p>Legend says the very first bowl of kolo mee was tossed here at 3:47 a.m. by a cat who refused to sleep. Locals still leave out a saucer of char siu in tribute. The city's stray cats are rumoured to review hawker stalls with a strict five-whisker rating system.</p>https://en.wikipedia.org/wiki/KuchingCat City. Coincidence? The felines think not.Whisker TimesKuching8http://maps.gstatic.com/intl/en_us/mapfiles/ms/micons/blue-pushpin.png11908-01-01
2Mukah — The Sago Detour<p>Our expedition briefly abandons noodles for <em>umai</em> and sago pearls. Scientists (imaginary ones) estimate that Mukah produces enough sago each year to build a bouncy castle the size of a small island. No one has tried. Yet.</p>https://en.wikipedia.org/wiki/MukahSago: chewy, wobbly, structurally underrated.Institute of Bouncy StudiesMukah8http://maps.gstatic.com/intl/en_us/mapfiles/ms/micons/blue-pushpin.png1
3Sibu — The Kampua Rivalry<p>Here the trail turns tense. Sibu insists its <em>kampua mee</em> is the true champion, not kolo mee. Diplomatic noodle summits are held nightly at the pasar. So far, the only treaty signed is that everyone orders a second bowl.</p>https://en.wikipedia.org/wiki/SibuNeutral ground: the shared chilli sauce bottle.Council of Noodle AffairsSibu8http://maps.gstatic.com/intl/en_us/mapfiles/ms/micons/blue-pushpin.png1
4Bintulu — Refuel at the Energy Town<p>Powered by natural gas and, apparently, unlimited belacan, Bintulu is where our travellers refuel — both the van and themselves. Local myth claims a bowl of noodles here gives you enough energy to walk to Miri. It does not. We checked.</p>https://en.wikipedia.org/wiki/BintuluFuel gauge: full. Stomach gauge: fuller.Department of Optimistic DistancesBintulu8http://maps.gstatic.com/intl/en_us/mapfiles/ms/micons/blue-pushpin.png1
5Miri — The Final Bowl<p>The trail ends where it began, in oil-town Miri, with a sunset, a seahorse mascot, and the biggest bowl of kolo mee anyone dared to order. Verdict after 1,200 km: they are all the best. This is the only scientifically imaginary conclusion possible.</p>https://en.wikipedia.org/wiki/Miri,_MalaysiaThe Seahorse City approves this expedition.Bureau of Happy EndingsMiri8http://maps.gstatic.com/intl/en_us/mapfiles/ms/micons/blue-pushpin.png1

The Whole Toolkit

At this point the blog has six custom Liquid tags covering pretty much everything I need for GIS writing:

Tag Takes Gives you
{% map %} lat/lon Leaflet marker map
{% storymap %} GeoJSON/CSV/JSON KnightLab StoryMapJS
{% lungkui %} GeoJSON/JSON lungkui.js MapLibre scrollytelling
{% gpx_track %} GPX file Leaflet track + SVG profile + stats
{% datatable %} GeoJSON/CSV Sortable HTML table

No webpack, no npm, no node_modules. Everything that can be computed at build time — GeoJSON transforms, CSV parsing, SVG generation, GPX stats, Haversine distances — is. The only runtime dependencies are Leaflet and MapLibre from CDN, and those are loaded once per page.

For a solo GIS blog, this is about as good as it gets.