markmap-cli 0.18.4 → 0.18.5-alpha.6
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/client/index.d.ts +1 -0
- package/dist/client.css +11 -0
- package/dist/client.js +93 -0
- package/dist/dev-server.d.ts +20 -4
- package/dist/index.d.ts +8 -6
- package/dist/index.js +211 -171
- package/dist/types.d.ts +0 -4
- package/dist/util.d.ts +1 -0
- package/package.json +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import './style.css';
|
package/dist/client.css
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
.markmap-highlight-area {
|
|
2
|
+
--mm-highlight-scale: 1;
|
|
3
|
+
position: absolute;
|
|
4
|
+
width: var(--mm-highlight-width);
|
|
5
|
+
height: var(--mm-highlight-height);
|
|
6
|
+
left: var(--mm-highlight-x);
|
|
7
|
+
top: var(--mm-highlight-y);
|
|
8
|
+
z-index: -1;
|
|
9
|
+
background: #ff02;
|
|
10
|
+
transform: scale(var(--mm-highlight-scale));
|
|
11
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const { mm, markmap } = window;
|
|
2
|
+
const { cliOptions } = markmap;
|
|
3
|
+
const key = new URLSearchParams(window.location.search).get("key") || "";
|
|
4
|
+
let ts = 0;
|
|
5
|
+
let root;
|
|
6
|
+
let active;
|
|
7
|
+
const activeNodeOptions = {};
|
|
8
|
+
const highlightEl = document.createElement("div");
|
|
9
|
+
highlightEl.className = "markmap-highlight-area";
|
|
10
|
+
checkData();
|
|
11
|
+
checkHighlight();
|
|
12
|
+
async function checkData() {
|
|
13
|
+
try {
|
|
14
|
+
const resp = await fetch(`/~data?key=${key}&ts=${ts}`);
|
|
15
|
+
const res = await resp.json();
|
|
16
|
+
if (res.ts && res.ts > ts && res.result) {
|
|
17
|
+
let frontmatter;
|
|
18
|
+
({ root, frontmatter } = res.result);
|
|
19
|
+
mm.setOptions(markmap.deriveOptions(frontmatter == null ? void 0 : frontmatter.markmap));
|
|
20
|
+
await mm.setData(root);
|
|
21
|
+
if (!ts) await mm.fit();
|
|
22
|
+
ts = res.ts;
|
|
23
|
+
}
|
|
24
|
+
if (root && res.line != null) {
|
|
25
|
+
await setCursor({ line: res.line });
|
|
26
|
+
}
|
|
27
|
+
} finally {
|
|
28
|
+
setTimeout(checkData, 3e3);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function findActiveNode({
|
|
32
|
+
line,
|
|
33
|
+
autoExpand = true
|
|
34
|
+
}) {
|
|
35
|
+
function dfs(node, ancestors = []) {
|
|
36
|
+
var _a, _b, _c;
|
|
37
|
+
const [start, end] = ((_b = (_a = node.payload) == null ? void 0 : _a.lines) == null ? void 0 : _b.split(",").map((s) => +s)) || [];
|
|
38
|
+
if (start >= 0 && start <= line && line < end) {
|
|
39
|
+
best = node;
|
|
40
|
+
bestAncestors = ancestors;
|
|
41
|
+
}
|
|
42
|
+
ancestors = [...ancestors, node];
|
|
43
|
+
(_c = node.children) == null ? void 0 : _c.forEach((child) => {
|
|
44
|
+
dfs(child, ancestors);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
let best;
|
|
48
|
+
let bestAncestors = [];
|
|
49
|
+
dfs(root);
|
|
50
|
+
let needRerender = false;
|
|
51
|
+
if (autoExpand) {
|
|
52
|
+
bestAncestors.forEach((node) => {
|
|
53
|
+
var _a;
|
|
54
|
+
if ((_a = node.payload) == null ? void 0 : _a.fold) {
|
|
55
|
+
node.payload.fold = 0;
|
|
56
|
+
needRerender = true;
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return best && { node: best, needRerender };
|
|
61
|
+
}
|
|
62
|
+
async function setCursor(options) {
|
|
63
|
+
const result = root && findActiveNode(options);
|
|
64
|
+
if (!result) return;
|
|
65
|
+
const { node, needRerender } = result;
|
|
66
|
+
if (needRerender) await mm.renderData();
|
|
67
|
+
if (node) highlightNode(node);
|
|
68
|
+
}
|
|
69
|
+
async function highlightNode(node) {
|
|
70
|
+
var _a;
|
|
71
|
+
await mm[activeNodeOptions.placement === "center" ? "centerNode" : "ensureVisible"](node, {
|
|
72
|
+
bottom: cliOptions.toolbar ? 80 : 0
|
|
73
|
+
});
|
|
74
|
+
const g = (_a = mm.findElement(node)) == null ? void 0 : _a.g;
|
|
75
|
+
const el = g == null ? void 0 : g.querySelector("foreignObject");
|
|
76
|
+
active = el && { el, node };
|
|
77
|
+
}
|
|
78
|
+
function checkHighlight() {
|
|
79
|
+
if (!active) {
|
|
80
|
+
highlightEl.remove();
|
|
81
|
+
} else {
|
|
82
|
+
const rect = active.el.getBoundingClientRect();
|
|
83
|
+
const padding = 4;
|
|
84
|
+
const { width } = active.node.state.rect;
|
|
85
|
+
const scale = (width + padding * 2) / width;
|
|
86
|
+
highlightEl.setAttribute(
|
|
87
|
+
"style",
|
|
88
|
+
`--mm-highlight-x:${rect.x}px;--mm-highlight-y:${rect.y}px;--mm-highlight-width:${rect.width}px;--mm-highlight-height:${rect.height}px;--mm-highlight-scale:${scale}`
|
|
89
|
+
);
|
|
90
|
+
if (!highlightEl.parentNode) document.body.append(highlightEl);
|
|
91
|
+
}
|
|
92
|
+
requestAnimationFrame(checkHighlight);
|
|
93
|
+
}
|
package/dist/dev-server.d.ts
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
|
+
import { ServerType } from '@hono/node-server';
|
|
2
|
+
import { Transformer } from 'markmap-lib';
|
|
3
|
+
import { AddressInfo } from 'net';
|
|
1
4
|
import { IContentProvider, IDevelopOptions } from './types';
|
|
2
|
-
export declare
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
export declare class MarkmapDevServer {
|
|
6
|
+
options: IDevelopOptions;
|
|
7
|
+
providers: Record<string, IContentProvider>;
|
|
8
|
+
private transformer;
|
|
9
|
+
private html;
|
|
10
|
+
serverInfo: {
|
|
11
|
+
server: ServerType;
|
|
12
|
+
address: AddressInfo;
|
|
13
|
+
} | null;
|
|
14
|
+
constructor(options: IDevelopOptions, transformer?: Transformer);
|
|
15
|
+
private _buildHtml;
|
|
16
|
+
setup(): Promise<void>;
|
|
17
|
+
shutdown(): Promise<void>;
|
|
18
|
+
addProvider(filePath?: string): string;
|
|
19
|
+
delProvider(filePath?: string): void;
|
|
20
|
+
}
|
|
21
|
+
export declare function develop(options: IDevelopOptions): Promise<MarkmapDevServer>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { type IMarkmapCreateOptions } from 'markmap-lib';
|
|
2
|
-
import { config } from './util';
|
|
3
|
-
import { IDevelopOptions } from './types';
|
|
4
|
-
import { develop } from './dev-server';
|
|
5
2
|
import { fetchAssets } from './fetch-assets';
|
|
6
|
-
|
|
3
|
+
import { IDevelopOptions } from './types';
|
|
4
|
+
import { config } from './util';
|
|
5
|
+
export * from './dev-server';
|
|
7
6
|
export * from './types';
|
|
8
|
-
export { config,
|
|
9
|
-
export
|
|
7
|
+
export { config, fetchAssets };
|
|
8
|
+
export * as markmap from 'markmap-lib';
|
|
9
|
+
export declare function createMarkmap(options: IMarkmapCreateOptions & IDevelopOptions & {
|
|
10
|
+
open: boolean;
|
|
11
|
+
}): Promise<void>;
|
|
10
12
|
export declare function main(): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -1,77 +1,22 @@
|
|
|
1
|
-
import { readFile, stat, mkdir, writeFile } from "fs/promises";
|
|
2
|
-
import { dirname, join, resolve } from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
1
|
import { Command } from "commander";
|
|
5
|
-
import
|
|
6
|
-
import updateNotifier from "update-notifier";
|
|
7
|
-
import { readPackageUp } from "read-package-up";
|
|
2
|
+
import { readFile, stat, mkdir, writeFile } from "fs/promises";
|
|
8
3
|
import { buildCSSItem, buildJSItem, defer } from "markmap-common";
|
|
9
4
|
import { Transformer } from "markmap-lib";
|
|
10
|
-
|
|
5
|
+
import * as markmapLib from "markmap-lib";
|
|
11
6
|
import { fillTemplate, baseJsPaths } from "markmap-render";
|
|
7
|
+
import open from "open";
|
|
8
|
+
import { dirname, join, resolve, basename } from "path";
|
|
9
|
+
import { readPackageUp } from "read-package-up";
|
|
10
|
+
import updateNotifier from "update-notifier";
|
|
12
11
|
import { serve } from "@hono/node-server";
|
|
13
12
|
import { watch } from "chokidar";
|
|
13
|
+
import { createHash } from "crypto";
|
|
14
14
|
import { EventEmitter } from "events";
|
|
15
15
|
import { createReadStream, createWriteStream } from "fs";
|
|
16
16
|
import { Hono } from "hono";
|
|
17
|
+
import { fileURLToPath } from "url";
|
|
17
18
|
import { Readable } from "stream";
|
|
18
19
|
import { finished } from "stream/promises";
|
|
19
|
-
const TOOLBAR_VERSION = "0.18.4";
|
|
20
|
-
const TOOLBAR_CSS = `markmap-toolbar@${TOOLBAR_VERSION}/dist/style.css`;
|
|
21
|
-
const TOOLBAR_JS = `markmap-toolbar@${TOOLBAR_VERSION}/dist/index.js`;
|
|
22
|
-
const currentDir = dirname(fileURLToPath(import.meta.url));
|
|
23
|
-
const ASSETS_PREFIX = "/assets/";
|
|
24
|
-
const renderToolbar = () => {
|
|
25
|
-
const { markmap, mm } = window;
|
|
26
|
-
const toolbar = new markmap.Toolbar();
|
|
27
|
-
toolbar.attach(mm);
|
|
28
|
-
const el = toolbar.render();
|
|
29
|
-
el.setAttribute("style", "position:absolute;bottom:20px;right:20px");
|
|
30
|
-
document.body.append(el);
|
|
31
|
-
};
|
|
32
|
-
function addToolbar(urlBuilder, assets) {
|
|
33
|
-
return {
|
|
34
|
-
styles: [
|
|
35
|
-
...assets.styles || [],
|
|
36
|
-
...[TOOLBAR_CSS].map((path) => urlBuilder.getFullUrl(path)).map((path) => buildCSSItem(path))
|
|
37
|
-
],
|
|
38
|
-
scripts: [
|
|
39
|
-
...assets.scripts || [],
|
|
40
|
-
...[TOOLBAR_JS].map((path) => urlBuilder.getFullUrl(path)).map((path) => buildJSItem(path)),
|
|
41
|
-
{
|
|
42
|
-
type: "iife",
|
|
43
|
-
data: {
|
|
44
|
-
fn: (r) => {
|
|
45
|
-
setTimeout(r);
|
|
46
|
-
},
|
|
47
|
-
getParams: () => [renderToolbar]
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function localProvider(path) {
|
|
54
|
-
return `${ASSETS_PREFIX}${path}`;
|
|
55
|
-
}
|
|
56
|
-
function createStreamBody(stream) {
|
|
57
|
-
const body = new ReadableStream({
|
|
58
|
-
start(controller) {
|
|
59
|
-
stream.on("data", (chunk) => {
|
|
60
|
-
controller.enqueue(chunk);
|
|
61
|
-
});
|
|
62
|
-
stream.on("end", () => {
|
|
63
|
-
controller.close();
|
|
64
|
-
});
|
|
65
|
-
},
|
|
66
|
-
cancel() {
|
|
67
|
-
stream.destroy();
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
return body;
|
|
71
|
-
}
|
|
72
|
-
const config = {
|
|
73
|
-
assetsDir: `${currentDir}${ASSETS_PREFIX}`
|
|
74
|
-
};
|
|
75
20
|
var getMimeType = (filename, mimes = baseMimes) => {
|
|
76
21
|
const regexp = /\.([a-zA-Z0-9]+?)$/;
|
|
77
22
|
const match = filename.match(regexp);
|
|
@@ -79,7 +24,7 @@ var getMimeType = (filename, mimes = baseMimes) => {
|
|
|
79
24
|
return;
|
|
80
25
|
}
|
|
81
26
|
let mimeType = mimes[match[1]];
|
|
82
|
-
if (mimeType && mimeType.startsWith("text")
|
|
27
|
+
if (mimeType && mimeType.startsWith("text")) {
|
|
83
28
|
mimeType += "; charset=utf-8";
|
|
84
29
|
}
|
|
85
30
|
return mimeType;
|
|
@@ -142,6 +87,63 @@ var _baseMimes = {
|
|
|
142
87
|
glb: "model/gltf-binary"
|
|
143
88
|
};
|
|
144
89
|
var baseMimes = _baseMimes;
|
|
90
|
+
const TOOLBAR_VERSION = "0.18.5-alpha.6+cea75c9";
|
|
91
|
+
const TOOLBAR_CSS = `markmap-toolbar@${TOOLBAR_VERSION}/dist/style.css`;
|
|
92
|
+
const TOOLBAR_JS = `markmap-toolbar@${TOOLBAR_VERSION}/dist/index.js`;
|
|
93
|
+
const distDir = dirname(fileURLToPath(import.meta.url));
|
|
94
|
+
const ASSETS_PREFIX = "/assets/";
|
|
95
|
+
const renderToolbar = () => {
|
|
96
|
+
const { markmap, mm } = window;
|
|
97
|
+
const toolbar = new markmap.Toolbar();
|
|
98
|
+
toolbar.attach(mm);
|
|
99
|
+
const el = toolbar.render();
|
|
100
|
+
el.setAttribute("style", "position:absolute;bottom:20px;right:20px");
|
|
101
|
+
document.body.append(el);
|
|
102
|
+
};
|
|
103
|
+
function addToolbar(urlBuilder, assets) {
|
|
104
|
+
return {
|
|
105
|
+
styles: [
|
|
106
|
+
...assets.styles || [],
|
|
107
|
+
...[TOOLBAR_CSS].map((path) => urlBuilder.getFullUrl(path)).map((path) => buildCSSItem(path))
|
|
108
|
+
],
|
|
109
|
+
scripts: [
|
|
110
|
+
...assets.scripts || [],
|
|
111
|
+
...[TOOLBAR_JS].map((path) => urlBuilder.getFullUrl(path)).map((path) => buildJSItem(path)),
|
|
112
|
+
{
|
|
113
|
+
type: "iife",
|
|
114
|
+
data: {
|
|
115
|
+
fn: (r) => {
|
|
116
|
+
setTimeout(r);
|
|
117
|
+
},
|
|
118
|
+
getParams: () => [renderToolbar]
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function localProvider(path) {
|
|
125
|
+
return `${ASSETS_PREFIX}${path}`;
|
|
126
|
+
}
|
|
127
|
+
function createStreamBody(stream) {
|
|
128
|
+
const body = new ReadableStream({
|
|
129
|
+
start(controller) {
|
|
130
|
+
stream.on("data", (chunk) => {
|
|
131
|
+
controller.enqueue(chunk);
|
|
132
|
+
});
|
|
133
|
+
stream.on("end", () => {
|
|
134
|
+
controller.close();
|
|
135
|
+
});
|
|
136
|
+
},
|
|
137
|
+
cancel() {
|
|
138
|
+
stream.destroy();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
return body;
|
|
142
|
+
}
|
|
143
|
+
const config = {
|
|
144
|
+
distDir,
|
|
145
|
+
assetsDir: `${distDir}${ASSETS_PREFIX}`
|
|
146
|
+
};
|
|
145
147
|
function sequence(fn) {
|
|
146
148
|
let promise;
|
|
147
149
|
return () => {
|
|
@@ -158,6 +160,7 @@ class BufferContentProvider {
|
|
|
158
160
|
this.ts = 0;
|
|
159
161
|
this.content = "";
|
|
160
162
|
this.line = -1;
|
|
163
|
+
this.key = "";
|
|
161
164
|
this.events.on("content", () => {
|
|
162
165
|
this.feed({
|
|
163
166
|
ts: this.ts,
|
|
@@ -205,16 +208,17 @@ class BufferContentProvider {
|
|
|
205
208
|
}
|
|
206
209
|
}
|
|
207
210
|
class FileSystemProvider extends BufferContentProvider {
|
|
208
|
-
constructor(
|
|
211
|
+
constructor(key, filePath) {
|
|
209
212
|
super();
|
|
210
|
-
this.
|
|
211
|
-
this.
|
|
213
|
+
this.key = key;
|
|
214
|
+
this.filePath = filePath;
|
|
215
|
+
this.watcher = watch(filePath).on(
|
|
212
216
|
"all",
|
|
213
217
|
sequence(() => this.update())
|
|
214
218
|
);
|
|
215
219
|
}
|
|
216
220
|
async update() {
|
|
217
|
-
const content = await readFile(this.
|
|
221
|
+
const content = await readFile(this.filePath, "utf8");
|
|
218
222
|
this.setContent(content);
|
|
219
223
|
}
|
|
220
224
|
dispose() {
|
|
@@ -222,114 +226,137 @@ class FileSystemProvider extends BufferContentProvider {
|
|
|
222
226
|
this.watcher.close();
|
|
223
227
|
}
|
|
224
228
|
}
|
|
225
|
-
function
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
229
|
+
function sha256(input) {
|
|
230
|
+
return createHash("sha256").update(input, "utf8").digest("hex").slice(0, 7);
|
|
231
|
+
}
|
|
232
|
+
async function sendStatic(c, realpath) {
|
|
233
|
+
try {
|
|
234
|
+
const result = await stat(realpath);
|
|
235
|
+
if (!result.isFile()) throw new Error("File not found");
|
|
236
|
+
} catch {
|
|
237
|
+
return c.body("File not found", 404);
|
|
238
|
+
}
|
|
239
|
+
const stream = createReadStream(realpath);
|
|
240
|
+
const type = getMimeType(realpath);
|
|
241
|
+
if (type) c.header("content-type", type);
|
|
242
|
+
return c.body(createStreamBody(stream));
|
|
243
|
+
}
|
|
244
|
+
class MarkmapDevServer {
|
|
245
|
+
constructor(options, transformer) {
|
|
246
|
+
this.options = options;
|
|
247
|
+
this.providers = {};
|
|
248
|
+
this.serverInfo = null;
|
|
249
|
+
this.transformer = transformer || new Transformer();
|
|
250
|
+
this.html = this._buildHtml();
|
|
251
|
+
}
|
|
252
|
+
_buildHtml() {
|
|
253
|
+
let assets = this.transformer.getAssets();
|
|
254
|
+
if (this.options.toolbar)
|
|
255
|
+
assets = addToolbar(this.transformer.urlBuilder, assets);
|
|
256
|
+
assets = {
|
|
257
|
+
styles: [
|
|
258
|
+
...assets.styles || [],
|
|
259
|
+
{
|
|
260
|
+
type: "stylesheet",
|
|
261
|
+
data: {
|
|
262
|
+
href: "/~client.css"
|
|
263
|
+
}
|
|
242
264
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
265
|
+
],
|
|
266
|
+
scripts: [
|
|
267
|
+
...assets.scripts || [],
|
|
268
|
+
{
|
|
269
|
+
type: "iife",
|
|
270
|
+
data: {
|
|
271
|
+
fn: (options) => {
|
|
272
|
+
window.markmap.cliOptions = options;
|
|
273
|
+
},
|
|
274
|
+
getParams: () => [this.options]
|
|
275
|
+
}
|
|
247
276
|
}
|
|
248
|
-
|
|
249
|
-
|
|
277
|
+
]
|
|
278
|
+
};
|
|
279
|
+
const html = fillTemplate(null, assets, {
|
|
280
|
+
urlBuilder: this.transformer.urlBuilder
|
|
281
|
+
}) + '<script src="/~client.js"><\/script>';
|
|
282
|
+
return html;
|
|
283
|
+
}
|
|
284
|
+
async setup() {
|
|
285
|
+
if (this.serverInfo) throw new Error("Server already set up");
|
|
286
|
+
const app = new Hono();
|
|
287
|
+
app.get("/", (c) => c.html(this.html));
|
|
288
|
+
app.get("/~data", async (c) => {
|
|
289
|
+
const key = c.req.query("key") || "";
|
|
290
|
+
const provider = this.providers[key];
|
|
291
|
+
if (!provider) return c.json({}, 404);
|
|
292
|
+
const ts = +(c.req.query("ts") || "") || 0;
|
|
293
|
+
const update = await provider.getUpdate(ts);
|
|
294
|
+
const result = update.content == null ? null : this.transformer.transform(update.content || "");
|
|
295
|
+
return c.json({ ts: update.ts, result, line: update.line });
|
|
296
|
+
});
|
|
297
|
+
app.post("/~api", async (c) => {
|
|
298
|
+
var _a;
|
|
299
|
+
const key = c.req.query("key") || "";
|
|
300
|
+
const provider = this.providers[key];
|
|
301
|
+
if (!provider) return c.json({}, 404);
|
|
302
|
+
const { cmd, args } = await c.req.json();
|
|
303
|
+
await ((_a = provider[cmd]) == null ? void 0 : _a.call(provider, ...args));
|
|
304
|
+
return c.body(null, 204);
|
|
305
|
+
});
|
|
306
|
+
const { distDir: distDir2, assetsDir } = config;
|
|
307
|
+
app.get("/~client.*", async (c) => {
|
|
308
|
+
const realpath = join(distDir2, c.req.path.slice(2));
|
|
309
|
+
return sendStatic(c, realpath);
|
|
310
|
+
});
|
|
311
|
+
app.get(`${ASSETS_PREFIX}*`, async (c) => {
|
|
312
|
+
const relpath = c.req.path.slice(ASSETS_PREFIX.length);
|
|
313
|
+
const realpath = join(assetsDir, relpath);
|
|
314
|
+
return sendStatic(c, realpath);
|
|
315
|
+
});
|
|
316
|
+
const deferred = defer();
|
|
317
|
+
const server = serve(
|
|
318
|
+
{
|
|
319
|
+
fetch: app.fetch,
|
|
320
|
+
port: this.options.port
|
|
321
|
+
},
|
|
322
|
+
deferred.resolve
|
|
250
323
|
);
|
|
324
|
+
const address = await deferred.promise;
|
|
325
|
+
this.serverInfo = {
|
|
326
|
+
server,
|
|
327
|
+
address
|
|
328
|
+
};
|
|
251
329
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
(_c = node.children) == null ? void 0 : _c.forEach(dfs);
|
|
263
|
-
}
|
|
330
|
+
async shutdown() {
|
|
331
|
+
if (!this.serverInfo) throw new Error("Server is not set up yet");
|
|
332
|
+
const deferred = defer();
|
|
333
|
+
this.serverInfo.server.close((err) => {
|
|
334
|
+
if (err) deferred.reject();
|
|
335
|
+
else deferred.resolve();
|
|
336
|
+
});
|
|
337
|
+
await deferred.promise;
|
|
338
|
+
this.serverInfo = null;
|
|
264
339
|
}
|
|
265
|
-
|
|
266
|
-
async function setUpServer(transformer, provider, options) {
|
|
267
|
-
let assets = transformer.getAssets();
|
|
268
|
-
if (options.toolbar) assets = addToolbar(transformer.urlBuilder, assets);
|
|
269
|
-
const html = `${fillTemplate(null, assets, {
|
|
270
|
-
urlBuilder: transformer.urlBuilder
|
|
271
|
-
})}<script>(${startServer.toString()})(${options.toolbar ? 60 : 0})<\/script>`;
|
|
272
|
-
const app = new Hono();
|
|
273
|
-
app.get("/", (c) => c.html(html));
|
|
274
|
-
app.get("/~data", async (c) => {
|
|
275
|
-
const update = await provider.getUpdate(+(c.req.query("ts") || 0));
|
|
276
|
-
const result = update.content == null ? null : transformer.transform(update.content || "");
|
|
277
|
-
return c.json({ ts: update.ts, result, line: update.line });
|
|
278
|
-
});
|
|
279
|
-
app.post("/~api", async (c) => {
|
|
340
|
+
addProvider(filePath) {
|
|
280
341
|
var _a;
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
if (!result.isFile()) throw new Error("File not found");
|
|
292
|
-
} catch {
|
|
293
|
-
return c.body("File not found", 404);
|
|
294
|
-
}
|
|
295
|
-
const stream = createReadStream(realpath);
|
|
296
|
-
const type = getMimeType(relpath);
|
|
297
|
-
if (type) c.header("content-type", type);
|
|
298
|
-
return c.body(createStreamBody(stream));
|
|
299
|
-
});
|
|
300
|
-
const server = serve(
|
|
301
|
-
{
|
|
302
|
-
fetch: app.fetch,
|
|
303
|
-
port: options.port
|
|
304
|
-
},
|
|
305
|
-
(info) => {
|
|
306
|
-
const { port } = info;
|
|
307
|
-
console.info(`Listening at http://localhost:${port}`);
|
|
308
|
-
if (options.open) open(`http://localhost:${port}`);
|
|
309
|
-
}
|
|
310
|
-
);
|
|
311
|
-
let closing;
|
|
312
|
-
return {
|
|
313
|
-
provider,
|
|
314
|
-
close() {
|
|
315
|
-
if (!closing) {
|
|
316
|
-
closing = new Promise(
|
|
317
|
-
(resolve2, reject) => server.close((err) => {
|
|
318
|
-
if (err) reject(err);
|
|
319
|
-
else resolve2();
|
|
320
|
-
})
|
|
321
|
-
);
|
|
322
|
-
}
|
|
323
|
-
return closing;
|
|
324
|
-
}
|
|
325
|
-
};
|
|
342
|
+
filePath = filePath && resolve(filePath);
|
|
343
|
+
const key = filePath ? sha256(filePath) : "";
|
|
344
|
+
(_a = this.providers)[key] || (_a[key] = filePath ? new FileSystemProvider(key, filePath) : new BufferContentProvider());
|
|
345
|
+
return key;
|
|
346
|
+
}
|
|
347
|
+
delProvider(filePath) {
|
|
348
|
+
filePath = filePath && resolve(filePath);
|
|
349
|
+
const key = filePath ? sha256(filePath) : "";
|
|
350
|
+
delete this.providers[key];
|
|
351
|
+
}
|
|
326
352
|
}
|
|
327
|
-
async function develop(
|
|
353
|
+
async function develop(options) {
|
|
328
354
|
const transformer = new Transformer();
|
|
329
355
|
transformer.urlBuilder.setProvider("local", localProvider);
|
|
330
356
|
transformer.urlBuilder.provider = "local";
|
|
331
|
-
const
|
|
332
|
-
|
|
357
|
+
const devServer = new MarkmapDevServer(options);
|
|
358
|
+
await devServer.setup();
|
|
359
|
+
return devServer;
|
|
333
360
|
}
|
|
334
361
|
const providerName = "local-hook";
|
|
335
362
|
async function fetchAssets(assetsDir = config.assetsDir) {
|
|
@@ -339,6 +366,12 @@ async function fetchAssets(assetsDir = config.assetsDir) {
|
|
|
339
366
|
transformer.urlBuilder.setProvider(providerName, localProvider);
|
|
340
367
|
transformer.urlBuilder.provider = providerName;
|
|
341
368
|
let assets = transformer.getAssets();
|
|
369
|
+
const resources = transformer.plugins.flatMap(
|
|
370
|
+
(plugin) => {
|
|
371
|
+
var _a2;
|
|
372
|
+
return ((_a2 = plugin.config) == null ? void 0 : _a2.resources) || [];
|
|
373
|
+
}
|
|
374
|
+
);
|
|
342
375
|
assets = addToolbar(transformer.urlBuilder, assets);
|
|
343
376
|
delete transformer.urlBuilder.providers[providerName];
|
|
344
377
|
transformer.urlBuilder.provider = provider;
|
|
@@ -350,7 +383,7 @@ async function fetchAssets(assetsDir = config.assetsDir) {
|
|
|
350
383
|
(item) => item.type === "stylesheet" && item.data.href || ""
|
|
351
384
|
)) || []
|
|
352
385
|
].filter((url) => url.startsWith(ASSETS_PREFIX)).map((url) => url.slice(ASSETS_PREFIX.length));
|
|
353
|
-
const paths = [...baseJsPaths, ...pluginPaths];
|
|
386
|
+
const paths = [...baseJsPaths, ...pluginPaths, ...resources];
|
|
354
387
|
let findingProvider;
|
|
355
388
|
const findProvider = () => {
|
|
356
389
|
findingProvider || (findingProvider = transformer.urlBuilder.getFastestProvider());
|
|
@@ -456,7 +489,7 @@ async function createMarkmap(options) {
|
|
|
456
489
|
async function main() {
|
|
457
490
|
var _a;
|
|
458
491
|
const pkg = (_a = await readPackageUp({
|
|
459
|
-
cwd:
|
|
492
|
+
cwd: import.meta.url
|
|
460
493
|
})) == null ? void 0 : _a.packageJson;
|
|
461
494
|
if (!pkg) throw new Error("package.json not found");
|
|
462
495
|
const notifier = updateNotifier({ pkg });
|
|
@@ -475,11 +508,16 @@ async function main() {
|
|
|
475
508
|
const content = await readFile(input, "utf8");
|
|
476
509
|
const output = cmd.output || `${input.replace(/\.\w*$/, "")}.html`;
|
|
477
510
|
if (cmd.watch) {
|
|
478
|
-
await develop(
|
|
479
|
-
open: cmd.open,
|
|
511
|
+
const devServer = await develop({
|
|
480
512
|
toolbar: cmd.toolbar,
|
|
481
513
|
offline
|
|
482
514
|
});
|
|
515
|
+
const address = devServer.serverInfo.address;
|
|
516
|
+
const key = devServer.addProvider(input);
|
|
517
|
+
const filename = basename(input);
|
|
518
|
+
const url = `http://localhost:${address.port}/?key=${key}&filename=${filename}`;
|
|
519
|
+
console.log(`Listening at ${url}`);
|
|
520
|
+
if (cmd.open) open(url);
|
|
483
521
|
} else {
|
|
484
522
|
await createMarkmap({
|
|
485
523
|
content,
|
|
@@ -493,9 +531,11 @@ async function main() {
|
|
|
493
531
|
program.parse(process.argv);
|
|
494
532
|
}
|
|
495
533
|
export {
|
|
534
|
+
MarkmapDevServer,
|
|
496
535
|
config,
|
|
497
536
|
createMarkmap,
|
|
498
537
|
develop,
|
|
499
538
|
fetchAssets,
|
|
500
|
-
main
|
|
539
|
+
main,
|
|
540
|
+
markmapLib as markmap
|
|
501
541
|
};
|
package/dist/types.d.ts
CHANGED
package/dist/util.d.ts
CHANGED
|
@@ -6,5 +6,6 @@ export declare function addToolbar(urlBuilder: UrlBuilder, assets: IAssets): IAs
|
|
|
6
6
|
export declare function localProvider(path: string): string;
|
|
7
7
|
export declare function createStreamBody(stream: ReadStream): ReadableStream<any>;
|
|
8
8
|
export declare const config: {
|
|
9
|
+
distDir: string;
|
|
9
10
|
assetsDir: string;
|
|
10
11
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markmap-cli",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.5-alpha.6+cea75c9",
|
|
4
4
|
"description": "Create markmaps from CLI",
|
|
5
5
|
"author": "Gerald <gera2ld@live.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -49,14 +49,14 @@
|
|
|
49
49
|
"chokidar": "^4.0.1",
|
|
50
50
|
"commander": "^12.1.0",
|
|
51
51
|
"hono": "^4.6.13",
|
|
52
|
-
"markmap-common": "0.18.
|
|
53
|
-
"markmap-lib": "0.18.
|
|
54
|
-
"markmap-render": "0.18.
|
|
55
|
-
"markmap-toolbar": "0.18.
|
|
52
|
+
"markmap-common": "0.18.5-alpha.6+cea75c9",
|
|
53
|
+
"markmap-lib": "0.18.5-alpha.6+cea75c9",
|
|
54
|
+
"markmap-render": "0.18.5-alpha.6+cea75c9",
|
|
55
|
+
"markmap-toolbar": "0.18.5-alpha.6+cea75c9",
|
|
56
56
|
"open": "^10.1.0",
|
|
57
57
|
"pkg-dir": "^8.0.0",
|
|
58
58
|
"read-package-up": "^11.0.0",
|
|
59
59
|
"update-notifier": "^7.3.1"
|
|
60
60
|
},
|
|
61
|
-
"gitHead": "
|
|
61
|
+
"gitHead": "cea75c9906a30ddf515f94bd6ad61d6c9ca4035a"
|
|
62
62
|
}
|