icuewidget-cli 0.4.44

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.
@@ -0,0 +1,77 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { toZipPath, walkFiles } from "./fs-utils.js";
4
+
5
+ const CRC_TABLE = new Uint32Array(256).map((_, n) => {
6
+ let c = n;
7
+ for (let k = 0; k < 8; k += 1) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
8
+ return c >>> 0;
9
+ });
10
+
11
+ function crc32(buffer) {
12
+ let crc = 0xffffffff;
13
+ for (const byte of buffer) crc = CRC_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);
14
+ return (crc ^ 0xffffffff) >>> 0;
15
+ }
16
+
17
+ function dosDateTime(date = new Date()) {
18
+ const time = (date.getHours() << 11) | (date.getMinutes() << 5) | Math.floor(date.getSeconds() / 2);
19
+ const day = ((date.getFullYear() - 1980) << 9) | ((date.getMonth() + 1) << 5) | date.getDate();
20
+ return { time, day };
21
+ }
22
+
23
+ function u16(value) {
24
+ const buffer = Buffer.alloc(2);
25
+ buffer.writeUInt16LE(value);
26
+ return buffer;
27
+ }
28
+
29
+ function u32(value) {
30
+ const buffer = Buffer.alloc(4);
31
+ buffer.writeUInt32LE(value >>> 0);
32
+ return buffer;
33
+ }
34
+
35
+ function shouldInclude(root, outputPath, absolutePath) {
36
+ if (absolutePath === outputPath) return false;
37
+ const rel = path.relative(root, absolutePath);
38
+ if (rel.endsWith(".icuewidget")) return false;
39
+ return rel.split(path.sep).every((part) => part && !part.startsWith(".") && part !== "__pycache__");
40
+ }
41
+
42
+ export async function createPackage(widgetDir, outputPath) {
43
+ const root = path.resolve(widgetDir);
44
+ const output = path.resolve(outputPath);
45
+ await fs.mkdir(path.dirname(output), { recursive: true });
46
+
47
+ const filePaths = (await walkFiles(root)).filter((file) => shouldInclude(root, output, path.resolve(file))).sort();
48
+ const chunks = [];
49
+ const central = [];
50
+ let offset = 0;
51
+ const { time, day } = dosDateTime();
52
+
53
+ for (const filePath of filePaths) {
54
+ const data = await fs.readFile(filePath);
55
+ const name = Buffer.from(toZipPath(path.relative(root, filePath)), "utf8");
56
+ const crc = crc32(data);
57
+ const local = Buffer.concat([
58
+ u32(0x04034b50), u16(20), u16(0x0800), u16(0), u16(time), u16(day),
59
+ u32(crc), u32(data.length), u32(data.length), u16(name.length), u16(0), name,
60
+ ]);
61
+ chunks.push(local, data);
62
+ central.push(Buffer.concat([
63
+ u32(0x02014b50), u16(20), u16(20), u16(0x0800), u16(0), u16(time), u16(day),
64
+ u32(crc), u32(data.length), u32(data.length), u16(name.length), u16(0), u16(0),
65
+ u16(0), u16(0), u32(0), u32(offset), name,
66
+ ]));
67
+ offset += local.length + data.length;
68
+ }
69
+
70
+ const centralStart = offset;
71
+ const centralData = Buffer.concat(central);
72
+ const end = Buffer.concat([
73
+ u32(0x06054b50), u16(0), u16(0), u16(central.length), u16(central.length),
74
+ u32(centralData.length), u32(centralStart), u16(0),
75
+ ]);
76
+ await fs.writeFile(output, Buffer.concat([...chunks, centralData, end]));
77
+ }