@aicayzer/inkkit 0.1.1 → 0.1.2
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/chunks/{core-CYp5ONPO.js → core-Dyg5rJLT.js} +971 -116
- package/dist/chunks/{highlight-BW9W8PtS.js → highlight-DQC71L-N.js} +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/editor.d.ts +22 -7
- package/dist/index.js +1 -1
- package/dist/style.css +19 -5
- package/dist/types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -31143,6 +31143,11 @@ function mermaidPreview(onError) {
|
|
|
31143
31143
|
}));
|
|
31144
31144
|
}
|
|
31145
31145
|
//#endregion
|
|
31146
|
+
//#region src/hard-break.ts
|
|
31147
|
+
function htmlBreakAt(position) {
|
|
31148
|
+
return position.parent.type.name === "heading" && position.parent.attrs.form !== "setext" || position.depth > 1 && /^table_(cell|header)$/.test(position.node(-1).type.name);
|
|
31149
|
+
}
|
|
31150
|
+
//#endregion
|
|
31146
31151
|
//#region node_modules/.pnpm/rope-sequence@1.3.4/node_modules/rope-sequence/dist/index.js
|
|
31147
31152
|
var GOOD_LEAF_SIZE = 200;
|
|
31148
31153
|
var RopeSequence = function RopeSequence() {};
|
|
@@ -39501,6 +39506,194 @@ var cursor = [
|
|
|
39501
39506
|
})
|
|
39502
39507
|
].flat();
|
|
39503
39508
|
//#endregion
|
|
39509
|
+
//#region src/smart-punctuation.ts
|
|
39510
|
+
/**
|
|
39511
|
+
* Smart punctuation: the quote or dash being typed becomes a curly quote or a dash.
|
|
39512
|
+
*
|
|
39513
|
+
* - `"` and `'` open after the start of a block, a line break, whitespace, an opening bracket, a
|
|
39514
|
+
* dash or another opening quote, and close everywhere else. A `'` between letters is an
|
|
39515
|
+
* apostrophe, which is the closing form.
|
|
39516
|
+
* - `--` gives an en dash and `---` an em dash: the third hyphen turns the en dash that the second
|
|
39517
|
+
* one made into an em dash. Only a hyphen that text input has just inserted counts as the first
|
|
39518
|
+
* of the two, so a hyphen already in the note, or typed before the caret moved, stays one.
|
|
39519
|
+
* - A quote that a dead key made arrives as a composition. When the composition commits exactly
|
|
39520
|
+
* that quote at the caret, it follows the same rules.
|
|
39521
|
+
*
|
|
39522
|
+
* These are input rules, so only the character being typed changes, Backspace and Undo straight
|
|
39523
|
+
* after restore what was typed, and nothing in a note is rewritten. The editor answers
|
|
39524
|
+
* `smartPunctuationCtx` with the current option, so turning it on or off needs no new editor.
|
|
39525
|
+
*/
|
|
39526
|
+
var smartPunctuationCtx = $ctx(() => false, "inkkitSmartPunctuation");
|
|
39527
|
+
/** Set on the transaction of each rule that this file makes. */
|
|
39528
|
+
var smartRule = "inkkitSmartPunctuation";
|
|
39529
|
+
var enDash = "–";
|
|
39530
|
+
var emDash = "—";
|
|
39531
|
+
/** What may come before a quote for it to open. */
|
|
39532
|
+
var opensAfter = /[\s([{<\u2013\u2014\u2018\u201C]/u;
|
|
39533
|
+
/**
|
|
39534
|
+
* Markdown that a person is typing out in a line of text, not words: a code span, a link
|
|
39535
|
+
* destination, a web address, a wiki link or footnote label, an HTML tag or comment and a
|
|
39536
|
+
* reference definition. Smart punctuation leaves a line alone while one is open, because the
|
|
39537
|
+
* curly character would change what the Markdown means.
|
|
39538
|
+
*/
|
|
39539
|
+
var typingSyntax = [
|
|
39540
|
+
(before) => (before.match(/`+/g)?.length ?? 0) % 2 === 1,
|
|
39541
|
+
(before) => /\]\([^)]*$/.test(before),
|
|
39542
|
+
(before) => /\[\[[^\]]*$/.test(before),
|
|
39543
|
+
(before) => /\[\^[^\]]*$/.test(before),
|
|
39544
|
+
(before) => /(?:^|[^\w])(?:[a-z][a-z0-9+.-]*:\/\/|www\.|mailto:)\S*$/i.test(before),
|
|
39545
|
+
(before) => /(?:^|[^\w])<[A-Za-z!/?][^>]*$/.test(before),
|
|
39546
|
+
(before) => /^\s*\[[^\]]+\]:/.test(before)
|
|
39547
|
+
];
|
|
39548
|
+
/**
|
|
39549
|
+
* The text of the block before `pos`, with each code span and each non-text node as one
|
|
39550
|
+
* placeholder, so that a backtick or `<` inside code is not syntax being typed.
|
|
39551
|
+
*/
|
|
39552
|
+
function textBefore(state, pos) {
|
|
39553
|
+
const $pos = state.doc.resolve(pos);
|
|
39554
|
+
let text = "";
|
|
39555
|
+
$pos.parent.forEach((child, offset) => {
|
|
39556
|
+
if (offset >= $pos.parentOffset) return;
|
|
39557
|
+
text += child.isText && !child.marks.some((mark) => mark.type.spec.code) ? child.text.slice(0, $pos.parentOffset - offset) : "";
|
|
39558
|
+
});
|
|
39559
|
+
return text;
|
|
39560
|
+
}
|
|
39561
|
+
var input = new PluginKey("inkkitSmartPunctuationInput");
|
|
39562
|
+
/** The text a transaction inserted, when it is one step that inserts text at `at` and nothing else. */
|
|
39563
|
+
function insertedAt(tr, at) {
|
|
39564
|
+
const [step] = tr.steps;
|
|
39565
|
+
if (tr.steps.length !== 1 || !(step instanceof ReplaceStep)) return void 0;
|
|
39566
|
+
if (step.from !== at || step.slice.openStart || step.slice.openEnd) return void 0;
|
|
39567
|
+
return step.slice.content.textBetween(0, step.slice.content.size);
|
|
39568
|
+
}
|
|
39569
|
+
var inputTracking = $prose(() => new Plugin({
|
|
39570
|
+
key: input,
|
|
39571
|
+
state: {
|
|
39572
|
+
init: () => ({
|
|
39573
|
+
pending: null,
|
|
39574
|
+
hyphen: null,
|
|
39575
|
+
composition: null,
|
|
39576
|
+
composedQuote: null
|
|
39577
|
+
}),
|
|
39578
|
+
apply(tr, value) {
|
|
39579
|
+
const { pending, composition } = value;
|
|
39580
|
+
value.pending = value.hyphen = value.composedQuote = null;
|
|
39581
|
+
if (tr.getMeta(hyphenReceived)) value.hyphen = tr.selection.from;
|
|
39582
|
+
if (!tr.docChanged) return value;
|
|
39583
|
+
if (pending !== null && insertedAt(tr, pending) === "-") value.hyphen = pending + 1;
|
|
39584
|
+
if (composition) {
|
|
39585
|
+
value.composition = null;
|
|
39586
|
+
const text = insertedAt(tr, composition.pos);
|
|
39587
|
+
if (tr.getMeta("composition") !== void 0 && (text === "\"" || text === "'") && tr.doc.content.size === composition.size + 1) value.composedQuote = composition.pos + 1;
|
|
39588
|
+
}
|
|
39589
|
+
return value;
|
|
39590
|
+
}
|
|
39591
|
+
},
|
|
39592
|
+
props: {
|
|
39593
|
+
handleTextInput(view, from, _to, text) {
|
|
39594
|
+
input.getState(view.state).pending = text === "-" ? from : null;
|
|
39595
|
+
return false;
|
|
39596
|
+
},
|
|
39597
|
+
handleDOMEvents: { compositionstart(view) {
|
|
39598
|
+
const { from, empty } = view.state.selection;
|
|
39599
|
+
const tracked = input.getState(view.state);
|
|
39600
|
+
tracked.composedQuote = null;
|
|
39601
|
+
tracked.composition = empty ? {
|
|
39602
|
+
pos: from,
|
|
39603
|
+
size: view.state.doc.content.size
|
|
39604
|
+
} : null;
|
|
39605
|
+
return false;
|
|
39606
|
+
} }
|
|
39607
|
+
}
|
|
39608
|
+
}));
|
|
39609
|
+
/** Set on a transaction that inserted text ending in a hyphen, whatever else came with it. */
|
|
39610
|
+
var hyphenReceived = "inkkitHyphenReceived";
|
|
39611
|
+
/** Marks a transaction that inserted text ending in a hyphen that no rule changed. */
|
|
39612
|
+
function insertedHyphen(tr) {
|
|
39613
|
+
return tr.setMeta(hyphenReceived, true);
|
|
39614
|
+
}
|
|
39615
|
+
/**
|
|
39616
|
+
* The state that input rules see for text that arrived in one piece, which holds only what the
|
|
39617
|
+
* rules need: it follows the document, with the tracking plugin when the editor has one. When
|
|
39618
|
+
* `rest` ends in a hyphen, the last character follows a hyphen that came in the same piece.
|
|
39619
|
+
*/
|
|
39620
|
+
function chunkState(state, config, rest) {
|
|
39621
|
+
const tracker = input.get(state);
|
|
39622
|
+
const prepared = EditorState.create({
|
|
39623
|
+
...config,
|
|
39624
|
+
plugins: tracker ? [tracker] : []
|
|
39625
|
+
});
|
|
39626
|
+
return tracker && rest.endsWith("-") ? prepared.apply(insertedHyphen(prepared.tr)) : prepared;
|
|
39627
|
+
}
|
|
39628
|
+
/**
|
|
39629
|
+
* Whether a rule may change what `match` found at `pos`: the option is on, the last character of
|
|
39630
|
+
* the match is the one being typed, which is not in the document yet, and the text is ordinary,
|
|
39631
|
+
* with no Markdown being typed. The input rules plugin also runs every rule when a composition
|
|
39632
|
+
* ends, over text that is all in the document; that is not typing, and is left alone.
|
|
39633
|
+
*/
|
|
39634
|
+
function applies(on, state, match, pos) {
|
|
39635
|
+
if (!on()) return false;
|
|
39636
|
+
const typed = pos + match[0].length - 1 === state.selection.from;
|
|
39637
|
+
const composed = !typed && match[0].length === 1 && input.getState(state)?.composedQuote === state.selection.from && pos === state.selection.from - 1;
|
|
39638
|
+
if (!typed && !composed) return false;
|
|
39639
|
+
const $pos = state.doc.resolve(pos);
|
|
39640
|
+
if ($pos.parent.type.spec.code || !$pos.parent.inlineContent) return false;
|
|
39641
|
+
if ((state.storedMarks ?? $pos.marks()).some((mark) => mark.type.spec.code)) return false;
|
|
39642
|
+
const before = textBefore(state, pos);
|
|
39643
|
+
return !typingSyntax.some((open) => open(before));
|
|
39644
|
+
}
|
|
39645
|
+
function opensHere(state, pos) {
|
|
39646
|
+
const node = state.doc.resolve(pos).nodeBefore;
|
|
39647
|
+
if (!node) return true;
|
|
39648
|
+
if (node.isText) {
|
|
39649
|
+
const text = node.text ?? "";
|
|
39650
|
+
return opensAfter.test(String.fromCodePoint(text.codePointAt(text.length - 1)));
|
|
39651
|
+
}
|
|
39652
|
+
return node.type.name === "hardbreak";
|
|
39653
|
+
}
|
|
39654
|
+
/** The input rule that ran at the last change, when nothing has happened since. */
|
|
39655
|
+
function lastRule(state) {
|
|
39656
|
+
for (const plugin of state.plugins) if (plugin.spec.isInputRules) {
|
|
39657
|
+
const stored = plugin.getState(state);
|
|
39658
|
+
if (stored) return stored;
|
|
39659
|
+
}
|
|
39660
|
+
}
|
|
39661
|
+
var quotes$1 = {
|
|
39662
|
+
"\"": ["“", "”"],
|
|
39663
|
+
"'": ["‘", "’"]
|
|
39664
|
+
};
|
|
39665
|
+
var smartPunctuation = [
|
|
39666
|
+
smartPunctuationCtx,
|
|
39667
|
+
inputTracking,
|
|
39668
|
+
$inputRule((ctx) => new InputRule(/["']$/, (state, match, start, end) => {
|
|
39669
|
+
if (!applies(ctx.get(smartPunctuationCtx.key), state, match, start)) return null;
|
|
39670
|
+
const [opening, closing] = quotes$1[match[0]];
|
|
39671
|
+
return state.tr.insertText(opensHere(state, start) ? opening : closing, start, end).setMeta(smartRule, "quote");
|
|
39672
|
+
}, { inCodeMark: false })),
|
|
39673
|
+
$inputRule((ctx) => new InputRule(/--$/, (state, match, start, end) => {
|
|
39674
|
+
if (!applies(ctx.get(smartPunctuationCtx.key), state, match, start)) return null;
|
|
39675
|
+
if (input.getState(state)?.hyphen !== state.selection.from) return null;
|
|
39676
|
+
const before = textBefore(state, start);
|
|
39677
|
+
if (!before.trim() || before.endsWith("-") || /^\s*\|/.test(before)) return null;
|
|
39678
|
+
return state.tr.insertText(enDash, start, end).setMeta(smartRule, "en");
|
|
39679
|
+
}, { inCodeMark: false })),
|
|
39680
|
+
$inputRule((ctx) => new InputRule(/\u2013-$/, (state, match, start, end) => {
|
|
39681
|
+
if (!applies(ctx.get(smartPunctuationCtx.key), state, match, start)) return null;
|
|
39682
|
+
if (lastRule(state)?.transform.getMeta(smartRule) !== "en") return null;
|
|
39683
|
+
return state.tr.insertText(emDash, start, end).setMeta(smartRule, "em");
|
|
39684
|
+
}, { inCodeMark: false }))
|
|
39685
|
+
].flat();
|
|
39686
|
+
/**
|
|
39687
|
+
* Undo straight after a smart quote or dash puts back the character that was typed, as Backspace
|
|
39688
|
+
* does for any input rule. The replacement joins the typing's history step, so the next Undo
|
|
39689
|
+
* removes the typing and not the curly character. Returns whether it applied.
|
|
39690
|
+
*/
|
|
39691
|
+
var undoSmartPunctuation = (state, dispatch) => {
|
|
39692
|
+
const rule = lastRule(state);
|
|
39693
|
+
if (!rule?.transform.getMeta(smartRule)) return false;
|
|
39694
|
+
return undoInputRule(state, dispatch && ((tr) => dispatch(tr.setMeta("appendedTransaction", rule.transform))));
|
|
39695
|
+
};
|
|
39696
|
+
//#endregion
|
|
39504
39697
|
//#region src/text-input.ts
|
|
39505
39698
|
var isInputRules = (plugin) => plugin.spec.isInputRules === true;
|
|
39506
39699
|
/**
|
|
@@ -39530,12 +39723,12 @@ function insertTextChunk(view, from, to, text, deflt) {
|
|
|
39530
39723
|
return true;
|
|
39531
39724
|
}
|
|
39532
39725
|
const rules = state.plugins.filter(isInputRules);
|
|
39533
|
-
const prepared =
|
|
39726
|
+
const prepared = chunkState(state, {
|
|
39534
39727
|
schema: state.schema,
|
|
39535
39728
|
doc: tr.doc,
|
|
39536
39729
|
selection: TextSelection.create(tr.doc, at),
|
|
39537
39730
|
storedMarks: state.storedMarks ?? (from === to ? $from.marks() : $from.marksAcross($to))
|
|
39538
|
-
});
|
|
39731
|
+
}, rest);
|
|
39539
39732
|
let ruled;
|
|
39540
39733
|
const preparedView = Object.create(view, {
|
|
39541
39734
|
state: { value: prepared },
|
|
@@ -39544,7 +39737,8 @@ function insertTextChunk(view, from, to, text, deflt) {
|
|
|
39544
39737
|
} }
|
|
39545
39738
|
});
|
|
39546
39739
|
if (!rules.some((rule) => rule.props.handleTextInput?.call(rule, preparedView, at, at, last, () => prepared.tr.insertText(last, at)))) {
|
|
39547
|
-
|
|
39740
|
+
const plain = deflt().scrollIntoView();
|
|
39741
|
+
view.dispatch(last === "-" ? insertedHyphen(plain) : plain);
|
|
39548
39742
|
return true;
|
|
39549
39743
|
}
|
|
39550
39744
|
if (ruled) {
|
|
@@ -44241,7 +44435,7 @@ function lineBreakHTML(value) {
|
|
|
44241
44435
|
].includes(value.trim());
|
|
44242
44436
|
}
|
|
44243
44437
|
function restoreInlineBreaks(node) {
|
|
44244
|
-
if (
|
|
44438
|
+
if (node.type === "paragraph" && node.children.length > 1 || node.type === "heading" || node.type === "tableCell") node.children = node.children.map((child) => child.type === "html" && lineBreakHTML(child.value) ? {
|
|
44245
44439
|
type: "break",
|
|
44246
44440
|
data: { inkkitHTMLBreak: true },
|
|
44247
44441
|
position: child.position
|
|
@@ -44499,6 +44693,39 @@ function relabel(text, offsets, marker) {
|
|
|
44499
44693
|
}
|
|
44500
44694
|
return text;
|
|
44501
44695
|
}
|
|
44696
|
+
var parentKey = (node) => `${node.type}:${node.position.start.offset}`;
|
|
44697
|
+
function reorderedWithin(node, reorder) {
|
|
44698
|
+
if (!reorder) return false;
|
|
44699
|
+
const start = node.position?.start.offset;
|
|
44700
|
+
const end = node.position?.end.offset;
|
|
44701
|
+
if (start == null || end == null) return false;
|
|
44702
|
+
for (const key of reorder.keys()) {
|
|
44703
|
+
const at = Number(key.slice(key.lastIndexOf(":") + 1));
|
|
44704
|
+
if (at >= start && at < end) return true;
|
|
44705
|
+
}
|
|
44706
|
+
return false;
|
|
44707
|
+
}
|
|
44708
|
+
/**
|
|
44709
|
+
* An item of an ordered list moved from `original`'s place to `place`'s, which
|
|
44710
|
+
* takes the number written there, so the numbers keep their order. Lines after
|
|
44711
|
+
* the first that are indented to the item's content move with it when the
|
|
44712
|
+
* number's width changes.
|
|
44713
|
+
*/
|
|
44714
|
+
function renumberItem(text, source, original, place) {
|
|
44715
|
+
const own = /^\d{1,9}/.exec(text)?.[0];
|
|
44716
|
+
const number = /^\d{1,9}/.exec(source.slice(place.position.start.offset))?.[0];
|
|
44717
|
+
if (!own || !number || own === number) return text;
|
|
44718
|
+
const start = original.position.start.offset;
|
|
44719
|
+
const content = original.children?.[0]?.position?.start.offset;
|
|
44720
|
+
const lines = text.split(/(?<=\n)/);
|
|
44721
|
+
const prefix = source.slice(source.lastIndexOf("\n", start - 1) + 1, start);
|
|
44722
|
+
const indent = content == null ? -1 : content - start;
|
|
44723
|
+
const first = lines[0];
|
|
44724
|
+
if (indent < 0 || first.slice(0, indent).includes("\n")) return text;
|
|
44725
|
+
const from = prefix + " ".repeat(indent);
|
|
44726
|
+
const to = prefix + " ".repeat(indent + number.length - own.length);
|
|
44727
|
+
return [number + first.slice(own.length), ...lines.slice(1).map((line) => line.startsWith(from) ? to + line.slice(from.length) : line)].join("");
|
|
44728
|
+
}
|
|
44502
44729
|
function authoredMarker(list, source) {
|
|
44503
44730
|
const at = list.children?.[0]?.position?.start.offset;
|
|
44504
44731
|
return at == null ? void 0 : markerAt(source, at)?.marker;
|
|
@@ -44740,11 +44967,18 @@ function runOffsets(nodes, text, from, to) {
|
|
|
44740
44967
|
let decoded = "";
|
|
44741
44968
|
const offsets = [from];
|
|
44742
44969
|
const links = [];
|
|
44970
|
+
const breaks = /* @__PURE__ */ new Set();
|
|
44743
44971
|
let at = from;
|
|
44972
|
+
let afterBreak = false;
|
|
44744
44973
|
for (const node of nodes) {
|
|
44745
44974
|
const start = node.position?.start.offset;
|
|
44746
44975
|
const end = node.position?.end.offset;
|
|
44747
|
-
if (start
|
|
44976
|
+
if (start == null || end == null) return void 0;
|
|
44977
|
+
if (afterBreak && start >= at && /^[ \t>]*$/.test(text.slice(at, start))) {
|
|
44978
|
+
at = start;
|
|
44979
|
+
offsets[offsets.length - 1] = start;
|
|
44980
|
+
}
|
|
44981
|
+
if (start !== at) return void 0;
|
|
44748
44982
|
const raw = text.slice(start, end);
|
|
44749
44983
|
if (node.type === "link") {
|
|
44750
44984
|
const label = inlineText(node);
|
|
@@ -44758,13 +44992,19 @@ function runOffsets(nodes, text, from, to) {
|
|
|
44758
44992
|
if (!read || read.decoded !== lf(node.value ?? "")) return void 0;
|
|
44759
44993
|
decoded += read.decoded;
|
|
44760
44994
|
offsets.push(...read.offsets.slice(1).map((offset) => start + offset));
|
|
44995
|
+
} else if (node.type === "break") {
|
|
44996
|
+
breaks.add(decoded.length);
|
|
44997
|
+
decoded += "\n";
|
|
44998
|
+
offsets.push(end);
|
|
44761
44999
|
} else return void 0;
|
|
45000
|
+
afterBreak = node.type === "break";
|
|
44762
45001
|
at = end;
|
|
44763
45002
|
}
|
|
44764
45003
|
return at === to ? {
|
|
44765
45004
|
decoded,
|
|
44766
45005
|
offsets,
|
|
44767
|
-
links
|
|
45006
|
+
links,
|
|
45007
|
+
breaks
|
|
44768
45008
|
} : void 0;
|
|
44769
45009
|
}
|
|
44770
45010
|
function retainRun(before, after, source, canonical, [from, to], [newFrom, newTo]) {
|
|
@@ -44774,9 +45014,9 @@ function retainRun(before, after, source, canonical, [from, to], [newFrom, newTo
|
|
|
44774
45014
|
const a = old.decoded;
|
|
44775
45015
|
const b = now.decoded;
|
|
44776
45016
|
let prefix = 0;
|
|
44777
|
-
while (prefix < a.length && prefix < b.length && a[prefix] === b[prefix]) prefix++;
|
|
45017
|
+
while (prefix < a.length && prefix < b.length && a[prefix] === b[prefix] && old.breaks.has(prefix) === now.breaks.has(prefix)) prefix++;
|
|
44778
45018
|
let suffix = 0;
|
|
44779
|
-
while (suffix < a.length - prefix && suffix < b.length - prefix && a[a.length - 1 - suffix] === b[b.length - 1 - suffix]) suffix++;
|
|
45019
|
+
while (suffix < a.length - prefix && suffix < b.length - prefix && a[a.length - 1 - suffix] === b[b.length - 1 - suffix] && old.breaks.has(a.length - 1 - suffix) === now.breaks.has(b.length - 1 - suffix)) suffix++;
|
|
44780
45020
|
for (let widened = true; widened;) {
|
|
44781
45021
|
widened = false;
|
|
44782
45022
|
for (const [links, length] of [[old.links, a.length], [now.links, b.length]]) for (const [start, end] of links) if (start <= length - suffix && end >= prefix) {
|
|
@@ -44790,7 +45030,7 @@ function retainRun(before, after, source, canonical, [from, to], [newFrom, newTo
|
|
|
44790
45030
|
}
|
|
44791
45031
|
}
|
|
44792
45032
|
}
|
|
44793
|
-
return source.slice(from, old.offsets[prefix]) + canonical.slice(now.offsets[prefix], now.offsets[b.length - suffix]) + source.slice(old.offsets[a.length - suffix], to);
|
|
45033
|
+
return source.slice(from, old.offsets[prefix]) + canonical.slice(now.offsets[prefix], now.offsets[b.length - suffix]) + (now.breaks.has(b.length - suffix - 1) ? retainBoundaryText(source.slice(old.offsets[a.length - suffix], to), canonical.slice(now.offsets[b.length - suffix], newTo), true) : source.slice(old.offsets[a.length - suffix], to));
|
|
44794
45034
|
}
|
|
44795
45035
|
function retainText(raw, before, after, inTable = false, written, beside = [false, false]) {
|
|
44796
45036
|
before = lf(before);
|
|
@@ -44812,14 +45052,38 @@ function retainText(raw, before, after, inTable = false, written, beside = [fals
|
|
|
44812
45052
|
}).join("");
|
|
44813
45053
|
return raw.slice(0, offsets[prefix]) + inserted + raw.slice(offsets[before.length - suffix]);
|
|
44814
45054
|
}
|
|
44815
|
-
function
|
|
45055
|
+
function retainBoundaryText(raw, canonical, afterBreak = false) {
|
|
45056
|
+
if (afterBreak) {
|
|
45057
|
+
const opening = /^(?:\d+)?(?:\\.)+/.exec(canonical)?.[0];
|
|
45058
|
+
const written = opening ? decodedOffsets(opening) : void 0;
|
|
45059
|
+
const original = written ? decodedOffsets(raw, true) : void 0;
|
|
45060
|
+
if (written && original?.decoded.startsWith(written.decoded)) raw = opening + raw.slice(original.offsets[written.decoded.length]);
|
|
45061
|
+
}
|
|
44816
45062
|
const token = "(?:[ \\t]|&#(?:[xX]0*(?:20|9)|0*(?:32|9));|	)";
|
|
44817
45063
|
const decoded = (value) => (value.match(new RegExp(token, "g")) ?? []).map((value) => value === " " || /(?:9;|Tab;)$/.test(value) ? " " : " ").join("");
|
|
44818
45064
|
const encode = (value) => value.replace(/[ \t]/g, (value) => value === " " ? "	" : " ");
|
|
44819
|
-
|
|
45065
|
+
if (raw.includes("\n")) {
|
|
45066
|
+
const lines = raw.split(/(\r?\n)/);
|
|
45067
|
+
const written = canonical.split(/\r?\n/);
|
|
45068
|
+
if (lines.length === written.length * 2 - 1) return lines.map((line, index) => {
|
|
45069
|
+
if (index % 2) return line;
|
|
45070
|
+
const canonicalLine = written[index / 2];
|
|
45071
|
+
const gutter = (value) => /^(?:[ \t]*>)*/.exec(value)?.[0] ?? "";
|
|
45072
|
+
const prefix = gutter(line);
|
|
45073
|
+
const canonicalPrefix = gutter(canonicalLine);
|
|
45074
|
+
if (prefix.replace(/[ \t]/g, "") !== canonicalPrefix.replace(/[ \t]/g, "")) return line;
|
|
45075
|
+
const canonicalBody = canonicalLine.slice(canonicalPrefix.length);
|
|
45076
|
+
return prefix + retainBoundaryText(line.slice(prefix.length), canonicalBody);
|
|
45077
|
+
}).join("");
|
|
45078
|
+
}
|
|
44820
45079
|
const rawStart = new RegExp(`^${token}+`).exec(raw)?.[0];
|
|
44821
45080
|
const encodedStart = new RegExp(`^${token}+`).exec(canonical)?.[0];
|
|
44822
|
-
if (
|
|
45081
|
+
if (rawStart && encodedStart?.includes("&")) {
|
|
45082
|
+
const content = decoded(encodedStart.slice(encodedStart.indexOf("&")));
|
|
45083
|
+
const parts = rawStart.match(new RegExp(token, "g"));
|
|
45084
|
+
const from = parts.length - content.length;
|
|
45085
|
+
if (from >= 0 && decoded(parts.slice(from).join("")) === content) raw = parts.map((part, index) => index < from ? part : encode(part)).join("") + raw.slice(rawStart.length);
|
|
45086
|
+
}
|
|
44823
45087
|
const end = /[ \t]+$/.exec(raw)?.[0];
|
|
44824
45088
|
const rawEnd = new RegExp(`${token}+$`).exec(raw)?.[0];
|
|
44825
45089
|
const encodedEnd = new RegExp(`${token}+$`).exec(canonical)?.[0];
|
|
@@ -44982,7 +45246,7 @@ function markLiterals(raw, transformed, blocks = []) {
|
|
|
44982
45246
|
};
|
|
44983
45247
|
raw.children.forEach(mark);
|
|
44984
45248
|
}
|
|
44985
|
-
function retainSource(before, after, source, canonical, lineEnding, inTable = false, width, beside = [false, false], joined = []) {
|
|
45249
|
+
function retainSource(before, after, source, canonical, lineEnding, inTable = false, width, beside = [false, false], joined = [], reorder, afterBreak = false) {
|
|
44986
45250
|
if (literals$1.has(after)) return withEnding(retainLiteral(source.slice(before.position.start.offset, before.position.end.offset), literalForms.get(before), lf(canonical.slice(after.position.start.offset, after.position.end.offset))), lineEnding);
|
|
44987
45251
|
if (before.type === "list" && after.type === "list" && before.ordered && after.ordered && !numbered.has(before) && before.position?.start.offset != null) {
|
|
44988
45252
|
const own = {
|
|
@@ -44990,7 +45254,7 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
44990
45254
|
start: after.start
|
|
44991
45255
|
};
|
|
44992
45256
|
numbered.add(own);
|
|
44993
|
-
const text = retainSource(own, after, source, canonical, lineEnding, inTable, width, beside, joined);
|
|
45257
|
+
const text = retainSource(own, after, source, canonical, lineEnding, inTable, width, beside, joined, reorder);
|
|
44994
45258
|
const at = before.position.start.offset;
|
|
44995
45259
|
const prefix = source.slice(source.lastIndexOf("\n", at - 1) + 1, at).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
44996
45260
|
let count = 0, previous = 0, number = 0;
|
|
@@ -45008,7 +45272,7 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
45008
45272
|
const text = retainSource({
|
|
45009
45273
|
...before,
|
|
45010
45274
|
checked: after.checked
|
|
45011
|
-
}, after, source, canonical, lineEnding, inTable, width, beside, joined);
|
|
45275
|
+
}, after, source, canonical, lineEnding, inTable, width, beside, joined, reorder);
|
|
45012
45276
|
const box = /^((?:[-*+]|\d{1,9}[.)])[ \t]+\[)[ xX](\])/.exec(text);
|
|
45013
45277
|
if (box) return box[1] + (after.checked ? "x" : " ") + text.slice(box[1].length + 1);
|
|
45014
45278
|
}
|
|
@@ -45073,8 +45337,8 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
45073
45337
|
const to = first.position.end.offset - start;
|
|
45074
45338
|
return retained.startsWith(source.slice(start, before.children[1].position.start.offset)) ? retained.slice(0, from) + "<br />" + retained.slice(to) : retained;
|
|
45075
45339
|
}
|
|
45076
|
-
if (before.type === "text" && after.type === "text") return
|
|
45077
|
-
if (signature(before) === signature(after) && ownShape(before) === ownShape(after) && !holdsLiteral(after)) return raw;
|
|
45340
|
+
if (before.type === "text" && after.type === "text") return retainBoundaryText(withEnding(retainText(raw, before.value, after.value, inTable, canonical.slice(newStart, newEnd), beside), lineEnding), canonical.slice(newStart, newEnd), afterBreak);
|
|
45341
|
+
if (signature(before) === signature(after) && ownShape(before) === ownShape(after) && !holdsLiteral(after) && !reorderedWithin(before, reorder)) return raw;
|
|
45078
45342
|
const marker = sameList(before, after) ? authoredMarker(before, source) : void 0;
|
|
45079
45343
|
const located = (nodes) => nodes.every((node) => node.position?.start.offset != null);
|
|
45080
45344
|
if (before.type === after.type && ownShape(before) === ownShape(after) && before.children && after.children && before.children.length === after.children.length && located(before.children) && located(after.children)) {
|
|
@@ -45082,15 +45346,17 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
45082
45346
|
let previous;
|
|
45083
45347
|
const same = (candidate, incoming) => signature(candidate) === signature(incoming) && ownShape(candidate) === ownShape(incoming);
|
|
45084
45348
|
const reorderable = before.type === "table" || before.type === "tableRow";
|
|
45349
|
+
const moves = reorder?.get(parentKey(before));
|
|
45085
45350
|
const retained = new Set(reorderable ? before.children.flatMap((child, index) => same(child, after.children[index]) ? [index] : []) : []);
|
|
45086
45351
|
before.children.forEach((child, index) => {
|
|
45087
45352
|
const incoming = after.children[index];
|
|
45088
|
-
const
|
|
45353
|
+
const carried = moves?.get(index);
|
|
45354
|
+
const movedIndex = !reorderable ? carried !== void 0 && before.children[carried] !== void 0 && same(before.children[carried], incoming) ? carried : -1 : same(child, incoming) ? index : before.children.findIndex((candidate, candidateIndex) => !retained.has(candidateIndex) && same(candidate, incoming));
|
|
45089
45355
|
const original = movedIndex < 0 ? child : before.children[movedIndex];
|
|
45090
45356
|
if (movedIndex >= 0) retained.add(movedIndex);
|
|
45091
45357
|
const childStart = child.position?.start.offset, childEnd = child.position?.end.offset;
|
|
45092
45358
|
if (childStart == null || childEnd == null) throw new PreservationError("A source token has no location");
|
|
45093
|
-
let retainedSource = rewrittenAddress(before.type, before.children, movedIndex < 0 ? index : movedIndex, after.children, index, source, canonical) ? canonical.slice(incoming.position.start.offset, incoming.position.end.offset) : incoming.type === "list" && !sameList(original, incoming) ? withEnding(canonicalSlice(void 0, [incoming], canonical, incoming.position.start.offset, incoming.position.end.offset, previous, authoredNeighbour(before.children[index + 1], after.children[index + 1], source)), lineEnding) : retainSource(original, incoming, source, canonical, lineEnding, inTable || before.type === "tableCell", before.type === "table" ? before.children[0]?.children?.length : void 0, [after.children[index - 1]?.type === "link", after.children[index + 1]?.type === "link"]);
|
|
45359
|
+
let retainedSource = rewrittenAddress(before.type, before.children, movedIndex < 0 ? index : movedIndex, after.children, index, source, canonical) ? canonical.slice(incoming.position.start.offset, incoming.position.end.offset) : incoming.type === "list" && !sameList(original, incoming) ? withEnding(canonicalSlice(void 0, [incoming], canonical, incoming.position.start.offset, incoming.position.end.offset, previous, authoredNeighbour(before.children[index + 1], after.children[index + 1], source)), lineEnding) : retainSource(original, incoming, source, canonical, lineEnding, inTable || before.type === "tableCell", before.type === "table" ? before.children[0]?.children?.length : void 0, [after.children[index - 1]?.type === "link", after.children[index + 1]?.type === "link"], [], reorder, after.children[index - 1]?.type === "break");
|
|
45094
45360
|
if (before.type === "tableRow" && movedIndex >= 0 && movedIndex !== index) {
|
|
45095
45361
|
const originalFrom = original.children?.[0]?.position?.start.offset;
|
|
45096
45362
|
const originalTo = original.children?.at(-1)?.position?.end.offset;
|
|
@@ -45098,6 +45364,7 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
45098
45364
|
const to = child.children?.at(-1)?.position?.end.offset;
|
|
45099
45365
|
retainedSource = originalFrom != null && originalTo != null && from != null && to != null ? source.slice(childStart, from) + source.slice(originalFrom, originalTo) + source.slice(to, childEnd) : withEnding(canonical.slice(incoming.position.start.offset, incoming.position.end.offset), lineEnding);
|
|
45100
45366
|
}
|
|
45367
|
+
if (!reorderable && before.ordered && movedIndex >= 0 && movedIndex !== index) retainedSource = renumberItem(retainedSource, source, original, child);
|
|
45101
45368
|
if (marker) retainedSource = relabel(retainedSource, [0], marker);
|
|
45102
45369
|
previous = incoming.type !== "list" ? void 0 : authoredNeighbour(original, incoming, source) ?? {
|
|
45103
45370
|
ordered: incoming.ordered,
|
|
@@ -45114,11 +45381,11 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
45114
45381
|
while (suffix < before.children.length - prefix && suffix < after.children.length - prefix && signature(before.children[before.children.length - 1 - suffix]) === signature(after.children[after.children.length - 1 - suffix])) suffix++;
|
|
45115
45382
|
if (prefix && rewrittenAddress(before.type, before.children, prefix - 1, after.children, prefix - 1, source, canonical)) prefix--;
|
|
45116
45383
|
if (suffix && rewrittenAddress(before.type, before.children, before.children.length - suffix, after.children, after.children.length - suffix, source, canonical)) suffix--;
|
|
45117
|
-
const
|
|
45118
|
-
const first =
|
|
45119
|
-
const last =
|
|
45120
|
-
const newFirst =
|
|
45121
|
-
const newLast =
|
|
45384
|
+
const wrapped = (before.type === "tableCell" || formatting.has(before.type)) && before.children.length > 0 && after.children.length > 0;
|
|
45385
|
+
const first = wrapped ? before.children[0].position?.start.offset : start;
|
|
45386
|
+
const last = wrapped ? before.children.at(-1).position?.end.offset : end;
|
|
45387
|
+
const newFirst = wrapped ? after.children[0].position?.start.offset : newStart;
|
|
45388
|
+
const newLast = wrapped ? after.children.at(-1).position?.end.offset : newEnd;
|
|
45122
45389
|
const ending = (node) => {
|
|
45123
45390
|
const last = node.children?.at(-1);
|
|
45124
45391
|
return last && (node.type === "list" || node.type === "listItem" && last.type === "list") ? ending(last) : node;
|
|
@@ -45133,7 +45400,7 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
45133
45400
|
const changes = after.children.slice(prefix, after.children.length - suffix);
|
|
45134
45401
|
const previous = authoredNeighbour(before.children[prefix - 1], after.children[prefix - 1], source);
|
|
45135
45402
|
const next = authoredNeighbour(before.children[before.children.length - suffix], after.children[after.children.length - suffix], source);
|
|
45136
|
-
return source.slice(start, first) +
|
|
45403
|
+
return source.slice(start, first) + retainBoundaryText(source.slice(first, from) + withEnding((inlineParents.has(before.type) ? retainRun(changed, changes, source, canonical, [from, to], [newFrom, newTo]) : retainParts(marker, [...changed, ...joined], changes, source, canonical, newFrom, newTo, lineEnding, previous, next)) ?? canonicalSlice(marker, changes, canonical, newFrom, newTo, previous, next), lineEnding) + (inlineParents.has(before.type) ? retainBoundaryText(source.slice(to, last), canonical.slice(newTo, newLast), after.children[after.children.length - suffix - 1]?.type === "break") : source.slice(to, last)), canonical.slice(newFirst, newLast)) + source.slice(last, end);
|
|
45137
45404
|
}
|
|
45138
45405
|
}
|
|
45139
45406
|
const lastAfter = after.children?.at(-1)?.position?.end.offset;
|
|
@@ -45229,7 +45496,13 @@ function semanticSignature(doc) {
|
|
|
45229
45496
|
const content = value.content;
|
|
45230
45497
|
if (!content) return value;
|
|
45231
45498
|
const tokens = [];
|
|
45232
|
-
for (const child of content) {
|
|
45499
|
+
for (const [index, child] of content.entries()) {
|
|
45500
|
+
const attrs = child.attrs;
|
|
45501
|
+
const next = content[index + 1];
|
|
45502
|
+
if (child.type === "hardbreak" && attrs?.isInline === false && next?.type === "comment_inline" && next.attrs?.syntax === "html") child.attrs = {
|
|
45503
|
+
...attrs,
|
|
45504
|
+
isHTML: true
|
|
45505
|
+
};
|
|
45233
45506
|
if (child.type !== "text") {
|
|
45234
45507
|
tokens.push(clean(child));
|
|
45235
45508
|
continue;
|
|
@@ -45441,6 +45714,11 @@ function similarity(left, right) {
|
|
|
45441
45714
|
while (suffix < limit - prefix && left[left.length - 1 - suffix] === right[right.length - 1 - suffix]) suffix++;
|
|
45442
45715
|
return prefix + suffix;
|
|
45443
45716
|
}
|
|
45717
|
+
var nothingCarried = {
|
|
45718
|
+
moved: /* @__PURE__ */ new Map(),
|
|
45719
|
+
children: false,
|
|
45720
|
+
within: /* @__PURE__ */ new Set()
|
|
45721
|
+
};
|
|
45444
45722
|
/** Retains the loaded source of blocks the edit leaves alone. */
|
|
45445
45723
|
var Preservation = class Preservation {
|
|
45446
45724
|
ctx;
|
|
@@ -45456,6 +45734,8 @@ var Preservation = class Preservation {
|
|
|
45456
45734
|
itemEdits = /* @__PURE__ */ new WeakMap();
|
|
45457
45735
|
regionEdits = /* @__PURE__ */ new WeakMap();
|
|
45458
45736
|
definitionNodes = /* @__PURE__ */ new Map();
|
|
45737
|
+
moves;
|
|
45738
|
+
origins;
|
|
45459
45739
|
nestedLiterals = /* @__PURE__ */ new Set();
|
|
45460
45740
|
literalsRead = /* @__PURE__ */ new WeakSet();
|
|
45461
45741
|
definitionSources;
|
|
@@ -45521,12 +45801,12 @@ var Preservation = class Preservation {
|
|
|
45521
45801
|
throw new PreservationError("Cannot read Markdown for preservation", { cause });
|
|
45522
45802
|
}
|
|
45523
45803
|
}
|
|
45524
|
-
retainBlock(block, after, canonical, joined = []) {
|
|
45804
|
+
retainBlock(block, after, canonical, joined = [], reorder) {
|
|
45525
45805
|
const offset = this.source.startsWith("") ? 1 : 0;
|
|
45526
45806
|
const start = block.ast.position?.start.offset;
|
|
45527
45807
|
if (start == null) throw new PreservationError("A source block has no location");
|
|
45528
45808
|
this.readNestedLiterals(block);
|
|
45529
|
-
return this.source.slice(block.start, start + offset) + retainSource(block.ast, after, this.source.slice(offset), canonical, this.lineEnding, false, void 0, void 0, joined);
|
|
45809
|
+
return this.source.slice(block.start, start + offset) + retainSource(block.ast, after, this.source.slice(offset), canonical, this.lineEnding, false, void 0, void 0, joined, reorder);
|
|
45530
45810
|
}
|
|
45531
45811
|
readNestedLiterals(block) {
|
|
45532
45812
|
if (!this.nestedLiterals.size || this.literalsRead.has(block)) return;
|
|
@@ -45567,7 +45847,8 @@ var Preservation = class Preservation {
|
|
|
45567
45847
|
for (let index = 0; index <= doc.childCount; index++) {
|
|
45568
45848
|
const node = index < doc.childCount ? doc.child(index) : void 0;
|
|
45569
45849
|
const before = node && this.baseline.child(index);
|
|
45570
|
-
if (
|
|
45850
|
+
if (node && node !== before && this.moves?.has(node)) return void 0;
|
|
45851
|
+
if (!node || node === before || node.eq(before) && !this.carries(node)) {
|
|
45571
45852
|
if (run.length > 1 && !this.pairedInPlace(doc, run)) return void 0;
|
|
45572
45853
|
run = [];
|
|
45573
45854
|
continue;
|
|
@@ -45713,19 +45994,24 @@ var Preservation = class Preservation {
|
|
|
45713
45994
|
if (other !== index && candidate.type === node.type && candidate.childCount === node.childCount && candidate.textContent === node.textContent) return void 0;
|
|
45714
45995
|
}
|
|
45715
45996
|
const marker = authoredMarker(list, source);
|
|
45997
|
+
const reorder = this.moves ? this.carriedChildren(node, index) : void 0;
|
|
45998
|
+
const carried = reorder?.get(parentKey(list));
|
|
45716
45999
|
let output = "";
|
|
45717
46000
|
let previous = block.start;
|
|
45718
46001
|
for (let at = 0; at < node.childCount; at++) {
|
|
45719
46002
|
const item = node.child(at);
|
|
45720
46003
|
const original = before.child(at);
|
|
45721
|
-
if (item === original || item.eq(original)) continue;
|
|
46004
|
+
if (item === original || item.eq(original) && !this.carries(item)) continue;
|
|
46005
|
+
const moved = carried?.get(at);
|
|
46006
|
+
const from = moved !== void 0 && list.children[moved] ? moved : void 0;
|
|
45722
46007
|
let retained = this.itemEdits.get(item);
|
|
45723
|
-
if (retained?.index !== index || retained.item !== at) {
|
|
45724
|
-
const text = this.localItem(node, item, before.child(at), list.children[at], source, marker);
|
|
46008
|
+
if (retained?.index !== index || retained.item !== at || retained.from !== from) {
|
|
46009
|
+
const text = from === void 0 ? this.localItem(node, item, before.child(at), list.children[at], source, marker, reorder) : this.movedItem(node, item, list, list.children[from], list.children[at], source, marker);
|
|
45725
46010
|
if (text === void 0) return void 0;
|
|
45726
46011
|
retained = {
|
|
45727
46012
|
index,
|
|
45728
46013
|
item: at,
|
|
46014
|
+
from,
|
|
45729
46015
|
text
|
|
45730
46016
|
};
|
|
45731
46017
|
this.itemEdits.set(item, retained);
|
|
@@ -45736,18 +46022,17 @@ var Preservation = class Preservation {
|
|
|
45736
46022
|
}
|
|
45737
46023
|
return output + this.source.slice(previous, block.end);
|
|
45738
46024
|
}
|
|
45739
|
-
|
|
45740
|
-
const start =
|
|
45741
|
-
const end =
|
|
45742
|
-
if (!
|
|
45743
|
-
|
|
45744
|
-
|
|
45745
|
-
if (!local || local.node.children.length !== 1 || !after) return void 0;
|
|
45746
|
-
let text = retainSource(ast, {
|
|
45747
|
-
...after,
|
|
45748
|
-
spread: ast.spread
|
|
45749
|
-
}, source, local.canonical, this.lineEnding);
|
|
46025
|
+
movedItem(node, item, list, original, place, source, marker) {
|
|
46026
|
+
const start = original.position.start.offset;
|
|
46027
|
+
const end = original.position.end.offset;
|
|
46028
|
+
if (!Preservation.plainInline(item) || !this.inContext(source.slice(start, end))) return void 0;
|
|
46029
|
+
let text = source.slice(start, end);
|
|
46030
|
+
if (list.ordered) text = renumberItem(text, source, original, place);
|
|
45750
46031
|
if (marker) text = relabel(text, [0], marker);
|
|
46032
|
+
return this.readsAsItem(node, item, text, place, source);
|
|
46033
|
+
}
|
|
46034
|
+
readsAsItem(list, item, text, ast, source) {
|
|
46035
|
+
const start = ast.position.start.offset;
|
|
45751
46036
|
const content = ast.children?.[0]?.position?.start.offset;
|
|
45752
46037
|
if (content == null || !text.startsWith(source.slice(start, content))) return void 0;
|
|
45753
46038
|
if (/^(?:[-*+]|\d{1,9}[.)])[ \t]*(?:\r?\n|$)/.test(text)) return void 0;
|
|
@@ -45760,6 +46045,20 @@ var Preservation = class Preservation {
|
|
|
45760
46045
|
const { label: _l, spread: _s, ...expected } = item.attrs;
|
|
45761
46046
|
return reread.type === item.type && JSON.stringify(attrs) === JSON.stringify(expected) && reread.content.eq(item.content) ? text : void 0;
|
|
45762
46047
|
}
|
|
46048
|
+
localItem(list, item, before, ast, source, marker, reorder) {
|
|
46049
|
+
const start = ast.position.start.offset;
|
|
46050
|
+
const end = ast.position.end.offset;
|
|
46051
|
+
if (!item.sameMarkup(before) || !sameBlocks(item, before) || !Preservation.plainInline(item) || !Preservation.plainInline(before) || !this.inContext(source.slice(start, end))) return void 0;
|
|
46052
|
+
const local = this.canonicalTree(form(write(this.ctx, list.type.schema.topNodeType.create(null, [list.type.create(list.attrs, [item])]))));
|
|
46053
|
+
const after = local?.node.children?.[0];
|
|
46054
|
+
if (!local || local.node.children.length !== 1 || !after) return void 0;
|
|
46055
|
+
let text = retainSource(ast, {
|
|
46056
|
+
...after,
|
|
46057
|
+
spread: ast.spread
|
|
46058
|
+
}, source, local.canonical, this.lineEnding, false, void 0, void 0, [], reorder);
|
|
46059
|
+
if (marker) text = relabel(text, [0], marker);
|
|
46060
|
+
return this.readsAsItem(list, item, text, ast, source);
|
|
46061
|
+
}
|
|
45763
46062
|
separateLists(doc, pieces, kept, positions, current) {
|
|
45764
46063
|
const kind = (index) => {
|
|
45765
46064
|
const name = doc.maybeChild(index)?.type.name;
|
|
@@ -45779,7 +46078,7 @@ var Preservation = class Preservation {
|
|
|
45779
46078
|
return true;
|
|
45780
46079
|
};
|
|
45781
46080
|
const cost = (index) => {
|
|
45782
|
-
if (kept[index] === "canonical") return 1;
|
|
46081
|
+
if (kept[index] === "canonical" || kept[index] === "moved") return 1;
|
|
45783
46082
|
if (kept[index] === "edited") return 10;
|
|
45784
46083
|
const own = marker(index);
|
|
45785
46084
|
const sides = [-1, 1].map((step) => inPlace(index, step));
|
|
@@ -45842,7 +46141,18 @@ var Preservation = class Preservation {
|
|
|
45842
46141
|
const reread = read(relabelled);
|
|
45843
46142
|
return reread.length === 1 && signature(reread[0]) === signature(list) && markerAt(relabelled, list.children[0].position.start.offset)?.marker === marker ? relabelled : void 0;
|
|
45844
46143
|
}
|
|
45845
|
-
|
|
46144
|
+
/** `moved` holds the nodes block moves carried. A moved node that is still a
|
|
46145
|
+
* node of the loaded document keeps that node's source where it reads the
|
|
46146
|
+
* same; every other edit is saved without it. */
|
|
46147
|
+
serialize(doc, moved) {
|
|
46148
|
+
this.moves = moved;
|
|
46149
|
+
try {
|
|
46150
|
+
return this.serializeWith(doc);
|
|
46151
|
+
} finally {
|
|
46152
|
+
this.moves = void 0;
|
|
46153
|
+
}
|
|
46154
|
+
}
|
|
46155
|
+
serializeWith(doc) {
|
|
45846
46156
|
if (this.unchanged(doc)) return this.source;
|
|
45847
46157
|
let local;
|
|
45848
46158
|
try {
|
|
@@ -45864,10 +46174,20 @@ var Preservation = class Preservation {
|
|
|
45864
46174
|
for (let index = 0; index < doc.childCount; index++) {
|
|
45865
46175
|
const node = doc.child(index);
|
|
45866
46176
|
const before = this.baseline.child(index);
|
|
45867
|
-
if (node !== before && !node.eq(before)) return false;
|
|
46177
|
+
if (node !== before && (!node.eq(before) || this.carries(node))) return false;
|
|
45868
46178
|
}
|
|
45869
46179
|
return true;
|
|
45870
46180
|
}
|
|
46181
|
+
carries(node) {
|
|
46182
|
+
const moves = this.moves;
|
|
46183
|
+
if (!moves) return false;
|
|
46184
|
+
let found = moves.has(node);
|
|
46185
|
+
node.descendants((child) => {
|
|
46186
|
+
found ||= moves.has(child);
|
|
46187
|
+
return !found && !child.isTextblock;
|
|
46188
|
+
});
|
|
46189
|
+
return found;
|
|
46190
|
+
}
|
|
45871
46191
|
checked(doc, text) {
|
|
45872
46192
|
if (!crossCheck.enabled) return text;
|
|
45873
46193
|
crossCheck.compared++;
|
|
@@ -45900,7 +46220,7 @@ var Preservation = class Preservation {
|
|
|
45900
46220
|
const previous = positions[index - 1];
|
|
45901
46221
|
return previous != null && position === previous + 1 && block ? this.source.slice(this.blocks[previous].end, block.start) : this.lineEnding.repeat(2);
|
|
45902
46222
|
}
|
|
45903
|
-
build(doc, positions, current, from, to, canonical, tree) {
|
|
46223
|
+
build(doc, positions, current, carried, from, to, canonical, tree) {
|
|
45904
46224
|
const transformed = (index) => tree.transformed.children[index - from];
|
|
45905
46225
|
if (tree) {
|
|
45906
46226
|
const failed = [];
|
|
@@ -45928,12 +46248,13 @@ var Preservation = class Preservation {
|
|
|
45928
46248
|
for (let index = from; index < to; index++) {
|
|
45929
46249
|
const text = current[index];
|
|
45930
46250
|
const position = positions[index];
|
|
45931
|
-
const
|
|
46251
|
+
const moved = carried.moved.get(index);
|
|
46252
|
+
const block = position == null ? moved === void 0 ? void 0 : this.blocks[moved] : this.blocks[position];
|
|
45932
46253
|
gaps.push(this.gap(index, positions));
|
|
45933
|
-
const kind = block && block.form === text ? "unchanged" : block && tree ? "edited" : "canonical";
|
|
46254
|
+
const kind = block && block.form === text && !carried.within.has(index) ? position == null ? "moved" : "unchanged" : block && tree && position != null ? "edited" : "canonical";
|
|
45934
46255
|
kept.push(kind);
|
|
45935
46256
|
const node = tree ? positionalNode(tree.raw, transformed(index)) : void 0;
|
|
45936
|
-
pieces.push(kind === "unchanged" ? this.source.slice(block.start, block.end) : kind === "edited" ? this.retainBlock(block, node, canonical, this.around(positions, index).filter((other) => !paired.has(other) && other.ast.type === block.ast.type).flatMap((other) => other.ast.children ?? [])) : (node && this.retainPart(positions, index, node, canonical, taken)) ?? restoreCodeEndings(this.ctx, doc.type.create(null, [doc.child(index)]), withEnding(text, this.lineEnding)));
|
|
46257
|
+
pieces.push(kind === "unchanged" || kind === "moved" ? this.source.slice(block.start, block.end) : kind === "edited" ? this.retainBlock(block, node, canonical, this.around(positions, index).filter((other) => !paired.has(other) && other.ast.type === block.ast.type).flatMap((other) => other.ast.children ?? []), carried.children ? this.carriedChildren(doc.child(index), position) : void 0) : (node && this.retainPart(positions, index, node, canonical, taken)) ?? restoreCodeEndings(this.ctx, doc.type.create(null, [doc.child(index)]), withEnding(text, this.lineEnding)));
|
|
45937
46258
|
}
|
|
45938
46259
|
return {
|
|
45939
46260
|
gaps,
|
|
@@ -45977,10 +46298,10 @@ var Preservation = class Preservation {
|
|
|
45977
46298
|
extra
|
|
45978
46299
|
};
|
|
45979
46300
|
}
|
|
45980
|
-
runs(positions, current) {
|
|
46301
|
+
runs(positions, current, within = nothingCarried.within) {
|
|
45981
46302
|
const unchanged = (index) => {
|
|
45982
46303
|
const position = positions[index];
|
|
45983
|
-
return position != null && this.blocks[position].form === current[index];
|
|
46304
|
+
return position != null && this.blocks[position].form === current[index] && !within.has(index);
|
|
45984
46305
|
};
|
|
45985
46306
|
const consecutive = (index) => index === 0 ? positions[0] === 0 : positions[index] != null && positions[index - 1] != null && positions[index] === positions[index - 1] + 1;
|
|
45986
46307
|
const runs = [];
|
|
@@ -46010,7 +46331,7 @@ var Preservation = class Preservation {
|
|
|
46010
46331
|
return true;
|
|
46011
46332
|
});
|
|
46012
46333
|
}
|
|
46013
|
-
runPieces(doc, positions, current, run) {
|
|
46334
|
+
runPieces(doc, positions, current, carried, run) {
|
|
46014
46335
|
const from = run.previous === void 0 ? 0 : run.previous + 1;
|
|
46015
46336
|
const to = run.next ?? doc.childCount;
|
|
46016
46337
|
if (from === to) return {
|
|
@@ -46021,26 +46342,27 @@ var Preservation = class Preservation {
|
|
|
46021
46342
|
const nodes = [];
|
|
46022
46343
|
for (let index = from; index < to; index++) nodes.push(doc.child(index));
|
|
46023
46344
|
const { canonical, tree } = from === 0 && to === doc.childCount ? this.canonicalDocument(doc) : this.canonicalBlocks(doc, nodes);
|
|
46024
|
-
return this.build(doc, positions, current, from, to, canonical, tree);
|
|
46345
|
+
return this.build(doc, positions, current, carried, from, to, canonical, tree);
|
|
46025
46346
|
}
|
|
46026
46347
|
regions(doc) {
|
|
46027
46348
|
if (!doc.childCount || this.baseline.childCount !== this.blocks.length || !doc.sameMarkup(this.baseline) || this.definitionSources === void 0) return void 0;
|
|
46028
46349
|
const current = [];
|
|
46029
46350
|
doc.forEach((node) => current.push(this.formOf(node)));
|
|
46030
46351
|
let positions;
|
|
46352
|
+
let carried;
|
|
46031
46353
|
try {
|
|
46032
|
-
positions =
|
|
46354
|
+
({positions, carried} = this.pairing(doc, current));
|
|
46033
46355
|
} catch {
|
|
46034
46356
|
return;
|
|
46035
46357
|
}
|
|
46036
|
-
const runs = this.runs(positions, current);
|
|
46358
|
+
const runs = this.runs(positions, current, carried.within);
|
|
46037
46359
|
if (runs.some((run) => run.previous === void 0 && run.next === void 0) || !this.readAlone(doc, positions, runs)) return void 0;
|
|
46038
46360
|
let output = "";
|
|
46039
46361
|
let at = 0;
|
|
46040
46362
|
for (const run of runs) {
|
|
46041
46363
|
const from = run.previous === void 0 ? 0 : this.blocks[positions[run.previous]].end;
|
|
46042
46364
|
const to = run.next === void 0 ? this.source.length : this.blocks[positions[run.next]].start;
|
|
46043
|
-
const text = this.region(doc, positions, current, run);
|
|
46365
|
+
const text = this.region(doc, positions, current, carried, run);
|
|
46044
46366
|
if (text === void 0) return void 0;
|
|
46045
46367
|
output += this.source.slice(at, from) + text;
|
|
46046
46368
|
at = to;
|
|
@@ -46051,7 +46373,7 @@ var Preservation = class Preservation {
|
|
|
46051
46373
|
if (frontmatter !== sourceFrontmatter(bom(this.source)) || doc.firstChild?.type.name === "hr" && frontmatter?.startsWith("---")) return void 0;
|
|
46052
46374
|
return output;
|
|
46053
46375
|
}
|
|
46054
|
-
region(doc, positions, current, run) {
|
|
46376
|
+
region(doc, positions, current, carried, run) {
|
|
46055
46377
|
const from = run.previous === void 0 ? 0 : run.previous + 1;
|
|
46056
46378
|
const to = run.next ?? doc.childCount;
|
|
46057
46379
|
const nodes = [];
|
|
@@ -46062,7 +46384,7 @@ var Preservation = class Preservation {
|
|
|
46062
46384
|
const identity = [
|
|
46063
46385
|
original(run.previous),
|
|
46064
46386
|
original(run.next),
|
|
46065
|
-
...
|
|
46387
|
+
...Array.from({ length: to - from }, (_, at) => positions[from + at] ?? `m${carried.moved.get(from + at) ?? ""}`)
|
|
46066
46388
|
].join();
|
|
46067
46389
|
const cached = this.regionEdits.get(key);
|
|
46068
46390
|
if (cached && cached.identity === identity && cached.nodes.length === nodes.length + neighbours.length && [...nodes, ...neighbours].every((node, index) => cached.nodes[index] === node)) return cached.text;
|
|
@@ -46071,10 +46393,10 @@ var Preservation = class Preservation {
|
|
|
46071
46393
|
return name === "bullet_list" || name === "ordered_list" ? name : void 0;
|
|
46072
46394
|
};
|
|
46073
46395
|
for (let index = Math.max(1, from); index <= Math.min(to, doc.childCount - 1); index++) if (list(index) && list(index) === list(index - 1)) return void 0;
|
|
46074
|
-
const { gaps, pieces } = this.runPieces(doc, positions, current, run);
|
|
46396
|
+
const { gaps, pieces } = this.runPieces(doc, positions, current, carried, run);
|
|
46075
46397
|
let text = pieces.map((piece, index) => gaps[index] + piece).join("");
|
|
46076
46398
|
if (run.next !== void 0) text += this.gap(run.next, positions);
|
|
46077
|
-
else text +=
|
|
46399
|
+
else text += this.endsAsAuthored(positions, carried) ? this.source.slice(this.blocks.at(-1).end) : finalCodeEnding(doc) ?? this.lineEnding;
|
|
46078
46400
|
const slice = (index) => {
|
|
46079
46401
|
if (index === void 0) return "";
|
|
46080
46402
|
const block = this.blocks[positions[index]];
|
|
@@ -46134,26 +46456,21 @@ var Preservation = class Preservation {
|
|
|
46134
46456
|
if (canonical === "") return this.source.startsWith("") ? "" : "";
|
|
46135
46457
|
const current = [];
|
|
46136
46458
|
doc.forEach((node) => current.push(this.formOf(node)));
|
|
46137
|
-
const
|
|
46138
|
-
const
|
|
46139
|
-
|
|
46140
|
-
|
|
46141
|
-
|
|
46142
|
-
|
|
46143
|
-
|
|
46144
|
-
|
|
46145
|
-
|
|
46146
|
-
|
|
46147
|
-
kept[from + index] = written.kept[index];
|
|
46148
|
-
});
|
|
46459
|
+
const pairing = this.pairing(doc, current);
|
|
46460
|
+
const carries = pairing.carried.moved.size > 0 || pairing.carried.children;
|
|
46461
|
+
if (carries) {
|
|
46462
|
+
let output;
|
|
46463
|
+
try {
|
|
46464
|
+
output = this.writeDocument(doc, current, pairing);
|
|
46465
|
+
} catch {
|
|
46466
|
+
output = void 0;
|
|
46467
|
+
}
|
|
46468
|
+
if (output !== void 0 && this.reopens(doc, output, canonical)) return output;
|
|
46149
46469
|
}
|
|
46150
|
-
const
|
|
46151
|
-
|
|
46152
|
-
|
|
46153
|
-
|
|
46154
|
-
else if (output) output += finalCodeEnding(doc) ?? this.lineEnding;
|
|
46155
|
-
const bom = output.startsWith("") ? 1 : 0;
|
|
46156
|
-
if (doc.firstChild?.type.name === "hr" && sourceFrontmatter(output.slice(bom))?.startsWith("---")) output = output.slice(0, bom) + "***" + output.slice(bom + 3);
|
|
46470
|
+
const output = this.writeDocument(doc, current, carries ? {
|
|
46471
|
+
positions: correspondence(this.blockForms, current),
|
|
46472
|
+
carried: nothingCarried
|
|
46473
|
+
} : pairing);
|
|
46157
46474
|
if (this.reopens(doc, output, canonical)) return output;
|
|
46158
46475
|
throw new PreservationError("The edited Markdown cannot be reopened without changing its content");
|
|
46159
46476
|
} catch (cause) {
|
|
@@ -46161,6 +46478,157 @@ var Preservation = class Preservation {
|
|
|
46161
46478
|
throw new PreservationError("Cannot preserve the edited Markdown", { cause });
|
|
46162
46479
|
}
|
|
46163
46480
|
}
|
|
46481
|
+
writeDocument(doc, current, { positions, carried }) {
|
|
46482
|
+
const gaps = current.map((_, index) => this.gap(index, positions));
|
|
46483
|
+
const pieces = positions.map((position) => position == null ? "" : this.source.slice(this.blocks[position].start, this.blocks[position].end));
|
|
46484
|
+
const kept = current.map(() => "unchanged");
|
|
46485
|
+
const runs = this.runs(positions, current, carried.within);
|
|
46486
|
+
for (const run of this.readAlone(doc, positions, runs) ? runs : [{}]) {
|
|
46487
|
+
const from = run.previous === void 0 ? 0 : run.previous + 1;
|
|
46488
|
+
const written = this.runPieces(doc, positions, current, carried, run);
|
|
46489
|
+
written.pieces.forEach((piece, index) => {
|
|
46490
|
+
pieces[from + index] = piece;
|
|
46491
|
+
kept[from + index] = written.kept[index];
|
|
46492
|
+
});
|
|
46493
|
+
}
|
|
46494
|
+
positions.at(-1);
|
|
46495
|
+
this.separateLists(doc, pieces, kept, positions, current);
|
|
46496
|
+
let output = pieces.map((piece, index) => gaps[index] + piece).join("");
|
|
46497
|
+
if (this.endsAsAuthored(positions, carried)) output += this.source.slice(this.blocks.at(-1).end);
|
|
46498
|
+
else if (output) output += finalCodeEnding(doc) ?? this.lineEnding;
|
|
46499
|
+
const bom = output.startsWith("") ? 1 : 0;
|
|
46500
|
+
if (doc.firstChild?.type.name === "hr" && sourceFrontmatter(output.slice(bom))?.startsWith("---")) output = output.slice(0, bom) + "***" + output.slice(bom + 3);
|
|
46501
|
+
return output;
|
|
46502
|
+
}
|
|
46503
|
+
originIndex() {
|
|
46504
|
+
if (this.origins) return this.origins;
|
|
46505
|
+
const origins = /* @__PURE__ */ new WeakMap();
|
|
46506
|
+
const visit = (node, path) => node.forEach((child, _, index) => {
|
|
46507
|
+
const at = [...path, index];
|
|
46508
|
+
origins.set(child, at);
|
|
46509
|
+
if (!child.isTextblock && !child.isLeaf && child.type.name !== "table") visit(child, at);
|
|
46510
|
+
});
|
|
46511
|
+
visit(this.baseline, []);
|
|
46512
|
+
return this.origins = origins;
|
|
46513
|
+
}
|
|
46514
|
+
pairing(doc, current) {
|
|
46515
|
+
const moves = this.moves;
|
|
46516
|
+
if (!moves || this.baseline.childCount !== this.blocks.length) return {
|
|
46517
|
+
positions: correspondence(this.blockForms, current),
|
|
46518
|
+
carried: nothingCarried
|
|
46519
|
+
};
|
|
46520
|
+
const origins = this.originIndex();
|
|
46521
|
+
const pinned = /* @__PURE__ */ new Map();
|
|
46522
|
+
doc.forEach((node, _, index) => {
|
|
46523
|
+
if (moves.has(node)) {
|
|
46524
|
+
const origin = origins.get(node);
|
|
46525
|
+
if (origin?.length === 1) pinned.set(index, origin[0]);
|
|
46526
|
+
}
|
|
46527
|
+
});
|
|
46528
|
+
if (!pinned.size) {
|
|
46529
|
+
const positions = correspondence(this.blockForms, current);
|
|
46530
|
+
return {
|
|
46531
|
+
positions,
|
|
46532
|
+
carried: {
|
|
46533
|
+
moved: pinned,
|
|
46534
|
+
children: true,
|
|
46535
|
+
within: this.within(doc, positions, current)
|
|
46536
|
+
}
|
|
46537
|
+
};
|
|
46538
|
+
}
|
|
46539
|
+
const taken = new Set(pinned.values());
|
|
46540
|
+
const before = this.blocks.flatMap((_, index) => taken.has(index) ? [] : [index]);
|
|
46541
|
+
const after = current.flatMap((_, index) => pinned.has(index) ? [] : [index]);
|
|
46542
|
+
const present = /* @__PURE__ */ new Map();
|
|
46543
|
+
for (const index of after) {
|
|
46544
|
+
const origin = origins.get(doc.child(index));
|
|
46545
|
+
if (origin?.length === 1) present.set(index, origin[0]);
|
|
46546
|
+
}
|
|
46547
|
+
const kept = new Set(present.values());
|
|
46548
|
+
const matched = correspondence(before.map((index) => kept.has(index) ? `${this.blockForms[index]}\u0000${index}` : this.blockForms[index]), after.map((index) => present.has(index) ? `${current[index]}\u0000${present.get(index)}` : current[index]));
|
|
46549
|
+
const positions = new Array(current.length);
|
|
46550
|
+
after.forEach((index, at) => {
|
|
46551
|
+
const match = matched[at];
|
|
46552
|
+
if (match !== void 0) positions[index] = before[match];
|
|
46553
|
+
});
|
|
46554
|
+
const next = new Array(current.length);
|
|
46555
|
+
let following = this.blocks.length;
|
|
46556
|
+
for (let index = current.length - 1; index >= 0; index--) {
|
|
46557
|
+
next[index] = following;
|
|
46558
|
+
if (positions[index] !== void 0) following = positions[index];
|
|
46559
|
+
}
|
|
46560
|
+
const own = (index) => {
|
|
46561
|
+
const origin = origins.get(doc.child(index));
|
|
46562
|
+
return origin?.length === 1 ? origin[0] : void 0;
|
|
46563
|
+
};
|
|
46564
|
+
const above = new Array(current.length);
|
|
46565
|
+
let upper = this.blocks.length;
|
|
46566
|
+
for (let index = current.length - 1; index >= 0; index--) {
|
|
46567
|
+
above[index] = upper;
|
|
46568
|
+
upper = own(index) ?? upper;
|
|
46569
|
+
}
|
|
46570
|
+
const moved = /* @__PURE__ */ new Map();
|
|
46571
|
+
let last = -1;
|
|
46572
|
+
let lower = -1;
|
|
46573
|
+
for (let index = 0; index < current.length; index++) {
|
|
46574
|
+
const origin = pinned.get(index);
|
|
46575
|
+
const inOrder = origin > lower && origin < above[index];
|
|
46576
|
+
lower = own(index) ?? lower;
|
|
46577
|
+
if (origin === void 0) {
|
|
46578
|
+
if (positions[index] !== void 0) last = positions[index];
|
|
46579
|
+
} else if (origin > last && origin < next[index] && inOrder) {
|
|
46580
|
+
positions[index] = origin;
|
|
46581
|
+
last = origin;
|
|
46582
|
+
} else moved.set(index, origin);
|
|
46583
|
+
}
|
|
46584
|
+
return {
|
|
46585
|
+
positions,
|
|
46586
|
+
carried: {
|
|
46587
|
+
moved,
|
|
46588
|
+
children: true,
|
|
46589
|
+
within: this.within(doc, positions, current)
|
|
46590
|
+
}
|
|
46591
|
+
};
|
|
46592
|
+
}
|
|
46593
|
+
endsAsAuthored(positions, carried) {
|
|
46594
|
+
const end = this.blocks.length - 1;
|
|
46595
|
+
if (end < 0) return false;
|
|
46596
|
+
if (positions.at(-1) === end) return true;
|
|
46597
|
+
return carried.moved.has(positions.length - 1) && [...carried.moved.values()].includes(end);
|
|
46598
|
+
}
|
|
46599
|
+
within(doc, positions, current) {
|
|
46600
|
+
const within = /* @__PURE__ */ new Set();
|
|
46601
|
+
positions.forEach((position, index) => {
|
|
46602
|
+
const node = doc.child(index);
|
|
46603
|
+
if (position !== void 0 && this.blocks[position].form === current[index] && node !== this.baseline.child(position) && this.carries(node)) within.add(index);
|
|
46604
|
+
});
|
|
46605
|
+
return within;
|
|
46606
|
+
}
|
|
46607
|
+
carriedChildren(node, original) {
|
|
46608
|
+
const moves = this.moves;
|
|
46609
|
+
if (!moves || this.baseline.childCount !== this.blocks.length) return;
|
|
46610
|
+
const origins = this.originIndex();
|
|
46611
|
+
let reorder;
|
|
46612
|
+
const walk = (current, path, ast) => {
|
|
46613
|
+
if (!ast?.children || ast.position?.start.offset == null) return;
|
|
46614
|
+
current.forEach((child, _, index) => {
|
|
46615
|
+
let from = index;
|
|
46616
|
+
const origin = moves.has(child) ? origins.get(child) : void 0;
|
|
46617
|
+
if (origin?.length === path.length + 1 && origin.every((step, at) => at === path.length || step === path[at])) {
|
|
46618
|
+
from = origin.at(-1);
|
|
46619
|
+
if (from !== index) {
|
|
46620
|
+
reorder ??= /* @__PURE__ */ new Map();
|
|
46621
|
+
const key = parentKey(ast);
|
|
46622
|
+
if (!reorder.has(key)) reorder.set(key, /* @__PURE__ */ new Map());
|
|
46623
|
+
reorder.get(key).set(index, from);
|
|
46624
|
+
}
|
|
46625
|
+
}
|
|
46626
|
+
if (!child.isTextblock && !child.isLeaf && child.type.name !== "table") walk(child, [...path, from], ast.children[from]);
|
|
46627
|
+
});
|
|
46628
|
+
};
|
|
46629
|
+
walk(node, [original], this.blocks[original].ast);
|
|
46630
|
+
return reorder;
|
|
46631
|
+
}
|
|
46164
46632
|
};
|
|
46165
46633
|
//#endregion
|
|
46166
46634
|
//#region src/autolink.ts
|
|
@@ -46210,14 +46678,8 @@ function read(ctx, sources, texts) {
|
|
|
46210
46678
|
function literals(ctx, texts) {
|
|
46211
46679
|
const possible = texts.map((text) => /www\.|https?:\/\/|@/i.test(text));
|
|
46212
46680
|
const candidates = texts.filter((_, index) => possible[index]);
|
|
46213
|
-
const
|
|
46214
|
-
|
|
46215
|
-
const changed = candidates.flatMap((text, index) => escaped[index] === text ? [] : [index]);
|
|
46216
|
-
const written = read(ctx, changed.map((index) => escaped[index]), changed.map((index) => candidates[index]));
|
|
46217
|
-
changed.forEach((index, at) => {
|
|
46218
|
-
if (JSON.stringify(written[at]) !== JSON.stringify(raw[index])) raw[index] = void 0;
|
|
46219
|
-
});
|
|
46220
|
-
return texts.map((_, index) => possible[index] ? raw.shift() : []);
|
|
46681
|
+
const found = read(ctx, candidates.map((text) => text.replace(/[\\`[\]<>]/g, "\\$&")), candidates);
|
|
46682
|
+
return texts.map((_, index) => possible[index] ? found.shift() : []);
|
|
46221
46683
|
}
|
|
46222
46684
|
function angleHref(text) {
|
|
46223
46685
|
if (/^[a-zA-Z][a-zA-Z0-9+.-]{1,31}:[^\s<>\u0000-\u001f]*$/.test(text)) return text;
|
|
@@ -46249,7 +46711,7 @@ function wantedLinks(ctx, chars, from, to) {
|
|
|
46249
46711
|
}
|
|
46250
46712
|
const free = (index) => {
|
|
46251
46713
|
const char = chars[index];
|
|
46252
|
-
return char !== void 0 && (released.has(index) || char.form !== "angle" && !(char.link && !char.form));
|
|
46714
|
+
return char !== void 0 && !char.marks.some((mark) => mark.type.spec.code) && (released.has(index) || char.form !== "angle" && !(char.link && !char.form));
|
|
46253
46715
|
};
|
|
46254
46716
|
const spans = [];
|
|
46255
46717
|
for (let index = 0; index < chars.length;) {
|
|
@@ -46419,9 +46881,96 @@ var autolinkLiterals = $prose((ctx) => new Plugin({
|
|
|
46419
46881
|
}
|
|
46420
46882
|
}));
|
|
46421
46883
|
//#endregion
|
|
46884
|
+
//#region src/inline-code.ts
|
|
46885
|
+
var held = new PluginKey("storedInlineCode");
|
|
46886
|
+
function finish(state, pending, code) {
|
|
46887
|
+
const { selection } = state;
|
|
46888
|
+
if (state.storedMarks || !selection.empty || selection.from !== pending.to) return null;
|
|
46889
|
+
const tr = state.tr;
|
|
46890
|
+
if (pending.from < pending.to) tr.addMark(pending.from, pending.to, code.create());
|
|
46891
|
+
return tr.setStoredMarks(pending.marks);
|
|
46892
|
+
}
|
|
46893
|
+
var storedInlineCode = $prose((ctx) => {
|
|
46894
|
+
const type = () => inlineCodeSchema.type(ctx);
|
|
46895
|
+
let composing;
|
|
46896
|
+
return new Plugin({
|
|
46897
|
+
key: held,
|
|
46898
|
+
state: {
|
|
46899
|
+
init: () => null,
|
|
46900
|
+
apply(tr, value, old) {
|
|
46901
|
+
const id = tr.getMeta("composition");
|
|
46902
|
+
if (id === void 0) return tr.docChanged || tr.selectionSet || tr.storedMarksSet ? null : value;
|
|
46903
|
+
const marks = old.storedMarks;
|
|
46904
|
+
const start = value?.id === id ? value : marks && type().isInSet(marks) ? {
|
|
46905
|
+
marks,
|
|
46906
|
+
id,
|
|
46907
|
+
from: old.selection.from,
|
|
46908
|
+
to: 0
|
|
46909
|
+
} : null;
|
|
46910
|
+
if (!start) return null;
|
|
46911
|
+
let to = value?.id === id ? tr.mapping.map(start.to, 1) : start.from;
|
|
46912
|
+
tr.mapping.maps.forEach((map, index) => map.forEach((_from, _to, _start, end) => {
|
|
46913
|
+
to = Math.max(to, tr.mapping.slice(index + 1).map(end, 1));
|
|
46914
|
+
}));
|
|
46915
|
+
return {
|
|
46916
|
+
...start,
|
|
46917
|
+
to
|
|
46918
|
+
};
|
|
46919
|
+
}
|
|
46920
|
+
},
|
|
46921
|
+
view: (view) => {
|
|
46922
|
+
composing = view;
|
|
46923
|
+
return { destroy() {
|
|
46924
|
+
composing = void 0;
|
|
46925
|
+
} };
|
|
46926
|
+
},
|
|
46927
|
+
props: { handleDOMEvents: { compositionend(view) {
|
|
46928
|
+
Promise.resolve().then(() => void 0).then(() => {
|
|
46929
|
+
if (view.isDestroyed || view.composing) return;
|
|
46930
|
+
const pending = held.getState(view.state);
|
|
46931
|
+
const tr = pending && finish(view.state, pending, type());
|
|
46932
|
+
if (tr) view.dispatch(tr.setMeta("appendedTransaction", tr));
|
|
46933
|
+
});
|
|
46934
|
+
return false;
|
|
46935
|
+
} } },
|
|
46936
|
+
appendTransaction(transactions, oldState, newState) {
|
|
46937
|
+
const code = type();
|
|
46938
|
+
const stored = oldState.storedMarks;
|
|
46939
|
+
if (!stored || !code.isInSet(stored) || composing?.composing || transactions.some((tr) => tr.getMeta("composition"))) return null;
|
|
46940
|
+
const { $from } = newState.selection;
|
|
46941
|
+
if ($from.start() !== oldState.selection.$from.start()) return newState.storedMarks && code.isInSet(newState.storedMarks) ? newState.tr.setStoredMarks(code.removeFromSet(newState.storedMarks)) : null;
|
|
46942
|
+
const before = $from.nodeBefore;
|
|
46943
|
+
if (newState.storedMarks || !transactions.some((tr) => tr.docChanged) || !newState.selection.empty || !before?.isText || !code.isInSet(before.marks)) return null;
|
|
46944
|
+
return newState.tr.setStoredMarks(stored);
|
|
46945
|
+
}
|
|
46946
|
+
});
|
|
46947
|
+
});
|
|
46948
|
+
//#endregion
|
|
46422
46949
|
//#region src/source.ts
|
|
46423
46950
|
var sourceAttribute = "inkkitSource";
|
|
46951
|
+
var completedLines = /* @__PURE__ */ new WeakMap();
|
|
46952
|
+
function completedSource(node) {
|
|
46953
|
+
const cached = completedLines.get(node);
|
|
46954
|
+
if (cached) return cached;
|
|
46955
|
+
let result = node;
|
|
46956
|
+
if (node.type.name === "paragraph" || node.type.name === "heading" && node.attrs.form === "setext") {
|
|
46957
|
+
let end = node.content.size;
|
|
46958
|
+
for (let index = node.childCount - 1; index >= 0; index--) {
|
|
46959
|
+
const child = node.child(index);
|
|
46960
|
+
if (child.type.name !== "hardbreak" || child.attrs.isInline || child.attrs.isHTML) break;
|
|
46961
|
+
end -= child.nodeSize;
|
|
46962
|
+
}
|
|
46963
|
+
if (end !== node.content.size) result = node.copy(node.content.cut(0, end));
|
|
46964
|
+
} else if (!node.isLeaf && !node.isTextblock) {
|
|
46965
|
+
const children = [];
|
|
46966
|
+
node.forEach((child) => children.push(completedSource(child)));
|
|
46967
|
+
if (children.some((child, index) => child !== node.child(index))) result = node.copy(Fragment.fromArray(children));
|
|
46968
|
+
}
|
|
46969
|
+
completedLines.set(node, result);
|
|
46970
|
+
return result;
|
|
46971
|
+
}
|
|
46424
46972
|
function cleanSourceDoc(doc) {
|
|
46973
|
+
doc = completedSource(doc);
|
|
46425
46974
|
return doc.attrs["inkkitSource"] == null ? doc : doc.type.create({
|
|
46426
46975
|
...doc.attrs,
|
|
46427
46976
|
[sourceAttribute]: null
|
|
@@ -48564,6 +49113,7 @@ function writesBare(node, index, ancestors) {
|
|
|
48564
49113
|
const follows = (parent, text) => {
|
|
48565
49114
|
if (text.type !== "text") return false;
|
|
48566
49115
|
const run = /^\S*/.exec(text.value)[0];
|
|
49116
|
+
if (!node.url.startsWith("mailto:") && blocks$2.has(parent.type) && parent.children.at(-1) === text && /^[ \t]+$/.test(text.value.slice(run.length))) return false;
|
|
48567
49117
|
return trailing.test(run) && (run.length < text.value.length || blocks$2.has(parent.type) && parent.children.at(-1) === text);
|
|
48568
49118
|
};
|
|
48569
49119
|
const side = (step) => {
|
|
@@ -48723,6 +49273,10 @@ function remarkDialect() {
|
|
|
48723
49273
|
]
|
|
48724
49274
|
}],
|
|
48725
49275
|
handlers: {
|
|
49276
|
+
break(node, parent, state, info) {
|
|
49277
|
+
const next = parent?.children[parent.children.indexOf(node) + 1];
|
|
49278
|
+
return next?.type === "inkkitCommentInline" && next.syntax === "html" ? "<br />" : handle.break(node, parent, state, info);
|
|
49279
|
+
},
|
|
48726
49280
|
text(node, parent, state, info) {
|
|
48727
49281
|
const value = handle.text(node, parent, state, info);
|
|
48728
49282
|
if (!state.stack.includes("tableCell") || parent?.type !== "paragraph" && parent?.type !== "tableCell") return value;
|
|
@@ -48754,12 +49308,11 @@ function padShortRows(node) {
|
|
|
48754
49308
|
if ("children" in node) node.children.forEach(padShortRows);
|
|
48755
49309
|
}
|
|
48756
49310
|
var remarkDialectPlugin = $remark("remarkDialect", () => remarkDialect);
|
|
48757
|
-
var commonmarkWithLiteralReferences = commonmark.filter((plugin) => !remarkInlineLinkPlugin.includes(plugin) && plugin !== hardbreakClearMarkPlugin && plugin !== syncHeadingIdPlugin && plugin !== createCodeBlockInputRule);
|
|
49311
|
+
var commonmarkWithLiteralReferences = commonmark.filter((plugin) => !remarkInlineLinkPlugin.includes(plugin) && plugin !== hardbreakClearMarkPlugin && !hardbreakKeymap.some((part) => part === plugin) && plugin !== syncHeadingIdPlugin && plugin !== createCodeBlockInputRule);
|
|
48758
49312
|
var breaksWithoutMarks = $prose((ctx) => new Plugin({
|
|
48759
49313
|
key: new PluginKey("inkkitBreaksWithoutMarks"),
|
|
48760
49314
|
appendTransaction(transactions, oldState, newState) {
|
|
48761
49315
|
if (!transactions.some((tr) => tr.docChanged)) return null;
|
|
48762
|
-
const inserted = transactions.some((tr) => tr.getMeta("hardbreak"));
|
|
48763
49316
|
const start = oldState.doc.content.findDiffStart(newState.doc.content);
|
|
48764
49317
|
if (start == null) return null;
|
|
48765
49318
|
const end = oldState.doc.content.findDiffEnd(newState.doc.content).b;
|
|
@@ -48767,7 +49320,7 @@ var breaksWithoutMarks = $prose((ctx) => new Plugin({
|
|
|
48767
49320
|
const tr = newState.tr;
|
|
48768
49321
|
newState.doc.nodesBetween(start, Math.max(start, end), (node, pos) => {
|
|
48769
49322
|
if (node.type !== type) return;
|
|
48770
|
-
for (const mark of node.marks) if (
|
|
49323
|
+
for (const mark of node.marks) if (mark.type.spec.code) tr.removeMark(pos, pos + 1, mark.type);
|
|
48771
49324
|
});
|
|
48772
49325
|
return tr.steps.length ? tr : null;
|
|
48773
49326
|
}
|
|
@@ -48801,6 +49354,36 @@ var preserveSpacerParagraphs = paragraphSchema.extendSchema((base) => (ctx) => {
|
|
|
48801
49354
|
}
|
|
48802
49355
|
};
|
|
48803
49356
|
});
|
|
49357
|
+
var headingsWithBreaks = headingSchema.extendSchema((base) => (ctx) => {
|
|
49358
|
+
const schema = base(ctx);
|
|
49359
|
+
return {
|
|
49360
|
+
...schema,
|
|
49361
|
+
attrs: {
|
|
49362
|
+
...schema.attrs,
|
|
49363
|
+
form: { default: "atx" }
|
|
49364
|
+
},
|
|
49365
|
+
parseMarkdown: {
|
|
49366
|
+
...schema.parseMarkdown,
|
|
49367
|
+
runner(state, node, type) {
|
|
49368
|
+
const position = node.position;
|
|
49369
|
+
state.openNode(type, {
|
|
49370
|
+
level: node.depth,
|
|
49371
|
+
form: position && position.end.line > position.start.line ? "setext" : "atx"
|
|
49372
|
+
});
|
|
49373
|
+
state.next(node.children);
|
|
49374
|
+
state.closeNode();
|
|
49375
|
+
}
|
|
49376
|
+
},
|
|
49377
|
+
toMarkdown: {
|
|
49378
|
+
...schema.toMarkdown,
|
|
49379
|
+
runner(state, node) {
|
|
49380
|
+
state.openNode("heading", void 0, { depth: node.attrs.level });
|
|
49381
|
+
state.next(node.content);
|
|
49382
|
+
state.closeNode();
|
|
49383
|
+
}
|
|
49384
|
+
}
|
|
49385
|
+
};
|
|
49386
|
+
});
|
|
48804
49387
|
var visibleSoftbreaks = hardbreakSchema.extendSchema((base) => (ctx) => {
|
|
48805
49388
|
const schema = base(ctx);
|
|
48806
49389
|
return {
|
|
@@ -48897,10 +49480,14 @@ function cellToMarkdown(base) {
|
|
|
48897
49480
|
}
|
|
48898
49481
|
};
|
|
48899
49482
|
}
|
|
48900
|
-
var
|
|
49483
|
+
var breakKeymap = $prose(() => keymap$3({ "Shift-Enter": (state, dispatch, view) => {
|
|
48901
49484
|
const { $from } = state.selection;
|
|
48902
|
-
if (
|
|
48903
|
-
|
|
49485
|
+
if (!(state.selection instanceof TextSelection) || $from.parent.type.spec.code) return false;
|
|
49486
|
+
const isHTML = htmlBreakAt($from);
|
|
49487
|
+
if (dispatch) {
|
|
49488
|
+
dispatch(closeHistory(state.tr).replaceSelectionWith(state.schema.nodes.hardbreak.create({ isHTML }), false).scrollIntoView());
|
|
49489
|
+
if (view) dispatch(closeHistory(view.state.tr).setMeta("addToHistory", false));
|
|
49490
|
+
}
|
|
48904
49491
|
return true;
|
|
48905
49492
|
} }));
|
|
48906
49493
|
var listItems = extendListItemSchemaForTask.extendSchema((previous) => (ctx) => {
|
|
@@ -48986,7 +49573,7 @@ var tables = [
|
|
|
48986
49573
|
].flat();
|
|
48987
49574
|
function createDialect(images, wikiLinks = false, files = false) {
|
|
48988
49575
|
return [
|
|
48989
|
-
|
|
49576
|
+
breakKeymap,
|
|
48990
49577
|
remarkCodeFences,
|
|
48991
49578
|
remarkReferencesPlugin,
|
|
48992
49579
|
remarkLinkFormsPlugin,
|
|
@@ -49014,9 +49601,11 @@ function createDialect(images, wikiLinks = false, files = false) {
|
|
|
49014
49601
|
joinKeepingSourceKeymap,
|
|
49015
49602
|
preserveSpacerParagraphs,
|
|
49016
49603
|
visibleSoftbreaks,
|
|
49604
|
+
headingsWithBreaks,
|
|
49017
49605
|
normalizedImages,
|
|
49018
49606
|
imageBlocks,
|
|
49019
49607
|
autolinkLiterals,
|
|
49608
|
+
storedInlineCode,
|
|
49020
49609
|
breaksWithoutMarks,
|
|
49021
49610
|
listItems,
|
|
49022
49611
|
strikethroughAttr,
|
|
@@ -49025,6 +49614,7 @@ function createDialect(images, wikiLinks = false, files = false) {
|
|
|
49025
49614
|
strikethroughKeymap,
|
|
49026
49615
|
toggleStrikethroughCommand,
|
|
49027
49616
|
wrapInTaskListInputRule,
|
|
49617
|
+
smartPunctuation,
|
|
49028
49618
|
remarkDialectPlugin,
|
|
49029
49619
|
tables,
|
|
49030
49620
|
literalBlock,
|
|
@@ -49305,7 +49895,7 @@ function selectionContent(doc, content) {
|
|
|
49305
49895
|
return content.append(Fragment.fromArray(extra));
|
|
49306
49896
|
}
|
|
49307
49897
|
function selectionMarkdown(ctx, doc, content) {
|
|
49308
|
-
return serialize(ctx, doc.type.create(null, selectionContent(doc, content)));
|
|
49898
|
+
return serialize(ctx, cleanSourceDoc(doc.type.create(null, selectionContent(doc, content))));
|
|
49309
49899
|
}
|
|
49310
49900
|
function referenceMetadata(ctx, doc, content) {
|
|
49311
49901
|
doc = doc.copy(shareableFragment(doc.content));
|
|
@@ -49899,9 +50489,116 @@ function tableAvailability(ctx) {
|
|
|
49899
50489
|
available.sortRows = [...body].sort((a, b) => compareCells(a.key, b.key, "text", "ascending") || a.index - b.index).some((row, index) => row !== body[index]);
|
|
49900
50490
|
return available;
|
|
49901
50491
|
}
|
|
50492
|
+
/** Trims the whitespace at both ends of a cell's inline content. */
|
|
50493
|
+
function trimCell(nodes) {
|
|
50494
|
+
const trimmed = [...nodes];
|
|
50495
|
+
for (const [edge, trim] of [[0, (text) => text.trimStart()], [-1, (text) => text.trimEnd()]]) for (;;) {
|
|
50496
|
+
const node = trimmed.at(edge);
|
|
50497
|
+
if (!node?.text) break;
|
|
50498
|
+
const text = trim(node.text);
|
|
50499
|
+
if (text) {
|
|
50500
|
+
trimmed.splice(edge < 0 ? trimmed.length - 1 : 0, 1, node.type.schema.text(text, node.marks));
|
|
50501
|
+
break;
|
|
50502
|
+
}
|
|
50503
|
+
trimmed.splice(edge < 0 ? trimmed.length - 1 : 0, 1);
|
|
50504
|
+
}
|
|
50505
|
+
return trimmed;
|
|
50506
|
+
}
|
|
50507
|
+
/**
|
|
50508
|
+
* The cells of a paragraph that is one table row typed as Markdown, such as `| Name | Date |`: it
|
|
50509
|
+
* starts and ends with a pipe and holds at least two cells. A pipe written `\|` or inside inline
|
|
50510
|
+
* code belongs to its cell. Returns nothing for any other paragraph, including one with a line
|
|
50511
|
+
* break or an inline node, which a cell could not hold the same way.
|
|
50512
|
+
*/
|
|
50513
|
+
function typedRowCells(paragraph) {
|
|
50514
|
+
const rows = [[]];
|
|
50515
|
+
for (let index = 0; index < paragraph.childCount; index++) {
|
|
50516
|
+
const child = paragraph.child(index);
|
|
50517
|
+
if (!child.isText || /[\r\n]/.test(child.text)) return void 0;
|
|
50518
|
+
if (child.marks.some((mark) => mark.type.spec.code)) {
|
|
50519
|
+
rows.at(-1).push(child);
|
|
50520
|
+
continue;
|
|
50521
|
+
}
|
|
50522
|
+
let piece = "", slashes = 0;
|
|
50523
|
+
const flush = () => {
|
|
50524
|
+
if (piece) rows.at(-1).push(child.type.schema.text(piece, child.marks));
|
|
50525
|
+
piece = "";
|
|
50526
|
+
};
|
|
50527
|
+
for (const character of child.text) if (character !== "|") {
|
|
50528
|
+
slashes = character === "\\" ? slashes + 1 : 0;
|
|
50529
|
+
piece += character;
|
|
50530
|
+
} else if (slashes % 2) {
|
|
50531
|
+
piece = piece.slice(0, -1) + character;
|
|
50532
|
+
slashes = 0;
|
|
50533
|
+
} else {
|
|
50534
|
+
flush();
|
|
50535
|
+
rows.push([]);
|
|
50536
|
+
slashes = 0;
|
|
50537
|
+
}
|
|
50538
|
+
flush();
|
|
50539
|
+
}
|
|
50540
|
+
const blank = (cell) => cell.every((node) => node.isText && !node.text.trim());
|
|
50541
|
+
if (rows.length < 4 || !blank(rows[0]) || !blank(rows.at(-1))) return void 0;
|
|
50542
|
+
const cells = rows.slice(1, -1);
|
|
50543
|
+
return cells.length <= 100 ? cells.map(trimCell) : void 0;
|
|
50544
|
+
}
|
|
50545
|
+
/**
|
|
50546
|
+
* Turns the paragraph holding the caret at its end into a table when it is a typed table row: the
|
|
50547
|
+
* typed cells are the header, one empty row follows, and the caret is in its first cell. It builds
|
|
50548
|
+
* the table `table('insert')` does and replaces the paragraph in one undo step of its own, so Undo
|
|
50549
|
+
* restores the typed line with the caret at its end.
|
|
50550
|
+
*/
|
|
50551
|
+
function typedRowToTable(ctx) {
|
|
50552
|
+
return (state, dispatch) => {
|
|
50553
|
+
const view = ctx.get(editorViewCtx);
|
|
50554
|
+
const { $cursor } = state.selection;
|
|
50555
|
+
if (!$cursor || !view.editable || view.composing || $cursor.parent.type.name !== "paragraph" || $cursor.parentOffset !== $cursor.parent.content.size || $cursor.depth < 1) return false;
|
|
50556
|
+
const cells = typedRowCells($cursor.parent);
|
|
50557
|
+
if (!cells) return false;
|
|
50558
|
+
const template = createTable(ctx, 2, cells.length);
|
|
50559
|
+
const [head, ...rest] = [template.child(0), template.child(1)];
|
|
50560
|
+
const paragraph = state.schema.nodes.paragraph;
|
|
50561
|
+
let table;
|
|
50562
|
+
try {
|
|
50563
|
+
table = template.copy(Fragment.from([head.copy(Fragment.fromArray(cells.map((cell, column) => {
|
|
50564
|
+
return head.child(column).copy(Fragment.from(paragraph.create(null, cell)));
|
|
50565
|
+
}))), ...rest]));
|
|
50566
|
+
table.check();
|
|
50567
|
+
} catch {
|
|
50568
|
+
return false;
|
|
50569
|
+
}
|
|
50570
|
+
const index = $cursor.index(-1), parent = $cursor.node(-1);
|
|
50571
|
+
const replaces = parent.canReplaceWith(index, index + 1, table.type);
|
|
50572
|
+
if (!replaces && (parent.attrs.checked != null || !parent.canReplaceWith(index + 1, index + 1, table.type))) return false;
|
|
50573
|
+
if (dispatch) {
|
|
50574
|
+
const tr = state.tr;
|
|
50575
|
+
if (replaces) tr.replaceWith($cursor.before(), $cursor.after(), table);
|
|
50576
|
+
else {
|
|
50577
|
+
tr.delete($cursor.start(), $cursor.end());
|
|
50578
|
+
tr.insert($cursor.start() + 1, table);
|
|
50579
|
+
}
|
|
50580
|
+
const body = (replaces ? $cursor.before() : $cursor.start() + 1) + 1 + table.child(0).nodeSize;
|
|
50581
|
+
tr.setSelection(Selection.findFrom(tr.doc.resolve(body), 1, true));
|
|
50582
|
+
dispatchTableOperation(view, tr);
|
|
50583
|
+
}
|
|
50584
|
+
return true;
|
|
50585
|
+
};
|
|
50586
|
+
}
|
|
49902
50587
|
var tablePlugins = [
|
|
49903
50588
|
moveRowCommand,
|
|
49904
50589
|
moveColCommand,
|
|
50590
|
+
$shortcut((ctx) => ({
|
|
50591
|
+
Enter: {
|
|
50592
|
+
key: "Enter",
|
|
50593
|
+
onRun: () => typedRowToTable(ctx),
|
|
50594
|
+
priority: 60
|
|
50595
|
+
},
|
|
50596
|
+
Tab: {
|
|
50597
|
+
key: "Tab",
|
|
50598
|
+
onRun: () => typedRowToTable(ctx),
|
|
50599
|
+
priority: 60
|
|
50600
|
+
}
|
|
50601
|
+
})),
|
|
49905
50602
|
$prose(() => keymap$3({
|
|
49906
50603
|
Tab: goToNextCell(1),
|
|
49907
50604
|
"Shift-Tab": goToNextCell(-1)
|
|
@@ -50970,6 +51667,101 @@ function literalVisibleRanges(plain, viewport) {
|
|
|
50970
51667
|
}) ?? [];
|
|
50971
51668
|
}
|
|
50972
51669
|
//#endregion
|
|
51670
|
+
//#region src/block-move.ts
|
|
51671
|
+
var containers = /* @__PURE__ */ new Set([
|
|
51672
|
+
"doc",
|
|
51673
|
+
"blockquote",
|
|
51674
|
+
"inkkit_callout",
|
|
51675
|
+
"bullet_list",
|
|
51676
|
+
"ordered_list",
|
|
51677
|
+
"footnote_definition"
|
|
51678
|
+
]);
|
|
51679
|
+
var tableParts = /* @__PURE__ */ new Set([
|
|
51680
|
+
"table",
|
|
51681
|
+
"table_row",
|
|
51682
|
+
"table_header_row",
|
|
51683
|
+
"table_cell",
|
|
51684
|
+
"table_header"
|
|
51685
|
+
]);
|
|
51686
|
+
/** On a move's transaction, the blocks it carried, so their source can go
|
|
51687
|
+
* with them. */
|
|
51688
|
+
var carriedBlocks = new PluginKey("carriedBlocks");
|
|
51689
|
+
var frontMatter = (node) => node.type.name === "literal_markdown" && /^(?:---|\+\+\+)[ \t]*\r?\n/.test(node.textContent);
|
|
51690
|
+
/**
|
|
51691
|
+
* The move a selection makes, or `'boundary'` when its blocks are already
|
|
51692
|
+
* first or last in their container, or `undefined` when it has no blocks to
|
|
51693
|
+
* move, such as in a table, where the table's own row moves apply.
|
|
51694
|
+
*/
|
|
51695
|
+
function plan(state, direction) {
|
|
51696
|
+
const { $from, $to } = state.selection;
|
|
51697
|
+
for (const $pos of [$from, $to]) for (let depth = $pos.depth; depth > 0; depth--) if (tableParts.has($pos.node(depth).type.name)) return void 0;
|
|
51698
|
+
const range = $from.blockRange($to, (node) => containers.has(node.type.name));
|
|
51699
|
+
if (!range) return void 0;
|
|
51700
|
+
const container = range.parent;
|
|
51701
|
+
const first = range.depth === 0 && frontMatter(container.child(0)) ? 1 : 0;
|
|
51702
|
+
if (range.startIndex < first) return void 0;
|
|
51703
|
+
const hidden = (index) => !commentsVisible(state) && container.child(index).type.name === "comment_block";
|
|
51704
|
+
const up = direction === "up";
|
|
51705
|
+
let index = up ? range.startIndex - 1 : range.endIndex;
|
|
51706
|
+
const step = up ? -1 : 1;
|
|
51707
|
+
const inside = (index) => up ? index >= first : index < container.childCount;
|
|
51708
|
+
while (inside(index) && hidden(index)) index += step;
|
|
51709
|
+
if (!inside(index)) return "boundary";
|
|
51710
|
+
const past = up ? [index, range.startIndex] : [range.endIndex, index + 1];
|
|
51711
|
+
return {
|
|
51712
|
+
depth: range.depth,
|
|
51713
|
+
start: range.startIndex,
|
|
51714
|
+
end: range.endIndex,
|
|
51715
|
+
past
|
|
51716
|
+
};
|
|
51717
|
+
}
|
|
51718
|
+
/** Whether `moveBlock` would move the blocks at the selection. */
|
|
51719
|
+
function canMoveBlock(state, direction) {
|
|
51720
|
+
return typeof plan(state, direction) === "object";
|
|
51721
|
+
}
|
|
51722
|
+
/**
|
|
51723
|
+
* `'move'` when `moveBlock` would move the blocks at the selection,
|
|
51724
|
+
* `'boundary'` when they are already first or last in their container, and
|
|
51725
|
+
* undefined when there are none to move, as in a table.
|
|
51726
|
+
*/
|
|
51727
|
+
function blockMove(state, direction) {
|
|
51728
|
+
const move = plan(state, direction);
|
|
51729
|
+
return typeof move === "object" ? "move" : move;
|
|
51730
|
+
}
|
|
51731
|
+
/**
|
|
51732
|
+
* Moves the blocks at the selection past their neighbour in `direction`, as
|
|
51733
|
+
* one step that keeps the moved and the passed nodes as they are, so their
|
|
51734
|
+
* authored source travels with them. Returns undefined when nothing moves.
|
|
51735
|
+
*/
|
|
51736
|
+
function moveBlockTransaction(state, direction) {
|
|
51737
|
+
const move = plan(state, direction);
|
|
51738
|
+
if (typeof move !== "object") return void 0;
|
|
51739
|
+
const { depth, start, end, past } = move;
|
|
51740
|
+
const $at = state.selection.$from;
|
|
51741
|
+
const container = $at.node(depth);
|
|
51742
|
+
const offset = (index) => $at.posAtIndex(index, depth);
|
|
51743
|
+
const children = (from, to) => {
|
|
51744
|
+
const nodes = [];
|
|
51745
|
+
for (let index = from; index < to; index++) nodes.push(container.child(index));
|
|
51746
|
+
return nodes;
|
|
51747
|
+
};
|
|
51748
|
+
const moved = children(start, end);
|
|
51749
|
+
const passed = children(past[0], past[1]);
|
|
51750
|
+
const up = direction === "up";
|
|
51751
|
+
const from = offset(up ? past[0] : start);
|
|
51752
|
+
const to = offset(up ? end : past[1]);
|
|
51753
|
+
const reordered = up ? [...moved, ...passed] : [...passed, ...moved];
|
|
51754
|
+
const tr = state.tr.replaceWith(from, to, Fragment.fromArray(reordered)).setMeta(carriedBlocks, reordered);
|
|
51755
|
+
const shift = up ? -passed.reduce((size, node) => size + node.nodeSize, 0) : passed.reduce((size, node) => size + node.nodeSize, 0);
|
|
51756
|
+
tr.setSelection(shifted(state.selection, tr.doc, shift));
|
|
51757
|
+
return tr.scrollIntoView();
|
|
51758
|
+
}
|
|
51759
|
+
function shifted(selection, doc, shift) {
|
|
51760
|
+
if (selection instanceof NodeSelection) return NodeSelection.create(doc, selection.from + shift);
|
|
51761
|
+
if (selection instanceof TextSelection) return TextSelection.create(doc, selection.anchor + shift, selection.head + shift);
|
|
51762
|
+
return Selection.near(doc.resolve(selection.head + shift));
|
|
51763
|
+
}
|
|
51764
|
+
//#endregion
|
|
50973
51765
|
//#region src/scroll.ts
|
|
50974
51766
|
/** Rounds a distance away from zero, to a whole number of pixels. */
|
|
50975
51767
|
var scrollOutward = (distance) => distance > 0 ? Math.ceil(distance) : Math.floor(distance);
|
|
@@ -53106,9 +53898,10 @@ function replacementSlice(state, from, to, value) {
|
|
|
53106
53898
|
if (start.parent.type.spec.code) {
|
|
53107
53899
|
if (value) nodes.push(state.schema.text(value, marks));
|
|
53108
53900
|
} else {
|
|
53901
|
+
const isHTML = htmlBreakAt(start);
|
|
53109
53902
|
const lines = value.split("\n");
|
|
53110
53903
|
lines.forEach((line, index) => {
|
|
53111
|
-
if (index) nodes.push(state.schema.nodes.hardbreak.create({ isHTML
|
|
53904
|
+
if (index) nodes.push(state.schema.nodes.hardbreak.create({ isHTML }, null, index === lines.length - 1 && line === "" ? [] : marks));
|
|
53112
53905
|
if (line) nodes.push(state.schema.text(line, marks));
|
|
53113
53906
|
});
|
|
53114
53907
|
}
|
|
@@ -53154,8 +53947,8 @@ function replaceFormattedRange(view, from, to, replacement, preflight) {
|
|
|
53154
53947
|
const start = view.state.doc.resolve(from);
|
|
53155
53948
|
const end = view.state.doc.resolve(to);
|
|
53156
53949
|
let textOnly = start.parent === end.parent && start.parent.inlineContent;
|
|
53157
|
-
|
|
53158
|
-
if (!node.isText
|
|
53950
|
+
if (textOnly) start.parent.nodesBetween(start.parentOffset, end.parentOffset, (node) => {
|
|
53951
|
+
if (!node.isText) textOnly = false;
|
|
53159
53952
|
});
|
|
53160
53953
|
if (!textOnly) throw new InkKitError("invalid-range", "Replacement requires literal text within one block");
|
|
53161
53954
|
const value = replacement.replace(/\r\n?/g, "\n");
|
|
@@ -53704,6 +54497,8 @@ var shortcutNames = [
|
|
|
53704
54497
|
...formatShortcuts,
|
|
53705
54498
|
"undo",
|
|
53706
54499
|
"redo",
|
|
54500
|
+
"moveBlockUp",
|
|
54501
|
+
"moveBlockDown",
|
|
53707
54502
|
...tableCommands.map(tableShortcut)
|
|
53708
54503
|
];
|
|
53709
54504
|
/** Checks a keymap and drops omitted entries, so a `null` binding keeps its default. */
|
|
@@ -53732,11 +54527,13 @@ function textInputPreferences(value, name) {
|
|
|
53732
54527
|
const record = expectRecord(value, name, [
|
|
53733
54528
|
"spellcheck",
|
|
53734
54529
|
"autocorrect",
|
|
53735
|
-
"autocapitalize"
|
|
54530
|
+
"autocapitalize",
|
|
54531
|
+
"smartPunctuation"
|
|
53736
54532
|
]);
|
|
53737
54533
|
return {
|
|
53738
54534
|
spellcheck: optionalBoolean(record.spellcheck, `${name}.spellcheck`),
|
|
53739
54535
|
autocorrect: optionalBoolean(record.autocorrect, `${name}.autocorrect`),
|
|
54536
|
+
smartPunctuation: optionalBoolean(record.smartPunctuation, `${name}.smartPunctuation`),
|
|
53740
54537
|
autocapitalize: isOmitted(record.autocapitalize) ? void 0 : expectOneOf(record.autocapitalize, autocapitalizeValues, `${name}.autocapitalize`)
|
|
53741
54538
|
};
|
|
53742
54539
|
}
|
|
@@ -54150,6 +54947,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
54150
54947
|
ready = false;
|
|
54151
54948
|
destroyed = false;
|
|
54152
54949
|
preservation;
|
|
54950
|
+
carried;
|
|
54153
54951
|
pasteController;
|
|
54154
54952
|
plain;
|
|
54155
54953
|
root;
|
|
@@ -54180,7 +54978,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
54180
54978
|
changePlugin = $prose(() => new Plugin({
|
|
54181
54979
|
key: new PluginKey("documentChanges"),
|
|
54182
54980
|
view: () => ({ update: (view, previous) => {
|
|
54183
|
-
if (this.loading || view.state.doc
|
|
54981
|
+
if (this.loading || this.sameDocument(view.state.doc, previous.doc)) return;
|
|
54184
54982
|
if (this.syncingSource) {
|
|
54185
54983
|
this.mediaPolicy();
|
|
54186
54984
|
return;
|
|
@@ -54442,7 +55240,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
54442
55240
|
}
|
|
54443
55241
|
this.publishCommandState();
|
|
54444
55242
|
}
|
|
54445
|
-
/** Replaces the input
|
|
55243
|
+
/** Replaces the input preferences. A field left out takes its default. Throws `composition`
|
|
54446
55244
|
* during text composition. */
|
|
54447
55245
|
setTextInputPreferences(preferences) {
|
|
54448
55246
|
this.assertAlive();
|
|
@@ -54542,7 +55340,9 @@ var InkKitEditor = class InkKitEditor {
|
|
|
54542
55340
|
insertFootnote: formatted,
|
|
54543
55341
|
editReferenceDefinition: formatted && referenceDefinitions(state.doc).size > 0,
|
|
54544
55342
|
format,
|
|
54545
|
-
table: tables
|
|
55343
|
+
table: tables,
|
|
55344
|
+
moveBlockUp: formatted && canMoveBlock(state, "up"),
|
|
55345
|
+
moveBlockDown: formatted && canMoveBlock(state, "down")
|
|
54546
55346
|
}
|
|
54547
55347
|
};
|
|
54548
55348
|
}
|
|
@@ -54564,6 +55364,17 @@ var InkKitEditor = class InkKitEditor {
|
|
|
54564
55364
|
range = new NodeRange(state.doc.resolve($from.before(depth)), state.doc.resolve($from.after(depth)), depth - 1);
|
|
54565
55365
|
return !!findWrapping(range, type);
|
|
54566
55366
|
}
|
|
55367
|
+
historyInputPlugin = $prose(() => new Plugin({
|
|
55368
|
+
key: new PluginKey("inkkitHistoryInput"),
|
|
55369
|
+
props: { handleDOMEvents: { beforeinput: (_view, event) => {
|
|
55370
|
+
if (!this.writable) return false;
|
|
55371
|
+
const name = event.inputType === "historyUndo" ? "undo" : event.inputType === "historyRedo" ? "redo" : void 0;
|
|
55372
|
+
if (!name) return false;
|
|
55373
|
+
event.preventDefault();
|
|
55374
|
+
if (this.ready && this.commandState().commands[name]) this.forPerson(() => this[name](), true);
|
|
55375
|
+
return true;
|
|
55376
|
+
} } }
|
|
55377
|
+
}));
|
|
54567
55378
|
policyPlugin = $prose(() => new Plugin({
|
|
54568
55379
|
key: new PluginKey("inkkitInputPolicy"),
|
|
54569
55380
|
filterTransaction: (tr) => this.loading || this.writable || this.syncingSource || !tr.docChanged && !tr.storedMarksSet,
|
|
@@ -54618,7 +55429,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
54618
55429
|
this.sourcePreservations.set(provenance, preservation);
|
|
54619
55430
|
}
|
|
54620
55431
|
}
|
|
54621
|
-
text = preservation.serialize(cleanSourceDoc(doc));
|
|
55432
|
+
text = preservation.serialize(cleanSourceDoc(doc), this.carried);
|
|
54622
55433
|
} catch (error) {
|
|
54623
55434
|
throw coded(error, "preservation");
|
|
54624
55435
|
}
|
|
@@ -54834,7 +55645,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
54834
55645
|
this.assertMutation(expectedGeneration);
|
|
54835
55646
|
if (this.literalSurface && this.stepTypedSource("undo")) return true;
|
|
54836
55647
|
const view = this.editor.ctx.get(editorViewCtx);
|
|
54837
|
-
const undone = undo(view.state, view.dispatch);
|
|
55648
|
+
const undone = !this.literalSurface && undoSmartPunctuation(view.state, view.dispatch) || undo(view.state, view.dispatch);
|
|
54838
55649
|
if (undone) {
|
|
54839
55650
|
if (this.literalSurface && this.undoneSteps.length) this.formattedUndone++;
|
|
54840
55651
|
else this.undoneSteps = [];
|
|
@@ -55000,10 +55811,11 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55000
55811
|
const { schema } = view.state;
|
|
55001
55812
|
const marks = view.state.storedMarks ?? (view.state.selection.empty ? view.state.selection.$from.marks() : view.state.selection.$from.marksAcross(view.state.selection.$to)) ?? [];
|
|
55002
55813
|
const children = [];
|
|
55814
|
+
const isHTML = !inHiddenComment && htmlBreakAt(view.state.selection.$from);
|
|
55003
55815
|
const lines = text.replace(/\r\n?/g, "\n").split("\n");
|
|
55004
55816
|
lines.forEach((line, index) => {
|
|
55005
55817
|
const finalBreak = index === lines.length - 1 && line === "";
|
|
55006
|
-
if (index) children.push(schema.nodes.hardbreak.create({ isHTML
|
|
55818
|
+
if (index) children.push(schema.nodes.hardbreak.create({ isHTML }, null, finalBreak ? [] : marks));
|
|
55007
55819
|
if (line) children.push(schema.text(line, marks));
|
|
55008
55820
|
});
|
|
55009
55821
|
if (!children.length) {
|
|
@@ -55013,8 +55825,9 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55013
55825
|
const paragraph = schema.nodes.paragraph.create(null, children);
|
|
55014
55826
|
const transaction = inHiddenComment ? insertAfterHiddenComment(view.state, Fragment.from(paragraph)) : view.state.tr.replaceSelection(new Slice(Fragment.from(paragraph), 1, 1)).scrollIntoView();
|
|
55015
55827
|
if (!transaction) return;
|
|
55016
|
-
|
|
55017
|
-
view.dispatch(transaction);
|
|
55828
|
+
const isolated = lines.length > 1;
|
|
55829
|
+
view.dispatch(isolated ? closeHistory(transaction) : transaction);
|
|
55830
|
+
if (isolated) view.dispatch(closeHistory(view.state.tr).setMeta("addToHistory", false));
|
|
55018
55831
|
}
|
|
55019
55832
|
}
|
|
55020
55833
|
}
|
|
@@ -55027,6 +55840,21 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55027
55840
|
if (this.literalSurface) return false;
|
|
55028
55841
|
return tableCommand(this.editor.ctx, command, options);
|
|
55029
55842
|
}
|
|
55843
|
+
/** Moves the blocks at the selection one place up or down in their list, quote, callout, footnote
|
|
55844
|
+
* or note, as one undo step. Returns whether they moved: false in source and TXT modes, in a
|
|
55845
|
+
* table, and when they are already first or last. */
|
|
55846
|
+
moveBlock(direction, expectedGeneration) {
|
|
55847
|
+
this.assertAlive();
|
|
55848
|
+
expectOneOf(direction, ["up", "down"], "direction");
|
|
55849
|
+
this.assertMutation(expectedGeneration);
|
|
55850
|
+
if (this.literalSurface) return false;
|
|
55851
|
+
const view = this.editor.ctx.get(editorViewCtx);
|
|
55852
|
+
const tr = moveBlockTransaction(view.state, direction);
|
|
55853
|
+
if (!tr) return false;
|
|
55854
|
+
view.dispatch(closeHistory(tr));
|
|
55855
|
+
view.dispatch(closeHistory(view.state.tr).setMeta("addToHistory", false));
|
|
55856
|
+
return true;
|
|
55857
|
+
}
|
|
55030
55858
|
/** Cancels pending work and releases the editor. It never rejects. Afterwards every other member
|
|
55031
55859
|
* throws `destroyed`. */
|
|
55032
55860
|
async destroy() {
|
|
@@ -55122,6 +55950,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55122
55950
|
instance.editor = await Editor.make().config((ctx) => {
|
|
55123
55951
|
ctx.set(rootCtx, root);
|
|
55124
55952
|
ctx.set(authoredSourcesCtx.key, (doc, positions) => instance.authoredSources(doc, positions));
|
|
55953
|
+
ctx.set(smartPunctuationCtx.key, () => instance.inputPreferences.smartPunctuation === true);
|
|
55125
55954
|
ctx.update(labelsCtx.key, () => ({
|
|
55126
55955
|
...defaultLabels,
|
|
55127
55956
|
...options.labels
|
|
@@ -55159,6 +55988,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55159
55988
|
...options,
|
|
55160
55989
|
dispatchTransaction: function(tr) {
|
|
55161
55990
|
if (instance.call?.refusal && tr.docChanged) return;
|
|
55991
|
+
for (const node of tr.getMeta(carriedBlocks) ?? []) (instance.carried ??= /* @__PURE__ */ new WeakSet()).add(node);
|
|
55162
55992
|
const applied = this.state.applyTransaction(tr);
|
|
55163
55993
|
let next = applied.state;
|
|
55164
55994
|
if (!instance.loading) {
|
|
@@ -55187,7 +56017,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55187
56017
|
return true;
|
|
55188
56018
|
}
|
|
55189
56019
|
}));
|
|
55190
|
-
}).use(labelsCtx).use(instance.pasteController.plugin).use(visibleClipboard).use(instance.keymapPlugin).use(createDialect(Boolean(options.images || options.files), Boolean(options.wikiLinks), Boolean(options.files))).use(tablePlugins).use(tableBlock).use(instance.changePlugin).use(history).use(clipboard).use(cursor).use(taskListPlugin).use(quoteBackspace).use(calloutEnter).use(literalEnter).use(literalReread).use(listItemBackspace).use(listItemShiftTab).use(nestedItemEnter).use(rejoinLists).use(movedListItems).use(textInputPolicy).use(events.copy ? codeCopyPlugin((text) => events.copy?.(text)) : []).use(placeholderPlugin).use(options.rendering?.codeHighlighting === false ? [] : (await import("./highlight-
|
|
56020
|
+
}).use(labelsCtx).use(instance.pasteController.plugin).use(visibleClipboard).use(instance.keymapPlugin).use(createDialect(Boolean(options.images || options.files), Boolean(options.wikiLinks), Boolean(options.files))).use(tablePlugins).use(tableBlock).use(instance.changePlugin).use(instance.historyInputPlugin).use(history).use(clipboard).use(cursor).use(taskListPlugin).use(quoteBackspace).use(calloutEnter).use(literalEnter).use(literalReread).use(listItemBackspace).use(listItemShiftTab).use(nestedItemEnter).use(rejoinLists).use(movedListItems).use(textInputPolicy).use(events.copy ? codeCopyPlugin((text) => events.copy?.(text)) : []).use(placeholderPlugin).use(options.rendering?.codeHighlighting === false ? [] : (await import("./highlight-DQC71L-N.js")).highlightPlugin).use(options.rendering?.diagramPreview === false || !diagramsAvailable() ? [] : mermaidPreview((error) => instance.report(error))).use(selectionPlugin).use($prose(() => search())).use(instance.policyPlugin).use(options.wikiLinks ? wikiLinkView(options.wikiLinks, {
|
|
55191
56021
|
capture: () => instance.adapterCapture(),
|
|
55192
56022
|
active: () => instance.ready && !instance.destroyed && !instance.literalSurface,
|
|
55193
56023
|
labels: {
|
|
@@ -55602,12 +56432,24 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55602
56432
|
if (reveal) this.revealTextRange(range);
|
|
55603
56433
|
this.publishCommandState();
|
|
55604
56434
|
}
|
|
56435
|
+
/** Whether two documents are the same note. A move of blocks that read alike, such as a setext
|
|
56436
|
+
* heading and the same heading written with `#`, gives an equal document with other source. */
|
|
56437
|
+
sameDocument(after, before) {
|
|
56438
|
+
if (after === before) return true;
|
|
56439
|
+
if (!after.eq(before)) return false;
|
|
56440
|
+
if (!this.carried || !this.preservation) return true;
|
|
56441
|
+
try {
|
|
56442
|
+
return this.currentText(after) === this.currentText(before);
|
|
56443
|
+
} catch {
|
|
56444
|
+
return false;
|
|
56445
|
+
}
|
|
56446
|
+
}
|
|
55605
56447
|
/** Throws when a document reached by an edit, after every appended normalisation, cannot be
|
|
55606
56448
|
* saved as preserved Markdown. Dispatch and the replacement commands share this check.
|
|
55607
56449
|
* `written` is false for history steps and source replacement, which restore or supply a
|
|
55608
56450
|
* document that may hold comment text the formatted editor would refuse to accept typed. */
|
|
55609
56451
|
assertPreserved(before, after, written = true) {
|
|
55610
|
-
if (this.literalSurface ||
|
|
56452
|
+
if (this.literalSurface || this.sameDocument(after, before)) return;
|
|
55611
56453
|
if (written) assertCommentsEndWhereWritten(before, after);
|
|
55612
56454
|
if (this.preservation) this.currentText(after);
|
|
55613
56455
|
}
|
|
@@ -55784,6 +56626,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55784
56626
|
this.loading = false;
|
|
55785
56627
|
}
|
|
55786
56628
|
this.preservation = preservation;
|
|
56629
|
+
this.carried = void 0;
|
|
55787
56630
|
this.lastMarkdown = markdown;
|
|
55788
56631
|
const { doc } = view.state;
|
|
55789
56632
|
const $end = doc.resolve(doc.content.size);
|
|
@@ -55975,14 +56818,17 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55975
56818
|
this.releaseFocus();
|
|
55976
56819
|
}
|
|
55977
56820
|
/** Replaces every binding. Keys are in ProseMirror's notation. A key given to two shortcuts goes
|
|
55978
|
-
* to the later one, in the order history, formatting, tables, so it lands the same
|
|
55979
|
-
* time.
|
|
56821
|
+
* to the later one, in the order history, formatting, block moves, tables, so it lands the same
|
|
56822
|
+
* way every time. A table binding passes a key it shares with a block move to the move outside
|
|
56823
|
+
* a table. */
|
|
55980
56824
|
setKeymap(keymap) {
|
|
55981
56825
|
this.assertAlive();
|
|
55982
56826
|
keymap = keymapBindings(keymap, "keymap");
|
|
55983
56827
|
this.configuredKeys = {
|
|
55984
56828
|
undo: ["Mod-z"],
|
|
55985
56829
|
redo: ["Mod-y", "Shift-Mod-z"],
|
|
56830
|
+
moveBlockUp: ["Alt-ArrowUp"],
|
|
56831
|
+
moveBlockDown: ["Alt-ArrowDown"],
|
|
55986
56832
|
tableExit: ["Mod-Enter", "Enter"],
|
|
55987
56833
|
...keymap
|
|
55988
56834
|
};
|
|
@@ -56002,11 +56848,19 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56002
56848
|
this.forPerson(() => this.format(name), false);
|
|
56003
56849
|
return true;
|
|
56004
56850
|
};
|
|
56005
|
-
|
|
56006
|
-
|
|
56851
|
+
const moves = {};
|
|
56852
|
+
for (const [name, direction] of [["moveBlockUp", "up"], ["moveBlockDown", "down"]]) for (const key of this.configuredKeys[name] ?? []) moves[key] = bindings[key] = (state) => {
|
|
56853
|
+
if (!this.ready || !this.writable || this.literalSurface) return false;
|
|
56854
|
+
const move = blockMove(state, direction);
|
|
56855
|
+
if (!move) return false;
|
|
56856
|
+
if (move === "move" && !this.composing && !this.pasteController.pending) this.forPerson(() => this.moveBlock(direction), false);
|
|
56857
|
+
return true;
|
|
56858
|
+
};
|
|
56859
|
+
for (const command of tableCommands) for (const key of this.configuredKeys[tableShortcut(command)] ?? []) bindings[key] = (state, dispatch, view) => {
|
|
56860
|
+
if (!this.ready || !this.commandState().commands.table[command]) return moves[key]?.(state, dispatch, view) ?? false;
|
|
56007
56861
|
return this.forPerson(() => this.table(command), true);
|
|
56008
56862
|
};
|
|
56009
|
-
this.readOnlyKeys = keydownHandler(Object.fromEntries(Object.keys(bindings).map((key) => [key, () => {
|
|
56863
|
+
this.readOnlyKeys = keydownHandler(Object.fromEntries(Object.keys(bindings).filter((key) => !moves[key]).map((key) => [key, () => {
|
|
56010
56864
|
throw new InkKitError("read-only", "The editor is read-only");
|
|
56011
56865
|
}])));
|
|
56012
56866
|
this.keys = keydownHandler(bindings);
|
|
@@ -56464,6 +57318,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56464
57318
|
"replaceAll",
|
|
56465
57319
|
"format",
|
|
56466
57320
|
"table",
|
|
57321
|
+
"moveBlock",
|
|
56467
57322
|
"insertText",
|
|
56468
57323
|
"keyDown",
|
|
56469
57324
|
"insertPaths",
|