@san-siva/blogkit-md-cli 0.1.20 → 0.1.21
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/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/cache/.previewinfo +1 -1
- package/.next/cache/.rscinfo +1 -1
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/diagnostics/route-bundle-stats.json +4 -4
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/server/app/[...slug]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/chunks/ssr/_0lv77ha._.js +1 -1
- package/.next/server/chunks/ssr/_0lv77ha._.js.map +1 -1
- package/.next/server/chunks/ssr/_0z4n825._.js +1 -1
- package/.next/server/chunks/ssr/_0z4n825._.js.map +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{0mr~5~notxy69.js → 0bgomtoptb4q7.js} +1 -1
- package/.next/static/chunks/{15yu-awv-.t~z.js → 10t4l336soqlc.js} +1 -1
- package/.next/trace +1 -1
- package/.next/trace-build +1 -1
- package/README.md +37 -2
- package/bin/blogkit-md.js +389 -46
- package/package.json +19 -4
- /package/.next/static/{k_detxuW-GmsRteYh4x8e → N6e_l60Njhp5bsxU4aIBS}/_buildManifest.js +0 -0
- /package/.next/static/{k_detxuW-GmsRteYh4x8e → N6e_l60Njhp5bsxU4aIBS}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{k_detxuW-GmsRteYh4x8e → N6e_l60Njhp5bsxU4aIBS}/_ssgManifest.js +0 -0
package/bin/blogkit-md.js
CHANGED
|
@@ -22,64 +22,360 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
22
|
mod
|
|
23
23
|
));
|
|
24
24
|
|
|
25
|
-
// scripts/
|
|
26
|
-
var import_node_http = require("http");
|
|
25
|
+
// scripts/cli.ts
|
|
27
26
|
var import_node_child_process = require("child_process");
|
|
28
27
|
var import_node_fs = require("fs");
|
|
28
|
+
var import_node_http = require("http");
|
|
29
|
+
var import_node_os = __toESM(require("os"));
|
|
29
30
|
var import_node_path = __toESM(require("path"));
|
|
30
|
-
var
|
|
31
|
-
var
|
|
32
|
-
var
|
|
33
|
-
var
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
var import_node_readline = __toESM(require("readline"));
|
|
32
|
+
var useColor = process.stdout.isTTY && !process.env.NO_COLOR;
|
|
33
|
+
var paint = (code) => (s) => useColor ? `\x1B[${code}m${s}\x1B[0m` : s;
|
|
34
|
+
var c = {
|
|
35
|
+
bold: paint("1"),
|
|
36
|
+
dim: paint("2"),
|
|
37
|
+
red: paint("31"),
|
|
38
|
+
green: paint("32"),
|
|
39
|
+
yellow: paint("33"),
|
|
40
|
+
blue: paint("34"),
|
|
41
|
+
magenta: paint("35"),
|
|
42
|
+
cyan: paint("36"),
|
|
43
|
+
gray: paint("90")
|
|
44
|
+
};
|
|
45
|
+
var INDENT = " ".repeat(3);
|
|
46
|
+
var line = (s = "") => console.log(INDENT + s);
|
|
47
|
+
var tree = (s = "") => console.log(c.gray(INDENT + "\u2502 ") + s);
|
|
48
|
+
var bannerShown = false;
|
|
49
|
+
function banner() {
|
|
50
|
+
if (bannerShown) return;
|
|
51
|
+
bannerShown = true;
|
|
52
|
+
line();
|
|
53
|
+
line(c.bold(c.blue("blogkit-md")));
|
|
54
|
+
line(c.gray("preview markdown as blogkit blog posts"));
|
|
55
|
+
line();
|
|
37
56
|
}
|
|
38
|
-
var
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
var tilde = (p) => {
|
|
58
|
+
const home = import_node_os.default.homedir();
|
|
59
|
+
return p.startsWith(home) ? "~" + p.slice(home.length) : p;
|
|
60
|
+
};
|
|
61
|
+
function humanAge(iso) {
|
|
62
|
+
const start = Date.parse(iso);
|
|
63
|
+
if (Number.isNaN(start)) return "\u2014";
|
|
64
|
+
const secs = Math.max(0, Math.floor((Date.now() - start) / 1e3));
|
|
65
|
+
if (secs < 60) return `${secs}s`;
|
|
66
|
+
if (secs < 3600) return `${Math.floor(secs / 60)}m`;
|
|
67
|
+
if (secs < 86400) return `${Math.floor(secs / 3600)}h`;
|
|
68
|
+
return `${Math.floor(secs / 86400)}d`;
|
|
69
|
+
}
|
|
70
|
+
function openBrowser(url) {
|
|
71
|
+
if (process.env.BLOGKIT_MD_NO_OPEN) return;
|
|
72
|
+
try {
|
|
73
|
+
(0, import_node_child_process.exec)(`open ${url}`);
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
var registryDir = () => process.env.BLOGKIT_MD_DIR || import_node_path.default.join(import_node_os.default.homedir(), ".blogkit-md");
|
|
78
|
+
var registryFile = () => import_node_path.default.join(registryDir(), "instances.json");
|
|
79
|
+
var logDir = () => import_node_path.default.join(registryDir(), "logs");
|
|
80
|
+
var isAlive = (pid) => {
|
|
81
|
+
try {
|
|
82
|
+
process.kill(pid, 0);
|
|
83
|
+
return true;
|
|
84
|
+
} catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
function readRegistry() {
|
|
89
|
+
try {
|
|
90
|
+
const raw = JSON.parse((0, import_node_fs.readFileSync)(registryFile(), "utf8"));
|
|
91
|
+
return Array.isArray(raw) ? raw : [];
|
|
92
|
+
} catch {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function writeRegistry(list) {
|
|
97
|
+
try {
|
|
98
|
+
(0, import_node_fs.mkdirSync)(registryDir(), { recursive: true });
|
|
99
|
+
(0, import_node_fs.writeFileSync)(registryFile(), JSON.stringify(list, null, 2));
|
|
100
|
+
} catch {
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function pruneRegistry() {
|
|
104
|
+
const all = readRegistry();
|
|
105
|
+
const live = all.filter((index) => isAlive(index.pid));
|
|
106
|
+
if (live.length !== all.length) writeRegistry(live);
|
|
107
|
+
return live;
|
|
108
|
+
}
|
|
109
|
+
function addInstance(inst) {
|
|
110
|
+
const list = pruneRegistry().filter((index) => index.pid !== inst.pid);
|
|
111
|
+
list.push(inst);
|
|
112
|
+
writeRegistry(list);
|
|
113
|
+
}
|
|
114
|
+
function removeInstance(pid) {
|
|
115
|
+
writeRegistry(readRegistry().filter((index) => index.pid !== pid));
|
|
116
|
+
}
|
|
117
|
+
function findByDir(dir) {
|
|
118
|
+
return pruneRegistry().find((index) => index.dir === dir);
|
|
119
|
+
}
|
|
120
|
+
function killInstance(inst) {
|
|
121
|
+
try {
|
|
122
|
+
process.kill(inst.pid, "SIGTERM");
|
|
123
|
+
} catch {
|
|
124
|
+
}
|
|
125
|
+
removeInstance(inst.pid);
|
|
126
|
+
}
|
|
127
|
+
function instanceLabel(inst) {
|
|
128
|
+
const kind = inst.isDirectory ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
129
|
+
const mode = inst.background ? c.magenta("bg") : c.gray("fg");
|
|
130
|
+
return `${c.green("localhost:" + inst.port)} ${kind} ${tilde(inst.dir)} ${c.gray("pid " + inst.pid)} ${c.gray("\xB7 " + humanAge(inst.startedAt))} ${mode}`;
|
|
131
|
+
}
|
|
132
|
+
function printPlainList(instances) {
|
|
133
|
+
banner();
|
|
134
|
+
line(c.bold("Running instances"));
|
|
135
|
+
instances.forEach((index) => tree(instanceLabel(index)));
|
|
136
|
+
line();
|
|
137
|
+
}
|
|
138
|
+
async function listInstancesInteractive() {
|
|
139
|
+
let instances = pruneRegistry();
|
|
140
|
+
if (instances.length === 0) {
|
|
141
|
+
banner();
|
|
142
|
+
line(c.yellow("No running blogkit-md instances."));
|
|
143
|
+
line();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (!process.stdin.isTTY) {
|
|
147
|
+
printPlainList(instances);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
await new Promise((resolve) => {
|
|
151
|
+
let index = 0;
|
|
152
|
+
const stdin = process.stdin;
|
|
153
|
+
try {
|
|
154
|
+
import_node_readline.default.emitKeypressEvents(stdin);
|
|
155
|
+
stdin.setRawMode(true);
|
|
156
|
+
stdin.resume();
|
|
157
|
+
} catch {
|
|
158
|
+
printPlainList(instances);
|
|
159
|
+
resolve();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const render = (footer) => {
|
|
163
|
+
const out = [
|
|
164
|
+
"",
|
|
165
|
+
INDENT + c.bold(c.blue("blogkit-md")) + c.gray(" \xB7 running instances"),
|
|
166
|
+
"",
|
|
167
|
+
...instances.map((inst, rowIndex) => {
|
|
168
|
+
const selected = rowIndex === index;
|
|
169
|
+
const pointer = selected ? c.blue("\u276F ") : " ";
|
|
170
|
+
const label = selected ? instanceLabel(inst) : c.dim(instanceLabel(inst));
|
|
171
|
+
return INDENT + pointer + label;
|
|
172
|
+
}),
|
|
173
|
+
"",
|
|
174
|
+
footer ?? c.gray(INDENT + "\u2191/\u2193 move \u23CE stop selected q quit"),
|
|
175
|
+
""
|
|
176
|
+
];
|
|
177
|
+
process.stdout.write("\x1B[2J\x1B[H" + out.join("\n") + "\n");
|
|
178
|
+
};
|
|
179
|
+
const finish = () => {
|
|
180
|
+
stdin.setRawMode(false);
|
|
181
|
+
stdin.removeAllListeners("keypress");
|
|
182
|
+
stdin.pause();
|
|
183
|
+
resolve();
|
|
184
|
+
};
|
|
185
|
+
const onKey = (_string, key) => {
|
|
186
|
+
if (!key) return;
|
|
187
|
+
switch (key.name) {
|
|
188
|
+
case "up":
|
|
189
|
+
case "k": {
|
|
190
|
+
index = (index - 1 + instances.length) % instances.length;
|
|
191
|
+
render();
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
case "down":
|
|
195
|
+
case "j": {
|
|
196
|
+
index = (index + 1) % instances.length;
|
|
197
|
+
render();
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
case "return": {
|
|
201
|
+
const target = instances[index];
|
|
202
|
+
killInstance(target);
|
|
203
|
+
instances = pruneRegistry();
|
|
204
|
+
if (instances.length === 0) {
|
|
205
|
+
render(c.green(INDENT + `\u2713 Stopped localhost:${target.port}. No instances left.`));
|
|
206
|
+
finish();
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
index = Math.min(index, instances.length - 1);
|
|
210
|
+
render(c.green(INDENT + `\u2713 Stopped localhost:${target.port}.`));
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
default: {
|
|
214
|
+
if (key.name === "q" || key.name === "escape" || key.ctrl && key.name === "c") {
|
|
215
|
+
render(c.gray(INDENT + "Bye \u{1F44B}"));
|
|
216
|
+
finish();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
stdin.on("keypress", onKey);
|
|
222
|
+
render();
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
function parseArgs(argv) {
|
|
226
|
+
const isFlag = (a) => a.startsWith("-");
|
|
227
|
+
const flagNames = new Set(argv.filter(isFlag).map((a) => a.split("=", 1)[0]));
|
|
228
|
+
const inputArgument = argv.find((a) => !isFlag(a));
|
|
229
|
+
const portArgument = argv.find((a) => a.startsWith("--port="));
|
|
230
|
+
const requestedPort = portArgument ? Number.parseInt(portArgument.split("=", 2)[1], 10) || 0 : 0;
|
|
231
|
+
return {
|
|
232
|
+
inputArg: inputArgument,
|
|
233
|
+
requestedPort,
|
|
234
|
+
wantBackground: flagNames.has("--background") || flagNames.has("-b"),
|
|
235
|
+
wantList: flagNames.has("--list") || flagNames.has("-l") || flagNames.has("--list-instances"),
|
|
236
|
+
// legacy alias
|
|
237
|
+
wantTear: flagNames.has("--tear") || flagNames.has("-t"),
|
|
238
|
+
isDetachedChild: flagNames.has("--__detached"),
|
|
239
|
+
// internal use only
|
|
240
|
+
wantHelp: flagNames.has("--help") || flagNames.has("-h")
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
function printHelp() {
|
|
244
|
+
banner();
|
|
245
|
+
line(c.bold("Usage"));
|
|
246
|
+
tree("blogkit-md <file-or-directory> [options]");
|
|
247
|
+
line();
|
|
248
|
+
line(c.bold("Options"));
|
|
249
|
+
tree(`${c.green("--port=<port>")} run on a specific port (default: random free port)`);
|
|
250
|
+
tree(`${c.green("-b, --background")} run the preview server detached in the background`);
|
|
251
|
+
tree(`${c.green("-t, --tear")} stop the instance already serving this path, then start fresh`);
|
|
252
|
+
tree(`${c.green("-l, --list")} interactively list & stop running instances`);
|
|
253
|
+
tree(`${c.green("-h, --help")} show this help`);
|
|
254
|
+
line();
|
|
255
|
+
line(c.gray("If a path is already being served, running it again just reopens it."));
|
|
256
|
+
line();
|
|
257
|
+
}
|
|
258
|
+
async function run(argv) {
|
|
259
|
+
const parsed = parseArgs(argv);
|
|
260
|
+
if (parsed.wantHelp) {
|
|
261
|
+
printHelp();
|
|
262
|
+
process.exit(0);
|
|
263
|
+
}
|
|
264
|
+
if (parsed.wantList) {
|
|
265
|
+
await listInstancesInteractive();
|
|
266
|
+
process.exit(0);
|
|
267
|
+
}
|
|
268
|
+
if (!parsed.inputArg) {
|
|
269
|
+
printHelp();
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
const inputPath = import_node_path.default.resolve(process.cwd(), parsed.inputArg);
|
|
273
|
+
let inputStat;
|
|
274
|
+
try {
|
|
275
|
+
inputStat = (0, import_node_fs.statSync)(inputPath);
|
|
276
|
+
} catch {
|
|
277
|
+
banner();
|
|
278
|
+
line(c.red("\u2717 Path does not exist"));
|
|
279
|
+
tree(c.dim(inputPath));
|
|
280
|
+
line();
|
|
281
|
+
process.exit(1);
|
|
282
|
+
}
|
|
283
|
+
const isDirectory = inputStat.isDirectory();
|
|
284
|
+
if (!parsed.isDetachedChild) {
|
|
285
|
+
const existing = findByDir(inputPath);
|
|
286
|
+
if (existing) {
|
|
287
|
+
if (parsed.wantTear) {
|
|
288
|
+
banner();
|
|
289
|
+
line(c.yellow("\u25B8 Tearing down the running instance"));
|
|
290
|
+
tree(
|
|
291
|
+
`${c.green("localhost:" + existing.port)} ${c.gray("pid " + existing.pid)} ${existing.background ? c.magenta("background") : c.gray("foreground")}`
|
|
292
|
+
);
|
|
293
|
+
killInstance(existing);
|
|
294
|
+
line(c.green(`\u2713 Stopped localhost:${existing.port}`));
|
|
295
|
+
line();
|
|
296
|
+
await new Promise((r) => setTimeout(r, 400));
|
|
297
|
+
} else {
|
|
298
|
+
const url = `http://localhost:${existing.port}`;
|
|
299
|
+
banner();
|
|
300
|
+
line(c.green("\u25B8 Already running \u2014 opening it in the browser"));
|
|
301
|
+
tree(`${c.bold("URL")} ${c.blue(url)}`);
|
|
302
|
+
tree(`${c.bold("Path")} ${c.dim(tilde(existing.dir))}`);
|
|
303
|
+
line();
|
|
304
|
+
line(c.gray("Restart it with ") + c.blue("--tear") + c.gray(", or list with ") + c.blue("--list"));
|
|
305
|
+
line();
|
|
306
|
+
openBrowser(url);
|
|
307
|
+
process.exit(0);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
const scriptPath = process.argv[1];
|
|
312
|
+
const packageRoot = import_node_path.default.dirname(import_node_path.default.dirname(scriptPath));
|
|
313
|
+
const nextBin = import_node_path.default.join(packageRoot, "node_modules/.bin/next");
|
|
314
|
+
if (parsed.wantBackground && !parsed.isDetachedChild) {
|
|
315
|
+
try {
|
|
316
|
+
const port = parsed.requestedPort || await getFreePort();
|
|
317
|
+
(0, import_node_fs.mkdirSync)(logDir(), { recursive: true });
|
|
318
|
+
const logFile = import_node_path.default.join(logDir(), `${port}.log`);
|
|
319
|
+
const out = (0, import_node_fs.openSync)(logFile, "a");
|
|
320
|
+
const child = (0, import_node_child_process.spawn)(
|
|
321
|
+
process.execPath,
|
|
322
|
+
[scriptPath, inputPath, `--port=${port}`, "--__detached"],
|
|
323
|
+
{ detached: true, stdio: ["ignore", out, out] }
|
|
324
|
+
);
|
|
325
|
+
child.unref();
|
|
326
|
+
banner();
|
|
327
|
+
line(c.green("\u25B8 Started in the background"));
|
|
328
|
+
tree(`${c.bold("URL")} ${c.blue("http://localhost:" + port)}`);
|
|
329
|
+
tree(`${c.bold("Path")} ${c.dim(tilde(inputPath))}`);
|
|
330
|
+
tree(`${c.bold("PID")} ${c.dim(String(child.pid))}`);
|
|
331
|
+
tree(`${c.bold("Log")} ${c.dim(tilde(logFile))}`);
|
|
332
|
+
line();
|
|
333
|
+
line(c.gray("Stop it with: ") + c.blue("blogkit-md --list"));
|
|
334
|
+
line();
|
|
335
|
+
} catch (error) {
|
|
336
|
+
banner();
|
|
337
|
+
line(c.red("\u2717 Failed to start in the background"));
|
|
338
|
+
tree(c.dim(String(error)));
|
|
339
|
+
line();
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
342
|
+
process.exit(0);
|
|
343
|
+
}
|
|
344
|
+
await startServer(inputPath, isDirectory, parsed, { nextBin, packageRoot });
|
|
47
345
|
}
|
|
48
|
-
var isDirectory = inputStat.isDirectory();
|
|
49
|
-
var clients = /* @__PURE__ */ new Set();
|
|
50
346
|
function getFreePort() {
|
|
51
347
|
return new Promise((resolve, reject) => {
|
|
52
348
|
const s = (0, import_node_http.createServer)();
|
|
53
349
|
s.listen(0, () => {
|
|
54
350
|
const port = s.address().port;
|
|
55
|
-
s.close((
|
|
351
|
+
s.close((error) => error ? reject(error) : resolve(port));
|
|
56
352
|
});
|
|
57
353
|
s.on("error", reject);
|
|
58
354
|
});
|
|
59
355
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
356
|
+
async function startServer(inputPath, isDirectory, parsed, paths) {
|
|
357
|
+
const clients = /* @__PURE__ */ new Set();
|
|
358
|
+
const sseServer = (0, import_node_http.createServer)((request, res) => {
|
|
359
|
+
res.writeHead(200, {
|
|
360
|
+
"Content-Type": "text/event-stream",
|
|
361
|
+
"Cache-Control": "no-cache",
|
|
362
|
+
"Connection": "keep-alive",
|
|
363
|
+
"Access-Control-Allow-Origin": "*"
|
|
364
|
+
});
|
|
365
|
+
res.write("data: connected\n\n");
|
|
366
|
+
clients.add(res);
|
|
367
|
+
request.on("close", () => clients.delete(res));
|
|
66
368
|
});
|
|
67
|
-
|
|
68
|
-
clients.add(res);
|
|
69
|
-
req.on("close", () => clients.delete(res));
|
|
70
|
-
});
|
|
71
|
-
sseServer.listen(0, async () => {
|
|
369
|
+
await new Promise((resolve) => sseServer.listen(0, resolve));
|
|
72
370
|
const ssePort = sseServer.address().port;
|
|
73
|
-
const nextPort = requestedPort || await getFreePort();
|
|
74
|
-
const
|
|
371
|
+
const nextPort = parsed.requestedPort || await getFreePort();
|
|
372
|
+
const nextEnvironment = {
|
|
75
373
|
...process.env,
|
|
76
374
|
...isDirectory ? { MARKDOWN_DIR: inputPath } : { MARKDOWN_FILE: inputPath },
|
|
77
375
|
SSE_PORT: String(ssePort)
|
|
78
376
|
};
|
|
79
377
|
const broadcastReload = () => {
|
|
80
|
-
for (const client of clients)
|
|
81
|
-
client.write("data: reload\n\n");
|
|
82
|
-
}
|
|
378
|
+
for (const client of clients) client.write("data: reload\n\n");
|
|
83
379
|
};
|
|
84
380
|
if (isDirectory) {
|
|
85
381
|
(0, import_node_fs.watch)(inputPath, { recursive: true }, (_, filename) => {
|
|
@@ -91,24 +387,71 @@ sseServer.listen(0, async () => {
|
|
|
91
387
|
if (filename === markdownFilename) broadcastReload();
|
|
92
388
|
});
|
|
93
389
|
}
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
390
|
+
const me = {
|
|
391
|
+
pid: process.pid,
|
|
392
|
+
port: nextPort,
|
|
393
|
+
ssePort,
|
|
394
|
+
dir: inputPath,
|
|
395
|
+
isDirectory,
|
|
396
|
+
background: parsed.isDetachedChild,
|
|
397
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
398
|
+
};
|
|
399
|
+
addInstance(me);
|
|
400
|
+
if (!parsed.isDetachedChild) {
|
|
401
|
+
banner();
|
|
402
|
+
line(c.gray("starting preview server for ") + c.blue(tilde(inputPath)) + c.gray(" \u2026"));
|
|
403
|
+
}
|
|
404
|
+
const child = (0, import_node_child_process.spawn)(paths.nextBin, ["start", "--port", String(nextPort)], {
|
|
405
|
+
cwd: paths.packageRoot,
|
|
406
|
+
env: nextEnvironment,
|
|
97
407
|
stdio: ["inherit", "pipe", "inherit"]
|
|
98
408
|
});
|
|
99
|
-
|
|
409
|
+
const shutdown = () => {
|
|
410
|
+
try {
|
|
411
|
+
child.kill("SIGTERM");
|
|
412
|
+
} catch {
|
|
413
|
+
}
|
|
414
|
+
try {
|
|
415
|
+
sseServer.close();
|
|
416
|
+
} catch {
|
|
417
|
+
}
|
|
418
|
+
removeInstance(process.pid);
|
|
419
|
+
};
|
|
420
|
+
process.on("exit", shutdown);
|
|
421
|
+
process.on("SIGINT", () => process.exit(0));
|
|
422
|
+
process.on("SIGTERM", () => process.exit(0));
|
|
423
|
+
let ready = false;
|
|
100
424
|
child.stdout?.on("data", (chunk) => {
|
|
101
|
-
|
|
102
|
-
if (!browserOpened) {
|
|
425
|
+
if (!ready) {
|
|
103
426
|
const match = chunk.toString().match(/http:\/\/localhost:\d+/);
|
|
104
427
|
if (match) {
|
|
105
|
-
|
|
106
|
-
|
|
428
|
+
ready = true;
|
|
429
|
+
const url = `http://localhost:${nextPort}`;
|
|
430
|
+
if (!parsed.isDetachedChild) {
|
|
431
|
+
line();
|
|
432
|
+
line(c.green("\u2713 Ready"));
|
|
433
|
+
tree(`${c.bold("URL")} ${c.blue(url)}`);
|
|
434
|
+
tree(`${c.bold("Path")} ${c.dim(tilde(inputPath))}`);
|
|
435
|
+
line();
|
|
436
|
+
line(c.gray("live reload on save \xB7 Ctrl-C to stop"));
|
|
437
|
+
line();
|
|
438
|
+
}
|
|
439
|
+
openBrowser(url);
|
|
107
440
|
}
|
|
108
441
|
}
|
|
109
442
|
});
|
|
110
443
|
child.on("exit", (code) => {
|
|
111
|
-
|
|
444
|
+
try {
|
|
445
|
+
sseServer.close();
|
|
446
|
+
} catch {
|
|
447
|
+
}
|
|
448
|
+
removeInstance(process.pid);
|
|
112
449
|
process.exit(code ?? 0);
|
|
113
450
|
});
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// scripts/blogkit-md.ts
|
|
454
|
+
run(process.argv.slice(2)).catch((error) => {
|
|
455
|
+
console.error(error);
|
|
456
|
+
process.exit(1);
|
|
114
457
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@san-siva/blogkit-md-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"description": "CLI tool to preview markdown files as blogkit-md blog posts",
|
|
5
5
|
"bin": {
|
|
6
6
|
"blogkit-md": "./bin/blogkit-md"
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
"build": "rm -rf .next && tsup && next build",
|
|
14
14
|
"prepublishOnly": "npm ci && npm run build",
|
|
15
15
|
"lint": "eslint . --config eslint.config.ts",
|
|
16
|
-
"fix": "eslint . --config eslint.config.ts --fix"
|
|
16
|
+
"fix": "eslint . --config eslint.config.ts --fix",
|
|
17
|
+
"pretest": "tsup",
|
|
18
|
+
"test": "node --test scripts/cli.test.ts"
|
|
17
19
|
},
|
|
18
20
|
"dependencies": {
|
|
19
21
|
"@san-siva/blogkit": "^1.1.38",
|
|
@@ -24,11 +26,24 @@
|
|
|
24
26
|
"react-dom": "^19.0.0"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
|
29
|
+
"@eslint/js": "^9.39.4",
|
|
27
30
|
"@types/node": "^22",
|
|
28
|
-
"tsup": "^8.0.0",
|
|
29
31
|
"@types/react": "^19",
|
|
30
32
|
"@types/react-dom": "^19",
|
|
31
|
-
"
|
|
33
|
+
"eslint": "^9.39.4",
|
|
34
|
+
"eslint-config-prettier": "^10.1.8",
|
|
35
|
+
"eslint-import-resolver-typescript": "^4.4.5",
|
|
36
|
+
"eslint-plugin-import": "^2.32.0",
|
|
37
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
38
|
+
"eslint-plugin-no-await-in-promise": "^3.0.1",
|
|
39
|
+
"eslint-plugin-react": "^7.37.5",
|
|
40
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
41
|
+
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
42
|
+
"eslint-plugin-unicorn": "^65.0.0",
|
|
43
|
+
"jiti": "^2.7.0",
|
|
44
|
+
"tsup": "^8.0.0",
|
|
45
|
+
"typescript": "^5.0.0",
|
|
46
|
+
"typescript-eslint": "^8.60.1"
|
|
32
47
|
},
|
|
33
48
|
"license": "MIT",
|
|
34
49
|
"preferGlobal": true,
|
|
File without changes
|
/package/.next/static/{k_detxuW-GmsRteYh4x8e → N6e_l60Njhp5bsxU4aIBS}/_clientMiddlewareManifest.js
RENAMED
|
File without changes
|
|
File without changes
|