@aicayzer/inkkit 0.2.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-C612uj1Q.js → core-Dx4gTiUo.js} +1109 -263
- package/dist/chunks/{highlight-AI86evan.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 +88 -16
- 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 = [];
|
|
@@ -43687,27 +43850,9 @@ function remarkComments() {
|
|
|
43687
43850
|
});
|
|
43688
43851
|
return (tree) => {
|
|
43689
43852
|
const visit = (node, inline, parentType) => {
|
|
43690
|
-
if (parentType === "listItem" && node.type === "inkkitCommentBlock") return {
|
|
43691
|
-
type: "paragraph",
|
|
43692
|
-
children: [{
|
|
43693
|
-
...node,
|
|
43694
|
-
type: "inkkitCommentInline",
|
|
43695
|
-
block: true
|
|
43696
|
-
}],
|
|
43697
|
-
position: node.position
|
|
43698
|
-
};
|
|
43699
43853
|
if (node.type === "html") {
|
|
43700
43854
|
const spans = htmlSpans(node.value);
|
|
43701
|
-
if (spans.length === 1 && spans[0].start === 0 && spans[0].end === node.value.length) return
|
|
43702
|
-
type: "paragraph",
|
|
43703
|
-
children: [{
|
|
43704
|
-
type: "inkkitCommentInline",
|
|
43705
|
-
syntax: "html",
|
|
43706
|
-
value: spans[0].value,
|
|
43707
|
-
position: node.position
|
|
43708
|
-
}],
|
|
43709
|
-
position: node.position
|
|
43710
|
-
} : {
|
|
43855
|
+
if (spans.length === 1 && spans[0].start === 0 && spans[0].end === node.value.length) return {
|
|
43711
43856
|
type: inline ? "inkkitCommentInline" : "inkkitCommentBlock",
|
|
43712
43857
|
syntax: "html",
|
|
43713
43858
|
value: spans[0].value,
|
|
@@ -43718,6 +43863,7 @@ function remarkComments() {
|
|
|
43718
43863
|
if (node.type === "paragraph" && parentType !== "listItem" && node.children.length === 1 && node.children[0]?.type === "inkkitCommentInline") return {
|
|
43719
43864
|
...node.children[0],
|
|
43720
43865
|
type: "inkkitCommentBlock",
|
|
43866
|
+
block: false,
|
|
43721
43867
|
position: node.position
|
|
43722
43868
|
};
|
|
43723
43869
|
return node;
|
|
@@ -43757,7 +43903,7 @@ function commentNode(inline) {
|
|
|
43757
43903
|
runner: (state, node, type) => {
|
|
43758
43904
|
state.addNode(type, {
|
|
43759
43905
|
syntax: node.syntax,
|
|
43760
|
-
block: inline ? Boolean(node.block) :
|
|
43906
|
+
block: inline ? Boolean(node.block) : node.block !== false
|
|
43761
43907
|
}, node.value ? [state.schema.text(String(node.value))] : void 0);
|
|
43762
43908
|
}
|
|
43763
43909
|
},
|
|
@@ -43981,6 +44127,25 @@ async function resolveFile(adapter, reference, context) {
|
|
|
43981
44127
|
].includes(presentation.kind)) throw new TypeError("File presentation needs a resource URL");
|
|
43982
44128
|
return Object.freeze({ ...presentation });
|
|
43983
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
|
+
}
|
|
43984
44149
|
var FileResolution = class {
|
|
43985
44150
|
runtime;
|
|
43986
44151
|
changed;
|
|
@@ -43995,6 +44160,7 @@ var FileResolution = class {
|
|
|
43995
44160
|
}
|
|
43996
44161
|
update(reference) {
|
|
43997
44162
|
const key = JSON.stringify([
|
|
44163
|
+
reference.raw,
|
|
43998
44164
|
reference.reference,
|
|
43999
44165
|
reference.kind,
|
|
44000
44166
|
reference.fragment
|
|
@@ -44004,8 +44170,23 @@ var FileResolution = class {
|
|
|
44004
44170
|
this.key = key;
|
|
44005
44171
|
this.retry();
|
|
44006
44172
|
}
|
|
44173
|
+
/** Resolves again from a blank loading card. */
|
|
44007
44174
|
retry() {
|
|
44008
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;
|
|
44009
44190
|
if (this.dead || !this.reference || !this.runtime.active()) return;
|
|
44010
44191
|
const captured = this.runtime.capture();
|
|
44011
44192
|
const request = {
|
|
@@ -44013,18 +44194,21 @@ var FileResolution = class {
|
|
|
44013
44194
|
isCurrent: captured.isCurrent
|
|
44014
44195
|
};
|
|
44015
44196
|
this.request = request;
|
|
44016
|
-
|
|
44017
|
-
|
|
44197
|
+
if (blank) {
|
|
44198
|
+
this.state = { status: "loading" };
|
|
44199
|
+
this.changed();
|
|
44200
|
+
}
|
|
44018
44201
|
resolveFile(this.runtime.adapter, this.reference, {
|
|
44019
44202
|
...captured.context,
|
|
44020
44203
|
signal: request.controller.signal
|
|
44021
44204
|
}).then((presentation) => {
|
|
44022
44205
|
if (!this.current(request)) return;
|
|
44206
|
+
const before = this.state;
|
|
44023
44207
|
this.state = {
|
|
44024
44208
|
status: "resolved",
|
|
44025
44209
|
presentation
|
|
44026
44210
|
};
|
|
44027
|
-
this.changed();
|
|
44211
|
+
if (before.status !== "resolved" || !samePresentation(before.presentation, presentation)) this.changed();
|
|
44028
44212
|
}, (failure) => {
|
|
44029
44213
|
if (!this.current(request)) return;
|
|
44030
44214
|
const error = coded(failure, "file-unavailable");
|
|
@@ -44135,7 +44319,7 @@ function nodeText(node, missingImages, fileDescriptions) {
|
|
|
44135
44319
|
if (node.type.name === "image") {
|
|
44136
44320
|
const description = fileDescriptions.get(node.attrs);
|
|
44137
44321
|
if (description != null) return description;
|
|
44138
|
-
const alt =
|
|
44322
|
+
const alt = fileFields(node).label || "Image";
|
|
44139
44323
|
return missingImages.has(String(node.attrs.src ?? "")) ? `[${alt}: image unavailable]` : alt;
|
|
44140
44324
|
}
|
|
44141
44325
|
if (node.type.name === "table") {
|
|
@@ -44149,7 +44333,9 @@ function nodeText(node, missingImages, fileDescriptions) {
|
|
|
44149
44333
|
}
|
|
44150
44334
|
return clipboardText(node.content, missingImages, fileDescriptions);
|
|
44151
44335
|
}
|
|
44152
|
-
|
|
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) {
|
|
44153
44339
|
content = shareableFragment(content);
|
|
44154
44340
|
const container = document.createElement("div");
|
|
44155
44341
|
const serializer = DOMSerializer.fromSchema(schema);
|
|
@@ -44162,7 +44348,7 @@ function clipboardDOM(content, schema) {
|
|
|
44162
44348
|
}]
|
|
44163
44349
|
}, {
|
|
44164
44350
|
...serializer.marks,
|
|
44165
|
-
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]
|
|
44166
44352
|
});
|
|
44167
44353
|
container.append(safe.serializeFragment(content));
|
|
44168
44354
|
if (!onlyDefinitions(content)) for (const definition of container.querySelectorAll("[data-inkkit-reference-definition]")) definition.remove();
|
|
@@ -44181,18 +44367,18 @@ function clipboardDOM(content, schema) {
|
|
|
44181
44367
|
}
|
|
44182
44368
|
return container;
|
|
44183
44369
|
}
|
|
44184
|
-
function clipboardContent(content, schema) {
|
|
44370
|
+
function clipboardContent(content, schema, linkSchemes) {
|
|
44185
44371
|
return {
|
|
44186
44372
|
text: clipboardText(content),
|
|
44187
|
-
html: clipboardDOM(content, schema).innerHTML
|
|
44373
|
+
html: clipboardDOM(content, schema, linkSchemes).innerHTML
|
|
44188
44374
|
};
|
|
44189
44375
|
}
|
|
44190
|
-
function clipboardSerializer(schema) {
|
|
44376
|
+
function clipboardSerializer(schema, linkSchemes) {
|
|
44191
44377
|
const serializer = DOMSerializer.fromSchema(schema);
|
|
44192
44378
|
const safe = new DOMSerializer(serializer.nodes, serializer.marks);
|
|
44193
44379
|
safe.serializeFragment = (content, options = {}, target) => {
|
|
44194
44380
|
const output = target ?? (options.document ?? document).createDocumentFragment();
|
|
44195
|
-
output.append(...clipboardDOM(content, schema).childNodes);
|
|
44381
|
+
output.append(...clipboardDOM(content, schema, linkSchemes).childNodes);
|
|
44196
44382
|
return output;
|
|
44197
44383
|
};
|
|
44198
44384
|
return safe;
|
|
@@ -44200,15 +44386,15 @@ function clipboardSerializer(schema) {
|
|
|
44200
44386
|
var visibleClipboard = $prose((ctx) => new Plugin({
|
|
44201
44387
|
key: new PluginKey("visibleClipboard"),
|
|
44202
44388
|
props: {
|
|
44203
|
-
clipboardSerializer: clipboardSerializer(ctx.get(schemaCtx)),
|
|
44389
|
+
clipboardSerializer: clipboardSerializer(ctx.get(schemaCtx), editorLinkSchemes(ctx)),
|
|
44204
44390
|
clipboardTextSerializer: (slice) => clipboardText(slice.content)
|
|
44205
44391
|
}
|
|
44206
44392
|
}));
|
|
44207
44393
|
/** Export a frozen document fragment; presentation URLs never enter the clipboard. */
|
|
44208
|
-
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) {
|
|
44209
44395
|
signal.throwIfAborted();
|
|
44210
44396
|
content = shareableFragment(content);
|
|
44211
|
-
const base = clipboardContent(content, schema);
|
|
44397
|
+
const base = clipboardContent(content, schema, linkSchemes);
|
|
44212
44398
|
const container = document.createElement("div");
|
|
44213
44399
|
container.innerHTML = base.html;
|
|
44214
44400
|
const images = [];
|
|
@@ -44220,7 +44406,7 @@ async function portableClipboard(content, schema, markdown, adapter, context, co
|
|
|
44220
44406
|
const captured = [...container.querySelectorAll("img")].map((element, index) => {
|
|
44221
44407
|
const node = references[index];
|
|
44222
44408
|
const reference = String(node?.attrs.src ?? "");
|
|
44223
|
-
const { label: authoredAlt, width } =
|
|
44409
|
+
const { label: authoredAlt, width } = fileFields(node);
|
|
44224
44410
|
const alt = authoredAlt || "Image";
|
|
44225
44411
|
if (width != null && width > 0) element.setAttribute("width", String(Math.min(4096, width)));
|
|
44226
44412
|
element.removeAttribute("src");
|
|
@@ -44483,7 +44669,7 @@ function isHTMLElement(node) {
|
|
|
44483
44669
|
return isElement(node) && node.namespaceURI === "http://www.w3.org/1999/xhtml";
|
|
44484
44670
|
}
|
|
44485
44671
|
//#endregion
|
|
44486
|
-
//#region node_modules/.pnpm/prosemirror-drop-indicator@0.1.
|
|
44672
|
+
//#region node_modules/.pnpm/prosemirror-drop-indicator@0.1.4_patch_hash=4afd7e652c59a5f25f8ecc7b74d6370bde7273ee46a28766df1490663f928940/node_modules/prosemirror-drop-indicator/dist/index.js
|
|
44487
44673
|
function getTargetsByView(view) {
|
|
44488
44674
|
const stack = [[-1, view.state.doc]];
|
|
44489
44675
|
const targets = [];
|
|
@@ -44639,6 +44825,8 @@ function createDropIndicatorView(view, getTarget, options) {
|
|
|
44639
44825
|
let hasDragOverEvent = false;
|
|
44640
44826
|
const scheduleHide = () => {
|
|
44641
44827
|
if (hideId) clearTimeout(hideId);
|
|
44828
|
+
prevX = void 0;
|
|
44829
|
+
prevY = void 0;
|
|
44642
44830
|
hasDragOverEvent = false;
|
|
44643
44831
|
hideId = setTimeout(() => {
|
|
44644
44832
|
if (hasDragOverEvent) return;
|
|
@@ -44679,6 +44867,7 @@ function createDropIndicatorView(view, getTarget, options) {
|
|
|
44679
44867
|
dom.addEventListener("drop", scheduleHide);
|
|
44680
44868
|
dom.addEventListener("dragleave", scheduleHide);
|
|
44681
44869
|
const destroy = () => {
|
|
44870
|
+
if (hideId) clearTimeout(hideId);
|
|
44682
44871
|
dom.removeEventListener("dragover", handleDragOver);
|
|
44683
44872
|
dom.removeEventListener("dragend", scheduleHide);
|
|
44684
44873
|
dom.removeEventListener("drop", scheduleHide);
|
|
@@ -44820,10 +45009,82 @@ var cursor = [
|
|
|
44820
45009
|
//#endregion
|
|
44821
45010
|
//#region src/text-input.ts
|
|
44822
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
|
+
}
|
|
44823
45026
|
/**
|
|
44824
|
-
*
|
|
44825
|
-
*
|
|
44826
|
-
*
|
|
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.
|
|
44827
45088
|
*
|
|
44828
45089
|
* Input rules are written for one typed character: Milkdown's take their
|
|
44829
45090
|
* positions from the document before the text goes in, so given more than
|
|
@@ -44831,19 +45092,25 @@ var isInputRules = (plugin) => plugin.spec.isInputRules === true;
|
|
|
44831
45092
|
* in except for its last character, and the input rules see that character
|
|
44832
45093
|
* typed after the rest, all in one transaction.
|
|
44833
45094
|
*/
|
|
44834
|
-
function
|
|
45095
|
+
function insertTypedText(view, from, to, text, deflt) {
|
|
44835
45096
|
const characters = Array.from(text);
|
|
44836
|
-
if (characters.length
|
|
45097
|
+
if (!characters.length || view.composing || /[\r\n]/.test(text)) return false;
|
|
44837
45098
|
const { state } = view;
|
|
44838
|
-
const
|
|
44839
|
-
|
|
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);
|
|
44840
45106
|
const last = characters.at(-1);
|
|
44841
45107
|
const rest = text.slice(0, -last.length);
|
|
44842
|
-
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);
|
|
44843
45110
|
const $at = Selection.near(tr.doc.resolve(tr.mapping.map(to)), -1).$head;
|
|
44844
45111
|
const at = $at.pos;
|
|
44845
45112
|
if (!$at.parent.inlineContent || $at.parent.type.spec.code || $at.parentOffset < rest.length || $at.parent.textBetween($at.parentOffset - rest.length, $at.parentOffset) !== rest) {
|
|
44846
|
-
view.dispatch(
|
|
45113
|
+
view.dispatch(fallback().scrollIntoView());
|
|
44847
45114
|
return true;
|
|
44848
45115
|
}
|
|
44849
45116
|
const rules = state.plugins.filter(isInputRules);
|
|
@@ -44851,7 +45118,7 @@ function insertTextChunk(view, from, to, text, deflt) {
|
|
|
44851
45118
|
schema: state.schema,
|
|
44852
45119
|
doc: tr.doc,
|
|
44853
45120
|
selection: TextSelection.create(tr.doc, at),
|
|
44854
|
-
storedMarks:
|
|
45121
|
+
storedMarks: typing && typing.linked < text.length ? typing.link.removeFromSet(marks) : marks
|
|
44855
45122
|
}, rest);
|
|
44856
45123
|
let ruled;
|
|
44857
45124
|
const preparedView = Object.create(view, {
|
|
@@ -44861,7 +45128,7 @@ function insertTextChunk(view, from, to, text, deflt) {
|
|
|
44861
45128
|
} }
|
|
44862
45129
|
});
|
|
44863
45130
|
if (!rules.some((rule) => rule.props.handleTextInput?.call(rule, preparedView, at, at, last, () => prepared.tr.insertText(last, at)))) {
|
|
44864
|
-
const plain =
|
|
45131
|
+
const plain = fallback().scrollIntoView();
|
|
44865
45132
|
view.dispatch(last === "-" ? insertedHyphen(plain) : plain);
|
|
44866
45133
|
return true;
|
|
44867
45134
|
}
|
|
@@ -44869,6 +45136,7 @@ function insertTextChunk(view, from, to, text, deflt) {
|
|
|
44869
45136
|
for (const step of ruled.steps) tr.step(step);
|
|
44870
45137
|
tr.setSelection(ruled.selection.map(tr.doc, StepMap.empty));
|
|
44871
45138
|
if (ruled.storedMarksSet) tr.setStoredMarks(ruled.storedMarks);
|
|
45139
|
+
else if (typing?.stored) tr.setStoredMarks(typing.stored);
|
|
44872
45140
|
for (const rule of rules) {
|
|
44873
45141
|
const meta = ruled.getMeta(rule);
|
|
44874
45142
|
if (meta !== void 0) tr.setMeta(rule, meta);
|
|
@@ -44877,6 +45145,65 @@ function insertTextChunk(view, from, to, text, deflt) {
|
|
|
44877
45145
|
view.dispatch(tr.scrollIntoView());
|
|
44878
45146
|
return true;
|
|
44879
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
|
+
}
|
|
44880
45207
|
//#endregion
|
|
44881
45208
|
//#region src/drop-placement.ts
|
|
44882
45209
|
/**
|
|
@@ -44992,6 +45319,20 @@ function caretAfterInsertion(tr, view) {
|
|
|
44992
45319
|
return tr.setSelection($end.parent.inlineContent ? TextSelection.create(tr.doc, end) : caretAfter(tr.doc, end, view && calloutFolds(view, tr)));
|
|
44993
45320
|
}
|
|
44994
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
|
|
44995
45336
|
//#region src/code-fences.ts
|
|
44996
45337
|
function readFence(value) {
|
|
44997
45338
|
if (typeof value !== "object" || value == null) return null;
|
|
@@ -45383,10 +45724,11 @@ var formatting = /* @__PURE__ */ new Set([
|
|
|
45383
45724
|
"delete",
|
|
45384
45725
|
"highlight"
|
|
45385
45726
|
]);
|
|
45727
|
+
var linkTypes = /* @__PURE__ */ new Set(["link", "linkReference"]);
|
|
45386
45728
|
function ordered(node) {
|
|
45387
45729
|
let current = node;
|
|
45388
45730
|
const inner = current.children?.[0];
|
|
45389
|
-
if (current.type
|
|
45731
|
+
if (linkTypes.has(current.type) && current.children.length === 1 && formatting.has(inner.type)) current = {
|
|
45390
45732
|
...inner,
|
|
45391
45733
|
children: [{
|
|
45392
45734
|
...current,
|
|
@@ -45398,6 +45740,32 @@ function ordered(node) {
|
|
|
45398
45740
|
children: current.children.map(ordered)
|
|
45399
45741
|
} : current;
|
|
45400
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
|
+
}
|
|
45401
45769
|
/** Where the delimiter row ends, given where the header row before it ends. */
|
|
45402
45770
|
function delimiterRowEnd(text, headerEnd) {
|
|
45403
45771
|
const next = text.indexOf("\n", headerEnd);
|
|
@@ -45406,15 +45774,17 @@ function delimiterRowEnd(text, headerEnd) {
|
|
|
45406
45774
|
ending.lastIndex = next + 1;
|
|
45407
45775
|
return ending.exec(text)?.index ?? text.length;
|
|
45408
45776
|
}
|
|
45409
|
-
function ownShape(node) {
|
|
45777
|
+
function ownShape(node, spreadless = false) {
|
|
45410
45778
|
return JSON.stringify(ordered(node), (key, value) => [
|
|
45411
45779
|
"position",
|
|
45412
45780
|
"data",
|
|
45413
45781
|
"children",
|
|
45414
45782
|
"value",
|
|
45415
45783
|
"marker"
|
|
45416
|
-
].includes(key) ? void 0 : value);
|
|
45784
|
+
].includes(key) || spreadless && key === "spread" ? void 0 : value);
|
|
45417
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);
|
|
45418
45788
|
var matchShape = (node) => ownShape({
|
|
45419
45789
|
...node,
|
|
45420
45790
|
checked: void 0
|
|
@@ -45471,10 +45841,25 @@ function authoredMarker(list, source) {
|
|
|
45471
45841
|
return at == null ? void 0 : markerAt(source, at)?.marker;
|
|
45472
45842
|
}
|
|
45473
45843
|
var sameList = (before, after) => before.type === "list" && after.type === "list" && before.ordered === after.ordered;
|
|
45474
|
-
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) {
|
|
45475
45860
|
let text = canonical.slice(from, to);
|
|
45476
45861
|
const offsets = (list) => (list.children ?? []).map((item) => item.position.start.offset - from);
|
|
45477
|
-
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);
|
|
45478
45863
|
children.forEach((child, index) => {
|
|
45479
45864
|
if (child.type !== "list") {
|
|
45480
45865
|
previous = void 0;
|
|
@@ -45482,19 +45867,24 @@ function canonicalSlice(marker, children, canonical, from, to, previous, next) {
|
|
|
45482
45867
|
}
|
|
45483
45868
|
const avoid = [previous, index === children.length - 1 ? next : void 0].filter((neighbour) => neighbour?.ordered === child.ordered).map((neighbour) => neighbour.marker);
|
|
45484
45869
|
const own = markerAt(canonical, child.children[0].position.start.offset)?.marker;
|
|
45485
|
-
const choice = [
|
|
45486
|
-
|
|
45487
|
-
|
|
45488
|
-
"
|
|
45489
|
-
|
|
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));
|
|
45490
45879
|
if (choice) text = relabel(text, offsets(child), choice);
|
|
45491
45880
|
previous = {
|
|
45492
45881
|
ordered: child.ordered,
|
|
45493
45882
|
marker: choice ?? own ?? ""
|
|
45494
45883
|
};
|
|
45495
45884
|
});
|
|
45496
|
-
return text;
|
|
45885
|
+
return regutter(text, gutters, open);
|
|
45497
45886
|
}
|
|
45887
|
+
var itemMarker = (item, source) => item.type === "listItem" ? markerAt(source, item.position.start.offset)?.marker : void 0;
|
|
45498
45888
|
function authoredNeighbour(before, after, source) {
|
|
45499
45889
|
if (!before || !after || !sameList(before, after)) return void 0;
|
|
45500
45890
|
const marker = authoredMarker(before, source);
|
|
@@ -45594,35 +45984,90 @@ function retainSplit(candidates, after, source, canonical, lineEnding, taken) {
|
|
|
45594
45984
|
text: retainSource(part, after, source, canonical, lineEnding)
|
|
45595
45985
|
};
|
|
45596
45986
|
}
|
|
45597
|
-
function
|
|
45598
|
-
|
|
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) {
|
|
45599
46016
|
const taken = /* @__PURE__ */ new Set();
|
|
45600
46017
|
const opening = (item) => item.children?.length ? matchShape(item) + signature(item.children[0]) : void 0;
|
|
45601
|
-
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) => {
|
|
45602
46041
|
const end = child.position.end.offset;
|
|
45603
46042
|
if (child.type === "list" || child.type === "blockquote") {
|
|
45604
46043
|
const part = retainSplit(before, child, source, canonical, lineEnding, taken);
|
|
45605
46044
|
if (part) return part.text + canonical.slice(child.children.at(-1).position.end.offset, end);
|
|
45606
46045
|
const lists = before.filter((node) => node.type === "list" && node.ordered === child.ordered);
|
|
45607
|
-
|
|
45608
|
-
|
|
45609
|
-
|
|
45610
|
-
|
|
45611
|
-
|
|
45612
|
-
|
|
45613
|
-
|
|
45614
|
-
|
|
45615
|
-
|
|
45616
|
-
|
|
45617
|
-
|
|
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);
|
|
45618
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;
|
|
45619
46063
|
}
|
|
45620
|
-
|
|
45621
|
-
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;
|
|
45622
46067
|
return text !== void 0 && marker ? relabel(text, [0], marker) : text;
|
|
45623
46068
|
});
|
|
45624
46069
|
if (pieces.every((piece) => piece === void 0)) return void 0;
|
|
45625
|
-
let text = "", at = from;
|
|
46070
|
+
let text = "", at = from, lastNumber;
|
|
45626
46071
|
after.forEach((child, index) => {
|
|
45627
46072
|
const childStart = child.position.start.offset;
|
|
45628
46073
|
const childEnd = child.position.end.offset;
|
|
@@ -45630,15 +46075,18 @@ function retainParts(marker, before, after, source, canonical, from, to, lineEnd
|
|
|
45630
46075
|
let piece = pieces[index];
|
|
45631
46076
|
const own = piece && markerAt(piece, 0)?.marker;
|
|
45632
46077
|
if (child.type === "list" && [previous, following].some((neighbour) => neighbour?.ordered === child.ordered && neighbour?.marker === own)) piece = void 0;
|
|
45633
|
-
|
|
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;
|
|
45634
46082
|
previous = child.type === "list" ? {
|
|
45635
46083
|
ordered: child.ordered,
|
|
45636
46084
|
marker: markerAt(piece, /^[ \t]*/.exec(piece)[0].length)?.marker ?? ""
|
|
45637
46085
|
} : void 0;
|
|
45638
|
-
text += canonical.slice(at, childStart) + piece;
|
|
46086
|
+
text += regutter(canonical.slice(at, childStart), gutters, true) + piece;
|
|
45639
46087
|
at = childEnd;
|
|
45640
46088
|
});
|
|
45641
|
-
return text + canonical.slice(at, to);
|
|
46089
|
+
return text + regutter(canonical.slice(at, to), gutters, open);
|
|
45642
46090
|
}
|
|
45643
46091
|
function decodedOffsets(raw, lines = false) {
|
|
45644
46092
|
const offsets = [0];
|
|
@@ -45646,7 +46094,7 @@ function decodedOffsets(raw, lines = false) {
|
|
|
45646
46094
|
for (let index = 0; index < raw.length;) {
|
|
45647
46095
|
const rest = raw.slice(index);
|
|
45648
46096
|
const line = /[ \t]/.test(raw[index - 1] ?? "") && /[ \t]/.test(raw[index]) ? void 0 : /^[ \t]*(?:\r\n?|\n)(?:[ \t]*>)*[ \t]*/.exec(rest)?.[0];
|
|
45649
|
-
|
|
46097
|
+
let token = line ?? /^\\[!"#$%&'()*+,\-./:;<=>?@[\]\\^_`{|}~]/.exec(rest)?.[0] ?? /^&(?:#[xX][\da-fA-F]+|#\d+|[A-Za-z][A-Za-z\d]+);/.exec(rest)?.[0];
|
|
45650
46098
|
let value = raw[index];
|
|
45651
46099
|
if (line) {
|
|
45652
46100
|
if (!lines) return void 0;
|
|
@@ -45655,7 +46103,8 @@ function decodedOffsets(raw, lines = false) {
|
|
|
45655
46103
|
else if (token) {
|
|
45656
46104
|
const element = document.createElement("textarea");
|
|
45657
46105
|
element.innerHTML = token;
|
|
45658
|
-
value =
|
|
46106
|
+
if (element.value === token) token = void 0;
|
|
46107
|
+
else value = element.value;
|
|
45659
46108
|
}
|
|
45660
46109
|
index += token?.length ?? 1;
|
|
45661
46110
|
decoded += value;
|
|
@@ -45772,7 +46221,10 @@ function retainRun(before, after, source, canonical, [from, to], [newFrom, newTo
|
|
|
45772
46221
|
}
|
|
45773
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));
|
|
45774
46223
|
}
|
|
45775
|
-
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;
|
|
45776
46228
|
before = lf(before);
|
|
45777
46229
|
after = lf(after);
|
|
45778
46230
|
let prefix = 0;
|
|
@@ -45782,15 +46234,42 @@ function retainText(raw, before, after, inTable = false, written, beside = [fals
|
|
|
45782
46234
|
const read = decodedOffsets(raw, true);
|
|
45783
46235
|
if (read?.decoded !== before) return after;
|
|
45784
46236
|
const { offsets } = read;
|
|
46237
|
+
const lineStart = after.lastIndexOf("\n", prefix - 1) + 1;
|
|
46238
|
+
if (lineStart > 0 && written !== void 0) {
|
|
46239
|
+
const canonical = decodedOffsets(written, true);
|
|
46240
|
+
if (canonical?.decoded === after) {
|
|
46241
|
+
const opening = written.slice(canonical.offsets[lineStart]);
|
|
46242
|
+
const marker = /^(?:\d+)?\\[#+.\->)]/.exec(opening)?.[0];
|
|
46243
|
+
if (marker && prefix - lineStart <= decodedOffsets(marker).decoded.length) {
|
|
46244
|
+
prefix = lineStart;
|
|
46245
|
+
return raw.slice(0, offsets[prefix]) + guttered(written.slice(canonical.offsets[prefix], canonical.offsets[after.length - suffix])) + raw.slice(offsets[before.length - suffix]);
|
|
46246
|
+
}
|
|
46247
|
+
}
|
|
46248
|
+
}
|
|
45785
46249
|
if (written !== void 0 && (beside[0] && prefix === 0 || beside[1] && suffix === 0)) {
|
|
45786
46250
|
const writtenOffsets = decodedOffsets(written);
|
|
45787
|
-
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]);
|
|
45788
46252
|
}
|
|
45789
46253
|
const inserted = after.slice(prefix, after.length - suffix).split("").map((character, index) => {
|
|
45790
46254
|
const at = prefix + index;
|
|
45791
|
-
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;
|
|
45792
46256
|
}).join("");
|
|
45793
|
-
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);
|
|
45794
46273
|
}
|
|
45795
46274
|
function retainBoundaryText(raw, canonical, afterBreak = false) {
|
|
45796
46275
|
if (afterBreak) {
|
|
@@ -45987,6 +46466,7 @@ function markLiterals(raw, transformed, blocks = []) {
|
|
|
45987
46466
|
raw.children.forEach(mark);
|
|
45988
46467
|
}
|
|
45989
46468
|
function retainSource(before, after, source, canonical, lineEnding, inTable = false, width, beside = [false, false], joined = [], reorder, afterBreak = false) {
|
|
46469
|
+
after = authoredNesting(before, after);
|
|
45990
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);
|
|
45991
46471
|
if (before.type === "list" && after.type === "list" && before.ordered && after.ordered && !numbered.has(before) && before.position?.start.offset != null) {
|
|
45992
46472
|
const own = {
|
|
@@ -46083,15 +46563,20 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
46083
46563
|
const to = first.position.end.offset - start;
|
|
46084
46564
|
return retained.startsWith(source.slice(start, before.children[1].position.start.offset)) ? retained.slice(0, from) + "<br />" + retained.slice(to) : retained;
|
|
46085
46565
|
}
|
|
46086
|
-
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);
|
|
46087
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
|
+
}
|
|
46088
46572
|
const marker = sameList(before, after) ? authoredMarker(before, source) : void 0;
|
|
46089
46573
|
const located = (nodes) => nodes.every((node) => node.position?.start.offset != null);
|
|
46090
|
-
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)) {
|
|
46091
46575
|
let output = "", at = start;
|
|
46092
46576
|
let previous;
|
|
46093
46577
|
const same = (candidate, incoming) => signature(candidate) === signature(incoming) && ownShape(candidate) === ownShape(incoming);
|
|
46094
46578
|
const reorderable = before.type === "table" || before.type === "tableRow";
|
|
46579
|
+
const gutters = childGutters(before, after, source, canonical);
|
|
46095
46580
|
const moves = reorder?.get(parentKey(before));
|
|
46096
46581
|
const retained = new Set(reorderable ? before.children.flatMap((child, index) => same(child, after.children[index]) ? [index] : []) : []);
|
|
46097
46582
|
before.children.forEach((child, index) => {
|
|
@@ -46102,7 +46587,7 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
46102
46587
|
if (movedIndex >= 0) retained.add(movedIndex);
|
|
46103
46588
|
const childStart = child.position?.start.offset, childEnd = child.position?.end.offset;
|
|
46104
46589
|
if (childStart == null || childEnd == null) throw new PreservationError("A source token has no location");
|
|
46105
|
-
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");
|
|
46106
46591
|
if (before.type === "tableRow" && movedIndex >= 0 && movedIndex !== index) {
|
|
46107
46592
|
const originalFrom = original.children?.[0]?.position?.start.offset;
|
|
46108
46593
|
const originalTo = original.children?.at(-1)?.position?.end.offset;
|
|
@@ -46121,7 +46606,7 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
46121
46606
|
});
|
|
46122
46607
|
return output + source.slice(at, end);
|
|
46123
46608
|
}
|
|
46124
|
-
if (before.type === after.type &&
|
|
46609
|
+
if (before.type === after.type && sameShape(before, after) && before.children && after.children) {
|
|
46125
46610
|
let prefix = 0, suffix = 0;
|
|
46126
46611
|
while (prefix < before.children.length && prefix < after.children.length && signature(before.children[prefix]) === signature(after.children[prefix])) prefix++;
|
|
46127
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++;
|
|
@@ -46146,13 +46631,15 @@ function retainSource(before, after, source, canonical, lineEnding, inTable = fa
|
|
|
46146
46631
|
const changes = after.children.slice(prefix, after.children.length - suffix);
|
|
46147
46632
|
const previous = authoredNeighbour(before.children[prefix - 1], after.children[prefix - 1], source);
|
|
46148
46633
|
const next = authoredNeighbour(before.children[before.children.length - suffix], after.children[after.children.length - suffix], source);
|
|
46149
|
-
|
|
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);
|
|
46150
46637
|
}
|
|
46151
46638
|
}
|
|
46152
46639
|
const lastAfter = after.children?.at(-1)?.position?.end.offset;
|
|
46153
46640
|
const lastBefore = before.children?.at(-1)?.position?.end.offset;
|
|
46154
46641
|
const trailing = marker != null && lastAfter != null && lastBefore != null && loose(before, source) === loose(after, canonical);
|
|
46155
|
-
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) : "");
|
|
46156
46643
|
}
|
|
46157
46644
|
function loose(list, text) {
|
|
46158
46645
|
const blank = (from, to) => from != null && to != null && /\n[ \t>]*\r?\n/.test(text.slice(from, to));
|
|
@@ -46249,6 +46736,13 @@ function semanticSignature(doc) {
|
|
|
46249
46736
|
attrs
|
|
46250
46737
|
};
|
|
46251
46738
|
}
|
|
46739
|
+
if (value.type === "comment_block" && value.attrs) {
|
|
46740
|
+
const { block: _block, ...attrs } = value.attrs;
|
|
46741
|
+
value = {
|
|
46742
|
+
...value,
|
|
46743
|
+
attrs
|
|
46744
|
+
};
|
|
46745
|
+
}
|
|
46252
46746
|
const content = value.content;
|
|
46253
46747
|
if (!content) return value;
|
|
46254
46748
|
const tokens = [];
|
|
@@ -46291,6 +46785,7 @@ function semanticSignature(doc) {
|
|
|
46291
46785
|
"authoredFence",
|
|
46292
46786
|
"form",
|
|
46293
46787
|
"inkkitFileRaw",
|
|
46788
|
+
"inkkitFileSource",
|
|
46294
46789
|
"inkkitFileWidth",
|
|
46295
46790
|
"inkkitFileInTable"
|
|
46296
46791
|
].includes(key) ? void 0 : value));
|
|
@@ -46502,7 +46997,7 @@ var Preservation = class Preservation {
|
|
|
46502
46997
|
try {
|
|
46503
46998
|
const parse = (text) => parseDoc(ctx, text);
|
|
46504
46999
|
this.baseline = parse(source);
|
|
46505
|
-
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";
|
|
46506
47001
|
const processor = ctx.get(remarkCtx);
|
|
46507
47002
|
const offset = source.startsWith("") ? 1 : 0;
|
|
46508
47003
|
const body = source.slice(offset);
|
|
@@ -46597,6 +47092,9 @@ var Preservation = class Preservation {
|
|
|
46597
47092
|
const indent = source.slice(source.lastIndexOf("\n", part.from - 1) + 1, part.from);
|
|
46598
47093
|
return (/^[ \t]*$/.test(indent) ? indent : "") + part.text;
|
|
46599
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
|
+
}
|
|
46600
47098
|
localEdits(doc) {
|
|
46601
47099
|
if (this.baseline.childCount !== this.blocks.length || doc.childCount !== this.blocks.length || !doc.sameMarkup(this.baseline)) return void 0;
|
|
46602
47100
|
let output = "", previous = 0;
|
|
@@ -47011,7 +47509,7 @@ var Preservation = class Preservation {
|
|
|
47011
47509
|
const kind = block && block.form === text && !carried.within.has(index) ? position == null ? "moved" : "unchanged" : block && tree && position != null ? "edited" : "canonical";
|
|
47012
47510
|
kept.push(kind);
|
|
47013
47511
|
const node = tree ? positionalNode(tree.raw, transformed(index)) : void 0;
|
|
47014
|
-
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)));
|
|
47015
47513
|
}
|
|
47016
47514
|
return {
|
|
47017
47515
|
gaps,
|
|
@@ -47547,23 +48045,6 @@ function completedAngle(tr, chars, from, to) {
|
|
|
47547
48045
|
form: "angle"
|
|
47548
48046
|
})).removeStoredMark(tr.doc.type.schema.marks.link);
|
|
47549
48047
|
}
|
|
47550
|
-
function closeAngleEnds(tr, transactions) {
|
|
47551
|
-
const steps = transactions.flatMap((transaction) => transaction.steps.map((step, index) => ({
|
|
47552
|
-
doc: transaction.docs[index],
|
|
47553
|
-
map: step.getMap()
|
|
47554
|
-
})));
|
|
47555
|
-
steps.forEach(({ doc, map }, index) => {
|
|
47556
|
-
const remaining = new Mapping(steps.slice(index + 1).map(({ map }) => map));
|
|
47557
|
-
map.forEach((from, to, start, end) => {
|
|
47558
|
-
if (from !== to || start === end) return;
|
|
47559
|
-
const at = doc.resolve(from);
|
|
47560
|
-
const before = at.nodeBefore?.marks.find((mark) => mark.attrs.form === "angle");
|
|
47561
|
-
const after = at.nodeAfter?.marks.find((mark) => mark.attrs.form === "angle");
|
|
47562
|
-
if (before && after && before.eq(after)) return;
|
|
47563
|
-
for (const mark of [before, after]) if (mark) tr.removeMark(remaining.map(start, 1), remaining.map(end, -1), mark);
|
|
47564
|
-
});
|
|
47565
|
-
});
|
|
47566
|
-
}
|
|
47567
48048
|
function codeAngles(tr, edited) {
|
|
47568
48049
|
const spans = [];
|
|
47569
48050
|
for (const block of edited) tr.doc.nodesBetween(block.pos, block.pos + block.block.nodeSize, (node, pos) => {
|
|
@@ -47772,10 +48253,7 @@ var autolinkLiterals = $prose((ctx) => new Plugin({
|
|
|
47772
48253
|
if (!transactions.some((tr) => tr.docChanged)) return null;
|
|
47773
48254
|
const base = newState.tr;
|
|
47774
48255
|
const written = transactions.every(isWrittenEdit);
|
|
47775
|
-
if (written)
|
|
47776
|
-
closeAngleEnds(base, transactions);
|
|
47777
|
-
codeAngles(base, editedBlocks(oldState.doc, base.doc));
|
|
47778
|
-
}
|
|
48256
|
+
if (written) codeAngles(base, editedBlocks(oldState.doc, base.doc));
|
|
47779
48257
|
let edited = editedBlocks(oldState.doc, base.doc);
|
|
47780
48258
|
if (written && edited.length === 1) {
|
|
47781
48259
|
const { pos, block, from, to } = edited[0];
|
|
@@ -48144,7 +48622,8 @@ function remarkCallouts() {
|
|
|
48144
48622
|
const visit = (node) => {
|
|
48145
48623
|
if (node.type === "blockquote") {
|
|
48146
48624
|
const start = node.position?.start.offset, end = node.position?.end.offset;
|
|
48147
|
-
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);
|
|
48148
48627
|
const header = /^>[ \t]*([\s\S]*?)(?:\r?\n|$)/.exec(raw)?.[1] ?? "";
|
|
48149
48628
|
if (header.startsWith("[!")) {
|
|
48150
48629
|
const match = /^(\[!([A-Za-z]+)\])([+-]?)(?:[ \t]+([^\r\n]*))?$/.exec(header);
|
|
@@ -48316,7 +48795,7 @@ var calloutView = $prose((ctx) => new Plugin({
|
|
|
48316
48795
|
const render = () => {
|
|
48317
48796
|
title.textContent = node.attrs.title || String(node.attrs.kind).toLowerCase().replace(/^./, (letter) => letter.toUpperCase());
|
|
48318
48797
|
dom.setAttribute("data-inkkit-folded", String(folded));
|
|
48319
|
-
view.dom.dispatchEvent(new Event(
|
|
48798
|
+
view.dom.dispatchEvent(new Event(mediaPolicyEvent));
|
|
48320
48799
|
button.hidden = !node.attrs.fold;
|
|
48321
48800
|
button.setAttribute("aria-expanded", String(!folded));
|
|
48322
48801
|
button.setAttribute("aria-label", `${folded ? editorLabels(ctx).expandCallout : editorLabels(ctx).collapseCallout} ${title.textContent}`);
|
|
@@ -50083,12 +50562,50 @@ function writesBare(node, index, ancestors) {
|
|
|
50083
50562
|
return side(-1) && side(1);
|
|
50084
50563
|
}
|
|
50085
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
|
+
}
|
|
50086
50602
|
var root = (node, parent, state, info) => {
|
|
50087
50603
|
bareLinks = /* @__PURE__ */ new WeakSet();
|
|
50088
50604
|
const empty = (child) => child.type === "text" && child.value === "" || wrappers.has(child.type) && "children" in child && child.children.every(empty);
|
|
50089
50605
|
const visit = (current, ancestors) => {
|
|
50090
50606
|
if (current.children.some((child) => empty(child))) current.children = current.children.filter((child) => !empty(child));
|
|
50091
50607
|
const children = current.children;
|
|
50608
|
+
shareFormatting(children);
|
|
50092
50609
|
children.forEach((child, index) => {
|
|
50093
50610
|
if (child.type === "link" && formOf(child)) {
|
|
50094
50611
|
const outside = formattedOutside(child);
|
|
@@ -50309,6 +50826,16 @@ var breaksWithoutMarks = $prose((ctx) => new Plugin({
|
|
|
50309
50826
|
}
|
|
50310
50827
|
}));
|
|
50311
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
|
+
};
|
|
50312
50839
|
var preserveSpacerParagraphs = paragraphSchema.extendSchema((base) => (ctx) => {
|
|
50313
50840
|
const schema = base(ctx);
|
|
50314
50841
|
return {
|
|
@@ -50439,7 +50966,16 @@ var normalizedImages = imageSchema.extendSchema((base) => (ctx) => {
|
|
|
50439
50966
|
...schema.toMarkdown,
|
|
50440
50967
|
runner(state, node) {
|
|
50441
50968
|
const raw = namedFileMarkdown(node, Boolean(node.attrs.inkkitFileInTable));
|
|
50442
|
-
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
|
+
}
|
|
50443
50979
|
state.addNode("image", void 0, void 0, {
|
|
50444
50980
|
url: node.attrs.src,
|
|
50445
50981
|
alt: node.attrs.alt,
|
|
@@ -50447,7 +50983,7 @@ var normalizedImages = imageSchema.extendSchema((base) => (ctx) => {
|
|
|
50447
50983
|
inkkitFileRaw: raw,
|
|
50448
50984
|
inkkitFileTarget: node.attrs.inkkitFileTarget,
|
|
50449
50985
|
inkkitFileFragment: node.attrs.inkkitFileFragment,
|
|
50450
|
-
inkkitFileWidth:
|
|
50986
|
+
inkkitFileWidth: fileFields(node).width ?? null,
|
|
50451
50987
|
inkkitFileInTable: node.attrs.inkkitFileInTable
|
|
50452
50988
|
});
|
|
50453
50989
|
}
|
|
@@ -50560,6 +51096,7 @@ function createDialect(images, wikiLinks = false, files = false) {
|
|
|
50560
51096
|
remarkCodeFences,
|
|
50561
51097
|
remarkReferencesPlugin,
|
|
50562
51098
|
remarkLinkFormsPlugin,
|
|
51099
|
+
remarkFileSourcesPlugin,
|
|
50563
51100
|
remarkCalloutsPlugin,
|
|
50564
51101
|
remarkCommentsPlugin,
|
|
50565
51102
|
wikiLinks || files ? linkedSyntax(wikiLinks, files) : [],
|
|
@@ -50579,6 +51116,7 @@ function createDialect(images, wikiLinks = false, files = false) {
|
|
|
50579
51116
|
wikiLinkComposition,
|
|
50580
51117
|
wikiLinkInputRule
|
|
50581
51118
|
] : [],
|
|
51119
|
+
wikiLinks || files ? referenceTableContext : [],
|
|
50582
51120
|
callouts,
|
|
50583
51121
|
comments,
|
|
50584
51122
|
hiddenCommentEditing,
|
|
@@ -50606,7 +51144,8 @@ function createDialect(images, wikiLinks = false, files = false) {
|
|
|
50606
51144
|
remarkDialectPlugin,
|
|
50607
51145
|
tables,
|
|
50608
51146
|
literalBlock,
|
|
50609
|
-
checkedParser
|
|
51147
|
+
checkedParser,
|
|
51148
|
+
imageWriter
|
|
50610
51149
|
].flat();
|
|
50611
51150
|
}
|
|
50612
51151
|
createDialect(false);
|
|
@@ -51318,7 +51857,7 @@ var ImageView = class {
|
|
|
51318
51857
|
view;
|
|
51319
51858
|
getPos;
|
|
51320
51859
|
adapter;
|
|
51321
|
-
|
|
51860
|
+
host;
|
|
51322
51861
|
canMutate;
|
|
51323
51862
|
dom;
|
|
51324
51863
|
/** The card or picture, which a standalone image's block row holds. */
|
|
@@ -51330,22 +51869,30 @@ var ImageView = class {
|
|
|
51330
51869
|
stopResize;
|
|
51331
51870
|
resolution;
|
|
51332
51871
|
previewFailed = false;
|
|
51333
|
-
|
|
51872
|
+
/** Present when the host sets `files`, which then shows every image. */
|
|
51873
|
+
runtime;
|
|
51874
|
+
constructor(node, view, getPos, adapter, host, files, canMutate = () => true) {
|
|
51334
51875
|
this.node = node;
|
|
51335
51876
|
this.view = view;
|
|
51336
51877
|
this.getPos = getPos;
|
|
51337
51878
|
this.adapter = adapter;
|
|
51338
|
-
this.
|
|
51879
|
+
this.host = host;
|
|
51339
51880
|
this.canMutate = canMutate;
|
|
51881
|
+
const runtime = files && host && {
|
|
51882
|
+
...host,
|
|
51883
|
+
adapter: files
|
|
51884
|
+
};
|
|
51885
|
+
this.runtime = runtime;
|
|
51340
51886
|
this.element = document.createElement("span");
|
|
51341
51887
|
this.element.className = "inkkit-image";
|
|
51888
|
+
this.element.addEventListener("contextmenu", this.contextMenu);
|
|
51342
51889
|
if (node.isBlock) {
|
|
51343
51890
|
this.dom = document.createElement("div");
|
|
51344
51891
|
this.dom.className = "inkkit-image-block";
|
|
51345
51892
|
this.dom.append(this.element);
|
|
51346
51893
|
} else this.dom = this.element;
|
|
51347
51894
|
this.view.dom.addEventListener("inkkit-cancel-resize", this.cancelResize);
|
|
51348
|
-
this.view.dom.addEventListener(
|
|
51895
|
+
this.view.dom.addEventListener(mediaPolicyEvent, this.mediaPolicy);
|
|
51349
51896
|
if (runtime) {
|
|
51350
51897
|
this.resolution = new FileResolution({
|
|
51351
51898
|
...runtime,
|
|
@@ -51382,8 +51929,15 @@ var ImageView = class {
|
|
|
51382
51929
|
ignoreMutation() {
|
|
51383
51930
|
return true;
|
|
51384
51931
|
}
|
|
51385
|
-
mediaPolicy = () => {
|
|
51932
|
+
mediaPolicy = (event) => {
|
|
51386
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
|
+
}
|
|
51387
51941
|
if (!this.active()) {
|
|
51388
51942
|
this.stopResize?.();
|
|
51389
51943
|
this.stopResize = void 0;
|
|
@@ -51411,7 +51965,7 @@ var ImageView = class {
|
|
|
51411
51965
|
}
|
|
51412
51966
|
destroy() {
|
|
51413
51967
|
this.view.dom.removeEventListener("inkkit-cancel-resize", this.cancelResize);
|
|
51414
|
-
this.view.dom.removeEventListener(
|
|
51968
|
+
this.view.dom.removeEventListener(mediaPolicyEvent, this.mediaPolicy);
|
|
51415
51969
|
this.stopResize?.();
|
|
51416
51970
|
this.stopResize = void 0;
|
|
51417
51971
|
this.resolution?.destroy();
|
|
@@ -51440,6 +51994,37 @@ var ImageView = class {
|
|
|
51440
51994
|
report(error) {
|
|
51441
51995
|
this.runtime?.error?.(coded(error, "file-unavailable"));
|
|
51442
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
|
+
}
|
|
51443
52028
|
card(label, status, retry = false) {
|
|
51444
52029
|
const footer = document.createElement("span");
|
|
51445
52030
|
footer.className = "inkkit-file-footer";
|
|
@@ -51488,20 +52073,6 @@ var ImageView = class {
|
|
|
51488
52073
|
this.image = void 0;
|
|
51489
52074
|
if (this.runtime) {
|
|
51490
52075
|
this.element.classList.add("inkkit-file");
|
|
51491
|
-
this.element.oncontextmenu = (event) => {
|
|
51492
|
-
if (!this.runtime?.adapter.contextMenu || !this.active()) return;
|
|
51493
|
-
const captured = this.runtime.capture();
|
|
51494
|
-
if (!captured.isCurrent()) return;
|
|
51495
|
-
event.preventDefault();
|
|
51496
|
-
try {
|
|
51497
|
-
this.runtime.adapter.contextMenu(this.reference(), {
|
|
51498
|
-
clientX: event.clientX,
|
|
51499
|
-
clientY: event.clientY
|
|
51500
|
-
}, captured.context);
|
|
51501
|
-
} catch (error) {
|
|
51502
|
-
this.report(error);
|
|
51503
|
-
}
|
|
51504
|
-
};
|
|
51505
52076
|
const state = this.resolution.state;
|
|
51506
52077
|
const label = state.status === "resolved" ? state.presentation.label || alt || reference.reference : alt || reference.reference;
|
|
51507
52078
|
this.element.setAttribute("role", "group");
|
|
@@ -51650,8 +52221,8 @@ function openArrow() {
|
|
|
51650
52221
|
icon.append(path);
|
|
51651
52222
|
return icon;
|
|
51652
52223
|
}
|
|
51653
|
-
function imageView(adapter,
|
|
51654
|
-
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));
|
|
51655
52226
|
return [view(imageSchema), view(imageBlockSchema)];
|
|
51656
52227
|
}
|
|
51657
52228
|
//#endregion
|
|
@@ -51663,26 +52234,29 @@ function wikiLinkView(adapter, runtime) {
|
|
|
51663
52234
|
dom.className = "inkkit-wiki-link";
|
|
51664
52235
|
dom.setAttribute("role", "link");
|
|
51665
52236
|
dom.tabIndex = 0;
|
|
51666
|
-
const reference = () => (
|
|
51667
|
-
target: String(current.attrs.target),
|
|
51668
|
-
...current.attrs.fragment ? { fragment: String(current.attrs.fragment) } : {},
|
|
51669
|
-
label: String(current.attrs.label)
|
|
51670
|
-
});
|
|
52237
|
+
const reference = () => wikiReference(current);
|
|
51671
52238
|
const report = (error) => runtime.error?.(coded(error, "file-unavailable"));
|
|
51672
52239
|
const render = () => {
|
|
51673
|
-
|
|
51674
|
-
dom.
|
|
51675
|
-
|
|
51676
|
-
if (
|
|
51677
|
-
|
|
51678
|
-
|
|
51679
|
-
|
|
51680
|
-
|
|
51681
|
-
|
|
51682
|
-
|
|
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);
|
|
51683
52250
|
}
|
|
51684
|
-
}
|
|
51685
|
-
|
|
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");
|
|
51686
52260
|
}
|
|
51687
52261
|
};
|
|
51688
52262
|
const open = (event) => {
|
|
@@ -51701,7 +52275,11 @@ function wikiLinkView(adapter, runtime) {
|
|
|
51701
52275
|
dom.addEventListener("keydown", (event) => {
|
|
51702
52276
|
if (event.key === "Enter" || event.key === " ") open(event);
|
|
51703
52277
|
});
|
|
51704
|
-
|
|
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);
|
|
51705
52283
|
render();
|
|
51706
52284
|
return {
|
|
51707
52285
|
dom,
|
|
@@ -51716,7 +52294,7 @@ function wikiLinkView(adapter, runtime) {
|
|
|
51716
52294
|
},
|
|
51717
52295
|
ignoreMutation: () => true,
|
|
51718
52296
|
destroy() {
|
|
51719
|
-
view.dom.removeEventListener(
|
|
52297
|
+
view.dom.removeEventListener(mediaPolicyEvent, policy);
|
|
51720
52298
|
}
|
|
51721
52299
|
};
|
|
51722
52300
|
});
|
|
@@ -52787,7 +53365,7 @@ function readableProjection(doc) {
|
|
|
52787
53365
|
}
|
|
52788
53366
|
if (name === "image_block") {
|
|
52789
53367
|
block(position);
|
|
52790
|
-
append(
|
|
53368
|
+
append(fileFields(node).label || "Image", position, position + node.nodeSize, "embed");
|
|
52791
53369
|
return false;
|
|
52792
53370
|
}
|
|
52793
53371
|
if (node.isTextblock) {
|
|
@@ -52804,7 +53382,7 @@ function readableProjection(doc) {
|
|
|
52804
53382
|
return false;
|
|
52805
53383
|
}
|
|
52806
53384
|
if (name === "image" || name === "footnote_reference" || name === "inkkit_wiki_link") {
|
|
52807
|
-
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");
|
|
52808
53386
|
return false;
|
|
52809
53387
|
}
|
|
52810
53388
|
return true;
|
|
@@ -54056,6 +54634,96 @@ function htmlGrid(schema, html) {
|
|
|
54056
54634
|
};
|
|
54057
54635
|
}
|
|
54058
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
|
|
54059
54727
|
//#region src/paste.ts
|
|
54060
54728
|
var PasteController = class {
|
|
54061
54729
|
options;
|
|
@@ -54217,12 +54885,12 @@ var PasteController = class {
|
|
|
54217
54885
|
this.active = operation;
|
|
54218
54886
|
this.options.onPendingChanged?.();
|
|
54219
54887
|
try {
|
|
54220
|
-
const
|
|
54221
|
-
for (const file of files) images.push({
|
|
54888
|
+
const fromFiles = files.length ? distinctImages(await Promise.all(files.map(async (file) => ({
|
|
54222
54889
|
bytes: new Uint8Array(await file.arrayBuffer()),
|
|
54223
54890
|
mimeType: file.type,
|
|
54224
54891
|
filename: file.name
|
|
54225
|
-
});
|
|
54892
|
+
})))) : [];
|
|
54893
|
+
const images = distinctImages([...input.images ?? [], ...fromFiles]);
|
|
54226
54894
|
this.assertContext(context, operation);
|
|
54227
54895
|
const schema = view.state.schema;
|
|
54228
54896
|
let slice;
|
|
@@ -54241,8 +54909,7 @@ var PasteController = class {
|
|
|
54241
54909
|
}
|
|
54242
54910
|
const anchor = this.anchor(operation);
|
|
54243
54911
|
const start = view.state.doc.resolve(anchor.from);
|
|
54244
|
-
const
|
|
54245
|
-
const marks = view.state.storedMarks ?? (anchor.from === anchor.to ? start.marks() : start.marksAcross(end)) ?? [];
|
|
54912
|
+
const marks = replacementMarks(view.state, anchor.from, anchor.to);
|
|
54246
54913
|
const nodes = literalTextNodes(schema, input.text, marks, htmlBreakAt(start));
|
|
54247
54914
|
slice = new Slice(Fragment.from(schema.nodes.paragraph.create(null, nodes)), 1, 1);
|
|
54248
54915
|
} else if (input.html) {
|
|
@@ -54250,7 +54917,7 @@ var PasteController = class {
|
|
|
54250
54917
|
const imported = /* @__PURE__ */ new Map();
|
|
54251
54918
|
const elements = [...container.querySelectorAll("img")];
|
|
54252
54919
|
const uniqueSources = new Set(elements.map((element) => element.getAttribute("src") ?? ""));
|
|
54253
|
-
const positional = (
|
|
54920
|
+
const positional = (fromFiles.length === 0 || fromFiles.length === 1 && uniqueSources.size === 1 ? images : input.images ?? []).filter((image) => !image.source);
|
|
54254
54921
|
let index = 0;
|
|
54255
54922
|
for (const element of elements) {
|
|
54256
54923
|
const source = element.getAttribute("src") ?? "";
|
|
@@ -54747,11 +55414,11 @@ var DocumentSession = class {
|
|
|
54747
55414
|
//#region src/selection.ts
|
|
54748
55415
|
/** The stylesheet paints the selection under this name. */
|
|
54749
55416
|
var name = "inkkit-selection";
|
|
54750
|
-
var
|
|
55417
|
+
var activeClass = "inkkit-selection-active";
|
|
54751
55418
|
/** The selected text within each block. */
|
|
54752
55419
|
function covered(state) {
|
|
54753
55420
|
const { from, to, empty, visible } = state.selection;
|
|
54754
|
-
if (empty || !visible) return
|
|
55421
|
+
if (empty || !visible) return [];
|
|
54755
55422
|
const text = [];
|
|
54756
55423
|
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
54757
55424
|
if (!node.isTextblock) return true;
|
|
@@ -54768,39 +55435,140 @@ function covered(state) {
|
|
|
54768
55435
|
function domRange(view, span) {
|
|
54769
55436
|
const start = view.domAtPos(span.from);
|
|
54770
55437
|
const end = view.domAtPos(span.to);
|
|
54771
|
-
const range =
|
|
55438
|
+
const range = view.dom.ownerDocument.createRange();
|
|
54772
55439
|
range.setStart(start.node, start.offset);
|
|
54773
55440
|
range.setEnd(end.node, end.offset);
|
|
54774
55441
|
return range;
|
|
54775
55442
|
}
|
|
54776
|
-
|
|
54777
|
-
ranges.set(view, (covered(view.state) ?? []).map((span) => domRange(view, span)));
|
|
54778
|
-
refresh();
|
|
54779
|
-
}
|
|
54780
|
-
function refresh() {
|
|
54781
|
-
if (ranges.size === 0) {
|
|
54782
|
-
CSS.highlights.delete(name);
|
|
54783
|
-
return;
|
|
54784
|
-
}
|
|
54785
|
-
const highlight = new Highlight();
|
|
54786
|
-
for (const selection of ranges.values()) for (const range of selection) highlight.add(range);
|
|
54787
|
-
CSS.highlights.set(name, highlight);
|
|
54788
|
-
}
|
|
55443
|
+
var rootOf = (view) => view.dom.closest(".inkkit-root");
|
|
54789
55444
|
var paintable = () => typeof Highlight === "function" && "highlights" in CSS && CSS.supports(`selector(::highlight(${name}))`);
|
|
54790
|
-
|
|
54791
|
-
|
|
54792
|
-
|
|
54793
|
-
|
|
54794
|
-
|
|
54795
|
-
|
|
54796
|
-
|
|
54797
|
-
|
|
54798
|
-
|
|
54799
|
-
|
|
54800
|
-
|
|
54801
|
-
|
|
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;
|
|
54802
55480
|
}
|
|
54803
|
-
|
|
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
|
+
});
|
|
54804
55572
|
//#endregion
|
|
54805
55573
|
//#region node_modules/.pnpm/prosemirror-search@1.1.1/node_modules/prosemirror-search/dist/index.js
|
|
54806
55574
|
var SearchQuery = class {
|
|
@@ -55230,8 +55998,8 @@ function findFormatted(view, text) {
|
|
|
55230
55998
|
return found;
|
|
55231
55999
|
}
|
|
55232
56000
|
function replacementSlice(state, from, to, value) {
|
|
55233
|
-
const start = state.doc.resolve(from)
|
|
55234
|
-
const marks =
|
|
56001
|
+
const start = state.doc.resolve(from);
|
|
56002
|
+
const marks = replacementMarks(state, from, to);
|
|
55235
56003
|
const nodes = [];
|
|
55236
56004
|
if (start.parent.type.spec.code) {
|
|
55237
56005
|
if (value) nodes.push(state.schema.text(value, marks));
|
|
@@ -55848,6 +56616,8 @@ var shortcutNames = [
|
|
|
55848
56616
|
"redo",
|
|
55849
56617
|
"moveBlockUp",
|
|
55850
56618
|
"moveBlockDown",
|
|
56619
|
+
"indent",
|
|
56620
|
+
"outdent",
|
|
55851
56621
|
...tableCommands.map(tableShortcut)
|
|
55852
56622
|
];
|
|
55853
56623
|
/** Checks a keymap and drops omitted entries, so a `null` binding keeps its default. */
|
|
@@ -55899,6 +56669,7 @@ function editorOptions(value) {
|
|
|
55899
56669
|
"textInput",
|
|
55900
56670
|
"labels",
|
|
55901
56671
|
"keymap",
|
|
56672
|
+
"linkSchemes",
|
|
55902
56673
|
"rendering",
|
|
55903
56674
|
"slashMenu"
|
|
55904
56675
|
]) ?? {};
|
|
@@ -55908,6 +56679,7 @@ function editorOptions(value) {
|
|
|
55908
56679
|
optionalBoolean(options.editable, "options.editable");
|
|
55909
56680
|
if (!isOmitted(options.textInput)) textInputPreferences(options.textInput, "options.textInput");
|
|
55910
56681
|
if (!isOmitted(options.keymap)) keymapBindings(options.keymap, "options.keymap");
|
|
56682
|
+
const linkSchemes = isOmitted(options.linkSchemes) ? void 0 : extraLinkSchemes(options.linkSchemes, "options.linkSchemes");
|
|
55911
56683
|
const rendering = optionalRecord(options.rendering, "options.rendering", ["codeHighlighting", "diagramPreview"]);
|
|
55912
56684
|
optionalBoolean(rendering?.codeHighlighting, "options.rendering.codeHighlighting");
|
|
55913
56685
|
optionalBoolean(rendering?.diagramPreview, "options.rendering.diagramPreview");
|
|
@@ -55915,6 +56687,7 @@ function editorOptions(value) {
|
|
|
55915
56687
|
return {
|
|
55916
56688
|
...options,
|
|
55917
56689
|
slashMenu: slashMenuOptions(options.slashMenu),
|
|
56690
|
+
linkSchemes,
|
|
55918
56691
|
labels: labels && Object.fromEntries(Object.entries(labels).filter(([, label]) => !isOmitted(label)).map(([key, label]) => [key, expectString(label, `options.labels.${key}`)]))
|
|
55919
56692
|
};
|
|
55920
56693
|
}
|
|
@@ -56111,6 +56884,18 @@ function blockAt(parent, $from) {
|
|
|
56111
56884
|
return { type: "paragraph" };
|
|
56112
56885
|
}
|
|
56113
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 }));
|
|
56114
56899
|
var quoteBackspace = $prose(() => keymap$3({ Backspace: (state, dispatch) => {
|
|
56115
56900
|
const { $from, empty } = state.selection;
|
|
56116
56901
|
if (!empty || $from.parentOffset > 0 || $from.depth < 2) return false;
|
|
@@ -56120,7 +56905,7 @@ var quoteBackspace = $prose(() => keymap$3({ Backspace: (state, dispatch) => {
|
|
|
56120
56905
|
const range = $from.blockRange($from, (node) => quotes.has(node.type.name));
|
|
56121
56906
|
const target = range && liftTarget(range);
|
|
56122
56907
|
if (!range || target == null) return false;
|
|
56123
|
-
dispatch?.(state
|
|
56908
|
+
dispatch?.(liftQuote(state, range, target).scrollIntoView());
|
|
56124
56909
|
return true;
|
|
56125
56910
|
} }));
|
|
56126
56911
|
var calloutEnter = $prose(() => keymap$3({ Enter: (state, dispatch) => {
|
|
@@ -56162,7 +56947,6 @@ var liftItem = (state, dispatch) => {
|
|
|
56162
56947
|
dispatch(lifted);
|
|
56163
56948
|
return true;
|
|
56164
56949
|
};
|
|
56165
|
-
var listItemShiftTab = $prose(() => keymap$3({ "Shift-Tab": liftItem }));
|
|
56166
56950
|
var rejoinLists = $prose(() => keymap$3({ Backspace: (state, dispatch) => {
|
|
56167
56951
|
const { $from, empty } = state.selection;
|
|
56168
56952
|
if (!empty || $from.parent.type.name !== "paragraph" || $from.parent.content.size > 0) return false;
|
|
@@ -56255,11 +57039,7 @@ var movedListItems = $prose(() => new Plugin({
|
|
|
56255
57039
|
return tr.docChanged ? tr : null;
|
|
56256
57040
|
}
|
|
56257
57041
|
}));
|
|
56258
|
-
var
|
|
56259
|
-
var textInputPolicy = $prose(() => new Plugin({
|
|
56260
|
-
key: new PluginKey("inkkitTextInput"),
|
|
56261
|
-
props: { handleTextInput: (view, from, to, text, deflt) => controlCharacters.test(text) || insertTextChunk(view, from, to, text, deflt) }
|
|
56262
|
-
}));
|
|
57042
|
+
var textInputPolicy = $prose(() => textInputPlugin());
|
|
56263
57043
|
function outermostListDepth($pos) {
|
|
56264
57044
|
for (let depth = 1; depth <= $pos.depth; depth++) if (isList($pos.node(depth))) return depth;
|
|
56265
57045
|
return null;
|
|
@@ -56384,6 +57164,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56384
57164
|
inputPreferences = {};
|
|
56385
57165
|
literalKeys = () => false;
|
|
56386
57166
|
configuredKeys = {};
|
|
57167
|
+
indentKeys = () => false;
|
|
56387
57168
|
readOnlyKeys = () => false;
|
|
56388
57169
|
suggestions;
|
|
56389
57170
|
suggestionBase;
|
|
@@ -56423,6 +57204,8 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56423
57204
|
}));
|
|
56424
57205
|
keys = () => false;
|
|
56425
57206
|
events;
|
|
57207
|
+
/** The host's extra link schemes, in lower case. */
|
|
57208
|
+
linkSchemes;
|
|
56426
57209
|
/** How many of each state event the host has been sent. */
|
|
56427
57210
|
sentEvents = /* @__PURE__ */ new Map();
|
|
56428
57211
|
constructor(events, options) {
|
|
@@ -56442,6 +57225,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56442
57225
|
else send();
|
|
56443
57226
|
};
|
|
56444
57227
|
} });
|
|
57228
|
+
this.linkSchemes = new Set(options.linkSchemes);
|
|
56445
57229
|
this.writable = options.editable ?? true;
|
|
56446
57230
|
this.inputPreferences = textInputPreferences(options.textInput ?? {}, "options.textInput");
|
|
56447
57231
|
}
|
|
@@ -56502,7 +57286,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56502
57286
|
};
|
|
56503
57287
|
}
|
|
56504
57288
|
mediaPolicy() {
|
|
56505
|
-
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));
|
|
56506
57290
|
}
|
|
56507
57291
|
assertAlive() {
|
|
56508
57292
|
if (this.destroyed) throw new InkKitError("destroyed", "The editor has been destroyed");
|
|
@@ -56753,6 +57537,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
56753
57537
|
replace: mutable,
|
|
56754
57538
|
replaceSource: mutable,
|
|
56755
57539
|
insertImages: formatted && this.canInsertImages,
|
|
57540
|
+
appendImages: formatted && this.canInsertImages,
|
|
56756
57541
|
insertPaths: mutable,
|
|
56757
57542
|
insertFootnote: formatted,
|
|
56758
57543
|
editReferenceDefinition: formatted && referenceDefinitions(state.doc).size > 0,
|
|
@@ -57212,7 +57997,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57212
57997
|
} catch (error) {
|
|
57213
57998
|
throw coded(error, "preservation");
|
|
57214
57999
|
}
|
|
57215
|
-
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));
|
|
57216
58001
|
const metadata = referenceMetadata(this.editor.ctx, selectedDoc ?? doc, content);
|
|
57217
58002
|
if (metadata != null) result.html = withReferenceMetadata(result.html, metadata);
|
|
57218
58003
|
this.assertCaptured(captured);
|
|
@@ -57263,7 +58048,8 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57263
58048
|
if (view.state.selection.$from.parent.type.spec.code && !inHiddenComment) view.dispatch(view.state.tr.insertText(text.replace(/\r\n?/g, "\n")).scrollIntoView());
|
|
57264
58049
|
else {
|
|
57265
58050
|
const { schema } = view.state;
|
|
57266
|
-
const
|
|
58051
|
+
const { from, to } = view.state.selection;
|
|
58052
|
+
const marks = replacementMarks(view.state, from, to);
|
|
57267
58053
|
const isHTML = !inHiddenComment && htmlBreakAt(view.state.selection.$from);
|
|
57268
58054
|
const lines = text.replace(/\r\n?/g, "\n").split("\n");
|
|
57269
58055
|
const children = literalTextNodes(schema, text, marks, isHTML);
|
|
@@ -57339,6 +58125,10 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57339
58125
|
return this.keys(view, event);
|
|
57340
58126
|
} }
|
|
57341
58127
|
}));
|
|
58128
|
+
indentPlugin = new Plugin({
|
|
58129
|
+
key: new PluginKey("listIndent"),
|
|
58130
|
+
props: { handleKeyDown: (view, event) => this.indentKeys(view, event) }
|
|
58131
|
+
});
|
|
57342
58132
|
copySourceSelection(event) {
|
|
57343
58133
|
event.preventDefault();
|
|
57344
58134
|
event.stopPropagation();
|
|
@@ -57364,7 +58154,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57364
58154
|
}
|
|
57365
58155
|
}).catch((error) => this.report(error));
|
|
57366
58156
|
else {
|
|
57367
|
-
const output = clipboardContent(parsed.content, parsed.type.schema);
|
|
58157
|
+
const output = clipboardContent(parsed.content, parsed.type.schema, this.linkSchemes);
|
|
57368
58158
|
if (!event.clipboardData) return;
|
|
57369
58159
|
this.rememberCopy(output, selected.markdown, parsed.content, selected.markdown !== selected.shareable, true);
|
|
57370
58160
|
event.clipboardData.setData("text/plain", output.text);
|
|
@@ -57430,6 +58220,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57430
58220
|
ctx.set(rootCtx, root);
|
|
57431
58221
|
ctx.set(authoredSourcesCtx.key, (doc, positions) => instance.authoredSources(doc, positions));
|
|
57432
58222
|
ctx.set(smartPunctuationCtx.key, () => instance.inputPreferences.smartPunctuation === true);
|
|
58223
|
+
ctx.set(linkSchemesCtx.key, instance.linkSchemes);
|
|
57433
58224
|
ctx.update(labelsCtx.key, () => ({
|
|
57434
58225
|
...defaultLabels,
|
|
57435
58226
|
...options.labels
|
|
@@ -57444,9 +58235,16 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57444
58235
|
}), false));
|
|
57445
58236
|
ctx.set(defaultValueCtx, "");
|
|
57446
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
|
+
});
|
|
57447
58245
|
ctx.update(listItemKeymap.key, (keys) => ({
|
|
57448
58246
|
...keys,
|
|
57449
|
-
SinkListItem: { shortcuts:
|
|
58247
|
+
SinkListItem: { shortcuts: [] },
|
|
57450
58248
|
LiftListItem: { shortcuts: [] }
|
|
57451
58249
|
}));
|
|
57452
58250
|
const unbind = (keymap, keep = []) => ctx.update(keymap.key, (keys) => {
|
|
@@ -57510,7 +58308,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57510
58308
|
return true;
|
|
57511
58309
|
}
|
|
57512
58310
|
}));
|
|
57513
|
-
}).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, {
|
|
57514
58312
|
capture: () => instance.adapterCapture(),
|
|
57515
58313
|
active: () => instance.ready && !instance.destroyed && !instance.literalSurface,
|
|
57516
58314
|
labels: {
|
|
@@ -57518,8 +58316,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57518
58316
|
...options.labels
|
|
57519
58317
|
},
|
|
57520
58318
|
error: (error) => instance.report(error)
|
|
57521
|
-
}) : []).use(options.images || options.files ? imageView(options.images,
|
|
57522
|
-
adapter: options.files,
|
|
58319
|
+
}) : []).use(options.images || options.files ? imageView(options.images, {
|
|
57523
58320
|
capture: () => instance.adapterCapture(),
|
|
57524
58321
|
active: () => instance.ready && !instance.destroyed && !instance.literalSurface,
|
|
57525
58322
|
labels: {
|
|
@@ -57527,7 +58324,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57527
58324
|
...options.labels
|
|
57528
58325
|
},
|
|
57529
58326
|
error: (error) => instance.report(error)
|
|
57530
|
-
}
|
|
58327
|
+
}, options.files, () => {
|
|
57531
58328
|
try {
|
|
57532
58329
|
instance.assertMutation();
|
|
57533
58330
|
return true;
|
|
@@ -57661,7 +58458,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
57661
58458
|
const content = expanded;
|
|
57662
58459
|
const valid = fragment.firstChild?.isInline ? Fragment.from(view.state.schema.nodes.paragraph.create(null, fragment)) : fragment;
|
|
57663
58460
|
const markdown = selectionMarkdown(instance.editor.ctx, view.state.doc, valid);
|
|
57664
|
-
const output = clipboardContent(content, view.state.schema);
|
|
58461
|
+
const output = clipboardContent(content, view.state.schema, instance.linkSchemes);
|
|
57665
58462
|
const metadata = referenceMetadata(instance.editor.ctx, view.state.doc, valid);
|
|
57666
58463
|
if (metadata != null) output.html = withReferenceMetadata(output.html, metadata);
|
|
57667
58464
|
instance.rememberCopy(output, markdown, fragment, false, true);
|
|
@@ -58314,10 +59111,23 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58314
59111
|
this.assertReady(expectedGeneration);
|
|
58315
59112
|
this.releaseFocus();
|
|
58316
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
|
+
}
|
|
58317
59126
|
/** Replaces every binding. Keys are in ProseMirror's notation. A key given to two shortcuts goes
|
|
58318
59127
|
* to the later one, in the order history, formatting, block moves, tables, so it lands the same
|
|
58319
59128
|
* way every time. A table binding passes a key it shares with a block move to the move outside
|
|
58320
|
-
* a table.
|
|
59129
|
+
* a table. List indentation keys apply after all of these, and after the table keys the editor
|
|
59130
|
+
* keeps for itself. */
|
|
58321
59131
|
setKeymap(keymap) {
|
|
58322
59132
|
this.assertAlive();
|
|
58323
59133
|
keymap = keymapBindings(keymap, "keymap");
|
|
@@ -58327,6 +59137,8 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58327
59137
|
moveBlockUp: ["Alt-ArrowUp"],
|
|
58328
59138
|
moveBlockDown: ["Alt-ArrowDown"],
|
|
58329
59139
|
tableExit: ["Mod-Enter", "Enter"],
|
|
59140
|
+
indent: ["Tab"],
|
|
59141
|
+
outdent: ["Shift-Tab"],
|
|
58330
59142
|
...keymap
|
|
58331
59143
|
};
|
|
58332
59144
|
const bindings = {};
|
|
@@ -58353,6 +59165,9 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58353
59165
|
if (move === "move" && !this.composing && !this.pasteController.pending) this.forPerson(() => this.moveBlock(direction), false);
|
|
58354
59166
|
return true;
|
|
58355
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;
|
|
58356
59171
|
for (const command of tableCommands) for (const key of this.configuredKeys[tableShortcut(command)] ?? []) bindings[key] = (state, dispatch, view) => {
|
|
58357
59172
|
if (!this.ready || !this.commandState().commands.table[command]) return moves[key]?.(state, dispatch, view) ?? false;
|
|
58358
59173
|
return this.forPerson(() => this.table(command), true);
|
|
@@ -58361,6 +59176,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58361
59176
|
throw new InkKitError("read-only", "The editor is read-only");
|
|
58362
59177
|
}])));
|
|
58363
59178
|
this.keys = keydownHandler(bindings);
|
|
59179
|
+
this.indentKeys = keydownHandler(indents);
|
|
58364
59180
|
this.literalKeys = keydownHandler(historyBindings);
|
|
58365
59181
|
}
|
|
58366
59182
|
/** Dropped files land as one paragraph per path at the drop point: in place of an empty block, after
|
|
@@ -58388,17 +59204,12 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58388
59204
|
this.assertMutation(expectedGeneration);
|
|
58389
59205
|
if (!images.length || !this.canInsertImages || this.literalSurface) return false;
|
|
58390
59206
|
const view = this.editor.ctx.get(editorViewCtx);
|
|
58391
|
-
const { schema } = view.state;
|
|
58392
59207
|
const placement = point ? void 0 : imagePlacement(view.state);
|
|
58393
59208
|
if (placement?.kind === "inline") {
|
|
58394
59209
|
this.insertInline(images);
|
|
58395
59210
|
return true;
|
|
58396
59211
|
}
|
|
58397
|
-
const blocks =
|
|
58398
|
-
src: image.reference,
|
|
58399
|
-
alt: image.alt,
|
|
58400
|
-
title: image.title ?? ""
|
|
58401
|
-
})));
|
|
59212
|
+
const blocks = this.imageBlocks(images);
|
|
58402
59213
|
if (point) {
|
|
58403
59214
|
this.insertBlocks(blocks, point);
|
|
58404
59215
|
return true;
|
|
@@ -58414,6 +59225,31 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58414
59225
|
view.dispatch(tr.scrollIntoView());
|
|
58415
59226
|
return true;
|
|
58416
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
|
+
}
|
|
58417
59253
|
insertInline(images) {
|
|
58418
59254
|
const view = this.editor.ctx.get(editorViewCtx);
|
|
58419
59255
|
const { state } = view;
|
|
@@ -58531,7 +59367,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58531
59367
|
if (!range) return;
|
|
58532
59368
|
const target = liftTarget(range);
|
|
58533
59369
|
if (target == null) return;
|
|
58534
|
-
view.dispatch(view.state
|
|
59370
|
+
view.dispatch(liftQuote(view.state, range, target));
|
|
58535
59371
|
}
|
|
58536
59372
|
/** Changes the selected textblocks' type, keeping everything they hold. */
|
|
58537
59373
|
textblockType(type, attr) {
|
|
@@ -58616,25 +59452,27 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58616
59452
|
commit(command);
|
|
58617
59453
|
return;
|
|
58618
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;
|
|
58619
59468
|
try {
|
|
58620
|
-
|
|
58621
|
-
const insert = (markdown) => {
|
|
58622
|
-
if (this.destroyed) return;
|
|
58623
|
-
if (markdown === void 0) return;
|
|
58624
|
-
if (typeof markdown !== "string") {
|
|
58625
|
-
this.report(invalidArgument("A slash command must return Markdown text"));
|
|
58626
|
-
return;
|
|
58627
|
-
}
|
|
58628
|
-
commit({ markdown });
|
|
58629
|
-
};
|
|
58630
|
-
if (result instanceof Promise) result.then(insert).catch((error) => {
|
|
58631
|
-
if (this.destroyed) return;
|
|
58632
|
-
this.report(error);
|
|
58633
|
-
});
|
|
58634
|
-
else insert(result);
|
|
59469
|
+
result = command.action(this.context());
|
|
58635
59470
|
} catch (error) {
|
|
58636
|
-
|
|
59471
|
+
onHostError(error);
|
|
59472
|
+
return;
|
|
58637
59473
|
}
|
|
59474
|
+
if (result instanceof Promise) result.then(insert, onHostError);
|
|
59475
|
+
else insert(result);
|
|
58638
59476
|
}
|
|
58639
59477
|
/** Returns whether the document or the marks the next typed text takes changed. */
|
|
58640
59478
|
format(command, options, expectedGeneration) {
|
|
@@ -58695,12 +59533,13 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58695
59533
|
return !after.doc.eq(before.doc) || !Mark.sameSet(marks(after), marks(before));
|
|
58696
59534
|
}
|
|
58697
59535
|
/**
|
|
58698
|
-
* Refuses a link destination that is empty, that opens anything but a web, mail or phone address
|
|
58699
|
-
* 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.
|
|
58700
59539
|
*/
|
|
58701
59540
|
checkDestination(destination, name) {
|
|
58702
59541
|
if (destination.trim() === "") throw invalidArgument(`${name} must not be empty`);
|
|
58703
|
-
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`);
|
|
58704
59543
|
const { schema } = this.editor.ctx.get(editorViewCtx).state;
|
|
58705
59544
|
const written = serialize(this.editor.ctx, schema.node("doc", null, [schema.node("paragraph", null, [schema.text("x", [schema.marks.link.create({ href: destination })])])]));
|
|
58706
59545
|
let read;
|
|
@@ -58722,13 +59561,18 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58722
59561
|
const { selection, storedMarks } = state;
|
|
58723
59562
|
const { from, to, empty } = selection;
|
|
58724
59563
|
const stored = empty ? type.isInSet(storedMarks ?? []) : void 0;
|
|
58725
|
-
|
|
59564
|
+
const beside = empty ? selection.$from.nodeBefore?.marks ?? [] : [];
|
|
59565
|
+
if (stored && !stored.isInSet(selection.$from.marks()) && !stored.isInSet(beside)) {
|
|
58726
59566
|
const tr = state.tr.removeStoredMark(type);
|
|
58727
59567
|
if (destination !== void 0) tr.addStoredMark(type.create({ href: destination }));
|
|
58728
59568
|
view.dispatch(tr);
|
|
58729
59569
|
return;
|
|
58730
59570
|
}
|
|
58731
|
-
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 ?? []);
|
|
58732
59576
|
const extent = mark && markRun(state.doc, mark, from, to);
|
|
58733
59577
|
const keepStored = (tr, link) => {
|
|
58734
59578
|
if (!storedMarks) return tr;
|
|
@@ -58875,12 +59719,14 @@ var InkKitEditor = class InkKitEditor {
|
|
|
58875
59719
|
"keyDown",
|
|
58876
59720
|
"insertPaths",
|
|
58877
59721
|
"insertImages",
|
|
59722
|
+
"appendImages",
|
|
58878
59723
|
"insertFootnote",
|
|
58879
59724
|
"navigateFootnote",
|
|
58880
59725
|
"editReferenceDefinition",
|
|
58881
59726
|
"setCommentsVisible",
|
|
58882
59727
|
"focus",
|
|
58883
59728
|
"blur",
|
|
59729
|
+
"refreshReferences",
|
|
58884
59730
|
"setKeymap",
|
|
58885
59731
|
"textSnapshot",
|
|
58886
59732
|
"selectTextRange",
|