@mapsight/traffic-style 5.0.1 → 5.0.2

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.
@@ -1,40 +0,0 @@
1
- import {z} from "zod/v4";
2
-
3
- export type IconVariant = z.infer<typeof IconVariantSchema>;
4
- export const IconVariantSchema = z.stringFormat(
5
- "mapsight-icon-variant",
6
- /[a-z]+/,
7
- );
8
-
9
- export type IconId = z.infer<typeof IconIdSchema>;
10
- export const IconIdSchema = z.stringFormat("mapsight-icon-id", /[0-9a-z-]+/);
11
-
12
- export type LangCode = z.infer<typeof LangCodeSchema>;
13
- export const LangCodeSchema = z.stringFormat("mapsight-lang-code", /[a-z]{2}/);
14
-
15
- export type IconGroupName = z.infer<typeof IconGroupNameSchema>;
16
- export const IconGroupNameSchema = z.stringFormat(
17
- "mapsight-icon-group",
18
- /[0-9a-z-]+/,
19
- );
20
-
21
- export type IconMeta = z.infer<typeof IconMetaSchema>;
22
- export const IconMetaSchema = z.object({
23
- // The label object has dynamic keys for languages (e.g., "de", "en", "en_US")
24
- // and string values for the text.
25
- id: IconIdSchema,
26
- label: z.record(LangCodeSchema, z.string()).optional(),
27
- aliases: z.array(IconIdSchema).optional(),
28
- groups: z.array(IconGroupNameSchema).optional(),
29
- // The fallback field is optional.
30
- fallback: IconIdSchema.optional(),
31
- });
32
-
33
- export type MetaData = z.infer<typeof DistMetaDataSchema>;
34
- export const DistMetaDataSchema = z.object({
35
- name: z.string(),
36
- version: z.string(),
37
- copyright: z.string(),
38
- defaultIcon: IconIdSchema,
39
- icons: z.array(IconMetaSchema),
40
- });
@@ -1,234 +0,0 @@
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
-
7
- import {afterEach, beforeEach, describe, expect, it, vi} from "vitest";
8
-
9
- import {main} from "./optimize-icons";
10
-
11
- describe("optimize-icons.ts", () => {
12
- let tmpDir: string;
13
- let srcDir: string;
14
- let destDir: string;
15
-
16
- beforeEach(async () => {
17
- tmpDir = path.join(
18
- os.tmpdir(),
19
- `optimize-icons-test-${Math.random().toString(36).slice(2)}`,
20
- );
21
- srcDir = path.join(tmpDir, "src");
22
- destDir = path.join(tmpDir, "dest");
23
- await mkdir(srcDir, {recursive: true});
24
- await mkdir(destDir, {recursive: true});
25
-
26
- // Mock process.exitCode to avoid affecting the test runner
27
- vi.stubGlobal("process", {
28
- ...process,
29
- exitCode: 0,
30
- });
31
- });
32
-
33
- afterEach(async () => {
34
- if (srcDir && destDir) {
35
- try {
36
- const manifestPath = getManifestPath(srcDir, destDir);
37
- await unlink(manifestPath);
38
- } catch {
39
- // ignore if manifest doesn't exist
40
- }
41
- }
42
- if (tmpDir) {
43
- await rm(tmpDir, {recursive: true, force: true});
44
- }
45
- vi.unstubAllGlobals();
46
- });
47
-
48
- async function runScript(args: Record<string, string | boolean>) {
49
- const argv = ["node", "optimize-icons.ts"];
50
- for (const [key, value] of Object.entries(args)) {
51
- if (typeof value === "boolean") {
52
- if (value) argv.push(`--${key}`);
53
- } else {
54
- argv.push(`--${key}`, String(value));
55
- }
56
- }
57
-
58
- vi.stubGlobal("process", {
59
- ...process,
60
- argv,
61
- });
62
-
63
- await main();
64
- }
65
-
66
- function getManifestPath(src: string, dest: string) {
67
- const scriptPath = fileURLToPath(import.meta.url);
68
- const packageRoot = path.resolve(path.dirname(scriptPath), "..");
69
- const hash = createHash("sha256")
70
- .update(`${path.resolve(src)}:${path.resolve(dest)}`)
71
- .digest("hex")
72
- .slice(0, 16);
73
- return path.join(
74
- packageRoot,
75
- "tmp",
76
- `.optimize-icons-manifest-${hash}.json`,
77
- );
78
- }
79
-
80
- it("should process an SVG file and produce SVG, PNG, and WebP outputs", async () => {
81
- 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>`;
82
- await writeFile(path.join(srcDir, "test.svg"), svgContent);
83
-
84
- await runScript({
85
- src: srcDir,
86
- dest: destDir,
87
- });
88
-
89
- expect(await stat(path.join(destDir, "test.svg"))).toBeDefined();
90
- expect(await stat(path.join(destDir, "test.png"))).toBeDefined();
91
- expect(await stat(path.join(destDir, "test.webp"))).toBeDefined();
92
-
93
- const manifestPath = getManifestPath(srcDir, destDir);
94
- const manifestRaw = await readFile(manifestPath, "utf8");
95
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
96
- const outputs = JSON.parse(manifestRaw).files["test.svg"].outputs as
97
- | string[]
98
- | undefined;
99
- expect(outputs).toBeDefined();
100
- expect(outputs).toContain("test.svg");
101
- expect(outputs).toContain("test.png");
102
- expect(outputs).toContain("test.webp");
103
- });
104
-
105
- it("should process a PNG file and produce PNG and WebP outputs", async () => {
106
- // Create a tiny valid PNG using sharp if possible, or just a placeholder if we skip actual image check
107
- // Since we have sharp available in the environment, let's use it if we can, but simpler is to use a minimal PNG buffer.
108
- const sharp = (await import("sharp")).default;
109
- const pngBuffer = await sharp({
110
- create: {
111
- width: 10,
112
- height: 10,
113
- channels: 4,
114
- background: {r: 255, g: 0, b: 0, alpha: 0.5},
115
- },
116
- })
117
- .png()
118
- .toBuffer();
119
-
120
- await writeFile(path.join(srcDir, "test.png"), pngBuffer);
121
-
122
- await runScript({
123
- src: srcDir,
124
- dest: destDir,
125
- });
126
-
127
- expect(await stat(path.join(destDir, "test.png"))).toBeDefined();
128
- expect(await stat(path.join(destDir, "test.webp"))).toBeDefined();
129
- await expect(
130
- async () => await stat(path.join(destDir, "test.svg")),
131
- ).rejects.toThrow();
132
- });
133
-
134
- it("should scale images when --scale is provided", async () => {
135
- 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>`;
136
- await writeFile(path.join(srcDir, "scale-test.svg"), svgContent);
137
-
138
- await runScript({
139
- src: srcDir,
140
- dest: destDir,
141
- scale: "2",
142
- });
143
-
144
- const sharp = (await import("sharp")).default;
145
- const metadata = await sharp(
146
- path.join(destDir, "scale-test.png"),
147
- ).metadata();
148
- expect(metadata.width).toBe(20);
149
- expect(metadata.height).toBe(20);
150
- });
151
-
152
- it("should skip processing if files haven't changed", async () => {
153
- const svgContent = `<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg"><rect width="10" height="10" fill="red"/></svg>`;
154
- const testFile = path.join(srcDir, "skip-test.svg");
155
- await writeFile(testFile, svgContent);
156
-
157
- // First run
158
- await runScript({
159
- src: srcDir,
160
- dest: destDir,
161
- verbose: true,
162
- });
163
-
164
- const destFile = path.join(destDir, "skip-test.png");
165
- const firstStat = await stat(destFile);
166
-
167
- // Second run
168
- await runScript({
169
- src: srcDir,
170
- dest: destDir,
171
- verbose: true,
172
- });
173
-
174
- const secondStat = await stat(destFile);
175
- expect(secondStat.mtimeMs).toBe(firstStat.mtimeMs);
176
- });
177
-
178
- it("should only produce specified targets when --target is provided", async () => {
179
- const svgContent = `<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="red"/></svg>`;
180
- await writeFile(path.join(srcDir, "target-test.svg"), svgContent);
181
-
182
- await runScript({
183
- src: srcDir,
184
- dest: destDir,
185
- target: "png",
186
- });
187
-
188
- expect(await stat(path.join(destDir, "target-test.png"))).toBeDefined();
189
- await expect(
190
- async () => await stat(path.join(destDir, "target-test.svg")),
191
- ).rejects.toThrow();
192
- await expect(
193
- async () => await stat(path.join(destDir, "target-test.webp")),
194
- ).rejects.toThrow();
195
-
196
- const manifestPath = getManifestPath(srcDir, destDir);
197
- const manifestRaw = await readFile(manifestPath, "utf8");
198
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
199
- const outputs = JSON.parse(manifestRaw).files["target-test.svg"]
200
- .outputs as string[];
201
- expect(outputs).toEqual(["target-test.png"]);
202
- });
203
-
204
- it("should produce multiple specified targets", async () => {
205
- const svgContent = `<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" fill="red"/></svg>`;
206
- await writeFile(path.join(srcDir, "multi-target.svg"), svgContent);
207
-
208
- await runScript({
209
- src: srcDir,
210
- dest: destDir,
211
- target: "svg,webp",
212
- });
213
-
214
- expect(
215
- await stat(path.join(destDir, "multi-target.svg")),
216
- ).toBeDefined();
217
- expect(
218
- await stat(path.join(destDir, "multi-target.webp")),
219
- ).toBeDefined();
220
- await expect(
221
- async () => await stat(path.join(destDir, "multi-target.png")),
222
- ).rejects.toThrow();
223
- });
224
-
225
- it("should fail if an invalid target is provided", async () => {
226
- await expect(
227
- runScript({
228
- src: srcDir,
229
- dest: destDir,
230
- target: "invalid",
231
- }),
232
- ).rejects.toThrow("Invalid target format: invalid");
233
- });
234
- });