@aicayzer/inkkit 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{core-DrVCeBzK.js → core-Dx4gTiUo.js} +1093 -244
- package/dist/chunks/{highlight-D6evOlOs.js → highlight-GlZZ_7st.js} +1 -1
- package/dist/core.js +1 -1
- package/dist/editor.d.ts +29 -7
- package/dist/index.js +1 -1
- package/dist/style.css +35 -8
- package/dist/types.d.ts +7 -1
- package/package.json +1 -1
|
@@ -2214,7 +2214,7 @@ function tokenizeCharacterEscape(effects, ok, nok) {
|
|
|
2214
2214
|
* } from 'micromark-util-types'
|
|
2215
2215
|
*/
|
|
2216
2216
|
/** @type {Construct} */
|
|
2217
|
-
var characterReference = {
|
|
2217
|
+
var characterReference$1 = {
|
|
2218
2218
|
name: "characterReference",
|
|
2219
2219
|
tokenize: tokenizeCharacterReference
|
|
2220
2220
|
};
|
|
@@ -7349,7 +7349,7 @@ var flow = {
|
|
|
7349
7349
|
};
|
|
7350
7350
|
/** @satisfies {Extension['string']} */
|
|
7351
7351
|
var string = {
|
|
7352
|
-
[38]: characterReference,
|
|
7352
|
+
[38]: characterReference$1,
|
|
7353
7353
|
[92]: characterEscape
|
|
7354
7354
|
};
|
|
7355
7355
|
/** @satisfies {Extension['text']} */
|
|
@@ -7358,7 +7358,7 @@ var text$4 = {
|
|
|
7358
7358
|
[-4]: lineEnding$1,
|
|
7359
7359
|
[-3]: lineEnding$1,
|
|
7360
7360
|
[33]: labelStartImage,
|
|
7361
|
-
[38]: characterReference,
|
|
7361
|
+
[38]: characterReference$1,
|
|
7362
7362
|
[42]: attention$2,
|
|
7363
7363
|
[60]: [autolink$1, htmlText],
|
|
7364
7364
|
[91]: labelStartLink,
|
|
@@ -31817,21 +31817,51 @@ var linkSchemes = /* @__PURE__ */ new Set([
|
|
|
31817
31817
|
"mailto",
|
|
31818
31818
|
"tel"
|
|
31819
31819
|
]);
|
|
31820
|
+
/** Schemes a host may never add: each runs code or reads local data. */
|
|
31821
|
+
var refusedSchemes = /* @__PURE__ */ new Set([
|
|
31822
|
+
"javascript",
|
|
31823
|
+
"data",
|
|
31824
|
+
"vbscript",
|
|
31825
|
+
"file"
|
|
31826
|
+
]);
|
|
31827
|
+
var noSchemes = /* @__PURE__ */ new Set();
|
|
31820
31828
|
/**
|
|
31821
31829
|
* Whether a link address may be kept. Relative paths, queries and fragments
|
|
31822
31830
|
* pass, and so does an address whose scheme is listed, in any letter case.
|
|
31823
|
-
*
|
|
31824
|
-
*
|
|
31825
|
-
*
|
|
31826
|
-
* the
|
|
31827
|
-
* scheme is
|
|
31828
|
-
|
|
31829
|
-
|
|
31831
|
+
* `extra` holds the lower-case schemes one editor's host added. Spaces, tabs
|
|
31832
|
+
* and line breaks at the ends are ignored, as in a browser. Any other control
|
|
31833
|
+
* character makes the address unsafe, because a browser may skip it while it
|
|
31834
|
+
* reads the scheme. The scheme is the text before the first `:` in the part
|
|
31835
|
+
* before the first `/`, `?`, `#` or `\`, so an unknown or malformed scheme is
|
|
31836
|
+
* refused.
|
|
31837
|
+
*/
|
|
31838
|
+
function isSafeLinkTarget(value, extra = noSchemes) {
|
|
31830
31839
|
const target = value.replace(/^[ \t\n\f\r]+|[ \t\n\f\r]+$/g, "");
|
|
31831
31840
|
if (/[\u0000-\u001f\u007f]/.test(target)) return false;
|
|
31832
31841
|
const head = target.slice(0, target.search(/[/?#\\]|$/));
|
|
31833
31842
|
const colon = head.indexOf(":");
|
|
31834
|
-
|
|
31843
|
+
if (colon < 0) return true;
|
|
31844
|
+
const scheme = head.slice(0, colon).toLowerCase();
|
|
31845
|
+
return linkSchemes.has(scheme) || extra.has(scheme);
|
|
31846
|
+
}
|
|
31847
|
+
/**
|
|
31848
|
+
* Checks the host's `linkSchemes` option and returns its entries in lower
|
|
31849
|
+
* case. An entry is a scheme name, and `javascript`, `data`, `vbscript` and
|
|
31850
|
+
* `file` are never accepted.
|
|
31851
|
+
*/
|
|
31852
|
+
function extraLinkSchemes(value, name) {
|
|
31853
|
+
if (!Array.isArray(value)) throw invalidArgument(`${name} must be a list`);
|
|
31854
|
+
return value.map((entry, index) => {
|
|
31855
|
+
if (typeof entry !== "string" || !/^[a-z][a-z0-9+.-]*$/i.test(entry)) throw invalidArgument(`${name}[${index}] must be a scheme name of letters, digits, +, - and ., starting with a letter`);
|
|
31856
|
+
const scheme = entry.toLowerCase();
|
|
31857
|
+
if (refusedSchemes.has(scheme)) throw invalidArgument(`${name}[${index}] cannot be ${scheme}`);
|
|
31858
|
+
return scheme;
|
|
31859
|
+
});
|
|
31860
|
+
}
|
|
31861
|
+
/** The extra schemes of one editor, so that two editors on a page keep their own. */
|
|
31862
|
+
var linkSchemesCtx = $ctx(noSchemes, "inkkitLinkSchemes");
|
|
31863
|
+
function editorLinkSchemes(ctx) {
|
|
31864
|
+
return ctx.isInjected(linkSchemesCtx.key) ? ctx.get(linkSchemesCtx.key) : noSchemes;
|
|
31835
31865
|
}
|
|
31836
31866
|
/**
|
|
31837
31867
|
* Whether an image source would run script if a renderer treated it as an
|
|
@@ -34914,6 +34944,7 @@ var referenceLinks = linkSchema.extendSchema((base) => (ctx) => {
|
|
|
34914
34944
|
const schema = base(ctx);
|
|
34915
34945
|
return {
|
|
34916
34946
|
...schema,
|
|
34947
|
+
inclusive: false,
|
|
34917
34948
|
priority: 40,
|
|
34918
34949
|
attrs: {
|
|
34919
34950
|
...schema.attrs,
|
|
@@ -34942,7 +34973,9 @@ var referenceLinks = linkSchema.extendSchema((base) => (ctx) => {
|
|
|
34942
34973
|
}],
|
|
34943
34974
|
toDOM(mark) {
|
|
34944
34975
|
const attrs = { ...schema.toDOM(mark, false)[1] };
|
|
34945
|
-
|
|
34976
|
+
const href = String(mark.attrs.href ?? "");
|
|
34977
|
+
if (!isSafeLinkTarget(href, editorLinkSchemes(ctx))) attrs.href = "";
|
|
34978
|
+
else if (!attrs.href) attrs.href = href.trim();
|
|
34946
34979
|
delete attrs.label;
|
|
34947
34980
|
delete attrs.identifier;
|
|
34948
34981
|
delete attrs.referenceType;
|
|
@@ -35387,6 +35420,10 @@ var undoSmartPunctuation = (state, dispatch) => {
|
|
|
35387
35420
|
//#region src/linked-syntax.ts
|
|
35388
35421
|
var fromTable = (raw) => raw.replace(/(\\*)\|/g, (_match, escapes) => `${"\\".repeat(Math.floor(escapes.length / 2))}|`);
|
|
35389
35422
|
var toTable = (raw) => raw.replace(/(\\*)\|/g, (_match, escapes) => `${"\\".repeat(escapes.length * 2 + 1)}|`);
|
|
35423
|
+
function pathTableForm(raw, inTable) {
|
|
35424
|
+
if (!inTable) return raw;
|
|
35425
|
+
return raw.replace(/(\\*)\|/g, (_match, escapes) => escapes.length % 2 ? escapes + "|" : escapes + "\\|");
|
|
35426
|
+
}
|
|
35390
35427
|
function parseLinkedSyntax(raw, inTable = false) {
|
|
35391
35428
|
const source = inTable ? fromTable(raw) : raw;
|
|
35392
35429
|
const embed = source.startsWith("!");
|
|
@@ -35473,7 +35510,25 @@ function tableForm(raw, authoredInTable, outputInTable) {
|
|
|
35473
35510
|
if (authoredInTable === outputInTable) return raw;
|
|
35474
35511
|
return outputInTable ? toTable(raw) : fromTable(raw);
|
|
35475
35512
|
}
|
|
35513
|
+
function wikiMarkdown(node, inTable = false) {
|
|
35514
|
+
return tableForm(String(node.attrs.raw), Boolean(node.attrs.inTable), inTable);
|
|
35515
|
+
}
|
|
35516
|
+
function wikiReference(node) {
|
|
35517
|
+
return {
|
|
35518
|
+
raw: wikiMarkdown(node, Boolean(node.attrs.inTable)),
|
|
35519
|
+
target: String(node.attrs.target),
|
|
35520
|
+
...node.attrs.fragment != null ? { fragment: String(node.attrs.fragment) } : {},
|
|
35521
|
+
label: String(node.attrs.label)
|
|
35522
|
+
};
|
|
35523
|
+
}
|
|
35476
35524
|
function fileReference(node) {
|
|
35525
|
+
return {
|
|
35526
|
+
...fileFields(node),
|
|
35527
|
+
raw: fileSource(node)
|
|
35528
|
+
};
|
|
35529
|
+
}
|
|
35530
|
+
/** `fileReference` without the embed's text, which takes writing it. */
|
|
35531
|
+
function fileFields(node) {
|
|
35477
35532
|
const reference = String(node.attrs.src ?? "");
|
|
35478
35533
|
const named = node.attrs.inkkitFileRaw != null;
|
|
35479
35534
|
const alt = String(node.attrs.alt ?? "");
|
|
@@ -35492,11 +35547,49 @@ function fileReference(node) {
|
|
|
35492
35547
|
...width != null ? { width } : {}
|
|
35493
35548
|
};
|
|
35494
35549
|
}
|
|
35550
|
+
var writers = /* @__PURE__ */ new WeakMap();
|
|
35551
|
+
/** Sets how an image of `schema` is written when it has no authored text. */
|
|
35552
|
+
function setImageWriter(schema, write) {
|
|
35553
|
+
writers.set(schema, write);
|
|
35554
|
+
}
|
|
35555
|
+
/**
|
|
35556
|
+
* A file embed's Markdown as the document holds it: its authored text while
|
|
35557
|
+
* the embed is unchanged, otherwise the text InkKit writes for it.
|
|
35558
|
+
*/
|
|
35559
|
+
function fileSource(node) {
|
|
35560
|
+
if (node.attrs.inkkitFileRaw != null) return namedFileMarkdown(node, Boolean(node.attrs.inkkitFileInTable)) ?? "";
|
|
35561
|
+
const authored = authoredFileSource(node);
|
|
35562
|
+
if (authored != null) return authored;
|
|
35563
|
+
const write = writers.get(node.type.schema);
|
|
35564
|
+
if (!write) throw new InkKitError("internal", "The image writer is not set");
|
|
35565
|
+
return pathTableForm(write(node), Boolean(node.attrs.inkkitFileInTable));
|
|
35566
|
+
}
|
|
35567
|
+
/** Only reuse authored spelling while it still describes the image. */
|
|
35568
|
+
function authoredFileSource(node) {
|
|
35569
|
+
const authored = node.attrs.inkkitFileSource;
|
|
35570
|
+
return authored && authored.src === node.attrs.src && authored.alt === node.attrs.alt && authored.title === node.attrs.title ? authored.text : null;
|
|
35571
|
+
}
|
|
35572
|
+
/** Records each path image's Markdown as written, for `FileReference.raw`. */
|
|
35573
|
+
function remarkFileSources() {
|
|
35574
|
+
return (tree, file) => {
|
|
35575
|
+
const source = String(file.value ?? "").replace(/^\uFEFF/, "");
|
|
35576
|
+
const visit = (node, inTable = false) => {
|
|
35577
|
+
if (node.type === "image" && node.inkkitFileRaw == null) {
|
|
35578
|
+
const start = node.position?.start.offset;
|
|
35579
|
+
const end = node.position?.end.offset;
|
|
35580
|
+
if (start != null && end != null) node.inkkitFileSource = source.slice(start, end);
|
|
35581
|
+
node.inkkitFileInTable = inTable;
|
|
35582
|
+
}
|
|
35583
|
+
if ("children" in node) node.children.forEach((child) => visit(child, inTable || node.type === "tableCell"));
|
|
35584
|
+
};
|
|
35585
|
+
visit(tree);
|
|
35586
|
+
};
|
|
35587
|
+
}
|
|
35495
35588
|
function namedFileMarkdown(node, inTable = false) {
|
|
35496
35589
|
if (node.attrs.inkkitFileRaw == null) return void 0;
|
|
35497
35590
|
let raw = String(node.attrs.inkkitFileRaw);
|
|
35498
35591
|
const authoredInTable = Boolean(node.attrs.inkkitFileInTable);
|
|
35499
|
-
const width =
|
|
35592
|
+
const width = fileFields(node).width ?? null;
|
|
35500
35593
|
const original = node.attrs.inkkitFileWidth ?? null;
|
|
35501
35594
|
if (width !== original) {
|
|
35502
35595
|
if (authoredInTable) raw = fromTable(raw);
|
|
@@ -35608,6 +35701,54 @@ var wikiLinkComposition = $prose(() => new Plugin({
|
|
|
35608
35701
|
} } }
|
|
35609
35702
|
}));
|
|
35610
35703
|
/**
|
|
35704
|
+
* A pasted or moved atom retains its original attributes. Stores the spelling
|
|
35705
|
+
* its new context saves before preservation and node views observe it, so
|
|
35706
|
+
* adapter references and clipboard metadata agree.
|
|
35707
|
+
*/
|
|
35708
|
+
var referenceTableContext = $prose(() => new Plugin({
|
|
35709
|
+
key: new PluginKey("inkkitReferenceTableContext"),
|
|
35710
|
+
appendTransaction(transactions, _before, state) {
|
|
35711
|
+
if (!transactions.some((tr) => tr.docChanged)) return null;
|
|
35712
|
+
let ranges = [];
|
|
35713
|
+
for (const transaction of transactions) for (const map of transaction.mapping.maps) {
|
|
35714
|
+
ranges = ranges.map(([from, to]) => [map.map(from, -1), map.map(to)]);
|
|
35715
|
+
map.forEach((_from, _to, from, to) => ranges.push([from, to]));
|
|
35716
|
+
}
|
|
35717
|
+
const tr = state.tr;
|
|
35718
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35719
|
+
for (const [from, to] of ranges) state.doc.nodesBetween(from, to, (node, pos) => {
|
|
35720
|
+
if (![
|
|
35721
|
+
"inkkit_wiki_link",
|
|
35722
|
+
"image",
|
|
35723
|
+
"image_block"
|
|
35724
|
+
].includes(node.type.name) || seen.has(pos)) return;
|
|
35725
|
+
seen.add(pos);
|
|
35726
|
+
const $pos = state.doc.resolve(pos);
|
|
35727
|
+
let inTable = false;
|
|
35728
|
+
for (let depth = $pos.depth; depth > 0; depth--) if (["table_cell", "table_header"].includes($pos.node(depth).type.name)) inTable = true;
|
|
35729
|
+
if (node.type.name === "inkkit_wiki_link") {
|
|
35730
|
+
if (inTable !== Boolean(node.attrs.inTable)) tr.setNodeMarkup(pos, void 0, {
|
|
35731
|
+
...node.attrs,
|
|
35732
|
+
raw: wikiMarkdown(node, inTable),
|
|
35733
|
+
inTable
|
|
35734
|
+
});
|
|
35735
|
+
} else if (inTable !== Boolean(node.attrs.inkkitFileInTable)) {
|
|
35736
|
+
const authored = node.attrs.inkkitFileSource;
|
|
35737
|
+
tr.setNodeMarkup(pos, void 0, {
|
|
35738
|
+
...node.attrs,
|
|
35739
|
+
inkkitFileRaw: namedFileMarkdown(node, inTable) ?? null,
|
|
35740
|
+
inkkitFileSource: authored ? {
|
|
35741
|
+
...authored,
|
|
35742
|
+
text: pathTableForm(authored.text, inTable)
|
|
35743
|
+
} : null,
|
|
35744
|
+
inkkitFileInTable: inTable
|
|
35745
|
+
});
|
|
35746
|
+
}
|
|
35747
|
+
});
|
|
35748
|
+
return tr.steps.length ? tr : null;
|
|
35749
|
+
}
|
|
35750
|
+
}));
|
|
35751
|
+
/**
|
|
35611
35752
|
* Turns `[[target]]`, as the person types its last bracket, into the wiki link
|
|
35612
35753
|
* it reads as when the note is opened, so the note keeps the characters that
|
|
35613
35754
|
* were typed. Left as text, the brackets save as `\[\[target]]`, which no
|
|
@@ -35695,6 +35836,7 @@ function linkedSyntax(wikiLinks, files) {
|
|
|
35695
35836
|
const wiki = (node, _parent, state) => tableForm(String(node.raw), Boolean(node.inTable), state.stack.includes("tableCell"));
|
|
35696
35837
|
const named = (node, parent, state, info) => {
|
|
35697
35838
|
if (node.inkkitFileRaw != null) return tableForm(String(node.inkkitFileRaw), Boolean(node.inkkitFileInTable), state.stack.includes("tableCell"));
|
|
35839
|
+
if (node.inkkitFileSource != null) return pathTableForm(node.inkkitFileSource, state.stack.includes("tableCell"));
|
|
35698
35840
|
return handle.image(node, parent, state, info);
|
|
35699
35841
|
};
|
|
35700
35842
|
return $remark("inkkitLinkedSyntax", () => function() {
|
|
@@ -35719,13 +35861,22 @@ function validName(value) {
|
|
|
35719
35861
|
}
|
|
35720
35862
|
function wikiSuggestionNode(state, name) {
|
|
35721
35863
|
if (!validName(name)) throw invalidArgument("A note suggestion must be a supported note name");
|
|
35722
|
-
|
|
35864
|
+
const { $from } = state.selection;
|
|
35865
|
+
let inTable = false;
|
|
35866
|
+
for (let depth = $from.depth; depth > 0; depth--) if (["table_cell", "table_header"].includes($from.node(depth).type.name)) inTable = true;
|
|
35867
|
+
const node = state.schema.nodes.inkkit_wiki_link.create({
|
|
35723
35868
|
raw: rawName(name),
|
|
35724
35869
|
target: name,
|
|
35725
35870
|
label: name,
|
|
35726
35871
|
fragment: null,
|
|
35727
35872
|
inTable: false
|
|
35728
|
-
}, void 0,
|
|
35873
|
+
}, void 0, $from.marks());
|
|
35874
|
+
if (!inTable) return node;
|
|
35875
|
+
return node.type.create({
|
|
35876
|
+
...node.attrs,
|
|
35877
|
+
raw: wikiMarkdown(node, true),
|
|
35878
|
+
inTable
|
|
35879
|
+
}, void 0, node.marks);
|
|
35729
35880
|
}
|
|
35730
35881
|
function wikiSuggestionTransaction(view, session, name) {
|
|
35731
35882
|
const { state } = view;
|
|
@@ -43197,17 +43348,28 @@ var imageAttrs = {
|
|
|
43197
43348
|
validate: "string"
|
|
43198
43349
|
},
|
|
43199
43350
|
inkkitFileRaw: { default: null },
|
|
43351
|
+
inkkitFileSource: { default: null },
|
|
43200
43352
|
inkkitFileTarget: { default: null },
|
|
43201
43353
|
inkkitFileFragment: { default: null },
|
|
43202
43354
|
inkkitFileWidth: { default: null },
|
|
43203
43355
|
inkkitFileInTable: { default: false }
|
|
43204
43356
|
};
|
|
43205
43357
|
function markdownImageAttrs(node) {
|
|
43358
|
+
const src = String(node.url ?? "");
|
|
43359
|
+
const alt = String(node.alt ?? "");
|
|
43360
|
+
const title = String(node.title ?? "");
|
|
43361
|
+
const source = typeof node.inkkitFileSource === "string" ? {
|
|
43362
|
+
text: node.inkkitFileSource,
|
|
43363
|
+
src,
|
|
43364
|
+
alt,
|
|
43365
|
+
title
|
|
43366
|
+
} : null;
|
|
43206
43367
|
return {
|
|
43207
|
-
src
|
|
43208
|
-
alt
|
|
43209
|
-
title
|
|
43368
|
+
src,
|
|
43369
|
+
alt,
|
|
43370
|
+
title,
|
|
43210
43371
|
inkkitFileRaw: node.inkkitFileRaw ?? null,
|
|
43372
|
+
inkkitFileSource: source,
|
|
43211
43373
|
inkkitFileTarget: node.inkkitFileTarget ?? null,
|
|
43212
43374
|
inkkitFileFragment: node.inkkitFileFragment ?? null,
|
|
43213
43375
|
inkkitFileWidth: node.inkkitFileWidth ?? null,
|
|
@@ -43603,14 +43765,15 @@ var from = {
|
|
|
43603
43765
|
}
|
|
43604
43766
|
}
|
|
43605
43767
|
};
|
|
43768
|
+
var onThreeLines = (isBlock, block, value) => isBlock ? block !== false || /[\r\n]/.test(value) : Boolean(block);
|
|
43606
43769
|
function commentSource(node) {
|
|
43607
43770
|
const body = node.textContent;
|
|
43608
|
-
return node.attrs.syntax === "html" ? `<!--${body}-->` : node.type.name === "comment_block"
|
|
43771
|
+
return node.attrs.syntax === "html" ? `<!--${body}-->` : onThreeLines(node.type.name === "comment_block", node.attrs.block, body) ? `%%\n${body}\n%%` : `%%${body}%%`;
|
|
43609
43772
|
}
|
|
43610
43773
|
var handler = (node) => {
|
|
43611
43774
|
const comment = node;
|
|
43612
43775
|
const value = comment.value ?? "";
|
|
43613
|
-
return comment.syntax === "html" ? `<!--${value}-->` : comment.type === "inkkitCommentBlock"
|
|
43776
|
+
return comment.syntax === "html" ? `<!--${value}-->` : onThreeLines(comment.type === "inkkitCommentBlock", comment.block, value) ? `%%\n${value}\n%%` : `%%${value}%%`;
|
|
43614
43777
|
};
|
|
43615
43778
|
function htmlSpans(value) {
|
|
43616
43779
|
const spans = [];
|
|
@@ -43700,6 +43863,7 @@ function remarkComments() {
|
|
|
43700
43863
|
if (node.type === "paragraph" && parentType !== "listItem" && node.children.length === 1 && node.children[0]?.type === "inkkitCommentInline") return {
|
|
43701
43864
|
...node.children[0],
|
|
43702
43865
|
type: "inkkitCommentBlock",
|
|
43866
|
+
block: false,
|
|
43703
43867
|
position: node.position
|
|
43704
43868
|
};
|
|
43705
43869
|
return node;
|
|
@@ -43739,7 +43903,7 @@ function commentNode(inline) {
|
|
|
43739
43903
|
runner: (state, node, type) => {
|
|
43740
43904
|
state.addNode(type, {
|
|
43741
43905
|
syntax: node.syntax,
|
|
43742
|
-
block: inline ? Boolean(node.block) :
|
|
43906
|
+
block: inline ? Boolean(node.block) : node.block !== false
|
|
43743
43907
|
}, node.value ? [state.schema.text(String(node.value))] : void 0);
|
|
43744
43908
|
}
|
|
43745
43909
|
},
|
|
@@ -43963,6 +44127,25 @@ async function resolveFile(adapter, reference, context) {
|
|
|
43963
44127
|
].includes(presentation.kind)) throw new TypeError("File presentation needs a resource URL");
|
|
43964
44128
|
return Object.freeze({ ...presentation });
|
|
43965
44129
|
}
|
|
44130
|
+
/** The event every reference view hears when the editor's media policy or references change. */
|
|
44131
|
+
var mediaPolicyEvent = "inkkit-media-policy";
|
|
44132
|
+
function requestRefresh(dom, refresh) {
|
|
44133
|
+
dom.dispatchEvent(new CustomEvent(mediaPolicyEvent, { detail: { refresh } }));
|
|
44134
|
+
}
|
|
44135
|
+
/** The refresh a policy event carries. A plain event, such as a host's, carries none. */
|
|
44136
|
+
function refreshOf(event) {
|
|
44137
|
+
const detail = event instanceof CustomEvent ? event.detail : null;
|
|
44138
|
+
return detail && typeof detail === "object" && "refresh" in detail ? detail.refresh : void 0;
|
|
44139
|
+
}
|
|
44140
|
+
function refreshes(refresh, target) {
|
|
44141
|
+
return !refresh.targets || refresh.targets.has(target);
|
|
44142
|
+
}
|
|
44143
|
+
function samePresentation(a, b) {
|
|
44144
|
+
const left = a;
|
|
44145
|
+
const right = b;
|
|
44146
|
+
const keys = Object.keys(left);
|
|
44147
|
+
return keys.length === Object.keys(right).length && keys.every((key) => left[key] === right[key]);
|
|
44148
|
+
}
|
|
43966
44149
|
var FileResolution = class {
|
|
43967
44150
|
runtime;
|
|
43968
44151
|
changed;
|
|
@@ -43977,6 +44160,7 @@ var FileResolution = class {
|
|
|
43977
44160
|
}
|
|
43978
44161
|
update(reference) {
|
|
43979
44162
|
const key = JSON.stringify([
|
|
44163
|
+
reference.raw,
|
|
43980
44164
|
reference.reference,
|
|
43981
44165
|
reference.kind,
|
|
43982
44166
|
reference.fragment
|
|
@@ -43986,8 +44170,23 @@ var FileResolution = class {
|
|
|
43986
44170
|
this.key = key;
|
|
43987
44171
|
this.retry();
|
|
43988
44172
|
}
|
|
44173
|
+
/** Resolves again from a blank loading card. */
|
|
43989
44174
|
retry() {
|
|
43990
44175
|
this.cancel();
|
|
44176
|
+
this.start(true);
|
|
44177
|
+
}
|
|
44178
|
+
/**
|
|
44179
|
+
* Resolves again behind the current card, which stays until the answer differs, so a card that
|
|
44180
|
+
* the host's change doesn't affect neither blanks nor moves.
|
|
44181
|
+
*/
|
|
44182
|
+
refresh() {
|
|
44183
|
+
if (this.dead || !this.runtime.active()) return;
|
|
44184
|
+
if (this.state.status === "idle") this.retry();
|
|
44185
|
+
else this.start(false);
|
|
44186
|
+
}
|
|
44187
|
+
start(blank) {
|
|
44188
|
+
this.request?.controller.abort();
|
|
44189
|
+
this.request = void 0;
|
|
43991
44190
|
if (this.dead || !this.reference || !this.runtime.active()) return;
|
|
43992
44191
|
const captured = this.runtime.capture();
|
|
43993
44192
|
const request = {
|
|
@@ -43995,18 +44194,21 @@ var FileResolution = class {
|
|
|
43995
44194
|
isCurrent: captured.isCurrent
|
|
43996
44195
|
};
|
|
43997
44196
|
this.request = request;
|
|
43998
|
-
|
|
43999
|
-
|
|
44197
|
+
if (blank) {
|
|
44198
|
+
this.state = { status: "loading" };
|
|
44199
|
+
this.changed();
|
|
44200
|
+
}
|
|
44000
44201
|
resolveFile(this.runtime.adapter, this.reference, {
|
|
44001
44202
|
...captured.context,
|
|
44002
44203
|
signal: request.controller.signal
|
|
44003
44204
|
}).then((presentation) => {
|
|
44004
44205
|
if (!this.current(request)) return;
|
|
44206
|
+
const before = this.state;
|
|
44005
44207
|
this.state = {
|
|
44006
44208
|
status: "resolved",
|
|
44007
44209
|
presentation
|
|
44008
44210
|
};
|
|
44009
|
-
this.changed();
|
|
44211
|
+
if (before.status !== "resolved" || !samePresentation(before.presentation, presentation)) this.changed();
|
|
44010
44212
|
}, (failure) => {
|
|
44011
44213
|
if (!this.current(request)) return;
|
|
44012
44214
|
const error = coded(failure, "file-unavailable");
|
|
@@ -44117,7 +44319,7 @@ function nodeText(node, missingImages, fileDescriptions) {
|
|
|
44117
44319
|
if (node.type.name === "image") {
|
|
44118
44320
|
const description = fileDescriptions.get(node.attrs);
|
|
44119
44321
|
if (description != null) return description;
|
|
44120
|
-
const alt =
|
|
44322
|
+
const alt = fileFields(node).label || "Image";
|
|
44121
44323
|
return missingImages.has(String(node.attrs.src ?? "")) ? `[${alt}: image unavailable]` : alt;
|
|
44122
44324
|
}
|
|
44123
44325
|
if (node.type.name === "table") {
|
|
@@ -44131,7 +44333,9 @@ function nodeText(node, missingImages, fileDescriptions) {
|
|
|
44131
44333
|
}
|
|
44132
44334
|
return clipboardText(node.content, missingImages, fileDescriptions);
|
|
44133
44335
|
}
|
|
44134
|
-
|
|
44336
|
+
/** `linkSchemes` are the schemes beyond the built-in ones that a copied link keeps. Print and paste
|
|
44337
|
+
* leave it out, so they keep only the built-in ones. */
|
|
44338
|
+
function clipboardDOM(content, schema, linkSchemes) {
|
|
44135
44339
|
content = shareableFragment(content);
|
|
44136
44340
|
const container = document.createElement("div");
|
|
44137
44341
|
const serializer = DOMSerializer.fromSchema(schema);
|
|
@@ -44144,7 +44348,7 @@ function clipboardDOM(content, schema) {
|
|
|
44144
44348
|
}]
|
|
44145
44349
|
}, {
|
|
44146
44350
|
...serializer.marks,
|
|
44147
|
-
link: (mark, inline) => isSafeLinkTarget(String(mark.attrs.href ?? "")) ? serializer.marks.link(mark, inline) : ["span", 0]
|
|
44351
|
+
link: (mark, inline) => isSafeLinkTarget(String(mark.attrs.href ?? ""), linkSchemes) ? serializer.marks.link(mark, inline) : ["span", 0]
|
|
44148
44352
|
});
|
|
44149
44353
|
container.append(safe.serializeFragment(content));
|
|
44150
44354
|
if (!onlyDefinitions(content)) for (const definition of container.querySelectorAll("[data-inkkit-reference-definition]")) definition.remove();
|
|
@@ -44163,18 +44367,18 @@ function clipboardDOM(content, schema) {
|
|
|
44163
44367
|
}
|
|
44164
44368
|
return container;
|
|
44165
44369
|
}
|
|
44166
|
-
function clipboardContent(content, schema) {
|
|
44370
|
+
function clipboardContent(content, schema, linkSchemes) {
|
|
44167
44371
|
return {
|
|
44168
44372
|
text: clipboardText(content),
|
|
44169
|
-
html: clipboardDOM(content, schema).innerHTML
|
|
44373
|
+
html: clipboardDOM(content, schema, linkSchemes).innerHTML
|
|
44170
44374
|
};
|
|
44171
44375
|
}
|
|
44172
|
-
function clipboardSerializer(schema) {
|
|
44376
|
+
function clipboardSerializer(schema, linkSchemes) {
|
|
44173
44377
|
const serializer = DOMSerializer.fromSchema(schema);
|
|
44174
44378
|
const safe = new DOMSerializer(serializer.nodes, serializer.marks);
|
|
44175
44379
|
safe.serializeFragment = (content, options = {}, target) => {
|
|
44176
44380
|
const output = target ?? (options.document ?? document).createDocumentFragment();
|
|
44177
|
-
output.append(...clipboardDOM(content, schema).childNodes);
|
|
44381
|
+
output.append(...clipboardDOM(content, schema, linkSchemes).childNodes);
|
|
44178
44382
|
return output;
|
|
44179
44383
|
};
|
|
44180
44384
|
return safe;
|
|
@@ -44182,15 +44386,15 @@ function clipboardSerializer(schema) {
|
|
|
44182
44386
|
var visibleClipboard = $prose((ctx) => new Plugin({
|
|
44183
44387
|
key: new PluginKey("visibleClipboard"),
|
|
44184
44388
|
props: {
|
|
44185
|
-
clipboardSerializer: clipboardSerializer(ctx.get(schemaCtx)),
|
|
44389
|
+
clipboardSerializer: clipboardSerializer(ctx.get(schemaCtx), editorLinkSchemes(ctx)),
|
|
44186
44390
|
clipboardTextSerializer: (slice) => clipboardText(slice.content)
|
|
44187
44391
|
}
|
|
44188
44392
|
}));
|
|
44189
44393
|
/** Export a frozen document fragment; presentation URLs never enter the clipboard. */
|
|
44190
|
-
async function portableClipboard(content, schema, markdown, adapter, context, completeDiagrams, files, signal = new AbortController().signal) {
|
|
44394
|
+
async function portableClipboard(content, schema, markdown, adapter, context, completeDiagrams, files, signal = new AbortController().signal, linkSchemes) {
|
|
44191
44395
|
signal.throwIfAborted();
|
|
44192
44396
|
content = shareableFragment(content);
|
|
44193
|
-
const base = clipboardContent(content, schema);
|
|
44397
|
+
const base = clipboardContent(content, schema, linkSchemes);
|
|
44194
44398
|
const container = document.createElement("div");
|
|
44195
44399
|
container.innerHTML = base.html;
|
|
44196
44400
|
const images = [];
|
|
@@ -44202,7 +44406,7 @@ async function portableClipboard(content, schema, markdown, adapter, context, co
|
|
|
44202
44406
|
const captured = [...container.querySelectorAll("img")].map((element, index) => {
|
|
44203
44407
|
const node = references[index];
|
|
44204
44408
|
const reference = String(node?.attrs.src ?? "");
|
|
44205
|
-
const { label: authoredAlt, width } =
|
|
44409
|
+
const { label: authoredAlt, width } = fileFields(node);
|
|
44206
44410
|
const alt = authoredAlt || "Image";
|
|
44207
44411
|
if (width != null && width > 0) element.setAttribute("width", String(Math.min(4096, width)));
|
|
44208
44412
|
element.removeAttribute("src");
|
|
@@ -44805,10 +45009,82 @@ var cursor = [
|
|
|
44805
45009
|
//#endregion
|
|
44806
45010
|
//#region src/text-input.ts
|
|
44807
45011
|
var isInputRules = (plugin) => plugin.spec.isInputRules === true;
|
|
45012
|
+
function heldLink(doc, from, to) {
|
|
45013
|
+
const type = doc.type.schema.marks.link;
|
|
45014
|
+
if (!type) return void 0;
|
|
45015
|
+
let link;
|
|
45016
|
+
let whole = true;
|
|
45017
|
+
doc.nodesBetween(from, to, (node) => {
|
|
45018
|
+
if (!node.isInline) return true;
|
|
45019
|
+
const own = type.isInSet(node.marks);
|
|
45020
|
+
if (!own || link && !own.eq(link)) whole = false;
|
|
45021
|
+
link ??= own;
|
|
45022
|
+
return false;
|
|
45023
|
+
});
|
|
45024
|
+
return whole ? link : void 0;
|
|
45025
|
+
}
|
|
44808
45026
|
/**
|
|
44809
|
-
*
|
|
44810
|
-
*
|
|
44811
|
-
*
|
|
45027
|
+
* The marks that text put in place of `from` to `to` takes. Links are not
|
|
45028
|
+
* inclusive, so text typed at either end of a link stays outside it, but text
|
|
45029
|
+
* that replaces part or all of one link's text stays in that link. Marks
|
|
45030
|
+
* stored for the selection, such as a link started at the caret, come first.
|
|
45031
|
+
*/
|
|
45032
|
+
function replacementMarks(state, from, to) {
|
|
45033
|
+
const { doc, selection, storedMarks } = state;
|
|
45034
|
+
if (storedMarks && selection.from === from && selection.to === to) return storedMarks;
|
|
45035
|
+
const $from = doc.resolve(from);
|
|
45036
|
+
if (from === to) return $from.marks();
|
|
45037
|
+
const $to = doc.resolve(to);
|
|
45038
|
+
const marks = $from.marksAcross($to) ?? $from.marks();
|
|
45039
|
+
const link = $from.sameParent($to) ? heldLink(doc, from, to) : void 0;
|
|
45040
|
+
return link && !link.isInSet(marks) ? link.addToSet(marks) : marks;
|
|
45041
|
+
}
|
|
45042
|
+
/**
|
|
45043
|
+
* The link that typing over its end continues, after typing replaced the end
|
|
45044
|
+
* or all of its text. Its stored marks keep it for the next keystrokes until
|
|
45045
|
+
* the caret moves or another edit clears them.
|
|
45046
|
+
*/
|
|
45047
|
+
var typingKey = new PluginKey("inkkitTextInput");
|
|
45048
|
+
var typingState = {
|
|
45049
|
+
init: () => null,
|
|
45050
|
+
apply(tr, link, _old, state) {
|
|
45051
|
+
const meta = tr.getMeta(typingKey);
|
|
45052
|
+
if (meta !== void 0) return meta;
|
|
45053
|
+
return link && link.isInSet(state.storedMarks ?? []) ? link : null;
|
|
45054
|
+
}
|
|
45055
|
+
};
|
|
45056
|
+
function linkTyping(state, from, to, text) {
|
|
45057
|
+
const type = state.schema.marks.link;
|
|
45058
|
+
if (!type) return void 0;
|
|
45059
|
+
const marks = replacementMarks(state, from, to);
|
|
45060
|
+
const link = type.isInSet(marks);
|
|
45061
|
+
if (!link) return void 0;
|
|
45062
|
+
const stored = type.isInSet(state.storedMarks ?? []);
|
|
45063
|
+
const continued = typingKey.getState(state);
|
|
45064
|
+
const retyped = stored !== void 0 && continued?.eq(stored) || from < to && !type.isInSet(state.doc.resolve(from).marksAcross(state.doc.resolve(to)) ?? []);
|
|
45065
|
+
if (!retyped && !stored) return void 0;
|
|
45066
|
+
const space = retyped ? -1 : text.search(/\s/);
|
|
45067
|
+
const linked = space < 0 ? text.length : space;
|
|
45068
|
+
const address = link.attrs.form != null;
|
|
45069
|
+
return {
|
|
45070
|
+
marks,
|
|
45071
|
+
link,
|
|
45072
|
+
linked,
|
|
45073
|
+
stored: address ? null : linked < text.length ? link.removeFromSet(marks) : marks,
|
|
45074
|
+
retyped: retyped && !address
|
|
45075
|
+
};
|
|
45076
|
+
}
|
|
45077
|
+
function continueLink(tr, from, text, typing) {
|
|
45078
|
+
const linked = Math.min(typing.linked, text.length);
|
|
45079
|
+
tr.removeMark(from, from + text.length, typing.link.type);
|
|
45080
|
+
if (linked) tr.addMark(from, from + linked, typing.link);
|
|
45081
|
+
if (typing.stored) tr.setStoredMarks(typing.stored);
|
|
45082
|
+
return tr.setMeta(typingKey, typing.retyped ? typing.link : null);
|
|
45083
|
+
}
|
|
45084
|
+
/**
|
|
45085
|
+
* Inserts typed text at `from` to `to`, and returns whether it did. It handles
|
|
45086
|
+
* text that arrives in one piece, such as buffered native typing, dictation or
|
|
45087
|
+
* a text replacement, and typing that continues a link.
|
|
44812
45088
|
*
|
|
44813
45089
|
* Input rules are written for one typed character: Milkdown's take their
|
|
44814
45090
|
* positions from the document before the text goes in, so given more than
|
|
@@ -44816,19 +45092,25 @@ var isInputRules = (plugin) => plugin.spec.isInputRules === true;
|
|
|
44816
45092
|
* in except for its last character, and the input rules see that character
|
|
44817
45093
|
* typed after the rest, all in one transaction.
|
|
44818
45094
|
*/
|
|
44819
|
-
function
|
|
45095
|
+
function insertTypedText(view, from, to, text, deflt) {
|
|
44820
45096
|
const characters = Array.from(text);
|
|
44821
|
-
if (characters.length
|
|
45097
|
+
if (!characters.length || view.composing || /[\r\n]/.test(text)) return false;
|
|
44822
45098
|
const { state } = view;
|
|
44823
|
-
const
|
|
44824
|
-
|
|
45099
|
+
const typing = linkTyping(state, from, to, text);
|
|
45100
|
+
if (characters.length < 2 && !typing) return false;
|
|
45101
|
+
const fallback = () => {
|
|
45102
|
+
const plain = deflt();
|
|
45103
|
+
return typing ? continueLink(plain, from, text, typing) : plain;
|
|
45104
|
+
};
|
|
45105
|
+
const marks = typing?.marks ?? replacementMarks(state, from, to);
|
|
44825
45106
|
const last = characters.at(-1);
|
|
44826
45107
|
const rest = text.slice(0, -last.length);
|
|
44827
|
-
const tr = state.tr.insertText(rest, from, to);
|
|
45108
|
+
const tr = rest ? state.tr.setStoredMarks(marks).insertText(rest, from, to) : state.tr.delete(from, to);
|
|
45109
|
+
if (typing) continueLink(tr, from, rest, typing);
|
|
44828
45110
|
const $at = Selection.near(tr.doc.resolve(tr.mapping.map(to)), -1).$head;
|
|
44829
45111
|
const at = $at.pos;
|
|
44830
45112
|
if (!$at.parent.inlineContent || $at.parent.type.spec.code || $at.parentOffset < rest.length || $at.parent.textBetween($at.parentOffset - rest.length, $at.parentOffset) !== rest) {
|
|
44831
|
-
view.dispatch(
|
|
45113
|
+
view.dispatch(fallback().scrollIntoView());
|
|
44832
45114
|
return true;
|
|
44833
45115
|
}
|
|
44834
45116
|
const rules = state.plugins.filter(isInputRules);
|
|
@@ -44836,7 +45118,7 @@ function insertTextChunk(view, from, to, text, deflt) {
|
|
|
44836
45118
|
schema: state.schema,
|
|
44837
45119
|
doc: tr.doc,
|
|
44838
45120
|
selection: TextSelection.create(tr.doc, at),
|
|
44839
|
-
storedMarks:
|
|
45121
|
+
storedMarks: typing && typing.linked < text.length ? typing.link.removeFromSet(marks) : marks
|
|
44840
45122
|
}, rest);
|
|
44841
45123
|
let ruled;
|
|
44842
45124
|
const preparedView = Object.create(view, {
|
|
@@ -44846,7 +45128,7 @@ function insertTextChunk(view, from, to, text, deflt) {
|
|
|
44846
45128
|
} }
|
|
44847
45129
|
});
|
|
44848
45130
|
if (!rules.some((rule) => rule.props.handleTextInput?.call(rule, preparedView, at, at, last, () => prepared.tr.insertText(last, at)))) {
|
|
44849
|
-
const plain =
|
|
45131
|
+
const plain = fallback().scrollIntoView();
|
|
44850
45132
|
view.dispatch(last === "-" ? insertedHyphen(plain) : plain);
|
|
44851
45133
|
return true;
|
|
44852
45134
|
}
|
|
@@ -44854,6 +45136,7 @@ function insertTextChunk(view, from, to, text, deflt) {
|
|
|
44854
45136
|
for (const step of ruled.steps) tr.step(step);
|
|
44855
45137
|
tr.setSelection(ruled.selection.map(tr.doc, StepMap.empty));
|
|
44856
45138
|
if (ruled.storedMarksSet) tr.setStoredMarks(ruled.storedMarks);
|
|
45139
|
+
else if (typing?.stored) tr.setStoredMarks(typing.stored);
|
|
44857
45140
|
for (const rule of rules) {
|
|
44858
45141
|
const meta = ruled.getMeta(rule);
|
|
44859
45142
|
if (meta !== void 0) tr.setMeta(rule, meta);
|
|
@@ -44862,6 +45145,65 @@ function insertTextChunk(view, from, to, text, deflt) {
|
|
|
44862
45145
|
view.dispatch(tr.scrollIntoView());
|
|
44863
45146
|
return true;
|
|
44864
45147
|
}
|
|
45148
|
+
function finishComposition(view, composing) {
|
|
45149
|
+
const { state } = view;
|
|
45150
|
+
const { start, link, retyped } = composing;
|
|
45151
|
+
const end = state.selection.head;
|
|
45152
|
+
if (view.isDestroyed || view.composing || state.doc !== composing.doc || !state.selection.empty || end <= start || !state.doc.resolve(start).sameParent(state.selection.$head)) return;
|
|
45153
|
+
const text = state.doc.textBetween(start, end);
|
|
45154
|
+
if (text.length !== end - start) return;
|
|
45155
|
+
const space = retyped ? -1 : text.search(/\s/);
|
|
45156
|
+
const linked = start + (space < 0 ? text.length : space);
|
|
45157
|
+
const tr = state.tr;
|
|
45158
|
+
if (linked > start) tr.addMark(start, linked, link);
|
|
45159
|
+
const marks = link.type.removeFromSet(tr.doc.resolve(end).marks());
|
|
45160
|
+
tr.setStoredMarks(linked === end ? link.addToSet(marks) : marks).setMeta(typingKey, retyped && linked === end ? link : null).setMeta("composition", composing.composition);
|
|
45161
|
+
view.dispatch(tr);
|
|
45162
|
+
}
|
|
45163
|
+
var controlCharacters = /^[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]+$/;
|
|
45164
|
+
/** Typed text: chunks, control characters, and the link rule for typing and composition. */
|
|
45165
|
+
function textInputPlugin() {
|
|
45166
|
+
let composing;
|
|
45167
|
+
return new Plugin({
|
|
45168
|
+
key: typingKey,
|
|
45169
|
+
state: typingState,
|
|
45170
|
+
props: {
|
|
45171
|
+
handleTextInput: (view, from, to, text, deflt) => controlCharacters.test(text) || insertTypedText(view, from, to, text, deflt),
|
|
45172
|
+
handleDOMEvents: {
|
|
45173
|
+
compositionstart(view) {
|
|
45174
|
+
if (view.composing) return false;
|
|
45175
|
+
const { state } = view;
|
|
45176
|
+
const { from, to } = state.selection;
|
|
45177
|
+
const typing = linkTyping(state, from, to, "");
|
|
45178
|
+
composing = typing?.stored && !view.isDestroyed ? {
|
|
45179
|
+
link: typing.link,
|
|
45180
|
+
retyped: typing.retyped,
|
|
45181
|
+
start: from,
|
|
45182
|
+
doc: state.doc
|
|
45183
|
+
} : void 0;
|
|
45184
|
+
return false;
|
|
45185
|
+
},
|
|
45186
|
+
compositionend(view) {
|
|
45187
|
+
const ended = composing;
|
|
45188
|
+
if (ended) setTimeout(() => {
|
|
45189
|
+
if (composing !== ended) return;
|
|
45190
|
+
composing = void 0;
|
|
45191
|
+
finishComposition(view, ended);
|
|
45192
|
+
});
|
|
45193
|
+
return false;
|
|
45194
|
+
}
|
|
45195
|
+
}
|
|
45196
|
+
},
|
|
45197
|
+
appendTransaction(transactions, _old, state) {
|
|
45198
|
+
if (composing && transactions.some((tr) => tr.docChanged)) for (const tr of transactions) {
|
|
45199
|
+
composing.start = tr.mapping.map(composing.start, -1);
|
|
45200
|
+
composing.composition ??= tr.getMeta("composition");
|
|
45201
|
+
}
|
|
45202
|
+
if (composing) composing.doc = state.doc;
|
|
45203
|
+
return null;
|
|
45204
|
+
}
|
|
45205
|
+
});
|
|
45206
|
+
}
|
|
44865
45207
|
//#endregion
|
|
44866
45208
|
//#region src/drop-placement.ts
|
|
44867
45209
|
/**
|
|
@@ -44977,6 +45319,20 @@ function caretAfterInsertion(tr, view) {
|
|
|
44977
45319
|
return tr.setSelection($end.parent.inlineContent ? TextSelection.create(tr.doc, end) : caretAfter(tr.doc, end, view && calloutFolds(view, tr)));
|
|
44978
45320
|
}
|
|
44979
45321
|
//#endregion
|
|
45322
|
+
//#region src/gutter.ts
|
|
45323
|
+
var listMarker = /(?:[-*+]|\d{1,9}[.)])(?=[ \t])/g;
|
|
45324
|
+
/**
|
|
45325
|
+
* What the lines of a block repeat before it: the quote markers and
|
|
45326
|
+
* indentation that open the line `offset` is on, up to `offset`, with a list
|
|
45327
|
+
* marker as the spaces it takes, which is how the lines after the item's first
|
|
45328
|
+
* are indented. Anything else before `offset` on its line is content, and ends
|
|
45329
|
+
* the gutter.
|
|
45330
|
+
*/
|
|
45331
|
+
function gutterAt(text, offset) {
|
|
45332
|
+
const line = text.slice(text.lastIndexOf("\n", offset - 1) + 1, offset);
|
|
45333
|
+
return /^(?:[ \t]|>|(?:[-*+]|\d{1,9}[.)])(?=[ \t]))*/.exec(line)[0].replace(listMarker, (marker) => " ".repeat(marker.length));
|
|
45334
|
+
}
|
|
45335
|
+
//#endregion
|
|
44980
45336
|
//#region src/code-fences.ts
|
|
44981
45337
|
function readFence(value) {
|
|
44982
45338
|
if (typeof value !== "object" || value == null) return null;
|
|
@@ -45368,10 +45724,11 @@ var formatting = /* @__PURE__ */ new Set([
|
|
|
45368
45724
|
"delete",
|
|
45369
45725
|
"highlight"
|
|
45370
45726
|
]);
|
|
45727
|
+
var linkTypes = /* @__PURE__ */ new Set(["link", "linkReference"]);
|
|
45371
45728
|
function ordered(node) {
|
|
45372
45729
|
let current = node;
|
|
45373
45730
|
const inner = current.children?.[0];
|
|
45374
|
-
if (current.type
|
|
45731
|
+
if (linkTypes.has(current.type) && current.children.length === 1 && formatting.has(inner.type)) current = {
|
|
45375
45732
|
...inner,
|
|
45376
45733
|
children: [{
|
|
45377
45734
|
...current,
|
|
@@ -45383,6 +45740,32 @@ function ordered(node) {
|
|
|
45383
45740
|
children: current.children.map(ordered)
|
|
45384
45741
|
} : current;
|
|
45385
45742
|
}
|
|
45743
|
+
function wrappers$1(node) {
|
|
45744
|
+
const chain = [];
|
|
45745
|
+
for (let at = node; at && (linkTypes.has(at.type) || formatting.has(at.type)); at = at.children?.length === 1 ? at.children[0] : void 0) chain.push(at);
|
|
45746
|
+
return chain;
|
|
45747
|
+
}
|
|
45748
|
+
function authoredNesting(before, after) {
|
|
45749
|
+
if (before.type === after.type || !formatting.has(before.type)) return after;
|
|
45750
|
+
const authored = wrappers$1(before);
|
|
45751
|
+
const written = wrappers$1(after);
|
|
45752
|
+
const types = (chain) => chain.map((node) => node.type).sort().join();
|
|
45753
|
+
const linksIn = (chain) => chain.filter((node) => linkTypes.has(node.type));
|
|
45754
|
+
const shape = (node) => ownShape({
|
|
45755
|
+
...node,
|
|
45756
|
+
children: []
|
|
45757
|
+
});
|
|
45758
|
+
const [authoredLink] = linksIn(authored);
|
|
45759
|
+
const [writtenLink] = linksIn(written);
|
|
45760
|
+
if (linksIn(authored).length !== 1 || linksIn(written).length !== 1 || types(authored) !== types(written) || shape(authoredLink) !== shape(writtenLink) || authored.at(-1).children?.length !== written.at(-1).children?.length) return after;
|
|
45761
|
+
const inner = written.at(-1).children;
|
|
45762
|
+
const byType = new Map(written.map((node) => [node.type, node]));
|
|
45763
|
+
return authored.reduceRight((child, node, level) => ({
|
|
45764
|
+
...byType.get(node.type),
|
|
45765
|
+
...level === 0 && { position: after.position },
|
|
45766
|
+
children: child ? [child] : inner
|
|
45767
|
+
}), void 0);
|
|
45768
|
+
}
|
|
45386
45769
|
/** Where the delimiter row ends, given where the header row before it ends. */
|
|
45387
45770
|
function delimiterRowEnd(text, headerEnd) {
|
|
45388
45771
|
const next = text.indexOf("\n", headerEnd);
|
|
@@ -45391,15 +45774,17 @@ function delimiterRowEnd(text, headerEnd) {
|
|
|
45391
45774
|
ending.lastIndex = next + 1;
|
|
45392
45775
|
return ending.exec(text)?.index ?? text.length;
|
|
45393
45776
|
}
|
|
45394
|
-
function ownShape(node) {
|
|
45777
|
+
function ownShape(node, spreadless = false) {
|
|
45395
45778
|
return JSON.stringify(ordered(node), (key, value) => [
|
|
45396
45779
|
"position",
|
|
45397
45780
|
"data",
|
|
45398
45781
|
"children",
|
|
45399
45782
|
"value",
|
|
45400
45783
|
"marker"
|
|
45401
|
-
].includes(key) ? void 0 : value);
|
|
45784
|
+
].includes(key) || spreadless && key === "spread" ? void 0 : value);
|
|
45402
45785
|
}
|
|
45786
|
+
var holdsLiteralBlock = (node) => (node.type === "listItem" || node.type === "list") && !!node.children?.some((child) => child.type === "inkkitLiteral" || literals$1.has(child) || holdsLiteralBlock(child));
|
|
45787
|
+
var sameShape = (before, after) => ownShape(before) === ownShape(after) || (holdsLiteralBlock(before) || holdsLiteralBlock(after)) && ownShape(before, true) === ownShape(after, true);
|
|
45403
45788
|
var matchShape = (node) => ownShape({
|
|
45404
45789
|
...node,
|
|
45405
45790
|
checked: void 0
|
|
@@ -45456,10 +45841,25 @@ function authoredMarker(list, source) {
|
|
|
45456
45841
|
return at == null ? void 0 : markerAt(source, at)?.marker;
|
|
45457
45842
|
}
|
|
45458
45843
|
var sameList = (before, after) => before.type === "list" && after.type === "list" && before.ordered === after.ordered;
|
|
45459
|
-
function
|
|
45844
|
+
function childGutters(before, after, source, canonical, fromStart = false) {
|
|
45845
|
+
if (inlineParents.has(before.type) || before.type === "table") return void 0;
|
|
45846
|
+
const [first, now] = [before, after].map((node) => fromStart ? node.position?.start.offset : node.children?.[0]?.position?.start.offset);
|
|
45847
|
+
return first == null || now == null ? void 0 : [gutterAt(source, first), gutterAt(canonical, now)];
|
|
45848
|
+
}
|
|
45849
|
+
function regutter(text, gutters, open = false) {
|
|
45850
|
+
if (!gutters || gutters[0] === gutters[1]) return text;
|
|
45851
|
+
const [authored, canonical] = gutters;
|
|
45852
|
+
const bare = canonical.trimEnd();
|
|
45853
|
+
return text.replace(/(\r?\n)([^\r\n]*)/g, (match, ending, line, at) => {
|
|
45854
|
+
if (open && at + match.length === text.length && (line === bare || line === canonical)) return ending + authored;
|
|
45855
|
+
if (line === bare) return ending + authored.trimEnd();
|
|
45856
|
+
return line.startsWith(canonical) ? ending + authored + line.slice(canonical.length) : match;
|
|
45857
|
+
});
|
|
45858
|
+
}
|
|
45859
|
+
function canonicalSlice(marker, children, canonical, from, to, previous, next, gutters, open = false, inherited) {
|
|
45460
45860
|
let text = canonical.slice(from, to);
|
|
45461
45861
|
const offsets = (list) => (list.children ?? []).map((item) => item.position.start.offset - from);
|
|
45462
|
-
if (marker) return relabel(text, children.map((item) => item.position.start.offset - from), marker);
|
|
45862
|
+
if (marker) return regutter(relabel(text, children.map((item) => item.position.start.offset - from), marker), gutters, open);
|
|
45463
45863
|
children.forEach((child, index) => {
|
|
45464
45864
|
if (child.type !== "list") {
|
|
45465
45865
|
previous = void 0;
|
|
@@ -45467,19 +45867,24 @@ function canonicalSlice(marker, children, canonical, from, to, previous, next) {
|
|
|
45467
45867
|
}
|
|
45468
45868
|
const avoid = [previous, index === children.length - 1 ? next : void 0].filter((neighbour) => neighbour?.ordered === child.ordered).map((neighbour) => neighbour.marker);
|
|
45469
45869
|
const own = markerAt(canonical, child.children[0].position.start.offset)?.marker;
|
|
45470
|
-
const choice = [
|
|
45471
|
-
|
|
45472
|
-
|
|
45473
|
-
"
|
|
45474
|
-
|
|
45870
|
+
const choice = [
|
|
45871
|
+
inherited && /[.)]/.test(inherited) === !!child.ordered ? inherited : void 0,
|
|
45872
|
+
own,
|
|
45873
|
+
...child.ordered ? [".", ")"] : [
|
|
45874
|
+
"-",
|
|
45875
|
+
"*",
|
|
45876
|
+
"+"
|
|
45877
|
+
]
|
|
45878
|
+
].find((candidate) => candidate && !avoid.includes(candidate));
|
|
45475
45879
|
if (choice) text = relabel(text, offsets(child), choice);
|
|
45476
45880
|
previous = {
|
|
45477
45881
|
ordered: child.ordered,
|
|
45478
45882
|
marker: choice ?? own ?? ""
|
|
45479
45883
|
};
|
|
45480
45884
|
});
|
|
45481
|
-
return text;
|
|
45885
|
+
return regutter(text, gutters, open);
|
|
45482
45886
|
}
|
|
45887
|
+
var itemMarker = (item, source) => item.type === "listItem" ? markerAt(source, item.position.start.offset)?.marker : void 0;
|
|
45483
45888
|
function authoredNeighbour(before, after, source) {
|
|
45484
45889
|
if (!before || !after || !sameList(before, after)) return void 0;
|
|
45485
45890
|
const marker = authoredMarker(before, source);
|
|
@@ -45579,35 +45984,90 @@ function retainSplit(candidates, after, source, canonical, lineEnding, taken) {
|
|
|
45579
45984
|
text: retainSource(part, after, source, canonical, lineEnding)
|
|
45580
45985
|
};
|
|
45581
45986
|
}
|
|
45582
|
-
function
|
|
45583
|
-
|
|
45987
|
+
function liftedSource(blocks, after, source) {
|
|
45988
|
+
if (after.type === "list" || after.type === "blockquote") return void 0;
|
|
45989
|
+
const wanted = signature(after);
|
|
45990
|
+
const found = [];
|
|
45991
|
+
const visit = (node) => {
|
|
45992
|
+
for (const child of node.children ?? []) if (child.type === "list" || child.type === "listItem" || child.type === "blockquote") visit(child);
|
|
45993
|
+
else if ((node.type === "blockquote" || node.type === "listItem" && node.checked == null) && signature(child) === wanted) found.push(child);
|
|
45994
|
+
};
|
|
45995
|
+
blocks.forEach(visit);
|
|
45996
|
+
if (found.length !== 1) return void 0;
|
|
45997
|
+
const start = found[0].position?.start.offset;
|
|
45998
|
+
const end = found[0].position?.end.offset;
|
|
45999
|
+
if (start == null || end == null) return void 0;
|
|
46000
|
+
return regutter(source.slice(start, end), ["", gutterAt(source, start)]);
|
|
46001
|
+
}
|
|
46002
|
+
function strayRun(strays, wanted, source, opening) {
|
|
46003
|
+
const keys = wanted.map(opening);
|
|
46004
|
+
for (const [at, stray] of strays.entries()) {
|
|
46005
|
+
if (opening(stray) !== keys[0]) continue;
|
|
46006
|
+
const run = [stray];
|
|
46007
|
+
for (const next of strays.slice(at + 1)) {
|
|
46008
|
+
if (opening(next) !== keys[run.length] || !/^[ \t>]*(\r?\n[ \t>]*)+$/.test(source.slice(run.at(-1).position.end.offset, next.position.start.offset))) break;
|
|
46009
|
+
run.push(next);
|
|
46010
|
+
}
|
|
46011
|
+
return run;
|
|
46012
|
+
}
|
|
46013
|
+
return [];
|
|
46014
|
+
}
|
|
46015
|
+
function retainParts(marker, before, after, source, canonical, from, to, lineEnding, previous, next, gutters, open = false, inherited) {
|
|
45584
46016
|
const taken = /* @__PURE__ */ new Set();
|
|
45585
46017
|
const opening = (item) => item.children?.length ? matchShape(item) + signature(item.children[0]) : void 0;
|
|
45586
|
-
const
|
|
46018
|
+
const items = /* @__PURE__ */ new Map();
|
|
46019
|
+
for (let row = before; row.length;) {
|
|
46020
|
+
const deeper = [];
|
|
46021
|
+
for (const node of row) {
|
|
46022
|
+
if (node.type !== "listItem") continue;
|
|
46023
|
+
const key = opening(node);
|
|
46024
|
+
if (key) {
|
|
46025
|
+
const same = items.get(key);
|
|
46026
|
+
if (same) same.push(node);
|
|
46027
|
+
else items.set(key, [node]);
|
|
46028
|
+
}
|
|
46029
|
+
for (const child of node.children ?? []) if (child.type === "list") deeper.push(...child.children ?? []);
|
|
46030
|
+
}
|
|
46031
|
+
row = deeper;
|
|
46032
|
+
}
|
|
46033
|
+
const isNumbered = (item) => /[.)]/.test(itemMarker(item, source) ?? "");
|
|
46034
|
+
const originals = after.map((child) => {
|
|
46035
|
+
const original = child.type === "listItem" ? items.get(opening(child) ?? "")?.shift() : void 0;
|
|
46036
|
+
return original && marker && isNumbered(original) !== /[.)]/.test(marker) ? void 0 : original;
|
|
46037
|
+
});
|
|
46038
|
+
const ownLevel = new Set(before);
|
|
46039
|
+
const strays = [...items.values()].flat().sort((left, right) => left.position.start.offset - right.position.start.offset);
|
|
46040
|
+
const pieces = after.map((child, index) => {
|
|
45587
46041
|
const end = child.position.end.offset;
|
|
45588
46042
|
if (child.type === "list" || child.type === "blockquote") {
|
|
45589
46043
|
const part = retainSplit(before, child, source, canonical, lineEnding, taken);
|
|
45590
46044
|
if (part) return part.text + canonical.slice(child.children.at(-1).position.end.offset, end);
|
|
45591
46045
|
const lists = before.filter((node) => node.type === "list" && node.ordered === child.ordered);
|
|
45592
|
-
|
|
45593
|
-
|
|
45594
|
-
|
|
45595
|
-
|
|
45596
|
-
|
|
45597
|
-
|
|
45598
|
-
|
|
45599
|
-
|
|
45600
|
-
|
|
45601
|
-
|
|
45602
|
-
|
|
46046
|
+
if (child.type === "list" && !lists.length) {
|
|
46047
|
+
const run = strayRun(strays, child.children, source, opening);
|
|
46048
|
+
if (!run.length) return void 0;
|
|
46049
|
+
const first = run[0].position.start.offset;
|
|
46050
|
+
return regutter(retainSource({
|
|
46051
|
+
type: "list",
|
|
46052
|
+
ordered: child.ordered,
|
|
46053
|
+
start: child.ordered ? Number(/^\d+/.exec(source.slice(first))[0]) : null,
|
|
46054
|
+
spread: false,
|
|
46055
|
+
children: run,
|
|
46056
|
+
position: {
|
|
46057
|
+
start: { offset: first },
|
|
46058
|
+
end: { offset: run.at(-1).position.end.offset }
|
|
46059
|
+
}
|
|
46060
|
+
}, child, source, canonical, lineEnding), gutters && [gutters[0], gutterAt(source, first)]) + canonical.slice(child.children.at(-1).position.end.offset, end);
|
|
45603
46061
|
}
|
|
46062
|
+
return child.type === "list" && lists.length ? retainParts(authoredMarker(lists[0], source), lists.flatMap((list) => list.children ?? []), child.children, source, canonical, child.position.start.offset, end, lineEnding, void 0, void 0, childGutters(lists[0], child, source, canonical)) : void 0;
|
|
45604
46063
|
}
|
|
45605
|
-
|
|
45606
|
-
const
|
|
46064
|
+
if (child.type !== "listItem") return void 0;
|
|
46065
|
+
const original = originals[index];
|
|
46066
|
+
const text = original ? regutter(retainSource(original, child, source, canonical, lineEnding, false, void 0, void 0, strays), gutters && [gutters[0], gutterAt(source, original.position.start.offset)]) : child.children?.some((node) => node.type === "list" || node.type === "blockquote") ? retainParts(void 0, before.flatMap((node) => node.type === "listItem" ? node.children ?? [] : []), child.children, source, canonical, child.position.start.offset, end, lineEnding, void 0, void 0, childGutters(before.find((node) => node.type === "listItem"), child, source, canonical)) : void 0;
|
|
45607
46067
|
return text !== void 0 && marker ? relabel(text, [0], marker) : text;
|
|
45608
46068
|
});
|
|
45609
46069
|
if (pieces.every((piece) => piece === void 0)) return void 0;
|
|
45610
|
-
let text = "", at = from;
|
|
46070
|
+
let text = "", at = from, lastNumber;
|
|
45611
46071
|
after.forEach((child, index) => {
|
|
45612
46072
|
const childStart = child.position.start.offset;
|
|
45613
46073
|
const childEnd = child.position.end.offset;
|
|
@@ -45615,15 +46075,18 @@ function retainParts(marker, before, after, source, canonical, from, to, lineEnd
|
|
|
45615
46075
|
let piece = pieces[index];
|
|
45616
46076
|
const own = piece && markerAt(piece, 0)?.marker;
|
|
45617
46077
|
if (child.type === "list" && [previous, following].some((neighbour) => neighbour?.ordered === child.ordered && neighbour?.marker === own)) piece = void 0;
|
|
45618
|
-
|
|
46078
|
+
const number = /^\d+/.exec(piece ?? "")?.[0];
|
|
46079
|
+
if (piece && number && marker && lastNumber !== void 0 && originals[index] && !ownLevel.has(originals[index]) && String(lastNumber + 1).length === number.length) piece = String(lastNumber + 1) + piece.slice(number.length);
|
|
46080
|
+
piece ??= canonicalSlice(marker, [child], canonical, childStart, childEnd, previous, following, gutters, false, inherited);
|
|
46081
|
+
lastNumber = child.type === "listItem" && /^\d/.test(piece) ? Number(/^\d+/.exec(piece)[0]) : void 0;
|
|
45619
46082
|
previous = child.type === "list" ? {
|
|
45620
46083
|
ordered: child.ordered,
|
|
45621
46084
|
marker: markerAt(piece, /^[ \t]*/.exec(piece)[0].length)?.marker ?? ""
|
|
45622
46085
|
} : void 0;
|
|
45623
|
-
text += canonical.slice(at, childStart) + piece;
|
|
46086
|
+
text += regutter(canonical.slice(at, childStart), gutters, true) + piece;
|
|
45624
46087
|
at = childEnd;
|
|
45625
46088
|
});
|
|
45626
|
-
return text + canonical.slice(at, to);
|
|
46089
|
+
return text + regutter(canonical.slice(at, to), gutters, open);
|
|
45627
46090
|
}
|
|
45628
46091
|
function decodedOffsets(raw, lines = false) {
|
|
45629
46092
|
const offsets = [0];
|
|
@@ -45631,7 +46094,7 @@ function decodedOffsets(raw, lines = false) {
|
|
|
45631
46094
|
for (let index = 0; index < raw.length;) {
|
|
45632
46095
|
const rest = raw.slice(index);
|
|
45633
46096
|
const line = /[ \t]/.test(raw[index - 1] ?? "") && /[ \t]/.test(raw[index]) ? void 0 : /^[ \t]*(?:\r\n?|\n)(?:[ \t]*>)*[ \t]*/.exec(rest)?.[0];
|
|
45634
|
-
|
|
46097
|
+
let token = line ?? /^\\[!"#$%&'()*+,\-./:;<=>?@[\]\\^_`{|}~]/.exec(rest)?.[0] ?? /^&(?:#[xX][\da-fA-F]+|#\d+|[A-Za-z][A-Za-z\d]+);/.exec(rest)?.[0];
|
|
45635
46098
|
let value = raw[index];
|
|
45636
46099
|
if (line) {
|
|
45637
46100
|
if (!lines) return void 0;
|
|
@@ -45640,7 +46103,8 @@ function decodedOffsets(raw, lines = false) {
|
|
|
45640
46103
|
else if (token) {
|
|
45641
46104
|
const element = document.createElement("textarea");
|
|
45642
46105
|
element.innerHTML = token;
|
|
45643
|
-
value =
|
|
46106
|
+
if (element.value === token) token = void 0;
|
|
46107
|
+
else value = element.value;
|
|
45644
46108
|
}
|
|
45645
46109
|
index += token?.length ?? 1;
|
|
45646
46110
|
decoded += value;
|
|
@@ -45757,7 +46221,10 @@ function retainRun(before, after, source, canonical, [from, to], [newFrom, newTo
|
|
|
45757
46221
|
}
|
|
45758
46222
|
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));
|
|
45759
46223
|
}
|
|
45760
|
-
function retainText(raw, before, after, inTable = false, written, beside = [false, false]) {
|
|
46224
|
+
function retainText(raw, before, after, inTable = false, written, beside = [false, false], readGutters) {
|
|
46225
|
+
let found;
|
|
46226
|
+
const gutters = () => found ??= readGutters?.();
|
|
46227
|
+
const guttered = (text) => text.includes("\n") ? regutter(text, gutters()) : text;
|
|
45761
46228
|
before = lf(before);
|
|
45762
46229
|
after = lf(after);
|
|
45763
46230
|
let prefix = 0;
|
|
@@ -45775,19 +46242,34 @@ function retainText(raw, before, after, inTable = false, written, beside = [fals
|
|
|
45775
46242
|
const marker = /^(?:\d+)?\\[#+.\->)]/.exec(opening)?.[0];
|
|
45776
46243
|
if (marker && prefix - lineStart <= decodedOffsets(marker).decoded.length) {
|
|
45777
46244
|
prefix = lineStart;
|
|
45778
|
-
return raw.slice(0, offsets[prefix]) + written.slice(canonical.offsets[prefix], canonical.offsets[after.length - suffix]) + raw.slice(offsets[before.length - suffix]);
|
|
46245
|
+
return raw.slice(0, offsets[prefix]) + guttered(written.slice(canonical.offsets[prefix], canonical.offsets[after.length - suffix])) + raw.slice(offsets[before.length - suffix]);
|
|
45779
46246
|
}
|
|
45780
46247
|
}
|
|
45781
46248
|
}
|
|
45782
46249
|
if (written !== void 0 && (beside[0] && prefix === 0 || beside[1] && suffix === 0)) {
|
|
45783
46250
|
const writtenOffsets = decodedOffsets(written);
|
|
45784
|
-
if (writtenOffsets && writtenOffsets.decoded === after) return raw.slice(0, offsets[prefix]) + written.slice(writtenOffsets.offsets[prefix], writtenOffsets.offsets[after.length - suffix]) + raw.slice(offsets[before.length - suffix]);
|
|
46251
|
+
if (writtenOffsets && writtenOffsets.decoded === after) return raw.slice(0, offsets[prefix]) + guttered(written.slice(writtenOffsets.offsets[prefix], writtenOffsets.offsets[after.length - suffix])) + raw.slice(offsets[before.length - suffix]);
|
|
45785
46252
|
}
|
|
45786
46253
|
const inserted = after.slice(prefix, after.length - suffix).split("").map((character, index) => {
|
|
45787
46254
|
const at = prefix + index;
|
|
45788
|
-
return (character === "%" || character === "=") && (after[at - 1] === character || after[at + 1] === character) || /[\\`*_[\]<>]/.test(character) || inTable && character === "|" ? `\\${character}` : character;
|
|
46255
|
+
return (character === "%" || character === "=") && (after[at - 1] === character || after[at + 1] === character) || /[\\`*_[\]<>]/.test(character) || inTable && character === "|" ? `\\${character}` : character === "\n" ? character + (gutters()?.[0] ?? "") : character;
|
|
45789
46256
|
}).join("");
|
|
45790
|
-
return raw.slice(0, offsets[prefix])
|
|
46257
|
+
return escapeReferences(raw.slice(0, offsets[prefix]), inserted, raw.slice(offsets[before.length - suffix]));
|
|
46258
|
+
}
|
|
46259
|
+
var characterReference = /&(?:#[xX][\da-fA-F]+|#\d+|[A-Za-z][A-Za-z\d]*);/g;
|
|
46260
|
+
function escapeReferences(head, inserted, tail) {
|
|
46261
|
+
const text = head + inserted + tail;
|
|
46262
|
+
const from = head.length;
|
|
46263
|
+
const to = from + inserted.length;
|
|
46264
|
+
let output = "", at = 0;
|
|
46265
|
+
for (const match of text.matchAll(characterReference)) {
|
|
46266
|
+
const start = match.index;
|
|
46267
|
+
const end = start + match[0].length;
|
|
46268
|
+
if (start >= to || end <= from || (/\\*$/.exec(text.slice(0, start))[0].length & 1) === 1) continue;
|
|
46269
|
+
output += text.slice(at, end - 1) + "\\";
|
|
46270
|
+
at = end - 1;
|
|
46271
|
+
}
|
|
46272
|
+
return output + text.slice(at);
|
|
45791
46273
|
}
|
|
45792
46274
|
function retainBoundaryText(raw, canonical, afterBreak = false) {
|
|
45793
46275
|
if (afterBreak) {
|
|
@@ -45984,6 +46466,7 @@ function markLiterals(raw, transformed, blocks = []) {
|
|
|
45984
46466
|
raw.children.forEach(mark);
|
|
45985
46467
|
}
|
|
45986
46468
|
function retainSource(before, after, source, canonical, lineEnding, inTable = false, width, beside = [false, false], joined = [], reorder, afterBreak = false) {
|
|
46469
|
+
after = authoredNesting(before, after);
|
|
45987
46470
|
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);
|
|
45988
46471
|
if (before.type === "list" && after.type === "list" && before.ordered && after.ordered && !numbered.has(before) && before.position?.start.offset != null) {
|
|
45989
46472
|
const own = {
|
|
@@ -46080,15 +46563,20 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
46080
46563
|
const to = first.position.end.offset - start;
|
|
46081
46564
|
return retained.startsWith(source.slice(start, before.children[1].position.start.offset)) ? retained.slice(0, from) + "<br />" + retained.slice(to) : retained;
|
|
46082
46565
|
}
|
|
46083
|
-
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);
|
|
46566
|
+
if (before.type === "text" && after.type === "text") return retainBoundaryText(withEnding(retainText(raw, before.value, after.value, inTable, canonical.slice(newStart, newEnd), beside, () => [gutterAt(source, start), gutterAt(canonical, newStart)]), lineEnding), canonical.slice(newStart, newEnd), afterBreak);
|
|
46084
46567
|
if (signature(before) === signature(after) && ownShape(before) === ownShape(after) && !holdsLiteral(after) && !reorderedWithin(before, reorder)) return raw;
|
|
46568
|
+
if (before.type !== after.type) {
|
|
46569
|
+
const lifted = liftedSource([before], after, source);
|
|
46570
|
+
if (lifted !== void 0) return lifted;
|
|
46571
|
+
}
|
|
46085
46572
|
const marker = sameList(before, after) ? authoredMarker(before, source) : void 0;
|
|
46086
46573
|
const located = (nodes) => nodes.every((node) => node.position?.start.offset != null);
|
|
46087
|
-
if (before.type === after.type &&
|
|
46574
|
+
if (before.type === after.type && sameShape(before, after) && before.children && after.children && before.children.length === after.children.length && located(before.children) && located(after.children)) {
|
|
46088
46575
|
let output = "", at = start;
|
|
46089
46576
|
let previous;
|
|
46090
46577
|
const same = (candidate, incoming) => signature(candidate) === signature(incoming) && ownShape(candidate) === ownShape(incoming);
|
|
46091
46578
|
const reorderable = before.type === "table" || before.type === "tableRow";
|
|
46579
|
+
const gutters = childGutters(before, after, source, canonical);
|
|
46092
46580
|
const moves = reorder?.get(parentKey(before));
|
|
46093
46581
|
const retained = new Set(reorderable ? before.children.flatMap((child, index) => same(child, after.children[index]) ? [index] : []) : []);
|
|
46094
46582
|
before.children.forEach((child, index) => {
|
|
@@ -46099,7 +46587,7 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
46099
46587
|
if (movedIndex >= 0) retained.add(movedIndex);
|
|
46100
46588
|
const childStart = child.position?.start.offset, childEnd = child.position?.end.offset;
|
|
46101
46589
|
if (childStart == null || childEnd == null) throw new PreservationError("A source token has no location");
|
|
46102
|
-
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"],
|
|
46590
|
+
let retainedSource = rewrittenAddress(before.type, before.children, movedIndex < 0 ? index : movedIndex, after.children, index, source, canonical) ? regutter(canonical.slice(incoming.position.start.offset, incoming.position.end.offset), gutters) : 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), gutters), 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"], joined, reorder, after.children[index - 1]?.type === "break");
|
|
46103
46591
|
if (before.type === "tableRow" && movedIndex >= 0 && movedIndex !== index) {
|
|
46104
46592
|
const originalFrom = original.children?.[0]?.position?.start.offset;
|
|
46105
46593
|
const originalTo = original.children?.at(-1)?.position?.end.offset;
|
|
@@ -46118,7 +46606,7 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
46118
46606
|
});
|
|
46119
46607
|
return output + source.slice(at, end);
|
|
46120
46608
|
}
|
|
46121
|
-
if (before.type === after.type &&
|
|
46609
|
+
if (before.type === after.type && sameShape(before, after) && before.children && after.children) {
|
|
46122
46610
|
let prefix = 0, suffix = 0;
|
|
46123
46611
|
while (prefix < before.children.length && prefix < after.children.length && signature(before.children[prefix]) === signature(after.children[prefix])) prefix++;
|
|
46124
46612
|
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++;
|
|
@@ -46143,13 +46631,15 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
46143
46631
|
const changes = after.children.slice(prefix, after.children.length - suffix);
|
|
46144
46632
|
const previous = authoredNeighbour(before.children[prefix - 1], after.children[prefix - 1], source);
|
|
46145
46633
|
const next = authoredNeighbour(before.children[before.children.length - suffix], after.children[after.children.length - suffix], source);
|
|
46146
|
-
|
|
46634
|
+
const gutters = childGutters(before, after, source, canonical, !prefix);
|
|
46635
|
+
const inherited = itemMarker(before, source);
|
|
46636
|
+
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, gutters, suffix > 0, inherited)) ?? canonicalSlice(marker, changes, canonical, newFrom, newTo, previous, next, gutters, suffix > 0, inherited), 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);
|
|
46147
46637
|
}
|
|
46148
46638
|
}
|
|
46149
46639
|
const lastAfter = after.children?.at(-1)?.position?.end.offset;
|
|
46150
46640
|
const lastBefore = before.children?.at(-1)?.position?.end.offset;
|
|
46151
46641
|
const trailing = marker != null && lastAfter != null && lastBefore != null && loose(before, source) === loose(after, canonical);
|
|
46152
|
-
return withEnding(canonicalSlice(marker, after.children ?? [], canonical, newStart, trailing ? lastAfter : newEnd), lineEnding) + (trailing ? source.slice(lastBefore, end) : "");
|
|
46642
|
+
return withEnding(canonicalSlice(marker, after.children ?? [], canonical, newStart, trailing ? lastAfter : newEnd, void 0, void 0, childGutters(before, after, source, canonical, true), false, itemMarker(before, source)), lineEnding) + (trailing ? source.slice(lastBefore, end) : "");
|
|
46153
46643
|
}
|
|
46154
46644
|
function loose(list, text) {
|
|
46155
46645
|
const blank = (from, to) => from != null && to != null && /\n[ \t>]*\r?\n/.test(text.slice(from, to));
|
|
@@ -46246,6 +46736,13 @@ function semanticSignature(doc) {
|
|
|
46246
46736
|
attrs
|
|
46247
46737
|
};
|
|
46248
46738
|
}
|
|
46739
|
+
if (value.type === "comment_block" && value.attrs) {
|
|
46740
|
+
const { block: _block, ...attrs } = value.attrs;
|
|
46741
|
+
value = {
|
|
46742
|
+
...value,
|
|
46743
|
+
attrs
|
|
46744
|
+
};
|
|
46745
|
+
}
|
|
46249
46746
|
const content = value.content;
|
|
46250
46747
|
if (!content) return value;
|
|
46251
46748
|
const tokens = [];
|
|
@@ -46288,6 +46785,7 @@ function semanticSignature(doc) {
|
|
|
46288
46785
|
"authoredFence",
|
|
46289
46786
|
"form",
|
|
46290
46787
|
"inkkitFileRaw",
|
|
46788
|
+
"inkkitFileSource",
|
|
46291
46789
|
"inkkitFileWidth",
|
|
46292
46790
|
"inkkitFileInTable"
|
|
46293
46791
|
].includes(key) ? void 0 : value));
|
|
@@ -46499,7 +46997,7 @@ var Preservation = class Preservation {
|
|
|
46499
46997
|
try {
|
|
46500
46998
|
const parse = (text) => parseDoc(ctx, text);
|
|
46501
46999
|
this.baseline = parse(source);
|
|
46502
|
-
this.lineEnding = source.includes("\r\n") && !source.replaceAll("\r\n", "").includes("\n") ? "\r\n" : "\n";
|
|
47000
|
+
this.lineEnding = !source.includes("\n") ? source.includes("\r") ? "\r" : "\n" : source.includes("\r\n") && !source.replaceAll("\r\n", "").includes("\n") ? "\r\n" : "\n";
|
|
46503
47001
|
const processor = ctx.get(remarkCtx);
|
|
46504
47002
|
const offset = source.startsWith("") ? 1 : 0;
|
|
46505
47003
|
const body = source.slice(offset);
|
|
@@ -46594,6 +47092,9 @@ var Preservation = class Preservation {
|
|
|
46594
47092
|
const indent = source.slice(source.lastIndexOf("\n", part.from - 1) + 1, part.from);
|
|
46595
47093
|
return (/^[ \t]*$/.test(indent) ? indent : "") + part.text;
|
|
46596
47094
|
}
|
|
47095
|
+
retainLifted(positions, index, after) {
|
|
47096
|
+
return liftedSource(this.around(positions, index).map((block) => block.ast), after, this.source.slice(this.source.startsWith("") ? 1 : 0));
|
|
47097
|
+
}
|
|
46597
47098
|
localEdits(doc) {
|
|
46598
47099
|
if (this.baseline.childCount !== this.blocks.length || doc.childCount !== this.blocks.length || !doc.sameMarkup(this.baseline)) return void 0;
|
|
46599
47100
|
let output = "", previous = 0;
|
|
@@ -47008,7 +47509,7 @@ var Preservation = class Preservation {
|
|
|
47008
47509
|
const kind = block && block.form === text && !carried.within.has(index) ? position == null ? "moved" : "unchanged" : block && tree && position != null ? "edited" : "canonical";
|
|
47009
47510
|
kept.push(kind);
|
|
47010
47511
|
const node = tree ? positionalNode(tree.raw, transformed(index)) : void 0;
|
|
47011
|
-
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)));
|
|
47512
|
+
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) ?? this.retainLifted(positions, index, node))) ?? restoreCodeEndings(this.ctx, doc.type.create(null, [doc.child(index)]), withEnding(text, this.lineEnding)));
|
|
47012
47513
|
}
|
|
47013
47514
|
return {
|
|
47014
47515
|
gaps,
|
|
@@ -47544,23 +48045,6 @@ function completedAngle(tr, chars, from, to) {
|
|
|
47544
48045
|
form: "angle"
|
|
47545
48046
|
})).removeStoredMark(tr.doc.type.schema.marks.link);
|
|
47546
48047
|
}
|
|
47547
|
-
function closeAngleEnds(tr, transactions) {
|
|
47548
|
-
const steps = transactions.flatMap((transaction) => transaction.steps.map((step, index) => ({
|
|
47549
|
-
doc: transaction.docs[index],
|
|
47550
|
-
map: step.getMap()
|
|
47551
|
-
})));
|
|
47552
|
-
steps.forEach(({ doc, map }, index) => {
|
|
47553
|
-
const remaining = new Mapping(steps.slice(index + 1).map(({ map }) => map));
|
|
47554
|
-
map.forEach((from, to, start, end) => {
|
|
47555
|
-
if (from !== to || start === end) return;
|
|
47556
|
-
const at = doc.resolve(from);
|
|
47557
|
-
const before = at.nodeBefore?.marks.find((mark) => mark.attrs.form === "angle");
|
|
47558
|
-
const after = at.nodeAfter?.marks.find((mark) => mark.attrs.form === "angle");
|
|
47559
|
-
if (before && after && before.eq(after)) return;
|
|
47560
|
-
for (const mark of [before, after]) if (mark) tr.removeMark(remaining.map(start, 1), remaining.map(end, -1), mark);
|
|
47561
|
-
});
|
|
47562
|
-
});
|
|
47563
|
-
}
|
|
47564
48048
|
function codeAngles(tr, edited) {
|
|
47565
48049
|
const spans = [];
|
|
47566
48050
|
for (const block of edited) tr.doc.nodesBetween(block.pos, block.pos + block.block.nodeSize, (node, pos) => {
|
|
@@ -47769,10 +48253,7 @@ var autolinkLiterals = $prose((ctx) => new Plugin({
|
|
|
47769
48253
|
if (!transactions.some((tr) => tr.docChanged)) return null;
|
|
47770
48254
|
const base = newState.tr;
|
|
47771
48255
|
const written = transactions.every(isWrittenEdit);
|
|
47772
|
-
if (written)
|
|
47773
|
-
closeAngleEnds(base, transactions);
|
|
47774
|
-
codeAngles(base, editedBlocks(oldState.doc, base.doc));
|
|
47775
|
-
}
|
|
48256
|
+
if (written) codeAngles(base, editedBlocks(oldState.doc, base.doc));
|
|
47776
48257
|
let edited = editedBlocks(oldState.doc, base.doc);
|
|
47777
48258
|
if (written && edited.length === 1) {
|
|
47778
48259
|
const { pos, block, from, to } = edited[0];
|
|
@@ -48141,7 +48622,8 @@ function remarkCallouts() {
|
|
|
48141
48622
|
const visit = (node) => {
|
|
48142
48623
|
if (node.type === "blockquote") {
|
|
48143
48624
|
const start = node.position?.start.offset, end = node.position?.end.offset;
|
|
48144
|
-
const
|
|
48625
|
+
const gutter = start == null ? "" : gutterAt(source, start);
|
|
48626
|
+
const raw = start == null || end == null ? "" : source.slice(start, end).replace(/(\r?\n)([^\r\n]*)/g, (line, eol, text) => gutter && text.startsWith(gutter) ? eol + text.slice(gutter.length) : line);
|
|
48145
48627
|
const header = /^>[ \t]*([\s\S]*?)(?:\r?\n|$)/.exec(raw)?.[1] ?? "";
|
|
48146
48628
|
if (header.startsWith("[!")) {
|
|
48147
48629
|
const match = /^(\[!([A-Za-z]+)\])([+-]?)(?:[ \t]+([^\r\n]*))?$/.exec(header);
|
|
@@ -48313,7 +48795,7 @@ var calloutView = $prose((ctx) => new Plugin({
|
|
|
48313
48795
|
const render = () => {
|
|
48314
48796
|
title.textContent = node.attrs.title || String(node.attrs.kind).toLowerCase().replace(/^./, (letter) => letter.toUpperCase());
|
|
48315
48797
|
dom.setAttribute("data-inkkit-folded", String(folded));
|
|
48316
|
-
view.dom.dispatchEvent(new Event(
|
|
48798
|
+
view.dom.dispatchEvent(new Event(mediaPolicyEvent));
|
|
48317
48799
|
button.hidden = !node.attrs.fold;
|
|
48318
48800
|
button.setAttribute("aria-expanded", String(!folded));
|
|
48319
48801
|
button.setAttribute("aria-label", `${folded ? editorLabels(ctx).expandCallout : editorLabels(ctx).collapseCallout} ${title.textContent}`);
|
|
@@ -50080,12 +50562,50 @@ function writesBare(node, index, ancestors) {
|
|
|
50080
50562
|
return side(-1) && side(1);
|
|
50081
50563
|
}
|
|
50082
50564
|
var bareLinks = /* @__PURE__ */ new WeakSet();
|
|
50565
|
+
function linkFormatting(node) {
|
|
50566
|
+
const plain = node.type === "link" && !formOf(node) || node.type === "linkReference" && node.referenceType === "full";
|
|
50567
|
+
const [inner] = plain ? node.children : [];
|
|
50568
|
+
return plain && node.children.length === 1 && inner && wrappers.has(inner.type) ? inner : void 0;
|
|
50569
|
+
}
|
|
50570
|
+
function shareFormatting(children) {
|
|
50571
|
+
const same = (left, right) => {
|
|
50572
|
+
const { children: _left, position: _a, ...leftRest } = left;
|
|
50573
|
+
const { children: _right, position: _b, ...rightRest } = right;
|
|
50574
|
+
return JSON.stringify(leftRest) === JSON.stringify(rightRest);
|
|
50575
|
+
};
|
|
50576
|
+
for (let index = 0; index < children.length; index++) {
|
|
50577
|
+
const child = children[index];
|
|
50578
|
+
const formatting = linkFormatting(child);
|
|
50579
|
+
if (!formatting) continue;
|
|
50580
|
+
const link = {
|
|
50581
|
+
...child,
|
|
50582
|
+
children: formatting.children
|
|
50583
|
+
};
|
|
50584
|
+
const previous = children[index - 1];
|
|
50585
|
+
const next = children[index + 1];
|
|
50586
|
+
const before = previous && same(previous, formatting);
|
|
50587
|
+
const after = next && same(next, formatting);
|
|
50588
|
+
if (!before && !after) continue;
|
|
50589
|
+
const merged = {
|
|
50590
|
+
...formatting,
|
|
50591
|
+
children: [
|
|
50592
|
+
...before ? previous.children : [],
|
|
50593
|
+
link,
|
|
50594
|
+
...after ? next.children : []
|
|
50595
|
+
]
|
|
50596
|
+
};
|
|
50597
|
+
const from = before ? index - 1 : index;
|
|
50598
|
+
children.splice(from, 1 + Number(before) + Number(after), merged);
|
|
50599
|
+
index = from - 1;
|
|
50600
|
+
}
|
|
50601
|
+
}
|
|
50083
50602
|
var root = (node, parent, state, info) => {
|
|
50084
50603
|
bareLinks = /* @__PURE__ */ new WeakSet();
|
|
50085
50604
|
const empty = (child) => child.type === "text" && child.value === "" || wrappers.has(child.type) && "children" in child && child.children.every(empty);
|
|
50086
50605
|
const visit = (current, ancestors) => {
|
|
50087
50606
|
if (current.children.some((child) => empty(child))) current.children = current.children.filter((child) => !empty(child));
|
|
50088
50607
|
const children = current.children;
|
|
50608
|
+
shareFormatting(children);
|
|
50089
50609
|
children.forEach((child, index) => {
|
|
50090
50610
|
if (child.type === "link" && formOf(child)) {
|
|
50091
50611
|
const outside = formattedOutside(child);
|
|
@@ -50306,6 +50826,16 @@ var breaksWithoutMarks = $prose((ctx) => new Plugin({
|
|
|
50306
50826
|
}
|
|
50307
50827
|
}));
|
|
50308
50828
|
var remarkLinkFormsPlugin = $remark("inkkitLinkForms", () => remarkLinkForms);
|
|
50829
|
+
var remarkFileSourcesPlugin = $remark("inkkitFileSources", () => remarkFileSources);
|
|
50830
|
+
var imageWriter = (ctx) => async () => {
|
|
50831
|
+
await ctx.wait(SerializerReady);
|
|
50832
|
+
const schema = ctx.get(schemaCtx);
|
|
50833
|
+
setImageWriter(schema, (node) => {
|
|
50834
|
+
node = node.mark([]);
|
|
50835
|
+
const block = node.isBlock ? node : schema.nodes.paragraph.create(null, node);
|
|
50836
|
+
return ctx.get(serializerCtx)(schema.topNodeType.create(null, block)).replace(/\n+$/, "");
|
|
50837
|
+
});
|
|
50838
|
+
};
|
|
50309
50839
|
var preserveSpacerParagraphs = paragraphSchema.extendSchema((base) => (ctx) => {
|
|
50310
50840
|
const schema = base(ctx);
|
|
50311
50841
|
return {
|
|
@@ -50436,7 +50966,16 @@ var normalizedImages = imageSchema.extendSchema((base) => (ctx) => {
|
|
|
50436
50966
|
...schema.toMarkdown,
|
|
50437
50967
|
runner(state, node) {
|
|
50438
50968
|
const raw = namedFileMarkdown(node, Boolean(node.attrs.inkkitFileInTable));
|
|
50439
|
-
if (raw == null)
|
|
50969
|
+
if (raw == null) {
|
|
50970
|
+
state.addNode("image", void 0, void 0, {
|
|
50971
|
+
url: node.attrs.src,
|
|
50972
|
+
alt: node.attrs.alt,
|
|
50973
|
+
title: node.attrs.title || null,
|
|
50974
|
+
inkkitFileSource: authoredFileSource(node),
|
|
50975
|
+
inkkitFileInTable: node.attrs.inkkitFileInTable
|
|
50976
|
+
});
|
|
50977
|
+
return;
|
|
50978
|
+
}
|
|
50440
50979
|
state.addNode("image", void 0, void 0, {
|
|
50441
50980
|
url: node.attrs.src,
|
|
50442
50981
|
alt: node.attrs.alt,
|
|
@@ -50444,7 +50983,7 @@ var normalizedImages = imageSchema.extendSchema((base) => (ctx) => {
|
|
|
50444
50983
|
inkkitFileRaw: raw,
|
|
50445
50984
|
inkkitFileTarget: node.attrs.inkkitFileTarget,
|
|
50446
50985
|
inkkitFileFragment: node.attrs.inkkitFileFragment,
|
|
50447
|
-
inkkitFileWidth:
|
|
50986
|
+
inkkitFileWidth: fileFields(node).width ?? null,
|
|
50448
50987
|
inkkitFileInTable: node.attrs.inkkitFileInTable
|
|
50449
50988
|
});
|
|
50450
50989
|
}
|
|
@@ -50557,6 +51096,7 @@ function createDialect(images, wikiLinks = false, files = false) {
|
|
|
50557
51096
|
remarkCodeFences,
|
|
50558
51097
|
remarkReferencesPlugin,
|
|
50559
51098
|
remarkLinkFormsPlugin,
|
|
51099
|
+
remarkFileSourcesPlugin,
|
|
50560
51100
|
remarkCalloutsPlugin,
|
|
50561
51101
|
remarkCommentsPlugin,
|
|
50562
51102
|
wikiLinks || files ? linkedSyntax(wikiLinks, files) : [],
|
|
@@ -50576,6 +51116,7 @@ function createDialect(images, wikiLinks = false, files = false) {
|
|
|
50576
51116
|
wikiLinkComposition,
|
|
50577
51117
|
wikiLinkInputRule
|
|
50578
51118
|
] : [],
|
|
51119
|
+
wikiLinks || files ? referenceTableContext : [],
|
|
50579
51120
|
callouts,
|
|
50580
51121
|
comments,
|
|
50581
51122
|
hiddenCommentEditing,
|
|
@@ -50603,7 +51144,8 @@ function createDialect(images, wikiLinks = false, files = false) {
|
|
|
50603
51144
|
remarkDialectPlugin,
|
|
50604
51145
|
tables,
|
|
50605
51146
|
literalBlock,
|
|
50606
|
-
checkedParser
|
|
51147
|
+
checkedParser,
|
|
51148
|
+
imageWriter
|
|
50607
51149
|
].flat();
|
|
50608
51150
|
}
|
|
50609
51151
|
createDialect(false);
|
|
@@ -51315,7 +51857,7 @@ var ImageView = class {
|
|
|
51315
51857
|
view;
|
|
51316
51858
|
getPos;
|
|
51317
51859
|
adapter;
|
|
51318
|
-
|
|
51860
|
+
host;
|
|
51319
51861
|
canMutate;
|
|
51320
51862
|
dom;
|
|
51321
51863
|
/** The card or picture, which a standalone image's block row holds. */
|
|
@@ -51327,22 +51869,30 @@ var ImageView = class {
|
|
|
51327
51869
|
stopResize;
|
|
51328
51870
|
resolution;
|
|
51329
51871
|
previewFailed = false;
|
|
51330
|
-
|
|
51872
|
+
/** Present when the host sets `files`, which then shows every image. */
|
|
51873
|
+
runtime;
|
|
51874
|
+
constructor(node, view, getPos, adapter, host, files, canMutate = () => true) {
|
|
51331
51875
|
this.node = node;
|
|
51332
51876
|
this.view = view;
|
|
51333
51877
|
this.getPos = getPos;
|
|
51334
51878
|
this.adapter = adapter;
|
|
51335
|
-
this.
|
|
51879
|
+
this.host = host;
|
|
51336
51880
|
this.canMutate = canMutate;
|
|
51881
|
+
const runtime = files && host && {
|
|
51882
|
+
...host,
|
|
51883
|
+
adapter: files
|
|
51884
|
+
};
|
|
51885
|
+
this.runtime = runtime;
|
|
51337
51886
|
this.element = document.createElement("span");
|
|
51338
51887
|
this.element.className = "inkkit-image";
|
|
51888
|
+
this.element.addEventListener("contextmenu", this.contextMenu);
|
|
51339
51889
|
if (node.isBlock) {
|
|
51340
51890
|
this.dom = document.createElement("div");
|
|
51341
51891
|
this.dom.className = "inkkit-image-block";
|
|
51342
51892
|
this.dom.append(this.element);
|
|
51343
51893
|
} else this.dom = this.element;
|
|
51344
51894
|
this.view.dom.addEventListener("inkkit-cancel-resize", this.cancelResize);
|
|
51345
|
-
this.view.dom.addEventListener(
|
|
51895
|
+
this.view.dom.addEventListener(mediaPolicyEvent, this.mediaPolicy);
|
|
51346
51896
|
if (runtime) {
|
|
51347
51897
|
this.resolution = new FileResolution({
|
|
51348
51898
|
...runtime,
|
|
@@ -51379,8 +51929,15 @@ var ImageView = class {
|
|
|
51379
51929
|
ignoreMutation() {
|
|
51380
51930
|
return true;
|
|
51381
51931
|
}
|
|
51382
|
-
mediaPolicy = () => {
|
|
51932
|
+
mediaPolicy = (event) => {
|
|
51383
51933
|
if (!this.runtime) return;
|
|
51934
|
+
const refresh = refreshOf(event);
|
|
51935
|
+
if (refresh) {
|
|
51936
|
+
if (!this.active() || !refreshes(refresh, this.reference().target)) return;
|
|
51937
|
+
if (this.previewFailed) this.resolution?.retry();
|
|
51938
|
+
else this.resolution?.refresh();
|
|
51939
|
+
return;
|
|
51940
|
+
}
|
|
51384
51941
|
if (!this.active()) {
|
|
51385
51942
|
this.stopResize?.();
|
|
51386
51943
|
this.stopResize = void 0;
|
|
@@ -51408,7 +51965,7 @@ var ImageView = class {
|
|
|
51408
51965
|
}
|
|
51409
51966
|
destroy() {
|
|
51410
51967
|
this.view.dom.removeEventListener("inkkit-cancel-resize", this.cancelResize);
|
|
51411
|
-
this.view.dom.removeEventListener(
|
|
51968
|
+
this.view.dom.removeEventListener(mediaPolicyEvent, this.mediaPolicy);
|
|
51412
51969
|
this.stopResize?.();
|
|
51413
51970
|
this.stopResize = void 0;
|
|
51414
51971
|
this.resolution?.destroy();
|
|
@@ -51437,6 +51994,37 @@ var ImageView = class {
|
|
|
51437
51994
|
report(error) {
|
|
51438
51995
|
this.runtime?.error?.(coded(error, "file-unavailable"));
|
|
51439
51996
|
}
|
|
51997
|
+
/** Hands the request to the host's hook, which replaces the web view's own menu. A file card
|
|
51998
|
+
* uses `FileAdapter.contextMenu`; any other image selects itself and uses
|
|
51999
|
+
* `ImageAdapter.contextMenu`. */
|
|
52000
|
+
contextMenu = (event) => {
|
|
52001
|
+
const { host, runtime, adapter } = this;
|
|
52002
|
+
if (!host?.active() || !(runtime ? runtime.adapter.contextMenu : adapter?.contextMenu)) return;
|
|
52003
|
+
const captured = host.capture();
|
|
52004
|
+
if (!captured.isCurrent()) return;
|
|
52005
|
+
event.preventDefault();
|
|
52006
|
+
const point = {
|
|
52007
|
+
clientX: event.clientX,
|
|
52008
|
+
clientY: event.clientY
|
|
52009
|
+
};
|
|
52010
|
+
try {
|
|
52011
|
+
if (runtime) runtime.adapter.contextMenu?.(this.reference(), point, captured.context);
|
|
52012
|
+
else {
|
|
52013
|
+
this.select();
|
|
52014
|
+
adapter?.contextMenu?.(String(this.node.attrs.src ?? ""), point, captured.context);
|
|
52015
|
+
}
|
|
52016
|
+
} catch (error) {
|
|
52017
|
+
if (runtime) this.report(error);
|
|
52018
|
+
else host.error?.(coded(error, "image-unavailable"));
|
|
52019
|
+
}
|
|
52020
|
+
};
|
|
52021
|
+
select() {
|
|
52022
|
+
const pos = this.getPos();
|
|
52023
|
+
if (pos == null || this.view.composing) return;
|
|
52024
|
+
const { state } = this.view;
|
|
52025
|
+
const selection = NodeSelection.create(state.doc, pos);
|
|
52026
|
+
if (!state.selection.eq(selection)) this.view.dispatch(state.tr.setSelection(selection));
|
|
52027
|
+
}
|
|
51440
52028
|
card(label, status, retry = false) {
|
|
51441
52029
|
const footer = document.createElement("span");
|
|
51442
52030
|
footer.className = "inkkit-file-footer";
|
|
@@ -51485,20 +52073,6 @@ var ImageView = class {
|
|
|
51485
52073
|
this.image = void 0;
|
|
51486
52074
|
if (this.runtime) {
|
|
51487
52075
|
this.element.classList.add("inkkit-file");
|
|
51488
|
-
this.element.oncontextmenu = (event) => {
|
|
51489
|
-
if (!this.runtime?.adapter.contextMenu || !this.active()) return;
|
|
51490
|
-
const captured = this.runtime.capture();
|
|
51491
|
-
if (!captured.isCurrent()) return;
|
|
51492
|
-
event.preventDefault();
|
|
51493
|
-
try {
|
|
51494
|
-
this.runtime.adapter.contextMenu(this.reference(), {
|
|
51495
|
-
clientX: event.clientX,
|
|
51496
|
-
clientY: event.clientY
|
|
51497
|
-
}, captured.context);
|
|
51498
|
-
} catch (error) {
|
|
51499
|
-
this.report(error);
|
|
51500
|
-
}
|
|
51501
|
-
};
|
|
51502
52076
|
const state = this.resolution.state;
|
|
51503
52077
|
const label = state.status === "resolved" ? state.presentation.label || alt || reference.reference : alt || reference.reference;
|
|
51504
52078
|
this.element.setAttribute("role", "group");
|
|
@@ -51647,8 +52221,8 @@ function openArrow() {
|
|
|
51647
52221
|
icon.append(path);
|
|
51648
52222
|
return icon;
|
|
51649
52223
|
}
|
|
51650
|
-
function imageView(adapter,
|
|
51651
|
-
const view = (schema) => $view(schema.node, () => (node, view, getPos) => new ImageView(node, view, getPos, adapter,
|
|
52224
|
+
function imageView(adapter, host, files, canMutate = () => true) {
|
|
52225
|
+
const view = (schema) => $view(schema.node, () => (node, view, getPos) => new ImageView(node, view, getPos, adapter, host, files, canMutate));
|
|
51652
52226
|
return [view(imageSchema), view(imageBlockSchema)];
|
|
51653
52227
|
}
|
|
51654
52228
|
//#endregion
|
|
@@ -51660,26 +52234,29 @@ function wikiLinkView(adapter, runtime) {
|
|
|
51660
52234
|
dom.className = "inkkit-wiki-link";
|
|
51661
52235
|
dom.setAttribute("role", "link");
|
|
51662
52236
|
dom.tabIndex = 0;
|
|
51663
|
-
const reference = () => (
|
|
51664
|
-
target: String(current.attrs.target),
|
|
51665
|
-
...current.attrs.fragment ? { fragment: String(current.attrs.fragment) } : {},
|
|
51666
|
-
label: String(current.attrs.label)
|
|
51667
|
-
});
|
|
52237
|
+
const reference = () => wikiReference(current);
|
|
51668
52238
|
const report = (error) => runtime.error?.(coded(error, "file-unavailable"));
|
|
51669
52239
|
const render = () => {
|
|
51670
|
-
|
|
51671
|
-
dom.
|
|
51672
|
-
|
|
51673
|
-
if (
|
|
51674
|
-
|
|
51675
|
-
|
|
51676
|
-
|
|
51677
|
-
|
|
51678
|
-
|
|
51679
|
-
|
|
52240
|
+
const { label } = reference();
|
|
52241
|
+
if (dom.textContent !== label) dom.textContent = label;
|
|
52242
|
+
let missing = false;
|
|
52243
|
+
if (runtime.active()) {
|
|
52244
|
+
const captured = runtime.capture();
|
|
52245
|
+
try {
|
|
52246
|
+
const result = adapter.resolve?.(reference(), captured.context);
|
|
52247
|
+
missing = captured.isCurrent() && Boolean(result?.missing);
|
|
52248
|
+
} catch (error) {
|
|
52249
|
+
report(error);
|
|
51680
52250
|
}
|
|
51681
|
-
}
|
|
51682
|
-
|
|
52251
|
+
}
|
|
52252
|
+
if (missing) {
|
|
52253
|
+
dom.dataset.missing = "true";
|
|
52254
|
+
dom.title = runtime.labels.wikiMissing;
|
|
52255
|
+
dom.setAttribute("aria-description", runtime.labels.wikiMissing);
|
|
52256
|
+
} else {
|
|
52257
|
+
dom.removeAttribute("data-missing");
|
|
52258
|
+
dom.removeAttribute("title");
|
|
52259
|
+
dom.removeAttribute("aria-description");
|
|
51683
52260
|
}
|
|
51684
52261
|
};
|
|
51685
52262
|
const open = (event) => {
|
|
@@ -51698,7 +52275,11 @@ function wikiLinkView(adapter, runtime) {
|
|
|
51698
52275
|
dom.addEventListener("keydown", (event) => {
|
|
51699
52276
|
if (event.key === "Enter" || event.key === " ") open(event);
|
|
51700
52277
|
});
|
|
51701
|
-
|
|
52278
|
+
const policy = (event) => {
|
|
52279
|
+
const refresh = refreshOf(event);
|
|
52280
|
+
if (!refresh || refreshes(refresh, String(current.attrs.target))) render();
|
|
52281
|
+
};
|
|
52282
|
+
view.dom.addEventListener(mediaPolicyEvent, policy);
|
|
51702
52283
|
render();
|
|
51703
52284
|
return {
|
|
51704
52285
|
dom,
|
|
@@ -51713,7 +52294,7 @@ function wikiLinkView(adapter, runtime) {
|
|
|
51713
52294
|
},
|
|
51714
52295
|
ignoreMutation: () => true,
|
|
51715
52296
|
destroy() {
|
|
51716
|
-
view.dom.removeEventListener(
|
|
52297
|
+
view.dom.removeEventListener(mediaPolicyEvent, policy);
|
|
51717
52298
|
}
|
|
51718
52299
|
};
|
|
51719
52300
|
});
|
|
@@ -52784,7 +53365,7 @@ function readableProjection(doc) {
|
|
|
52784
53365
|
}
|
|
52785
53366
|
if (name === "image_block") {
|
|
52786
53367
|
block(position);
|
|
52787
|
-
append(
|
|
53368
|
+
append(fileFields(node).label || "Image", position, position + node.nodeSize, "embed");
|
|
52788
53369
|
return false;
|
|
52789
53370
|
}
|
|
52790
53371
|
if (node.isTextblock) {
|
|
@@ -52801,7 +53382,7 @@ function readableProjection(doc) {
|
|
|
52801
53382
|
return false;
|
|
52802
53383
|
}
|
|
52803
53384
|
if (name === "image" || name === "footnote_reference" || name === "inkkit_wiki_link") {
|
|
52804
|
-
append(name === "image" ?
|
|
53385
|
+
append(name === "image" ? fileFields(node).label || "Image" : name === "inkkit_wiki_link" ? String(node.attrs.label || node.attrs.target || "Link") : `[${node.attrs.label}]`, position, position + node.nodeSize, "embed");
|
|
52805
53386
|
return false;
|
|
52806
53387
|
}
|
|
52807
53388
|
return true;
|
|
@@ -54053,6 +54634,96 @@ function htmlGrid(schema, html) {
|
|
|
54053
54634
|
};
|
|
54054
54635
|
}
|
|
54055
54636
|
//#endregion
|
|
54637
|
+
//#region src/image-identity.ts
|
|
54638
|
+
var pngSignature = [
|
|
54639
|
+
137,
|
|
54640
|
+
80,
|
|
54641
|
+
78,
|
|
54642
|
+
71,
|
|
54643
|
+
13,
|
|
54644
|
+
10,
|
|
54645
|
+
26,
|
|
54646
|
+
10
|
|
54647
|
+
];
|
|
54648
|
+
function format(bytes) {
|
|
54649
|
+
if (bytes.length >= 8 && pngSignature.every((value, index) => bytes[index] === value)) return "png";
|
|
54650
|
+
if (bytes.length >= 8 && (bytes[0] === 73 && bytes[1] === 73 && bytes[2] === 42 && bytes[3] === 0 || bytes[0] === 77 && bytes[1] === 77 && bytes[2] === 0 && bytes[3] === 42)) return "tiff";
|
|
54651
|
+
}
|
|
54652
|
+
/** The pixel size in the header of a PNG or the first image of a TIFF. Nothing is decoded, so a
|
|
54653
|
+
* truncated or unusual file gives `undefined` and is never treated as a match. */
|
|
54654
|
+
function size(bytes, kind) {
|
|
54655
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
54656
|
+
if (kind === "png") {
|
|
54657
|
+
if (bytes.length < 24 || view.getUint32(12) !== 1229472850) return void 0;
|
|
54658
|
+
return {
|
|
54659
|
+
width: view.getUint32(16),
|
|
54660
|
+
height: view.getUint32(20)
|
|
54661
|
+
};
|
|
54662
|
+
}
|
|
54663
|
+
const little = bytes[0] === 73;
|
|
54664
|
+
const directory = view.getUint32(4, little);
|
|
54665
|
+
if (directory + 2 > bytes.length) return void 0;
|
|
54666
|
+
const entries = view.getUint16(directory, little);
|
|
54667
|
+
let width;
|
|
54668
|
+
let height;
|
|
54669
|
+
for (let index = 0; index < entries; index++) {
|
|
54670
|
+
const entry = directory + 2 + index * 12;
|
|
54671
|
+
if (entry + 12 > bytes.length) return void 0;
|
|
54672
|
+
const tag = view.getUint16(entry, little);
|
|
54673
|
+
if (tag !== 256 && tag !== 257) continue;
|
|
54674
|
+
const type = view.getUint16(entry + 2, little);
|
|
54675
|
+
const value = type === 3 ? view.getUint16(entry + 8, little) : type === 4 ? view.getUint32(entry + 8, little) : void 0;
|
|
54676
|
+
if (tag === 256) width = value;
|
|
54677
|
+
else height = value;
|
|
54678
|
+
}
|
|
54679
|
+
return width && height ? {
|
|
54680
|
+
width,
|
|
54681
|
+
height
|
|
54682
|
+
} : void 0;
|
|
54683
|
+
}
|
|
54684
|
+
function identical(a, b) {
|
|
54685
|
+
if (a.length !== b.length) return false;
|
|
54686
|
+
for (let index = 0; index < a.length; index++) if (a[index] !== b[index]) return false;
|
|
54687
|
+
return true;
|
|
54688
|
+
}
|
|
54689
|
+
function stem(filename) {
|
|
54690
|
+
const name = (filename ?? "").split(/[\\/]/).pop() ?? "";
|
|
54691
|
+
const dot = name.lastIndexOf(".");
|
|
54692
|
+
return (dot > 0 ? name.slice(0, dot) : name).normalize("NFC").toLowerCase();
|
|
54693
|
+
}
|
|
54694
|
+
/** Whether two captured images are one picture in two representations. */
|
|
54695
|
+
function sameImage(a, b) {
|
|
54696
|
+
if ((a.source ?? "") !== (b.source ?? "")) return false;
|
|
54697
|
+
if (identical(a.bytes, b.bytes)) return true;
|
|
54698
|
+
const kindA = format(a.bytes);
|
|
54699
|
+
const kindB = format(b.bytes);
|
|
54700
|
+
if (!kindA || !kindB || kindA === kindB) return false;
|
|
54701
|
+
const nameA = stem(a.filename);
|
|
54702
|
+
const nameB = stem(b.filename);
|
|
54703
|
+
if (nameA && nameB && nameA !== nameB) return false;
|
|
54704
|
+
const sizeA = size(a.bytes, kindA);
|
|
54705
|
+
const sizeB = size(b.bytes, kindB);
|
|
54706
|
+
return !!sizeA && !!sizeB && sizeA.width === sizeB.width && sizeA.height === sizeB.height;
|
|
54707
|
+
}
|
|
54708
|
+
/** Keeps one image for each picture in a single paste or drop. A clipboard can hold a picture
|
|
54709
|
+
* more than once, such as a screenshot as PNG and as TIFF, and each copy would be stored and
|
|
54710
|
+
* inserted separately.
|
|
54711
|
+
*
|
|
54712
|
+
* Two images are one picture when their bytes are identical, or when one is a PNG and the other a
|
|
54713
|
+
* TIFF with the same pixel size and compatible names (the same name without its extension, or a
|
|
54714
|
+
* name missing). Anything else is a different image, including a copy that was resized, re-encoded
|
|
54715
|
+
* as JPEG or renamed. The first image keeps its place; a PNG replaces a TIFF of the same picture
|
|
54716
|
+
* because every web view can show it. */
|
|
54717
|
+
function distinctImages(images) {
|
|
54718
|
+
const kept = [];
|
|
54719
|
+
for (const image of images) {
|
|
54720
|
+
const index = kept.findIndex((other) => sameImage(other, image));
|
|
54721
|
+
if (index < 0) kept.push(image);
|
|
54722
|
+
else if (format(kept[index].bytes) === "tiff" && format(image.bytes) === "png") kept[index] = image;
|
|
54723
|
+
}
|
|
54724
|
+
return kept;
|
|
54725
|
+
}
|
|
54726
|
+
//#endregion
|
|
54056
54727
|
//#region src/paste.ts
|
|
54057
54728
|
var PasteController = class {
|
|
54058
54729
|
options;
|
|
@@ -54214,12 +54885,12 @@ var PasteController = class {
|
|
|
54214
54885
|
this.active = operation;
|
|
54215
54886
|
this.options.onPendingChanged?.();
|
|
54216
54887
|
try {
|
|
54217
|
-
const
|
|
54218
|
-
for (const file of files) images.push({
|
|
54888
|
+
const fromFiles = files.length ? distinctImages(await Promise.all(files.map(async (file) => ({
|
|
54219
54889
|
bytes: new Uint8Array(await file.arrayBuffer()),
|
|
54220
54890
|
mimeType: file.type,
|
|
54221
54891
|
filename: file.name
|
|
54222
|
-
});
|
|
54892
|
+
})))) : [];
|
|
54893
|
+
const images = distinctImages([...input.images ?? [], ...fromFiles]);
|
|
54223
54894
|
this.assertContext(context, operation);
|
|
54224
54895
|
const schema = view.state.schema;
|
|
54225
54896
|
let slice;
|
|
@@ -54238,8 +54909,7 @@ var PasteController = class {
|
|
|
54238
54909
|
}
|
|
54239
54910
|
const anchor = this.anchor(operation);
|
|
54240
54911
|
const start = view.state.doc.resolve(anchor.from);
|
|
54241
|
-
const
|
|
54242
|
-
const marks = view.state.storedMarks ?? (anchor.from === anchor.to ? start.marks() : start.marksAcross(end)) ?? [];
|
|
54912
|
+
const marks = replacementMarks(view.state, anchor.from, anchor.to);
|
|
54243
54913
|
const nodes = literalTextNodes(schema, input.text, marks, htmlBreakAt(start));
|
|
54244
54914
|
slice = new Slice(Fragment.from(schema.nodes.paragraph.create(null, nodes)), 1, 1);
|
|
54245
54915
|
} else if (input.html) {
|
|
@@ -54247,7 +54917,7 @@ var PasteController = class {
|
|
|
54247
54917
|
const imported = /* @__PURE__ */ new Map();
|
|
54248
54918
|
const elements = [...container.querySelectorAll("img")];
|
|
54249
54919
|
const uniqueSources = new Set(elements.map((element) => element.getAttribute("src") ?? ""));
|
|
54250
|
-
const positional = (
|
|
54920
|
+
const positional = (fromFiles.length === 0 || fromFiles.length === 1 && uniqueSources.size === 1 ? images : input.images ?? []).filter((image) => !image.source);
|
|
54251
54921
|
let index = 0;
|
|
54252
54922
|
for (const element of elements) {
|
|
54253
54923
|
const source = element.getAttribute("src") ?? "";
|
|
@@ -54744,11 +55414,11 @@ var DocumentSession = class {
|
|
|
54744
55414
|
//#region src/selection.ts
|
|
54745
55415
|
/** The stylesheet paints the selection under this name. */
|
|
54746
55416
|
var name = "inkkit-selection";
|
|
54747
|
-
var
|
|
55417
|
+
var activeClass = "inkkit-selection-active";
|
|
54748
55418
|
/** The selected text within each block. */
|
|
54749
55419
|
function covered(state) {
|
|
54750
55420
|
const { from, to, empty, visible } = state.selection;
|
|
54751
|
-
if (empty || !visible) return
|
|
55421
|
+
if (empty || !visible) return [];
|
|
54752
55422
|
const text = [];
|
|
54753
55423
|
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
54754
55424
|
if (!node.isTextblock) return true;
|
|
@@ -54765,39 +55435,140 @@ function covered(state) {
|
|
|
54765
55435
|
function domRange(view, span) {
|
|
54766
55436
|
const start = view.domAtPos(span.from);
|
|
54767
55437
|
const end = view.domAtPos(span.to);
|
|
54768
|
-
const range =
|
|
55438
|
+
const range = view.dom.ownerDocument.createRange();
|
|
54769
55439
|
range.setStart(start.node, start.offset);
|
|
54770
55440
|
range.setEnd(end.node, end.offset);
|
|
54771
55441
|
return range;
|
|
54772
55442
|
}
|
|
54773
|
-
|
|
54774
|
-
ranges.set(view, (covered(view.state) ?? []).map((span) => domRange(view, span)));
|
|
54775
|
-
refresh();
|
|
54776
|
-
}
|
|
54777
|
-
function refresh() {
|
|
54778
|
-
if (ranges.size === 0) {
|
|
54779
|
-
CSS.highlights.delete(name);
|
|
54780
|
-
return;
|
|
54781
|
-
}
|
|
54782
|
-
const highlight = new Highlight();
|
|
54783
|
-
for (const selection of ranges.values()) for (const range of selection) highlight.add(range);
|
|
54784
|
-
CSS.highlights.set(name, highlight);
|
|
54785
|
-
}
|
|
55443
|
+
var rootOf = (view) => view.dom.closest(".inkkit-root");
|
|
54786
55444
|
var paintable = () => typeof Highlight === "function" && "highlights" in CSS && CSS.supports(`selector(::highlight(${name}))`);
|
|
54787
|
-
|
|
54788
|
-
|
|
54789
|
-
|
|
54790
|
-
|
|
54791
|
-
|
|
54792
|
-
|
|
54793
|
-
|
|
54794
|
-
|
|
54795
|
-
|
|
54796
|
-
|
|
54797
|
-
|
|
54798
|
-
|
|
55445
|
+
/**
|
|
55446
|
+
* Whether the view holds the user's input: its formatted surface, or the source or TXT
|
|
55447
|
+
* textarea beside it, has focus, or, in a read-only editor that takes no focus, the
|
|
55448
|
+
* document selection is inside it.
|
|
55449
|
+
*/
|
|
55450
|
+
function focused(view) {
|
|
55451
|
+
const doc = view.dom.ownerDocument;
|
|
55452
|
+
const surface = doc.activeElement;
|
|
55453
|
+
if (surface === view.dom || view.dom.contains(surface) || surface instanceof HTMLTextAreaElement && surface.classList.contains("inkkit-plain") && rootOf(view).contains(surface)) return true;
|
|
55454
|
+
const anchor = doc.getSelection()?.anchorNode;
|
|
55455
|
+
return !view.editable && !!anchor && view.dom.contains(anchor);
|
|
55456
|
+
}
|
|
55457
|
+
/** Whether the focused element takes typing, so a selection kept elsewhere is still what the host is working on. */
|
|
55458
|
+
function takesText(element) {
|
|
55459
|
+
return element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement || element instanceof HTMLSelectElement || element instanceof HTMLElement && element.isContentEditable;
|
|
55460
|
+
}
|
|
55461
|
+
/**
|
|
55462
|
+
* One document has one selection, so the editors on it share one painter and one highlight.
|
|
55463
|
+
* The owner is the editor that most recently held the selection. Its selection is painted
|
|
55464
|
+
* in the active colour while it has focus in a focused window, and in the inactive colour
|
|
55465
|
+
* otherwise, so a host that selects a range from its search field, or blurs the editor,
|
|
55466
|
+
* still shows what is selected. Anything that takes the selection elsewhere releases it.
|
|
55467
|
+
*/
|
|
55468
|
+
var Painter = class Painter {
|
|
55469
|
+
doc;
|
|
55470
|
+
static all = /* @__PURE__ */ new WeakMap();
|
|
55471
|
+
views = /* @__PURE__ */ new Map();
|
|
55472
|
+
win;
|
|
55473
|
+
custom = paintable();
|
|
55474
|
+
owner = null;
|
|
55475
|
+
windowFocused;
|
|
55476
|
+
static of(doc) {
|
|
55477
|
+
let painter = Painter.all.get(doc);
|
|
55478
|
+
if (!painter) Painter.all.set(doc, painter = new Painter(doc));
|
|
55479
|
+
return painter;
|
|
54799
55480
|
}
|
|
54800
|
-
|
|
55481
|
+
constructor(doc) {
|
|
55482
|
+
this.doc = doc;
|
|
55483
|
+
this.win = doc.defaultView;
|
|
55484
|
+
this.windowFocused = doc.hasFocus();
|
|
55485
|
+
}
|
|
55486
|
+
add(view) {
|
|
55487
|
+
if (!this.views.size) this.listen("add");
|
|
55488
|
+
this.views.set(view, rootOf(view));
|
|
55489
|
+
this.sync();
|
|
55490
|
+
}
|
|
55491
|
+
remove(view) {
|
|
55492
|
+
this.views.get(view)?.classList.remove(activeClass);
|
|
55493
|
+
this.views.delete(view);
|
|
55494
|
+
if (this.owner === view) this.owner = null;
|
|
55495
|
+
this.sync();
|
|
55496
|
+
if (!this.views.size) {
|
|
55497
|
+
this.listen("remove");
|
|
55498
|
+
Painter.all.delete(this.doc);
|
|
55499
|
+
}
|
|
55500
|
+
}
|
|
55501
|
+
/** A transaction gave this view a selection. A focused owner is not taken over by an editor that is not. */
|
|
55502
|
+
take(view) {
|
|
55503
|
+
if (!this.owner || this.owner === view || focused(view) || !focused(this.owner)) this.owner = view;
|
|
55504
|
+
this.sync();
|
|
55505
|
+
}
|
|
55506
|
+
/** The owner's document changed, or its selection moved with it. */
|
|
55507
|
+
changed(view) {
|
|
55508
|
+
if (this.owner === view) this.sync();
|
|
55509
|
+
}
|
|
55510
|
+
onFocusIn = () => {
|
|
55511
|
+
for (const view of this.views.keys()) if (focused(view)) this.owner = view;
|
|
55512
|
+
this.sync();
|
|
55513
|
+
};
|
|
55514
|
+
onFocusOut = () => this.sync();
|
|
55515
|
+
onWindow = (event) => {
|
|
55516
|
+
this.windowFocused = event.type === "focus";
|
|
55517
|
+
this.sync();
|
|
55518
|
+
};
|
|
55519
|
+
onSelectionChange = () => {
|
|
55520
|
+
const owner = this.owner;
|
|
55521
|
+
if (!owner || focused(owner)) return;
|
|
55522
|
+
const selection = this.doc.getSelection();
|
|
55523
|
+
if (!selection?.rangeCount || owner.dom.contains(selection.anchorNode)) return;
|
|
55524
|
+
if (selection.isCollapsed && takesText(this.doc.activeElement)) return;
|
|
55525
|
+
this.owner = null;
|
|
55526
|
+
this.sync();
|
|
55527
|
+
};
|
|
55528
|
+
listen(action) {
|
|
55529
|
+
const method = `${action}EventListener`;
|
|
55530
|
+
this.doc[method]("focusin", this.onFocusIn);
|
|
55531
|
+
this.doc[method]("focusout", this.onFocusOut);
|
|
55532
|
+
this.doc[method]("selectionchange", this.onSelectionChange);
|
|
55533
|
+
this.win[method]("focus", this.onWindow);
|
|
55534
|
+
this.win[method]("blur", this.onWindow);
|
|
55535
|
+
}
|
|
55536
|
+
sync() {
|
|
55537
|
+
for (const [view, root] of this.views) root.classList.toggle(activeClass, this.windowFocused && focused(view));
|
|
55538
|
+
if (!this.custom) return;
|
|
55539
|
+
const { owner } = this;
|
|
55540
|
+
const spans = owner ? covered(owner.state) : [];
|
|
55541
|
+
if (!owner || !spans.length) {
|
|
55542
|
+
CSS.highlights.delete(name);
|
|
55543
|
+
return;
|
|
55544
|
+
}
|
|
55545
|
+
const highlight = new Highlight();
|
|
55546
|
+
for (const span of spans) highlight.add(domRange(owner, span));
|
|
55547
|
+
CSS.highlights.set(name, highlight);
|
|
55548
|
+
}
|
|
55549
|
+
};
|
|
55550
|
+
var selectionPlugin = $prose(() => {
|
|
55551
|
+
const key = new PluginKey("selection");
|
|
55552
|
+
return new Plugin({
|
|
55553
|
+
key,
|
|
55554
|
+
state: {
|
|
55555
|
+
init: () => 0,
|
|
55556
|
+
apply: (tr, count) => tr.selectionSet ? count + 1 : count
|
|
55557
|
+
},
|
|
55558
|
+
props: paintable() ? { attributes: { class: "inkkit-painted-selection" } } : {},
|
|
55559
|
+
view(view) {
|
|
55560
|
+
const painter = Painter.of(view.dom.ownerDocument);
|
|
55561
|
+
painter.add(view);
|
|
55562
|
+
return {
|
|
55563
|
+
update(view, previous) {
|
|
55564
|
+
if (key.getState(view.state) !== key.getState(previous)) painter.take(view);
|
|
55565
|
+
else painter.changed(view);
|
|
55566
|
+
},
|
|
55567
|
+
destroy: () => painter.remove(view)
|
|
55568
|
+
};
|
|
55569
|
+
}
|
|
55570
|
+
});
|
|
55571
|
+
});
|
|
54801
55572
|
//#endregion
|
|
54802
55573
|
//#region node_modules/.pnpm/prosemirror-search@1.1.1/node_modules/prosemirror-search/dist/index.js
|
|
54803
55574
|
var SearchQuery = class {
|
|
@@ -55227,8 +55998,8 @@ function findFormatted(view, text) {
|
|
|
55227
55998
|
return found;
|
|
55228
55999
|
}
|
|
55229
56000
|
function replacementSlice(state, from, to, value) {
|
|
55230
|
-
const start = state.doc.resolve(from)
|
|
55231
|
-
const marks =
|
|
56001
|
+
const start = state.doc.resolve(from);
|
|
56002
|
+
const marks = replacementMarks(state, from, to);
|
|
55232
56003
|
const nodes = [];
|
|
55233
56004
|
if (start.parent.type.spec.code) {
|
|
55234
56005
|
if (value) nodes.push(state.schema.text(value, marks));
|
|
@@ -55845,6 +56616,8 @@ var shortcutNames = [
|
|
|
55845
56616
|
"redo",
|
|
55846
56617
|
"moveBlockUp",
|
|
55847
56618
|
"moveBlockDown",
|
|
56619
|
+
"indent",
|
|
56620
|
+
"outdent",
|
|
55848
56621
|
...tableCommands.map(tableShortcut)
|
|
55849
56622
|
];
|
|
55850
56623
|
/** Checks a keymap and drops omitted entries, so a `null` binding keeps its default. */
|
|
@@ -55896,6 +56669,7 @@ function editorOptions(value) {
|
|
|
55896
56669
|
"textInput",
|
|
55897
56670
|
"labels",
|
|
55898
56671
|
"keymap",
|
|
56672
|
+
"linkSchemes",
|
|
55899
56673
|
"rendering",
|
|
55900
56674
|
"slashMenu"
|
|
55901
56675
|
]) ?? {};
|
|
@@ -55905,6 +56679,7 @@ function editorOptions(value) {
|
|
|
55905
56679
|
optionalBoolean(options.editable, "options.editable");
|
|
55906
56680
|
if (!isOmitted(options.textInput)) textInputPreferences(options.textInput, "options.textInput");
|
|
55907
56681
|
if (!isOmitted(options.keymap)) keymapBindings(options.keymap, "options.keymap");
|
|
56682
|
+
const linkSchemes = isOmitted(options.linkSchemes) ? void 0 : extraLinkSchemes(options.linkSchemes, "options.linkSchemes");
|
|
55908
56683
|
const rendering = optionalRecord(options.rendering, "options.rendering", ["codeHighlighting", "diagramPreview"]);
|
|
55909
56684
|
optionalBoolean(rendering?.codeHighlighting, "options.rendering.codeHighlighting");
|
|
55910
56685
|
optionalBoolean(rendering?.diagramPreview, "options.rendering.diagramPreview");
|
|
@@ -55912,6 +56687,7 @@ function editorOptions(value) {
|
|
|
55912
56687
|
return {
|
|
55913
56688
|
...options,
|
|
55914
56689
|
slashMenu: slashMenuOptions(options.slashMenu),
|
|
56690
|
+
linkSchemes,
|
|
55915
56691
|
labels: labels && Object.fromEntries(Object.entries(labels).filter(([, label]) => !isOmitted(label)).map(([key, label]) => [key, expectString(label, `options.labels.${key}`)]))
|
|
55916
56692
|
};
|
|
55917
56693
|
}
|
|
@@ -56108,6 +56884,18 @@ function blockAt(parent, $from) {
|
|
|
56108
56884
|
return { type: "paragraph" };
|
|
56109
56885
|
}
|
|
56110
56886
|
var quotes = /* @__PURE__ */ new Set(["blockquote", "inkkit_callout"]);
|
|
56887
|
+
function liftQuote(state, range, target) {
|
|
56888
|
+
const tr = state.tr.lift(range, target);
|
|
56889
|
+
const { depth } = range;
|
|
56890
|
+
const item = range.$from.node(depth - 1);
|
|
56891
|
+
const spacer = item.firstChild;
|
|
56892
|
+
if (item.type.name === "list_item" && range.$from.index(depth - 1) === 1 && spacer?.type.name === "paragraph" && spacer.content.size === 0) {
|
|
56893
|
+
const from = range.$from.start(depth - 1);
|
|
56894
|
+
if (tr.doc.nodeAt(from + spacer.nodeSize)?.type === spacer.type) tr.delete(from, from + spacer.nodeSize);
|
|
56895
|
+
}
|
|
56896
|
+
return tr;
|
|
56897
|
+
}
|
|
56898
|
+
var undoTypedRule = $prose(() => keymap$3({ Backspace: undoInputRule }));
|
|
56111
56899
|
var quoteBackspace = $prose(() => keymap$3({ Backspace: (state, dispatch) => {
|
|
56112
56900
|
const { $from, empty } = state.selection;
|
|
56113
56901
|
if (!empty || $from.parentOffset > 0 || $from.depth < 2) return false;
|
|
@@ -56117,7 +56905,7 @@ var quoteBackspace = $prose(() => keymap$3({ Backspace: (state, dispatch) => {
|
|
|
56117
56905
|
const range = $from.blockRange($from, (node) => quotes.has(node.type.name));
|
|
56118
56906
|
const target = range && liftTarget(range);
|
|
56119
56907
|
if (!range || target == null) return false;
|
|
56120
|
-
dispatch?.(state
|
|
56908
|
+
dispatch?.(liftQuote(state, range, target).scrollIntoView());
|
|
56121
56909
|
return true;
|
|
56122
56910
|
} }));
|
|
56123
56911
|
var calloutEnter = $prose(() => keymap$3({ Enter: (state, dispatch) => {
|
|
@@ -56159,7 +56947,6 @@ var liftItem = (state, dispatch) => {
|
|
|
56159
56947
|
dispatch(lifted);
|
|
56160
56948
|
return true;
|
|
56161
56949
|
};
|
|
56162
|
-
var listItemShiftTab = $prose(() => keymap$3({ "Shift-Tab": liftItem }));
|
|
56163
56950
|
var rejoinLists = $prose(() => keymap$3({ Backspace: (state, dispatch) => {
|
|
56164
56951
|
const { $from, empty } = state.selection;
|
|
56165
56952
|
if (!empty || $from.parent.type.name !== "paragraph" || $from.parent.content.size > 0) return false;
|
|
@@ -56252,11 +57039,7 @@ var movedListItems = $prose(() => new Plugin({
|
|
|
56252
57039
|
return tr.docChanged ? tr : null;
|
|
56253
57040
|
}
|
|
56254
57041
|
}));
|
|
56255
|
-
var
|
|
56256
|
-
var textInputPolicy = $prose(() => new Plugin({
|
|
56257
|
-
key: new PluginKey("inkkitTextInput"),
|
|
56258
|
-
props: { handleTextInput: (view, from, to, text, deflt) => controlCharacters.test(text) || insertTextChunk(view, from, to, text, deflt) }
|
|
56259
|
-
}));
|
|
57042
|
+
var textInputPolicy = $prose(() => textInputPlugin());
|
|
56260
57043
|
function outermostListDepth($pos) {
|
|
56261
57044
|
for (let depth = 1; depth <= $pos.depth; depth++) if (isList($pos.node(depth))) return depth;
|
|
56262
57045
|
return null;
|
|
@@ -56381,6 +57164,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56381
57164
|
inputPreferences = {};
|
|
56382
57165
|
literalKeys = () => false;
|
|
56383
57166
|
configuredKeys = {};
|
|
57167
|
+
indentKeys = () => false;
|
|
56384
57168
|
readOnlyKeys = () => false;
|
|
56385
57169
|
suggestions;
|
|
56386
57170
|
suggestionBase;
|
|
@@ -56420,6 +57204,8 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56420
57204
|
}));
|
|
56421
57205
|
keys = () => false;
|
|
56422
57206
|
events;
|
|
57207
|
+
/** The host's extra link schemes, in lower case. */
|
|
57208
|
+
linkSchemes;
|
|
56423
57209
|
/** How many of each state event the host has been sent. */
|
|
56424
57210
|
sentEvents = /* @__PURE__ */ new Map();
|
|
56425
57211
|
constructor(events, options) {
|
|
@@ -56439,6 +57225,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56439
57225
|
else send();
|
|
56440
57226
|
};
|
|
56441
57227
|
} });
|
|
57228
|
+
this.linkSchemes = new Set(options.linkSchemes);
|
|
56442
57229
|
this.writable = options.editable ?? true;
|
|
56443
57230
|
this.inputPreferences = textInputPreferences(options.textInput ?? {}, "options.textInput");
|
|
56444
57231
|
}
|
|
@@ -56499,7 +57286,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56499
57286
|
};
|
|
56500
57287
|
}
|
|
56501
57288
|
mediaPolicy() {
|
|
56502
|
-
if (this.editor && this.root) this.editor.ctx.get(editorViewCtx).dom.dispatchEvent(new Event(
|
|
57289
|
+
if (this.editor && this.root) this.editor.ctx.get(editorViewCtx).dom.dispatchEvent(new Event(mediaPolicyEvent));
|
|
56503
57290
|
}
|
|
56504
57291
|
assertAlive() {
|
|
56505
57292
|
if (this.destroyed) throw new InkKitError("destroyed", "The editor has been destroyed");
|
|
@@ -56750,6 +57537,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56750
57537
|
replace: mutable,
|
|
56751
57538
|
replaceSource: mutable,
|
|
56752
57539
|
insertImages: formatted && this.canInsertImages,
|
|
57540
|
+
appendImages: formatted && this.canInsertImages,
|
|
56753
57541
|
insertPaths: mutable,
|
|
56754
57542
|
insertFootnote: formatted,
|
|
56755
57543
|
editReferenceDefinition: formatted && referenceDefinitions(state.doc).size > 0,
|
|
@@ -57209,7 +57997,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57209
57997
|
} catch (error) {
|
|
57210
57998
|
throw coded(error, "preservation");
|
|
57211
57999
|
}
|
|
57212
|
-
const result = await this.exportContent(captured, (signal) => portableClipboard(all || selectedDoc ? content : selectionContent(doc, content), schema, markdown, this.options.images, this.context(), completeDiagrams, this.options.files, signal));
|
|
58000
|
+
const result = await this.exportContent(captured, (signal) => portableClipboard(all || selectedDoc ? content : selectionContent(doc, content), schema, markdown, this.options.images, this.context(), completeDiagrams, this.options.files, signal, this.linkSchemes));
|
|
57213
58001
|
const metadata = referenceMetadata(this.editor.ctx, selectedDoc ?? doc, content);
|
|
57214
58002
|
if (metadata != null) result.html = withReferenceMetadata(result.html, metadata);
|
|
57215
58003
|
this.assertCaptured(captured);
|
|
@@ -57260,7 +58048,8 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57260
58048
|
if (view.state.selection.$from.parent.type.spec.code && !inHiddenComment) view.dispatch(view.state.tr.insertText(text.replace(/\r\n?/g, "\n")).scrollIntoView());
|
|
57261
58049
|
else {
|
|
57262
58050
|
const { schema } = view.state;
|
|
57263
|
-
const
|
|
58051
|
+
const { from, to } = view.state.selection;
|
|
58052
|
+
const marks = replacementMarks(view.state, from, to);
|
|
57264
58053
|
const isHTML = !inHiddenComment && htmlBreakAt(view.state.selection.$from);
|
|
57265
58054
|
const lines = text.replace(/\r\n?/g, "\n").split("\n");
|
|
57266
58055
|
const children = literalTextNodes(schema, text, marks, isHTML);
|
|
@@ -57336,6 +58125,10 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57336
58125
|
return this.keys(view, event);
|
|
57337
58126
|
} }
|
|
57338
58127
|
}));
|
|
58128
|
+
indentPlugin = new Plugin({
|
|
58129
|
+
key: new PluginKey("listIndent"),
|
|
58130
|
+
props: { handleKeyDown: (view, event) => this.indentKeys(view, event) }
|
|
58131
|
+
});
|
|
57339
58132
|
copySourceSelection(event) {
|
|
57340
58133
|
event.preventDefault();
|
|
57341
58134
|
event.stopPropagation();
|
|
@@ -57361,7 +58154,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57361
58154
|
}
|
|
57362
58155
|
}).catch((error) => this.report(error));
|
|
57363
58156
|
else {
|
|
57364
|
-
const output = clipboardContent(parsed.content, parsed.type.schema);
|
|
58157
|
+
const output = clipboardContent(parsed.content, parsed.type.schema, this.linkSchemes);
|
|
57365
58158
|
if (!event.clipboardData) return;
|
|
57366
58159
|
this.rememberCopy(output, selected.markdown, parsed.content, selected.markdown !== selected.shareable, true);
|
|
57367
58160
|
event.clipboardData.setData("text/plain", output.text);
|
|
@@ -57427,6 +58220,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57427
58220
|
ctx.set(rootCtx, root);
|
|
57428
58221
|
ctx.set(authoredSourcesCtx.key, (doc, positions) => instance.authoredSources(doc, positions));
|
|
57429
58222
|
ctx.set(smartPunctuationCtx.key, () => instance.inputPreferences.smartPunctuation === true);
|
|
58223
|
+
ctx.set(linkSchemesCtx.key, instance.linkSchemes);
|
|
57430
58224
|
ctx.update(labelsCtx.key, () => ({
|
|
57431
58225
|
...defaultLabels,
|
|
57432
58226
|
...options.labels
|
|
@@ -57441,9 +58235,16 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57441
58235
|
}), false));
|
|
57442
58236
|
ctx.set(defaultValueCtx, "");
|
|
57443
58237
|
ctx.set(remarkStringifyOptionsCtx, stringifyOptions);
|
|
58238
|
+
ctx.update(editorStateOptionsCtx, (override) => (options) => {
|
|
58239
|
+
const next = override(options);
|
|
58240
|
+
return {
|
|
58241
|
+
...next,
|
|
58242
|
+
plugins: [...next.plugins ?? [], instance.indentPlugin]
|
|
58243
|
+
};
|
|
58244
|
+
});
|
|
57444
58245
|
ctx.update(listItemKeymap.key, (keys) => ({
|
|
57445
58246
|
...keys,
|
|
57446
|
-
SinkListItem: { shortcuts:
|
|
58247
|
+
SinkListItem: { shortcuts: [] },
|
|
57447
58248
|
LiftListItem: { shortcuts: [] }
|
|
57448
58249
|
}));
|
|
57449
58250
|
const unbind = (keymap, keep = []) => ctx.update(keymap.key, (keys) => {
|
|
@@ -57507,7 +58308,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57507
58308
|
return true;
|
|
57508
58309
|
}
|
|
57509
58310
|
}));
|
|
57510
|
-
}).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(
|
|
58311
|
+
}).use(labelsCtx).use(linkSchemesCtx).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(undoTypedRule).use(quoteBackspace).use(calloutEnter).use(literalEnter).use(literalReread).use(listItemBackspace).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-GlZZ_7st.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, {
|
|
57511
58312
|
capture: () => instance.adapterCapture(),
|
|
57512
58313
|
active: () => instance.ready && !instance.destroyed && !instance.literalSurface,
|
|
57513
58314
|
labels: {
|
|
@@ -57515,8 +58316,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57515
58316
|
...options.labels
|
|
57516
58317
|
},
|
|
57517
58318
|
error: (error) => instance.report(error)
|
|
57518
|
-
}) : []).use(options.images || options.files ? imageView(options.images,
|
|
57519
|
-
adapter: options.files,
|
|
58319
|
+
}) : []).use(options.images || options.files ? imageView(options.images, {
|
|
57520
58320
|
capture: () => instance.adapterCapture(),
|
|
57521
58321
|
active: () => instance.ready && !instance.destroyed && !instance.literalSurface,
|
|
57522
58322
|
labels: {
|
|
@@ -57524,7 +58324,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57524
58324
|
...options.labels
|
|
57525
58325
|
},
|
|
57526
58326
|
error: (error) => instance.report(error)
|
|
57527
|
-
}
|
|
58327
|
+
}, options.files, () => {
|
|
57528
58328
|
try {
|
|
57529
58329
|
instance.assertMutation();
|
|
57530
58330
|
return true;
|
|
@@ -57658,7 +58458,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57658
58458
|
const content = expanded;
|
|
57659
58459
|
const valid = fragment.firstChild?.isInline ? Fragment.from(view.state.schema.nodes.paragraph.create(null, fragment)) : fragment;
|
|
57660
58460
|
const markdown = selectionMarkdown(instance.editor.ctx, view.state.doc, valid);
|
|
57661
|
-
const output = clipboardContent(content, view.state.schema);
|
|
58461
|
+
const output = clipboardContent(content, view.state.schema, instance.linkSchemes);
|
|
57662
58462
|
const metadata = referenceMetadata(instance.editor.ctx, view.state.doc, valid);
|
|
57663
58463
|
if (metadata != null) output.html = withReferenceMetadata(output.html, metadata);
|
|
57664
58464
|
instance.rememberCopy(output, markdown, fragment, false, true);
|
|
@@ -58311,10 +59111,23 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58311
59111
|
this.assertReady(expectedGeneration);
|
|
58312
59112
|
this.releaseFocus();
|
|
58313
59113
|
}
|
|
59114
|
+
/**
|
|
59115
|
+
* Resolves wiki links and file embeds again, all of them or those whose `target` is named, after
|
|
59116
|
+
* something they point to changed. A file keeps its card until the new answer differs. Changes no
|
|
59117
|
+
* document state, so it works in a read-only editor and during composition. Source and TXT modes
|
|
59118
|
+
* draw no references, and they resolve afresh when formatted mode returns.
|
|
59119
|
+
*/
|
|
59120
|
+
refreshReferences(targets, expectedGeneration) {
|
|
59121
|
+
this.assertAlive();
|
|
59122
|
+
const names = isOmitted(targets) ? void 0 : new Set(expectArray(targets, "targets").map((target) => expectString(target, "targets entry")));
|
|
59123
|
+
this.assertReady(expectedGeneration);
|
|
59124
|
+
requestRefresh(this.editor.ctx.get(editorViewCtx).dom, { ...names && { targets: names } });
|
|
59125
|
+
}
|
|
58314
59126
|
/** Replaces every binding. Keys are in ProseMirror's notation. A key given to two shortcuts goes
|
|
58315
59127
|
* to the later one, in the order history, formatting, block moves, tables, so it lands the same
|
|
58316
59128
|
* way every time. A table binding passes a key it shares with a block move to the move outside
|
|
58317
|
-
* a table.
|
|
59129
|
+
* a table. List indentation keys apply after all of these, and after the table keys the editor
|
|
59130
|
+
* keeps for itself. */
|
|
58318
59131
|
setKeymap(keymap) {
|
|
58319
59132
|
this.assertAlive();
|
|
58320
59133
|
keymap = keymapBindings(keymap, "keymap");
|
|
@@ -58324,6 +59137,8 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58324
59137
|
moveBlockUp: ["Alt-ArrowUp"],
|
|
58325
59138
|
moveBlockDown: ["Alt-ArrowDown"],
|
|
58326
59139
|
tableExit: ["Mod-Enter", "Enter"],
|
|
59140
|
+
indent: ["Tab"],
|
|
59141
|
+
outdent: ["Shift-Tab"],
|
|
58327
59142
|
...keymap
|
|
58328
59143
|
};
|
|
58329
59144
|
const bindings = {};
|
|
@@ -58350,6 +59165,9 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58350
59165
|
if (move === "move" && !this.composing && !this.pasteController.pending) this.forPerson(() => this.moveBlock(direction), false);
|
|
58351
59166
|
return true;
|
|
58352
59167
|
};
|
|
59168
|
+
const indents = {};
|
|
59169
|
+
const sink = (state, dispatch) => sinkListItem(state.schema.nodes.list_item)(state, dispatch);
|
|
59170
|
+
for (const [name, command] of [["indent", sink], ["outdent", liftItem]]) for (const key of this.configuredKeys[name] ?? []) indents[key] = (state, dispatch, view) => this.ready && this.writable && !this.literalSurface ? command(state, dispatch, view) : false;
|
|
58353
59171
|
for (const command of tableCommands) for (const key of this.configuredKeys[tableShortcut(command)] ?? []) bindings[key] = (state, dispatch, view) => {
|
|
58354
59172
|
if (!this.ready || !this.commandState().commands.table[command]) return moves[key]?.(state, dispatch, view) ?? false;
|
|
58355
59173
|
return this.forPerson(() => this.table(command), true);
|
|
@@ -58358,6 +59176,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58358
59176
|
throw new InkKitError("read-only", "The editor is read-only");
|
|
58359
59177
|
}])));
|
|
58360
59178
|
this.keys = keydownHandler(bindings);
|
|
59179
|
+
this.indentKeys = keydownHandler(indents);
|
|
58361
59180
|
this.literalKeys = keydownHandler(historyBindings);
|
|
58362
59181
|
}
|
|
58363
59182
|
/** Dropped files land as one paragraph per path at the drop point: in place of an empty block, after
|
|
@@ -58385,17 +59204,12 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58385
59204
|
this.assertMutation(expectedGeneration);
|
|
58386
59205
|
if (!images.length || !this.canInsertImages || this.literalSurface) return false;
|
|
58387
59206
|
const view = this.editor.ctx.get(editorViewCtx);
|
|
58388
|
-
const { schema } = view.state;
|
|
58389
59207
|
const placement = point ? void 0 : imagePlacement(view.state);
|
|
58390
59208
|
if (placement?.kind === "inline") {
|
|
58391
59209
|
this.insertInline(images);
|
|
58392
59210
|
return true;
|
|
58393
59211
|
}
|
|
58394
|
-
const blocks =
|
|
58395
|
-
src: image.reference,
|
|
58396
|
-
alt: image.alt,
|
|
58397
|
-
title: image.title ?? ""
|
|
58398
|
-
})));
|
|
59212
|
+
const blocks = this.imageBlocks(images);
|
|
58399
59213
|
if (point) {
|
|
58400
59214
|
this.insertBlocks(blocks, point);
|
|
58401
59215
|
return true;
|
|
@@ -58411,6 +59225,31 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58411
59225
|
view.dispatch(tr.scrollIntoView());
|
|
58412
59226
|
return true;
|
|
58413
59227
|
}
|
|
59228
|
+
/** Adds images as the last blocks of the document and leaves everything else as it is: no focus,
|
|
59229
|
+
* no scrolling, and the selection stays on the text it covered. For a host that attaches images
|
|
59230
|
+
* to a document the person is not editing at that moment. Returns false when it does nothing. */
|
|
59231
|
+
appendImages(images, expectedGeneration) {
|
|
59232
|
+
this.assertAlive();
|
|
59233
|
+
images = imageInsertions(images);
|
|
59234
|
+
this.assertMutation(expectedGeneration);
|
|
59235
|
+
if (!images.length || !this.canInsertImages || this.literalSurface) return false;
|
|
59236
|
+
const view = this.editor.ctx.get(editorViewCtx);
|
|
59237
|
+
const { doc, tr } = view.state;
|
|
59238
|
+
const blocks = this.imageBlocks(images);
|
|
59239
|
+
if (doc.childCount === 1 && doc.firstChild.content.size === 0) tr.replaceWith(0, doc.content.size, blocks);
|
|
59240
|
+
else tr.insert(doc.content.size, blocks);
|
|
59241
|
+
view.dispatch(closeHistory(tr));
|
|
59242
|
+
view.dispatch(closeHistory(view.state.tr).setMeta("addToHistory", false));
|
|
59243
|
+
return true;
|
|
59244
|
+
}
|
|
59245
|
+
imageBlocks(images) {
|
|
59246
|
+
const { schema } = this.editor.ctx.get(editorViewCtx).state;
|
|
59247
|
+
return images.map((image) => schema.nodes.paragraph.create(null, schema.nodes.image.create({
|
|
59248
|
+
src: image.reference,
|
|
59249
|
+
alt: image.alt,
|
|
59250
|
+
title: image.title ?? ""
|
|
59251
|
+
})));
|
|
59252
|
+
}
|
|
58414
59253
|
insertInline(images) {
|
|
58415
59254
|
const view = this.editor.ctx.get(editorViewCtx);
|
|
58416
59255
|
const { state } = view;
|
|
@@ -58528,7 +59367,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58528
59367
|
if (!range) return;
|
|
58529
59368
|
const target = liftTarget(range);
|
|
58530
59369
|
if (target == null) return;
|
|
58531
|
-
view.dispatch(view.state
|
|
59370
|
+
view.dispatch(liftQuote(view.state, range, target));
|
|
58532
59371
|
}
|
|
58533
59372
|
/** Changes the selected textblocks' type, keeping everything they hold. */
|
|
58534
59373
|
textblockType(type, attr) {
|
|
@@ -58613,25 +59452,27 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58613
59452
|
commit(command);
|
|
58614
59453
|
return;
|
|
58615
59454
|
}
|
|
59455
|
+
const onHostError = (error) => {
|
|
59456
|
+
if (!this.destroyed) this.report(coded(error, "slash-command-failed"));
|
|
59457
|
+
};
|
|
59458
|
+
const insert = (markdown) => {
|
|
59459
|
+
if (this.destroyed) return;
|
|
59460
|
+
if (markdown === void 0) return;
|
|
59461
|
+
if (typeof markdown !== "string") {
|
|
59462
|
+
this.report(invalidArgument("A slash command must return Markdown text"));
|
|
59463
|
+
return;
|
|
59464
|
+
}
|
|
59465
|
+
commit({ markdown });
|
|
59466
|
+
};
|
|
59467
|
+
let result;
|
|
58616
59468
|
try {
|
|
58617
|
-
|
|
58618
|
-
const insert = (markdown) => {
|
|
58619
|
-
if (this.destroyed) return;
|
|
58620
|
-
if (markdown === void 0) return;
|
|
58621
|
-
if (typeof markdown !== "string") {
|
|
58622
|
-
this.report(invalidArgument("A slash command must return Markdown text"));
|
|
58623
|
-
return;
|
|
58624
|
-
}
|
|
58625
|
-
commit({ markdown });
|
|
58626
|
-
};
|
|
58627
|
-
if (result instanceof Promise) result.then(insert).catch((error) => {
|
|
58628
|
-
if (this.destroyed) return;
|
|
58629
|
-
this.report(error);
|
|
58630
|
-
});
|
|
58631
|
-
else insert(result);
|
|
59469
|
+
result = command.action(this.context());
|
|
58632
59470
|
} catch (error) {
|
|
58633
|
-
|
|
59471
|
+
onHostError(error);
|
|
59472
|
+
return;
|
|
58634
59473
|
}
|
|
59474
|
+
if (result instanceof Promise) result.then(insert, onHostError);
|
|
59475
|
+
else insert(result);
|
|
58635
59476
|
}
|
|
58636
59477
|
/** Returns whether the document or the marks the next typed text takes changed. */
|
|
58637
59478
|
format(command, options, expectedGeneration) {
|
|
@@ -58692,12 +59533,13 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58692
59533
|
return !after.doc.eq(before.doc) || !Mark.sameSet(marks(after), marks(before));
|
|
58693
59534
|
}
|
|
58694
59535
|
/**
|
|
58695
|
-
* Refuses a link destination that is empty, that opens anything but a web, mail or phone address
|
|
58696
|
-
* or that the Markdown writer cannot save so that it reads back the
|
|
59536
|
+
* Refuses a link destination that is empty, that opens anything but a web, mail or phone address
|
|
59537
|
+
* or a scheme the host listed, or that the Markdown writer cannot save so that it reads back the
|
|
59538
|
+
* same.
|
|
58697
59539
|
*/
|
|
58698
59540
|
checkDestination(destination, name) {
|
|
58699
59541
|
if (destination.trim() === "") throw invalidArgument(`${name} must not be empty`);
|
|
58700
|
-
if (!isSafeLinkTarget(destination)) throw invalidArgument(`${name} must be relative, or an http, https, mailto or
|
|
59542
|
+
if (!isSafeLinkTarget(destination, this.linkSchemes)) throw invalidArgument(`${name} must be relative, or an address with an allowed scheme (http, https, mailto, tel or one of linkSchemes), with no control characters`);
|
|
58701
59543
|
const { schema } = this.editor.ctx.get(editorViewCtx).state;
|
|
58702
59544
|
const written = serialize(this.editor.ctx, schema.node("doc", null, [schema.node("paragraph", null, [schema.text("x", [schema.marks.link.create({ href: destination })])])]));
|
|
58703
59545
|
let read;
|
|
@@ -58719,13 +59561,18 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58719
59561
|
const { selection, storedMarks } = state;
|
|
58720
59562
|
const { from, to, empty } = selection;
|
|
58721
59563
|
const stored = empty ? type.isInSet(storedMarks ?? []) : void 0;
|
|
58722
|
-
|
|
59564
|
+
const beside = empty ? selection.$from.nodeBefore?.marks ?? [] : [];
|
|
59565
|
+
if (stored && !stored.isInSet(selection.$from.marks()) && !stored.isInSet(beside)) {
|
|
58723
59566
|
const tr = state.tr.removeStoredMark(type);
|
|
58724
59567
|
if (destination !== void 0) tr.addStoredMark(type.create({ href: destination }));
|
|
58725
59568
|
view.dispatch(tr);
|
|
58726
59569
|
return;
|
|
58727
59570
|
}
|
|
58728
|
-
const mark = type.isInSet(empty ? [
|
|
59571
|
+
const mark = type.isInSet(empty ? [
|
|
59572
|
+
...selection.$from.marks(),
|
|
59573
|
+
...beside,
|
|
59574
|
+
...state.doc.nodeAt(from)?.marks ?? []
|
|
59575
|
+
] : state.doc.nodeAt(from)?.marks ?? []);
|
|
58729
59576
|
const extent = mark && markRun(state.doc, mark, from, to);
|
|
58730
59577
|
const keepStored = (tr, link) => {
|
|
58731
59578
|
if (!storedMarks) return tr;
|
|
@@ -58872,12 +59719,14 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58872
59719
|
"keyDown",
|
|
58873
59720
|
"insertPaths",
|
|
58874
59721
|
"insertImages",
|
|
59722
|
+
"appendImages",
|
|
58875
59723
|
"insertFootnote",
|
|
58876
59724
|
"navigateFootnote",
|
|
58877
59725
|
"editReferenceDefinition",
|
|
58878
59726
|
"setCommentsVisible",
|
|
58879
59727
|
"focus",
|
|
58880
59728
|
"blur",
|
|
59729
|
+
"refreshReferences",
|
|
58881
59730
|
"setKeymap",
|
|
58882
59731
|
"textSnapshot",
|
|
58883
59732
|
"selectTextRange",
|