@aicayzer/inkkit 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -0
- package/dist/chunks/{core-Bvj0PMMi.js → core-D7n0IhAZ.js} +947 -315
- package/dist/chunks/{highlight-yHFoKkKz.js → highlight-BIasnL-b.js} +4 -3
- package/dist/core.js +1 -1
- package/dist/index.js +1 -1
- package/dist/style.css +87 -16
- package/dist/types.d.ts +4 -0
- package/package.json +1 -1
|
@@ -28357,6 +28357,10 @@ var defaultLabels = {
|
|
|
28357
28357
|
sourceEditor: "Markdown source editor",
|
|
28358
28358
|
placeholder: "Start typing…",
|
|
28359
28359
|
copyCode: "Copy",
|
|
28360
|
+
codeLanguage: "Code language",
|
|
28361
|
+
codeLanguageSearch: "Search languages",
|
|
28362
|
+
codeAuto: "Auto",
|
|
28363
|
+
codePlainText: "Plain text",
|
|
28360
28364
|
expandCallout: "Expand",
|
|
28361
28365
|
collapseCallout: "Collapse",
|
|
28362
28366
|
diagramRendering: "Rendering diagram…",
|
|
@@ -35086,6 +35090,194 @@ var references = [
|
|
|
35086
35090
|
}))
|
|
35087
35091
|
].flat();
|
|
35088
35092
|
//#endregion
|
|
35093
|
+
//#region src/smart-punctuation.ts
|
|
35094
|
+
/**
|
|
35095
|
+
* Smart punctuation: the quote or dash being typed becomes a curly quote or a dash.
|
|
35096
|
+
*
|
|
35097
|
+
* - `"` and `'` open after the start of a block, a line break, whitespace, an opening bracket, a
|
|
35098
|
+
* dash or another opening quote, and close everywhere else. A `'` between letters is an
|
|
35099
|
+
* apostrophe, which is the closing form.
|
|
35100
|
+
* - `--` gives an en dash and `---` an em dash: the third hyphen turns the en dash that the second
|
|
35101
|
+
* one made into an em dash. Only a hyphen that text input has just inserted counts as the first
|
|
35102
|
+
* of the two, so a hyphen already in the note, or typed before the caret moved, stays one.
|
|
35103
|
+
* - A quote that a dead key made arrives as a composition. When the composition commits exactly
|
|
35104
|
+
* that quote at the caret, it follows the same rules.
|
|
35105
|
+
*
|
|
35106
|
+
* These are input rules, so only the character being typed changes, Backspace and Undo straight
|
|
35107
|
+
* after restore what was typed, and nothing in a note is rewritten. The editor answers
|
|
35108
|
+
* `smartPunctuationCtx` with the current option, so turning it on or off needs no new editor.
|
|
35109
|
+
*/
|
|
35110
|
+
var smartPunctuationCtx = $ctx(() => false, "inkkitSmartPunctuation");
|
|
35111
|
+
/** Set on the transaction of each rule that this file makes. */
|
|
35112
|
+
var smartRule = "inkkitSmartPunctuation";
|
|
35113
|
+
var enDash = "–";
|
|
35114
|
+
var emDash = "—";
|
|
35115
|
+
/** What may come before a quote for it to open. */
|
|
35116
|
+
var opensAfter = /[\s([{<\u2013\u2014\u2018\u201C]/u;
|
|
35117
|
+
/**
|
|
35118
|
+
* Markdown that a person is typing out in a line of text, not words: a code span, a link
|
|
35119
|
+
* destination, a web address, a wiki link or footnote label, an HTML tag or comment and a
|
|
35120
|
+
* reference definition. Smart punctuation leaves a line alone while one is open, because the
|
|
35121
|
+
* curly character would change what the Markdown means.
|
|
35122
|
+
*/
|
|
35123
|
+
var typingSyntax = [
|
|
35124
|
+
(before) => (before.match(/`+/g)?.length ?? 0) % 2 === 1,
|
|
35125
|
+
(before) => /\]\([^)]*$/.test(before),
|
|
35126
|
+
(before) => /\[\[[^\]]*$/.test(before),
|
|
35127
|
+
(before) => /\[\^[^\]]*$/.test(before),
|
|
35128
|
+
(before) => /(?:^|[^\w])(?:[a-z][a-z0-9+.-]*:\/\/|www\.|mailto:)\S*$/i.test(before),
|
|
35129
|
+
(before) => /(?:^|[^\w])<[A-Za-z!/?][^>]*$/.test(before),
|
|
35130
|
+
(before) => /^\s*\[[^\]]+\]:/.test(before)
|
|
35131
|
+
];
|
|
35132
|
+
/**
|
|
35133
|
+
* The text of the block before `pos`, with each code span and each non-text node as one
|
|
35134
|
+
* placeholder, so that a backtick or `<` inside code is not syntax being typed.
|
|
35135
|
+
*/
|
|
35136
|
+
function textBefore(state, pos) {
|
|
35137
|
+
const $pos = state.doc.resolve(pos);
|
|
35138
|
+
let text = "";
|
|
35139
|
+
$pos.parent.forEach((child, offset) => {
|
|
35140
|
+
if (offset >= $pos.parentOffset) return;
|
|
35141
|
+
text += child.isText && !child.marks.some((mark) => mark.type.spec.code) ? child.text.slice(0, $pos.parentOffset - offset) : "";
|
|
35142
|
+
});
|
|
35143
|
+
return text;
|
|
35144
|
+
}
|
|
35145
|
+
var input = new PluginKey("inkkitSmartPunctuationInput");
|
|
35146
|
+
/** The text a transaction inserted, when it is one step that inserts text at `at` and nothing else. */
|
|
35147
|
+
function insertedAt(tr, at) {
|
|
35148
|
+
const [step] = tr.steps;
|
|
35149
|
+
if (tr.steps.length !== 1 || !(step instanceof ReplaceStep)) return void 0;
|
|
35150
|
+
if (step.from !== at || step.slice.openStart || step.slice.openEnd) return void 0;
|
|
35151
|
+
return step.slice.content.textBetween(0, step.slice.content.size);
|
|
35152
|
+
}
|
|
35153
|
+
var inputTracking = $prose(() => new Plugin({
|
|
35154
|
+
key: input,
|
|
35155
|
+
state: {
|
|
35156
|
+
init: () => ({
|
|
35157
|
+
pending: null,
|
|
35158
|
+
hyphen: null,
|
|
35159
|
+
composition: null,
|
|
35160
|
+
composedQuote: null
|
|
35161
|
+
}),
|
|
35162
|
+
apply(tr, value) {
|
|
35163
|
+
const { pending, composition } = value;
|
|
35164
|
+
value.pending = value.hyphen = value.composedQuote = null;
|
|
35165
|
+
if (tr.getMeta(hyphenReceived)) value.hyphen = tr.selection.from;
|
|
35166
|
+
if (!tr.docChanged) return value;
|
|
35167
|
+
if (pending !== null && insertedAt(tr, pending) === "-") value.hyphen = pending + 1;
|
|
35168
|
+
if (composition) {
|
|
35169
|
+
value.composition = null;
|
|
35170
|
+
const text = insertedAt(tr, composition.pos);
|
|
35171
|
+
if (tr.getMeta("composition") !== void 0 && (text === "\"" || text === "'") && tr.doc.content.size === composition.size + 1) value.composedQuote = composition.pos + 1;
|
|
35172
|
+
}
|
|
35173
|
+
return value;
|
|
35174
|
+
}
|
|
35175
|
+
},
|
|
35176
|
+
props: {
|
|
35177
|
+
handleTextInput(view, from, _to, text) {
|
|
35178
|
+
input.getState(view.state).pending = text === "-" ? from : null;
|
|
35179
|
+
return false;
|
|
35180
|
+
},
|
|
35181
|
+
handleDOMEvents: { compositionstart(view) {
|
|
35182
|
+
const { from, empty } = view.state.selection;
|
|
35183
|
+
const tracked = input.getState(view.state);
|
|
35184
|
+
tracked.composedQuote = null;
|
|
35185
|
+
tracked.composition = empty ? {
|
|
35186
|
+
pos: from,
|
|
35187
|
+
size: view.state.doc.content.size
|
|
35188
|
+
} : null;
|
|
35189
|
+
return false;
|
|
35190
|
+
} }
|
|
35191
|
+
}
|
|
35192
|
+
}));
|
|
35193
|
+
/** Set on a transaction that inserted text ending in a hyphen, whatever else came with it. */
|
|
35194
|
+
var hyphenReceived = "inkkitHyphenReceived";
|
|
35195
|
+
/** Marks a transaction that inserted text ending in a hyphen that no rule changed. */
|
|
35196
|
+
function insertedHyphen(tr) {
|
|
35197
|
+
return tr.setMeta(hyphenReceived, true);
|
|
35198
|
+
}
|
|
35199
|
+
/**
|
|
35200
|
+
* The state that input rules see for text that arrived in one piece, which holds only what the
|
|
35201
|
+
* rules need: it follows the document, with the tracking plugin when the editor has one. When
|
|
35202
|
+
* `rest` ends in a hyphen, the last character follows a hyphen that came in the same piece.
|
|
35203
|
+
*/
|
|
35204
|
+
function chunkState(state, config, rest) {
|
|
35205
|
+
const tracker = input.get(state);
|
|
35206
|
+
const prepared = EditorState.create({
|
|
35207
|
+
...config,
|
|
35208
|
+
plugins: tracker ? [tracker] : []
|
|
35209
|
+
});
|
|
35210
|
+
return tracker && rest.endsWith("-") ? prepared.apply(insertedHyphen(prepared.tr)) : prepared;
|
|
35211
|
+
}
|
|
35212
|
+
/**
|
|
35213
|
+
* Whether a rule may change what `match` found at `pos`: the option is on, the last character of
|
|
35214
|
+
* the match is the one being typed, which is not in the document yet, and the text is ordinary,
|
|
35215
|
+
* with no Markdown being typed. The input rules plugin also runs every rule when a composition
|
|
35216
|
+
* ends, over text that is all in the document; that is not typing, and is left alone.
|
|
35217
|
+
*/
|
|
35218
|
+
function applies(on, state, match, pos) {
|
|
35219
|
+
if (!on()) return false;
|
|
35220
|
+
const typed = pos + match[0].length - 1 === state.selection.from;
|
|
35221
|
+
const composed = !typed && match[0].length === 1 && input.getState(state)?.composedQuote === state.selection.from && pos === state.selection.from - 1;
|
|
35222
|
+
if (!typed && !composed) return false;
|
|
35223
|
+
const $pos = state.doc.resolve(pos);
|
|
35224
|
+
if ($pos.parent.type.spec.code || !$pos.parent.inlineContent) return false;
|
|
35225
|
+
if ((state.storedMarks ?? $pos.marks()).some((mark) => mark.type.spec.code)) return false;
|
|
35226
|
+
const before = textBefore(state, pos);
|
|
35227
|
+
return !typingSyntax.some((open) => open(before));
|
|
35228
|
+
}
|
|
35229
|
+
function opensHere(state, pos) {
|
|
35230
|
+
const node = state.doc.resolve(pos).nodeBefore;
|
|
35231
|
+
if (!node) return true;
|
|
35232
|
+
if (node.isText) {
|
|
35233
|
+
const text = node.text ?? "";
|
|
35234
|
+
return opensAfter.test(String.fromCodePoint(text.codePointAt(text.length - 1)));
|
|
35235
|
+
}
|
|
35236
|
+
return node.type.name === "hardbreak";
|
|
35237
|
+
}
|
|
35238
|
+
/** The input rule that ran at the last change, when nothing has happened since. */
|
|
35239
|
+
function lastRule(state) {
|
|
35240
|
+
for (const plugin of state.plugins) if (plugin.spec.isInputRules) {
|
|
35241
|
+
const stored = plugin.getState(state);
|
|
35242
|
+
if (stored) return stored;
|
|
35243
|
+
}
|
|
35244
|
+
}
|
|
35245
|
+
var quotes$1 = {
|
|
35246
|
+
"\"": ["“", "”"],
|
|
35247
|
+
"'": ["‘", "’"]
|
|
35248
|
+
};
|
|
35249
|
+
var smartPunctuation = [
|
|
35250
|
+
smartPunctuationCtx,
|
|
35251
|
+
inputTracking,
|
|
35252
|
+
$inputRule((ctx) => new InputRule(/["']$/, (state, match, start, end) => {
|
|
35253
|
+
if (!applies(ctx.get(smartPunctuationCtx.key), state, match, start)) return null;
|
|
35254
|
+
const [opening, closing] = quotes$1[match[0]];
|
|
35255
|
+
return state.tr.insertText(opensHere(state, start) ? opening : closing, start, end).setMeta(smartRule, "quote");
|
|
35256
|
+
}, { inCodeMark: false })),
|
|
35257
|
+
$inputRule((ctx) => new InputRule(/--$/, (state, match, start, end) => {
|
|
35258
|
+
if (!applies(ctx.get(smartPunctuationCtx.key), state, match, start)) return null;
|
|
35259
|
+
if (input.getState(state)?.hyphen !== state.selection.from) return null;
|
|
35260
|
+
const before = textBefore(state, start);
|
|
35261
|
+
if (!before.trim() || before.endsWith("-") || /^\s*\|/.test(before)) return null;
|
|
35262
|
+
return state.tr.insertText(enDash, start, end).setMeta(smartRule, "en");
|
|
35263
|
+
}, { inCodeMark: false })),
|
|
35264
|
+
$inputRule((ctx) => new InputRule(/\u2013-$/, (state, match, start, end) => {
|
|
35265
|
+
if (!applies(ctx.get(smartPunctuationCtx.key), state, match, start)) return null;
|
|
35266
|
+
if (lastRule(state)?.transform.getMeta(smartRule) !== "en") return null;
|
|
35267
|
+
return state.tr.insertText(emDash, start, end).setMeta(smartRule, "em");
|
|
35268
|
+
}, { inCodeMark: false }))
|
|
35269
|
+
].flat();
|
|
35270
|
+
/**
|
|
35271
|
+
* Undo straight after a smart quote or dash puts back the character that was typed, as Backspace
|
|
35272
|
+
* does for any input rule. The replacement joins the typing's history step, so the next Undo
|
|
35273
|
+
* removes the typing and not the curly character. Returns whether it applied.
|
|
35274
|
+
*/
|
|
35275
|
+
var undoSmartPunctuation = (state, dispatch) => {
|
|
35276
|
+
const rule = lastRule(state);
|
|
35277
|
+
if (!rule?.transform.getMeta(smartRule)) return false;
|
|
35278
|
+
return undoInputRule(state, dispatch && ((tr) => dispatch(tr.setMeta("appendedTransaction", rule.transform))));
|
|
35279
|
+
};
|
|
35280
|
+
//#endregion
|
|
35089
35281
|
//#region src/linked-syntax.ts
|
|
35090
35282
|
var fromTable = (raw) => raw.replace(/(\\*)\|/g, (_match, escapes) => `${"\\".repeat(Math.floor(escapes.length / 2))}|`);
|
|
35091
35283
|
var toTable = (raw) => raw.replace(/(\\*)\|/g, (_match, escapes) => `${"\\".repeat(escapes.length * 2 + 1)}|`);
|
|
@@ -35277,6 +35469,76 @@ var wikiLinkSchema = $node("inkkit_wiki_link", () => ({
|
|
|
35277
35469
|
}
|
|
35278
35470
|
}
|
|
35279
35471
|
}));
|
|
35472
|
+
var composed = new PluginKey("inkkitWikiLinkComposition");
|
|
35473
|
+
/**
|
|
35474
|
+
* Lets the rule below tell a `]` that a composition committed from text that was already in the
|
|
35475
|
+
* note: ProseMirror runs every input rule when a composition ends, with nothing typed.
|
|
35476
|
+
*/
|
|
35477
|
+
var wikiLinkComposition = $prose(() => new Plugin({
|
|
35478
|
+
key: composed,
|
|
35479
|
+
state: {
|
|
35480
|
+
init: () => ({
|
|
35481
|
+
composition: null,
|
|
35482
|
+
closing: null
|
|
35483
|
+
}),
|
|
35484
|
+
apply(tr, value) {
|
|
35485
|
+
const { composition } = value;
|
|
35486
|
+
value.closing = null;
|
|
35487
|
+
if (!tr.docChanged || !composition) return value;
|
|
35488
|
+
if (tr.getMeta("composition") === void 0) value.composition = null;
|
|
35489
|
+
else if (insertedAt(tr, composition.pos) === "]" && tr.doc.content.size === composition.size + 1) value.closing = composition.pos + 1;
|
|
35490
|
+
return value;
|
|
35491
|
+
}
|
|
35492
|
+
},
|
|
35493
|
+
props: { handleDOMEvents: { compositionstart(view) {
|
|
35494
|
+
const { from, empty } = view.state.selection;
|
|
35495
|
+
const tracked = composed.getState(view.state);
|
|
35496
|
+
tracked.closing = null;
|
|
35497
|
+
tracked.composition = empty ? {
|
|
35498
|
+
pos: from,
|
|
35499
|
+
size: view.state.doc.content.size
|
|
35500
|
+
} : null;
|
|
35501
|
+
return false;
|
|
35502
|
+
} } }
|
|
35503
|
+
}));
|
|
35504
|
+
/**
|
|
35505
|
+
* Turns `[[target]]`, as the person types its last bracket, into the wiki link
|
|
35506
|
+
* it reads as when the note is opened, so the note keeps the characters that
|
|
35507
|
+
* were typed. Left as text, the brackets save as `\[\[target]]`, which no
|
|
35508
|
+
* other tool reads as a link. The last bracket has to be the one just typed,
|
|
35509
|
+
* or committed by a composition: text already in the note, such as escaped
|
|
35510
|
+
* brackets, is never changed, and that includes the run of every rule when a
|
|
35511
|
+
* composition ends.
|
|
35512
|
+
*/
|
|
35513
|
+
var wikiLinkInputRule = $inputRule(() => new InputRule(/\[\[(?:\\.|[^[\]\\\ufffc])*\]\]$/, (state, match, start, end) => {
|
|
35514
|
+
const { schema, doc } = state;
|
|
35515
|
+
const type = schema.nodes.inkkit_wiki_link;
|
|
35516
|
+
const caret = state.selection.from;
|
|
35517
|
+
if (start + match[0].length - 1 !== caret && !(start + match[0].length === caret && composed.getState(state)?.closing === caret)) return null;
|
|
35518
|
+
const $start = doc.resolve(start);
|
|
35519
|
+
const parent = $start.parent;
|
|
35520
|
+
if (!type || !parent.inlineContent || !parent.canReplaceWith($start.index(), $start.index(), type) || /[!\\[]/.test(doc.textBetween(Math.max($start.start(), start - 1), start))) return null;
|
|
35521
|
+
let marks;
|
|
35522
|
+
let plain = true;
|
|
35523
|
+
doc.nodesBetween(start, end, (node) => {
|
|
35524
|
+
if (!node.isInline) return;
|
|
35525
|
+
if (!node.isText) plain = false;
|
|
35526
|
+
else if (marks && !Mark.sameSet(marks, node.marks)) plain = false;
|
|
35527
|
+
else marks ??= node.marks;
|
|
35528
|
+
});
|
|
35529
|
+
if (!plain || !marks || marks.some((mark) => ["inlineCode", "link"].includes(mark.type.name)) || state.storedMarks && !Mark.sameSet(state.storedMarks, marks)) return null;
|
|
35530
|
+
let inTable = false;
|
|
35531
|
+
for (let depth = $start.depth; depth > 0; depth--) if (["table_cell", "table_header"].includes($start.node(depth).type.name)) inTable = true;
|
|
35532
|
+
const parsed = parseLinkedSyntax(inTable ? toTable(match[0]) : match[0], inTable);
|
|
35533
|
+
if (!parsed || parsed.embed) return null;
|
|
35534
|
+
return state.tr.replaceWith(start, end, type.create({
|
|
35535
|
+
raw: parsed.raw,
|
|
35536
|
+
target: parsed.target,
|
|
35537
|
+
fragment: parsed.fragment,
|
|
35538
|
+
label: parsed.label,
|
|
35539
|
+
inTable: parsed.inTable
|
|
35540
|
+
}, void 0, marks));
|
|
35541
|
+
}, { inCodeMark: false }));
|
|
35280
35542
|
function linkedSyntax(wikiLinks, files) {
|
|
35281
35543
|
const syntax = { text: {} };
|
|
35282
35544
|
if (wikiLinks) syntax.text[91] = {
|
|
@@ -44348,278 +44610,90 @@ var dropIndicatorDOMPlugin = $prose((ctx) => new Plugin({
|
|
|
44348
44610
|
}));
|
|
44349
44611
|
withMeta(dropIndicatorDOMPlugin, { displayName: "Prose<dropIndicatorDOM>" });
|
|
44350
44612
|
function renderIndicator(dom, state, config) {
|
|
44351
|
-
if (!state) {
|
|
44352
|
-
Object.assign(dom.style, { display: "none" });
|
|
44353
|
-
return;
|
|
44354
|
-
}
|
|
44355
|
-
const { line } = state;
|
|
44356
|
-
const { width: lineWidth } = config;
|
|
44357
|
-
const { p1: { x: x1, y: y1 }, p2: { x: x2, y: y2 } } = line;
|
|
44358
|
-
const horizontal = y1 === y2;
|
|
44359
|
-
let width;
|
|
44360
|
-
let height;
|
|
44361
|
-
let top = y1;
|
|
44362
|
-
let left = x1;
|
|
44363
|
-
if (horizontal) {
|
|
44364
|
-
width = x2 - x1;
|
|
44365
|
-
height = lineWidth;
|
|
44366
|
-
top -= lineWidth / 2;
|
|
44367
|
-
} else {
|
|
44368
|
-
width = lineWidth;
|
|
44369
|
-
height = y2 - y1;
|
|
44370
|
-
left -= lineWidth / 2;
|
|
44371
|
-
}
|
|
44372
|
-
top = Math.round(top);
|
|
44373
|
-
left = Math.round(left);
|
|
44374
|
-
Object.assign(dom.style, {
|
|
44375
|
-
display: "block",
|
|
44376
|
-
width: `${width}px`,
|
|
44377
|
-
height: `${height}px`,
|
|
44378
|
-
transform: `translate(${left}px, ${top}px)`
|
|
44379
|
-
});
|
|
44380
|
-
}
|
|
44381
|
-
var dropIndicatorPlugin = $prose((ctx) => {
|
|
44382
|
-
const onShow = (options) => {
|
|
44383
|
-
ctx.set(dropIndicatorState.key, options);
|
|
44384
|
-
};
|
|
44385
|
-
const onHide = () => {
|
|
44386
|
-
ctx.set(dropIndicatorState.key, null);
|
|
44387
|
-
};
|
|
44388
|
-
return createDropIndicatorPlugin({
|
|
44389
|
-
onShow,
|
|
44390
|
-
onHide,
|
|
44391
|
-
onDrag: () => true
|
|
44392
|
-
});
|
|
44393
|
-
});
|
|
44394
|
-
withMeta(dropIndicatorPlugin, { displayName: "Prose<dropIndicator>" });
|
|
44395
|
-
var gapCursorPlugin = $prose(() => gapCursor());
|
|
44396
|
-
withMeta(gapCursorPlugin, { displayName: "Prose<gapCursor>" });
|
|
44397
|
-
[
|
|
44398
|
-
gapCursorPlugin,
|
|
44399
|
-
dropIndicatorConfig,
|
|
44400
|
-
dropIndicatorState,
|
|
44401
|
-
dropIndicatorDOMPlugin,
|
|
44402
|
-
dropIndicatorPlugin
|
|
44403
|
-
].flat();
|
|
44404
|
-
var cursor = [
|
|
44405
|
-
gapCursorPlugin,
|
|
44406
|
-
dropIndicatorConfig,
|
|
44407
|
-
dropIndicatorState,
|
|
44408
|
-
dropIndicatorDOMPlugin,
|
|
44409
|
-
$prose((ctx) => {
|
|
44410
|
-
let live = false;
|
|
44411
|
-
const plugin = createDropIndicatorPlugin({
|
|
44412
|
-
onShow: (options) => ctx.set(dropIndicatorState.key, options),
|
|
44413
|
-
onHide: () => {
|
|
44414
|
-
if (live) ctx.set(dropIndicatorState.key, null);
|
|
44415
|
-
},
|
|
44416
|
-
onDrag: () => true
|
|
44417
|
-
});
|
|
44418
|
-
const view = plugin.spec.view;
|
|
44419
|
-
return new Plugin({
|
|
44420
|
-
...plugin.spec,
|
|
44421
|
-
view(editorView) {
|
|
44422
|
-
live = true;
|
|
44423
|
-
const inner = view(editorView);
|
|
44424
|
-
return {
|
|
44425
|
-
...inner,
|
|
44426
|
-
destroy() {
|
|
44427
|
-
live = false;
|
|
44428
|
-
inner.destroy?.();
|
|
44429
|
-
}
|
|
44430
|
-
};
|
|
44431
|
-
}
|
|
44432
|
-
});
|
|
44433
|
-
})
|
|
44434
|
-
].flat();
|
|
44435
|
-
//#endregion
|
|
44436
|
-
//#region src/smart-punctuation.ts
|
|
44437
|
-
/**
|
|
44438
|
-
* Smart punctuation: the quote or dash being typed becomes a curly quote or a dash.
|
|
44439
|
-
*
|
|
44440
|
-
* - `"` and `'` open after the start of a block, a line break, whitespace, an opening bracket, a
|
|
44441
|
-
* dash or another opening quote, and close everywhere else. A `'` between letters is an
|
|
44442
|
-
* apostrophe, which is the closing form.
|
|
44443
|
-
* - `--` gives an en dash and `---` an em dash: the third hyphen turns the en dash that the second
|
|
44444
|
-
* one made into an em dash. Only a hyphen that text input has just inserted counts as the first
|
|
44445
|
-
* of the two, so a hyphen already in the note, or typed before the caret moved, stays one.
|
|
44446
|
-
* - A quote that a dead key made arrives as a composition. When the composition commits exactly
|
|
44447
|
-
* that quote at the caret, it follows the same rules.
|
|
44448
|
-
*
|
|
44449
|
-
* These are input rules, so only the character being typed changes, Backspace and Undo straight
|
|
44450
|
-
* after restore what was typed, and nothing in a note is rewritten. The editor answers
|
|
44451
|
-
* `smartPunctuationCtx` with the current option, so turning it on or off needs no new editor.
|
|
44452
|
-
*/
|
|
44453
|
-
var smartPunctuationCtx = $ctx(() => false, "inkkitSmartPunctuation");
|
|
44454
|
-
/** Set on the transaction of each rule that this file makes. */
|
|
44455
|
-
var smartRule = "inkkitSmartPunctuation";
|
|
44456
|
-
var enDash = "–";
|
|
44457
|
-
var emDash = "—";
|
|
44458
|
-
/** What may come before a quote for it to open. */
|
|
44459
|
-
var opensAfter = /[\s([{<\u2013\u2014\u2018\u201C]/u;
|
|
44460
|
-
/**
|
|
44461
|
-
* Markdown that a person is typing out in a line of text, not words: a code span, a link
|
|
44462
|
-
* destination, a web address, a wiki link or footnote label, an HTML tag or comment and a
|
|
44463
|
-
* reference definition. Smart punctuation leaves a line alone while one is open, because the
|
|
44464
|
-
* curly character would change what the Markdown means.
|
|
44465
|
-
*/
|
|
44466
|
-
var typingSyntax = [
|
|
44467
|
-
(before) => (before.match(/`+/g)?.length ?? 0) % 2 === 1,
|
|
44468
|
-
(before) => /\]\([^)]*$/.test(before),
|
|
44469
|
-
(before) => /\[\[[^\]]*$/.test(before),
|
|
44470
|
-
(before) => /\[\^[^\]]*$/.test(before),
|
|
44471
|
-
(before) => /(?:^|[^\w])(?:[a-z][a-z0-9+.-]*:\/\/|www\.|mailto:)\S*$/i.test(before),
|
|
44472
|
-
(before) => /(?:^|[^\w])<[A-Za-z!/?][^>]*$/.test(before),
|
|
44473
|
-
(before) => /^\s*\[[^\]]+\]:/.test(before)
|
|
44474
|
-
];
|
|
44475
|
-
/**
|
|
44476
|
-
* The text of the block before `pos`, with each code span and each non-text node as one
|
|
44477
|
-
* placeholder, so that a backtick or `<` inside code is not syntax being typed.
|
|
44478
|
-
*/
|
|
44479
|
-
function textBefore(state, pos) {
|
|
44480
|
-
const $pos = state.doc.resolve(pos);
|
|
44481
|
-
let text = "";
|
|
44482
|
-
$pos.parent.forEach((child, offset) => {
|
|
44483
|
-
if (offset >= $pos.parentOffset) return;
|
|
44484
|
-
text += child.isText && !child.marks.some((mark) => mark.type.spec.code) ? child.text.slice(0, $pos.parentOffset - offset) : "";
|
|
44485
|
-
});
|
|
44486
|
-
return text;
|
|
44487
|
-
}
|
|
44488
|
-
var input = new PluginKey("inkkitSmartPunctuationInput");
|
|
44489
|
-
/** The text a transaction inserted, when it is one step that inserts text at `at` and nothing else. */
|
|
44490
|
-
function insertedAt(tr, at) {
|
|
44491
|
-
const [step] = tr.steps;
|
|
44492
|
-
if (tr.steps.length !== 1 || !(step instanceof ReplaceStep)) return void 0;
|
|
44493
|
-
if (step.from !== at || step.slice.openStart || step.slice.openEnd) return void 0;
|
|
44494
|
-
return step.slice.content.textBetween(0, step.slice.content.size);
|
|
44495
|
-
}
|
|
44496
|
-
var inputTracking = $prose(() => new Plugin({
|
|
44497
|
-
key: input,
|
|
44498
|
-
state: {
|
|
44499
|
-
init: () => ({
|
|
44500
|
-
pending: null,
|
|
44501
|
-
hyphen: null,
|
|
44502
|
-
composition: null,
|
|
44503
|
-
composedQuote: null
|
|
44504
|
-
}),
|
|
44505
|
-
apply(tr, value) {
|
|
44506
|
-
const { pending, composition } = value;
|
|
44507
|
-
value.pending = value.hyphen = value.composedQuote = null;
|
|
44508
|
-
if (tr.getMeta(hyphenReceived)) value.hyphen = tr.selection.from;
|
|
44509
|
-
if (!tr.docChanged) return value;
|
|
44510
|
-
if (pending !== null && insertedAt(tr, pending) === "-") value.hyphen = pending + 1;
|
|
44511
|
-
if (composition) {
|
|
44512
|
-
value.composition = null;
|
|
44513
|
-
const text = insertedAt(tr, composition.pos);
|
|
44514
|
-
if (tr.getMeta("composition") !== void 0 && (text === "\"" || text === "'") && tr.doc.content.size === composition.size + 1) value.composedQuote = composition.pos + 1;
|
|
44515
|
-
}
|
|
44516
|
-
return value;
|
|
44517
|
-
}
|
|
44518
|
-
},
|
|
44519
|
-
props: {
|
|
44520
|
-
handleTextInput(view, from, _to, text) {
|
|
44521
|
-
input.getState(view.state).pending = text === "-" ? from : null;
|
|
44522
|
-
return false;
|
|
44523
|
-
},
|
|
44524
|
-
handleDOMEvents: { compositionstart(view) {
|
|
44525
|
-
const { from, empty } = view.state.selection;
|
|
44526
|
-
const tracked = input.getState(view.state);
|
|
44527
|
-
tracked.composedQuote = null;
|
|
44528
|
-
tracked.composition = empty ? {
|
|
44529
|
-
pos: from,
|
|
44530
|
-
size: view.state.doc.content.size
|
|
44531
|
-
} : null;
|
|
44532
|
-
return false;
|
|
44533
|
-
} }
|
|
44534
|
-
}
|
|
44535
|
-
}));
|
|
44536
|
-
/** Set on a transaction that inserted text ending in a hyphen, whatever else came with it. */
|
|
44537
|
-
var hyphenReceived = "inkkitHyphenReceived";
|
|
44538
|
-
/** Marks a transaction that inserted text ending in a hyphen that no rule changed. */
|
|
44539
|
-
function insertedHyphen(tr) {
|
|
44540
|
-
return tr.setMeta(hyphenReceived, true);
|
|
44541
|
-
}
|
|
44542
|
-
/**
|
|
44543
|
-
* The state that input rules see for text that arrived in one piece, which holds only what the
|
|
44544
|
-
* rules need: it follows the document, with the tracking plugin when the editor has one. When
|
|
44545
|
-
* `rest` ends in a hyphen, the last character follows a hyphen that came in the same piece.
|
|
44546
|
-
*/
|
|
44547
|
-
function chunkState(state, config, rest) {
|
|
44548
|
-
const tracker = input.get(state);
|
|
44549
|
-
const prepared = EditorState.create({
|
|
44550
|
-
...config,
|
|
44551
|
-
plugins: tracker ? [tracker] : []
|
|
44552
|
-
});
|
|
44553
|
-
return tracker && rest.endsWith("-") ? prepared.apply(insertedHyphen(prepared.tr)) : prepared;
|
|
44554
|
-
}
|
|
44555
|
-
/**
|
|
44556
|
-
* Whether a rule may change what `match` found at `pos`: the option is on, the last character of
|
|
44557
|
-
* the match is the one being typed, which is not in the document yet, and the text is ordinary,
|
|
44558
|
-
* with no Markdown being typed. The input rules plugin also runs every rule when a composition
|
|
44559
|
-
* ends, over text that is all in the document; that is not typing, and is left alone.
|
|
44560
|
-
*/
|
|
44561
|
-
function applies(on, state, match, pos) {
|
|
44562
|
-
if (!on()) return false;
|
|
44563
|
-
const typed = pos + match[0].length - 1 === state.selection.from;
|
|
44564
|
-
const composed = !typed && match[0].length === 1 && input.getState(state)?.composedQuote === state.selection.from && pos === state.selection.from - 1;
|
|
44565
|
-
if (!typed && !composed) return false;
|
|
44566
|
-
const $pos = state.doc.resolve(pos);
|
|
44567
|
-
if ($pos.parent.type.spec.code || !$pos.parent.inlineContent) return false;
|
|
44568
|
-
if ((state.storedMarks ?? $pos.marks()).some((mark) => mark.type.spec.code)) return false;
|
|
44569
|
-
const before = textBefore(state, pos);
|
|
44570
|
-
return !typingSyntax.some((open) => open(before));
|
|
44571
|
-
}
|
|
44572
|
-
function opensHere(state, pos) {
|
|
44573
|
-
const node = state.doc.resolve(pos).nodeBefore;
|
|
44574
|
-
if (!node) return true;
|
|
44575
|
-
if (node.isText) {
|
|
44576
|
-
const text = node.text ?? "";
|
|
44577
|
-
return opensAfter.test(String.fromCodePoint(text.codePointAt(text.length - 1)));
|
|
44578
|
-
}
|
|
44579
|
-
return node.type.name === "hardbreak";
|
|
44580
|
-
}
|
|
44581
|
-
/** The input rule that ran at the last change, when nothing has happened since. */
|
|
44582
|
-
function lastRule(state) {
|
|
44583
|
-
for (const plugin of state.plugins) if (plugin.spec.isInputRules) {
|
|
44584
|
-
const stored = plugin.getState(state);
|
|
44585
|
-
if (stored) return stored;
|
|
44613
|
+
if (!state) {
|
|
44614
|
+
Object.assign(dom.style, { display: "none" });
|
|
44615
|
+
return;
|
|
44616
|
+
}
|
|
44617
|
+
const { line } = state;
|
|
44618
|
+
const { width: lineWidth } = config;
|
|
44619
|
+
const { p1: { x: x1, y: y1 }, p2: { x: x2, y: y2 } } = line;
|
|
44620
|
+
const horizontal = y1 === y2;
|
|
44621
|
+
let width;
|
|
44622
|
+
let height;
|
|
44623
|
+
let top = y1;
|
|
44624
|
+
let left = x1;
|
|
44625
|
+
if (horizontal) {
|
|
44626
|
+
width = x2 - x1;
|
|
44627
|
+
height = lineWidth;
|
|
44628
|
+
top -= lineWidth / 2;
|
|
44629
|
+
} else {
|
|
44630
|
+
width = lineWidth;
|
|
44631
|
+
height = y2 - y1;
|
|
44632
|
+
left -= lineWidth / 2;
|
|
44586
44633
|
}
|
|
44634
|
+
top = Math.round(top);
|
|
44635
|
+
left = Math.round(left);
|
|
44636
|
+
Object.assign(dom.style, {
|
|
44637
|
+
display: "block",
|
|
44638
|
+
width: `${width}px`,
|
|
44639
|
+
height: `${height}px`,
|
|
44640
|
+
transform: `translate(${left}px, ${top}px)`
|
|
44641
|
+
});
|
|
44587
44642
|
}
|
|
44588
|
-
var
|
|
44589
|
-
|
|
44590
|
-
|
|
44591
|
-
};
|
|
44592
|
-
|
|
44593
|
-
|
|
44594
|
-
|
|
44595
|
-
|
|
44596
|
-
|
|
44597
|
-
|
|
44598
|
-
|
|
44599
|
-
}
|
|
44600
|
-
|
|
44601
|
-
|
|
44602
|
-
|
|
44603
|
-
|
|
44604
|
-
|
|
44605
|
-
|
|
44606
|
-
|
|
44607
|
-
|
|
44608
|
-
|
|
44609
|
-
|
|
44610
|
-
|
|
44611
|
-
|
|
44643
|
+
var dropIndicatorPlugin = $prose((ctx) => {
|
|
44644
|
+
const onShow = (options) => {
|
|
44645
|
+
ctx.set(dropIndicatorState.key, options);
|
|
44646
|
+
};
|
|
44647
|
+
const onHide = () => {
|
|
44648
|
+
ctx.set(dropIndicatorState.key, null);
|
|
44649
|
+
};
|
|
44650
|
+
return createDropIndicatorPlugin({
|
|
44651
|
+
onShow,
|
|
44652
|
+
onHide,
|
|
44653
|
+
onDrag: () => true
|
|
44654
|
+
});
|
|
44655
|
+
});
|
|
44656
|
+
withMeta(dropIndicatorPlugin, { displayName: "Prose<dropIndicator>" });
|
|
44657
|
+
var gapCursorPlugin = $prose(() => gapCursor());
|
|
44658
|
+
withMeta(gapCursorPlugin, { displayName: "Prose<gapCursor>" });
|
|
44659
|
+
[
|
|
44660
|
+
gapCursorPlugin,
|
|
44661
|
+
dropIndicatorConfig,
|
|
44662
|
+
dropIndicatorState,
|
|
44663
|
+
dropIndicatorDOMPlugin,
|
|
44664
|
+
dropIndicatorPlugin
|
|
44665
|
+
].flat();
|
|
44666
|
+
var cursor = [
|
|
44667
|
+
gapCursorPlugin,
|
|
44668
|
+
dropIndicatorConfig,
|
|
44669
|
+
dropIndicatorState,
|
|
44670
|
+
dropIndicatorDOMPlugin,
|
|
44671
|
+
$prose((ctx) => {
|
|
44672
|
+
let live = false;
|
|
44673
|
+
const plugin = createDropIndicatorPlugin({
|
|
44674
|
+
onShow: (options) => ctx.set(dropIndicatorState.key, options),
|
|
44675
|
+
onHide: () => {
|
|
44676
|
+
if (live) ctx.set(dropIndicatorState.key, null);
|
|
44677
|
+
},
|
|
44678
|
+
onDrag: () => true
|
|
44679
|
+
});
|
|
44680
|
+
const view = plugin.spec.view;
|
|
44681
|
+
return new Plugin({
|
|
44682
|
+
...plugin.spec,
|
|
44683
|
+
view(editorView) {
|
|
44684
|
+
live = true;
|
|
44685
|
+
const inner = view(editorView);
|
|
44686
|
+
return {
|
|
44687
|
+
...inner,
|
|
44688
|
+
destroy() {
|
|
44689
|
+
live = false;
|
|
44690
|
+
inner.destroy?.();
|
|
44691
|
+
}
|
|
44692
|
+
};
|
|
44693
|
+
}
|
|
44694
|
+
});
|
|
44695
|
+
})
|
|
44612
44696
|
].flat();
|
|
44613
|
-
/**
|
|
44614
|
-
* Undo straight after a smart quote or dash puts back the character that was typed, as Backspace
|
|
44615
|
-
* does for any input rule. The replacement joins the typing's history step, so the next Undo
|
|
44616
|
-
* removes the typing and not the curly character. Returns whether it applied.
|
|
44617
|
-
*/
|
|
44618
|
-
var undoSmartPunctuation = (state, dispatch) => {
|
|
44619
|
-
const rule = lastRule(state);
|
|
44620
|
-
if (!rule?.transform.getMeta(smartRule)) return false;
|
|
44621
|
-
return undoInputRule(state, dispatch && ((tr) => dispatch(tr.setMeta("appendedTransaction", rule.transform))));
|
|
44622
|
-
};
|
|
44623
44697
|
//#endregion
|
|
44624
44698
|
//#region src/text-input.ts
|
|
44625
44699
|
var isInputRules = (plugin) => plugin.spec.isInputRules === true;
|
|
@@ -44921,6 +44995,16 @@ function finalCodeEnding(doc) {
|
|
|
44921
44995
|
last = last.lastChild;
|
|
44922
44996
|
}
|
|
44923
44997
|
}
|
|
44998
|
+
/** Change only the language word, retaining fence spelling and extra metadata. */
|
|
44999
|
+
function languageFence(value, language) {
|
|
45000
|
+
const fence = readFence(value);
|
|
45001
|
+
if (!fence) return null;
|
|
45002
|
+
const match = /^(\s*)(\S+)?([\s\S]*)$/.exec(fence.info);
|
|
45003
|
+
return {
|
|
45004
|
+
...fence,
|
|
45005
|
+
info: match[1] + language + match[3]
|
|
45006
|
+
};
|
|
45007
|
+
}
|
|
44924
45008
|
//#endregion
|
|
44925
45009
|
//#region src/literals.ts
|
|
44926
45010
|
var unsupported = /* @__PURE__ */ new Set([
|
|
@@ -44957,6 +45041,7 @@ function containsUnsupported(node, images, inline = false) {
|
|
|
44957
45041
|
return unsupported.has(node.type) && !(images && node.type === "image") || "children" in node && node.children.some((child) => containsUnsupported(child, images, inline || node.type === "paragraph" || node.type === "heading"));
|
|
44958
45042
|
}
|
|
44959
45043
|
function containsUnresolved(node, source) {
|
|
45044
|
+
if (node.type === "link") return false;
|
|
44960
45045
|
if (node.type === "text") {
|
|
44961
45046
|
const start = node.position?.start.offset;
|
|
44962
45047
|
const end = node.position?.end.offset;
|
|
@@ -45125,14 +45210,25 @@ var literalBlock = $node("literal_markdown", (ctx) => ({
|
|
|
45125
45210
|
}));
|
|
45126
45211
|
//#endregion
|
|
45127
45212
|
//#region src/preserve.ts
|
|
45213
|
+
var linkFormsMatter = false;
|
|
45214
|
+
function withLinkForms(run) {
|
|
45215
|
+
const before = linkFormsMatter;
|
|
45216
|
+
linkFormsMatter = true;
|
|
45217
|
+
try {
|
|
45218
|
+
return run();
|
|
45219
|
+
} finally {
|
|
45220
|
+
linkFormsMatter = before;
|
|
45221
|
+
}
|
|
45222
|
+
}
|
|
45128
45223
|
function signature(node) {
|
|
45129
45224
|
return JSON.stringify(ordered(node), function(key, value) {
|
|
45225
|
+
const holder = this;
|
|
45226
|
+
if (key === "data" && holder.type === "link" && linkFormsMatter) return { inkkitLinkForm: value?.inkkitLinkForm };
|
|
45130
45227
|
if ([
|
|
45131
45228
|
"position",
|
|
45132
45229
|
"data",
|
|
45133
45230
|
"marker"
|
|
45134
45231
|
].includes(key)) return void 0;
|
|
45135
|
-
const holder = this;
|
|
45136
45232
|
if (key === "value" && holder.type === "html" && lineBreakHTML(value)) return "<br />";
|
|
45137
45233
|
if (key === "children" && holder.type === "tableRow") {
|
|
45138
45234
|
let end = value.length;
|
|
@@ -45955,7 +46051,17 @@ function parseDoc(ctx, text) {
|
|
|
45955
46051
|
}
|
|
45956
46052
|
function parseTree(ctx, text) {
|
|
45957
46053
|
preservationWork.characters += text.length;
|
|
45958
|
-
|
|
46054
|
+
const tree = ctx.get(remarkCtx).parse(text);
|
|
46055
|
+
const body = text.replace(/^\uFEFF/, "");
|
|
46056
|
+
const visit = (node) => {
|
|
46057
|
+
if (node.type === "link") node.data = {
|
|
46058
|
+
...node.data,
|
|
46059
|
+
inkkitLinkForm: linkForm(node, body)
|
|
46060
|
+
};
|
|
46061
|
+
node.children?.forEach(visit);
|
|
46062
|
+
};
|
|
46063
|
+
visit(tree);
|
|
46064
|
+
return tree;
|
|
45959
46065
|
}
|
|
45960
46066
|
function write(ctx, doc) {
|
|
45961
46067
|
const text = serialize(ctx, doc);
|
|
@@ -46233,6 +46339,7 @@ var Preservation = class Preservation {
|
|
|
46233
46339
|
blocks = [];
|
|
46234
46340
|
lineEnding;
|
|
46235
46341
|
originalForms = /* @__PURE__ */ new Set();
|
|
46342
|
+
linkEdits = false;
|
|
46236
46343
|
blockForms = [];
|
|
46237
46344
|
forms = /* @__PURE__ */ new WeakMap();
|
|
46238
46345
|
blockEdits = /* @__PURE__ */ new WeakMap();
|
|
@@ -46759,7 +46866,7 @@ var Preservation = class Preservation {
|
|
|
46759
46866
|
const kind = block && block.form === text && !carried.within.has(index) ? position == null ? "moved" : "unchanged" : block && tree && position != null ? "edited" : "canonical";
|
|
46760
46867
|
kept.push(kind);
|
|
46761
46868
|
const node = tree ? positionalNode(tree.raw, transformed(index)) : void 0;
|
|
46762
|
-
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)));
|
|
46869
|
+
pieces.push(kind === "unchanged" || kind === "moved" ? this.source.slice(block.start, block.end) : kind === "edited" ? this.retainingForms(block, doc.child(index), () => 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)));
|
|
46763
46870
|
}
|
|
46764
46871
|
return {
|
|
46765
46872
|
gaps,
|
|
@@ -46955,6 +47062,31 @@ var Preservation = class Preservation {
|
|
|
46955
47062
|
for (let index = 0; index < nodes.length; index++) rewritten.push(again.child(index));
|
|
46956
47063
|
return actual === normalized(write(this.ctx, read.type.create(null, rewritten)));
|
|
46957
47064
|
}
|
|
47065
|
+
withLinkEdits(run) {
|
|
47066
|
+
this.linkEdits = true;
|
|
47067
|
+
try {
|
|
47068
|
+
return run();
|
|
47069
|
+
} finally {
|
|
47070
|
+
this.linkEdits = false;
|
|
47071
|
+
}
|
|
47072
|
+
}
|
|
47073
|
+
retainingForms(block, node, retain) {
|
|
47074
|
+
if (!this.linkEdits) return retain();
|
|
47075
|
+
const forms = (value) => {
|
|
47076
|
+
const found = [];
|
|
47077
|
+
let previous;
|
|
47078
|
+
value.descendants((child) => {
|
|
47079
|
+
if (!child.isText) return true;
|
|
47080
|
+
const link = child.marks.find((mark) => mark.type.name === "link");
|
|
47081
|
+
if (link && !previous?.eq(link)) found.push(link.attrs.form ?? null);
|
|
47082
|
+
previous = link;
|
|
47083
|
+
return false;
|
|
47084
|
+
});
|
|
47085
|
+
return JSON.stringify(found);
|
|
47086
|
+
};
|
|
47087
|
+
const original = this.baseline.maybeChild(this.blocks.indexOf(block));
|
|
47088
|
+
return !original || this.baseline.childCount !== this.blocks.length || forms(original) !== forms(node) ? withLinkForms(retain) : retain();
|
|
47089
|
+
}
|
|
46958
47090
|
wholeDocument(doc) {
|
|
46959
47091
|
try {
|
|
46960
47092
|
const canonical = write(this.ctx, doc);
|
|
@@ -46963,20 +47095,24 @@ var Preservation = class Preservation {
|
|
|
46963
47095
|
doc.forEach((node) => current.push(this.formOf(node)));
|
|
46964
47096
|
const pairing = this.pairing(doc, current);
|
|
46965
47097
|
const carries = pairing.carried.moved.size > 0 || pairing.carried.children;
|
|
46966
|
-
|
|
46967
|
-
|
|
46968
|
-
|
|
46969
|
-
|
|
46970
|
-
|
|
46971
|
-
|
|
47098
|
+
const attempt = () => {
|
|
47099
|
+
if (carries) {
|
|
47100
|
+
let output;
|
|
47101
|
+
try {
|
|
47102
|
+
output = this.writeDocument(doc, current, pairing);
|
|
47103
|
+
} catch {
|
|
47104
|
+
output = void 0;
|
|
47105
|
+
}
|
|
47106
|
+
if (output !== void 0 && this.reopens(doc, output, canonical)) return output;
|
|
46972
47107
|
}
|
|
46973
|
-
|
|
46974
|
-
|
|
46975
|
-
|
|
46976
|
-
|
|
46977
|
-
|
|
46978
|
-
}
|
|
46979
|
-
|
|
47108
|
+
const output = this.writeDocument(doc, current, carries ? {
|
|
47109
|
+
positions: correspondence(this.blockForms, current),
|
|
47110
|
+
carried: nothingCarried
|
|
47111
|
+
} : pairing);
|
|
47112
|
+
return this.reopens(doc, output, canonical) ? output : void 0;
|
|
47113
|
+
};
|
|
47114
|
+
const output = attempt() ?? this.withLinkEdits(attempt);
|
|
47115
|
+
if (output !== void 0) return output;
|
|
46980
47116
|
throw new PreservationError("The edited Markdown cannot be reopened without changing its content");
|
|
46981
47117
|
} catch (cause) {
|
|
46982
47118
|
if (cause instanceof PreservationError) throw cause;
|
|
@@ -47180,16 +47316,126 @@ function read(ctx, sources, texts) {
|
|
|
47180
47316
|
return valid ? found : void 0;
|
|
47181
47317
|
});
|
|
47182
47318
|
}
|
|
47319
|
+
function literalFormattingLinks(text) {
|
|
47320
|
+
if (!/[*_~`]/.test(text) || /[<>]/.test(text)) return void 0;
|
|
47321
|
+
const tree = fromMarkdown(`x ${text}`, {
|
|
47322
|
+
extensions: [gfmAutolinkLiteral(), { disable: { null: [
|
|
47323
|
+
"attention",
|
|
47324
|
+
"codeText",
|
|
47325
|
+
"htmlText",
|
|
47326
|
+
"labelStartLink",
|
|
47327
|
+
"labelStartImage",
|
|
47328
|
+
"characterEscape",
|
|
47329
|
+
"characterReference",
|
|
47330
|
+
"autolink"
|
|
47331
|
+
] } }],
|
|
47332
|
+
mdastExtensions: [gfmAutolinkLiteralFromMarkdown()]
|
|
47333
|
+
});
|
|
47334
|
+
const paragraph = tree.children[0];
|
|
47335
|
+
if (tree.children.length !== 1 || paragraph?.type !== "paragraph") return void 0;
|
|
47336
|
+
const found = [];
|
|
47337
|
+
let readable = "";
|
|
47338
|
+
for (const child of paragraph.children) if (child.type === "text") readable += child.value;
|
|
47339
|
+
else if (child.type === "link" && child.children.every((node) => node.type === "text")) {
|
|
47340
|
+
const start = readable.length - 2;
|
|
47341
|
+
for (const node of child.children) if (node.type === "text") readable += node.value;
|
|
47342
|
+
found.push([
|
|
47343
|
+
start,
|
|
47344
|
+
readable.length - 2,
|
|
47345
|
+
child.url
|
|
47346
|
+
]);
|
|
47347
|
+
} else return void 0;
|
|
47348
|
+
return readable === `x ${text}` ? found : void 0;
|
|
47349
|
+
}
|
|
47183
47350
|
function literals(ctx, texts) {
|
|
47184
47351
|
const possible = texts.map((text) => /www\.|https?:\/\/|@/i.test(text));
|
|
47185
47352
|
const candidates = texts.filter((_, index) => possible[index]);
|
|
47186
47353
|
const found = read(ctx, candidates.map((text) => text.replace(/[\\`[\]<>]/g, "\\$&")), candidates);
|
|
47187
|
-
return texts.map((
|
|
47354
|
+
return texts.map((text, index) => possible[index] ? endAtBackticks(ctx, found.shift() ?? literalFormattingLinks(text), text) : []);
|
|
47355
|
+
}
|
|
47356
|
+
function endAtBackticks(ctx, found, text) {
|
|
47357
|
+
if (!found) return found;
|
|
47358
|
+
const result = [];
|
|
47359
|
+
for (const [start, end, href] of found) {
|
|
47360
|
+
const parts = text.slice(start, end).split("`");
|
|
47361
|
+
if (parts.length === 1) {
|
|
47362
|
+
result.push([
|
|
47363
|
+
start,
|
|
47364
|
+
end,
|
|
47365
|
+
href
|
|
47366
|
+
]);
|
|
47367
|
+
continue;
|
|
47368
|
+
}
|
|
47369
|
+
let at = start;
|
|
47370
|
+
literals(ctx, parts).forEach((links, index) => {
|
|
47371
|
+
for (const [from, to, target] of links ?? []) result.push([
|
|
47372
|
+
at + from,
|
|
47373
|
+
at + to,
|
|
47374
|
+
target
|
|
47375
|
+
]);
|
|
47376
|
+
at += parts[index].length + 1;
|
|
47377
|
+
});
|
|
47378
|
+
}
|
|
47379
|
+
return result;
|
|
47188
47380
|
}
|
|
47189
47381
|
function angleHref(text) {
|
|
47190
47382
|
if (/^[a-zA-Z][a-zA-Z0-9+.-]{1,31}:[^\s<>\u0000-\u001f]*$/.test(text)) return text;
|
|
47191
47383
|
if (/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(text)) return `mailto:${text}`;
|
|
47192
47384
|
}
|
|
47385
|
+
function completedAngle(tr, chars, from, to) {
|
|
47386
|
+
if (to !== from + 1) return void 0;
|
|
47387
|
+
const end = chars.findIndex((char) => char?.pos === from);
|
|
47388
|
+
const closing = chars[end];
|
|
47389
|
+
if (closing?.text !== ">" || closing.marks.some((mark) => mark.type.spec.code) || closing.link && closing.form !== "literal") return void 0;
|
|
47390
|
+
let start = end - 1;
|
|
47391
|
+
for (; start >= 0; start--) {
|
|
47392
|
+
const char = chars[start];
|
|
47393
|
+
if (!char || char.marks.some((mark) => mark.type.spec.code) || char.link && char.form !== "literal" || char.text !== "<" && !sameMarks(char.marks, closing.marks) || /[\s>]/.test(char.text)) return void 0;
|
|
47394
|
+
if (char.text === "<") break;
|
|
47395
|
+
}
|
|
47396
|
+
if (start < 0) return void 0;
|
|
47397
|
+
const href = angleHref(chars.slice(start + 1, end).map((char) => char.text).join(""));
|
|
47398
|
+
if (!href) return void 0;
|
|
47399
|
+
const opening = chars[start].pos;
|
|
47400
|
+
return tr.delete(from, to).delete(opening, opening + 1).addMark(opening, from - 1, tr.doc.type.schema.marks.link.create({
|
|
47401
|
+
href,
|
|
47402
|
+
form: "angle"
|
|
47403
|
+
})).removeStoredMark(tr.doc.type.schema.marks.link);
|
|
47404
|
+
}
|
|
47405
|
+
function closeAngleEnds(tr, transactions) {
|
|
47406
|
+
const steps = transactions.flatMap((transaction) => transaction.steps.map((step, index) => ({
|
|
47407
|
+
doc: transaction.docs[index],
|
|
47408
|
+
map: step.getMap()
|
|
47409
|
+
})));
|
|
47410
|
+
steps.forEach(({ doc, map }, index) => {
|
|
47411
|
+
const remaining = new Mapping(steps.slice(index + 1).map(({ map }) => map));
|
|
47412
|
+
map.forEach((from, to, start, end) => {
|
|
47413
|
+
if (from !== to || start === end) return;
|
|
47414
|
+
const at = doc.resolve(from);
|
|
47415
|
+
const before = at.nodeBefore?.marks.find((mark) => mark.attrs.form === "angle");
|
|
47416
|
+
const after = at.nodeAfter?.marks.find((mark) => mark.attrs.form === "angle");
|
|
47417
|
+
if (before && after && before.eq(after)) return;
|
|
47418
|
+
for (const mark of [before, after]) if (mark) tr.removeMark(remaining.map(start, 1), remaining.map(end, -1), mark);
|
|
47419
|
+
});
|
|
47420
|
+
});
|
|
47421
|
+
}
|
|
47422
|
+
function codeAngles(tr, edited) {
|
|
47423
|
+
const spans = [];
|
|
47424
|
+
for (const block of edited) tr.doc.nodesBetween(block.pos, block.pos + block.block.nodeSize, (node, pos) => {
|
|
47425
|
+
if (!node.isText || !node.marks.some((mark) => mark.type.spec.code)) return;
|
|
47426
|
+
const link = node.marks.find((mark) => mark.attrs.form === "angle");
|
|
47427
|
+
if (link) spans.push({
|
|
47428
|
+
from: pos,
|
|
47429
|
+
to: pos + node.nodeSize,
|
|
47430
|
+
marks: node.marks.filter((mark) => mark !== link)
|
|
47431
|
+
});
|
|
47432
|
+
});
|
|
47433
|
+
for (const { from, to, marks } of spans.reverse()) {
|
|
47434
|
+
tr.removeMark(from, to, tr.doc.type.schema.marks.link);
|
|
47435
|
+
tr.insert(to, tr.doc.type.schema.text(">", marks));
|
|
47436
|
+
tr.insert(from, tr.doc.type.schema.text("<", marks));
|
|
47437
|
+
}
|
|
47438
|
+
}
|
|
47193
47439
|
function wantedLinks(ctx, chars, from, to) {
|
|
47194
47440
|
const wanted = /* @__PURE__ */ new Map();
|
|
47195
47441
|
const released = /* @__PURE__ */ new Set();
|
|
@@ -47214,6 +47460,20 @@ function wantedLinks(ctx, chars, from, to) {
|
|
|
47214
47460
|
}
|
|
47215
47461
|
index = end;
|
|
47216
47462
|
}
|
|
47463
|
+
const codeAddress = (index) => {
|
|
47464
|
+
const char = chars[index];
|
|
47465
|
+
return char?.form === "literal" && char.marks.some((mark) => mark.type.spec.code);
|
|
47466
|
+
};
|
|
47467
|
+
for (let index = 0; index < chars.length;) {
|
|
47468
|
+
if (!codeAddress(index)) {
|
|
47469
|
+
index++;
|
|
47470
|
+
continue;
|
|
47471
|
+
}
|
|
47472
|
+
let end = index + 1;
|
|
47473
|
+
while (end < chars.length && codeAddress(end)) end++;
|
|
47474
|
+
if (end >= from && index <= to) for (let at = index; at < end; at++) wanted.set(at, null);
|
|
47475
|
+
index = end;
|
|
47476
|
+
}
|
|
47217
47477
|
const free = (index) => {
|
|
47218
47478
|
const char = chars[index];
|
|
47219
47479
|
return char !== void 0 && !char.marks.some((mark) => mark.type.spec.code) && (released.has(index) || char.form !== "angle" && !(char.link && !char.form));
|
|
@@ -47305,7 +47565,12 @@ function linked(tr, blocks) {
|
|
|
47305
47565
|
}
|
|
47306
47566
|
function readsBack(ctx, tr, pos) {
|
|
47307
47567
|
const block = tr.doc.nodeAt(pos);
|
|
47308
|
-
const
|
|
47568
|
+
const references = /* @__PURE__ */ new Set();
|
|
47569
|
+
block.descendants((node) => {
|
|
47570
|
+
for (const mark of node.marks) if (mark.type.name === "link" && mark.attrs.identifier) references.add(normaliseLabel(String(mark.attrs.identifier)));
|
|
47571
|
+
});
|
|
47572
|
+
const definitions = references.size ? [...referenceDefinitions(tr.doc)].filter(([identifier]) => references.has(identifier)).map(([, definition]) => definition.node) : [];
|
|
47573
|
+
const doc = tr.doc.type.create(null, [tr.doc.type.schema.nodes.paragraph.create(null, block.content), ...definitions]);
|
|
47309
47574
|
return semanticSignature(ctx.get(parserCtx)(serialize(ctx, doc))) === semanticSignature(doc);
|
|
47310
47575
|
}
|
|
47311
47576
|
var textblocks = (doc, from, to) => {
|
|
@@ -47360,8 +47625,25 @@ var autolinkLiterals = $prose((ctx) => new Plugin({
|
|
|
47360
47625
|
key: new PluginKey("autolinkLiterals"),
|
|
47361
47626
|
appendTransaction(transactions, oldState, newState) {
|
|
47362
47627
|
if (!transactions.some((tr) => tr.docChanged)) return null;
|
|
47628
|
+
const base = newState.tr;
|
|
47629
|
+
const written = transactions.every(isWrittenEdit);
|
|
47630
|
+
if (written) {
|
|
47631
|
+
closeAngleEnds(base, transactions);
|
|
47632
|
+
codeAngles(base, editedBlocks(oldState.doc, base.doc));
|
|
47633
|
+
}
|
|
47634
|
+
let edited = editedBlocks(oldState.doc, base.doc);
|
|
47635
|
+
if (written && edited.length === 1) {
|
|
47636
|
+
const { pos, block, from, to } = edited[0];
|
|
47637
|
+
const start = base.steps.length;
|
|
47638
|
+
if (completedAngle(base, characters(block, pos + 1), from, to)) {
|
|
47639
|
+
edited = editedBlocks(oldState.doc, base.doc);
|
|
47640
|
+
const mapping = base.mapping.slice(start);
|
|
47641
|
+
edited[0].from = Math.min(edited[0].from, mapping.map(from, -1));
|
|
47642
|
+
edited[0].to = Math.max(edited[0].to, mapping.map(to, 1));
|
|
47643
|
+
}
|
|
47644
|
+
}
|
|
47363
47645
|
const blocks = [];
|
|
47364
|
-
for (const { pos, block, from, to } of
|
|
47646
|
+
for (const { pos, block, from, to } of edited) {
|
|
47365
47647
|
const chars = characters(block, pos + 1);
|
|
47366
47648
|
const index = (at) => {
|
|
47367
47649
|
const found = chars.findIndex((char) => char !== void 0 && char.pos >= at);
|
|
@@ -47374,15 +47656,32 @@ var autolinkLiterals = $prose((ctx) => new Plugin({
|
|
|
47374
47656
|
wanted
|
|
47375
47657
|
});
|
|
47376
47658
|
}
|
|
47377
|
-
if (!blocks.length) return null;
|
|
47378
|
-
|
|
47379
|
-
const
|
|
47380
|
-
|
|
47381
|
-
|
|
47382
|
-
|
|
47383
|
-
|
|
47384
|
-
|
|
47385
|
-
|
|
47659
|
+
if (!base.steps.length && !blocks.length) return null;
|
|
47660
|
+
const stored = base.storedMarks ?? newState.storedMarks;
|
|
47661
|
+
const finish = (tr) => {
|
|
47662
|
+
if (stored) tr.setStoredMarks(stored);
|
|
47663
|
+
if (!tr.steps.length) return null;
|
|
47664
|
+
for (const plugin of newState.plugins) if (plugin.spec.isInputRules) for (const transaction of transactions) {
|
|
47665
|
+
const meta = transaction.getMeta(plugin);
|
|
47666
|
+
if (meta !== void 0) tr.setMeta(plugin, meta);
|
|
47667
|
+
}
|
|
47668
|
+
return tr;
|
|
47669
|
+
};
|
|
47670
|
+
const attempt = (wanted) => {
|
|
47671
|
+
const tr = newState.tr;
|
|
47672
|
+
for (const step of base.steps) tr.step(step);
|
|
47673
|
+
tr.setSelection(base.selection.getBookmark().resolve(tr.doc));
|
|
47674
|
+
return linked(tr, wanted);
|
|
47675
|
+
};
|
|
47676
|
+
let tr = attempt(blocks);
|
|
47677
|
+
const failed = edited.filter((block) => !readsBack(ctx, tr, block.pos));
|
|
47678
|
+
if (!failed.length) return finish(tr);
|
|
47679
|
+
for (const block of blocks) if (failed.some(({ pos }) => pos === block.pos)) {
|
|
47680
|
+
for (const [at, want] of block.wanted) if (want?.form === "literal") block.wanted.set(at, null);
|
|
47681
|
+
}
|
|
47682
|
+
tr = attempt(blocks);
|
|
47683
|
+
if (edited.every((block) => readsBack(ctx, tr, block.pos))) return finish(tr);
|
|
47684
|
+
return null;
|
|
47386
47685
|
}
|
|
47387
47686
|
}));
|
|
47388
47687
|
//#endregion
|
|
@@ -49720,7 +50019,8 @@ function formattedOutside(node) {
|
|
|
49720
50019
|
};
|
|
49721
50020
|
return result;
|
|
49722
50021
|
}
|
|
49723
|
-
function written(node) {
|
|
50022
|
+
function written(node, inTable = false) {
|
|
50023
|
+
if (inTable && node.url.includes("|")) return "brackets";
|
|
49724
50024
|
if (bracketLinks.has(node)) return "brackets";
|
|
49725
50025
|
const form = formOf(node);
|
|
49726
50026
|
if (form === "literal" && bareLinks.has(node)) return "bare";
|
|
@@ -49736,12 +50036,12 @@ function withResourceLink(state, resourceLink, write) {
|
|
|
49736
50036
|
}
|
|
49737
50037
|
}
|
|
49738
50038
|
var link = (node, parent, state, info) => {
|
|
49739
|
-
const form = written(node);
|
|
50039
|
+
const form = written(node, state.stack.includes("tableCell"));
|
|
49740
50040
|
if (form === "bare") return node.children[0].value;
|
|
49741
50041
|
return withResourceLink(state, form === "brackets", () => handle.link(node, parent, state, info));
|
|
49742
50042
|
};
|
|
49743
50043
|
link.peek = (node, parent, state) => {
|
|
49744
|
-
const form = written(node);
|
|
50044
|
+
const form = written(node, state.stack.includes("tableCell"));
|
|
49745
50045
|
if (form === "bare") return node.children[0].value[0];
|
|
49746
50046
|
return withResourceLink(state, form === "brackets", () => handle.link.peek(node, parent, state));
|
|
49747
50047
|
};
|
|
@@ -50096,7 +50396,11 @@ function createDialect(images, wikiLinks = false, files = false) {
|
|
|
50096
50396
|
}
|
|
50097
50397
|
})),
|
|
50098
50398
|
references,
|
|
50099
|
-
wikiLinks ?
|
|
50399
|
+
wikiLinks ? [
|
|
50400
|
+
wikiLinkSchema,
|
|
50401
|
+
wikiLinkComposition,
|
|
50402
|
+
wikiLinkInputRule
|
|
50403
|
+
] : [],
|
|
50100
50404
|
callouts,
|
|
50101
50405
|
comments,
|
|
50102
50406
|
hiddenCommentEditing,
|
|
@@ -50300,16 +50604,16 @@ var literalReread = $prose((ctx) => new Plugin({
|
|
|
50300
50604
|
//#region src/decorations.ts
|
|
50301
50605
|
var copyIcon = "<svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"5.5\" y=\"5.5\" width=\"8\" height=\"8\" rx=\"1.5\"/><path d=\"M10.5 5.5v-2a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2\"/></svg>";
|
|
50302
50606
|
var doneIcon = "<svg width=\"14\" height=\"14\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3.5 8.5l3 3 6-6.5\"/></svg>";
|
|
50303
|
-
function copyButton(onCopy, label) {
|
|
50607
|
+
function copyButton(onCopy, label, text) {
|
|
50304
50608
|
const button = document.createElement("button");
|
|
50305
50609
|
button.type = "button";
|
|
50610
|
+
button.tabIndex = 0;
|
|
50306
50611
|
button.className = "inkkit-copy";
|
|
50307
50612
|
button.setAttribute("aria-label", label);
|
|
50308
50613
|
button.innerHTML = copyIcon;
|
|
50309
50614
|
button.addEventListener("mousedown", (event) => event.preventDefault());
|
|
50310
50615
|
button.addEventListener("click", () => {
|
|
50311
|
-
|
|
50312
|
-
onCopy(code?.textContent ?? "");
|
|
50616
|
+
onCopy(text());
|
|
50313
50617
|
button.dataset.copied = "";
|
|
50314
50618
|
button.innerHTML = doneIcon;
|
|
50315
50619
|
window.setTimeout(() => {
|
|
@@ -50326,7 +50630,10 @@ function codeCopyPlugin(onCopy) {
|
|
|
50326
50630
|
const widgets = [];
|
|
50327
50631
|
state.doc.descendants((node, pos) => {
|
|
50328
50632
|
if (node.type.name !== "code_block") return true;
|
|
50329
|
-
widgets.push(Decoration.widget(pos + 1, () => copyButton(onCopy, editorLabels(ctx).copyCode
|
|
50633
|
+
widgets.push(Decoration.widget(pos + 1, (view, getPos) => copyButton(onCopy, editorLabels(ctx).copyCode, () => {
|
|
50634
|
+
const at = getPos();
|
|
50635
|
+
return at == null ? "" : view.state.doc.nodeAt(at - 1)?.textContent ?? "";
|
|
50636
|
+
}), {
|
|
50330
50637
|
side: -1,
|
|
50331
50638
|
key: "copy",
|
|
50332
50639
|
ignoreSelection: true
|
|
@@ -50349,6 +50656,315 @@ var placeholderPlugin = $prose((ctx) => new Plugin({
|
|
|
50349
50656
|
} }
|
|
50350
50657
|
}));
|
|
50351
50658
|
//#endregion
|
|
50659
|
+
//#region src/code-languages.ts
|
|
50660
|
+
var codeLanguages = [
|
|
50661
|
+
["arduino", "Arduino"],
|
|
50662
|
+
["bash", "Bash"],
|
|
50663
|
+
["c", "C"],
|
|
50664
|
+
["cpp", "C++"],
|
|
50665
|
+
["csharp", "C#"],
|
|
50666
|
+
["css", "CSS"],
|
|
50667
|
+
["diff", "Diff"],
|
|
50668
|
+
["go", "Go"],
|
|
50669
|
+
["graphql", "GraphQL"],
|
|
50670
|
+
["ini", "INI"],
|
|
50671
|
+
["java", "Java"],
|
|
50672
|
+
["javascript", "JavaScript"],
|
|
50673
|
+
["json", "JSON"],
|
|
50674
|
+
["kotlin", "Kotlin"],
|
|
50675
|
+
["less", "Less"],
|
|
50676
|
+
["lua", "Lua"],
|
|
50677
|
+
["makefile", "Makefile"],
|
|
50678
|
+
["markdown", "Markdown"],
|
|
50679
|
+
["objectivec", "Objective-C"],
|
|
50680
|
+
["perl", "Perl"],
|
|
50681
|
+
["php", "PHP"],
|
|
50682
|
+
["php-template", "PHP template"],
|
|
50683
|
+
["python", "Python"],
|
|
50684
|
+
["python-repl", "Python REPL"],
|
|
50685
|
+
["r", "R"],
|
|
50686
|
+
["ruby", "Ruby"],
|
|
50687
|
+
["rust", "Rust"],
|
|
50688
|
+
["scss", "SCSS"],
|
|
50689
|
+
["shell", "Shell"],
|
|
50690
|
+
["sql", "SQL"],
|
|
50691
|
+
["swift", "Swift"],
|
|
50692
|
+
["typescript", "TypeScript"],
|
|
50693
|
+
["vbnet", "Visual Basic .NET"],
|
|
50694
|
+
["wasm", "WebAssembly"],
|
|
50695
|
+
["xml", "HTML / XML"],
|
|
50696
|
+
["yaml", "YAML"]
|
|
50697
|
+
];
|
|
50698
|
+
//#endregion
|
|
50699
|
+
//#region src/code-controls.ts
|
|
50700
|
+
var codeControlCtx = $ctx((operation) => operation(), "inkkitCodeControl");
|
|
50701
|
+
function codeControlsPlugin(visibleRect) {
|
|
50702
|
+
return $prose((ctx) => new Plugin({
|
|
50703
|
+
key: new PluginKey("codeControls"),
|
|
50704
|
+
props: { decorations(state) {
|
|
50705
|
+
const widgets = [];
|
|
50706
|
+
state.doc.descendants((node, pos) => {
|
|
50707
|
+
if (node.type.name !== "code_block") return true;
|
|
50708
|
+
const language = String(node.attrs.language ?? "");
|
|
50709
|
+
widgets.push(Decoration.widget(pos + 1, (view, getPos) => {
|
|
50710
|
+
const labels = editorLabels(ctx);
|
|
50711
|
+
const wrapper = document.createElement("span");
|
|
50712
|
+
wrapper.className = "inkkit-code-controls";
|
|
50713
|
+
const button = document.createElement("button");
|
|
50714
|
+
button.type = "button";
|
|
50715
|
+
button.tabIndex = 0;
|
|
50716
|
+
button.className = "inkkit-code-language";
|
|
50717
|
+
button.textContent = language === "text" || language === "plaintext" ? labels.codePlainText : codeLanguages.find(([value]) => value === language)?.[1] ?? (language || labels.codeAuto);
|
|
50718
|
+
button.setAttribute("aria-label", labels.codeLanguage);
|
|
50719
|
+
button.setAttribute("aria-haspopup", "dialog");
|
|
50720
|
+
button.setAttribute("aria-expanded", "false");
|
|
50721
|
+
wrapper.append(button);
|
|
50722
|
+
let popup;
|
|
50723
|
+
let restore;
|
|
50724
|
+
const close = (focus = false) => {
|
|
50725
|
+
popup?.remove();
|
|
50726
|
+
popup = void 0;
|
|
50727
|
+
restore?.();
|
|
50728
|
+
restore = void 0;
|
|
50729
|
+
button.setAttribute("aria-expanded", "false");
|
|
50730
|
+
if (focus) button.focus();
|
|
50731
|
+
};
|
|
50732
|
+
button.addEventListener("mousedown", (event) => event.preventDefault());
|
|
50733
|
+
button.addEventListener("click", () => {
|
|
50734
|
+
if (popup) {
|
|
50735
|
+
close();
|
|
50736
|
+
return;
|
|
50737
|
+
}
|
|
50738
|
+
const captured = view.state.doc;
|
|
50739
|
+
popup = document.createElement("span");
|
|
50740
|
+
popup.className = "inkkit-code-language-menu";
|
|
50741
|
+
popup.setAttribute("role", "dialog");
|
|
50742
|
+
popup.setAttribute("aria-label", labels.codeLanguage);
|
|
50743
|
+
popup.contentEditable = "false";
|
|
50744
|
+
const search = document.createElement("input");
|
|
50745
|
+
search.type = "search";
|
|
50746
|
+
search.placeholder = labels.codeLanguageSearch;
|
|
50747
|
+
search.setAttribute("aria-label", labels.codeLanguageSearch);
|
|
50748
|
+
const list = document.createElement("span");
|
|
50749
|
+
list.className = "inkkit-code-language-list";
|
|
50750
|
+
popup.append(search, list);
|
|
50751
|
+
const choices = [
|
|
50752
|
+
["", labels.codeAuto],
|
|
50753
|
+
["text", labels.codePlainText],
|
|
50754
|
+
...codeLanguages
|
|
50755
|
+
];
|
|
50756
|
+
if (language && !choices.some(([value]) => value === language)) choices.push([language, language]);
|
|
50757
|
+
const render = () => {
|
|
50758
|
+
list.replaceChildren();
|
|
50759
|
+
for (const [value, name] of choices) {
|
|
50760
|
+
if (!`${value} ${name}`.toLowerCase().includes(search.value.toLowerCase())) continue;
|
|
50761
|
+
const option = document.createElement("button");
|
|
50762
|
+
option.type = "button";
|
|
50763
|
+
option.textContent = name;
|
|
50764
|
+
option.setAttribute("aria-pressed", String(value === language));
|
|
50765
|
+
option.addEventListener("click", () => {
|
|
50766
|
+
close();
|
|
50767
|
+
if (view.state.doc !== captured) return;
|
|
50768
|
+
ctx.get(codeControlCtx.key)(() => {
|
|
50769
|
+
const at = getPos();
|
|
50770
|
+
if (at == null) return false;
|
|
50771
|
+
const position = at - 1;
|
|
50772
|
+
const current = view.state.doc.nodeAt(position);
|
|
50773
|
+
if (current?.type.name !== "code_block") return false;
|
|
50774
|
+
if (value === language) {
|
|
50775
|
+
view.focus();
|
|
50776
|
+
return false;
|
|
50777
|
+
}
|
|
50778
|
+
const transaction = view.state.tr.setNodeMarkup(position, void 0, {
|
|
50779
|
+
...current.attrs,
|
|
50780
|
+
language: value,
|
|
50781
|
+
authoredFence: languageFence(current.attrs.authoredFence, value)
|
|
50782
|
+
});
|
|
50783
|
+
view.dispatch(closeHistory(transaction));
|
|
50784
|
+
view.dispatch(closeHistory(view.state.tr).setMeta("addToHistory", false));
|
|
50785
|
+
view.focus();
|
|
50786
|
+
return true;
|
|
50787
|
+
});
|
|
50788
|
+
});
|
|
50789
|
+
list.append(option);
|
|
50790
|
+
}
|
|
50791
|
+
};
|
|
50792
|
+
search.addEventListener("input", render);
|
|
50793
|
+
popup.addEventListener("keydown", (event) => {
|
|
50794
|
+
if (event.key === "Escape") {
|
|
50795
|
+
event.preventDefault();
|
|
50796
|
+
event.stopPropagation();
|
|
50797
|
+
close(true);
|
|
50798
|
+
}
|
|
50799
|
+
if (event.key === "ArrowDown") {
|
|
50800
|
+
event.preventDefault();
|
|
50801
|
+
const options = [...list.querySelectorAll("button")];
|
|
50802
|
+
options[(options.indexOf(document.activeElement) + 1) % options.length]?.focus();
|
|
50803
|
+
}
|
|
50804
|
+
if (event.key === "ArrowUp") {
|
|
50805
|
+
event.preventDefault();
|
|
50806
|
+
const options = [...list.querySelectorAll("button")];
|
|
50807
|
+
options[(options.indexOf(document.activeElement) - 1 + options.length) % options.length]?.focus();
|
|
50808
|
+
}
|
|
50809
|
+
if (event.key === "Enter" && event.target === search) {
|
|
50810
|
+
event.preventDefault();
|
|
50811
|
+
list.querySelector("button")?.click();
|
|
50812
|
+
}
|
|
50813
|
+
});
|
|
50814
|
+
wrapper.append(popup);
|
|
50815
|
+
render();
|
|
50816
|
+
const bounds = button.getBoundingClientRect();
|
|
50817
|
+
const safe = visibleRect();
|
|
50818
|
+
const left = Math.max(8, safe.left + 4);
|
|
50819
|
+
const right = Math.min(window.innerWidth - 8, safe.right - 4);
|
|
50820
|
+
const top = Math.max(8, safe.top + 4);
|
|
50821
|
+
const bottom = Math.min(window.innerHeight - 8, safe.bottom - 4);
|
|
50822
|
+
const below = Math.max(0, bottom - bounds.bottom - 4);
|
|
50823
|
+
const above = Math.max(0, bounds.top - top - 4);
|
|
50824
|
+
const height = Math.min(320, Math.max(below, above));
|
|
50825
|
+
popup.style.width = `${Math.max(0, Math.min(220, right - left))}px`;
|
|
50826
|
+
popup.style.maxHeight = `${height}px`;
|
|
50827
|
+
popup.style.left = `${Math.max(left, Math.min(bounds.right - 220, right - 220))}px`;
|
|
50828
|
+
const menuHeight = Math.min(height, popup.getBoundingClientRect().height);
|
|
50829
|
+
popup.style.top = `${Math.max(top, Math.min(below >= menuHeight ? bounds.bottom + 4 : bounds.top - menuHeight - 4, bottom - menuHeight))}px`;
|
|
50830
|
+
const outside = (event) => {
|
|
50831
|
+
if (!wrapper.contains(event.target)) close();
|
|
50832
|
+
};
|
|
50833
|
+
const scroll = (event) => {
|
|
50834
|
+
if (popup?.contains(event.target)) return;
|
|
50835
|
+
const current = button.getBoundingClientRect();
|
|
50836
|
+
if (current.top !== bounds.top || current.left !== bounds.left || current.bottom !== bounds.bottom || current.right !== bounds.right) close();
|
|
50837
|
+
};
|
|
50838
|
+
document.addEventListener("pointerdown", outside, true);
|
|
50839
|
+
window.addEventListener("scroll", scroll, true);
|
|
50840
|
+
restore = () => {
|
|
50841
|
+
document.removeEventListener("pointerdown", outside, true);
|
|
50842
|
+
window.removeEventListener("scroll", scroll, true);
|
|
50843
|
+
};
|
|
50844
|
+
button.setAttribute("aria-expanded", "true");
|
|
50845
|
+
render();
|
|
50846
|
+
search.focus({ preventScroll: true });
|
|
50847
|
+
});
|
|
50848
|
+
wrapper.cleanup = close;
|
|
50849
|
+
return wrapper;
|
|
50850
|
+
}, {
|
|
50851
|
+
side: -1,
|
|
50852
|
+
key: `language:${language}`,
|
|
50853
|
+
ignoreSelection: true,
|
|
50854
|
+
stopEvent: () => true,
|
|
50855
|
+
destroy: (dom) => dom.cleanup?.()
|
|
50856
|
+
}));
|
|
50857
|
+
return false;
|
|
50858
|
+
});
|
|
50859
|
+
return DecorationSet.create(state.doc, widgets);
|
|
50860
|
+
} },
|
|
50861
|
+
view: (view) => ({ update(next, previous) {
|
|
50862
|
+
if (next.state.doc !== previous.doc || !next.editable) view.dom.querySelectorAll(".inkkit-code-controls").forEach((element) => element.cleanup?.());
|
|
50863
|
+
} })
|
|
50864
|
+
}));
|
|
50865
|
+
}
|
|
50866
|
+
//#endregion
|
|
50867
|
+
//#region src/mode-selection.ts
|
|
50868
|
+
function modeSelectionMap(ctx, source, doc) {
|
|
50869
|
+
const points = [];
|
|
50870
|
+
const bom = source.startsWith("") ? 1 : 0;
|
|
50871
|
+
let text = "";
|
|
50872
|
+
const offsets = [];
|
|
50873
|
+
const ends = [];
|
|
50874
|
+
const append = (value, positions) => {
|
|
50875
|
+
for (let index = 0; index < value.length; index++) offsets[text.length + index] = positions[index];
|
|
50876
|
+
for (let index = 1; index <= value.length; index++) ends[text.length + index] = positions[index];
|
|
50877
|
+
text += value;
|
|
50878
|
+
};
|
|
50879
|
+
const visit = (node) => {
|
|
50880
|
+
if (node.type === "definition") return;
|
|
50881
|
+
if ("children" in node) {
|
|
50882
|
+
node.children.forEach((child) => visit(child));
|
|
50883
|
+
return;
|
|
50884
|
+
}
|
|
50885
|
+
const start = node.position?.start.offset;
|
|
50886
|
+
const end = node.position?.end.offset;
|
|
50887
|
+
if (start == null || end == null || !("value" in node)) return;
|
|
50888
|
+
const raw = source.slice(start + bom, end + bom);
|
|
50889
|
+
if (node.type === "text") {
|
|
50890
|
+
const decoded = decodedOffsets(raw, true);
|
|
50891
|
+
if (decoded) append(decoded.decoded, decoded.offsets.map((at) => at + start + bom));
|
|
50892
|
+
} else if (node.type === "inlineCode") {
|
|
50893
|
+
const exact = raw.indexOf(node.value);
|
|
50894
|
+
if (exact >= 0) {
|
|
50895
|
+
append(node.value, Array.from({ length: node.value.length + 1 }, (_, index) => start + bom + exact + index));
|
|
50896
|
+
return;
|
|
50897
|
+
}
|
|
50898
|
+
const ticks = /^`+/.exec(raw)?.[0].length ?? 0;
|
|
50899
|
+
let value = "";
|
|
50900
|
+
const positions = [];
|
|
50901
|
+
for (let index = ticks; index < raw.length - ticks; index++) {
|
|
50902
|
+
positions.push(start + bom + index);
|
|
50903
|
+
if (raw[index] === "\r" && raw[index + 1] === "\n") index++;
|
|
50904
|
+
value += /[\r\n]/.test(raw[index]) ? " " : raw[index];
|
|
50905
|
+
}
|
|
50906
|
+
positions.push(start + bom + raw.length - ticks);
|
|
50907
|
+
if (value.startsWith(" ") && value.endsWith(" ") && /[^ ]/.test(value)) {
|
|
50908
|
+
value = value.slice(1, -1);
|
|
50909
|
+
positions.shift();
|
|
50910
|
+
positions.pop();
|
|
50911
|
+
}
|
|
50912
|
+
append(value, positions);
|
|
50913
|
+
} else if (node.type === "code") {
|
|
50914
|
+
const lines = [...raw.matchAll(/([^\r\n]*)(\r\n|\r|\n|$)/g)];
|
|
50915
|
+
let line = /^(`{3,}|~{3,})/.test(raw) ? 1 : 0;
|
|
50916
|
+
const value = node.value.replace(/\r\n?/g, "\n");
|
|
50917
|
+
const positions = [];
|
|
50918
|
+
let offset = 0;
|
|
50919
|
+
for (const content of value.split("\n")) {
|
|
50920
|
+
while (line < lines.length && !lines[line][1].endsWith(content)) line++;
|
|
50921
|
+
const match = lines[line++];
|
|
50922
|
+
if (!match) return;
|
|
50923
|
+
const at = match.index + match[1].length - content.length;
|
|
50924
|
+
for (let index = 0; index <= content.length; index++) positions[offset + index] = start + bom + at + index;
|
|
50925
|
+
offset += content.length + 1;
|
|
50926
|
+
}
|
|
50927
|
+
append(value, positions);
|
|
50928
|
+
} else if (node.type === "html" || node.type === "inkkitLiteral") {
|
|
50929
|
+
const value = node.value;
|
|
50930
|
+
const at = raw.indexOf(value);
|
|
50931
|
+
if (at >= 0) append(value, Array.from({ length: value.length + 1 }, (_, index) => start + bom + at + index));
|
|
50932
|
+
}
|
|
50933
|
+
};
|
|
50934
|
+
const processor = ctx.get(remarkCtx);
|
|
50935
|
+
processor.runSync(processor.parse(source), { value: source }).children.forEach((node) => visit(node));
|
|
50936
|
+
let cursor = 0;
|
|
50937
|
+
doc.descendants((node, position) => {
|
|
50938
|
+
if ([
|
|
50939
|
+
"comment_inline",
|
|
50940
|
+
"comment_block",
|
|
50941
|
+
"reference_definition"
|
|
50942
|
+
].includes(node.type.name)) return false;
|
|
50943
|
+
if (!node.isText) return true;
|
|
50944
|
+
const value = node.text;
|
|
50945
|
+
const at = text.indexOf(value, cursor);
|
|
50946
|
+
if (at < 0) return false;
|
|
50947
|
+
for (let index = 0; index <= value.length; index++) {
|
|
50948
|
+
const offset = index === value.length ? ends[at + index] : offsets[at + index];
|
|
50949
|
+
if (offset != null) points.push({
|
|
50950
|
+
formatted: position + index,
|
|
50951
|
+
source: offset
|
|
50952
|
+
});
|
|
50953
|
+
}
|
|
50954
|
+
cursor = at + value.length;
|
|
50955
|
+
return false;
|
|
50956
|
+
});
|
|
50957
|
+
const nearest = (position, from, to, bias = -1) => {
|
|
50958
|
+
let best;
|
|
50959
|
+
for (const point of points) if (!best || Math.abs(point[from] - position) < Math.abs(best[from] - position) || bias > 0 && Math.abs(point[from] - position) === Math.abs(best[from] - position)) best = point;
|
|
50960
|
+
return best?.[to] ?? (from === "formatted" ? 0 : 1);
|
|
50961
|
+
};
|
|
50962
|
+
return {
|
|
50963
|
+
source: (position, bias = -1) => nearest(position, "formatted", "source", bias),
|
|
50964
|
+
formatted: (offset) => nearest(offset, "source", "formatted")
|
|
50965
|
+
};
|
|
50966
|
+
}
|
|
50967
|
+
//#endregion
|
|
50352
50968
|
//#region src/reference-clipboard.ts
|
|
50353
50969
|
function key(node) {
|
|
50354
50970
|
if (node.type.name === "reference_definition") return `link:${node.attrs.identifier}`;
|
|
@@ -55956,14 +56572,24 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55956
56572
|
expectOneOf(mode, editingModes, "mode");
|
|
55957
56573
|
this.assertCurrent(expectedGeneration);
|
|
55958
56574
|
if (this.formatType === "txt" || this.mode === mode) return false;
|
|
56575
|
+
const wasSource = this.literalSurface;
|
|
56576
|
+
const view = this.editor.ctx.get(editorViewCtx);
|
|
56577
|
+
const focused = wasSource ? this.plain.ownerDocument.activeElement === this.plain : view.hasFocus();
|
|
56578
|
+
const container = this.viewportContainer ?? this.root;
|
|
56579
|
+
const previousSurface = wasSource ? this.plain : container;
|
|
56580
|
+
const fraction = previousSurface.scrollTop / Math.max(1, previousSurface.scrollHeight - previousSurface.clientHeight);
|
|
56581
|
+
const left = previousSurface.scrollLeft;
|
|
56582
|
+
const sourceSelection = wasSource ? {
|
|
56583
|
+
anchor: this.plain.selectionDirection === "backward" ? this.plain.selectionEnd : this.plain.selectionStart,
|
|
56584
|
+
head: this.plain.selectionDirection === "backward" ? this.plain.selectionStart : this.plain.selectionEnd
|
|
56585
|
+
} : void 0;
|
|
55959
56586
|
this.settleSource();
|
|
55960
56587
|
this.undoneSteps = [];
|
|
55961
56588
|
this.formattedUndone = 0;
|
|
55962
|
-
const view = this.editor.ctx.get(editorViewCtx);
|
|
55963
|
-
const focused = this.literalSurface ? this.plain.ownerDocument.activeElement === this.plain : view.hasFocus();
|
|
55964
|
-
const container = this.viewportContainer ?? this.root;
|
|
55965
|
-
const top = container.scrollTop, left = container.scrollLeft;
|
|
55966
56589
|
const text = this.snapshot().text;
|
|
56590
|
+
const mapping = modeSelectionMap(this.editor.ctx, text, view.state.doc);
|
|
56591
|
+
const anchor = sourceSelection ? mapping.formatted(rawOffset(text, sourceSelection.anchor)) : normalizedOffset(text, mapping.source(view.state.selection.anchor, view.state.selection.anchor < view.state.selection.head ? 1 : -1));
|
|
56592
|
+
const head = sourceSelection ? mapping.formatted(rawOffset(text, sourceSelection.head)) : normalizedOffset(text, mapping.source(view.state.selection.head, view.state.selection.head < view.state.selection.anchor ? 1 : -1));
|
|
55967
56593
|
this.mode = mode;
|
|
55968
56594
|
this.session.modeChanged();
|
|
55969
56595
|
this.cancelExports();
|
|
@@ -55971,8 +56597,8 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55971
56597
|
this.literalMatch = void 0;
|
|
55972
56598
|
if (mode === "source") {
|
|
55973
56599
|
this.plain.value = text;
|
|
55974
|
-
this.plain.setSelectionRange(
|
|
55975
|
-
}
|
|
56600
|
+
this.plain.setSelectionRange(Math.min(anchor, head), Math.max(anchor, head), anchor > head ? "backward" : "forward");
|
|
56601
|
+
} else view.dispatch(view.state.tr.setSelection(TextSelection.between(view.state.doc.resolve(Math.min(anchor, view.state.doc.content.size)), view.state.doc.resolve(Math.min(head, view.state.doc.content.size)))).setMeta("addToHistory", false));
|
|
55976
56602
|
const suppressed = this.reportingSuppressed;
|
|
55977
56603
|
this.reportingSuppressed = true;
|
|
55978
56604
|
try {
|
|
@@ -55980,12 +56606,14 @@ var InkKitEditor = class InkKitEditor {
|
|
|
55980
56606
|
} finally {
|
|
55981
56607
|
this.reportingSuppressed = suppressed;
|
|
55982
56608
|
}
|
|
56609
|
+
const surface = this.literalSurface ? this.plain : container;
|
|
56610
|
+
surface.scrollTop = fraction * Math.max(0, surface.scrollHeight - surface.clientHeight);
|
|
56611
|
+
surface.scrollLeft = left;
|
|
55983
56612
|
if (focused) {
|
|
55984
56613
|
if (this.literalSurface) this.plain.focus({ preventScroll: true });
|
|
55985
|
-
else view.focus();
|
|
56614
|
+
else view.dom.focus({ preventScroll: true });
|
|
56615
|
+
this.revealCurrentSelection();
|
|
55986
56616
|
}
|
|
55987
|
-
container.scrollTop = top;
|
|
55988
|
-
container.scrollLeft = left;
|
|
55989
56617
|
this.publishCommandState();
|
|
55990
56618
|
return true;
|
|
55991
56619
|
}
|
|
@@ -56493,6 +57121,10 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56493
57121
|
...defaultLabels,
|
|
56494
57122
|
...options.labels
|
|
56495
57123
|
}));
|
|
57124
|
+
ctx.set(codeControlCtx.key, (operation) => instance.forPerson(() => instance.facadeCall(() => {
|
|
57125
|
+
instance.assertMutation();
|
|
57126
|
+
return !instance.literalSurface && operation();
|
|
57127
|
+
}), false));
|
|
56496
57128
|
ctx.set(tableControlCtx.key, (operation) => instance.forPerson(() => instance.facadeCall(() => {
|
|
56497
57129
|
instance.assertMutation();
|
|
56498
57130
|
return !instance.literalSurface && operation();
|
|
@@ -56557,7 +57189,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56557
57189
|
return true;
|
|
56558
57190
|
}
|
|
56559
57191
|
}));
|
|
56560
|
-
}).use(labelsCtx).use(instance.pasteController.plugin).use(visibleClipboard).use($prose(() => instance.suggestions.plugin())).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-
|
|
57192
|
+
}).use(labelsCtx).use(instance.pasteController.plugin).use(visibleClipboard).use($prose(() => instance.suggestions.plugin())).use(instance.keymapPlugin).use(createDialect(Boolean(options.images || options.files), Boolean(options.wikiLinks), Boolean(options.files))).use(codeControlCtx).use(codeControlsPlugin(() => instance.viewport().rect)).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-BIasnL-b.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, {
|
|
56561
57193
|
capture: () => instance.adapterCapture(),
|
|
56562
57194
|
active: () => instance.ready && !instance.destroyed && !instance.literalSurface,
|
|
56563
57195
|
labels: {
|