@rathkit/rte-core 0.1.0-alpha.5 → 0.2.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/dom/view.d.ts +2 -0
- package/dist/dom/view.js +12 -2
- package/dist/markdown/inline.d.ts +5 -0
- package/dist/markdown/inline.js +28 -19
- package/dist/markdown/parse.js +1 -1
- package/dist/markdown/plugin.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @rathkit/rte-core
|
|
2
2
|
|
|
3
|
-
> **
|
|
3
|
+
> **Beta.** Not for production yet: the APIs may still change between releases. Published to the `next` tag only.
|
|
4
4
|
|
|
5
5
|
The editor itself: the document model, HTML import and export, editing operations, commands and keys, the plugin host, the browser view, and the free plugins (lists, tables, find and replace, word-processor lists, SVG, images). The model does not touch the DOM, so it also runs in Node.
|
|
6
6
|
|
package/dist/dom/view.d.ts
CHANGED
|
@@ -103,6 +103,8 @@ export declare class Editor {
|
|
|
103
103
|
/** Adds a plugin. Returns a function that removes it. */
|
|
104
104
|
/** Adds a plugin, with its page-facing part if it has one. Returns what takes both away again. */
|
|
105
105
|
use: Engine["use"];
|
|
106
|
+
/** What takes each added plugin away again, so `destroy` can take away every one that is still in (a plugin's page part holds listeners on the window). */
|
|
107
|
+
private readonly installed;
|
|
106
108
|
/** The document as HTML. `separator` goes between blocks (a newline makes it readable). */
|
|
107
109
|
getHtml(separator?: string): string;
|
|
108
110
|
/** Addresses of remote images in the document, so the host can decide whether to show them. */
|
package/dist/dom/view.js
CHANGED
|
@@ -165,9 +165,17 @@ export class Editor {
|
|
|
165
165
|
use = (plugin) => {
|
|
166
166
|
const remove = this.engine.use(plugin);
|
|
167
167
|
const stop = this.engine.attempt(plugin.id, "its page part", () => plugin.view?.(this.viewHost), () => undefined);
|
|
168
|
-
|
|
169
|
-
this.
|
|
168
|
+
const undo = () => {
|
|
169
|
+
if (!this.installed.delete(undo))
|
|
170
|
+
return;
|
|
171
|
+
if (stop)
|
|
172
|
+
this.engine.attempt(plugin.id, "taking its page part away", stop, undefined);
|
|
173
|
+
remove();
|
|
174
|
+
};
|
|
175
|
+
this.installed.add(undo);
|
|
176
|
+
return undo;
|
|
170
177
|
};
|
|
178
|
+
installed = new Set();
|
|
171
179
|
getHtml(separator = "") { return exportHtml(this.engine.document, separator); }
|
|
172
180
|
remoteImages() {
|
|
173
181
|
const found = [];
|
|
@@ -284,6 +292,8 @@ export class Editor {
|
|
|
284
292
|
return this.engine.subscribe(() => listener(this));
|
|
285
293
|
}
|
|
286
294
|
destroy() {
|
|
295
|
+
for (const undo of [...this.installed].reverse())
|
|
296
|
+
undo();
|
|
287
297
|
for (const cleanup of this.cleanups)
|
|
288
298
|
cleanup();
|
|
289
299
|
this.cleanups.length = 0;
|
|
@@ -8,6 +8,11 @@ export interface MarkdownOptions {
|
|
|
8
8
|
readonly maxDataImageLength?: number;
|
|
9
9
|
/** Keep an image whose address is relative. Default true. */
|
|
10
10
|
readonly relativeImages?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* How deep lists and quotes nest before what is inside stays text, at most 24 whatever is given (the editor passes its content profile's
|
|
13
|
+
* `maxDepth`, so a stricter profile reads less). Each level reads the lines inside it again, so this also bounds the work to 24 times the text.
|
|
14
|
+
*/
|
|
15
|
+
readonly maxDepth?: number;
|
|
11
16
|
}
|
|
12
17
|
/** Link reference definitions found in the document: `[label]: address "title"`. Keys come from `refLabel`. */
|
|
13
18
|
export type Refs = ReadonlyMap<string, {
|
package/dist/markdown/inline.js
CHANGED
|
@@ -39,10 +39,21 @@ export function parseInline(src, options = {}) {
|
|
|
39
39
|
let head = null;
|
|
40
40
|
let tail = null;
|
|
41
41
|
let buffer = "";
|
|
42
|
+
let pending = "";
|
|
43
|
+
const add = (text) => {
|
|
44
|
+
const kept = text.trimEnd().length;
|
|
45
|
+
if (kept === 0) {
|
|
46
|
+
pending += text;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
buffer += pending + text.slice(0, kept);
|
|
50
|
+
pending = text.slice(kept);
|
|
51
|
+
};
|
|
42
52
|
const flush = () => {
|
|
43
|
-
if (buffer !== "") {
|
|
44
|
-
pieces.push({ k: "t", s: buffer });
|
|
53
|
+
if (buffer !== "" || pending !== "") {
|
|
54
|
+
pieces.push({ k: "t", s: buffer + pending });
|
|
45
55
|
buffer = "";
|
|
56
|
+
pending = "";
|
|
46
57
|
}
|
|
47
58
|
};
|
|
48
59
|
const unlink = (d) => {
|
|
@@ -187,25 +198,23 @@ export function parseInline(src, options = {}) {
|
|
|
187
198
|
continue;
|
|
188
199
|
}
|
|
189
200
|
if (isAsciiPunct(n)) {
|
|
190
|
-
|
|
201
|
+
add(n);
|
|
191
202
|
i += 2;
|
|
192
203
|
continue;
|
|
193
204
|
}
|
|
194
|
-
|
|
205
|
+
add(c);
|
|
195
206
|
i++;
|
|
196
207
|
continue;
|
|
197
208
|
}
|
|
198
209
|
if (c === "\n") {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
spaces = buffer.length - kept;
|
|
202
|
-
buffer = buffer.slice(0, kept);
|
|
210
|
+
const spaces = pending.length;
|
|
211
|
+
pending = "";
|
|
203
212
|
if (spaces >= 2) {
|
|
204
213
|
flush();
|
|
205
214
|
pieces.push({ k: "br" });
|
|
206
215
|
}
|
|
207
216
|
else
|
|
208
|
-
|
|
217
|
+
add(" ");
|
|
209
218
|
i++;
|
|
210
219
|
while (src[i] === " " || src[i] === "\t")
|
|
211
220
|
i++;
|
|
@@ -214,11 +223,11 @@ export function parseInline(src, options = {}) {
|
|
|
214
223
|
if (c === "&") {
|
|
215
224
|
const m = /^&(?:#\d{1,7}|#[xX][0-9a-fA-F]{1,6}|[A-Za-z][A-Za-z0-9]{1,31});/.exec(src.slice(i, i + 40));
|
|
216
225
|
if (m) {
|
|
217
|
-
|
|
226
|
+
add(decodeEntities(m[0]));
|
|
218
227
|
i += m[0].length;
|
|
219
228
|
continue;
|
|
220
229
|
}
|
|
221
|
-
|
|
230
|
+
add(c);
|
|
222
231
|
i++;
|
|
223
232
|
continue;
|
|
224
233
|
}
|
|
@@ -228,7 +237,7 @@ export function parseInline(src, options = {}) {
|
|
|
228
237
|
run++;
|
|
229
238
|
const end = closingTicks(src, i + run, run);
|
|
230
239
|
if (end === -1) {
|
|
231
|
-
|
|
240
|
+
add("`".repeat(run));
|
|
232
241
|
i += run;
|
|
233
242
|
continue;
|
|
234
243
|
}
|
|
@@ -245,7 +254,7 @@ export function parseInline(src, options = {}) {
|
|
|
245
254
|
while (src[i + run] === c)
|
|
246
255
|
run++;
|
|
247
256
|
if (c === "~" && run > 2) {
|
|
248
|
-
|
|
257
|
+
add(c.repeat(run));
|
|
249
258
|
i += run;
|
|
250
259
|
continue;
|
|
251
260
|
}
|
|
@@ -270,7 +279,7 @@ export function parseInline(src, options = {}) {
|
|
|
270
279
|
const image = c === "!";
|
|
271
280
|
flush();
|
|
272
281
|
if (brackets.length >= MAX_BRACKETS) {
|
|
273
|
-
|
|
282
|
+
add(image ? "![" : "[");
|
|
274
283
|
i += image ? 2 : 1;
|
|
275
284
|
continue;
|
|
276
285
|
}
|
|
@@ -283,14 +292,14 @@ export function parseInline(src, options = {}) {
|
|
|
283
292
|
if (c === "]") {
|
|
284
293
|
const top = brackets.pop();
|
|
285
294
|
if (!top) {
|
|
286
|
-
|
|
295
|
+
add(c);
|
|
287
296
|
i++;
|
|
288
297
|
continue;
|
|
289
298
|
}
|
|
290
299
|
if (!top.active) {
|
|
291
300
|
flush();
|
|
292
301
|
asText(top);
|
|
293
|
-
|
|
302
|
+
add(c);
|
|
294
303
|
i++;
|
|
295
304
|
continue;
|
|
296
305
|
}
|
|
@@ -311,7 +320,7 @@ export function parseInline(src, options = {}) {
|
|
|
311
320
|
if (!tailInfo) {
|
|
312
321
|
flush();
|
|
313
322
|
asText(top);
|
|
314
|
-
|
|
323
|
+
add(c);
|
|
315
324
|
i++;
|
|
316
325
|
continue;
|
|
317
326
|
}
|
|
@@ -368,7 +377,7 @@ export function parseInline(src, options = {}) {
|
|
|
368
377
|
i = tag.end;
|
|
369
378
|
continue;
|
|
370
379
|
}
|
|
371
|
-
|
|
380
|
+
add(c);
|
|
372
381
|
i++;
|
|
373
382
|
continue;
|
|
374
383
|
}
|
|
@@ -381,7 +390,7 @@ export function parseInline(src, options = {}) {
|
|
|
381
390
|
continue;
|
|
382
391
|
}
|
|
383
392
|
}
|
|
384
|
-
|
|
393
|
+
add(c);
|
|
385
394
|
i++;
|
|
386
395
|
}
|
|
387
396
|
flush();
|
package/dist/markdown/parse.js
CHANGED
|
@@ -394,7 +394,7 @@ function parseList(lines, start, depth, options) {
|
|
|
394
394
|
}
|
|
395
395
|
function parseBlocks(lines, depth, options) {
|
|
396
396
|
const out = [];
|
|
397
|
-
if (depth >= MAX_DEPTH) {
|
|
397
|
+
if (depth >= Math.min(MAX_DEPTH, options.maxDepth ?? MAX_DEPTH)) {
|
|
398
398
|
const p = paragraph(lines.join("\n"), options);
|
|
399
399
|
return p ? [p] : [];
|
|
400
400
|
}
|
package/dist/markdown/plugin.js
CHANGED
|
@@ -48,6 +48,7 @@ export function markdown(options = {}) {
|
|
|
48
48
|
...(options.maxDataImageLength !== undefined ? { maxDataImageLength: options.maxDataImageLength } : {}),
|
|
49
49
|
sanitizeSvg: host.editor.importOptions.sanitizeSvg,
|
|
50
50
|
relativeImages: host.editor.importOptions.pasteRelativeImages ?? false,
|
|
51
|
+
...(host.editor.importOptions.maxDepth !== undefined ? { maxDepth: host.editor.importOptions.maxDepth } : {}),
|
|
51
52
|
});
|
|
52
53
|
return blocks.length > 0 ? blocks : undefined;
|
|
53
54
|
});
|