@aicayzer/inkkit 0.0.18 → 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.
- package/NOTICE +4 -2
- package/README.md +11 -7
- package/dist/THIRD-PARTY-NOTICES.txt +2742 -0
- package/dist/chunks/core-vtCr4MBS.js +56503 -0
- package/dist/chunks/highlight-Daj2fv_u.js +14122 -0
- package/dist/core.d.ts +2 -5
- package/dist/core.js +2 -2
- package/dist/editor.d.ts +229 -47
- package/dist/index.js +5 -3
- package/dist/style.css +231 -202
- package/dist/types.d.ts +143 -18
- package/package.json +16 -13
- package/dist/autolink.d.ts +0 -1
- package/dist/autolink.js +0 -18
- package/dist/callouts.d.ts +0 -25
- package/dist/callouts.js +0 -288
- package/dist/clipboard.d.ts +0 -11
- package/dist/clipboard.js +0 -261
- package/dist/code-fences.d.ts +0 -8
- package/dist/code-fences.js +0 -171
- package/dist/comments.d.ts +0 -76
- package/dist/comments.js +0 -545
- package/dist/cursor.d.ts +0 -2
- package/dist/cursor.js +0 -40
- package/dist/decorations.d.ts +0 -2
- package/dist/decorations.js +0 -67
- package/dist/dialect.d.ts +0 -9
- package/dist/dialect.js +0 -446
- package/dist/drop-placement.d.ts +0 -19
- package/dist/drop-placement.js +0 -47
- package/dist/editor.js +0 -2673
- package/dist/files.d.ts +0 -40
- package/dist/files.js +0 -133
- package/dist/highlight.d.ts +0 -1
- package/dist/highlight.js +0 -136
- package/dist/html-import.d.ts +0 -13
- package/dist/html-import.js +0 -477
- package/dist/image-blocks.d.ts +0 -86
- package/dist/image-blocks.js +0 -329
- package/dist/images.d.ts +0 -51
- package/dist/images.js +0 -398
- package/dist/inline-highlight.d.ts +0 -6
- package/dist/inline-highlight.js +0 -112
- package/dist/labels.d.ts +0 -36
- package/dist/labels.js +0 -34
- package/dist/link-safety.d.ts +0 -17
- package/dist/link-safety.js +0 -29
- package/dist/linked-syntax.d.ts +0 -48
- package/dist/linked-syntax.js +0 -320
- package/dist/literals.d.ts +0 -20
- package/dist/literals.js +0 -216
- package/dist/mermaid.d.ts +0 -28
- package/dist/mermaid.js +0 -404
- package/dist/outline.d.ts +0 -22
- package/dist/outline.js +0 -79
- package/dist/paste-html.d.ts +0 -31
- package/dist/paste-html.js +0 -462
- package/dist/paste.d.ts +0 -33
- package/dist/paste.js +0 -591
- package/dist/portable-files.d.ts +0 -10
- package/dist/portable-files.js +0 -36
- package/dist/preserve.d.ts +0 -38
- package/dist/preserve.js +0 -1396
- package/dist/print.d.ts +0 -7
- package/dist/print.js +0 -406
- package/dist/reference-clipboard.d.ts +0 -8
- package/dist/reference-clipboard.js +0 -201
- package/dist/references.d.ts +0 -16
- package/dist/references.js +0 -418
- package/dist/scroll.d.ts +0 -15
- package/dist/scroll.js +0 -27
- package/dist/search.d.ts +0 -15
- package/dist/search.js +0 -202
- package/dist/selection.d.ts +0 -1
- package/dist/selection.js +0 -59
- package/dist/source.d.ts +0 -16
- package/dist/source.js +0 -57
- package/dist/spreadsheet.d.ts +0 -8
- package/dist/spreadsheet.js +0 -289
- package/dist/table-alignment.d.ts +0 -2
- package/dist/table-alignment.js +0 -46
- package/dist/tables.d.ts +0 -27
- package/dist/tables.js +0 -344
- package/dist/tasks.d.ts +0 -3
- package/dist/tasks.js +0 -51
- package/dist/text-ranges.d.ts +0 -29
- package/dist/text-ranges.js +0 -256
- package/dist/types.js +0 -8
- package/dist/wiki-view.d.ts +0 -21
- package/dist/wiki-view.js +0 -78
package/dist/comments.js
DELETED
|
@@ -1,545 +0,0 @@
|
|
|
1
|
-
import { $node, $prose, $remark } from '@milkdown/kit/utils';
|
|
2
|
-
import { Fragment } from '@milkdown/kit/prose/model';
|
|
3
|
-
import { isHistoryTransaction } from '@milkdown/kit/prose/history';
|
|
4
|
-
import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
|
|
5
|
-
import { isImageBlock } from './image-blocks.js';
|
|
6
|
-
import { fromMarkdown } from 'mdast-util-from-markdown';
|
|
7
|
-
const lineEnding = (code) => code === -3 || code === -4 || code === -5;
|
|
8
|
-
const whitespace = (code) => code === 32 || code === -1 || code === -2;
|
|
9
|
-
function commentData(effects) {
|
|
10
|
-
let open = false;
|
|
11
|
-
return {
|
|
12
|
-
consume(code) {
|
|
13
|
-
if (!open) {
|
|
14
|
-
effects.enter('inkkitCommentData');
|
|
15
|
-
open = true;
|
|
16
|
-
}
|
|
17
|
-
effects.consume(code);
|
|
18
|
-
},
|
|
19
|
-
close() {
|
|
20
|
-
if (open) {
|
|
21
|
-
effects.exit('inkkitCommentData');
|
|
22
|
-
open = false;
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
const inlineComment = function (effects, ok, nok) {
|
|
28
|
-
const data = commentData(effects);
|
|
29
|
-
return start;
|
|
30
|
-
function start(code) {
|
|
31
|
-
effects.enter('inkkitCommentInline');
|
|
32
|
-
data.consume(code);
|
|
33
|
-
return second;
|
|
34
|
-
}
|
|
35
|
-
function second(code) {
|
|
36
|
-
if (code !== 37)
|
|
37
|
-
return nok(code);
|
|
38
|
-
data.consume(code);
|
|
39
|
-
return body;
|
|
40
|
-
}
|
|
41
|
-
function body(code) {
|
|
42
|
-
if (code === null)
|
|
43
|
-
return nok(code);
|
|
44
|
-
if (lineEnding(code)) {
|
|
45
|
-
data.close();
|
|
46
|
-
effects.enter('lineEnding');
|
|
47
|
-
effects.consume(code);
|
|
48
|
-
effects.exit('lineEnding');
|
|
49
|
-
return body;
|
|
50
|
-
}
|
|
51
|
-
data.consume(code);
|
|
52
|
-
return code === 37 ? closing : body;
|
|
53
|
-
}
|
|
54
|
-
function closing(code) {
|
|
55
|
-
if (code !== 37)
|
|
56
|
-
return body(code);
|
|
57
|
-
data.consume(code);
|
|
58
|
-
data.close();
|
|
59
|
-
effects.exit('inkkitCommentInline');
|
|
60
|
-
return ok;
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
// A flow construct owns blank lines and Markdown-looking text inside a block comment.
|
|
64
|
-
const blockComment = function (effects, ok, nok) {
|
|
65
|
-
const data = commentData(effects);
|
|
66
|
-
return start;
|
|
67
|
-
function start(code) {
|
|
68
|
-
effects.enter('inkkitCommentBlock');
|
|
69
|
-
data.consume(code);
|
|
70
|
-
return second;
|
|
71
|
-
}
|
|
72
|
-
function second(code) {
|
|
73
|
-
if (code !== 37)
|
|
74
|
-
return nok(code);
|
|
75
|
-
data.consume(code);
|
|
76
|
-
return openingEnd;
|
|
77
|
-
}
|
|
78
|
-
function openingEnd(code) {
|
|
79
|
-
if (whitespace(code)) {
|
|
80
|
-
data.consume(code);
|
|
81
|
-
return openingEnd;
|
|
82
|
-
}
|
|
83
|
-
if (!lineEnding(code))
|
|
84
|
-
return nok(code);
|
|
85
|
-
data.close();
|
|
86
|
-
effects.enter('lineEnding');
|
|
87
|
-
effects.consume(code);
|
|
88
|
-
effects.exit('lineEnding');
|
|
89
|
-
return lineStart;
|
|
90
|
-
}
|
|
91
|
-
function lineStart(code) {
|
|
92
|
-
if (whitespace(code)) {
|
|
93
|
-
data.consume(code);
|
|
94
|
-
return lineStart;
|
|
95
|
-
}
|
|
96
|
-
if (code === 37) {
|
|
97
|
-
data.consume(code);
|
|
98
|
-
return closingSecond;
|
|
99
|
-
}
|
|
100
|
-
return body(code);
|
|
101
|
-
}
|
|
102
|
-
function body(code) {
|
|
103
|
-
if (code === null)
|
|
104
|
-
return nok(code);
|
|
105
|
-
if (lineEnding(code)) {
|
|
106
|
-
data.close();
|
|
107
|
-
effects.enter('lineEnding');
|
|
108
|
-
effects.consume(code);
|
|
109
|
-
effects.exit('lineEnding');
|
|
110
|
-
return lineStart;
|
|
111
|
-
}
|
|
112
|
-
data.consume(code);
|
|
113
|
-
return lineEnding(code) ? lineStart : body;
|
|
114
|
-
}
|
|
115
|
-
function closingSecond(code) {
|
|
116
|
-
if (code !== 37)
|
|
117
|
-
return body(code);
|
|
118
|
-
data.consume(code);
|
|
119
|
-
return closingEnd;
|
|
120
|
-
}
|
|
121
|
-
function closingEnd(code) {
|
|
122
|
-
if (whitespace(code)) {
|
|
123
|
-
data.consume(code);
|
|
124
|
-
return closingEnd;
|
|
125
|
-
}
|
|
126
|
-
if (code !== null && !lineEnding(code))
|
|
127
|
-
return body(code);
|
|
128
|
-
data.close();
|
|
129
|
-
effects.exit('inkkitCommentBlock');
|
|
130
|
-
return ok(code);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
const syntax = {
|
|
134
|
-
text: { 37: { name: 'inkkitCommentInline', tokenize: inlineComment } },
|
|
135
|
-
flow: {
|
|
136
|
-
37: { name: 'inkkitCommentBlock', tokenize: blockComment, concrete: true },
|
|
137
|
-
},
|
|
138
|
-
};
|
|
139
|
-
const from = {
|
|
140
|
-
enter: {
|
|
141
|
-
inkkitCommentInline(token) {
|
|
142
|
-
this.enter({ type: 'inkkitCommentInline', syntax: 'obsidian', value: '' }, token);
|
|
143
|
-
},
|
|
144
|
-
inkkitCommentBlock(token) {
|
|
145
|
-
this.enter({ type: 'inkkitCommentBlock', syntax: 'obsidian', value: '' }, token);
|
|
146
|
-
},
|
|
147
|
-
},
|
|
148
|
-
exit: {
|
|
149
|
-
inkkitCommentInline(token) {
|
|
150
|
-
const node = this.stack.at(-1);
|
|
151
|
-
node.value = this.sliceSerialize(token).slice(2, -2);
|
|
152
|
-
this.exit(token);
|
|
153
|
-
},
|
|
154
|
-
inkkitCommentBlock(token) {
|
|
155
|
-
const node = this.stack.at(-1);
|
|
156
|
-
node.value = this.sliceSerialize(token)
|
|
157
|
-
.replace(/^%%[^\S\r\n]*\r?\n/, '')
|
|
158
|
-
.replace(/(?:\r?\n)?[^\S\r\n]*%%[^\S\r\n]*$/, '');
|
|
159
|
-
this.exit(token);
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
export function commentSource(node) {
|
|
164
|
-
const body = node.textContent;
|
|
165
|
-
return node.attrs.syntax === 'html'
|
|
166
|
-
? `<!--${body}-->`
|
|
167
|
-
: node.type.name === 'comment_block' || node.attrs.block
|
|
168
|
-
? `%%\n${body}\n%%`
|
|
169
|
-
: `%%${body}%%`;
|
|
170
|
-
}
|
|
171
|
-
const handler = (node) => {
|
|
172
|
-
const comment = node;
|
|
173
|
-
const value = comment.value ?? '';
|
|
174
|
-
return comment.syntax === 'html'
|
|
175
|
-
? `<!--${value}-->`
|
|
176
|
-
: comment.type === 'inkkitCommentBlock' || comment.block
|
|
177
|
-
? `%%\n${value}\n%%`
|
|
178
|
-
: `%%${value}%%`;
|
|
179
|
-
};
|
|
180
|
-
function htmlSpans(value) {
|
|
181
|
-
const spans = [];
|
|
182
|
-
let inTag = false;
|
|
183
|
-
let quote = '';
|
|
184
|
-
for (let index = 0; index < value.length; index++) {
|
|
185
|
-
const character = value[index];
|
|
186
|
-
if (quote) {
|
|
187
|
-
if (character === quote)
|
|
188
|
-
quote = '';
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
if (inTag && (character === '"' || character === "'")) {
|
|
192
|
-
quote = character;
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
if (value.startsWith('<!--', index)) {
|
|
196
|
-
const end = value.indexOf('-->', index + 4);
|
|
197
|
-
if (end < 0)
|
|
198
|
-
break;
|
|
199
|
-
spans.push({
|
|
200
|
-
start: index,
|
|
201
|
-
end: end + 3,
|
|
202
|
-
syntax: 'html',
|
|
203
|
-
value: value.slice(index + 4, end),
|
|
204
|
-
});
|
|
205
|
-
index = end + 2;
|
|
206
|
-
inTag = false;
|
|
207
|
-
}
|
|
208
|
-
else if (character === '<')
|
|
209
|
-
inTag = true;
|
|
210
|
-
else if (character === '>')
|
|
211
|
-
inTag = false;
|
|
212
|
-
}
|
|
213
|
-
return spans;
|
|
214
|
-
}
|
|
215
|
-
// Parse preserved source again rather than hiding delimiter-looking strings in code or escapes.
|
|
216
|
-
export function literalCommentSpans(value) {
|
|
217
|
-
const tree = fromMarkdown(value, {
|
|
218
|
-
extensions: [syntax],
|
|
219
|
-
mdastExtensions: [from],
|
|
220
|
-
});
|
|
221
|
-
const spans = [];
|
|
222
|
-
const visit = (node) => {
|
|
223
|
-
const start = node.position?.start.offset;
|
|
224
|
-
const end = node.position?.end.offset;
|
|
225
|
-
if (start != null && end != null) {
|
|
226
|
-
if (node.type === 'inkkitCommentInline' ||
|
|
227
|
-
node.type === 'inkkitCommentBlock')
|
|
228
|
-
spans.push({
|
|
229
|
-
start,
|
|
230
|
-
end,
|
|
231
|
-
syntax: node.syntax,
|
|
232
|
-
value: node.value,
|
|
233
|
-
block: node.type === 'inkkitCommentBlock',
|
|
234
|
-
});
|
|
235
|
-
else if (node.type === 'html')
|
|
236
|
-
spans.push(...htmlSpans(value.slice(start, end)).map((span) => ({
|
|
237
|
-
...span,
|
|
238
|
-
start: start + span.start,
|
|
239
|
-
end: start + span.end,
|
|
240
|
-
})));
|
|
241
|
-
}
|
|
242
|
-
if ('children' in node)
|
|
243
|
-
node.children.forEach(visit);
|
|
244
|
-
};
|
|
245
|
-
visit(tree);
|
|
246
|
-
return spans.sort((left, right) => left.start - right.start);
|
|
247
|
-
}
|
|
248
|
-
function remarkComments() {
|
|
249
|
-
const data = this.data();
|
|
250
|
-
(data.micromarkExtensions ??= []).push(syntax);
|
|
251
|
-
(data.fromMarkdownExtensions ??= []).push(from);
|
|
252
|
-
(data.toMarkdownExtensions ??= []).push({
|
|
253
|
-
handlers: { inkkitCommentInline: handler, inkkitCommentBlock: handler },
|
|
254
|
-
unsafe: [{ character: '%', inConstruct: 'phrasing', after: '%' }],
|
|
255
|
-
});
|
|
256
|
-
return (tree) => {
|
|
257
|
-
const visit = (node, inline, parentType) => {
|
|
258
|
-
if (parentType === 'listItem' && node.type === 'inkkitCommentBlock')
|
|
259
|
-
return {
|
|
260
|
-
type: 'paragraph',
|
|
261
|
-
children: [{ ...node, type: 'inkkitCommentInline', block: true }],
|
|
262
|
-
position: node.position,
|
|
263
|
-
};
|
|
264
|
-
if (node.type === 'html') {
|
|
265
|
-
const spans = htmlSpans(node.value);
|
|
266
|
-
if (spans.length === 1 &&
|
|
267
|
-
spans[0].start === 0 &&
|
|
268
|
-
spans[0].end === node.value.length)
|
|
269
|
-
return parentType === 'listItem'
|
|
270
|
-
? {
|
|
271
|
-
type: 'paragraph',
|
|
272
|
-
children: [
|
|
273
|
-
{
|
|
274
|
-
type: 'inkkitCommentInline',
|
|
275
|
-
syntax: 'html',
|
|
276
|
-
value: spans[0].value,
|
|
277
|
-
position: node.position,
|
|
278
|
-
},
|
|
279
|
-
],
|
|
280
|
-
position: node.position,
|
|
281
|
-
}
|
|
282
|
-
: {
|
|
283
|
-
type: inline ? 'inkkitCommentInline' : 'inkkitCommentBlock',
|
|
284
|
-
syntax: 'html',
|
|
285
|
-
value: spans[0].value,
|
|
286
|
-
position: node.position,
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
if ('children' in node)
|
|
290
|
-
node.children = node.children.map((child) => visit(child, node.type === 'paragraph' ||
|
|
291
|
-
node.type === 'heading' ||
|
|
292
|
-
node.type === 'tableCell' ||
|
|
293
|
-
node.type === 'link' ||
|
|
294
|
-
node.type === 'linkReference' ||
|
|
295
|
-
inline, node.type));
|
|
296
|
-
if (node.type === 'paragraph' &&
|
|
297
|
-
parentType !== 'listItem' &&
|
|
298
|
-
node.children.length === 1 &&
|
|
299
|
-
node.children[0]?.type === 'inkkitCommentInline')
|
|
300
|
-
return {
|
|
301
|
-
...node.children[0],
|
|
302
|
-
type: 'inkkitCommentBlock',
|
|
303
|
-
position: node.position,
|
|
304
|
-
};
|
|
305
|
-
return node;
|
|
306
|
-
};
|
|
307
|
-
tree.children = tree.children.map((node) => visit(node, false));
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
export const remarkCommentsPlugin = $remark('remarkComments', () => remarkComments);
|
|
311
|
-
function commentNode(inline) {
|
|
312
|
-
const name = inline ? 'comment_inline' : 'comment_block';
|
|
313
|
-
const mdastType = inline ? 'inkkitCommentInline' : 'inkkitCommentBlock';
|
|
314
|
-
return $node(name, () => ({
|
|
315
|
-
inline,
|
|
316
|
-
group: inline ? 'inline' : 'block',
|
|
317
|
-
content: 'text*',
|
|
318
|
-
marks: '',
|
|
319
|
-
code: true,
|
|
320
|
-
defining: true,
|
|
321
|
-
attrs: { syntax: { default: 'html' }, block: { default: !inline } },
|
|
322
|
-
parseDOM: [
|
|
323
|
-
{
|
|
324
|
-
tag: `${inline ? 'span' : 'div'}[data-inkkit-comment]`,
|
|
325
|
-
preserveWhitespace: 'full',
|
|
326
|
-
getAttrs(dom) {
|
|
327
|
-
const syntax = dom.getAttribute('data-inkkit-comment') === 'obsidian'
|
|
328
|
-
? 'obsidian'
|
|
329
|
-
: 'html';
|
|
330
|
-
// Text that would end the comment early would leave the rest as
|
|
331
|
-
// Markdown, so it stays plain text.
|
|
332
|
-
if (commentTextEndsEarly(syntax, dom.textContent ?? ''))
|
|
333
|
-
return false;
|
|
334
|
-
return { syntax };
|
|
335
|
-
},
|
|
336
|
-
},
|
|
337
|
-
],
|
|
338
|
-
toDOM: (node) => [
|
|
339
|
-
inline ? 'span' : 'div',
|
|
340
|
-
{
|
|
341
|
-
class: `inkkit-comment inkkit-comment-${inline ? 'inline' : 'block'}`,
|
|
342
|
-
'data-inkkit-comment': node.attrs.syntax,
|
|
343
|
-
'aria-label': 'Author comment',
|
|
344
|
-
},
|
|
345
|
-
0,
|
|
346
|
-
],
|
|
347
|
-
parseMarkdown: {
|
|
348
|
-
match: (node) => node.type === mdastType,
|
|
349
|
-
runner: (state, node, type) => {
|
|
350
|
-
state.openNode(type, {
|
|
351
|
-
syntax: node.syntax,
|
|
352
|
-
block: inline ? Boolean(node.block) : true,
|
|
353
|
-
});
|
|
354
|
-
if (node.value)
|
|
355
|
-
state.addText(String(node.value));
|
|
356
|
-
state.closeNode();
|
|
357
|
-
},
|
|
358
|
-
},
|
|
359
|
-
toMarkdown: {
|
|
360
|
-
match: (node) => node.type.name === name,
|
|
361
|
-
runner: (state, node) => {
|
|
362
|
-
state.addNode(mdastType, undefined, node.textContent, {
|
|
363
|
-
syntax: node.attrs.syntax,
|
|
364
|
-
block: node.attrs.block,
|
|
365
|
-
});
|
|
366
|
-
},
|
|
367
|
-
},
|
|
368
|
-
}));
|
|
369
|
-
}
|
|
370
|
-
export const commentInline = commentNode(true);
|
|
371
|
-
export const commentBlock = commentNode(false);
|
|
372
|
-
const visibilityKey = new PluginKey('inkkit-comments-visible');
|
|
373
|
-
export const commentVisibility = $prose(() => new Plugin({
|
|
374
|
-
key: visibilityKey,
|
|
375
|
-
state: {
|
|
376
|
-
init: () => false,
|
|
377
|
-
apply: (transaction, value) => transaction.getMeta(visibilityKey) ?? value,
|
|
378
|
-
},
|
|
379
|
-
view(view) {
|
|
380
|
-
const update = () => view.dom.setAttribute('data-inkkit-comments-visible', String(visibilityKey.getState(view.state) ?? false));
|
|
381
|
-
update();
|
|
382
|
-
return { update };
|
|
383
|
-
},
|
|
384
|
-
}));
|
|
385
|
-
export function setCommentVisibility(view, visible) {
|
|
386
|
-
if (visibilityKey.getState(view.state) === visible)
|
|
387
|
-
return;
|
|
388
|
-
view.dispatch(view.state.tr
|
|
389
|
-
.setMeta(visibilityKey, visible)
|
|
390
|
-
.setMeta('addToHistory', false));
|
|
391
|
-
}
|
|
392
|
-
export const comments = [commentInline, commentBlock, commentVisibility].flat();
|
|
393
|
-
/**
|
|
394
|
-
* Whether text inside a comment ends it early for a reader other than InkKit.
|
|
395
|
-
* HTML ends a comment at `-->` or `--!>`, and treats a start of `>` or `->` as
|
|
396
|
-
* an empty comment. A `%%` comment ends at its next `%%`.
|
|
397
|
-
*/
|
|
398
|
-
export function commentTextEndsEarly(syntax, text) {
|
|
399
|
-
return syntax === 'obsidian'
|
|
400
|
-
? text.includes('%%')
|
|
401
|
-
: /^-?>/.test(text) || text.includes('-->') || text.includes('--!>');
|
|
402
|
-
}
|
|
403
|
-
/**
|
|
404
|
-
* Refuses an edit that gives a comment text which ends it early. A comment
|
|
405
|
-
* that already held that text before the edit is left alone, so a note that
|
|
406
|
-
* has one still loads and can be edited elsewhere.
|
|
407
|
-
*/
|
|
408
|
-
export function assertCommentsEndWhereWritten(before, after) {
|
|
409
|
-
const unsafe = (doc, visit) => doc.descendants((node) => {
|
|
410
|
-
if (!isComment(node))
|
|
411
|
-
return true;
|
|
412
|
-
if (commentTextEndsEarly(node.attrs.syntax, node.textContent))
|
|
413
|
-
visit(`${node.attrs.syntax}:${node.textContent}`);
|
|
414
|
-
return false;
|
|
415
|
-
});
|
|
416
|
-
let allowed;
|
|
417
|
-
unsafe(after, (key) => {
|
|
418
|
-
if (!allowed) {
|
|
419
|
-
allowed = new Map();
|
|
420
|
-
unsafe(before, (known) => allowed.set(known, (allowed.get(known) ?? 0) + 1));
|
|
421
|
-
}
|
|
422
|
-
const remaining = allowed.get(key) ?? 0;
|
|
423
|
-
if (remaining === 0)
|
|
424
|
-
throw new Error('A comment cannot contain text that would end it early');
|
|
425
|
-
allowed.set(key, remaining - 1);
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
/** Marks a transaction that replaces the document with source given as written. */
|
|
429
|
-
export const sourceReplacement = 'inkkit:sourceReplacement';
|
|
430
|
-
/**
|
|
431
|
-
* Whether an edit is typed or inserted by a person in the formatted editor. A
|
|
432
|
-
* history step restores a document the editor already accepted, and a source
|
|
433
|
-
* replacement is the author's own text, so neither is checked.
|
|
434
|
-
*/
|
|
435
|
-
export function isWrittenEdit(tr) {
|
|
436
|
-
return !isHistoryTransaction(tr) && !tr.getMeta(sourceReplacement);
|
|
437
|
-
}
|
|
438
|
-
export function isComment(node) {
|
|
439
|
-
return (node.type.name === 'comment_inline' || node.type.name === 'comment_block');
|
|
440
|
-
}
|
|
441
|
-
// Authored reference metadata can retain comments after their visible nodes are removed.
|
|
442
|
-
function commentProvenance(value) {
|
|
443
|
-
if (typeof value !== 'string')
|
|
444
|
-
return false;
|
|
445
|
-
const visit = (value) => {
|
|
446
|
-
if (Array.isArray(value))
|
|
447
|
-
return value.some(visit);
|
|
448
|
-
if (!value || typeof value !== 'object')
|
|
449
|
-
return false;
|
|
450
|
-
const node = value;
|
|
451
|
-
return (node.type === 'inkkitCommentInline' ||
|
|
452
|
-
node.type === 'inkkitCommentBlock' ||
|
|
453
|
-
(node.type === 'html' &&
|
|
454
|
-
typeof node.value === 'string' &&
|
|
455
|
-
htmlSpans(node.value).length > 0) ||
|
|
456
|
-
Boolean(node.children?.some(visit)));
|
|
457
|
-
};
|
|
458
|
-
try {
|
|
459
|
-
return visit(JSON.parse(value));
|
|
460
|
-
}
|
|
461
|
-
catch {
|
|
462
|
-
return true;
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
export function shareableFragment(content) {
|
|
466
|
-
const filtered = [];
|
|
467
|
-
const labelHasComments = (label) => typeof label === 'string' &&
|
|
468
|
-
(label.includes('%%') || label.includes('<!--')) &&
|
|
469
|
-
literalCommentSpans(label).length > 0;
|
|
470
|
-
content.forEach((node) => {
|
|
471
|
-
if (isComment(node))
|
|
472
|
-
return;
|
|
473
|
-
// Shared output treats a standalone image as the paragraph its Markdown holds.
|
|
474
|
-
if (isImageBlock(node)) {
|
|
475
|
-
const { paragraph, image } = node.type.schema.nodes;
|
|
476
|
-
filtered.push(paragraph.create(null, image.create(node.attrs)));
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
if (node.type.name === 'reference_definition' &&
|
|
480
|
-
labelHasComments(node.attrs.label))
|
|
481
|
-
return;
|
|
482
|
-
node = node.mark(node.marks.map((mark) => {
|
|
483
|
-
if (mark.type.name !== 'link')
|
|
484
|
-
return mark;
|
|
485
|
-
const clearTarget = labelHasComments(mark.attrs.label);
|
|
486
|
-
if (!clearTarget && !commentProvenance(mark.attrs.referenceContent))
|
|
487
|
-
return mark;
|
|
488
|
-
return mark.type.create({
|
|
489
|
-
...mark.attrs,
|
|
490
|
-
referenceContent: null,
|
|
491
|
-
...(clearTarget
|
|
492
|
-
? { identifier: null, label: null, referenceType: null }
|
|
493
|
-
: {}),
|
|
494
|
-
});
|
|
495
|
-
}));
|
|
496
|
-
if (!node.childCount) {
|
|
497
|
-
filtered.push(node);
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
const inner = shareableFragment(node.content);
|
|
501
|
-
let whitespaceOnly = true, removedComment = false;
|
|
502
|
-
inner.forEach((child) => {
|
|
503
|
-
if (!(child.isText && !child.text.trim()) &&
|
|
504
|
-
child.type.name !== 'hardbreak')
|
|
505
|
-
whitespaceOnly = false;
|
|
506
|
-
});
|
|
507
|
-
node.content.descendants((child) => {
|
|
508
|
-
if (isComment(child)) {
|
|
509
|
-
removedComment = true;
|
|
510
|
-
return false;
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
const commentOnly = removedComment && whitespaceOnly;
|
|
514
|
-
const paragraph = () => Fragment.from(node.type.schema.nodes.paragraph.create());
|
|
515
|
-
if ((inner.size === 0 || commentOnly) && node.content.size > 0) {
|
|
516
|
-
if ([
|
|
517
|
-
'footnote_definition',
|
|
518
|
-
'list_item',
|
|
519
|
-
'table_cell',
|
|
520
|
-
'table_header',
|
|
521
|
-
'inkkit_callout',
|
|
522
|
-
].includes(node.type.name))
|
|
523
|
-
filtered.push(node.copy(paragraph()));
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
if (!node.type.validContent(inner)) {
|
|
527
|
-
if (node.type.name === 'list_item')
|
|
528
|
-
filtered.push(node.copy(paragraph().append(inner)));
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
filtered.push(node.copy(inner));
|
|
532
|
-
});
|
|
533
|
-
return Fragment.fromArray(filtered);
|
|
534
|
-
}
|
|
535
|
-
// ProseMirror omits a parent wrapper when a selection is wholly inside its text.
|
|
536
|
-
export function commentSelectionContent(doc, from, to, content) {
|
|
537
|
-
const start = doc.resolve(from);
|
|
538
|
-
const end = doc.resolve(to);
|
|
539
|
-
for (let depth = start.depth; depth > 0; depth--) {
|
|
540
|
-
const node = start.node(depth);
|
|
541
|
-
if (isComment(node) && end.depth >= depth && node === end.node(depth))
|
|
542
|
-
return Fragment.from(node.copy(node.content.cut(from - start.start(depth), to - start.start(depth))));
|
|
543
|
-
}
|
|
544
|
-
return content;
|
|
545
|
-
}
|
package/dist/cursor.d.ts
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { dropIndicatorConfig } from '@milkdown/kit/plugin/cursor';
|
|
2
|
-
export declare const cursor: (import("@milkdown/kit/utils").$Ctx<dropIndicatorConfig, "dropIndicatorConfig"> | import("@milkdown/kit/utils").$Ctx<import("@milkdown/kit/plugin/cursor").DropIndicatorState, "dropIndicatorState"> | import("@milkdown/kit/utils").$Prose)[];
|
package/dist/cursor.js
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { dropIndicatorConfig, dropIndicatorDOMPlugin, dropIndicatorState, gapCursorPlugin, } from '@milkdown/kit/plugin/cursor';
|
|
2
|
-
import { Plugin } from '@milkdown/kit/prose/state';
|
|
3
|
-
import { $prose } from '@milkdown/kit/utils';
|
|
4
|
-
import { createDropIndicatorPlugin } from 'prosemirror-drop-indicator';
|
|
5
|
-
// Milkdown's drop indicator, except that it does not hide once the editor is
|
|
6
|
-
// gone. The indicator hides 30 ms after a drop or drag end, and setting its
|
|
7
|
-
// state after the editor is destroyed throws.
|
|
8
|
-
const dropIndicator = $prose((ctx) => {
|
|
9
|
-
let live = false;
|
|
10
|
-
const plugin = createDropIndicatorPlugin({
|
|
11
|
-
onShow: (options) => ctx.set(dropIndicatorState.key, options),
|
|
12
|
-
onHide: () => {
|
|
13
|
-
if (live)
|
|
14
|
-
ctx.set(dropIndicatorState.key, null);
|
|
15
|
-
},
|
|
16
|
-
onDrag: () => true,
|
|
17
|
-
});
|
|
18
|
-
const view = plugin.spec.view;
|
|
19
|
-
return new Plugin({
|
|
20
|
-
...plugin.spec,
|
|
21
|
-
view(editorView) {
|
|
22
|
-
live = true;
|
|
23
|
-
const inner = view(editorView);
|
|
24
|
-
return {
|
|
25
|
-
...inner,
|
|
26
|
-
destroy() {
|
|
27
|
-
live = false;
|
|
28
|
-
inner.destroy?.();
|
|
29
|
-
},
|
|
30
|
-
};
|
|
31
|
-
},
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
export const cursor = [
|
|
35
|
-
gapCursorPlugin,
|
|
36
|
-
dropIndicatorConfig,
|
|
37
|
-
dropIndicatorState,
|
|
38
|
-
dropIndicatorDOMPlugin,
|
|
39
|
-
dropIndicator,
|
|
40
|
-
].flat();
|
package/dist/decorations.d.ts
DELETED
package/dist/decorations.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
|
|
2
|
-
import { Decoration, DecorationSet } from '@milkdown/kit/prose/view';
|
|
3
|
-
import { $prose } from '@milkdown/kit/utils';
|
|
4
|
-
import { editorLabels } from './labels.js';
|
|
5
|
-
const copyIcon = '<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="5.5" y="5.5" width="8" height="8" rx="1.5"/><path d="M10.5 5.5v-2a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2"/></svg>';
|
|
6
|
-
const doneIcon = '<svg width="14" height="14" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3.5 8.5l3 3 6-6.5"/></svg>';
|
|
7
|
-
// The button reads the block's text when clicked, so the same widget can stay
|
|
8
|
-
// mounted while the block is edited.
|
|
9
|
-
function copyButton(onCopy, label) {
|
|
10
|
-
const button = document.createElement('button');
|
|
11
|
-
button.type = 'button';
|
|
12
|
-
button.className = 'copy';
|
|
13
|
-
button.setAttribute('aria-label', label);
|
|
14
|
-
button.innerHTML = copyIcon;
|
|
15
|
-
button.addEventListener('mousedown', (event) => event.preventDefault());
|
|
16
|
-
button.addEventListener('click', () => {
|
|
17
|
-
const code = button.closest('pre')?.querySelector('code');
|
|
18
|
-
onCopy(code?.textContent ?? '');
|
|
19
|
-
button.dataset.copied = '';
|
|
20
|
-
button.innerHTML = doneIcon;
|
|
21
|
-
window.setTimeout(() => {
|
|
22
|
-
delete button.dataset.copied;
|
|
23
|
-
button.innerHTML = copyIcon;
|
|
24
|
-
}, 1200);
|
|
25
|
-
});
|
|
26
|
-
return button;
|
|
27
|
-
}
|
|
28
|
-
export function codeCopyPlugin(onCopy) {
|
|
29
|
-
return $prose((ctx) => new Plugin({
|
|
30
|
-
key: new PluginKey('codeCopy'),
|
|
31
|
-
props: {
|
|
32
|
-
decorations(state) {
|
|
33
|
-
const widgets = [];
|
|
34
|
-
state.doc.descendants((node, pos) => {
|
|
35
|
-
if (node.type.name !== 'code_block')
|
|
36
|
-
return true;
|
|
37
|
-
widgets.push(Decoration.widget(pos + 1, () => copyButton(onCopy, editorLabels(ctx).copyCode), {
|
|
38
|
-
side: -1,
|
|
39
|
-
key: 'copy',
|
|
40
|
-
ignoreSelection: true,
|
|
41
|
-
}));
|
|
42
|
-
return false;
|
|
43
|
-
});
|
|
44
|
-
return DecorationSet.create(state.doc, widgets);
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
}));
|
|
48
|
-
}
|
|
49
|
-
export const placeholderPlugin = $prose((ctx) => new Plugin({
|
|
50
|
-
key: new PluginKey('placeholder'),
|
|
51
|
-
props: {
|
|
52
|
-
decorations(state) {
|
|
53
|
-
const first = state.doc.firstChild;
|
|
54
|
-
if (state.doc.childCount !== 1 ||
|
|
55
|
-
!first?.isTextblock ||
|
|
56
|
-
first.type.name === 'heading' ||
|
|
57
|
-
first.content.size > 0)
|
|
58
|
-
return null;
|
|
59
|
-
return DecorationSet.create(state.doc, [
|
|
60
|
-
Decoration.node(0, first.nodeSize, {
|
|
61
|
-
class: 'empty',
|
|
62
|
-
'data-placeholder': editorLabels(ctx).placeholder,
|
|
63
|
-
}),
|
|
64
|
-
]);
|
|
65
|
-
},
|
|
66
|
-
},
|
|
67
|
-
}));
|
package/dist/dialect.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { Ctx, MilkdownPlugin } from '@milkdown/kit/ctx';
|
|
2
|
-
import type { Node as ProseNode } from '@milkdown/kit/prose/model';
|
|
3
|
-
import { type Options as StringifyOptions } from 'mdast-util-to-markdown';
|
|
4
|
-
export declare const remarkDialectPlugin: import("@milkdown/kit/utils").$Remark<"remarkDialect", unknown>;
|
|
5
|
-
export declare const tables: MilkdownPlugin[];
|
|
6
|
-
export declare function createDialect(images: boolean, wikiLinks?: boolean, files?: boolean): MilkdownPlugin[];
|
|
7
|
-
export declare const dialect: MilkdownPlugin[];
|
|
8
|
-
export declare const stringifyOptions: StringifyOptions;
|
|
9
|
-
export declare function serialize(ctx: Ctx, doc?: ProseNode): string;
|