@aicayzer/inkkit 0.0.17 → 0.1.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.
Files changed (81) hide show
  1. package/NOTICE +4 -2
  2. package/README.md +12 -6
  3. package/dist/THIRD-PARTY-NOTICES.txt +2742 -0
  4. package/dist/chunks/core-vtCr4MBS.js +56503 -0
  5. package/dist/chunks/highlight-Daj2fv_u.js +14122 -0
  6. package/dist/core.d.ts +4 -0
  7. package/dist/core.js +2 -0
  8. package/dist/editor.d.ts +261 -48
  9. package/dist/index.d.ts +1 -7
  10. package/dist/index.js +5 -2
  11. package/dist/style.css +242 -221
  12. package/dist/types.d.ts +143 -18
  13. package/package.json +26 -15
  14. package/dist/autolink.d.ts +0 -1
  15. package/dist/autolink.js +0 -18
  16. package/dist/callouts.d.ts +0 -26
  17. package/dist/callouts.js +0 -311
  18. package/dist/clipboard.d.ts +0 -11
  19. package/dist/clipboard.js +0 -261
  20. package/dist/code-fences.d.ts +0 -8
  21. package/dist/code-fences.js +0 -166
  22. package/dist/comments.d.ts +0 -55
  23. package/dist/comments.js +0 -494
  24. package/dist/decorations.d.ts +0 -2
  25. package/dist/decorations.js +0 -67
  26. package/dist/dialect.d.ts +0 -9
  27. package/dist/dialect.js +0 -358
  28. package/dist/editor.js +0 -2441
  29. package/dist/files.d.ts +0 -40
  30. package/dist/files.js +0 -133
  31. package/dist/highlight.d.ts +0 -1
  32. package/dist/highlight.js +0 -136
  33. package/dist/image-blocks.d.ts +0 -71
  34. package/dist/image-blocks.js +0 -286
  35. package/dist/images.d.ts +0 -51
  36. package/dist/images.js +0 -398
  37. package/dist/inline-highlight.d.ts +0 -6
  38. package/dist/inline-highlight.js +0 -112
  39. package/dist/labels.d.ts +0 -36
  40. package/dist/labels.js +0 -34
  41. package/dist/linked-syntax.d.ts +0 -48
  42. package/dist/linked-syntax.js +0 -320
  43. package/dist/literals.d.ts +0 -19
  44. package/dist/literals.js +0 -211
  45. package/dist/mermaid.d.ts +0 -8
  46. package/dist/mermaid.js +0 -321
  47. package/dist/outline.d.ts +0 -22
  48. package/dist/outline.js +0 -79
  49. package/dist/paste-html.d.ts +0 -23
  50. package/dist/paste-html.js +0 -441
  51. package/dist/paste.d.ts +0 -26
  52. package/dist/paste.js +0 -482
  53. package/dist/portable-files.d.ts +0 -10
  54. package/dist/portable-files.js +0 -36
  55. package/dist/preserve.d.ts +0 -21
  56. package/dist/preserve.js +0 -757
  57. package/dist/print.d.ts +0 -7
  58. package/dist/print.js +0 -409
  59. package/dist/reference-clipboard.d.ts +0 -8
  60. package/dist/reference-clipboard.js +0 -201
  61. package/dist/references.d.ts +0 -14
  62. package/dist/references.js +0 -368
  63. package/dist/search.d.ts +0 -15
  64. package/dist/search.js +0 -202
  65. package/dist/selection.d.ts +0 -1
  66. package/dist/selection.js +0 -59
  67. package/dist/source.d.ts +0 -16
  68. package/dist/source.js +0 -57
  69. package/dist/spreadsheet.d.ts +0 -3
  70. package/dist/spreadsheet.js +0 -275
  71. package/dist/table-alignment.d.ts +0 -2
  72. package/dist/table-alignment.js +0 -46
  73. package/dist/tables.d.ts +0 -27
  74. package/dist/tables.js +0 -322
  75. package/dist/tasks.d.ts +0 -3
  76. package/dist/tasks.js +0 -51
  77. package/dist/text-ranges.d.ts +0 -29
  78. package/dist/text-ranges.js +0 -256
  79. package/dist/types.js +0 -8
  80. package/dist/wiki-view.d.ts +0 -21
  81. package/dist/wiki-view.js +0 -78
@@ -1,368 +0,0 @@
1
- import { editorLabels } from './labels.js';
2
- import { $node, $remark, $prose } from '@milkdown/kit/utils';
3
- import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
4
- import { linkSchema } from '@milkdown/kit/preset/commonmark';
5
- import { normalizeIdentifier } from 'micromark-util-normalize-identifier';
6
- import { gfmFootnote } from 'micromark-extension-gfm-footnote';
7
- import { gfmFootnoteFromMarkdown, gfmFootnoteToMarkdown, } from 'mdast-util-gfm-footnote';
8
- import { defaultHandlers } from 'mdast-util-to-markdown';
9
- export function normaliseLabel(label) {
10
- return normalizeIdentifier(label).toLowerCase();
11
- }
12
- function definitions(doc, type) {
13
- const found = new Map();
14
- doc.descendants((node, pos) => {
15
- if (node.type.name !== type)
16
- return true;
17
- const identifier = normaliseLabel(String(node.attrs.identifier));
18
- if (!found.has(identifier))
19
- found.set(identifier, { node, pos });
20
- return false;
21
- });
22
- return found;
23
- }
24
- export const referenceDefinitions = (doc) => definitions(doc, 'reference_definition');
25
- export const footnoteDefinitions = (doc) => definitions(doc, 'footnote_definition');
26
- function contentShape(value) {
27
- const clean = (value) => {
28
- if (Array.isArray(value))
29
- return value.map(clean);
30
- if (value && typeof value === 'object')
31
- return Object.fromEntries(Object.entries(value)
32
- .filter(([key]) => !['position', 'data', 'marker', 'isMark'].includes(key))
33
- .sort(([left], [right]) => left.localeCompare(right))
34
- .map(([key, value]) => [key, clean(value)]));
35
- return value;
36
- };
37
- return JSON.stringify(clean(value));
38
- }
39
- const labelPlaceholder = 'inkkit-authored-label';
40
- const authoredLinkReference = (untyped, parent, state, info) => {
41
- const node = untyped;
42
- const full = defaultHandlers.linkReference({
43
- ...node,
44
- label: labelPlaceholder,
45
- identifier: labelPlaceholder,
46
- referenceType: 'full',
47
- }, parent, state, info);
48
- const display = full.slice(1, -labelPlaceholder.length - 3);
49
- const unchanged = node.referenceContent != null &&
50
- node.referenceContent === contentShape(node.children);
51
- if (node.referenceType !== 'full' &&
52
- (unchanged || normaliseLabel(display) === normaliseLabel(node.identifier)))
53
- return `[${unchanged ? node.label : display}]${node.referenceType === 'collapsed' ? '[]' : ''}`;
54
- // Raw entity and escape spelling participates in reference matching.
55
- return (full.slice(0, -labelPlaceholder.length - 2) +
56
- `[${node.label ?? node.identifier}]`);
57
- };
58
- authoredLinkReference.peek = () => '[';
59
- const authoredDefinition = (node, parent, state, info) => defaultHandlers
60
- .definition({ ...node, label: labelPlaceholder, identifier: labelPlaceholder }, parent, state, info)
61
- .replace(`[${labelPlaceholder}]:`, `[${String(node.label ?? node.identifier)}]:`);
62
- const footnoteHandlers = gfmFootnoteToMarkdown().handlers;
63
- const authoredFootnoteReference = (node) => `[^${String(node.label ?? node.identifier)}]`;
64
- authoredFootnoteReference.peek = () => '[';
65
- const authoredFootnoteDefinition = (node, parent, state, info) => footnoteHandlers.footnoteDefinition({ ...node, label: labelPlaceholder, identifier: labelPlaceholder }, parent, state, info).replace(`[^${labelPlaceholder}]:`, `[^${String(node.label ?? node.identifier)}]:`);
66
- function remarkReferences() {
67
- const data = this.data();
68
- (data.micromarkExtensions ??= []).push(gfmFootnote());
69
- (data.fromMarkdownExtensions ??= []).push(gfmFootnoteFromMarkdown());
70
- (data.toMarkdownExtensions ??= []).push(gfmFootnoteToMarkdown());
71
- (data.toMarkdownExtensions ??= []).push({
72
- handlers: {
73
- linkReference: authoredLinkReference,
74
- definition: authoredDefinition,
75
- footnoteReference: authoredFootnoteReference,
76
- footnoteDefinition: authoredFootnoteDefinition,
77
- },
78
- });
79
- return (tree, file) => {
80
- const source = String(file.value).replace(/^\uFEFF/, '');
81
- const targets = new Map();
82
- const walk = (node, visit) => {
83
- visit(node);
84
- if ('children' in node)
85
- node.children.forEach((child) => walk(child, visit));
86
- };
87
- walk(tree, (node) => {
88
- const start = node.position?.start.offset;
89
- const end = node.position?.end.offset;
90
- if (start != null && end != null) {
91
- const raw = source.slice(start, end);
92
- if (node.type === 'definition' || node.type === 'footnoteDefinition') {
93
- const label = /^\[((?:\\[\s\S]|[^\\[\]])*)\]:/.exec(raw)?.[1];
94
- if (label != null)
95
- node.label =
96
- node.type === 'footnoteDefinition' ? label.slice(1) : label;
97
- }
98
- else if (node.type === 'footnoteReference')
99
- node.label = raw.slice(2, -1);
100
- else if (node.type === 'linkReference') {
101
- const label = node.referenceType === 'full'
102
- ? /\[((?:\\[\s\S]|[^\\[\]])*)\]$/.exec(raw)?.[1]
103
- : raw.slice(1, node.referenceType === 'collapsed' ? -3 : -1);
104
- if (label != null)
105
- node.label = label;
106
- Object.assign(node, { referenceContent: contentShape(node.children) });
107
- }
108
- }
109
- if (node.type === 'definition' && !targets.has(node.identifier))
110
- targets.set(node.identifier, { url: node.url, title: node.title });
111
- });
112
- walk(tree, (node) => {
113
- if (node.type !== 'linkReference')
114
- return;
115
- const target = targets.get(node.identifier);
116
- if (target)
117
- Object.assign(node, target);
118
- });
119
- };
120
- }
121
- export const remarkReferencesPlugin = $remark('inkkitReferences', () => remarkReferences);
122
- export const referenceLinks = linkSchema.extendSchema((base) => (ctx) => {
123
- const schema = base(ctx);
124
- return {
125
- ...schema,
126
- // Label formatting belongs inside a reference, where its source determines the identifier.
127
- priority: 40,
128
- attrs: {
129
- ...schema.attrs,
130
- label: { default: null },
131
- identifier: { default: null },
132
- referenceType: { default: null },
133
- referenceContent: { default: null },
134
- },
135
- parseDOM: [
136
- {
137
- tag: 'a[href]',
138
- getAttrs(dom) {
139
- const element = dom;
140
- return {
141
- href: element.getAttribute('href') ?? '',
142
- title: element.getAttribute('title'),
143
- label: element.getAttribute('data-inkkit-label'),
144
- identifier: element.getAttribute('data-inkkit-reference'),
145
- referenceType: element.getAttribute('data-inkkit-reference-type'),
146
- referenceContent: element.getAttribute('data-inkkit-reference-content'),
147
- };
148
- },
149
- },
150
- ],
151
- toDOM(mark) {
152
- const dom = schema.toDOM(mark, false);
153
- const attrs = { ...dom[1] };
154
- delete attrs.label;
155
- delete attrs.identifier;
156
- delete attrs.referenceType;
157
- delete attrs.referenceContent;
158
- if (mark.attrs.identifier != null) {
159
- attrs['data-inkkit-reference'] = mark.attrs.identifier;
160
- attrs['data-inkkit-label'] = mark.attrs.label;
161
- attrs['data-inkkit-reference-type'] = mark.attrs.referenceType;
162
- attrs['data-inkkit-reference-content'] = mark.attrs.referenceContent;
163
- }
164
- return ['a', attrs];
165
- },
166
- parseMarkdown: {
167
- match: (node) => node.type === 'link' || node.type === 'linkReference',
168
- runner(state, node, type) {
169
- if (node.type === 'link')
170
- return schema.parseMarkdown.runner(state, node, type);
171
- state.openMark(type, {
172
- href: String(node.url ?? ''),
173
- title: node.title ?? null,
174
- label: String(node.label ?? node.identifier),
175
- identifier: String(node.identifier),
176
- referenceType: String(node.referenceType),
177
- referenceContent: node.referenceContent ?? null,
178
- });
179
- state.next(node.children);
180
- state.closeMark(type);
181
- },
182
- },
183
- toMarkdown: {
184
- ...schema.toMarkdown,
185
- runner(state, mark, node) {
186
- if (mark.attrs.identifier == null)
187
- return schema.toMarkdown.runner(state, mark, node);
188
- state.withMark(mark, 'linkReference', undefined, {
189
- identifier: mark.attrs.identifier,
190
- label: mark.attrs.label,
191
- referenceType: mark.attrs.referenceType,
192
- referenceContent: mark.attrs.referenceContent,
193
- });
194
- },
195
- },
196
- };
197
- });
198
- const associationAttrs = {
199
- label: { default: '' },
200
- identifier: { default: '' },
201
- };
202
- export const referenceDefinition = $node('reference_definition', () => ({
203
- group: 'block',
204
- atom: true,
205
- defining: true,
206
- attrs: {
207
- ...associationAttrs,
208
- url: { default: '' },
209
- title: { default: null },
210
- },
211
- parseDOM: [
212
- {
213
- tag: '[data-inkkit-reference-definition]',
214
- getAttrs: (dom) => ({
215
- label: dom.getAttribute('data-inkkit-label') ?? '',
216
- identifier: dom.getAttribute('data-inkkit-reference-definition') ?? '',
217
- url: dom.getAttribute('data-inkkit-url') ?? '',
218
- title: dom.getAttribute('data-inkkit-title'),
219
- }),
220
- },
221
- ],
222
- toDOM: (node) => [
223
- 'div',
224
- {
225
- class: 'inkkit-reference-definition',
226
- 'data-inkkit-reference-definition': node.attrs.identifier,
227
- 'data-inkkit-label': node.attrs.label,
228
- 'data-inkkit-url': node.attrs.url,
229
- 'data-inkkit-title': node.attrs.title,
230
- },
231
- `[${node.attrs.label}]: ${node.attrs.url}${node.attrs.title ? ` "${node.attrs.title}"` : ''}`,
232
- ],
233
- parseMarkdown: {
234
- match: (node) => node.type === 'definition',
235
- runner(state, node, type) {
236
- state.addNode(type, {
237
- label: String(node.label ?? node.identifier),
238
- identifier: String(node.identifier),
239
- url: String(node.url),
240
- title: node.title ?? null,
241
- });
242
- },
243
- },
244
- toMarkdown: {
245
- match: (node) => node.type.name === 'reference_definition',
246
- runner: (state, node) => {
247
- state.addNode('definition', undefined, undefined, { ...node.attrs });
248
- },
249
- },
250
- }));
251
- export const footnoteReference = $node('footnote_reference', (ctx) => ({
252
- inline: true,
253
- group: 'inline',
254
- atom: true,
255
- selectable: true,
256
- attrs: associationAttrs,
257
- parseDOM: [
258
- {
259
- tag: 'sup[data-inkkit-footnote-reference]',
260
- getAttrs: (dom) => ({
261
- label: dom.getAttribute('data-inkkit-label') ?? '',
262
- identifier: dom.getAttribute('data-inkkit-footnote-reference') ?? '',
263
- }),
264
- },
265
- ],
266
- toDOM: (node) => [
267
- 'sup',
268
- {
269
- class: 'inkkit-footnote-reference',
270
- tabindex: '0',
271
- role: 'button',
272
- 'aria-label': `${editorLabels(ctx).footnote} ${node.attrs.label}`,
273
- 'data-inkkit-footnote-reference': node.attrs.identifier,
274
- 'data-inkkit-label': node.attrs.label,
275
- },
276
- String(node.attrs.label),
277
- ],
278
- parseMarkdown: {
279
- match: (node) => node.type === 'footnoteReference',
280
- runner(state, node, type) {
281
- state.addNode(type, {
282
- label: String(node.label ?? node.identifier),
283
- identifier: String(node.identifier),
284
- });
285
- },
286
- },
287
- toMarkdown: {
288
- match: (node) => node.type.name === 'footnote_reference',
289
- runner: (state, node) => {
290
- state.addNode('footnoteReference', undefined, undefined, {
291
- ...node.attrs,
292
- });
293
- },
294
- },
295
- }));
296
- export const footnoteDefinition = $node('footnote_definition', (ctx) => ({
297
- group: 'block',
298
- content: 'block+',
299
- defining: true,
300
- attrs: associationAttrs,
301
- parseDOM: [
302
- {
303
- tag: '[data-inkkit-footnote-definition]',
304
- getAttrs: (dom) => ({
305
- label: dom.getAttribute('data-inkkit-label') ?? '',
306
- identifier: dom.getAttribute('data-inkkit-footnote-definition') ?? '',
307
- }),
308
- },
309
- ],
310
- toDOM: (node) => [
311
- 'div',
312
- {
313
- class: 'inkkit-footnote-definition',
314
- 'aria-label': `${editorLabels(ctx).footnote} ${node.attrs.label}`,
315
- 'data-inkkit-footnote-definition': node.attrs.identifier,
316
- 'data-inkkit-label': node.attrs.label,
317
- },
318
- 0,
319
- ],
320
- parseMarkdown: {
321
- match: (node) => node.type === 'footnoteDefinition',
322
- runner(state, node, type) {
323
- state.openNode(type, {
324
- label: String(node.label ?? node.identifier),
325
- identifier: String(node.identifier),
326
- });
327
- state.next(node.children);
328
- state.closeNode();
329
- },
330
- },
331
- toMarkdown: {
332
- match: (node) => node.type.name === 'footnote_definition',
333
- runner(state, node) {
334
- state.openNode('footnoteDefinition', undefined, { ...node.attrs });
335
- state.next(node.content);
336
- state.closeNode();
337
- },
338
- },
339
- }));
340
- const resolvedReferenceTargets = $prose(() => new Plugin({
341
- key: new PluginKey('inkkitReferenceTargets'),
342
- appendTransaction(transactions, _before, state) {
343
- if (!transactions.some((transaction) => transaction.docChanged))
344
- return null;
345
- const targets = referenceDefinitions(state.doc);
346
- const tr = state.tr;
347
- state.doc.descendants((node, pos) => {
348
- for (const mark of node.marks) {
349
- if (mark.type.name !== 'link' || mark.attrs.identifier == null)
350
- continue;
351
- const target = targets.get(normaliseLabel(String(mark.attrs.identifier)))?.node;
352
- const href = String(target?.attrs.url ?? '');
353
- const title = target?.attrs.title ?? null;
354
- if (mark.attrs.href === href && mark.attrs.title === title)
355
- continue;
356
- tr.addMark(pos, pos + node.nodeSize, mark.type.create({ ...mark.attrs, href, title }));
357
- }
358
- });
359
- return tr.docChanged ? tr.setMeta('addToHistory', false) : null;
360
- },
361
- }));
362
- export const references = [
363
- referenceLinks,
364
- referenceDefinition,
365
- footnoteReference,
366
- footnoteDefinition,
367
- resolvedReferenceTargets,
368
- ].flat();
package/dist/search.d.ts DELETED
@@ -1,15 +0,0 @@
1
- import { type Transaction } from '@milkdown/kit/prose/state';
2
- import type { EditorView } from '@milkdown/kit/prose/view';
3
- export interface TextMatch {
4
- from: number;
5
- to: number;
6
- }
7
- export interface LiteralReplacement extends TextMatch {
8
- text: string;
9
- count: number;
10
- }
11
- export declare function findLiteral(text: string, search: string, from?: number): TextMatch | undefined;
12
- export declare function replaceLiteral(text: string, search: string, replacement: string, selection: TextMatch, all?: boolean): LiteralReplacement;
13
- export declare function findFormatted(view: EditorView, text: string): boolean;
14
- export declare function replaceFormatted(view: EditorView, search: string, replacement: string, preflight: (tr: Transaction) => void, all?: boolean): number;
15
- export declare function replaceFormattedRange(view: EditorView, from: number, to: number, replacement: string, preflight: (tr: Transaction) => void): boolean;
package/dist/search.js DELETED
@@ -1,202 +0,0 @@
1
- import { Fragment, Slice } from '@milkdown/kit/prose/model';
2
- import { closeHistory } from '@milkdown/kit/prose/history';
3
- import { Selection, TextSelection, } from '@milkdown/kit/prose/state';
4
- import { SearchQuery, setSearchState, getSearchState } from 'prosemirror-search';
5
- import { InkKitError } from './types.js';
6
- function escapedPattern(text) {
7
- return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
8
- }
9
- function literalMatches(text, search) {
10
- if (!search)
11
- return [];
12
- const pattern = new RegExp(escapedPattern(search), 'giu');
13
- return [...text.matchAll(pattern)].map((match) => ({
14
- from: match.index,
15
- to: match.index + match[0].length,
16
- }));
17
- }
18
- export function findLiteral(text, search, from = 0) {
19
- const matches = literalMatches(text, search);
20
- return matches.find((match) => match.from >= from) ?? matches[0];
21
- }
22
- export function replaceLiteral(text, search, replacement, selection, all = false) {
23
- const matches = literalMatches(text, search);
24
- const selected = matches.find((match) => match.from === selection.from && match.to === selection.to) ??
25
- matches.find((match) => match.from >= selection.to) ??
26
- matches[0];
27
- const changed = (all ? matches : selected ? [selected] : []).filter((match) => text.slice(match.from, match.to) !== replacement);
28
- if (!changed.length)
29
- return { ...selection, text, count: 0 };
30
- let output = text;
31
- for (const match of [...changed].reverse())
32
- output = output.slice(0, match.from) + replacement + output.slice(match.to);
33
- if (!all)
34
- return {
35
- text: output,
36
- count: 1,
37
- from: changed[0].from,
38
- to: changed[0].from + replacement.length,
39
- };
40
- const map = (position) => {
41
- let difference = 0;
42
- for (const match of changed) {
43
- if (position < match.from)
44
- break;
45
- if (position <= match.to)
46
- return (match.from +
47
- difference +
48
- (position === match.from ? 0 : replacement.length));
49
- difference += replacement.length - (match.to - match.from);
50
- }
51
- return position + difference;
52
- };
53
- return {
54
- text: output,
55
- count: changed.length,
56
- from: map(selection.from),
57
- to: map(selection.to),
58
- };
59
- }
60
- function formattedQuery(text) {
61
- // Unicode regexp matching retains offsets when lowercasing would expand a character.
62
- return new SearchQuery({
63
- search: escapedPattern(text),
64
- regexp: true,
65
- literal: true,
66
- filter: (state, match) => {
67
- const from = state.doc.resolve(match.from);
68
- const to = state.doc.resolve(match.to);
69
- if (from.parent !== to.parent || !from.parent.inlineContent)
70
- return false;
71
- const content = state.doc.slice(match.from, match.to).content;
72
- let textOnly = true;
73
- content.forEach((node) => {
74
- if (!node.isText)
75
- textOnly = false;
76
- });
77
- return textOnly;
78
- },
79
- });
80
- }
81
- export function findFormatted(view, text) {
82
- const query = formattedQuery(text);
83
- const previous = getSearchState(view.state)?.query.search;
84
- let tr = setSearchState(view.state.tr, query);
85
- let found = false;
86
- if (text) {
87
- const start = previous === query.search
88
- ? view.state.selection.to
89
- : view.state.selection.from;
90
- const match = query.findNext(view.state, start) ?? query.findNext(view.state, 0);
91
- if (match) {
92
- found = true;
93
- tr = tr
94
- .setSelection(TextSelection.create(tr.doc, match.from, match.to))
95
- .scrollIntoView();
96
- }
97
- else
98
- tr = tr.setSelection(Selection.near(view.state.selection.$to));
99
- }
100
- else if (previous)
101
- tr = tr.setSelection(Selection.near(view.state.selection.$to));
102
- view.dispatch(tr);
103
- return found;
104
- }
105
- function replacementSlice(state, from, to, value) {
106
- const start = state.doc.resolve(from), end = state.doc.resolve(to);
107
- const marks = start.marksAcross(end) ?? start.marks();
108
- const nodes = [];
109
- if (start.parent.type.spec.code) {
110
- if (value)
111
- nodes.push(state.schema.text(value, marks));
112
- }
113
- else {
114
- const lines = value.split('\n');
115
- lines.forEach((line, index) => {
116
- if (index)
117
- nodes.push(state.schema.nodes.hardbreak.create({ isHTML: index === lines.length - 1 && line === '' }, null, marks));
118
- if (line)
119
- nodes.push(state.schema.text(line, marks));
120
- });
121
- }
122
- return new Slice(Fragment.fromArray(nodes), 0, 0);
123
- }
124
- export function replaceFormatted(view, search, replacement, preflight, all = false) {
125
- if (!search)
126
- return 0;
127
- const state = view.state;
128
- const query = formattedQuery(search);
129
- if (!query.valid)
130
- return 0;
131
- const matches = [];
132
- if (all) {
133
- for (let position = 0;;) {
134
- const match = query.findNext(state, position);
135
- if (!match)
136
- break;
137
- matches.push(match);
138
- position = match.to;
139
- }
140
- }
141
- else {
142
- const selection = state.selection;
143
- const current = query.findNext(state, selection.from, selection.to);
144
- const match = (current?.from === selection.from && current.to === selection.to
145
- ? current
146
- : undefined) ??
147
- query.findNext(state, selection.to) ??
148
- query.findNext(state, 0);
149
- if (match)
150
- matches.push(match);
151
- }
152
- const value = replacement.replace(/\r\n?/g, '\n');
153
- const changed = matches.filter((match) => state.doc.textBetween(match.from, match.to) !== value);
154
- if (!changed.length)
155
- return 0;
156
- let tr = setSearchState(state.tr, query);
157
- for (const match of [...changed].reverse()) {
158
- tr.replace(match.from, match.to, replacementSlice(state, match.from, match.to, value));
159
- }
160
- if (!all) {
161
- const match = changed[0];
162
- tr = tr.setSelection(TextSelection.create(tr.doc, match.from, tr.mapping.map(match.to, 1)));
163
- }
164
- try {
165
- preflight(tr);
166
- }
167
- catch (error) {
168
- if (error instanceof InkKitError)
169
- throw error;
170
- throw new InkKitError('preservation', error instanceof Error ? error.message : 'Cannot preserve replacement');
171
- }
172
- view.dispatch(closeHistory(tr).scrollIntoView());
173
- view.dispatch(closeHistory(view.state.tr).setMeta('addToHistory', false));
174
- return changed.length;
175
- }
176
- export function replaceFormattedRange(view, from, to, replacement, preflight) {
177
- const start = view.state.doc.resolve(from);
178
- const end = view.state.doc.resolve(to);
179
- let textOnly = start.parent === end.parent && start.parent.inlineContent;
180
- view.state.doc.nodesBetween(from, to, (node) => {
181
- if (!node.isText && !node.isTextblock)
182
- textOnly = false;
183
- });
184
- if (!textOnly)
185
- throw new InkKitError('invalid-range', 'Replacement requires literal text within one block');
186
- const value = replacement.replace(/\r\n?/g, '\n');
187
- if (view.state.doc.textBetween(from, to) === value)
188
- return false;
189
- const tr = closeHistory(view.state.tr.replace(from, to, replacementSlice(view.state, from, to, value)));
190
- tr.setSelection(TextSelection.create(tr.doc, from, tr.mapping.map(to, 1)));
191
- try {
192
- preflight(tr);
193
- }
194
- catch (error) {
195
- if (error instanceof InkKitError)
196
- throw error;
197
- throw new InkKitError('preservation', error instanceof Error ? error.message : 'Cannot preserve replacement');
198
- }
199
- view.dispatch(tr);
200
- view.dispatch(closeHistory(view.state.tr).setMeta('addToHistory', false));
201
- return true;
202
- }
@@ -1 +0,0 @@
1
- export declare const selectionPlugin: import("@milkdown/kit/utils").$Prose;
package/dist/selection.js DELETED
@@ -1,59 +0,0 @@
1
- import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
2
- import { $prose } from '@milkdown/kit/utils';
3
- /** The stylesheet paints the selection under this name. */
4
- const name = 'inkkit-selection';
5
- const ranges = new Map();
6
- /** The selected text within each block. */
7
- function covered(state) {
8
- const { from, to, empty, visible } = state.selection;
9
- if (empty || !visible)
10
- return null;
11
- const text = [];
12
- state.doc.nodesBetween(from, to, (node, pos) => {
13
- if (!node.isTextblock)
14
- return true;
15
- const start = Math.max(from, pos + 1);
16
- const end = Math.min(to, pos + node.nodeSize - 1);
17
- if (end > start)
18
- text.push({ from: start, to: end });
19
- return false;
20
- });
21
- return text;
22
- }
23
- function domRange(view, span) {
24
- const start = view.domAtPos(span.from);
25
- const end = view.domAtPos(span.to);
26
- const range = document.createRange();
27
- range.setStart(start.node, start.offset);
28
- range.setEnd(end.node, end.offset);
29
- return range;
30
- }
31
- function paint(view) {
32
- ranges.set(view, (covered(view.state) ?? []).map((span) => domRange(view, span)));
33
- refresh();
34
- }
35
- function refresh() {
36
- if (ranges.size === 0) {
37
- CSS.highlights.delete(name);
38
- return;
39
- }
40
- const highlight = new Highlight();
41
- for (const selection of ranges.values())
42
- for (const range of selection)
43
- highlight.add(range);
44
- CSS.highlights.set(name, highlight);
45
- }
46
- // Paint only selected text, without WebKit filling the surrounding margins.
47
- export const selectionPlugin = $prose(() => new Plugin({
48
- key: new PluginKey('selection'),
49
- view(view) {
50
- paint(view);
51
- return {
52
- update: (view) => paint(view),
53
- destroy: () => {
54
- ranges.delete(view);
55
- refresh();
56
- },
57
- };
58
- },
59
- }));
package/dist/source.d.ts DELETED
@@ -1,16 +0,0 @@
1
- import type { Node as ProseNode } from '@milkdown/kit/prose/model';
2
- export declare const sourceAttribute = "inkkitSource";
3
- export interface SourceProvenance {
4
- readonly text: string;
5
- readonly format: 'md' | 'txt';
6
- readonly from: number;
7
- readonly to: number;
8
- }
9
- export declare function cleanSourceDoc(doc: ProseNode): ProseNode;
10
- export declare function rawOffset(source: string, normalized: number): number;
11
- export declare function normalizedOffset(source: string, raw: number): number;
12
- export declare function editedPlainSource(previous: string, value: string): string;
13
- export declare function sourceSelection(source: string, start: number, end: number): {
14
- markdown: string;
15
- shareable: string;
16
- };