@aicayzer/inkkit 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{core-CbHV2KPY.js → core-B7CD5hsd.js} +422 -15
- package/dist/chunks/{highlight-C-9lbVMU.js → highlight-B_juJyDH.js} +1 -1
- package/dist/core.d.ts +2 -1
- package/dist/core.js +2 -2
- package/dist/editor.d.ts +20 -1
- package/dist/index.js +2 -2
- package/dist/link-address.d.ts +11 -0
- package/dist/types.d.ts +39 -1
- package/package.json +3 -1
|
@@ -28448,6 +28448,7 @@ var editorErrorCodes = [
|
|
|
28448
28448
|
"invalid-range",
|
|
28449
28449
|
"preservation",
|
|
28450
28450
|
"image-unavailable",
|
|
28451
|
+
"image-unsupported",
|
|
28451
28452
|
"diagram-unavailable",
|
|
28452
28453
|
"file-unavailable",
|
|
28453
28454
|
"clipboard-unavailable",
|
|
@@ -33178,6 +33179,13 @@ A command function that redoes the last undone change, if any.
|
|
|
33178
33179
|
*/
|
|
33179
33180
|
var redo = buildCommand(true, true);
|
|
33180
33181
|
/**
|
|
33182
|
+
The amount of undoable events available in a given state.
|
|
33183
|
+
*/
|
|
33184
|
+
function undoDepth(state) {
|
|
33185
|
+
let hist = historyKey.getState(state);
|
|
33186
|
+
return hist ? hist.done.eventCount : 0;
|
|
33187
|
+
}
|
|
33188
|
+
/**
|
|
33181
33189
|
The amount of redoable events available in a given editor state.
|
|
33182
33190
|
*/
|
|
33183
33191
|
function redoDepth(state) {
|
|
@@ -40553,7 +40561,7 @@ function parseLinkedSyntax(raw, inTable = false) {
|
|
|
40553
40561
|
let section = "target", hasFragment = false, hasAlias = false;
|
|
40554
40562
|
for (let index = 0; index < content.length; index++) {
|
|
40555
40563
|
const character = content[index];
|
|
40556
|
-
if (character === "\\") {
|
|
40564
|
+
if (character === "\\" && embed) {
|
|
40557
40565
|
const escaped = content[++index];
|
|
40558
40566
|
if (!escaped || !"[]|#\\".includes(escaped)) return void 0;
|
|
40559
40567
|
parts[section] += escaped;
|
|
@@ -40604,7 +40612,7 @@ function linkedTokenizer(embed) {
|
|
|
40604
40612
|
function body(code) {
|
|
40605
40613
|
if (code === null || code < 32 && code !== -2 && code !== -1 && code !== 9 || code === 91) return nok(code);
|
|
40606
40614
|
consume(code);
|
|
40607
|
-
if (code === 92) return escaped;
|
|
40615
|
+
if (code === 92 && embed) return escaped;
|
|
40608
40616
|
return code === 93 ? closing : body;
|
|
40609
40617
|
}
|
|
40610
40618
|
function escaped(code) {
|
|
@@ -40621,6 +40629,39 @@ function linkedTokenizer(embed) {
|
|
|
40621
40629
|
}
|
|
40622
40630
|
};
|
|
40623
40631
|
}
|
|
40632
|
+
/**
|
|
40633
|
+
* Looks ahead from a backslash for a wiki link that starts right after it. CommonMark reads `\[`
|
|
40634
|
+
* as an escaped bracket, which would hide the link, but a backslash before a wiki link is only
|
|
40635
|
+
* text, as it is inside one.
|
|
40636
|
+
*/
|
|
40637
|
+
var backslashBeforeWikiLink = {
|
|
40638
|
+
name: "inkkitWikiBackslash",
|
|
40639
|
+
tokenize(effects, ok, nok) {
|
|
40640
|
+
return function start(code) {
|
|
40641
|
+
if (code !== 92) return nok(code);
|
|
40642
|
+
return effects.check(wikiLinkAhead, literal, nok)(code);
|
|
40643
|
+
};
|
|
40644
|
+
function literal(code) {
|
|
40645
|
+
effects.enter("data");
|
|
40646
|
+
effects.consume(code);
|
|
40647
|
+
effects.exit("data");
|
|
40648
|
+
return ok;
|
|
40649
|
+
}
|
|
40650
|
+
}
|
|
40651
|
+
};
|
|
40652
|
+
var wikiLinkAhead = {
|
|
40653
|
+
partial: true,
|
|
40654
|
+
tokenize(effects, ok, nok) {
|
|
40655
|
+
const link = linkedTokenizer(false).call(this, effects, ok, nok);
|
|
40656
|
+
return function start(code) {
|
|
40657
|
+
if (code !== 92) return nok(code);
|
|
40658
|
+
effects.enter("data");
|
|
40659
|
+
effects.consume(code);
|
|
40660
|
+
effects.exit("data");
|
|
40661
|
+
return link;
|
|
40662
|
+
};
|
|
40663
|
+
}
|
|
40664
|
+
};
|
|
40624
40665
|
function tableForm(raw, authoredInTable, outputInTable) {
|
|
40625
40666
|
if (authoredInTable === outputInTable) return raw;
|
|
40626
40667
|
return outputInTable ? toTable(raw) : fromTable(raw);
|
|
@@ -40872,14 +40913,14 @@ var referenceTableContext = $prose(() => new Plugin({
|
|
|
40872
40913
|
* brackets, is never changed, and that includes the run of every rule when a
|
|
40873
40914
|
* composition ends.
|
|
40874
40915
|
*/
|
|
40875
|
-
var wikiLinkInputRule = $inputRule(() => new InputRule(/\[\[
|
|
40916
|
+
var wikiLinkInputRule = $inputRule(() => new InputRule(/\[\[[^[\]\ufffc]*\]\]$/, (state, match, start, end) => {
|
|
40876
40917
|
const { schema, doc } = state;
|
|
40877
40918
|
const type = schema.nodes.inkkit_wiki_link;
|
|
40878
40919
|
const caret = state.selection.from;
|
|
40879
40920
|
if (start + match[0].length - 1 !== caret && !(start + match[0].length === caret && composed.getState(state)?.closing === caret)) return null;
|
|
40880
40921
|
const $start = doc.resolve(start);
|
|
40881
40922
|
const parent = $start.parent;
|
|
40882
|
-
if (!type || !parent.inlineContent || !parent.canReplaceWith($start.index(), $start.index(), type) || /[
|
|
40923
|
+
if (!type || !parent.inlineContent || !parent.canReplaceWith($start.index(), $start.index(), type) || /[![]/.test(doc.textBetween(Math.max($start.start(), start - 1), start))) return null;
|
|
40883
40924
|
let marks;
|
|
40884
40925
|
let plain = true;
|
|
40885
40926
|
doc.nodesBetween(start, end, (node) => {
|
|
@@ -40908,6 +40949,7 @@ function linkedSyntax(wikiLinks, files) {
|
|
|
40908
40949
|
tokenize: linkedTokenizer(false),
|
|
40909
40950
|
previous: (code) => code !== 33 && code !== 91
|
|
40910
40951
|
};
|
|
40952
|
+
if (wikiLinks) syntax.text[92] = backslashBeforeWikiLink;
|
|
40911
40953
|
if (files) syntax.text[33] = {
|
|
40912
40954
|
name: "inkkitNamedFile",
|
|
40913
40955
|
tokenize: linkedTokenizer(true)
|
|
@@ -40967,7 +41009,7 @@ function linkedSyntax(wikiLinks, files) {
|
|
|
40967
41009
|
//#endregion
|
|
40968
41010
|
//#region src/wiki-suggestions.ts
|
|
40969
41011
|
function rawName(name) {
|
|
40970
|
-
return `[[${name
|
|
41012
|
+
return `[[${name}]]`;
|
|
40971
41013
|
}
|
|
40972
41014
|
function validName(value) {
|
|
40973
41015
|
if (typeof value !== "string") return false;
|
|
@@ -46968,12 +47010,29 @@ function caretState(state) {
|
|
|
46968
47010
|
const type = state.schema.marks[name];
|
|
46969
47011
|
if (type && state.doc.rangeHasMark($from.pos, $to.pos, type)) active.add(mark);
|
|
46970
47012
|
}
|
|
47013
|
+
const href = active.has("link") ? linkAddress(state, marks) : void 0;
|
|
46971
47014
|
return {
|
|
46972
47015
|
marks: [...active],
|
|
46973
47016
|
block: blockAt($from.parent, $from),
|
|
46974
|
-
quoted: quoted($from, $to)
|
|
47017
|
+
quoted: quoted($from, $to),
|
|
47018
|
+
...href != null ? { href } : {}
|
|
46975
47019
|
};
|
|
46976
47020
|
}
|
|
47021
|
+
/** The address of the first link at the caret, or in the selection, in document order. */
|
|
47022
|
+
function linkAddress(state, caretMarks) {
|
|
47023
|
+
const type = state.schema.marks.link;
|
|
47024
|
+
if (!type) return void 0;
|
|
47025
|
+
const { empty } = state.selection;
|
|
47026
|
+
if (empty) return type.isInSet(caretMarks)?.attrs.href;
|
|
47027
|
+
const { $from, $to } = textBounds(state);
|
|
47028
|
+
let href;
|
|
47029
|
+
state.doc.nodesBetween($from.pos, $to.pos, (node) => {
|
|
47030
|
+
if (href != null) return false;
|
|
47031
|
+
href = type.isInSet(node.marks)?.attrs.href;
|
|
47032
|
+
return true;
|
|
47033
|
+
});
|
|
47034
|
+
return href;
|
|
47035
|
+
}
|
|
46977
47036
|
function terminalSelection(doc) {
|
|
46978
47037
|
const $end = doc.resolve(doc.content.size);
|
|
46979
47038
|
const gap = GapCursor;
|
|
@@ -53333,6 +53392,29 @@ var EditorDocument = class {
|
|
|
53333
53392
|
//#region src/editor-history.ts
|
|
53334
53393
|
var sourceGroupDelay = 500;
|
|
53335
53394
|
var sourceStepLimit = 100;
|
|
53395
|
+
var isHistoryState = (value) => typeof value === "object" && value !== null && "done" in value && "undone" in value && typeof value.undone?.constructor?.empty === "object";
|
|
53396
|
+
/**
|
|
53397
|
+
* Empties the formatted document's redo stack and keeps every undo step. ProseMirror's history
|
|
53398
|
+
* clears the stack only when an edit lands, and offers no call for it, so this replaces the
|
|
53399
|
+
* plugin's state through the plugin's own transaction meta. It checks the result against
|
|
53400
|
+
* `undoDepth` and `redoDepth` before it changes anything, so a ProseMirror update that changes
|
|
53401
|
+
* the state's shape fails here, in `test/discard-undone.test.ts`, and not silently.
|
|
53402
|
+
*/
|
|
53403
|
+
function discardFormattedRedo(view) {
|
|
53404
|
+
const { state } = view;
|
|
53405
|
+
if (redoDepth(state) === 0) return;
|
|
53406
|
+
const plugin = state.plugins.find((candidate) => /^history\$/.test(candidate.spec.key?.key ?? "") && isHistoryState(candidate.getState(state)));
|
|
53407
|
+
const previous = plugin?.getState(state);
|
|
53408
|
+
if (!plugin || !previous) throw new InkKitError("internal", "The undo history could not be found");
|
|
53409
|
+
const historyState = Object.assign(Object.create(Object.getPrototypeOf(previous)), previous, { undone: previous.undone.constructor.empty });
|
|
53410
|
+
const tr = state.tr.setMeta(plugin.spec.key, {
|
|
53411
|
+
redo: false,
|
|
53412
|
+
historyState
|
|
53413
|
+
});
|
|
53414
|
+
const next = state.apply(tr);
|
|
53415
|
+
if (redoDepth(next) !== 0 || undoDepth(next) !== undoDepth(state)) throw new InkKitError("internal", "The redo steps could not be discarded");
|
|
53416
|
+
view.dispatch(tr);
|
|
53417
|
+
}
|
|
53336
53418
|
var SourceHistory = class {
|
|
53337
53419
|
runtime;
|
|
53338
53420
|
pendingSource;
|
|
@@ -53363,6 +53445,11 @@ var SourceHistory = class {
|
|
|
53363
53445
|
this.undoneSteps = [];
|
|
53364
53446
|
this.formattedUndone = 0;
|
|
53365
53447
|
}
|
|
53448
|
+
/** Drops the redo steps of typed source, and the count of formatted ones that wait behind them. */
|
|
53449
|
+
discardUndone() {
|
|
53450
|
+
this.undoneSteps = [];
|
|
53451
|
+
this.formattedUndone = 0;
|
|
53452
|
+
}
|
|
53366
53453
|
canUndo(state) {
|
|
53367
53454
|
return !!this.pendingSource || undo(state);
|
|
53368
53455
|
}
|
|
@@ -57281,7 +57368,7 @@ async function createMilkdownEditor(root, options, runtime) {
|
|
|
57281
57368
|
return true;
|
|
57282
57369
|
}
|
|
57283
57370
|
}));
|
|
57284
|
-
}).use(labelsCtx).use(linkSchemesCtx).use(formatInputCtx).use(richTextGuard).use(runtime.plugins.paste).use(visibleClipboard).use(runtime.plugins.suggestions).use(runtime.plugins.keymap).use(createDialect(Boolean(options.images || options.files), Boolean(options.wikiLinks), Boolean(options.files))).use(codeControlCtx).use(codeControlsPlugin(() => runtime.visibleRect())).use(tablePlugins).use(tableBlock).use(runtime.plugins.change).use(runtime.plugins.historyInput).use(history).use(clipboard).use(cursor).use(taskListPlugin((operation) => runtime.mutate(operation))).use(undoTypedRule).use(quoteBackspace).use(calloutEnter).use(literalEnter).use(literalReread).use(listItemBackspace).use(nestedItemEnter).use(rejoinLists).use(movedListItems).use(textInputPolicy).use(runtime.copy ? codeCopyPlugin((text) => runtime.copy?.(text)) : []).use(placeholderPlugin).use(options.rendering?.codeHighlighting === false ? [] : (await import("./highlight-
|
|
57371
|
+
}).use(labelsCtx).use(linkSchemesCtx).use(formatInputCtx).use(richTextGuard).use(runtime.plugins.paste).use(visibleClipboard).use(runtime.plugins.suggestions).use(runtime.plugins.keymap).use(createDialect(Boolean(options.images || options.files), Boolean(options.wikiLinks), Boolean(options.files))).use(codeControlCtx).use(codeControlsPlugin(() => runtime.visibleRect())).use(tablePlugins).use(tableBlock).use(runtime.plugins.change).use(runtime.plugins.historyInput).use(history).use(clipboard).use(cursor).use(taskListPlugin((operation) => runtime.mutate(operation))).use(undoTypedRule).use(quoteBackspace).use(calloutEnter).use(literalEnter).use(literalReread).use(listItemBackspace).use(nestedItemEnter).use(rejoinLists).use(movedListItems).use(textInputPolicy).use(runtime.copy ? codeCopyPlugin((text) => runtime.copy?.(text)) : []).use(placeholderPlugin).use(options.rendering?.codeHighlighting === false ? [] : (await import("./highlight-B_juJyDH.js")).highlightPlugin).use(options.rendering?.diagramPreview === false || !diagramsAvailable() ? [] : mermaidPreview(runtime.diagrams, (error) => runtime.report(error))).use(selectionPlugin).use($prose(() => search())).use(runtime.plugins.policy).use(options.wikiLinks ? wikiLinkView(options.wikiLinks, {
|
|
57285
57372
|
capture: () => runtime.capture(),
|
|
57286
57373
|
active: () => runtime.active(),
|
|
57287
57374
|
labels: {
|
|
@@ -58840,6 +58927,11 @@ var PasteController = class {
|
|
|
58840
58927
|
},
|
|
58841
58928
|
drop: (view, event) => {
|
|
58842
58929
|
const data = event.dataTransfer;
|
|
58930
|
+
if (!this.options.adapter && !this.options.files && !data?.getData("text/html") && view.editable && !view.dragging && imageFiles(data?.files ?? []).length) {
|
|
58931
|
+
event.preventDefault();
|
|
58932
|
+
options.onError?.(imagesRefused());
|
|
58933
|
+
return true;
|
|
58934
|
+
}
|
|
58843
58935
|
if (!data?.getData("text/html") || !view.editable || view.dragging) return false;
|
|
58844
58936
|
event.preventDefault();
|
|
58845
58937
|
const target = blockDropRange(view, event.clientX, event.clientY);
|
|
@@ -58848,7 +58940,7 @@ var PasteController = class {
|
|
|
58848
58940
|
text: data.getData("text/plain"),
|
|
58849
58941
|
html: data.getData("text/html"),
|
|
58850
58942
|
plainText: this.options.literalText?.() ?? false
|
|
58851
|
-
},
|
|
58943
|
+
}, imageFiles(data.files), target).catch((error) => options.onError?.(error));
|
|
58852
58944
|
return true;
|
|
58853
58945
|
}
|
|
58854
58946
|
},
|
|
@@ -58875,7 +58967,7 @@ var PasteController = class {
|
|
|
58875
58967
|
}).catch((error) => options.onError?.(error));
|
|
58876
58968
|
return true;
|
|
58877
58969
|
}
|
|
58878
|
-
const files =
|
|
58970
|
+
const files = imageFiles(data.files);
|
|
58879
58971
|
this.run({
|
|
58880
58972
|
text,
|
|
58881
58973
|
html,
|
|
@@ -58969,6 +59061,7 @@ var PasteController = class {
|
|
|
58969
59061
|
};
|
|
58970
59062
|
const rich = this.options.richText?.();
|
|
58971
59063
|
if (rich) {
|
|
59064
|
+
if (!this.options.adapter && (files.length || input.images?.length)) throw imagesRefused();
|
|
58972
59065
|
const anchor = operation;
|
|
58973
59066
|
const state = view.state;
|
|
58974
59067
|
const slice = input.plainText ? rich.paste({ text: input.text }, state, this.options.linkSchemes ?? /* @__PURE__ */ new Set()) : rich.paste(input, state, this.options.linkSchemes ?? /* @__PURE__ */ new Set());
|
|
@@ -58991,6 +59084,12 @@ var PasteController = class {
|
|
|
58991
59084
|
this.assertContext(context, operation);
|
|
58992
59085
|
const schema = view.state.schema;
|
|
58993
59086
|
let slice;
|
|
59087
|
+
const placeholders = [];
|
|
59088
|
+
const placeholder = (name) => {
|
|
59089
|
+
const text = `[${name}: image unavailable]`;
|
|
59090
|
+
placeholders.push(text);
|
|
59091
|
+
return text;
|
|
59092
|
+
};
|
|
58994
59093
|
let source;
|
|
58995
59094
|
const plainText = input.plainText || this.options.literalText?.() || inCode();
|
|
58996
59095
|
if (!plainText && input.markdown == null && this.commit(() => pasteSpreadsheet(ctx, {
|
|
@@ -59032,8 +59131,8 @@ var PasteController = class {
|
|
|
59032
59131
|
element.removeAttribute("srcset");
|
|
59033
59132
|
} catch (error) {
|
|
59034
59133
|
if (error instanceof InkKitError && error.code !== "image-unavailable") throw error;
|
|
59035
|
-
element.replaceWith(document.createTextNode(
|
|
59036
|
-
this.options.onError?.(coded(error, "image-unavailable", error instanceof Error ? error.message : "The pasted image is unavailable."));
|
|
59134
|
+
element.replaceWith(document.createTextNode(placeholder(alt)));
|
|
59135
|
+
if (this.options.adapter) this.options.onError?.(coded(error, "image-unavailable", error instanceof Error ? error.message : "The pasted image is unavailable."));
|
|
59037
59136
|
}
|
|
59038
59137
|
}
|
|
59039
59138
|
let imageIndex = 0;
|
|
@@ -59043,7 +59142,7 @@ var PasteController = class {
|
|
|
59043
59142
|
const position = slot ? Number(slot[1]) : imageIndex++;
|
|
59044
59143
|
const element = elements.some((element) => element.hasAttribute("data-inkkit-image-slot")) ? elements.find((element) => Number(element.getAttribute("data-inkkit-authored-image-slot") ?? element.getAttribute("data-inkkit-image-slot")) === position) : elements[position];
|
|
59045
59144
|
if (!element || !container.contains(element)) {
|
|
59046
|
-
const text = schema.text(
|
|
59145
|
+
const text = schema.text(placeholder(node.attrs.alt || "Image"));
|
|
59047
59146
|
return node.isBlock ? schema.nodes.paragraph.create(null, text) : text;
|
|
59048
59147
|
}
|
|
59049
59148
|
return node.type.create({
|
|
@@ -59072,6 +59171,7 @@ var PasteController = class {
|
|
|
59072
59171
|
}
|
|
59073
59172
|
}
|
|
59074
59173
|
} else if (images.length) {
|
|
59174
|
+
if (!this.options.adapter) throw imagesRefused();
|
|
59075
59175
|
const nodes = [];
|
|
59076
59176
|
if (input.text) nodes.push(schema.nodes.paragraph.create(null, schema.text(input.text)));
|
|
59077
59177
|
for (const image of images) try {
|
|
@@ -59086,7 +59186,7 @@ var PasteController = class {
|
|
|
59086
59186
|
nodes.push(schema.nodes.paragraph.create(null, imageNode));
|
|
59087
59187
|
} catch (error) {
|
|
59088
59188
|
if (error instanceof InkKitError && error.code !== "image-unavailable") throw error;
|
|
59089
|
-
nodes.push(schema.nodes.paragraph.create(null, schema.text(
|
|
59189
|
+
nodes.push(schema.nodes.paragraph.create(null, schema.text(placeholder(image.filename ?? "Image"))));
|
|
59090
59190
|
this.options.onError?.(coded(error, "image-unavailable", error instanceof Error ? error.message : "The pasted image is unavailable."));
|
|
59091
59191
|
}
|
|
59092
59192
|
slice = new Slice(Fragment.fromArray(nodes), 1, 1);
|
|
@@ -59103,6 +59203,10 @@ var PasteController = class {
|
|
|
59103
59203
|
source = markdown ?? input.text;
|
|
59104
59204
|
slice = joinable(ctx.get(parserCtx)(source).content);
|
|
59105
59205
|
}
|
|
59206
|
+
if (!this.options.adapter && placeholders.length) {
|
|
59207
|
+
const shown = slice.content.textBetween(0, slice.content.size, "\n", "\n");
|
|
59208
|
+
if (placeholders.some((text) => shown.includes(text))) throw imagesRefused();
|
|
59209
|
+
}
|
|
59106
59210
|
this.assertContext(context, operation);
|
|
59107
59211
|
if (!view.editable || this.options.editable?.() === false) return;
|
|
59108
59212
|
const anchor = this.anchor(operation);
|
|
@@ -59368,6 +59472,12 @@ function dropRange(doc, range) {
|
|
|
59368
59472
|
* keeps the provider's code-language behaviour; invalid metadata pastes plain
|
|
59369
59473
|
* text.
|
|
59370
59474
|
*/
|
|
59475
|
+
function imageFiles(files) {
|
|
59476
|
+
return [...files].filter((file) => file.type.startsWith("image/"));
|
|
59477
|
+
}
|
|
59478
|
+
function imagesRefused() {
|
|
59479
|
+
return new InkKitError("image-unsupported", "The images were not inserted because no image adapter is configured.");
|
|
59480
|
+
}
|
|
59371
59481
|
function claimsPaste(view, event) {
|
|
59372
59482
|
const data = event.clipboardData;
|
|
59373
59483
|
if (!data || !view.editable) return false;
|
|
@@ -59425,6 +59535,210 @@ function dataImage(source) {
|
|
|
59425
59535
|
};
|
|
59426
59536
|
}
|
|
59427
59537
|
//#endregion
|
|
59538
|
+
//#region src/find-session.ts
|
|
59539
|
+
/** The codes of failures that mean the editor cannot answer now, not that the session is wrong. */
|
|
59540
|
+
var transient = [
|
|
59541
|
+
"not-ready",
|
|
59542
|
+
"stale-document",
|
|
59543
|
+
"composition",
|
|
59544
|
+
"operation-pending"
|
|
59545
|
+
];
|
|
59546
|
+
/** The editor refreshes each open session after every edit, selection change, load and mode change. */
|
|
59547
|
+
var EditorFindSession = class {
|
|
59548
|
+
host;
|
|
59549
|
+
onChange;
|
|
59550
|
+
detach;
|
|
59551
|
+
text = "";
|
|
59552
|
+
reported = "";
|
|
59553
|
+
closed = false;
|
|
59554
|
+
busy = false;
|
|
59555
|
+
cached;
|
|
59556
|
+
constructor(host, onChange, detach) {
|
|
59557
|
+
this.host = host;
|
|
59558
|
+
this.onChange = onChange;
|
|
59559
|
+
this.detach = detach;
|
|
59560
|
+
}
|
|
59561
|
+
state(expectedGeneration) {
|
|
59562
|
+
this.assertOpen();
|
|
59563
|
+
return this.measure(expectedGeneration);
|
|
59564
|
+
}
|
|
59565
|
+
find(query, options, expectedGeneration) {
|
|
59566
|
+
this.assertOpen();
|
|
59567
|
+
return this.command(expectedGeneration, () => this.select(query, options?.direction, expectedGeneration));
|
|
59568
|
+
}
|
|
59569
|
+
next(expectedGeneration) {
|
|
59570
|
+
this.assertOpen();
|
|
59571
|
+
return this.command(expectedGeneration, () => this.select(this.text, "next", expectedGeneration));
|
|
59572
|
+
}
|
|
59573
|
+
previous(expectedGeneration) {
|
|
59574
|
+
this.assertOpen();
|
|
59575
|
+
return this.command(expectedGeneration, () => this.select(this.text, "previous", expectedGeneration));
|
|
59576
|
+
}
|
|
59577
|
+
replace(query, replacement, expectedGeneration) {
|
|
59578
|
+
this.assertOpen();
|
|
59579
|
+
return this.command(expectedGeneration, () => {
|
|
59580
|
+
const changed = this.restoring(expectedGeneration, () => {
|
|
59581
|
+
this.select(query, void 0, expectedGeneration);
|
|
59582
|
+
return this.host.replace(query, replacement, expectedGeneration);
|
|
59583
|
+
});
|
|
59584
|
+
const snapshot = this.host.textSnapshot(expectedGeneration);
|
|
59585
|
+
const matches = this.matches(query, snapshot.snapshotId, expectedGeneration);
|
|
59586
|
+
const following = matches.find((range) => range.from >= snapshot.selection.to) ?? matches[0];
|
|
59587
|
+
if (following) this.host.selectTextRange(following, { reveal: true });
|
|
59588
|
+
return changed;
|
|
59589
|
+
});
|
|
59590
|
+
}
|
|
59591
|
+
replaceAll(query, replacement, expectedGeneration) {
|
|
59592
|
+
this.assertOpen();
|
|
59593
|
+
return this.command(expectedGeneration, () => this.restoring(expectedGeneration, () => {
|
|
59594
|
+
this.select(query, void 0, expectedGeneration);
|
|
59595
|
+
return this.host.replaceAll(query, replacement, expectedGeneration);
|
|
59596
|
+
}));
|
|
59597
|
+
}
|
|
59598
|
+
clear(expectedGeneration) {
|
|
59599
|
+
this.assertOpen();
|
|
59600
|
+
this.command(expectedGeneration, () => {
|
|
59601
|
+
this.text = "";
|
|
59602
|
+
this.host.find("", expectedGeneration);
|
|
59603
|
+
});
|
|
59604
|
+
}
|
|
59605
|
+
close() {
|
|
59606
|
+
if (this.closed) return;
|
|
59607
|
+
this.closed = true;
|
|
59608
|
+
this.detach(this);
|
|
59609
|
+
if (!this.text) return;
|
|
59610
|
+
try {
|
|
59611
|
+
this.host.find("");
|
|
59612
|
+
} catch (error) {
|
|
59613
|
+
if (!(error instanceof InkKitError) || !transient.includes(error.code)) throw error;
|
|
59614
|
+
}
|
|
59615
|
+
}
|
|
59616
|
+
/** Reports the state if it changed. The editor calls this after each of its own updates; nothing
|
|
59617
|
+
* it cannot answer now is reported. */
|
|
59618
|
+
refresh(expectedGeneration) {
|
|
59619
|
+
if (this.closed || this.busy) return;
|
|
59620
|
+
let state;
|
|
59621
|
+
try {
|
|
59622
|
+
state = this.measure(expectedGeneration);
|
|
59623
|
+
} catch (error) {
|
|
59624
|
+
if (error instanceof InkKitError && transient.includes(error.code)) return;
|
|
59625
|
+
throw error;
|
|
59626
|
+
}
|
|
59627
|
+
const key = JSON.stringify([
|
|
59628
|
+
state.documentId,
|
|
59629
|
+
state.generation,
|
|
59630
|
+
state.query,
|
|
59631
|
+
state.current,
|
|
59632
|
+
state.total
|
|
59633
|
+
]);
|
|
59634
|
+
if (key === this.reported) return;
|
|
59635
|
+
this.reported = key;
|
|
59636
|
+
this.onChange(state);
|
|
59637
|
+
}
|
|
59638
|
+
/** Forgets the query after a new document loads. */
|
|
59639
|
+
reset() {
|
|
59640
|
+
this.text = "";
|
|
59641
|
+
this.cached = void 0;
|
|
59642
|
+
}
|
|
59643
|
+
/** Highlights the query again where the editor dropped its highlights, such as after a reload or
|
|
59644
|
+
* a mode change, and leaves the selection where it was. */
|
|
59645
|
+
reapply() {
|
|
59646
|
+
if (this.closed) return;
|
|
59647
|
+
this.cached = void 0;
|
|
59648
|
+
if (!this.text) return;
|
|
59649
|
+
this.busy = true;
|
|
59650
|
+
try {
|
|
59651
|
+
const { selection } = this.host.textSnapshot();
|
|
59652
|
+
this.host.find(this.text);
|
|
59653
|
+
this.host.selectTextRange(selection);
|
|
59654
|
+
} catch (error) {
|
|
59655
|
+
if (!(error instanceof InkKitError) || !transient.includes(error.code)) throw error;
|
|
59656
|
+
} finally {
|
|
59657
|
+
this.busy = false;
|
|
59658
|
+
}
|
|
59659
|
+
}
|
|
59660
|
+
assertOpen() {
|
|
59661
|
+
if (this.closed) throw new InkKitError("destroyed", "The find session was closed");
|
|
59662
|
+
}
|
|
59663
|
+
/** Runs a command without reporting the editor's intermediate states, then reports the result. */
|
|
59664
|
+
command(expectedGeneration, run) {
|
|
59665
|
+
this.busy = true;
|
|
59666
|
+
let failed = true;
|
|
59667
|
+
try {
|
|
59668
|
+
const result = run();
|
|
59669
|
+
failed = false;
|
|
59670
|
+
return result;
|
|
59671
|
+
} finally {
|
|
59672
|
+
this.busy = false;
|
|
59673
|
+
if (!failed) this.refresh(expectedGeneration);
|
|
59674
|
+
else try {
|
|
59675
|
+
this.refresh(expectedGeneration);
|
|
59676
|
+
} catch {}
|
|
59677
|
+
}
|
|
59678
|
+
}
|
|
59679
|
+
select(query, direction, expectedGeneration) {
|
|
59680
|
+
const snapshot = this.host.textSnapshot(expectedGeneration);
|
|
59681
|
+
const matches = this.matches(query, snapshot.snapshotId, expectedGeneration);
|
|
59682
|
+
const changedQuery = query !== this.text;
|
|
59683
|
+
let index = matches.findIndex((range) => sameRange(range, snapshot.selection));
|
|
59684
|
+
if (changedQuery || index < 0) {
|
|
59685
|
+
if (direction === "previous") {
|
|
59686
|
+
index = -1;
|
|
59687
|
+
for (let at = matches.length - 1; at >= 0; at -= 1) if (matches[at].to <= snapshot.selection.from) {
|
|
59688
|
+
index = at;
|
|
59689
|
+
break;
|
|
59690
|
+
}
|
|
59691
|
+
if (index < 0) index = matches.length - 1;
|
|
59692
|
+
} else {
|
|
59693
|
+
index = matches.findIndex((range) => range.from >= snapshot.selection.from);
|
|
59694
|
+
if (index < 0) index = 0;
|
|
59695
|
+
}
|
|
59696
|
+
} else if (direction) index = (index + (direction === "next" ? 1 : -1) + matches.length) % matches.length;
|
|
59697
|
+
if (changedQuery || !query) this.host.find(query, expectedGeneration);
|
|
59698
|
+
this.text = query;
|
|
59699
|
+
const match = matches[index];
|
|
59700
|
+
if (match) this.host.selectTextRange(match, { reveal: true });
|
|
59701
|
+
return !!match;
|
|
59702
|
+
}
|
|
59703
|
+
/** Runs an edit and, if it fails, puts the query, highlights and selection back. */
|
|
59704
|
+
restoring(expectedGeneration, run) {
|
|
59705
|
+
const before = this.host.textSnapshot(expectedGeneration);
|
|
59706
|
+
const previous = this.text;
|
|
59707
|
+
try {
|
|
59708
|
+
return run();
|
|
59709
|
+
} catch (error) {
|
|
59710
|
+
this.text = previous;
|
|
59711
|
+
this.host.find(previous, expectedGeneration);
|
|
59712
|
+
this.host.selectTextRange(before.selection);
|
|
59713
|
+
throw error;
|
|
59714
|
+
}
|
|
59715
|
+
}
|
|
59716
|
+
measure(expectedGeneration) {
|
|
59717
|
+
const snapshot = this.host.textSnapshot(expectedGeneration);
|
|
59718
|
+
const matches = this.matches(this.text, snapshot.snapshotId, expectedGeneration);
|
|
59719
|
+
return {
|
|
59720
|
+
documentId: snapshot.documentId,
|
|
59721
|
+
generation: snapshot.generation,
|
|
59722
|
+
revision: snapshot.revision,
|
|
59723
|
+
query: this.text,
|
|
59724
|
+
current: matches.findIndex((range) => sameRange(range, snapshot.selection)) + 1,
|
|
59725
|
+
total: matches.length
|
|
59726
|
+
};
|
|
59727
|
+
}
|
|
59728
|
+
matches(query, snapshotId, expectedGeneration) {
|
|
59729
|
+
if (!query) return [];
|
|
59730
|
+
if (this.cached?.snapshotId !== snapshotId || this.cached.query !== query) this.cached = {
|
|
59731
|
+
snapshotId,
|
|
59732
|
+
query,
|
|
59733
|
+
matches: this.host.searchMatches(query, expectedGeneration)
|
|
59734
|
+
};
|
|
59735
|
+
return this.cached.matches;
|
|
59736
|
+
}
|
|
59737
|
+
};
|
|
59738
|
+
function sameRange(left, right) {
|
|
59739
|
+
return left.snapshotId === right.snapshotId && left.from === right.from && left.to === right.to;
|
|
59740
|
+
}
|
|
59741
|
+
//#endregion
|
|
59428
59742
|
//#region src/session.ts
|
|
59429
59743
|
/**
|
|
59430
59744
|
* The loaded document's identity and counters. Each load must bring a greater `generation` than
|
|
@@ -59998,6 +60312,9 @@ var InkKitEditor = class InkKitEditor {
|
|
|
59998
60312
|
ownsRootClass = false;
|
|
59999
60313
|
activation;
|
|
60000
60314
|
reportingSuppressed = false;
|
|
60315
|
+
/** A reload keeps each find session's query; a load starts without one. */
|
|
60316
|
+
reloading = false;
|
|
60317
|
+
findSessions = /* @__PURE__ */ new Set();
|
|
60001
60318
|
loading = false;
|
|
60002
60319
|
call;
|
|
60003
60320
|
writable = true;
|
|
@@ -60402,6 +60719,14 @@ var InkKitEditor = class InkKitEditor {
|
|
|
60402
60719
|
this.suggestions?.refresh();
|
|
60403
60720
|
if (!this.ready || this.loading || this.reportingSuppressed || this.destroyed) return;
|
|
60404
60721
|
this.events.commandStateChanged?.(this.commandState());
|
|
60722
|
+
this.refreshFindSessions();
|
|
60723
|
+
}
|
|
60724
|
+
refreshFindSessions() {
|
|
60725
|
+
for (const session of [...this.findSessions]) try {
|
|
60726
|
+
session.refresh();
|
|
60727
|
+
} catch (error) {
|
|
60728
|
+
this.report(error);
|
|
60729
|
+
}
|
|
60405
60730
|
}
|
|
60406
60731
|
/** What the editor can do now, for enabling host controls. Unlike `snapshot`, it works during
|
|
60407
60732
|
* composition. */
|
|
@@ -60482,7 +60807,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
60482
60807
|
expectOneOf(mode, editingModes, "mode");
|
|
60483
60808
|
this.assertCurrent(expectedGeneration);
|
|
60484
60809
|
if (!this.document.handler.sourceMode || this.mode === mode) return false;
|
|
60485
|
-
|
|
60810
|
+
const switched = this.source.setMode(mode, {
|
|
60486
60811
|
ctx: this.editor.ctx,
|
|
60487
60812
|
wasSource: this.literalSurface,
|
|
60488
60813
|
container: this.geometry.container,
|
|
@@ -60508,6 +60833,8 @@ var InkKitEditor = class InkKitEditor {
|
|
|
60508
60833
|
},
|
|
60509
60834
|
reveal: () => this.revealCurrentSelection()
|
|
60510
60835
|
});
|
|
60836
|
+
if (switched) for (const session of this.findSessions) session.reapply();
|
|
60837
|
+
return switched;
|
|
60511
60838
|
}
|
|
60512
60839
|
updateSurface() {
|
|
60513
60840
|
this.source.element.hidden = !this.literalSurface;
|
|
@@ -60537,6 +60864,19 @@ var InkKitEditor = class InkKitEditor {
|
|
|
60537
60864
|
this.assertMutation(expectedGeneration);
|
|
60538
60865
|
return this.history.redo();
|
|
60539
60866
|
}
|
|
60867
|
+
/** Drops the steps that `undo` took off the history, so `redo` has nothing to bring back. For a
|
|
60868
|
+
* host that adds content after an undo and must not let a redo resurrect what was undone.
|
|
60869
|
+
* Returns whether a redo was available. The document, selection, revision and undo steps stay
|
|
60870
|
+
* as they are, and no `changed` event is sent. */
|
|
60871
|
+
discardUndone(expectedGeneration) {
|
|
60872
|
+
this.assertMutation(expectedGeneration);
|
|
60873
|
+
const view = this.editor.ctx.get(editorViewCtx);
|
|
60874
|
+
const available = this.history.canRedo(view.state);
|
|
60875
|
+
this.history.discardUndone();
|
|
60876
|
+
discardFormattedRedo(view);
|
|
60877
|
+
if (available) this.publishCommandState();
|
|
60878
|
+
return available;
|
|
60879
|
+
}
|
|
60540
60880
|
/** The complete current document, which is what a host saves. It throws rather than return a
|
|
60541
60881
|
* partial document. */
|
|
60542
60882
|
snapshot(expectedGeneration) {
|
|
@@ -60675,6 +61015,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
60675
61015
|
if (this.destroyed) return;
|
|
60676
61016
|
this.diagnostics.destroy(this.editor.ctx);
|
|
60677
61017
|
this.destroyed = true;
|
|
61018
|
+
this.findSessions.clear();
|
|
60678
61019
|
this.clipboard.clear();
|
|
60679
61020
|
this.ready = false;
|
|
60680
61021
|
this.session.close();
|
|
@@ -60739,6 +61080,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
60739
61080
|
ctx: () => instance.editor.ctx,
|
|
60740
61081
|
context: () => instance.context(),
|
|
60741
61082
|
adapter: options.images,
|
|
61083
|
+
files: !!options.files,
|
|
60742
61084
|
onError: (error) => instance.report(error),
|
|
60743
61085
|
commit: (apply) => instance.facadeCall(apply),
|
|
60744
61086
|
literalText: () => instance.literalSurface,
|
|
@@ -60864,6 +61206,7 @@ var InkKitEditor = class InkKitEditor {
|
|
|
60864
61206
|
this.mode = "formatted";
|
|
60865
61207
|
this.source.reset();
|
|
60866
61208
|
this.search.reset();
|
|
61209
|
+
if (!this.reloading) for (const session of this.findSessions) session.reset();
|
|
60867
61210
|
this.document.handler = handler;
|
|
60868
61211
|
this.source.setSourceValue(handler.richText ? "" : input.text);
|
|
60869
61212
|
this.source.element.setSelectionRange(this.source.element.value.length, this.source.element.value.length);
|
|
@@ -60895,11 +61238,14 @@ var InkKitEditor = class InkKitEditor {
|
|
|
60895
61238
|
const previous = this.document.handler;
|
|
60896
61239
|
const saved = captureReloadSurface(view, this.source.element, this.geometry.container, wasLiteral);
|
|
60897
61240
|
this.reportingSuppressed = true;
|
|
61241
|
+
this.reloading = true;
|
|
60898
61242
|
try {
|
|
60899
61243
|
this.loadDocument(document);
|
|
60900
61244
|
if (previous.sourceMode && this.document.handler.sourceMode && previousMode === "source") this.setEditingMode("source", input.generation);
|
|
60901
61245
|
restoreReloadSurface(view, this.source.element, () => this.literalSurface, saved);
|
|
61246
|
+
for (const session of this.findSessions) session.reapply();
|
|
60902
61247
|
} finally {
|
|
61248
|
+
this.reloading = false;
|
|
60903
61249
|
this.reportingSuppressed = false;
|
|
60904
61250
|
this.publishCommandState();
|
|
60905
61251
|
}
|
|
@@ -61052,6 +61398,24 @@ var InkKitEditor = class InkKitEditor {
|
|
|
61052
61398
|
const count = this.search.replace(search, replacement, true);
|
|
61053
61399
|
return count && replacement !== search && this.refusedRichEdit(doc) ? 0 : count;
|
|
61054
61400
|
}
|
|
61401
|
+
/**
|
|
61402
|
+
* Opens a find session, which keeps a query and reports its match count and position to
|
|
61403
|
+
* `onChange` whenever they change. Open one session per editor: the editor has one set of
|
|
61404
|
+
* highlights.
|
|
61405
|
+
*/
|
|
61406
|
+
findSession(onChange) {
|
|
61407
|
+
this.assertAlive();
|
|
61408
|
+
if (typeof onChange !== "function") throw invalidArgument("onChange must be a function");
|
|
61409
|
+
const session = new EditorFindSession(this, (state) => {
|
|
61410
|
+
try {
|
|
61411
|
+
onChange(state);
|
|
61412
|
+
} catch (error) {
|
|
61413
|
+
if (typeof globalThis.reportError === "function") globalThis.reportError(error);
|
|
61414
|
+
}
|
|
61415
|
+
}, (closed) => this.findSessions.delete(closed));
|
|
61416
|
+
this.findSessions.add(session);
|
|
61417
|
+
return session;
|
|
61418
|
+
}
|
|
61055
61419
|
outlineContext() {
|
|
61056
61420
|
const { documentId, generation, revision, key } = this.session.capture();
|
|
61057
61421
|
return {
|
|
@@ -61361,8 +61725,10 @@ var InkKitEditor = class InkKitEditor {
|
|
|
61361
61725
|
"replaceSource",
|
|
61362
61726
|
"undo",
|
|
61363
61727
|
"redo",
|
|
61728
|
+
"discardUndone",
|
|
61364
61729
|
"find",
|
|
61365
61730
|
"searchMatches",
|
|
61731
|
+
"findSession",
|
|
61366
61732
|
"replace",
|
|
61367
61733
|
"replaceAll",
|
|
61368
61734
|
"format",
|
|
@@ -61456,4 +61822,45 @@ var InkKitEditor = class InkKitEditor {
|
|
|
61456
61822
|
}
|
|
61457
61823
|
};
|
|
61458
61824
|
//#endregion
|
|
61459
|
-
|
|
61825
|
+
//#region src/link-address.ts
|
|
61826
|
+
var openable = /* @__PURE__ */ new Set([
|
|
61827
|
+
"http",
|
|
61828
|
+
"https",
|
|
61829
|
+
"mailto",
|
|
61830
|
+
"tel"
|
|
61831
|
+
]);
|
|
61832
|
+
var schemePrefix = /^(?:[a-z][a-z0-9+.-]*:\/\/|(?:mailto|tel):)/i;
|
|
61833
|
+
/**
|
|
61834
|
+
* The address a Link field should write for what the person typed, or `undefined` when it is not
|
|
61835
|
+
* a web, mail or phone address. See the reference, which describes each rule.
|
|
61836
|
+
*/
|
|
61837
|
+
function normalizeLinkAddress(input) {
|
|
61838
|
+
const text = input.trim();
|
|
61839
|
+
if (!text || /[\s\u0000-\u001f\u007f]/.test(text)) return void 0;
|
|
61840
|
+
const prefix = schemePrefix.exec(text);
|
|
61841
|
+
let address;
|
|
61842
|
+
if (prefix) address = prefix[0].toLowerCase() + text.slice(prefix[0].length);
|
|
61843
|
+
else if (text.startsWith("/")) return void 0;
|
|
61844
|
+
else if (text.includes("@") && !text.includes("/")) address = `mailto:${text}`;
|
|
61845
|
+
else address = `https://${text}`;
|
|
61846
|
+
const scheme = address.slice(0, address.indexOf(":"));
|
|
61847
|
+
if (scheme === "http" || scheme === "https") try {
|
|
61848
|
+
return new URL(address).hostname ? address : void 0;
|
|
61849
|
+
} catch {
|
|
61850
|
+
return;
|
|
61851
|
+
}
|
|
61852
|
+
if (scheme === "mailto" || scheme === "tel") return address.length > scheme.length + 1 ? address : void 0;
|
|
61853
|
+
}
|
|
61854
|
+
/**
|
|
61855
|
+
* Whether a host may open `address` for the person. Only `http`, `https`, `mailto` and `tel`
|
|
61856
|
+
* qualify, whatever the letter case. An address with no scheme, an unknown scheme such as
|
|
61857
|
+
* `javascript:` or `file:`, or a control character does not.
|
|
61858
|
+
*/
|
|
61859
|
+
function canOpenLink(address) {
|
|
61860
|
+
const text = address.replace(/^[ \t\n\f\r]+|[ \t\n\f\r]+$/g, "");
|
|
61861
|
+
if (/[\u0000-\u001f\u007f]/.test(text)) return false;
|
|
61862
|
+
const colon = text.search(/[:/?#\\]|$/);
|
|
61863
|
+
return text[colon] === ":" && openable.has(text.slice(0, colon).toLowerCase());
|
|
61864
|
+
}
|
|
61865
|
+
//#endregion
|
|
61866
|
+
export { InkKitError as a, DecorationSet as c, ok$1 as d, __commonJSMin as f, registerDiagram as i, Plugin as l, normalizeLinkAddress as n, $prose as o, __toESM as p, InkKitEditor as r, Decoration as s, canOpenLink as t, PluginKey as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as DecorationSet, f as __commonJSMin, l as Plugin, o as $prose, p as __toESM, s as Decoration, u as PluginKey } from "./core-B7CD5hsd.js";
|
|
2
2
|
//#region node_modules/.pnpm/highlight.js@11.11.2/node_modules/highlight.js/es/languages/arduino.js
|
|
3
3
|
/** @type LanguageFn */
|
|
4
4
|
function cPlusPlus(hljs) {
|
package/dist/core.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { InkKitEditor } from './editor.js';
|
|
2
2
|
export type { EditorEvents, EditorOptions, TextInputPreferences, CommandState, EditingMode, CaretState, Mark, Block, FormatCommand, FormatOptions, KeyInput, ImageInsertion, ShortcutName, Keymap, } from './editor.js';
|
|
3
3
|
export { InkKitError } from './types.js';
|
|
4
|
-
export
|
|
4
|
+
export { normalizeLinkAddress, canOpenLink } from './link-address.js';
|
|
5
|
+
export type { DocumentFormat, TextDocumentFormat, TextDocumentInput, RichTextDocumentInput, TextDocumentSnapshot, RichTextDocumentSnapshot, RichTextDocument, RichTextBlock, RichTextListItem, RichTextTableCell, RichTextInline, RichTextMark, FormatLoss, FormatLossCode, ConvertedDocument, FormatPromise, OfferedFormat, EditorLabels, Heading, TableCommand, TableOptions, BlockMoveDirection, DocumentContext, DocumentInput, DocumentSnapshot, DocumentVersion, EditorErrorCode, ImageAdapter, ImageImportContext, WikiLinkReference, WikiLinkAdapter, FileReference, ClientPoint, FileContext, FilePresentation, FileAdapter, CapturedImage, PortableImage, ClipboardInput, ClipboardOutput, ClipboardScope, ClipboardImage, ClipboardDiagram, PrintableDocument, PrintableWarning, TextRange, FindState, FindSession, ReadableTextSnapshot, TextRect, ViewportInsets, ViewportOptions, ViewportSnapshot, } from './types.js';
|
|
5
6
|
export type { SlashMenuOptions, SlashCommandName, SlashCommand } from './types.js';
|
|
6
7
|
export type { DiagnosticReport, DiagnosticEvent, DiagnosticState, DiagnosticPresentation, } from './diagnostics.js';
|
package/dist/core.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { InkKitEditor, InkKitError };
|
|
1
|
+
import { a as InkKitError, n as normalizeLinkAddress, r as InkKitEditor, t as canOpenLink } from "./chunks/core-B7CD5hsd.js";
|
|
2
|
+
export { InkKitEditor, InkKitError, canOpenLink, normalizeLinkAddress };
|
package/dist/editor.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DiagnosticReport } from './diagnostics.js';
|
|
2
2
|
import type { SlashMenuOptions } from './types.js';
|
|
3
|
-
import { InkKitError, type ClientPoint, type DocumentFormat, type DocumentInput, type DocumentSnapshot, type ConvertedDocument, type TextDocumentFormat, type ImageAdapter, type FileAdapter, type WikiLinkAdapter, type ClipboardInput, type ClipboardOutput, type ClipboardScope, type DocumentVersion, type PrintableDocument, type TextRange, type ReadableTextSnapshot, type TextRect, type ViewportOptions, type ViewportSnapshot, type EditorLabels, type Heading, type TableCommand, type TableOptions, type BlockMoveDirection, type OfferedFormat } from './types.js';
|
|
3
|
+
import { InkKitError, type ClientPoint, type DocumentFormat, type DocumentInput, type DocumentSnapshot, type ConvertedDocument, type TextDocumentFormat, type ImageAdapter, type FileAdapter, type WikiLinkAdapter, type ClipboardInput, type ClipboardOutput, type ClipboardScope, type DocumentVersion, type PrintableDocument, type TextRange, type ReadableTextSnapshot, type FindSession, type FindState, type TextRect, type ViewportOptions, type ViewportSnapshot, type EditorLabels, type Heading, type TableCommand, type TableOptions, type BlockMoveDirection, type OfferedFormat } from './types.js';
|
|
4
4
|
/** An inline format that `CaretState` can report. */
|
|
5
5
|
export type Mark = 'bold' | 'italic' | 'strikethrough' | 'highlight' | 'underline' | 'superscript' | 'subscript' | 'code' | 'link';
|
|
6
6
|
/** The kind of block that holds the start of the selection. Any other block reports `paragraph`. */
|
|
@@ -27,6 +27,10 @@ export interface CaretState {
|
|
|
27
27
|
block: Block;
|
|
28
28
|
/** One quote holds the whole selection; the block is what sits inside it. */
|
|
29
29
|
quoted: boolean;
|
|
30
|
+
/** The address of the link at the caret or, for a range, of the first link in it, as the
|
|
31
|
+
* document holds it. Present exactly when `marks` includes `'link'`. For a reference link, it
|
|
32
|
+
* is the address its definition gives. A host's Link sheet starts from it. */
|
|
33
|
+
href?: string;
|
|
30
34
|
/** In an RTF document, the alignment of the paragraph that holds the start of the selection. */
|
|
31
35
|
align?: 'left' | 'center' | 'right' | 'justify';
|
|
32
36
|
}
|
|
@@ -178,6 +182,9 @@ export declare class InkKitEditor<F extends DocumentFormat = TextDocumentFormat>
|
|
|
178
182
|
private ownsRootClass;
|
|
179
183
|
private activation;
|
|
180
184
|
private reportingSuppressed;
|
|
185
|
+
/** A reload keeps each find session's query; a load starts without one. */
|
|
186
|
+
private reloading;
|
|
187
|
+
private readonly findSessions;
|
|
181
188
|
private loading;
|
|
182
189
|
private call?;
|
|
183
190
|
private writable;
|
|
@@ -268,6 +275,7 @@ export declare class InkKitEditor<F extends DocumentFormat = TextDocumentFormat>
|
|
|
268
275
|
setTextInputPreferences(preferences: TextInputPreferences): void;
|
|
269
276
|
private applyInputPolicy;
|
|
270
277
|
private publishCommandState;
|
|
278
|
+
private refreshFindSessions;
|
|
271
279
|
/** What the editor can do now, for enabling host controls. Unlike `snapshot`, it works during
|
|
272
280
|
* composition. */
|
|
273
281
|
commandState(expectedGeneration?: number): CommandState;
|
|
@@ -289,6 +297,11 @@ export declare class InkKitEditor<F extends DocumentFormat = TextDocumentFormat>
|
|
|
289
297
|
undo(expectedGeneration?: number): boolean;
|
|
290
298
|
/** Returns whether a history step applied. */
|
|
291
299
|
redo(expectedGeneration?: number): boolean;
|
|
300
|
+
/** Drops the steps that `undo` took off the history, so `redo` has nothing to bring back. For a
|
|
301
|
+
* host that adds content after an undo and must not let a redo resurrect what was undone.
|
|
302
|
+
* Returns whether a redo was available. The document, selection, revision and undo steps stay
|
|
303
|
+
* as they are, and no `changed` event is sent. */
|
|
304
|
+
discardUndone(expectedGeneration?: number): boolean;
|
|
292
305
|
/** The complete current document, which is what a host saves. It throws rather than return a
|
|
293
306
|
* partial document. */
|
|
294
307
|
snapshot(expectedGeneration?: number): DocumentSnapshot<F>;
|
|
@@ -379,6 +392,12 @@ export declare class InkKitEditor<F extends DocumentFormat = TextDocumentFormat>
|
|
|
379
392
|
replace(search: string, replacement: string, expectedGeneration?: number): boolean;
|
|
380
393
|
/** Replaces every non-overlapping match once and returns how many. */
|
|
381
394
|
replaceAll(search: string, replacement: string, expectedGeneration?: number): number;
|
|
395
|
+
/**
|
|
396
|
+
* Opens a find session, which keeps a query and reports its match count and position to
|
|
397
|
+
* `onChange` whenever they change. Open one session per editor: the editor has one set of
|
|
398
|
+
* highlights.
|
|
399
|
+
*/
|
|
400
|
+
findSession(onChange: (state: FindState) => void): FindSession;
|
|
382
401
|
private outlineContext;
|
|
383
402
|
/** The outline in document order. Entries go stale when the document changes. */
|
|
384
403
|
headings(expectedGeneration?: number): readonly Heading[];
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as InkKitError, i as registerDiagram, n as normalizeLinkAddress, r as InkKitEditor, t as canOpenLink } from "./chunks/core-B7CD5hsd.js";
|
|
2
2
|
//#region node_modules/.pnpm/dompurify@3.4.17/node_modules/dompurify/dist/purify.es.mjs
|
|
3
3
|
/*! @license DOMPurify 3.4.17 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.17/LICENSE */
|
|
4
4
|
function _OverloadYield(e, d) {
|
|
@@ -32790,4 +32790,4 @@ function renderPele(source) {
|
|
|
32790
32790
|
//#region src/index.ts
|
|
32791
32791
|
registerDiagram(renderPele);
|
|
32792
32792
|
//#endregion
|
|
32793
|
-
export { InkKitEditor, InkKitError };
|
|
32793
|
+
export { InkKitEditor, InkKitError, canOpenLink, normalizeLinkAddress };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The address a Link field should write for what the person typed, or `undefined` when it is not
|
|
3
|
+
* a web, mail or phone address. See the reference, which describes each rule.
|
|
4
|
+
*/
|
|
5
|
+
export declare function normalizeLinkAddress(input: string): string | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Whether a host may open `address` for the person. Only `http`, `https`, `mailto` and `tel`
|
|
8
|
+
* qualify, whatever the letter case. An address with no scheme, an unknown scheme such as
|
|
9
|
+
* `javascript:` or `file:`, or a control character does not.
|
|
10
|
+
*/
|
|
11
|
+
export declare function canOpenLink(address: string): boolean;
|
package/dist/types.d.ts
CHANGED
|
@@ -120,7 +120,7 @@ export interface RichTextDocumentSnapshot extends RichTextDocumentInput, Documen
|
|
|
120
120
|
dirty: boolean;
|
|
121
121
|
}
|
|
122
122
|
/** The closed list of failure codes. The API reference describes each one. */
|
|
123
|
-
export declare const editorErrorCodes: readonly ['not-ready', 'destroyed', 'stale-document', 'composition', 'operation-pending', 'read-only', 'invalid-argument', 'invalid-range', 'preservation', 'image-unavailable', 'diagram-unavailable', 'file-unavailable', 'clipboard-unavailable', 'slash-command-failed', 'internal'];
|
|
123
|
+
export declare const editorErrorCodes: readonly ['not-ready', 'destroyed', 'stale-document', 'composition', 'operation-pending', 'read-only', 'invalid-argument', 'invalid-range', 'preservation', 'image-unavailable', 'image-unsupported', 'diagram-unavailable', 'file-unavailable', 'clipboard-unavailable', 'slash-command-failed', 'internal'];
|
|
124
124
|
export type EditorErrorCode = (typeof editorErrorCodes)[number];
|
|
125
125
|
/** Every failure InkKit reports. Hosts branch on `code`; `message` is for logs. When the failure
|
|
126
126
|
* started elsewhere, such as in an adapter, the host clipboard or the renderer, `cause` holds the
|
|
@@ -310,6 +310,44 @@ export interface ReadableTextSnapshot extends DocumentVersion {
|
|
|
310
310
|
text: string;
|
|
311
311
|
selection: TextRange;
|
|
312
312
|
}
|
|
313
|
+
/** What a find session shows: how many matches the query has and which one the selection is on. */
|
|
314
|
+
export interface FindState extends DocumentVersion {
|
|
315
|
+
/** The query, or an empty string when there is none. */
|
|
316
|
+
query: string;
|
|
317
|
+
/** The position, from 1, of the match that the selection covers exactly, or 0 when the selection
|
|
318
|
+
* is not on a match. */
|
|
319
|
+
current: number;
|
|
320
|
+
/** The number of matches. */
|
|
321
|
+
total: number;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* A find bar's state and commands: the query, the match count, the match the selection is on, and
|
|
325
|
+
* navigation that wraps. Open one with `InkKitEditor.findSession`.
|
|
326
|
+
*/
|
|
327
|
+
export interface FindSession {
|
|
328
|
+
/** The current state. It does not call the change handler. */
|
|
329
|
+
state(expectedGeneration?: number): FindState;
|
|
330
|
+
/** Sets the query, highlights its matches and selects one. A new query selects the first match
|
|
331
|
+
* at or after the selection, or the last one before it with `direction: 'previous'`. With the
|
|
332
|
+
* same query, the selection moves to the next or previous match and wraps at the ends; without
|
|
333
|
+
* a direction, a selection on a match stays there. Returns whether there is a match. */
|
|
334
|
+
find(query: string, options?: {
|
|
335
|
+
direction?: 'next' | 'previous';
|
|
336
|
+
}, expectedGeneration?: number): boolean;
|
|
337
|
+
/** Moves to the next match, wrapping at the end. Returns whether there is a match. */
|
|
338
|
+
next(expectedGeneration?: number): boolean;
|
|
339
|
+
/** Moves to the previous match, wrapping at the start. Returns whether there is a match. */
|
|
340
|
+
previous(expectedGeneration?: number): boolean;
|
|
341
|
+
/** Replaces the selected match, or the next one, and selects the match after it. Returns whether
|
|
342
|
+
* the text changed. A match that already reads as the replacement is skipped without a change. */
|
|
343
|
+
replace(query: string, replacement: string, expectedGeneration?: number): boolean;
|
|
344
|
+
/** Replaces every match and returns how many were replaced. */
|
|
345
|
+
replaceAll(query: string, replacement: string, expectedGeneration?: number): number;
|
|
346
|
+
/** Clears the query and the highlights. */
|
|
347
|
+
clear(expectedGeneration?: number): void;
|
|
348
|
+
/** Stops the session: it clears the highlights and its handler is not called again. */
|
|
349
|
+
close(): void;
|
|
350
|
+
}
|
|
313
351
|
/** A rectangle in CSS pixels in the web view's client coordinate space. */
|
|
314
352
|
export interface TextRect {
|
|
315
353
|
left: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aicayzer/inkkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "A preserving Markdown editor for offline web views and the web",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -55,6 +55,8 @@
|
|
|
55
55
|
"test:package": "node scripts/test-package.mjs",
|
|
56
56
|
"check": "pnpm typecheck && pnpm test && pnpm build && pnpm test:docs && pnpm test:package",
|
|
57
57
|
"test:browser": "playwright test --project=chromium",
|
|
58
|
+
"test:playground": "playwright test --config playwright.playground.config.ts --project=chromium",
|
|
59
|
+
"measure:browser": "playwright test --config playwright.measure.config.ts",
|
|
58
60
|
"test:built-playground": "playwright test --config playwright.built.config.ts"
|
|
59
61
|
},
|
|
60
62
|
"devDependencies": {
|