@markmap/parse 1.0.0 → 1.1.1
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.d.ts +1 -0
- package/dist/index.js +146 -83
- package/dist/mark.d.ts +24 -0
- package/dist/plugins.d.ts +0 -6
- package/package.json +8 -3
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -3,6 +3,9 @@ import remarkGfm from "remark-gfm";
|
|
|
3
3
|
import remarkParse from "remark-parse";
|
|
4
4
|
import { unified } from "unified";
|
|
5
5
|
import { parse as parse$1 } from "yaml";
|
|
6
|
+
import { splice } from "micromark-util-chunked";
|
|
7
|
+
import { classifyCharacter } from "micromark-util-classify-character";
|
|
8
|
+
import { resolveAll } from "micromark-util-resolve-all";
|
|
6
9
|
import { assignIds } from "@markmap/core";
|
|
7
10
|
// src/html-image.ts
|
|
8
11
|
var TAG = /^<img((?:\s+[a-z][a-z0-9-]*(?:\s*=\s*(?:"[^"<>]*"|'[^'<>]*'|[^\s"'=<>`]+))?)*)\s*\/?>$/i;
|
|
@@ -91,95 +94,155 @@ function remarkHtmlImages() {
|
|
|
91
94
|
};
|
|
92
95
|
return (tree) => visit(tree);
|
|
93
96
|
}
|
|
94
|
-
// src/
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}
|
|
97
|
+
// src/mark.ts
|
|
98
|
+
var EQUALS = 61;
|
|
99
|
+
var PUNCTUATION = 2;
|
|
100
|
+
/** Whether each `==` sequence can open or close a mark, from its flanking characters. */
|
|
101
|
+
var sides = /* @__PURE__ */ new WeakMap();
|
|
100
102
|
/**
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
103
|
+
* micromark syntax for `==text==`, modeled on GFM strikethrough: a sequence of exactly two
|
|
104
|
+
* `=` with the same flanking rules as `**`. Because it runs in the tokenizer, escapes
|
|
105
|
+
* (`\=`), character references (`=`) and code spans are never delimiters.
|
|
104
106
|
*/
|
|
105
|
-
function
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
function markSyntax() {
|
|
108
|
+
const construct = {
|
|
109
|
+
name: "mark",
|
|
110
|
+
tokenize: tokenizeMark,
|
|
111
|
+
resolveAll: resolveAllMark
|
|
112
|
+
};
|
|
113
|
+
return {
|
|
114
|
+
text: { [EQUALS]: construct },
|
|
115
|
+
insideSpan: { null: [construct] },
|
|
116
|
+
attentionMarkers: { null: [EQUALS] }
|
|
117
|
+
};
|
|
109
118
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
var resolveAllMark = (events, context) => {
|
|
120
|
+
for (let index = 0; index < events.length; index += 1) {
|
|
121
|
+
const closer = events[index][1];
|
|
122
|
+
if (events[index][0] !== "enter" || closer.type !== "markSequenceTemporary" || !sides.get(closer)?.close) continue;
|
|
123
|
+
for (let open = index - 1; open >= 0; open -= 1) {
|
|
124
|
+
const opener = events[open][1];
|
|
125
|
+
if (events[open][0] !== "exit" || opener.type !== "markSequenceTemporary" || !sides.get(opener)?.open) continue;
|
|
126
|
+
opener.type = "markSequence";
|
|
127
|
+
closer.type = "markSequence";
|
|
128
|
+
const mark = {
|
|
129
|
+
type: "mark",
|
|
130
|
+
start: { ...opener.start },
|
|
131
|
+
end: { ...closer.end }
|
|
132
|
+
};
|
|
133
|
+
const text = {
|
|
134
|
+
type: "markText",
|
|
135
|
+
start: { ...opener.end },
|
|
136
|
+
end: { ...closer.start }
|
|
137
|
+
};
|
|
138
|
+
const next = [
|
|
139
|
+
[
|
|
140
|
+
"enter",
|
|
141
|
+
mark,
|
|
142
|
+
context
|
|
143
|
+
],
|
|
144
|
+
[
|
|
145
|
+
"enter",
|
|
146
|
+
opener,
|
|
147
|
+
context
|
|
148
|
+
],
|
|
149
|
+
[
|
|
150
|
+
"exit",
|
|
151
|
+
opener,
|
|
152
|
+
context
|
|
153
|
+
],
|
|
154
|
+
[
|
|
155
|
+
"enter",
|
|
156
|
+
text,
|
|
157
|
+
context
|
|
158
|
+
]
|
|
159
|
+
];
|
|
160
|
+
const insideSpan = context.parser.constructs.insideSpan.null;
|
|
161
|
+
if (insideSpan) splice(next, next.length, 0, resolveAll(insideSpan, events.slice(open + 1, index), context));
|
|
162
|
+
splice(next, next.length, 0, [
|
|
163
|
+
[
|
|
164
|
+
"exit",
|
|
165
|
+
text,
|
|
166
|
+
context
|
|
167
|
+
],
|
|
168
|
+
[
|
|
169
|
+
"enter",
|
|
170
|
+
closer,
|
|
171
|
+
context
|
|
172
|
+
],
|
|
173
|
+
[
|
|
174
|
+
"exit",
|
|
175
|
+
closer,
|
|
176
|
+
context
|
|
177
|
+
],
|
|
178
|
+
[
|
|
179
|
+
"exit",
|
|
180
|
+
mark,
|
|
181
|
+
context
|
|
182
|
+
]
|
|
183
|
+
]);
|
|
184
|
+
splice(events, open - 1, index - open + 3, next);
|
|
185
|
+
index = open + next.length - 2;
|
|
186
|
+
break;
|
|
119
187
|
}
|
|
120
|
-
child.value.split(/(==)/).forEach((part) => {
|
|
121
|
-
if (part === "==") tokens.push({
|
|
122
|
-
delim: true,
|
|
123
|
-
canOpen: false,
|
|
124
|
-
canClose: false
|
|
125
|
-
});
|
|
126
|
-
else if (part) tokens.push({
|
|
127
|
-
delim: false,
|
|
128
|
-
node: {
|
|
129
|
-
type: "text",
|
|
130
|
-
value: part
|
|
131
|
-
}
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
188
|
}
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
});
|
|
148
|
-
const pairs = /* @__PURE__ */ new Map();
|
|
149
|
-
let open = -1;
|
|
150
|
-
tokens.forEach((token, i) => {
|
|
151
|
-
if (!token.delim) return;
|
|
152
|
-
if (open >= 0 && token.canClose && i > open + 1) {
|
|
153
|
-
pairs.set(open, i);
|
|
154
|
-
open = -1;
|
|
155
|
-
} else if (open < 0 && token.canOpen) open = i;
|
|
156
|
-
});
|
|
157
|
-
const build = (from, to) => {
|
|
158
|
-
const result = [];
|
|
159
|
-
const pushText = (value) => {
|
|
160
|
-
const last = result.at(-1);
|
|
161
|
-
if (last?.type === "text") last.value += value;
|
|
162
|
-
else result.push({
|
|
163
|
-
type: "text",
|
|
164
|
-
value
|
|
165
|
-
});
|
|
166
|
-
};
|
|
167
|
-
for (let i = from; i < to; i += 1) {
|
|
168
|
-
const token = tokens[i];
|
|
169
|
-
const close = pairs.get(i);
|
|
170
|
-
if (close != null) {
|
|
171
|
-
result.push({
|
|
172
|
-
type: "mark",
|
|
173
|
-
children: build(i + 1, close)
|
|
174
|
-
});
|
|
175
|
-
i = close;
|
|
176
|
-
} else if (token.delim) pushText("==");
|
|
177
|
-
else if (token.node.type === "text") pushText(token.node.value);
|
|
178
|
-
else result.push(token.node);
|
|
189
|
+
for (const [, token] of events) if (token.type === "markSequenceTemporary") token.type = "data";
|
|
190
|
+
return events;
|
|
191
|
+
};
|
|
192
|
+
var tokenizeMark = function(effects, ok, nok) {
|
|
193
|
+
const { previous, events } = this;
|
|
194
|
+
let size = 0;
|
|
195
|
+
const more = (code) => {
|
|
196
|
+
if (code === EQUALS) {
|
|
197
|
+
if (size > 1) return nok(code);
|
|
198
|
+
effects.consume(code);
|
|
199
|
+
size += 1;
|
|
200
|
+
return more;
|
|
179
201
|
}
|
|
180
|
-
return
|
|
202
|
+
if (size < 2) return nok(code);
|
|
203
|
+
const token = effects.exit("markSequenceTemporary");
|
|
204
|
+
const before = classifyCharacter(previous);
|
|
205
|
+
const after = classifyCharacter(code);
|
|
206
|
+
sides.set(token, {
|
|
207
|
+
open: !after || after === PUNCTUATION && Boolean(before),
|
|
208
|
+
close: !before || before === PUNCTUATION && Boolean(after)
|
|
209
|
+
});
|
|
210
|
+
return ok(code);
|
|
211
|
+
};
|
|
212
|
+
return (code) => {
|
|
213
|
+
if (previous === EQUALS && events.at(-1)?.[1].type !== "characterEscape") return nok(code);
|
|
214
|
+
effects.enter("markSequenceTemporary");
|
|
215
|
+
return more(code);
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
function markFromMarkdown() {
|
|
219
|
+
return {
|
|
220
|
+
canContainEols: ["mark"],
|
|
221
|
+
enter: { mark(token) {
|
|
222
|
+
this.enter({
|
|
223
|
+
type: "mark",
|
|
224
|
+
children: []
|
|
225
|
+
}, token);
|
|
226
|
+
} },
|
|
227
|
+
exit: { mark(token) {
|
|
228
|
+
this.exit(token);
|
|
229
|
+
} }
|
|
181
230
|
};
|
|
182
|
-
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Turn `==text==` into `mark` nodes. Like `**`, delimiters can wrap other inline nodes
|
|
234
|
+
* (`==a **b**==`) but not cross block boundaries.
|
|
235
|
+
*/
|
|
236
|
+
var remarkMark = function() {
|
|
237
|
+
const data = this.data();
|
|
238
|
+
(data.micromarkExtensions ??= []).push(markSyntax());
|
|
239
|
+
(data.fromMarkdownExtensions ??= []).push(markFromMarkdown());
|
|
240
|
+
};
|
|
241
|
+
// src/plugins.ts
|
|
242
|
+
function visitParents(node, fn) {
|
|
243
|
+
if (!("children" in node)) return;
|
|
244
|
+
for (const child of node.children) visitParents(child, fn);
|
|
245
|
+
fn(node);
|
|
183
246
|
}
|
|
184
247
|
/** Replace `[text][ref]` and `![alt][ref]` with plain links and images, and drop definitions. */
|
|
185
248
|
function remarkResolveReferences() {
|
|
@@ -382,4 +445,4 @@ function readFrontmatter(mdast) {
|
|
|
382
445
|
return {};
|
|
383
446
|
}
|
|
384
447
|
}
|
|
385
|
-
export { parse, parseHtmlImage, remarkHtmlImages, remarkMark, remarkResolveReferences, toTree };
|
|
448
|
+
export { markFromMarkdown, markSyntax, parse, parseHtmlImage, remarkHtmlImages, remarkMark, remarkResolveReferences, toTree };
|
package/dist/mark.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Extension as FromMarkdownExtension } from 'mdast-util-from-markdown';
|
|
2
|
+
import type { Extension } from 'micromark-util-types';
|
|
3
|
+
import type { Root } from 'mdast';
|
|
4
|
+
import type { Plugin } from 'unified';
|
|
5
|
+
declare module 'micromark-util-types' {
|
|
6
|
+
interface TokenTypeMap {
|
|
7
|
+
mark: 'mark';
|
|
8
|
+
markSequence: 'markSequence';
|
|
9
|
+
markSequenceTemporary: 'markSequenceTemporary';
|
|
10
|
+
markText: 'markText';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* micromark syntax for `==text==`, modeled on GFM strikethrough: a sequence of exactly two
|
|
15
|
+
* `=` with the same flanking rules as `**`. Because it runs in the tokenizer, escapes
|
|
16
|
+
* (`\=`), character references (`=`) and code spans are never delimiters.
|
|
17
|
+
*/
|
|
18
|
+
export declare function markSyntax(): Extension;
|
|
19
|
+
export declare function markFromMarkdown(): FromMarkdownExtension;
|
|
20
|
+
/**
|
|
21
|
+
* Turn `==text==` into `mark` nodes. Like `**`, delimiters can wrap other inline nodes
|
|
22
|
+
* (`==a **b**==`) but not cross block boundaries.
|
|
23
|
+
*/
|
|
24
|
+
export declare const remarkMark: Plugin<[], Root>;
|
package/dist/plugins.d.ts
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
1
|
import type { Root } from 'mdast';
|
|
2
|
-
/**
|
|
3
|
-
* Turn `==text==` into `mark` nodes. Like `**`, the opening `==` must be followed by
|
|
4
|
-
* a non-space and the closing one preceded by a non-space. Delimiters can wrap other
|
|
5
|
-
* inline nodes (`==a **b**==`) but not cross block boundaries.
|
|
6
|
-
*/
|
|
7
|
-
export declare function remarkMark(): (tree: Root) => void;
|
|
8
2
|
/** Replace `[text][ref]` and `![alt][ref]` with plain links and images, and drop definitions. */
|
|
9
3
|
export declare function remarkResolveReferences(): (tree: Root) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markmap/parse",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Parse Markdown into a Markmap tree",
|
|
5
5
|
"homepage": "https://github.com/markmap/markmap#readme",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,7 +24,10 @@
|
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@markmap/core": "1.
|
|
27
|
+
"@markmap/core": "1.1.1",
|
|
28
|
+
"micromark-util-chunked": "^2.0.1",
|
|
29
|
+
"micromark-util-classify-character": "^2.0.1",
|
|
30
|
+
"micromark-util-resolve-all": "^2.0.1",
|
|
28
31
|
"remark-frontmatter": "^5.0.0",
|
|
29
32
|
"remark-gfm": "^4.0.1",
|
|
30
33
|
"remark-parse": "^11.0.0",
|
|
@@ -32,7 +35,9 @@
|
|
|
32
35
|
"yaml": "^2.9.1"
|
|
33
36
|
},
|
|
34
37
|
"devDependencies": {
|
|
35
|
-
"@types/mdast": "^4.0.4"
|
|
38
|
+
"@types/mdast": "^4.0.4",
|
|
39
|
+
"mdast-util-from-markdown": "^2.1.0",
|
|
40
|
+
"micromark-util-types": "^2.0.3"
|
|
36
41
|
},
|
|
37
42
|
"scripts": {
|
|
38
43
|
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|