Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modernize setup #130

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions .eslintrc.cjs

This file was deleted.

38 changes: 38 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": ["docs", "dist"]
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noAssignInExpressions": "off",
"noImplicitAnyLet": "off",
"noExplicitAny": "off"
},
"style": {
"noParameterAssign": "off"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
}
}
296 changes: 148 additions & 148 deletions lib/gpx.ts
Original file line number Diff line number Diff line change
@@ -1,159 +1,159 @@
import type {
FeatureCollection,
Feature,
Point,
MultiLineString,
LineString,
Position,
Feature,
FeatureCollection,
LineString,
MultiLineString,
Point,
Position,
} from "geojson";
import { getLineStyle } from "./gpx/line";
import { coordPair } from "./gpx/coord_pair";
import { getLineStyle } from "./gpx/line";
import { extractProperties } from "./gpx/properties";
import { P, $, get1, getMulti } from "./shared";
import { $, type P, get1, getMulti } from "./shared";

/**
* Extract points from a trkseg or rte element.
*/
function getPoints(node: Element, pointname: "trkpt" | "rtept") {
const pts = $(node, pointname);
const line: Position[] = [];
const times = [];
const extendedValues: P = {};

for (let i = 0; i < pts.length; i++) {
const c = coordPair(pts[i]);
if (!c) {
continue;
}
line.push(c.coordinates);
if (c.time) times.push(c.time);
for (const [name, val] of c.extendedValues) {
const plural =
name === "heart" ? name : name.replace("gpxtpx:", "") + "s";
if (!extendedValues[plural]) {
extendedValues[plural] = Array(pts.length).fill(null);
}
extendedValues[plural][i] = val;
}
}

if (line.length < 2) return; // Invalid line in GeoJSON

return {
line: line,
times: times,
extendedValues: extendedValues,
};
const pts = $(node, pointname);
const line: Position[] = [];
const times = [];
const extendedValues: P = {};

for (let i = 0; i < pts.length; i++) {
const c = coordPair(pts[i]);
if (!c) {
continue;
}
line.push(c.coordinates);
if (c.time) times.push(c.time);
for (const [name, val] of c.extendedValues) {
const plural =
name === "heart" ? name : `${name.replace("gpxtpx:", "")}s`;
if (!extendedValues[plural]) {
extendedValues[plural] = Array(pts.length).fill(null);
}
extendedValues[plural][i] = val;
}
}

if (line.length < 2) return; // Invalid line in GeoJSON

return {
line: line,
times: times,
extendedValues: extendedValues,
};
}

/**
* Extract a LineString geometry from a rte
* element.
*/
function getRoute(node: Element): Feature<LineString> | undefined {
const line = getPoints(node, "rtept");
if (!line) return;
return {
type: "Feature",
properties: Object.assign(
{ _gpxType: "rte" },
extractProperties(node),
getLineStyle(get1(node, "extensions"))
),
geometry: {
type: "LineString",
coordinates: line.line,
},
};
const line = getPoints(node, "rtept");
if (!line) return;
return {
type: "Feature",
properties: Object.assign(
{ _gpxType: "rte" },
extractProperties(node),
getLineStyle(get1(node, "extensions")),
),
geometry: {
type: "LineString",
coordinates: line.line,
},
};
}

function getTrack(node: Element): Feature<LineString | MultiLineString> | null {
const segments = $(node, "trkseg");
const track = [];
const times = [];
const extractedLines = [];

for (const segment of segments) {
const line = getPoints(segment, "trkpt");
if (line) {
extractedLines.push(line);
if (line.times && line.times.length) times.push(line.times);
}
}

if (extractedLines.length === 0) return null;

const multi = extractedLines.length > 1;

const properties: Feature["properties"] = Object.assign(
{ _gpxType: "trk" },
extractProperties(node),
getLineStyle(get1(node, "extensions")),
times.length
? {
coordinateProperties: {
times: multi ? times : times[0],
},
}
: {}
);

for (const line of extractedLines) {
track.push(line.line);
if (!properties.coordinateProperties) {
properties.coordinateProperties = {};
}
const props = properties.coordinateProperties;
const entries = Object.entries(line.extendedValues);
for (let i = 0; i < entries.length; i++) {
const [name, val] = entries[i];
if (multi) {
if (!props[name]) {
props[name] = extractedLines.map((line) =>
new Array(line.line.length).fill(null)
);
}
props[name][i] = val;
} else {
props[name] = val;
}
}
}

return {
type: "Feature",
properties: properties,
geometry: multi
? {
type: "MultiLineString",
coordinates: track,
}
: {
type: "LineString",
coordinates: track[0],
},
};
const segments = $(node, "trkseg");
const track = [];
const times = [];
const extractedLines = [];

for (const segment of segments) {
const line = getPoints(segment, "trkpt");
if (line) {
extractedLines.push(line);
if (line.times?.length) times.push(line.times);
}
}

if (extractedLines.length === 0) return null;

const multi = extractedLines.length > 1;

const properties: Feature["properties"] = Object.assign(
{ _gpxType: "trk" },
extractProperties(node),
getLineStyle(get1(node, "extensions")),
times.length
? {
coordinateProperties: {
times: multi ? times : times[0],
},
}
: {},
);

for (const line of extractedLines) {
track.push(line.line);
if (!properties.coordinateProperties) {
properties.coordinateProperties = {};
}
const props = properties.coordinateProperties;
const entries = Object.entries(line.extendedValues);
for (let i = 0; i < entries.length; i++) {
const [name, val] = entries[i];
if (multi) {
if (!props[name]) {
props[name] = extractedLines.map((line) =>
new Array(line.line.length).fill(null),
);
}
props[name][i] = val;
} else {
props[name] = val;
}
}
}

return {
type: "Feature",
properties: properties,
geometry: multi
? {
type: "MultiLineString",
coordinates: track,
}
: {
type: "LineString",
coordinates: track[0],
},
};
}

/**
* Extract a point, if possible, from a given node,
* which is usually a wpt or trkpt
*/
function getPoint(node: Element): Feature<Point> | null {
const properties: Feature["properties"] = Object.assign(
extractProperties(node),
getMulti(node, ["sym"])
);
const pair = coordPair(node);
if (!pair) return null;
return {
type: "Feature",
properties,
geometry: {
type: "Point",
coordinates: pair.coordinates,
},
};
const properties: Feature["properties"] = Object.assign(
extractProperties(node),
getMulti(node, ["sym"]),
);
const pair = coordPair(node);
if (!pair) return null;
return {
type: "Feature",
properties,
geometry: {
type: "Point",
coordinates: pair.coordinates,
},
};
}

/**
Expand All @@ -162,20 +162,20 @@ function getPoint(node: Element): Feature<Point> | null {
* that yields output feature by feature.
*/
export function* gpxGen(node: Document): Generator<Feature> {
for (const track of $(node, "trk")) {
const feature = getTrack(track);
if (feature) yield feature;
}

for (const route of $(node, "rte")) {
const feature = getRoute(route);
if (feature) yield feature;
}

for (const waypoint of $(node, "wpt")) {
const point = getPoint(waypoint);
if (point) yield point;
}
for (const track of $(node, "trk")) {
const feature = getTrack(track);
if (feature) yield feature;
}

for (const route of $(node, "rte")) {
const feature = getRoute(route);
if (feature) yield feature;
}

for (const waypoint of $(node, "wpt")) {
const point = getPoint(waypoint);
if (point) yield point;
}
}

/**
Expand All @@ -190,8 +190,8 @@ export function* gpxGen(node: Document): Generator<Feature> {
* the feature was encoded as a route (`rte`) or track (`trk`) in the GPX document.
*/
export function gpx(node: Document): FeatureCollection {
return {
type: "FeatureCollection",
features: Array.from(gpxGen(node)),
};
return {
type: "FeatureCollection",
features: Array.from(gpxGen(node)),
};
}
Loading
Loading