@lexiaowen/md2wechat-new 2.2.0

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,173 @@
1
+ const crypto = require("crypto");
2
+ const fs = require("fs");
3
+ const http = require("http");
4
+ const https = require("https");
5
+ const os = require("os");
6
+ const path = require("path");
7
+ const { fileURLToPath } = require("url");
8
+
9
+ const pkg = require("../package.json");
10
+
11
+ const VERSION = pkg.version;
12
+ const REPO = "lexiaowenn/md2wechat-new";
13
+ const PACKAGE_NAME = pkg.name;
14
+
15
+ const isWindows = process.platform === "win32";
16
+ const TARGETS = {
17
+ darwin: {
18
+ x64: "md2wechat-darwin-amd64",
19
+ arm64: "md2wechat-darwin-arm64",
20
+ },
21
+ linux: {
22
+ x64: "md2wechat-linux-amd64",
23
+ arm64: "md2wechat-linux-arm64",
24
+ },
25
+ win32: {
26
+ x64: "md2wechat-windows-amd64.exe",
27
+ },
28
+ };
29
+ const releaseBaseUrl =
30
+ process.env.MD2WECHAT_RELEASE_BASE_URL ||
31
+ `https://github.com/${REPO}/releases/download/v${VERSION}`;
32
+ const assetName = TARGETS[process.platform]?.[process.arch];
33
+ const binaryName = isWindows ? "md2wechat.exe" : "md2wechat";
34
+ const binDir = path.join(__dirname, "..", "bin");
35
+ const destination = path.join(binDir, binaryName);
36
+
37
+ if (!assetName) {
38
+ console.error(
39
+ [
40
+ `Unsupported platform for ${PACKAGE_NAME}: ${process.platform}-${process.arch}`,
41
+ "Supported npm install targets are:",
42
+ " - darwin-x64",
43
+ " - darwin-arm64",
44
+ " - linux-x64",
45
+ " - linux-arm64",
46
+ " - win32-x64",
47
+ ].join("\n")
48
+ );
49
+ process.exit(1);
50
+ }
51
+
52
+ function hasScheme(value) {
53
+ return (
54
+ /^[a-zA-Z][a-zA-Z0-9+.-]*:/.test(value) && !path.win32.isAbsolute(value)
55
+ );
56
+ }
57
+
58
+ function resolveAssetLocation(base, name) {
59
+ if (!hasScheme(base)) {
60
+ return path.join(base, name);
61
+ }
62
+
63
+ return base.endsWith("/") ? `${base}${name}` : `${base}/${name}`;
64
+ }
65
+
66
+ function downloadToFile(source, destinationPath) {
67
+ if (!hasScheme(source)) {
68
+ fs.copyFileSync(source, destinationPath);
69
+ return Promise.resolve();
70
+ }
71
+
72
+ if (source.startsWith("file://")) {
73
+ fs.copyFileSync(fileURLToPath(source), destinationPath);
74
+ return Promise.resolve();
75
+ }
76
+
77
+ return new Promise((resolve, reject) => {
78
+ const client = source.startsWith("https:") ? https : http;
79
+
80
+ client
81
+ .get(source, (response) => {
82
+ if (
83
+ (response.statusCode === 301 || response.statusCode === 302) &&
84
+ response.headers.location
85
+ ) {
86
+ response.resume();
87
+ downloadToFile(response.headers.location, destinationPath).then(
88
+ resolve,
89
+ reject
90
+ );
91
+ return;
92
+ }
93
+
94
+ if (response.statusCode !== 200) {
95
+ response.resume();
96
+ reject(
97
+ new Error(
98
+ `download failed with status ${response.statusCode}: ${source}`
99
+ )
100
+ );
101
+ return;
102
+ }
103
+
104
+ const file = fs.createWriteStream(destinationPath);
105
+ response.pipe(file);
106
+ file.on("finish", () => {
107
+ file.close(resolve);
108
+ });
109
+ file.on("error", reject);
110
+ })
111
+ .on("error", reject);
112
+ });
113
+ }
114
+
115
+ function sha256(filePath) {
116
+ const hash = crypto.createHash("sha256");
117
+ hash.update(fs.readFileSync(filePath));
118
+ return hash.digest("hex");
119
+ }
120
+
121
+ function expectedChecksum(checksumsPath, filename) {
122
+ const line = fs
123
+ .readFileSync(checksumsPath, "utf8")
124
+ .split(/\r?\n/)
125
+ .find((entry) => entry.trim().endsWith(` ${filename}`));
126
+
127
+ if (!line) {
128
+ throw new Error(`checksums.txt does not contain an entry for ${filename}`);
129
+ }
130
+
131
+ return line.trim().split(/\s+/)[0].toLowerCase();
132
+ }
133
+
134
+ async function install() {
135
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "md2wechat-npm-"));
136
+ const downloadedBinary = path.join(tmpDir, assetName);
137
+ const checksumsPath = path.join(tmpDir, "checksums.txt");
138
+
139
+ try {
140
+ fs.mkdirSync(binDir, { recursive: true });
141
+
142
+ await downloadToFile(
143
+ resolveAssetLocation(releaseBaseUrl, assetName),
144
+ downloadedBinary
145
+ );
146
+ await downloadToFile(
147
+ resolveAssetLocation(releaseBaseUrl, "checksums.txt"),
148
+ checksumsPath
149
+ );
150
+
151
+ const expected = expectedChecksum(checksumsPath, assetName);
152
+ const actual = sha256(downloadedBinary);
153
+ if (expected !== actual) {
154
+ throw new Error(`checksum mismatch for ${assetName}`);
155
+ }
156
+
157
+ fs.copyFileSync(downloadedBinary, destination);
158
+ if (!isWindows) {
159
+ fs.chmodSync(destination, 0o755);
160
+ }
161
+
162
+ console.log(
163
+ `Installed md2wechat ${VERSION} from ${resolveAssetLocation(releaseBaseUrl, assetName)}`
164
+ );
165
+ } finally {
166
+ fs.rmSync(tmpDir, { recursive: true, force: true });
167
+ }
168
+ }
169
+
170
+ install().catch((error) => {
171
+ console.error(`Failed to install ${PACKAGE_NAME}: ${error.message}`);
172
+ process.exit(1);
173
+ });
package/scripts/run.js ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const { execFileSync } = require("child_process");
6
+
7
+ const ext = process.platform === "win32" ? ".exe" : "";
8
+ const binaryPath = path.join(__dirname, "..", "bin", `md2wechat${ext}`);
9
+
10
+ if (!fs.existsSync(binaryPath)) {
11
+ console.error(
12
+ "md2wechat binary is missing. Reinstall with `npm install -g @lexiaowen/md2wechat-new`."
13
+ );
14
+ process.exit(1);
15
+ }
16
+
17
+ try {
18
+ execFileSync(binaryPath, process.argv.slice(2), { stdio: "inherit" });
19
+ } catch (error) {
20
+ if (typeof error.status === "number") {
21
+ process.exit(error.status);
22
+ }
23
+
24
+ console.error(`Failed to launch md2wechat: ${error.message}`);
25
+ process.exit(1);
26
+ }