@meowdown/core 0.68.3 → 0.69.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/dist/index.d.ts +1 -0
- package/dist/index.js +92 -37
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -513,6 +513,7 @@ interface ReferenceDefinitionIndex {
|
|
|
513
513
|
definitions: ReferenceDefinitions;
|
|
514
514
|
nodes: ReadonlySet<EditorNode>;
|
|
515
515
|
}
|
|
516
|
+
export declare function isReferenceDefinitionNode(node: EditorNode, parent: EditorNode | null, index: number): boolean;
|
|
516
517
|
export declare function collectReferenceDefinitions(doc: EditorNode): ReferenceDefinitionIndex;
|
|
517
518
|
//#endregion
|
|
518
519
|
//#region src/extensions/wiki-embed.d.ts
|
package/dist/index.js
CHANGED
|
@@ -1318,7 +1318,8 @@ function definePlainTextPaste() {
|
|
|
1318
1318
|
function docToMarkdown(node, options = {}) {
|
|
1319
1319
|
const out = new MdOut();
|
|
1320
1320
|
if (options.frontmatter) emitFrontmatter(node.attrs.frontmatter, out);
|
|
1321
|
-
|
|
1321
|
+
const child = node.childCount === 1 ? node.child(0) : void 0;
|
|
1322
|
+
if (!(child && isNodeOfType(child, "paragraph") && child.childCount === 0)) emit$1(node, out);
|
|
1322
1323
|
return out.finish();
|
|
1323
1324
|
}
|
|
1324
1325
|
/**
|
|
@@ -1373,6 +1374,7 @@ var MdOut = class {
|
|
|
1373
1374
|
this.pendingFirst = null;
|
|
1374
1375
|
this.atLineStart = true;
|
|
1375
1376
|
this.deferredBlankPrefix = null;
|
|
1377
|
+
this.contentEnd = 0;
|
|
1376
1378
|
}
|
|
1377
1379
|
/**
|
|
1378
1380
|
* Write `text`, opening each embedded line with the current line prefix.
|
|
@@ -1407,20 +1409,30 @@ var MdOut = class {
|
|
|
1407
1409
|
}
|
|
1408
1410
|
}
|
|
1409
1411
|
/**
|
|
1410
|
-
* End a block that owns no line of its own (an empty paragraph):
|
|
1411
|
-
* blank line
|
|
1412
|
-
* one,
|
|
1413
|
-
*
|
|
1414
|
-
*
|
|
1415
|
-
* blank line
|
|
1416
|
-
*
|
|
1412
|
+
* End a block that owns no line of its own (an empty paragraph): it is one
|
|
1413
|
+
* blank line. After another block, the blank line that block owes is this
|
|
1414
|
+
* one, and the next block is owed a fresh one, so each empty block adds a
|
|
1415
|
+
* blank line to the separator. With nothing owed (the start of the output)
|
|
1416
|
+
* the line is written directly and nothing is owed after it: a leading empty
|
|
1417
|
+
* block is a blank line, not a separator. A marker-bearing block (an empty
|
|
1418
|
+
* list item's `- `, an empty quote line's `>`) writes its marker as the line.
|
|
1417
1419
|
*/
|
|
1418
1420
|
closeEmptyBlock() {
|
|
1419
|
-
if (!this.atLineStart
|
|
1421
|
+
if (!this.atLineStart) {
|
|
1420
1422
|
this.closeBlock();
|
|
1421
1423
|
return;
|
|
1422
1424
|
}
|
|
1423
|
-
if (this.
|
|
1425
|
+
if (this.pendingFirst !== null) {
|
|
1426
|
+
this.emitDeferredBlankLine();
|
|
1427
|
+
const marker = this.pendingFirst;
|
|
1428
|
+
this.parts.push(marker.endsWith("] ") ? marker : marker.trimEnd(), "\n");
|
|
1429
|
+
this.pendingFirst = null;
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
if (this.deferredBlankPrefix === null) {
|
|
1433
|
+
this.parts.push(this.linePrefix.trimEnd(), "\n");
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1424
1436
|
this.emitDeferredBlankLine();
|
|
1425
1437
|
this.deferredBlankPrefix = this.linePrefix;
|
|
1426
1438
|
}
|
|
@@ -1435,7 +1447,10 @@ var MdOut = class {
|
|
|
1435
1447
|
this.pendingFirst = null;
|
|
1436
1448
|
this.atLineStart = false;
|
|
1437
1449
|
}
|
|
1438
|
-
if (!this.atLineStart)
|
|
1450
|
+
if (!this.atLineStart) {
|
|
1451
|
+
this.parts.push("\n");
|
|
1452
|
+
this.contentEnd = this.parts.length;
|
|
1453
|
+
}
|
|
1439
1454
|
this.atLineStart = true;
|
|
1440
1455
|
this.deferredBlankPrefix = this.linePrefix;
|
|
1441
1456
|
}
|
|
@@ -1486,14 +1501,14 @@ var MdOut = class {
|
|
|
1486
1501
|
this.pendingFirst = firstLine !== null ? null : savedFirst;
|
|
1487
1502
|
}
|
|
1488
1503
|
finish() {
|
|
1489
|
-
const text = this.parts.join("");
|
|
1504
|
+
const text = this.parts.slice(0, this.contentEnd).join("");
|
|
1490
1505
|
let cut = text.length;
|
|
1491
1506
|
for (let i = text.length - 1; i >= 0; i--) {
|
|
1492
1507
|
const code = text.charCodeAt(i);
|
|
1493
1508
|
if (code === 10) cut = i;
|
|
1494
1509
|
else if (code !== 32 && code !== 9) break;
|
|
1495
1510
|
}
|
|
1496
|
-
return text.slice(0, cut) + "\n";
|
|
1511
|
+
return (cut === 0 ? "" : text.slice(0, cut) + "\n") + this.parts.slice(this.contentEnd).join("") || "\n";
|
|
1497
1512
|
}
|
|
1498
1513
|
emitDeferredBlankLine() {
|
|
1499
1514
|
const prefix = this.deferredBlankPrefix;
|
|
@@ -6157,7 +6172,7 @@ function markdownToDoc(markdown, options = {}) {
|
|
|
6157
6172
|
frontmatterBody = body;
|
|
6158
6173
|
if (matchLength) rest = markdown.slice(matchLength);
|
|
6159
6174
|
}
|
|
6160
|
-
const blocks = collectBlocks(nodes, gfmBlockOnlyParser.parse(rest).cursor(), rest, 0);
|
|
6175
|
+
const blocks = collectBlocks(nodes, gfmBlockOnlyParser.parse(rest).cursor(), rest, 0, rest !== markdown);
|
|
6161
6176
|
return nodes.doc(frontmatterBody === void 0 ? {} : { frontmatter: frontmatterBody }, blocks);
|
|
6162
6177
|
}
|
|
6163
6178
|
/**
|
|
@@ -6175,13 +6190,19 @@ function matchFrontmatter(markdown) {
|
|
|
6175
6190
|
return [(match[1] ?? "").replace(/\r?\n$/, ""), match[0].length];
|
|
6176
6191
|
}
|
|
6177
6192
|
/**
|
|
6178
|
-
* Walk the
|
|
6179
|
-
*
|
|
6180
|
-
*
|
|
6193
|
+
* Walk the document's children, converting each block-level child and
|
|
6194
|
+
* flattening any node converter that returns multiple siblings (lists are the
|
|
6195
|
+
* main case). Blank lines before the first block and after the last one are
|
|
6196
|
+
* content too, one empty paragraph each; when a frontmatter block was peeled
|
|
6197
|
+
* off ahead of `text`, the first leading blank line is that block's separator.
|
|
6181
6198
|
*/
|
|
6182
|
-
function collectBlocks(nodes, cursor, text, column) {
|
|
6199
|
+
function collectBlocks(nodes, cursor, text, column, afterFrontmatter) {
|
|
6183
6200
|
const out = [];
|
|
6184
|
-
if (!cursor.firstChild())
|
|
6201
|
+
if (!cursor.firstChild()) {
|
|
6202
|
+
appendEmptyParagraphs(out, nodes, Math.max(1, countNewlines(text, 0, text.length)));
|
|
6203
|
+
return out;
|
|
6204
|
+
}
|
|
6205
|
+
appendEmptyParagraphs(out, nodes, countNewlines(text, 0, cursor.from) - (afterFrontmatter ? 1 : 0));
|
|
6185
6206
|
let previousTo;
|
|
6186
6207
|
do {
|
|
6187
6208
|
if (previousTo != null) appendGapParagraphs(out, nodes, text, previousTo, cursor.from);
|
|
@@ -6189,6 +6210,8 @@ function collectBlocks(nodes, cursor, text, column) {
|
|
|
6189
6210
|
appendBlocks(out, nodes, convertBlock(nodes, cursor, text, column));
|
|
6190
6211
|
} while (cursor.nextSibling());
|
|
6191
6212
|
cursor.parent();
|
|
6213
|
+
const end = text.endsWith("\n") ? text.length - 1 : text.length;
|
|
6214
|
+
appendEmptyParagraphs(out, nodes, countNewlines(text, previousTo, end));
|
|
6192
6215
|
return out;
|
|
6193
6216
|
}
|
|
6194
6217
|
/**
|
|
@@ -6218,9 +6241,15 @@ function appendBlocks(out, nodes, blocks) {
|
|
|
6218
6241
|
* of them (the previous block's own terminator plus one per blank line).
|
|
6219
6242
|
*/
|
|
6220
6243
|
function appendGapParagraphs(out, nodes, text, gapFrom, gapTo) {
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6244
|
+
appendEmptyParagraphs(out, nodes, countNewlines(text, gapFrom, gapTo) - 2);
|
|
6245
|
+
}
|
|
6246
|
+
function appendEmptyParagraphs(out, nodes, count) {
|
|
6247
|
+
for (let i = 0; i < count; i++) out.push(nodes.paragraph());
|
|
6248
|
+
}
|
|
6249
|
+
function countNewlines(text, from, to) {
|
|
6250
|
+
let count = 0;
|
|
6251
|
+
for (let i = from; i < to; i++) if (text.charCodeAt(i) === 10) count++;
|
|
6252
|
+
return count;
|
|
6224
6253
|
}
|
|
6225
6254
|
function convertBlock(nodes, cursor, text, column) {
|
|
6226
6255
|
switch (cursor.type.id) {
|
|
@@ -6459,30 +6488,44 @@ function convertHTMLComment(nodes, cursor, text, column) {
|
|
|
6459
6488
|
/**
|
|
6460
6489
|
* A blockquote's children start at column 0: every column an enclosing container
|
|
6461
6490
|
* wrote sits in front of the `> ` marker on the line, and comes off with it.
|
|
6491
|
+
*
|
|
6492
|
+
* Blank quote lines before the first block and after the last one are empty
|
|
6493
|
+
* paragraphs, like the document's own edges. The quote's range ends on its last
|
|
6494
|
+
* line rather than after it, so every newline in the trailing slice is a blank
|
|
6495
|
+
* line, and a quote made of markers only has one more line than newlines.
|
|
6462
6496
|
*/
|
|
6463
6497
|
function convertBlockquote(nodes, cursor, text) {
|
|
6464
6498
|
const content = [];
|
|
6499
|
+
const from = cursor.from;
|
|
6500
|
+
const to = cursor.to;
|
|
6501
|
+
let previousTo;
|
|
6465
6502
|
if (cursor.firstChild()) {
|
|
6466
|
-
let previousTo;
|
|
6467
6503
|
do {
|
|
6468
6504
|
if (cursor.type.id === LEZER_NODE_IDS.QuoteMark) continue;
|
|
6469
|
-
if (previousTo
|
|
6505
|
+
if (previousTo == null) appendEmptyParagraphs(content, nodes, countNewlines(text, from, cursor.from));
|
|
6506
|
+
else appendGapParagraphs(content, nodes, text, previousTo, cursor.from);
|
|
6470
6507
|
previousTo = cursor.to;
|
|
6471
6508
|
appendBlocks(content, nodes, convertBlock(nodes, cursor, text, 0));
|
|
6472
6509
|
} while (cursor.nextSibling());
|
|
6473
6510
|
cursor.parent();
|
|
6474
6511
|
}
|
|
6512
|
+
appendEmptyParagraphs(content, nodes, previousTo == null ? countNewlines(text, from, to) + 1 : countNewlines(text, previousTo, to));
|
|
6475
6513
|
return nodes.blockquote(content);
|
|
6476
6514
|
}
|
|
6477
6515
|
function convertList(nodes, cursor, text, column, kind) {
|
|
6478
|
-
const
|
|
6516
|
+
const out = [];
|
|
6479
6517
|
if (cursor.firstChild()) {
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6518
|
+
let previousContentEnd;
|
|
6519
|
+
do {
|
|
6520
|
+
if (cursor.type.id !== LEZER_NODE_IDS.ListItem) continue;
|
|
6521
|
+
if (previousContentEnd != null) appendGapParagraphs(out, nodes, text, previousContentEnd, cursor.from);
|
|
6522
|
+
const [item, contentEnd] = convertListItem(nodes, cursor, text, column, kind);
|
|
6523
|
+
out.push(item);
|
|
6524
|
+
previousContentEnd = contentEnd;
|
|
6525
|
+
} while (cursor.nextSibling());
|
|
6483
6526
|
cursor.parent();
|
|
6484
6527
|
}
|
|
6485
|
-
return
|
|
6528
|
+
return out;
|
|
6486
6529
|
}
|
|
6487
6530
|
/**
|
|
6488
6531
|
* The marker style at `cursor`, plus the start number of an ordered item.
|
|
@@ -6536,6 +6579,19 @@ function convertTaskItem(nodes, cursor, text, column) {
|
|
|
6536
6579
|
paragraph
|
|
6537
6580
|
};
|
|
6538
6581
|
}
|
|
6582
|
+
/**
|
|
6583
|
+
* The gap between a list marker ending at `markTo` and the item's first content
|
|
6584
|
+
* at `contentFrom`. Only content that opens on the marker's own line measures a
|
|
6585
|
+
* gap; an item whose content starts on the next line takes the canonical single
|
|
6586
|
+
* space, the column its own continuation lines are indented to. A gap of 5+ is
|
|
6587
|
+
* indented code (a different node, so the content's column would be the code
|
|
6588
|
+
* block's), and 1 is the canonical default; only a 2-4 space gap is a faithful,
|
|
6589
|
+
* content-preserving variation.
|
|
6590
|
+
*/
|
|
6591
|
+
function measureMarkerGap(text, contentFrom, markTo, markEndColumn) {
|
|
6592
|
+
const gap = markTo != null && text.lastIndexOf("\n", contentFrom - 1) < markTo ? measureContentColumn(text, contentFrom) - markEndColumn : 1;
|
|
6593
|
+
return gap >= 2 && gap <= 4 ? gap : 1;
|
|
6594
|
+
}
|
|
6539
6595
|
function convertListItem(nodes, cursor, text, column, kind) {
|
|
6540
6596
|
const content = [];
|
|
6541
6597
|
let taskChecked;
|
|
@@ -6547,7 +6603,7 @@ function convertListItem(nodes, cursor, text, column, kind) {
|
|
|
6547
6603
|
let markEndColumn = 0;
|
|
6548
6604
|
let markerGap = 1;
|
|
6549
6605
|
let contentColumn = column + markWidth + markerGap;
|
|
6550
|
-
let
|
|
6606
|
+
let previousTo;
|
|
6551
6607
|
if (cursor.firstChild()) {
|
|
6552
6608
|
do {
|
|
6553
6609
|
if (cursor.type.id === LEZER_NODE_IDS.QuoteMark) continue;
|
|
@@ -6560,12 +6616,11 @@ function convertListItem(nodes, cursor, text, column, kind) {
|
|
|
6560
6616
|
markEndColumn = measureContentColumn(text, cursor.to);
|
|
6561
6617
|
continue;
|
|
6562
6618
|
}
|
|
6563
|
-
if (
|
|
6564
|
-
|
|
6565
|
-
const gap = markTo != null && text.lastIndexOf("\n", cursor.from - 1) < markTo ? measureContentColumn(text, cursor.from) - markEndColumn : 1;
|
|
6566
|
-
markerGap = gap >= 2 && gap <= 4 ? gap : 1;
|
|
6619
|
+
if (previousTo == null) {
|
|
6620
|
+
markerGap = measureMarkerGap(text, cursor.from, markTo, markEndColumn);
|
|
6567
6621
|
contentColumn = column + markWidth + markerGap;
|
|
6568
|
-
}
|
|
6622
|
+
} else appendGapParagraphs(content, nodes, text, previousTo, cursor.from);
|
|
6623
|
+
previousTo = cursor.to;
|
|
6569
6624
|
if (kind === "bullet" && cursor.type.id === LEZER_NODE_IDS.Task) {
|
|
6570
6625
|
const task = convertTaskItem(nodes, cursor, text, contentColumn);
|
|
6571
6626
|
taskChecked = task.checked;
|
|
@@ -6588,7 +6643,7 @@ function convertListItem(nodes, cursor, text, column, kind) {
|
|
|
6588
6643
|
taskMarker,
|
|
6589
6644
|
markerGap
|
|
6590
6645
|
};
|
|
6591
|
-
return nodes.list(attrs, content);
|
|
6646
|
+
return [nodes.list(attrs, content), previousTo ?? cursor.to];
|
|
6592
6647
|
}
|
|
6593
6648
|
function convertCodeBlock(nodes, cursor, text) {
|
|
6594
6649
|
const indented = cursor.type.id === LEZER_NODE_IDS.CodeBlock;
|
|
@@ -8809,4 +8864,4 @@ function getVirtualElementFromRange(view, range) {
|
|
|
8809
8864
|
}
|
|
8810
8865
|
|
|
8811
8866
|
//#endregion
|
|
8812
|
-
export { EDITOR_KEY_BINDINGS, Priority, buildFileMarkdown, checkRoundTrip, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineCodeBlockSyntaxHighlight, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLComment, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkCommands, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMath, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, formatSizedWikiEmbed, getCodeTokens, getFileKind, getIsComposing, getLinkText, getLinkUnitAt, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunks, inlineTextToMarkChunksWithContext, insertLink, isCodeBlockPreviewHiddenDecoration, isLinkTextForHref, isMarkOfType, isModEvent, isNodeOfType, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, normalizeHref, parseWikiEmbed, removeLink, renderMathInto, updateLink, wikiEmbedBasename, withPriority };
|
|
8867
|
+
export { EDITOR_KEY_BINDINGS, Priority, buildFileMarkdown, checkRoundTrip, codeBlockLanguages, collectReferenceDefinitions, defaultResolveImageUrl, defineBulletAfterHeading, defineCodeBlockPreviewPlugin, defineCodeBlockSyntaxHighlight, defineEditorExtension, defineEmbedPaste, defineExitBoundaryHandler, defineFileClickHandler, defineFilePaste, defineFileView, defineFollowLinkHandler, defineHTMLComment, defineImage, defineImageClickHandler, defineLinkClickHandler, defineLinkCommands, defineLinkEditKeymap, defineLinkHoverHandler, defineLinkPaste, defineMath, definePendingReplacementHandler, definePlaceholder, defineReadonly, defineSearchStatusHandler, defineSubstitution, defineTagClickHandler, defineViewAttributes, defineVirtualCaret, defineWikilinkClickHandler, defineWikilinkHoverHandler, defineWikilinkTrigger, docToMarkdown, formatFileSize, formatSizedWikiEmbed, getCodeTokens, getFileKind, getIsComposing, getLinkText, getLinkUnitAt, getMarkBuilders, getPendingReplacement, getSearchStatus, getSelectedText, getTableColumnAlign, getTextblockDisplayText, getVirtualElementFromRange, inlineTextToMarkChunks, inlineTextToMarkChunksWithContext, insertLink, isCodeBlockPreviewHiddenDecoration, isLinkTextForHref, isMarkOfType, isModEvent, isNodeOfType, isReferenceDefinitionNode, isSelectionInTableCell, listenForTweetHeight, loadKaTeX, markdownToDoc, matchEmbed, normalizeHref, parseWikiEmbed, removeLink, renderMathInto, updateLink, wikiEmbedBasename, withPriority };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meowdown/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.69.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"remark-stringify": "^11.0.0",
|
|
44
44
|
"unicode-by-name": "^0.2.0",
|
|
45
45
|
"unified": "^11.0.5",
|
|
46
|
-
"@meowdown/markdown": "^0.
|
|
46
|
+
"@meowdown/markdown": "^0.69.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@ocavue/tsconfig": "^0.7.1",
|