finch-markdown-editor 0.1.2 → 0.1.5

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/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  // src/index.ts
2
2
  import { createHash } from "node:crypto";
3
- import { mkdir, readFile, realpath, rm, stat, writeFile } from "node:fs/promises";
3
+ import { mkdir, readFile, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
4
+ import { gunzip } from "node:zlib";
5
+ import { promisify } from "node:util";
4
6
  import { watch } from "node:fs";
5
7
  import { spawn } from "node:child_process";
6
8
  import path from "node:path";
@@ -291,34 +293,63 @@ async function restoreDocument(ctx, panel) {
291
293
  return false;
292
294
  }
293
295
  }
296
+ var BMMD_VERSION = "0.2.0";
297
+ var BMMD_TARBALL_URL = `https://registry.npmjs.org/bmmd/-/bmmd-${BMMD_VERSION}.tgz`;
298
+ var gunzipAsync = promisify(gunzip);
294
299
  var bmmdBinPromise;
300
+ function tarString(buffer) {
301
+ const zero = buffer.indexOf(0);
302
+ return buffer.subarray(0, zero === -1 ? buffer.length : zero).toString("utf8");
303
+ }
304
+ async function extractBmmdTarball(tarball, destination) {
305
+ const tar = await gunzipAsync(tarball);
306
+ for (let offset = 0; offset + 512 <= tar.length; ) {
307
+ const header = tar.subarray(offset, offset + 512);
308
+ if (header.every((byte) => byte === 0)) break;
309
+ const name = tarString(header.subarray(0, 100));
310
+ const prefix = tarString(header.subarray(345, 500));
311
+ const entryPath = prefix ? `${prefix}/${name}` : name;
312
+ const sizeText = tarString(header.subarray(124, 136)).trim();
313
+ const size = Number.parseInt(sizeText || "0", 8);
314
+ if (!Number.isSafeInteger(size) || size < 0) throw new Error("Invalid bmmd package archive.");
315
+ const bodyStart = offset + 512;
316
+ const bodyEnd = bodyStart + size;
317
+ if (bodyEnd > tar.length) throw new Error("Truncated bmmd package archive.");
318
+ if (header[156] === 48 && entryPath.startsWith("package/bin/") && !entryPath.includes("..")) {
319
+ const relative = entryPath.slice("package/bin/".length);
320
+ if (relative && !path.isAbsolute(relative)) {
321
+ const outputPath = path.join(destination, relative);
322
+ await mkdir(path.dirname(outputPath), { recursive: true });
323
+ await writeFile(outputPath, tar.subarray(bodyStart, bodyEnd));
324
+ }
325
+ }
326
+ offset = bodyStart + Math.ceil(size / 512) * 512;
327
+ }
328
+ }
295
329
  async function ensureBmmdBin(ctx, onInstalling) {
296
330
  if (!bmmdBinPromise) {
297
331
  bmmdBinPromise = (async () => {
298
332
  const installDir = path.join(ctx.storagePath, "bmmd");
299
- const binPath = path.join(installDir, "node_modules", "bmmd", "bin", "bmmd.mjs");
333
+ const binPath = path.join(installDir, "bin", "bmmd.mjs");
300
334
  try {
301
335
  await stat(binPath);
302
336
  return binPath;
303
337
  } catch {
304
338
  }
305
339
  onInstalling?.();
306
- await mkdir(installDir, { recursive: true });
307
- await new Promise((resolve, reject) => {
308
- const child = spawn("npm", [
309
- "install",
310
- "--no-save",
311
- "--no-audit",
312
- "--no-fund",
313
- "--silent",
314
- "--prefix",
315
- installDir,
316
- "bmmd@latest"
317
- ], { stdio: "ignore" });
318
- child.on("error", reject);
319
- child.on("close", (code) => code === 0 ? resolve() : reject(new Error(`npm install bmmd exited with code ${code}`)));
320
- });
321
- await stat(binPath);
340
+ const response = await fetch(BMMD_TARBALL_URL);
341
+ if (!response.ok) throw new Error(`Could not download bmmd ${BMMD_VERSION}: HTTP ${response.status}.`);
342
+ const stagingDir = `${installDir}.staging-${process.pid}-${Date.now()}`;
343
+ await rm(stagingDir, { recursive: true, force: true });
344
+ try {
345
+ await extractBmmdTarball(Buffer.from(await response.arrayBuffer()), path.join(stagingDir, "bin"));
346
+ await stat(path.join(stagingDir, "bin", "bmmd.mjs"));
347
+ await rm(installDir, { recursive: true, force: true });
348
+ await rename(stagingDir, installDir);
349
+ } catch (error) {
350
+ await rm(stagingDir, { recursive: true, force: true });
351
+ throw error;
352
+ }
322
353
  return binPath;
323
354
  })();
324
355
  }
@@ -604,7 +635,7 @@ async function handleMessage(ctx, panel, raw) {
604
635
  case "renderBm": {
605
636
  try {
606
637
  const html = await renderWithBm(ctx, String(message.markdown ?? ""), String(message.markdownStyle ?? "kami"), message.customCss, () => {
607
- panel.postMessage({ type: "status", message: "\u9996\u6B21\u6E32\u67D3\uFF1A\u6B63\u5728\u672C\u673A\u5B89\u88C5 bmmd \u6E32\u67D3\u5F15\u64CE\uFF08\u7EA6\u51E0\u79D2\uFF0C\u4EC5\u4E00\u6B21\uFF09\u2026" }).catch(() => {
638
+ panel.postMessage({ type: "status", message: "\u9996\u6B21\u6E32\u67D3\uFF1A\u6B63\u5728\u4E0B\u8F7D bmmd \u6E32\u67D3\u5F15\u64CE\uFF08\u7EA6\u51E0\u79D2\uFF0C\u4EC5\u4E00\u6B21\uFF09\u2026" }).catch(() => {
608
639
  });
609
640
  });
610
641
  await panel.postMessage({ type: "bmRendered", html, requestId: message.requestId });
@@ -765,7 +796,7 @@ function activate(ctx) {
765
796
  }));
766
797
  ctx.subscriptions.push(ctx.tools.register({
767
798
  name: "markdown_editor_document",
768
- title: "\u5199\u4F5C",
799
+ title: "\u5199\u5B57",
769
800
  description: `Open, create, revise, or restyle a Markdown document in Markdown Editor.
770
801
  action:
771
802
  open \u2014 read an absolute local Markdown path and open it as an editable WeChat article preview