@trailstash/ultra
Version:
A web based tool for making MapLibre GL maps with data from sources such as Overpass, GeoJSON, GPX, KML, TCX, etc
130 lines (118 loc) • 3.7 kB
JavaScript
import fs from "fs";
import path from "path";
import process from "process";
import { fileURLToPath, pathToFileURL } from "url";
import { build } from "esbuild";
import { Args, Command, Flags } from "@oclif/core";
import { copy } from "esbuild-plugin-copy";
import { Liquid } from "liquidjs";
import { parseSettings } from "../lib/settings.js";
const engine = new Liquid();
export const getHTMLContext = async (configFile) => {
const config = await import(
configFile.startsWith("data:") ? configFile : pathToFileURL(configFile).href
);
const {
settings: { title, icon, description, url, mastodon },
} = config.modes[config.defaultMode];
return { title, icon, description, url, mastodon };
};
export const buildConfigFromQuery = async (config, query) => {
const querySettings = parseSettings(fs.readFileSync(query));
const { defaultMode, modes } = await import(
config.startsWith("data:") ? config : pathToFileURL(config).href
);
const settings = {
...modes.map.settings,
...querySettings,
loadSettingsFromQueryParams: false,
};
const newConfig = `export const defaultMode = "map";
export const modes = {map: {settings: ${JSON.stringify(settings, null, 2)}}};`;
return `data:text/javascript;base64,${Buffer.from(newConfig).toString("base64")}`;
};
export const ultraRoot = path.dirname(
path.dirname(fileURLToPath(import.meta.url)),
);
export const buildOptions = (config, watch = false) => ({
entryPoints: [path.join(ultraRoot, "index.js")],
bundle: true,
format: "esm",
outdir: "dist",
loader: {
".md": "text",
".css": "text",
".svg": "dataurl",
".ultra": "file",
".geojson": "file",
},
alias: {
"ultra-config": config,
"node:events": "node-events", // esri-dump support
events: "node-events", // osm2geojson-ultra support (i think)
},
define: {
// esri-dump & osm2geojson-ultra support
process: "{ 'env': {}, 'browser': true, 'version': '' }",
},
plugins: [
copy({
assets: {
from: [path.join(ultraRoot, "static/**/*")],
to: [path.join(process.cwd(), "./dist")],
},
watch,
}),
],
});
export default class Build extends Command {
static flags = {
config: Flags.string({
char: "c",
description: "configuration to use",
default: path.join(process.cwd(), "/config.mjs"),
}),
};
static args = {
query: Args.file({
description: "A query to build an interactive map for",
}),
};
static description = `Build a release of Ultra`;
async run() {
let {
flags: { config },
args: { query },
} = await this.parse(Build);
if (!fs.existsSync(config)) {
console.error(
`"${config}" not found, using ${path.join(ultraRoot, "config.mjs")}`,
);
config = path.join(ultraRoot, "config.mjs");
}
if (query) {
config = await buildConfigFromQuery(config, query);
}
let html = engine.parseAndRenderSync(
fs.readFileSync(path.join(ultraRoot, "index.html")),
await getHTMLContext(config),
);
fs.mkdirSync("dist", { recursive: true });
fs.writeFileSync("dist/index.html", html);
html = engine.parseAndRenderSync(
fs.readFileSync(path.join(ultraRoot, "app.html")),
await getHTMLContext(config),
);
fs.mkdirSync("dist/app", { recursive: true });
fs.writeFileSync("dist/app/index.html", html);
fs.copyFileSync(
"node_modules/maplibre-gl/dist/maplibre-gl-worker.mjs",
"dist/maplibre-gl-worker.mjs",
);
fs.copyFileSync(
"node_modules/maplibre-gl/dist/maplibre-gl-shared.mjs",
"dist/maplibre-gl-shared.mjs",
);
await build(buildOptions(config));
}
}