2021-01-23 11:38:26 +00:00
|
|
|
import fetch from "node-fetch";
|
2023-04-07 16:39:59 +00:00
|
|
|
import * as yauzl from "yauzl";
|
2021-01-23 11:38:26 +00:00
|
|
|
import util from "util";
|
2023-04-07 16:39:59 +00:00
|
|
|
import * as svgo from "svgo";
|
2021-01-23 11:38:26 +00:00
|
|
|
import cheerio from "cheerio";
|
|
|
|
import highland from "highland";
|
|
|
|
import fs from "fs";
|
2023-04-07 16:39:59 +00:00
|
|
|
import { fileURLToPath } from 'url';
|
2021-01-23 11:38:26 +00:00
|
|
|
|
2023-04-07 16:39:59 +00:00
|
|
|
const outDir = fileURLToPath(new URL('./assets/icons/osmi', import.meta.url));
|
2021-01-23 11:38:26 +00:00
|
|
|
|
|
|
|
function streamEachPromise<T>(stream: Highland.Stream<T>, handle: (item: T) => Promise<void> | void): Promise<void> {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
stream
|
|
|
|
.flatMap((item) => highland(Promise.resolve(handle(item as T))))
|
|
|
|
.stopOnError(reject)
|
|
|
|
.done(resolve);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
async function updateIcons() {
|
|
|
|
const buffer = await fetch("https://github.com/twain47/Open-SVG-Map-Icons/archive/master.zip").then((res) => res.buffer());
|
|
|
|
const zip = (await util.promisify(yauzl.fromBuffer)(buffer))!;
|
2023-04-07 16:39:59 +00:00
|
|
|
|
|
|
|
const entryStream = highland<yauzl.Entry>((push) => {
|
2021-01-23 11:38:26 +00:00
|
|
|
zip.on("entry", (entry) => { push(null, entry); });
|
|
|
|
zip.on("error", (err) => { push(err); });
|
|
|
|
}).filter((entry) => entry.fileName.endsWith(".svg"));
|
|
|
|
|
|
|
|
await streamEachPromise(entryStream, async (entry) => {
|
|
|
|
const readStream = (await util.promisify(zip.openReadStream.bind(zip))(entry))!;
|
|
|
|
const content = await highland<Buffer>(readStream).collect().map((buffers) => Buffer.concat(buffers)).toPromise(Promise);
|
2023-04-07 16:39:59 +00:00
|
|
|
const cleanedContent = cleanIcon(content.toString());
|
2021-01-23 11:38:26 +00:00
|
|
|
const outFile = `${outDir}/${entry.fileName.split('/').slice(-2).join('_')}`;
|
|
|
|
await fs.promises.writeFile(outFile, Buffer.from(cleanedContent));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-04-07 16:39:59 +00:00
|
|
|
function cleanIcon(icon: string): string {
|
|
|
|
const optimized = svgo.optimize(icon);
|
|
|
|
|
2021-03-04 15:45:34 +00:00
|
|
|
const $ = cheerio.load(optimized.data, {
|
2021-01-23 11:38:26 +00:00
|
|
|
xmlMode: true
|
|
|
|
});
|
|
|
|
|
2021-03-04 15:45:34 +00:00
|
|
|
for (const el of $("*").toArray() as cheerio.TagElement[]) {
|
2021-01-23 11:38:26 +00:00
|
|
|
el.name = el.name.replace(/^svg:/, "");
|
|
|
|
}
|
|
|
|
|
|
|
|
$("metadata,sodipodi\\:namedview,defs,image").remove();
|
|
|
|
|
|
|
|
for (const el of $("*").toArray()) {
|
2021-03-04 15:45:34 +00:00
|
|
|
const $el = $(el);
|
2021-01-23 11:38:26 +00:00
|
|
|
|
2021-03-04 15:45:34 +00:00
|
|
|
const fill = $el.css("fill") || $el.attr("fill");
|
2021-01-23 11:38:26 +00:00
|
|
|
if(fill && fill != "none") {
|
|
|
|
if(fill != "#ffffff" && fill != "#fff") { // This is the background
|
|
|
|
$el.remove();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if($el.css("fill"))
|
|
|
|
$el.css("fill", "#000");
|
|
|
|
else
|
|
|
|
$el.attr("fill", "#000");
|
|
|
|
}
|
|
|
|
|
|
|
|
if($el.css("stroke") && $el.css("stroke") != "none")
|
|
|
|
$el.css("stroke", "#000");
|
|
|
|
else if($el.attr("stroke") && $el.attr("stroke") != "none")
|
|
|
|
$el.attr("stroke", "#000");
|
|
|
|
}
|
|
|
|
|
|
|
|
return $(":root").html()!.replace(/(>|^)\s+(<|$)/g, "$1$2");
|
|
|
|
}
|
|
|
|
|
|
|
|
updateIcons().then(() => {
|
|
|
|
console.log('Success!');
|
|
|
|
}).catch((err) => {
|
|
|
|
console.error('Fatal error', err);
|
|
|
|
});
|