@mapsight/traffic-style 5.0.1 → 5.0.3
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/meta.json +1 -1
- package/package.json +10 -10
- package/scripts/create-meta-json.d.ts +2 -0
- package/scripts/create-meta-json.d.ts.map +1 -0
- package/scripts/create-meta-json.js +79 -0
- package/scripts/create-meta-json.js.map +1 -0
- package/scripts/create-overview-md.d.ts +2 -0
- package/scripts/create-overview-md.d.ts.map +1 -0
- package/scripts/create-overview-md.js +72 -0
- package/scripts/create-overview-md.js.map +1 -0
- package/scripts/lib/meta.d.ts +32 -0
- package/scripts/lib/meta.d.ts.map +1 -0
- package/scripts/lib/meta.js +23 -0
- package/scripts/lib/meta.js.map +1 -0
- package/scripts/optimize-icons.d.ts +47 -0
- package/scripts/optimize-icons.d.ts.map +1 -0
- package/scripts/optimize-icons.js +477 -0
- package/scripts/optimize-icons.js.map +1 -0
- package/scripts/optimize-icons.test.d.ts +2 -0
- package/scripts/optimize-icons.test.d.ts.map +1 -0
- package/scripts/optimize-icons.test.js +179 -0
- package/scripts/optimize-icons.test.js.map +1 -0
- package/scripts/traffic-icon-sprite.d.ts +3 -0
- package/scripts/traffic-icon-sprite.d.ts.map +1 -0
- package/scripts/traffic-icon-sprite.js +214 -0
- package/scripts/traffic-icon-sprite.js.map +1 -0
- package/scripts/create-meta-json.ts +0 -141
- package/scripts/create-overview-md.ts +0 -110
- package/scripts/lib/meta.ts +0 -40
- package/scripts/optimize-icons.test.ts +0 -234
- package/scripts/optimize-icons.ts +0 -686
- package/scripts/traffic-icon-sprite.ts +0 -292
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
7
|
+
import { main } from "./optimize-icons";
|
|
8
|
+
describe("optimize-icons.ts", () => {
|
|
9
|
+
let tmpDir;
|
|
10
|
+
let srcDir;
|
|
11
|
+
let destDir;
|
|
12
|
+
beforeEach(async () => {
|
|
13
|
+
tmpDir = path.join(os.tmpdir(), `optimize-icons-test-${Math.random().toString(36).slice(2)}`);
|
|
14
|
+
srcDir = path.join(tmpDir, "src");
|
|
15
|
+
destDir = path.join(tmpDir, "dest");
|
|
16
|
+
await mkdir(srcDir, { recursive: true });
|
|
17
|
+
await mkdir(destDir, { recursive: true });
|
|
18
|
+
// Mock process.exitCode to avoid affecting the test runner
|
|
19
|
+
vi.stubGlobal("process", {
|
|
20
|
+
...process,
|
|
21
|
+
exitCode: 0,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
afterEach(async () => {
|
|
25
|
+
if (srcDir && destDir) {
|
|
26
|
+
try {
|
|
27
|
+
const manifestPath = getManifestPath(srcDir, destDir);
|
|
28
|
+
await unlink(manifestPath);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// ignore if manifest doesn't exist
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (tmpDir) {
|
|
35
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
36
|
+
}
|
|
37
|
+
vi.unstubAllGlobals();
|
|
38
|
+
});
|
|
39
|
+
async function runScript(args) {
|
|
40
|
+
const argv = ["node", "optimize-icons.ts"];
|
|
41
|
+
for (const [key, value] of Object.entries(args)) {
|
|
42
|
+
if (typeof value === "boolean") {
|
|
43
|
+
if (value)
|
|
44
|
+
argv.push(`--${key}`);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
argv.push(`--${key}`, String(value));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
vi.stubGlobal("process", {
|
|
51
|
+
...process,
|
|
52
|
+
argv,
|
|
53
|
+
});
|
|
54
|
+
await main();
|
|
55
|
+
}
|
|
56
|
+
function getManifestPath(src, dest) {
|
|
57
|
+
const scriptPath = fileURLToPath(import.meta.url);
|
|
58
|
+
const packageRoot = path.resolve(path.dirname(scriptPath), "..");
|
|
59
|
+
const hash = createHash("sha256")
|
|
60
|
+
.update(`${path.resolve(src)}:${path.resolve(dest)}`)
|
|
61
|
+
.digest("hex")
|
|
62
|
+
.slice(0, 16);
|
|
63
|
+
return path.join(packageRoot, "tmp", `.optimize-icons-manifest-${hash}.json`);
|
|
64
|
+
}
|
|
65
|
+
it("should process an SVG file and produce SVG, PNG, and WebP outputs", async () => {
|
|
66
|
+
const svgContent = `<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="red"/></svg>`;
|
|
67
|
+
await writeFile(path.join(srcDir, "test.svg"), svgContent);
|
|
68
|
+
await runScript({
|
|
69
|
+
src: srcDir,
|
|
70
|
+
dest: destDir,
|
|
71
|
+
});
|
|
72
|
+
expect(await stat(path.join(destDir, "test.svg"))).toBeDefined();
|
|
73
|
+
expect(await stat(path.join(destDir, "test.png"))).toBeDefined();
|
|
74
|
+
expect(await stat(path.join(destDir, "test.webp"))).toBeDefined();
|
|
75
|
+
const manifestPath = getManifestPath(srcDir, destDir);
|
|
76
|
+
const manifestRaw = await readFile(manifestPath, "utf8");
|
|
77
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
78
|
+
const outputs = JSON.parse(manifestRaw).files["test.svg"].outputs;
|
|
79
|
+
expect(outputs).toBeDefined();
|
|
80
|
+
expect(outputs).toContain("test.svg");
|
|
81
|
+
expect(outputs).toContain("test.png");
|
|
82
|
+
expect(outputs).toContain("test.webp");
|
|
83
|
+
});
|
|
84
|
+
it("should process a PNG file and produce PNG and WebP outputs", async () => {
|
|
85
|
+
// Create a tiny valid PNG using sharp if possible, or just a placeholder if we skip actual image check
|
|
86
|
+
// Since we have sharp available in the environment, let's use it if we can, but simpler is to use a minimal PNG buffer.
|
|
87
|
+
const sharp = (await import("sharp")).default;
|
|
88
|
+
const pngBuffer = await sharp({
|
|
89
|
+
create: {
|
|
90
|
+
width: 10,
|
|
91
|
+
height: 10,
|
|
92
|
+
channels: 4,
|
|
93
|
+
background: { r: 255, g: 0, b: 0, alpha: 0.5 },
|
|
94
|
+
},
|
|
95
|
+
})
|
|
96
|
+
.png()
|
|
97
|
+
.toBuffer();
|
|
98
|
+
await writeFile(path.join(srcDir, "test.png"), pngBuffer);
|
|
99
|
+
await runScript({
|
|
100
|
+
src: srcDir,
|
|
101
|
+
dest: destDir,
|
|
102
|
+
});
|
|
103
|
+
expect(await stat(path.join(destDir, "test.png"))).toBeDefined();
|
|
104
|
+
expect(await stat(path.join(destDir, "test.webp"))).toBeDefined();
|
|
105
|
+
await expect(async () => await stat(path.join(destDir, "test.svg"))).rejects.toThrow();
|
|
106
|
+
});
|
|
107
|
+
it("should scale images when --scale is provided", async () => {
|
|
108
|
+
const svgContent = `<svg width="10" height="10" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="red"/></svg>`;
|
|
109
|
+
await writeFile(path.join(srcDir, "scale-test.svg"), svgContent);
|
|
110
|
+
await runScript({
|
|
111
|
+
src: srcDir,
|
|
112
|
+
dest: destDir,
|
|
113
|
+
scale: "2",
|
|
114
|
+
});
|
|
115
|
+
const sharp = (await import("sharp")).default;
|
|
116
|
+
const metadata = await sharp(path.join(destDir, "scale-test.png")).metadata();
|
|
117
|
+
expect(metadata.width).toBe(20);
|
|
118
|
+
expect(metadata.height).toBe(20);
|
|
119
|
+
});
|
|
120
|
+
it("should skip processing if files haven't changed", async () => {
|
|
121
|
+
const svgContent = `<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg"><rect width="10" height="10" fill="red"/></svg>`;
|
|
122
|
+
const testFile = path.join(srcDir, "skip-test.svg");
|
|
123
|
+
await writeFile(testFile, svgContent);
|
|
124
|
+
// First run
|
|
125
|
+
await runScript({
|
|
126
|
+
src: srcDir,
|
|
127
|
+
dest: destDir,
|
|
128
|
+
verbose: true,
|
|
129
|
+
});
|
|
130
|
+
const destFile = path.join(destDir, "skip-test.png");
|
|
131
|
+
const firstStat = await stat(destFile);
|
|
132
|
+
// Second run
|
|
133
|
+
await runScript({
|
|
134
|
+
src: srcDir,
|
|
135
|
+
dest: destDir,
|
|
136
|
+
verbose: true,
|
|
137
|
+
});
|
|
138
|
+
const secondStat = await stat(destFile);
|
|
139
|
+
expect(secondStat.mtimeMs).toBe(firstStat.mtimeMs);
|
|
140
|
+
});
|
|
141
|
+
it("should only produce specified targets when --target is provided", async () => {
|
|
142
|
+
const svgContent = `<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="red"/></svg>`;
|
|
143
|
+
await writeFile(path.join(srcDir, "target-test.svg"), svgContent);
|
|
144
|
+
await runScript({
|
|
145
|
+
src: srcDir,
|
|
146
|
+
dest: destDir,
|
|
147
|
+
target: "png",
|
|
148
|
+
});
|
|
149
|
+
expect(await stat(path.join(destDir, "target-test.png"))).toBeDefined();
|
|
150
|
+
await expect(async () => await stat(path.join(destDir, "target-test.svg"))).rejects.toThrow();
|
|
151
|
+
await expect(async () => await stat(path.join(destDir, "target-test.webp"))).rejects.toThrow();
|
|
152
|
+
const manifestPath = getManifestPath(srcDir, destDir);
|
|
153
|
+
const manifestRaw = await readFile(manifestPath, "utf8");
|
|
154
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
155
|
+
const outputs = JSON.parse(manifestRaw).files["target-test.svg"]
|
|
156
|
+
.outputs;
|
|
157
|
+
expect(outputs).toEqual(["target-test.png"]);
|
|
158
|
+
});
|
|
159
|
+
it("should produce multiple specified targets", async () => {
|
|
160
|
+
const svgContent = `<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="red"/></svg>`;
|
|
161
|
+
await writeFile(path.join(srcDir, "multi-target.svg"), svgContent);
|
|
162
|
+
await runScript({
|
|
163
|
+
src: srcDir,
|
|
164
|
+
dest: destDir,
|
|
165
|
+
target: "svg,webp",
|
|
166
|
+
});
|
|
167
|
+
expect(await stat(path.join(destDir, "multi-target.svg"))).toBeDefined();
|
|
168
|
+
expect(await stat(path.join(destDir, "multi-target.webp"))).toBeDefined();
|
|
169
|
+
await expect(async () => await stat(path.join(destDir, "multi-target.png"))).rejects.toThrow();
|
|
170
|
+
});
|
|
171
|
+
it("should fail if an invalid target is provided", async () => {
|
|
172
|
+
await expect(runScript({
|
|
173
|
+
src: srcDir,
|
|
174
|
+
dest: destDir,
|
|
175
|
+
target: "invalid",
|
|
176
|
+
})).rejects.toThrow("Invalid target format: invalid");
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
//# sourceMappingURL=optimize-icons.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optimize-icons.test.js","sourceRoot":"","sources":["../../scripts/optimize-icons.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traffic-icon-sprite.d.ts","sourceRoot":"","sources":["../../scripts/traffic-icon-sprite.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as fs from "node:fs/promises";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { parseArgs } from "node:util";
|
|
5
|
+
import { watch } from "chokidar";
|
|
6
|
+
import * as fse from "fs-extra";
|
|
7
|
+
import sharp from "sharp";
|
|
8
|
+
import { DistMetaDataSchema, } from "./lib/meta.js";
|
|
9
|
+
const calcGlobs = (groups, metaData, variants, fileType) => {
|
|
10
|
+
const globs = [];
|
|
11
|
+
metaData.icons.forEach((iconMeta) => groups.forEach((group) => {
|
|
12
|
+
if (iconMeta.groups && iconMeta.groups.includes(group)) {
|
|
13
|
+
variants
|
|
14
|
+
.map((variant) => `**/${iconMeta.id}-${variant}.${fileType}`)
|
|
15
|
+
.forEach((glob) => {
|
|
16
|
+
globs.push(glob);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}));
|
|
20
|
+
return globs;
|
|
21
|
+
};
|
|
22
|
+
async function buildIcons(opts) {
|
|
23
|
+
const { srcDir, spriteName, metaPath, outputScss, outputImg, groups = ["default"], variants = ["default", "small", "xsmall"], filetype = "png", margin = 4, overridesPath, } = opts;
|
|
24
|
+
const absMetaPath = path.resolve(metaPath);
|
|
25
|
+
if (!(await fse.pathExists(absMetaPath))) {
|
|
26
|
+
throw new Error(`Missing metadata at ${absMetaPath}`);
|
|
27
|
+
}
|
|
28
|
+
const metaDataStr = await fs.readFile(absMetaPath, { encoding: "utf-8" });
|
|
29
|
+
const metaData = DistMetaDataSchema.parse(JSON.parse(metaDataStr));
|
|
30
|
+
let globs = calcGlobs(groups, metaData, variants, filetype);
|
|
31
|
+
if (groups.length === 0) {
|
|
32
|
+
globs = variants.map((variant) => `**/*-${variant}.${filetype}`);
|
|
33
|
+
}
|
|
34
|
+
const srcFiles = [];
|
|
35
|
+
for (const pattern of globs) {
|
|
36
|
+
for await (const entry of fs.glob(pattern, {
|
|
37
|
+
cwd: srcDir,
|
|
38
|
+
})) {
|
|
39
|
+
srcFiles.push(path.resolve(srcDir, entry));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
console.log(`Found ${srcFiles.length} icon files matching globs`);
|
|
43
|
+
const tmpDir = path.resolve("./tmp", spriteName);
|
|
44
|
+
await fse.ensureDir(tmpDir);
|
|
45
|
+
let copiedCount = 0;
|
|
46
|
+
for (const srcFile of srcFiles) {
|
|
47
|
+
const relPath = path.relative(srcDir, srcFile);
|
|
48
|
+
const destFile = path.join(tmpDir, relPath);
|
|
49
|
+
await fse.ensureDir(path.dirname(destFile));
|
|
50
|
+
const doCopy = async () => {
|
|
51
|
+
await fse.copy(srcFile, destFile);
|
|
52
|
+
copiedCount++;
|
|
53
|
+
};
|
|
54
|
+
if (await fse.pathExists(destFile)) {
|
|
55
|
+
const srcStat = await fs.stat(srcFile);
|
|
56
|
+
const destStat = await fs.stat(destFile);
|
|
57
|
+
if (destStat.mtime > srcStat.mtime) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
await doCopy();
|
|
62
|
+
}
|
|
63
|
+
console.log(`Copied ${copiedCount} icons to ${tmpDir}`);
|
|
64
|
+
if (overridesPath) {
|
|
65
|
+
const absOverrides = path.resolve(overridesPath);
|
|
66
|
+
const overrideFiles = [];
|
|
67
|
+
for (const pattern of globs) {
|
|
68
|
+
for await (const entry of fs.glob(pattern, {
|
|
69
|
+
cwd: absOverrides,
|
|
70
|
+
})) {
|
|
71
|
+
overrideFiles.push(path.resolve(absOverrides, entry));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
for (const ovFile of overrideFiles) {
|
|
75
|
+
const relPath = path.relative(absOverrides, ovFile);
|
|
76
|
+
const destFile = path.join(tmpDir, relPath);
|
|
77
|
+
await fse.ensureDir(path.dirname(destFile));
|
|
78
|
+
await fse.copy(ovFile, destFile);
|
|
79
|
+
}
|
|
80
|
+
console.log(`Copied overrides from ${overridesPath}`);
|
|
81
|
+
}
|
|
82
|
+
const tmpFiles = [];
|
|
83
|
+
for await (const entry of fs.glob("**/*", {
|
|
84
|
+
cwd: tmpDir,
|
|
85
|
+
})) {
|
|
86
|
+
tmpFiles.push(entry);
|
|
87
|
+
}
|
|
88
|
+
const tiles = [];
|
|
89
|
+
for (const rel of tmpFiles) {
|
|
90
|
+
const fullPath = path.join(tmpDir, rel);
|
|
91
|
+
const stat = await fs.stat(fullPath);
|
|
92
|
+
if (!stat.isFile())
|
|
93
|
+
continue;
|
|
94
|
+
const buffer = await fs.readFile(fullPath);
|
|
95
|
+
const metadata = await sharp(buffer).metadata();
|
|
96
|
+
if (!metadata.width || !metadata.height)
|
|
97
|
+
continue;
|
|
98
|
+
const name = path.parse(rel).name;
|
|
99
|
+
tiles.push({
|
|
100
|
+
name,
|
|
101
|
+
info: { width: metadata.width, height: metadata.height },
|
|
102
|
+
buffer,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
const marginNum = Number(margin);
|
|
106
|
+
let items = tiles.map((tile) => ({
|
|
107
|
+
width: tile.info.width + 2 * marginNum,
|
|
108
|
+
height: tile.info.height + 2 * marginNum,
|
|
109
|
+
meta: tile,
|
|
110
|
+
x: 0,
|
|
111
|
+
y: 0,
|
|
112
|
+
}));
|
|
113
|
+
items = items.sort((a, b) => a.height - b.height);
|
|
114
|
+
let currentY = 0;
|
|
115
|
+
for (const item of items) {
|
|
116
|
+
item.x = 0;
|
|
117
|
+
item.y = currentY;
|
|
118
|
+
currentY += item.height;
|
|
119
|
+
}
|
|
120
|
+
const layoutWidth = items.length > 0 ? Math.max(...items.map((i) => i.width)) : 0;
|
|
121
|
+
const layoutHeight = currentY;
|
|
122
|
+
// SCSS
|
|
123
|
+
const absScssDir = path.resolve(outputScss);
|
|
124
|
+
await fse.ensureDir(absScssDir);
|
|
125
|
+
const scssFile = path.join(absScssDir, `${spriteName}.scss`);
|
|
126
|
+
let scssContent = `$${spriteName}: (\n`;
|
|
127
|
+
for (const item of items) {
|
|
128
|
+
scssContent += ` "${item.meta.name}": (
|
|
129
|
+
x: ${item.x},
|
|
130
|
+
y: ${item.y},
|
|
131
|
+
width: ${item.width},
|
|
132
|
+
height: ${item.height},
|
|
133
|
+
),
|
|
134
|
+
`;
|
|
135
|
+
}
|
|
136
|
+
scssContent += `);\n`;
|
|
137
|
+
await fs.writeFile(scssFile, scssContent, "utf-8");
|
|
138
|
+
console.log(`Generated SCSS: ${scssFile}`);
|
|
139
|
+
// PNG
|
|
140
|
+
const absImgDir = path.resolve(outputImg);
|
|
141
|
+
await fse.ensureDir(absImgDir);
|
|
142
|
+
const pngFile = path.join(absImgDir, `${spriteName}.png`);
|
|
143
|
+
const spriteSharp = sharp({
|
|
144
|
+
create: {
|
|
145
|
+
width: layoutWidth,
|
|
146
|
+
height: layoutHeight,
|
|
147
|
+
channels: 4,
|
|
148
|
+
background: { r: 0, g: 0, b: 0, alpha: 0 },
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
const composites = items.map((item) => ({
|
|
152
|
+
input: item.meta.buffer,
|
|
153
|
+
left: item.x,
|
|
154
|
+
top: item.y,
|
|
155
|
+
width: item.width,
|
|
156
|
+
height: item.height,
|
|
157
|
+
}));
|
|
158
|
+
await spriteSharp.composite(composites).png({ effort: 10 }).toFile(pngFile);
|
|
159
|
+
console.log(`Generated PNG: ${pngFile} (${layoutWidth}x${layoutHeight})`);
|
|
160
|
+
}
|
|
161
|
+
const debounceAsync = (fn, delay) => {
|
|
162
|
+
let timer;
|
|
163
|
+
return () => {
|
|
164
|
+
clearTimeout(timer);
|
|
165
|
+
timer = setTimeout(() => {
|
|
166
|
+
fn().catch(console.error);
|
|
167
|
+
}, delay);
|
|
168
|
+
};
|
|
169
|
+
};
|
|
170
|
+
const { values: options, positionals } = parseArgs({
|
|
171
|
+
options: {
|
|
172
|
+
"sprite-name": { type: "string", short: "n" },
|
|
173
|
+
"meta-path": { type: "string", short: "m" },
|
|
174
|
+
"output-scss": { type: "string", short: "s" },
|
|
175
|
+
"output-img": { type: "string", short: "i" },
|
|
176
|
+
groups: { type: "string", short: "g" },
|
|
177
|
+
variants: { type: "string", short: "v" },
|
|
178
|
+
filetype: { type: "string", short: "f" },
|
|
179
|
+
margin: { type: "string" },
|
|
180
|
+
overrides: { type: "string", short: "o" },
|
|
181
|
+
watch: { type: "boolean", short: "w" },
|
|
182
|
+
},
|
|
183
|
+
allowPositionals: true,
|
|
184
|
+
});
|
|
185
|
+
const srcDir = positionals[0] ??
|
|
186
|
+
"node_modules/@mapsight/traffic-style/img/mapsight-icons-2x/";
|
|
187
|
+
const absOpts = {
|
|
188
|
+
srcDir: path.resolve(srcDir),
|
|
189
|
+
spriteName: options["sprite-name"] ?? "mapsight-traffic-style-icon-sprite-2x",
|
|
190
|
+
metaPath: options["meta-path"] ??
|
|
191
|
+
"node_modules/@mapsight/traffic-style/meta.json",
|
|
192
|
+
outputScss: options["output-scss"] ?? "dist/",
|
|
193
|
+
outputImg: options["output-img"] ?? "dist/img/",
|
|
194
|
+
groups: options.groups?.split(",") ?? ["default"],
|
|
195
|
+
variants: options.variants?.split(",") ?? [
|
|
196
|
+
"default",
|
|
197
|
+
"small",
|
|
198
|
+
"xsmall",
|
|
199
|
+
],
|
|
200
|
+
filetype: options.filetype ?? "png",
|
|
201
|
+
margin: parseInt(options.margin ?? "4", 10),
|
|
202
|
+
overridesPath: options.overrides,
|
|
203
|
+
};
|
|
204
|
+
const runBuild = () => buildIcons(absOpts);
|
|
205
|
+
await runBuild();
|
|
206
|
+
if (options.watch) {
|
|
207
|
+
const debouncedBuild = debounceAsync(runBuild, 300);
|
|
208
|
+
const watchPaths = [absOpts.srcDir, absOpts.metaPath];
|
|
209
|
+
if (absOpts.overridesPath)
|
|
210
|
+
watchPaths.push(path.resolve(absOpts.overridesPath));
|
|
211
|
+
watch(watchPaths, { ignored: /node_modules|tmp/ }).on("all", debouncedBuild);
|
|
212
|
+
console.log(`Watching ${watchPaths.join(", ")}...`);
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=traffic-icon-sprite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traffic-icon-sprite.js","sourceRoot":"","sources":["../../scripts/traffic-icon-sprite.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import {readFile, readdir} from "node:fs/promises";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
|
|
4
|
-
const colors = {
|
|
5
|
-
red: (str: string) => `\x1b[31m${str}\x1b[0m`,
|
|
6
|
-
yellow: (str: string) => `\x1b[33m${str}\x1b[0m`,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
interface Icon {
|
|
10
|
-
fileName: string;
|
|
11
|
-
name: string;
|
|
12
|
-
variant: string;
|
|
13
|
-
suffix: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface MetaIcon {
|
|
17
|
-
label?: {
|
|
18
|
-
de: string;
|
|
19
|
-
en: string;
|
|
20
|
-
};
|
|
21
|
-
aliases?: string[];
|
|
22
|
-
groups?: string[];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface MetaData {
|
|
26
|
-
icons?: Record<string, MetaIcon>;
|
|
27
|
-
copyright?: string;
|
|
28
|
-
defaultIcon?: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
interface PackageJson {
|
|
32
|
-
name: string;
|
|
33
|
-
version: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
interface ResultIcon extends MetaIcon {
|
|
37
|
-
id: string;
|
|
38
|
-
variants: string[];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
interface Result {
|
|
42
|
-
name: string;
|
|
43
|
-
version: string;
|
|
44
|
-
copyright: string;
|
|
45
|
-
defaultIcon?: string;
|
|
46
|
-
icons: ResultIcon[];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function parseIconName(fileName: string): Icon {
|
|
50
|
-
const parts = fileName.split(".");
|
|
51
|
-
if (parts.length < 2) {
|
|
52
|
-
throw new Error("Invalid file name: no extension");
|
|
53
|
-
}
|
|
54
|
-
const main = parts[0]!;
|
|
55
|
-
const suffix = parts[1]!;
|
|
56
|
-
const nameParts = main.split("-");
|
|
57
|
-
if (nameParts.length < 1) {
|
|
58
|
-
throw new Error("Invalid file name: no parts");
|
|
59
|
-
}
|
|
60
|
-
const variant = nameParts.pop()!;
|
|
61
|
-
const name = nameParts.join("-");
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
fileName,
|
|
65
|
-
name,
|
|
66
|
-
variant,
|
|
67
|
-
suffix,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async function main() {
|
|
72
|
-
const argv = process.argv;
|
|
73
|
-
const [, , metaPath, srcPath] = argv;
|
|
74
|
-
|
|
75
|
-
if (!metaPath) {
|
|
76
|
-
throw new Error("argument metaPath missing");
|
|
77
|
-
}
|
|
78
|
-
if (!srcPath) {
|
|
79
|
-
throw new Error("argument srcPath missing");
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const metaDataContent = await readFile(path.resolve(metaPath), "utf8");
|
|
83
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
84
|
-
const metaData: MetaData = JSON.parse(metaDataContent);
|
|
85
|
-
|
|
86
|
-
const packageJsonContent = await readFile("package.json", "utf8");
|
|
87
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
88
|
-
const packageJson: PackageJson = JSON.parse(packageJsonContent);
|
|
89
|
-
|
|
90
|
-
if (!metaData.icons) {
|
|
91
|
-
console.error(
|
|
92
|
-
colors.red("ERROR: No Icons field found in src/meta.json!"),
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const result: Result = {
|
|
97
|
-
name: packageJson.name,
|
|
98
|
-
version: packageJson.version,
|
|
99
|
-
copyright: metaData.copyright || "Open Mapsight",
|
|
100
|
-
defaultIcon: metaData.defaultIcon,
|
|
101
|
-
icons: [],
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const files = await readdir(srcPath);
|
|
105
|
-
const icons = files
|
|
106
|
-
.filter((fileName) => /(\.webp|\.png|\.svg)$/.test(fileName))
|
|
107
|
-
.map((iconFile) => parseIconName(iconFile));
|
|
108
|
-
const variants = [...new Set(icons.map(({variant}) => variant))];
|
|
109
|
-
const iconGroups = icons.reduce(
|
|
110
|
-
(groups, icon) => ({
|
|
111
|
-
...groups,
|
|
112
|
-
[icon.name]: {
|
|
113
|
-
...(groups[icon.name] || {}),
|
|
114
|
-
[icon.variant]: icon,
|
|
115
|
-
},
|
|
116
|
-
}),
|
|
117
|
-
{} as Record<string, Record<string, Icon>>,
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
Object.keys(iconGroups).forEach((name) => {
|
|
121
|
-
if (metaData.icons && !metaData.icons[name]) {
|
|
122
|
-
console.warn(
|
|
123
|
-
colors.yellow(
|
|
124
|
-
'WARNING: Icon "' +
|
|
125
|
-
name +
|
|
126
|
-
'" is not specified in src/meta.json!',
|
|
127
|
-
),
|
|
128
|
-
);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
result.icons.push({
|
|
132
|
-
...((metaData.icons && metaData.icons[name]) || {}),
|
|
133
|
-
id: name,
|
|
134
|
-
variants: variants,
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
console.log(JSON.stringify(result, null, 4));
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
main().catch(console.error);
|