finch-markdown-editor 0.1.5 → 0.1.8
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/README.md +69 -69
- package/dist/bmmd/LICENSE +165 -0
- package/dist/bmmd/bin/bmmd.mjs +73 -0
- package/dist/bmmd/bin/decode-named-character-reference-o_gI0v-h.mjs +2 -0
- package/dist/bmmd/bin/dist-B0xJMeoM.mjs +134 -0
- package/dist/bmmd/bin/html-CCefjxd3.mjs +1406 -0
- package/dist/bmmd/bin/html-CSUv3zEC.mjs +21 -0
- package/dist/bmmd/bin/lib-BKH2iTnt.mjs +7 -0
- package/dist/bmmd/bin/lib-BRN_Fj5A.mjs +3 -0
- package/dist/bmmd/bin/lib-D_kP5PWU.mjs +13 -0
- package/dist/bmmd/bin/markdown-KovTQZtX.mjs +16 -0
- package/dist/bmmd/bin/markdownit-DkVD15-k.mjs +1 -0
- package/dist/bmmd/bin/rolldown-runtime-8V8biNmG.mjs +1 -0
- package/dist/bmmd/bin/syntax-BgWf_lVQ.mjs +1 -0
- package/dist/bmmd/bin/syntax-Dy8vTFtl.mjs +1 -0
- package/dist/bmmd/bin/text-3YfHIFOO.mjs +7 -0
- package/dist/codemirror.js +1 -1
- package/dist/index.js +12 -79
- package/dist/panel.html +2624 -2590
- package/i18n/en-US.json +16 -16
- package/i18n/zh-CN.json +16 -16
- package/package.json +212 -211
package/dist/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { mkdir, readFile, realpath,
|
|
4
|
-
import { gunzip } from "node:zlib";
|
|
5
|
-
import { promisify } from "node:util";
|
|
3
|
+
import { mkdir, readFile, realpath, rm, stat, writeFile } from "node:fs/promises";
|
|
6
4
|
import { watch } from "node:fs";
|
|
7
5
|
import { spawn } from "node:child_process";
|
|
8
6
|
import path from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
9
8
|
import os from "node:os";
|
|
10
9
|
var PASTE_IMAGE_EXT = {
|
|
11
10
|
"image/png": "png",
|
|
@@ -293,75 +292,9 @@ async function restoreDocument(ctx, panel) {
|
|
|
293
292
|
return false;
|
|
294
293
|
}
|
|
295
294
|
}
|
|
296
|
-
var
|
|
297
|
-
|
|
298
|
-
|
|
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
|
-
}
|
|
329
|
-
async function ensureBmmdBin(ctx, onInstalling) {
|
|
330
|
-
if (!bmmdBinPromise) {
|
|
331
|
-
bmmdBinPromise = (async () => {
|
|
332
|
-
const installDir = path.join(ctx.storagePath, "bmmd");
|
|
333
|
-
const binPath = path.join(installDir, "bin", "bmmd.mjs");
|
|
334
|
-
try {
|
|
335
|
-
await stat(binPath);
|
|
336
|
-
return binPath;
|
|
337
|
-
} catch {
|
|
338
|
-
}
|
|
339
|
-
onInstalling?.();
|
|
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
|
-
}
|
|
353
|
-
return binPath;
|
|
354
|
-
})();
|
|
355
|
-
}
|
|
356
|
-
try {
|
|
357
|
-
return await bmmdBinPromise;
|
|
358
|
-
} catch (error) {
|
|
359
|
-
bmmdBinPromise = void 0;
|
|
360
|
-
throw error;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
async function runBmmd(ctx, args, input, onInstalling) {
|
|
364
|
-
const binPath = await ensureBmmdBin(ctx, onInstalling);
|
|
295
|
+
var BMMD_BIN_PATH = fileURLToPath(new URL("./bmmd/bin/bmmd.mjs", import.meta.url));
|
|
296
|
+
async function runBmmd(args, input) {
|
|
297
|
+
const binPath = BMMD_BIN_PATH;
|
|
365
298
|
return new Promise((resolve, reject) => {
|
|
366
299
|
const child = spawn(process.execPath, [binPath, ...args], { stdio: ["pipe", "pipe", "pipe"] });
|
|
367
300
|
let output = "";
|
|
@@ -394,11 +327,11 @@ function substituteFinchFileImagesForBm(markdown) {
|
|
|
394
327
|
});
|
|
395
328
|
return { markdown: substituted, urls };
|
|
396
329
|
}
|
|
397
|
-
async function renderWithBm(
|
|
330
|
+
async function renderWithBm(markdown, markdownStyle, customCss) {
|
|
398
331
|
const args = ["render", "--platform", "wechat", "--markdown-style", markdownStyle || "kami"];
|
|
399
332
|
if (customCss && customCss.trim()) args.push("--custom-css", customCss);
|
|
400
333
|
const prepared = substituteFinchFileImagesForBm(markdown);
|
|
401
|
-
let html = await runBmmd(
|
|
334
|
+
let html = await runBmmd(args, prepared.markdown);
|
|
402
335
|
for (const [placeholder, originalUrl] of prepared.urls) html = html.split(placeholder).join(originalUrl);
|
|
403
336
|
return html;
|
|
404
337
|
}
|
|
@@ -634,10 +567,7 @@ async function handleMessage(ctx, panel, raw) {
|
|
|
634
567
|
}
|
|
635
568
|
case "renderBm": {
|
|
636
569
|
try {
|
|
637
|
-
const html = await renderWithBm(
|
|
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(() => {
|
|
639
|
-
});
|
|
640
|
-
});
|
|
570
|
+
const html = await renderWithBm(String(message.markdown ?? ""), String(message.markdownStyle ?? "kami"), message.customCss);
|
|
641
571
|
await panel.postMessage({ type: "bmRendered", html, requestId: message.requestId });
|
|
642
572
|
} catch (error) {
|
|
643
573
|
await panel.postMessage({ type: "error", message: `bm.md rendering failed: ${error instanceof Error ? error.message : String(error)}` });
|
|
@@ -773,6 +703,9 @@ function activate(ctx) {
|
|
|
773
703
|
},
|
|
774
704
|
feather: {
|
|
775
705
|
svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.086 18.412A2 2 0 0 1 12.67 19H5v-7.672a2 2 0 0 1 .586-1.414L11.75 3.75a6 6 0 1 1 8.49 8.49z"/><path d="M16 8 2 22"/><path d="M17.488 15H9"/></svg>'
|
|
706
|
+
},
|
|
707
|
+
"swatch-book": {
|
|
708
|
+
svg: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 17a4 4 0 0 1-8 0V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2Z"/><path d="M16.7 13H19a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2H7"/><path d="M 7 17h.01"/><path d="m11 8 2.3-2.3a2.4 2.4 0 0 1 3.404.004L18.6 7.6a2.4 2.4 0 0 1 .026 3.434L9.9 19.8"/></svg>'
|
|
776
709
|
}
|
|
777
710
|
}));
|
|
778
711
|
ctx.subscriptions.push(ctx.ui.onDidOpenPanel((panel) => {
|
|
@@ -800,7 +733,7 @@ function activate(ctx) {
|
|
|
800
733
|
description: `Open, create, revise, or restyle a Markdown document in Markdown Editor.
|
|
801
734
|
action:
|
|
802
735
|
open \u2014 read an absolute local Markdown path and open it as an editable WeChat article preview
|
|
803
|
-
create \u2014 write brand-new Markdown content to an absolute path that does not exist yet, then open it in Markdown Editor. Use this whenever the user asks to create
|
|
736
|
+
create \u2014 write brand-new Markdown content to an absolute path that does not exist yet, then open it in Markdown Editor. Use this whenever the user asks to write an article, start writing, write a post, create, or draft a new document \u2014 even if they do not mention Markdown. If title/topic or destination is missing, guide the user to provide it; once known, create and open the document rather than returning prose only. If they only want to begin, create a minimal titled starter document. Markdown Editor's own UI has no "new file" button on purpose \u2014 this tool action is the intended way to start a new document
|
|
804
737
|
apply \u2014 replace a source document with reviewed Markdown (requires path and markdown); the open panel refreshes in place, no Diff window
|
|
805
738
|
set_style \u2014 apply an AI-designed custom CSS layout to the currently open Markdown Editor preview (requires css). Write plain CSS scoped under #bm-md using tag/id selectors (no classes), use !important where needed to override the base style, and take inspiration from bm.md's built-in styles: kami (warm paper), bauhaus (geometric primary colors), blueprint (technical grid), botanical (soft green), newsprint (editorial serif), retro (nostalgic), sketch (hand-drawn), terminal (monospace dark).`,
|
|
806
739
|
inputSchema: {
|