markmap-cli 0.18.4 → 0.18.5-alpha.7
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.js +91 -0
- package/dist/dev-server.d.ts +28 -4
- package/dist/index.d.ts +8 -6
- package/dist/index.js +315 -235
- package/dist/types.d.ts +7 -9
- package/dist/util.d.ts +2 -2
- package/package.json +6 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const { mm, markmap } = window;
|
|
2
|
+
const { cliOptions } = markmap;
|
|
3
|
+
const key = new URLSearchParams(window.location.search).get("key") || "";
|
|
4
|
+
const state = {
|
|
5
|
+
content: {
|
|
6
|
+
ts: 0,
|
|
7
|
+
value: void 0
|
|
8
|
+
},
|
|
9
|
+
line: {
|
|
10
|
+
ts: 0,
|
|
11
|
+
value: 0
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const activeNodeOptions = {};
|
|
15
|
+
const highlightEl = document.createElement("div");
|
|
16
|
+
highlightEl.className = "markmap-highlight-area";
|
|
17
|
+
checkData();
|
|
18
|
+
async function checkData() {
|
|
19
|
+
var _a;
|
|
20
|
+
try {
|
|
21
|
+
const query = new URLSearchParams(
|
|
22
|
+
[
|
|
23
|
+
["key", key],
|
|
24
|
+
["content", state.content.ts],
|
|
25
|
+
["line", state.line.ts]
|
|
26
|
+
].map((pair) => pair.map((s) => `${s}`))
|
|
27
|
+
);
|
|
28
|
+
const resp = await fetch(`/~data?${query}`);
|
|
29
|
+
if (!resp.ok)
|
|
30
|
+
throw {
|
|
31
|
+
status: resp.status
|
|
32
|
+
};
|
|
33
|
+
const res = await resp.json();
|
|
34
|
+
if (res.content) {
|
|
35
|
+
const value = res.content.value;
|
|
36
|
+
mm.setOptions(markmap.deriveOptions((_a = value.frontmatter) == null ? void 0 : _a.markmap));
|
|
37
|
+
await mm.setData(value.root);
|
|
38
|
+
if (!state.content.ts) await mm.fit();
|
|
39
|
+
}
|
|
40
|
+
Object.assign(state, res);
|
|
41
|
+
if (res.line && state.content.value) {
|
|
42
|
+
await setCursor({ line: res.line.value });
|
|
43
|
+
}
|
|
44
|
+
setTimeout(checkData);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
if (err.status !== 404) {
|
|
47
|
+
setTimeout(checkData, 1e3);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function findActiveNode({
|
|
52
|
+
line,
|
|
53
|
+
autoExpand = true
|
|
54
|
+
}) {
|
|
55
|
+
function dfs(node, ancestors = []) {
|
|
56
|
+
var _a, _b, _c;
|
|
57
|
+
const [start, end] = ((_b = (_a = node.payload) == null ? void 0 : _a.lines) == null ? void 0 : _b.split(",").map((s) => +s)) || [];
|
|
58
|
+
if (start >= 0 && start <= line && line < end) {
|
|
59
|
+
best = node;
|
|
60
|
+
bestAncestors = ancestors;
|
|
61
|
+
}
|
|
62
|
+
ancestors = [...ancestors, node];
|
|
63
|
+
(_c = node.children) == null ? void 0 : _c.forEach((child) => {
|
|
64
|
+
dfs(child, ancestors);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
let best;
|
|
68
|
+
let bestAncestors = [];
|
|
69
|
+
dfs(state.content.value.root);
|
|
70
|
+
if (autoExpand) {
|
|
71
|
+
bestAncestors.forEach((node) => {
|
|
72
|
+
var _a;
|
|
73
|
+
if ((_a = node.payload) == null ? void 0 : _a.fold) {
|
|
74
|
+
node.payload.fold = 0;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
return best;
|
|
79
|
+
}
|
|
80
|
+
async function setCursor(options) {
|
|
81
|
+
if (!state.content.value) return;
|
|
82
|
+
const node = findActiveNode(options);
|
|
83
|
+
await highlightNode(node);
|
|
84
|
+
}
|
|
85
|
+
async function highlightNode(node) {
|
|
86
|
+
await mm.setHighlight(node);
|
|
87
|
+
if (!node) return;
|
|
88
|
+
await mm[activeNodeOptions.placement === "center" ? "centerNode" : "ensureVisible"](node, {
|
|
89
|
+
bottom: cliOptions.toolbar ? 80 : 0
|
|
90
|
+
});
|
|
91
|
+
}
|
package/dist/dev-server.d.ts
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
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
|
+
private watcher;
|
|
11
|
+
private callbacks;
|
|
12
|
+
private disposeList;
|
|
13
|
+
serverInfo: {
|
|
14
|
+
server: ServerType;
|
|
15
|
+
address: AddressInfo;
|
|
16
|
+
} | null;
|
|
17
|
+
constructor(options: IDevelopOptions, transformer?: Transformer);
|
|
18
|
+
private _buildHtml;
|
|
19
|
+
setup(): Promise<void>;
|
|
20
|
+
shutdown(): Promise<void>;
|
|
21
|
+
destroy(): Promise<void>;
|
|
22
|
+
private _watch;
|
|
23
|
+
addProvider(options?: {
|
|
24
|
+
key?: string;
|
|
25
|
+
filePath?: string;
|
|
26
|
+
}): IContentProvider;
|
|
27
|
+
delProvider(key: string): void;
|
|
28
|
+
}
|
|
29
|
+
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,21 @@
|
|
|
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
|
|
7
|
-
import { readPackageUp } from "read-package-up";
|
|
8
|
-
import { buildCSSItem, buildJSItem, defer } from "markmap-common";
|
|
2
|
+
import { readFile, stat, mkdir, writeFile } from "fs/promises";
|
|
3
|
+
import { buildCSSItem, buildJSItem, mergeAssets, defer, extractAssets } 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";
|
|
11
|
+
import { fileURLToPath } from "url";
|
|
12
12
|
import { serve } from "@hono/node-server";
|
|
13
13
|
import { watch } from "chokidar";
|
|
14
|
-
import {
|
|
14
|
+
import { createHash } from "crypto";
|
|
15
15
|
import { createReadStream, createWriteStream } from "fs";
|
|
16
16
|
import { Hono } from "hono";
|
|
17
17
|
import { Readable } from "stream";
|
|
18
18
|
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
19
|
var getMimeType = (filename, mimes = baseMimes) => {
|
|
76
20
|
const regexp = /\.([a-zA-Z0-9]+?)$/;
|
|
77
21
|
const match = filename.match(regexp);
|
|
@@ -79,7 +23,7 @@ var getMimeType = (filename, mimes = baseMimes) => {
|
|
|
79
23
|
return;
|
|
80
24
|
}
|
|
81
25
|
let mimeType = mimes[match[1]];
|
|
82
|
-
if (mimeType && mimeType.startsWith("text")
|
|
26
|
+
if (mimeType && mimeType.startsWith("text")) {
|
|
83
27
|
mimeType += "; charset=utf-8";
|
|
84
28
|
}
|
|
85
29
|
return mimeType;
|
|
@@ -142,215 +86,343 @@ var _baseMimes = {
|
|
|
142
86
|
glb: "model/gltf-binary"
|
|
143
87
|
};
|
|
144
88
|
var baseMimes = _baseMimes;
|
|
89
|
+
const TOOLBAR_VERSION = "0.18.5-alpha.7+41488b9";
|
|
90
|
+
const TOOLBAR_CSS = `markmap-toolbar@${TOOLBAR_VERSION}/dist/style.css`;
|
|
91
|
+
const TOOLBAR_JS = `markmap-toolbar@${TOOLBAR_VERSION}/dist/index.js`;
|
|
92
|
+
const distDir = dirname(fileURLToPath(import.meta.url));
|
|
93
|
+
const ASSETS_PREFIX = "/assets/";
|
|
94
|
+
const renderToolbar = () => {
|
|
95
|
+
const { markmap, mm } = window;
|
|
96
|
+
const toolbar = new markmap.Toolbar();
|
|
97
|
+
toolbar.attach(mm);
|
|
98
|
+
const el = toolbar.render();
|
|
99
|
+
el.setAttribute("style", "position:absolute;bottom:20px;right:20px");
|
|
100
|
+
document.body.append(el);
|
|
101
|
+
};
|
|
102
|
+
const toolbarAssets = {
|
|
103
|
+
styles: [buildCSSItem(TOOLBAR_CSS)],
|
|
104
|
+
scripts: [
|
|
105
|
+
buildJSItem(TOOLBAR_JS),
|
|
106
|
+
{
|
|
107
|
+
type: "iife",
|
|
108
|
+
data: {
|
|
109
|
+
fn: (r) => {
|
|
110
|
+
setTimeout(r);
|
|
111
|
+
},
|
|
112
|
+
getParams: () => [renderToolbar]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
};
|
|
117
|
+
function localProvider(path) {
|
|
118
|
+
return `${ASSETS_PREFIX}${path}`;
|
|
119
|
+
}
|
|
120
|
+
function createStreamBody(stream) {
|
|
121
|
+
const body = new ReadableStream({
|
|
122
|
+
start(controller) {
|
|
123
|
+
stream.on("data", (chunk) => {
|
|
124
|
+
controller.enqueue(chunk);
|
|
125
|
+
});
|
|
126
|
+
stream.on("end", () => {
|
|
127
|
+
controller.close();
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
cancel() {
|
|
131
|
+
stream.destroy();
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
return body;
|
|
135
|
+
}
|
|
136
|
+
const config = {
|
|
137
|
+
distDir,
|
|
138
|
+
assetsDir: `${distDir}${ASSETS_PREFIX}`
|
|
139
|
+
};
|
|
145
140
|
function sequence(fn) {
|
|
146
141
|
let promise;
|
|
147
142
|
return () => {
|
|
148
|
-
promise || (promise = fn().finally(() => {
|
|
143
|
+
promise || (promise = Promise.resolve(fn()).finally(() => {
|
|
149
144
|
promise = void 0;
|
|
150
145
|
}));
|
|
151
146
|
return promise;
|
|
152
147
|
};
|
|
153
148
|
}
|
|
154
149
|
class BufferContentProvider {
|
|
155
|
-
constructor() {
|
|
150
|
+
constructor(key) {
|
|
151
|
+
this.key = key;
|
|
156
152
|
this.deferredSet = /* @__PURE__ */ new Set();
|
|
157
|
-
this.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
ts:
|
|
164
|
-
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
this.
|
|
168
|
-
this.feed({
|
|
169
|
-
line: this.line
|
|
170
|
-
});
|
|
171
|
-
});
|
|
153
|
+
this.state = {
|
|
154
|
+
content: {
|
|
155
|
+
ts: 0,
|
|
156
|
+
value: ""
|
|
157
|
+
},
|
|
158
|
+
line: {
|
|
159
|
+
ts: 0,
|
|
160
|
+
value: 0
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
this.disposeList = [];
|
|
172
164
|
}
|
|
173
|
-
async getUpdate(
|
|
165
|
+
async getUpdate(query, timeout = 1e4) {
|
|
174
166
|
const deferred = defer();
|
|
175
167
|
this.deferredSet.add(deferred);
|
|
176
168
|
setTimeout(() => {
|
|
177
|
-
this.feed(
|
|
169
|
+
this.feed(null, deferred);
|
|
178
170
|
}, timeout);
|
|
179
|
-
if (
|
|
180
|
-
this.feed(
|
|
171
|
+
if (Object.keys(query).some((key) => query[key] < this.state[key].ts)) {
|
|
172
|
+
this.feed(null, deferred);
|
|
181
173
|
}
|
|
182
|
-
|
|
174
|
+
await deferred.promise;
|
|
183
175
|
}
|
|
184
176
|
feed(data, deferred) {
|
|
177
|
+
if (data) {
|
|
178
|
+
Object.assign(this.state, data);
|
|
179
|
+
}
|
|
185
180
|
if (deferred) {
|
|
186
|
-
deferred.resolve(
|
|
181
|
+
deferred.resolve();
|
|
187
182
|
this.deferredSet.delete(deferred);
|
|
188
183
|
} else {
|
|
189
184
|
for (const d of this.deferredSet) {
|
|
190
|
-
d.resolve(
|
|
185
|
+
d.resolve();
|
|
191
186
|
}
|
|
192
187
|
this.deferredSet.clear();
|
|
193
188
|
}
|
|
194
189
|
}
|
|
195
190
|
setCursor(line) {
|
|
196
|
-
this.
|
|
197
|
-
|
|
191
|
+
this.feed({
|
|
192
|
+
line: {
|
|
193
|
+
ts: Date.now(),
|
|
194
|
+
value: line
|
|
195
|
+
}
|
|
196
|
+
});
|
|
198
197
|
}
|
|
199
198
|
setContent(content) {
|
|
200
|
-
this.
|
|
201
|
-
|
|
202
|
-
|
|
199
|
+
this.feed({
|
|
200
|
+
content: {
|
|
201
|
+
ts: Date.now(),
|
|
202
|
+
value: content
|
|
203
|
+
}
|
|
204
|
+
});
|
|
203
205
|
}
|
|
204
206
|
dispose() {
|
|
207
|
+
this.disposeList.forEach((dispose) => dispose());
|
|
205
208
|
}
|
|
206
209
|
}
|
|
207
210
|
class FileSystemProvider extends BufferContentProvider {
|
|
208
|
-
constructor(
|
|
209
|
-
super();
|
|
210
|
-
this.
|
|
211
|
-
this.
|
|
212
|
-
"all",
|
|
213
|
-
sequence(() => this.update())
|
|
214
|
-
);
|
|
211
|
+
constructor(key, filePath, watch2) {
|
|
212
|
+
super(key);
|
|
213
|
+
this.filePath = filePath;
|
|
214
|
+
this.disposeList.push(watch2(() => this.update()));
|
|
215
215
|
}
|
|
216
216
|
async update() {
|
|
217
|
-
const content = await readFile(this.
|
|
217
|
+
const content = await readFile(this.filePath, "utf8");
|
|
218
218
|
this.setContent(content);
|
|
219
219
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
220
|
+
}
|
|
221
|
+
function sha256(input) {
|
|
222
|
+
return createHash("sha256").update(input, "utf8").digest("hex").slice(0, 7);
|
|
223
|
+
}
|
|
224
|
+
async function sendStatic(c, realpath) {
|
|
225
|
+
try {
|
|
226
|
+
const result = await stat(realpath);
|
|
227
|
+
if (!result.isFile()) throw new Error("File not found");
|
|
228
|
+
} catch {
|
|
229
|
+
return c.body("File not found", 404);
|
|
223
230
|
}
|
|
231
|
+
const stream = createReadStream(realpath);
|
|
232
|
+
const type = getMimeType(realpath);
|
|
233
|
+
if (type) c.header("content-type", type);
|
|
234
|
+
return c.body(createStreamBody(stream));
|
|
224
235
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
236
|
+
class MarkmapDevServer {
|
|
237
|
+
constructor(options, transformer) {
|
|
238
|
+
this.options = options;
|
|
239
|
+
this.providers = {};
|
|
240
|
+
this.callbacks = {};
|
|
241
|
+
this.disposeList = [];
|
|
242
|
+
this.serverInfo = null;
|
|
243
|
+
this.transformer = transformer || new Transformer();
|
|
244
|
+
this.html = this._buildHtml();
|
|
245
|
+
this.disposeList.push(() => {
|
|
246
|
+
var _a;
|
|
247
|
+
(_a = this.watcher) == null ? void 0 : _a.close();
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
_buildHtml() {
|
|
251
|
+
var _a, _b;
|
|
252
|
+
const otherAssets = mergeAssets(
|
|
253
|
+
this.options.toolbar ? toolbarAssets : null,
|
|
254
|
+
{
|
|
255
|
+
scripts: [
|
|
256
|
+
{
|
|
257
|
+
type: "iife",
|
|
258
|
+
data: {
|
|
259
|
+
fn: (options) => {
|
|
260
|
+
window.markmap.cliOptions = options;
|
|
261
|
+
},
|
|
262
|
+
getParams: () => [this.options]
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
]
|
|
249
266
|
}
|
|
250
267
|
);
|
|
268
|
+
const assets = mergeAssets(this.transformer.getAssets(), {
|
|
269
|
+
scripts: (_a = otherAssets.scripts) == null ? void 0 : _a.map(
|
|
270
|
+
(item) => this.transformer.resolveJS(item)
|
|
271
|
+
),
|
|
272
|
+
styles: (_b = otherAssets.styles) == null ? void 0 : _b.map(
|
|
273
|
+
(item) => this.transformer.resolveCSS(item)
|
|
274
|
+
)
|
|
275
|
+
});
|
|
276
|
+
const html = fillTemplate(null, assets, {
|
|
277
|
+
urlBuilder: this.transformer.urlBuilder
|
|
278
|
+
}) + '<script src="/~client.js"><\/script>';
|
|
279
|
+
return html;
|
|
251
280
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
281
|
+
async setup() {
|
|
282
|
+
if (this.serverInfo) throw new Error("Server already set up");
|
|
283
|
+
const app = new Hono();
|
|
284
|
+
app.get("/", (c) => {
|
|
285
|
+
const key = c.req.query("key") || "";
|
|
286
|
+
if (!this.providers[key]) return c.notFound();
|
|
287
|
+
return c.html(this.html);
|
|
288
|
+
});
|
|
289
|
+
app.get("/~data", async (c) => {
|
|
290
|
+
const key = c.req.query("key") || "";
|
|
291
|
+
const provider = this.providers[key];
|
|
292
|
+
if (!provider) return c.json({}, 404);
|
|
293
|
+
const query = Object.fromEntries(
|
|
294
|
+
["content", "line"].map((key2) => [key2, +(c.req.query(key2) || "") || 0])
|
|
295
|
+
);
|
|
296
|
+
await provider.getUpdate(query);
|
|
297
|
+
const updatedKeys = Object.keys(query).filter(
|
|
298
|
+
(key2) => query[key2] < provider.state[key2].ts
|
|
299
|
+
);
|
|
300
|
+
const result = Object.fromEntries(
|
|
301
|
+
updatedKeys.map((key2) => {
|
|
302
|
+
let data = provider.state[key2];
|
|
303
|
+
if (key2 === "content") {
|
|
304
|
+
const result2 = this.transformer.transform(data.value);
|
|
305
|
+
data = {
|
|
306
|
+
...data,
|
|
307
|
+
value: {
|
|
308
|
+
frontmatter: result2.frontmatter,
|
|
309
|
+
root: result2.root
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
return [key2, data];
|
|
314
|
+
})
|
|
315
|
+
);
|
|
316
|
+
return c.json(result);
|
|
317
|
+
});
|
|
318
|
+
app.post("/~api", async (c) => {
|
|
319
|
+
var _a;
|
|
320
|
+
const key = c.req.query("key") || "";
|
|
321
|
+
const provider = this.providers[key];
|
|
322
|
+
if (!provider) return c.json({}, 404);
|
|
323
|
+
const { cmd, args } = await c.req.json();
|
|
324
|
+
await ((_a = provider[cmd]) == null ? void 0 : _a.call(provider, ...args));
|
|
325
|
+
return c.body(null, 204);
|
|
326
|
+
});
|
|
327
|
+
const { distDir: distDir2, assetsDir } = config;
|
|
328
|
+
app.get("/~client.*", async (c) => {
|
|
329
|
+
const realpath = join(distDir2, c.req.path.slice(2));
|
|
330
|
+
return sendStatic(c, realpath);
|
|
331
|
+
});
|
|
332
|
+
app.get(`${ASSETS_PREFIX}*`, async (c) => {
|
|
333
|
+
const relpath = c.req.path.slice(ASSETS_PREFIX.length);
|
|
334
|
+
const realpath = join(assetsDir, relpath);
|
|
335
|
+
return sendStatic(c, realpath);
|
|
336
|
+
});
|
|
337
|
+
const deferred = defer();
|
|
338
|
+
const server = serve(
|
|
339
|
+
{
|
|
340
|
+
fetch: app.fetch,
|
|
341
|
+
port: this.options.port
|
|
342
|
+
},
|
|
343
|
+
deferred.resolve
|
|
344
|
+
);
|
|
345
|
+
const address = await deferred.promise;
|
|
346
|
+
this.serverInfo = {
|
|
347
|
+
server,
|
|
348
|
+
address
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
async shutdown() {
|
|
352
|
+
if (!this.serverInfo) throw new Error("Server is not set up yet");
|
|
353
|
+
const deferred = defer();
|
|
354
|
+
this.serverInfo.server.close((err) => {
|
|
355
|
+
if (err) deferred.reject();
|
|
356
|
+
else deferred.resolve();
|
|
357
|
+
});
|
|
358
|
+
await deferred.promise;
|
|
359
|
+
this.serverInfo = null;
|
|
360
|
+
}
|
|
361
|
+
async destroy() {
|
|
362
|
+
await this.shutdown();
|
|
363
|
+
this.disposeList.forEach((dispose) => dispose());
|
|
364
|
+
}
|
|
365
|
+
_watch(filePath, callback) {
|
|
366
|
+
let { watcher } = this;
|
|
367
|
+
if (!watcher) {
|
|
368
|
+
watcher = watch([]).on("all", (_event, path) => {
|
|
369
|
+
const callback2 = this.callbacks[path];
|
|
370
|
+
callback2 == null ? void 0 : callback2();
|
|
371
|
+
});
|
|
372
|
+
this.watcher = watcher;
|
|
263
373
|
}
|
|
374
|
+
watcher.add(filePath);
|
|
375
|
+
this.callbacks[filePath] = sequence(callback);
|
|
376
|
+
return () => {
|
|
377
|
+
watcher.unwatch(filePath);
|
|
378
|
+
delete this.callbacks[filePath];
|
|
379
|
+
};
|
|
264
380
|
}
|
|
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) => {
|
|
381
|
+
addProvider(options) {
|
|
280
382
|
var _a;
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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
|
-
};
|
|
383
|
+
const filePath = (options == null ? void 0 : options.filePath) && resolve(options.filePath);
|
|
384
|
+
const key = (options == null ? void 0 : options.key) || (filePath ? sha256(filePath) : Math.random().toString(36).slice(2, 9));
|
|
385
|
+
(_a = this.providers)[key] || (_a[key] = filePath ? new FileSystemProvider(
|
|
386
|
+
key,
|
|
387
|
+
filePath,
|
|
388
|
+
(callback) => this._watch(filePath, callback)
|
|
389
|
+
) : new BufferContentProvider(key));
|
|
390
|
+
return this.providers[key];
|
|
391
|
+
}
|
|
392
|
+
delProvider(key) {
|
|
393
|
+
const provider = this.providers[key];
|
|
394
|
+
provider == null ? void 0 : provider.dispose();
|
|
395
|
+
delete this.providers[key];
|
|
396
|
+
}
|
|
326
397
|
}
|
|
327
|
-
async function develop(
|
|
398
|
+
async function develop(options) {
|
|
328
399
|
const transformer = new Transformer();
|
|
329
400
|
transformer.urlBuilder.setProvider("local", localProvider);
|
|
330
401
|
transformer.urlBuilder.provider = "local";
|
|
331
|
-
const
|
|
332
|
-
|
|
402
|
+
const devServer = new MarkmapDevServer(options, transformer);
|
|
403
|
+
await devServer.setup();
|
|
404
|
+
return devServer;
|
|
333
405
|
}
|
|
334
406
|
const providerName = "local-hook";
|
|
335
407
|
async function fetchAssets(assetsDir = config.assetsDir) {
|
|
336
|
-
var _a, _b;
|
|
337
408
|
const transformer = new Transformer();
|
|
338
|
-
const { provider } = transformer.urlBuilder;
|
|
339
409
|
transformer.urlBuilder.setProvider(providerName, localProvider);
|
|
340
410
|
transformer.urlBuilder.provider = providerName;
|
|
341
|
-
|
|
342
|
-
assets = addToolbar(transformer.urlBuilder, assets);
|
|
411
|
+
const assets = transformer.getAssets();
|
|
343
412
|
delete transformer.urlBuilder.providers[providerName];
|
|
344
|
-
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
413
|
+
const pluginPaths = extractAssets(assets).filter((url) => url.startsWith(ASSETS_PREFIX)).map((url) => url.slice(ASSETS_PREFIX.length));
|
|
414
|
+
const resources = transformer.plugins.flatMap(
|
|
415
|
+
(plugin) => {
|
|
416
|
+
var _a;
|
|
417
|
+
return ((_a = plugin.config) == null ? void 0 : _a.resources) || [];
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
const paths = [
|
|
421
|
+
...baseJsPaths,
|
|
422
|
+
...pluginPaths,
|
|
423
|
+
...resources,
|
|
424
|
+
...extractAssets(toolbarAssets)
|
|
425
|
+
];
|
|
354
426
|
let findingProvider;
|
|
355
427
|
const findProvider = () => {
|
|
356
428
|
findingProvider || (findingProvider = transformer.urlBuilder.getFastestProvider());
|
|
@@ -417,6 +489,7 @@ async function inlineAssets(assets) {
|
|
|
417
489
|
};
|
|
418
490
|
}
|
|
419
491
|
async function createMarkmap(options) {
|
|
492
|
+
var _a, _b;
|
|
420
493
|
const transformer = new Transformer();
|
|
421
494
|
if (options.offline) {
|
|
422
495
|
transformer.urlBuilder.setProvider("local", localProvider);
|
|
@@ -430,20 +503,20 @@ async function createMarkmap(options) {
|
|
|
430
503
|
const { root, features, frontmatter } = transformer.transform(
|
|
431
504
|
options.content || ""
|
|
432
505
|
);
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
506
|
+
const otherAssets = mergeAssets(
|
|
507
|
+
{
|
|
508
|
+
scripts: baseJsPaths.map(buildJSItem)
|
|
509
|
+
},
|
|
510
|
+
options.toolbar ? toolbarAssets : null
|
|
511
|
+
);
|
|
512
|
+
let assets = mergeAssets(
|
|
513
|
+
{
|
|
514
|
+
scripts: (_a = otherAssets.scripts) == null ? void 0 : _a.map((item) => transformer.resolveJS(item)),
|
|
515
|
+
styles: (_b = otherAssets.styles) == null ? void 0 : _b.map((item) => transformer.resolveCSS(item))
|
|
516
|
+
},
|
|
517
|
+
transformer.getUsedAssets(features)
|
|
518
|
+
);
|
|
519
|
+
if (options.offline) assets = await inlineAssets(assets);
|
|
447
520
|
const html = fillTemplate(root, assets, {
|
|
448
521
|
baseJs: [],
|
|
449
522
|
jsonOptions: frontmatter == null ? void 0 : frontmatter.markmap,
|
|
@@ -475,11 +548,16 @@ async function main() {
|
|
|
475
548
|
const content = await readFile(input, "utf8");
|
|
476
549
|
const output = cmd.output || `${input.replace(/\.\w*$/, "")}.html`;
|
|
477
550
|
if (cmd.watch) {
|
|
478
|
-
await develop(
|
|
479
|
-
open: cmd.open,
|
|
551
|
+
const devServer = await develop({
|
|
480
552
|
toolbar: cmd.toolbar,
|
|
481
553
|
offline
|
|
482
554
|
});
|
|
555
|
+
const address = devServer.serverInfo.address;
|
|
556
|
+
const provider = devServer.addProvider({ filePath: input });
|
|
557
|
+
const filename = basename(input);
|
|
558
|
+
const url = `http://localhost:${address.port}/?key=${provider.key}&filename=${encodeURIComponent(filename)}`;
|
|
559
|
+
console.log(`Listening at ${url}`);
|
|
560
|
+
if (cmd.open) open(url);
|
|
483
561
|
} else {
|
|
484
562
|
await createMarkmap({
|
|
485
563
|
content,
|
|
@@ -493,9 +571,11 @@ async function main() {
|
|
|
493
571
|
program.parse(process.argv);
|
|
494
572
|
}
|
|
495
573
|
export {
|
|
574
|
+
MarkmapDevServer,
|
|
496
575
|
config,
|
|
497
576
|
createMarkmap,
|
|
498
577
|
develop,
|
|
499
578
|
fetchAssets,
|
|
500
|
-
main
|
|
579
|
+
main,
|
|
580
|
+
markmapLib as markmap
|
|
501
581
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
export interface IDevelopOptions {
|
|
2
|
-
/**
|
|
3
|
-
* Whether to open the generated markmap in browser
|
|
4
|
-
*/
|
|
5
|
-
open: boolean;
|
|
6
2
|
/**
|
|
7
3
|
* Whether to show the default toolbar
|
|
8
4
|
*/
|
|
@@ -15,13 +11,15 @@ export interface IDevelopOptions {
|
|
|
15
11
|
/** Port number for the devServer to listen. */
|
|
16
12
|
port?: number;
|
|
17
13
|
}
|
|
18
|
-
export interface
|
|
19
|
-
ts
|
|
20
|
-
|
|
21
|
-
line?: number;
|
|
14
|
+
export interface IVersionedValue<T = unknown> {
|
|
15
|
+
ts: number;
|
|
16
|
+
value: T;
|
|
22
17
|
}
|
|
18
|
+
export type IFileState = Record<string, IVersionedValue>;
|
|
23
19
|
export interface IContentProvider {
|
|
24
|
-
|
|
20
|
+
key: string;
|
|
21
|
+
state: IFileState;
|
|
22
|
+
getUpdate: (query: Record<string, number>, timeout?: number) => Promise<void>;
|
|
25
23
|
setContent: (content: string) => void;
|
|
26
24
|
setCursor: (line: number) => void;
|
|
27
25
|
dispose: () => void;
|
package/dist/util.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { ReadStream } from 'fs';
|
|
2
|
-
import { UrlBuilder } from 'markmap-common';
|
|
3
2
|
import { IAssets } from 'markmap-lib';
|
|
4
3
|
export declare const ASSETS_PREFIX = "/assets/";
|
|
5
|
-
export declare
|
|
4
|
+
export declare const toolbarAssets: IAssets;
|
|
6
5
|
export declare function localProvider(path: string): string;
|
|
7
6
|
export declare function createStreamBody(stream: ReadStream): ReadableStream<any>;
|
|
8
7
|
export declare const config: {
|
|
8
|
+
distDir: string;
|
|
9
9
|
assetsDir: string;
|
|
10
10
|
};
|
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.7+41488b9",
|
|
4
4
|
"description": "Create markmaps from CLI",
|
|
5
5
|
"author": "Gerald <gera2ld@live.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -49,14 +49,13 @@
|
|
|
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.7+41488b9",
|
|
53
|
+
"markmap-lib": "0.18.5-alpha.7+41488b9",
|
|
54
|
+
"markmap-render": "0.18.5-alpha.7+41488b9",
|
|
55
|
+
"markmap-toolbar": "0.18.5-alpha.7+41488b9",
|
|
56
56
|
"open": "^10.1.0",
|
|
57
|
-
"pkg-dir": "^8.0.0",
|
|
58
57
|
"read-package-up": "^11.0.0",
|
|
59
58
|
"update-notifier": "^7.3.1"
|
|
60
59
|
},
|
|
61
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "41488b9988a1f49f7dadc029ef6be18fed981cac"
|
|
62
61
|
}
|