@aicayzer/inkkit 0.0.13 → 0.0.15
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/comments.js +7 -0
- package/dist/dialect.js +10 -19
- package/dist/editor.d.ts +4 -0
- package/dist/editor.js +82 -28
- package/dist/image-blocks.d.ts +71 -0
- package/dist/image-blocks.js +286 -0
- package/dist/images.d.ts +3 -1
- package/dist/images.js +64 -23
- package/dist/paste.d.ts +2 -0
- package/dist/paste.js +27 -15
- package/dist/preserve.d.ts +4 -0
- package/dist/preserve.js +134 -30
- package/dist/search.d.ts +3 -3
- package/dist/search.js +2 -2
- package/dist/style.css +144 -10
- package/dist/text-ranges.d.ts +4 -1
- package/dist/text-ranges.js +36 -13
- package/package.json +1 -1
package/dist/style.css
CHANGED
|
@@ -201,22 +201,81 @@
|
|
|
201
201
|
max-width: 100%;
|
|
202
202
|
vertical-align: bottom;
|
|
203
203
|
}
|
|
204
|
+
/* A standalone image is its own block; the row is full width so a click beside the card lands on it. */
|
|
205
|
+
.inkkit-root .ProseMirror .inkkit-image-block {
|
|
206
|
+
display: block;
|
|
207
|
+
margin: 0 0
|
|
208
|
+
var(--inkkit-paragraph-spacing, calc(var(--inkkit-font-size, 15px) * 0.667));
|
|
209
|
+
line-height: 0;
|
|
210
|
+
}
|
|
211
|
+
.inkkit-root .ProseMirror .inkkit-image-block > .image {
|
|
212
|
+
line-height: normal;
|
|
213
|
+
}
|
|
214
|
+
/* A card that shares its paragraph with text sits on its own line within it. */
|
|
215
|
+
.inkkit-root .ProseMirror :not(.inkkit-image-block) > .image.inkkit-file {
|
|
216
|
+
display: block;
|
|
217
|
+
width: fit-content;
|
|
218
|
+
}
|
|
219
|
+
.inkkit-root .ProseMirror .inkkit-image-block.ProseMirror-selectednode {
|
|
220
|
+
outline: none;
|
|
221
|
+
}
|
|
222
|
+
.inkkit-root
|
|
223
|
+
.ProseMirror
|
|
224
|
+
.inkkit-image-block.ProseMirror-selectednode
|
|
225
|
+
> .image {
|
|
226
|
+
outline: 2px solid color-mix(in srgb, var(--_inkkit-accent) 60%, transparent);
|
|
227
|
+
outline-offset: 2px;
|
|
228
|
+
border-radius: 6px;
|
|
229
|
+
}
|
|
230
|
+
.inkkit-root .ProseMirror-gapcursor {
|
|
231
|
+
display: none;
|
|
232
|
+
pointer-events: none;
|
|
233
|
+
position: absolute;
|
|
234
|
+
}
|
|
235
|
+
.inkkit-root .ProseMirror-gapcursor::after {
|
|
236
|
+
content: '';
|
|
237
|
+
display: block;
|
|
238
|
+
position: absolute;
|
|
239
|
+
top: -2px;
|
|
240
|
+
width: 20px;
|
|
241
|
+
border-top: 2px solid var(--_inkkit-accent);
|
|
242
|
+
animation: inkkit-gapcursor-blink 1.1s steps(2, start) infinite;
|
|
243
|
+
}
|
|
244
|
+
@keyframes inkkit-gapcursor-blink {
|
|
245
|
+
to {
|
|
246
|
+
visibility: hidden;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
.inkkit-root .ProseMirror-focused .ProseMirror-gapcursor {
|
|
250
|
+
display: block;
|
|
251
|
+
}
|
|
204
252
|
.inkkit-root .ProseMirror .image img {
|
|
205
253
|
display: block;
|
|
206
254
|
max-width: 100%;
|
|
207
255
|
height: auto;
|
|
208
256
|
border-radius: 6px;
|
|
209
257
|
}
|
|
258
|
+
.inkkit-root .ProseMirror .inkkit-image-preview {
|
|
259
|
+
position: relative;
|
|
260
|
+
display: block;
|
|
261
|
+
width: fit-content;
|
|
262
|
+
max-width: 100%;
|
|
263
|
+
line-height: 0;
|
|
264
|
+
}
|
|
210
265
|
.inkkit-root .ProseMirror .image-absent {
|
|
211
266
|
color: var(--_inkkit-muted);
|
|
212
267
|
font-style: italic;
|
|
213
268
|
}
|
|
214
269
|
.inkkit-root .ProseMirror .image-handle {
|
|
215
270
|
position: absolute;
|
|
216
|
-
right:
|
|
217
|
-
top:
|
|
218
|
-
|
|
219
|
-
|
|
271
|
+
right: 0;
|
|
272
|
+
top: 50%;
|
|
273
|
+
z-index: 1;
|
|
274
|
+
transform: translateY(-50%);
|
|
275
|
+
width: 20px;
|
|
276
|
+
height: 32px;
|
|
277
|
+
max-height: 100%;
|
|
278
|
+
touch-action: none;
|
|
220
279
|
cursor: col-resize;
|
|
221
280
|
opacity: 0;
|
|
222
281
|
}
|
|
@@ -227,22 +286,58 @@
|
|
|
227
286
|
.inkkit-root .ProseMirror .image-handle::after {
|
|
228
287
|
content: '';
|
|
229
288
|
position: absolute;
|
|
230
|
-
right:
|
|
231
|
-
top:
|
|
232
|
-
|
|
289
|
+
right: 8px;
|
|
290
|
+
top: 50%;
|
|
291
|
+
transform: translateY(-50%);
|
|
292
|
+
height: 20px;
|
|
293
|
+
max-height: 100%;
|
|
233
294
|
width: 4px;
|
|
234
295
|
border-radius: 2px;
|
|
235
296
|
background: var(--_inkkit-accent);
|
|
236
297
|
}
|
|
298
|
+
.inkkit-root .ProseMirror[contenteditable='false'] .image-handle {
|
|
299
|
+
display: none;
|
|
300
|
+
}
|
|
237
301
|
|
|
238
302
|
.inkkit-root .ProseMirror .inkkit-file {
|
|
303
|
+
box-sizing: border-box;
|
|
239
304
|
vertical-align: middle;
|
|
240
305
|
border: 1px solid var(--_inkkit-rule);
|
|
241
|
-
border-radius:
|
|
242
|
-
padding:
|
|
306
|
+
border-radius: 6px;
|
|
307
|
+
padding: 6px;
|
|
243
308
|
white-space: normal;
|
|
244
309
|
}
|
|
245
310
|
|
|
311
|
+
.inkkit-root .ProseMirror .inkkit-file-footer {
|
|
312
|
+
display: flex;
|
|
313
|
+
flex-wrap: wrap;
|
|
314
|
+
align-items: center;
|
|
315
|
+
gap: 0.25em 0.5em;
|
|
316
|
+
font-size: 0.9em;
|
|
317
|
+
line-height: 1.4;
|
|
318
|
+
color: var(--_inkkit-muted);
|
|
319
|
+
}
|
|
320
|
+
.inkkit-root .ProseMirror .inkkit-file-footer:not(:first-child) {
|
|
321
|
+
margin-block-start: 0.25em;
|
|
322
|
+
}
|
|
323
|
+
/* Below a picture, the name takes the picture's width rather than widening the card, so the grip
|
|
324
|
+
stays at the picture's edge; a short picture still leaves room for a few characters. */
|
|
325
|
+
.inkkit-root .ProseMirror .inkkit-image-preview ~ .inkkit-file-footer {
|
|
326
|
+
width: 0;
|
|
327
|
+
min-width: 100%;
|
|
328
|
+
}
|
|
329
|
+
.inkkit-root .ProseMirror .image.inkkit-file:has(> .inkkit-image-preview) {
|
|
330
|
+
min-width: min(100%, 8em);
|
|
331
|
+
}
|
|
332
|
+
/* The name truncates; the open arrow stays visible right after it. */
|
|
333
|
+
.inkkit-root .ProseMirror .inkkit-file-name {
|
|
334
|
+
display: flex;
|
|
335
|
+
flex: 1 1 auto;
|
|
336
|
+
align-items: center;
|
|
337
|
+
gap: 0.25em;
|
|
338
|
+
min-width: 0;
|
|
339
|
+
}
|
|
340
|
+
|
|
246
341
|
.inkkit-root .ProseMirror .inkkit-file audio,
|
|
247
342
|
.inkkit-root .ProseMirror .inkkit-file video,
|
|
248
343
|
.inkkit-root .ProseMirror .inkkit-file iframe {
|
|
@@ -261,18 +356,57 @@
|
|
|
261
356
|
}
|
|
262
357
|
|
|
263
358
|
.inkkit-root .ProseMirror .inkkit-file-label {
|
|
359
|
+
flex: 0 1 auto;
|
|
360
|
+
min-width: 0;
|
|
361
|
+
overflow: hidden;
|
|
362
|
+
text-overflow: ellipsis;
|
|
363
|
+
white-space: nowrap;
|
|
364
|
+
}
|
|
365
|
+
.inkkit-root .ProseMirror .inkkit-file-status {
|
|
366
|
+
flex-basis: 100%;
|
|
264
367
|
overflow-wrap: anywhere;
|
|
265
368
|
}
|
|
266
369
|
|
|
267
370
|
.inkkit-root .ProseMirror .inkkit-file-control {
|
|
268
|
-
|
|
371
|
+
flex: none;
|
|
372
|
+
padding: 0.25em 0.5em;
|
|
269
373
|
font: inherit;
|
|
374
|
+
line-height: 1.4;
|
|
375
|
+
white-space: nowrap;
|
|
270
376
|
color: var(--_inkkit-text);
|
|
271
377
|
background: var(--_inkkit-code-bg);
|
|
272
378
|
border: 1px solid var(--_inkkit-rule);
|
|
273
379
|
border-radius: 3px;
|
|
274
380
|
cursor: pointer;
|
|
275
381
|
}
|
|
382
|
+
.inkkit-root .ProseMirror .inkkit-file-open {
|
|
383
|
+
display: inline-flex;
|
|
384
|
+
align-items: center;
|
|
385
|
+
justify-content: center;
|
|
386
|
+
min-width: 1.5em;
|
|
387
|
+
min-height: 1.5em;
|
|
388
|
+
padding: 0;
|
|
389
|
+
color: var(--_inkkit-muted);
|
|
390
|
+
background: transparent;
|
|
391
|
+
border-color: transparent;
|
|
392
|
+
}
|
|
393
|
+
.inkkit-root .ProseMirror .inkkit-file-open:hover {
|
|
394
|
+
color: var(--_inkkit-text);
|
|
395
|
+
background: var(--_inkkit-code-bg);
|
|
396
|
+
}
|
|
397
|
+
.inkkit-root .ProseMirror .inkkit-file-open:focus-visible {
|
|
398
|
+
outline: 2px solid var(--_inkkit-accent);
|
|
399
|
+
outline-offset: 1px;
|
|
400
|
+
}
|
|
401
|
+
.inkkit-root .ProseMirror .inkkit-file-open svg {
|
|
402
|
+
width: 0.85em;
|
|
403
|
+
height: 0.85em;
|
|
404
|
+
fill: none;
|
|
405
|
+
stroke: currentColor;
|
|
406
|
+
stroke-width: 1.5;
|
|
407
|
+
stroke-linecap: round;
|
|
408
|
+
stroke-linejoin: round;
|
|
409
|
+
}
|
|
276
410
|
|
|
277
411
|
.inkkit-root .ProseMirror {
|
|
278
412
|
/* The viewport, not the wrapper Milkdown adds, so a click below the text still places the caret. */
|
package/dist/text-ranges.d.ts
CHANGED
|
@@ -18,7 +18,10 @@ export declare function projectionOffset(projection: TextProjection, position: n
|
|
|
18
18
|
export declare function validateOffsets(text: string, from: number, to: number): void;
|
|
19
19
|
export declare function textRect(rect: Pick<TextRect, 'left' | 'top' | 'right' | 'bottom'>): TextRect;
|
|
20
20
|
export declare function formattedRects(view: EditorView, projection: TextProjection, from: number, to: number): TextRect[];
|
|
21
|
-
export declare function
|
|
21
|
+
export declare function literalRangesRects(plain: HTMLTextAreaElement, ranges: readonly {
|
|
22
|
+
from: number;
|
|
23
|
+
to: number;
|
|
24
|
+
}[]): TextRect[][];
|
|
22
25
|
export declare function intersectsViewport(rect: Pick<TextRect, 'top' | 'right' | 'bottom' | 'left'>, viewport: TextRect): boolean;
|
|
23
26
|
export declare function literalVisibleRanges(plain: HTMLTextAreaElement, viewport: TextRect): {
|
|
24
27
|
from: number;
|
package/dist/text-ranges.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { InkKitError } from './types.js';
|
|
2
2
|
import { fileReference } from './linked-syntax.js';
|
|
3
|
+
import { imageBlockName } from './image-blocks.js';
|
|
3
4
|
export function readableProjection(doc) {
|
|
4
5
|
const result = { text: '', spans: [] };
|
|
5
6
|
let blocks = 0;
|
|
@@ -24,6 +25,11 @@ export function readableProjection(doc) {
|
|
|
24
25
|
String(node.attrs.kind).replace(/^./, (value) => value.toUpperCase()), position, position + 1, 'embed');
|
|
25
26
|
return true;
|
|
26
27
|
}
|
|
28
|
+
if (name === imageBlockName) {
|
|
29
|
+
block(position);
|
|
30
|
+
append(fileReference(node).label || 'Image', position, position + node.nodeSize, 'embed');
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
27
33
|
if (node.isTextblock) {
|
|
28
34
|
block(position + 1);
|
|
29
35
|
if (!node.content.size)
|
|
@@ -110,15 +116,30 @@ export function formattedRects(view, projection, from, to) {
|
|
|
110
116
|
return [textRect(view.coordsAtPos(position))];
|
|
111
117
|
}
|
|
112
118
|
const rects = [];
|
|
113
|
-
|
|
114
|
-
|
|
119
|
+
let low = 0;
|
|
120
|
+
let high = projection.spans.length;
|
|
121
|
+
while (low < high) {
|
|
122
|
+
const middle = (low + high) >>> 1;
|
|
123
|
+
if (projection.spans[middle].to <= from)
|
|
124
|
+
low = middle + 1;
|
|
125
|
+
else
|
|
126
|
+
high = middle;
|
|
127
|
+
}
|
|
128
|
+
for (let index = low; index < projection.spans.length; index++) {
|
|
129
|
+
const span = projection.spans[index];
|
|
130
|
+
if (span.from >= to)
|
|
131
|
+
break;
|
|
132
|
+
if (span.kind === 'separator')
|
|
115
133
|
continue;
|
|
116
134
|
if (span.kind === 'embed' || span.kind === 'break') {
|
|
117
135
|
const node = view.nodeDOM(span.start);
|
|
118
136
|
if (node instanceof Element) {
|
|
137
|
+
// A standalone image's node is its full-width row; the card is what shows.
|
|
119
138
|
const label = node.matches('.inkkit-callout')
|
|
120
139
|
? (node.querySelector(':scope > .inkkit-callout-header > .inkkit-callout-title') ?? node)
|
|
121
|
-
: node
|
|
140
|
+
: node.matches('.inkkit-image-block')
|
|
141
|
+
? (node.firstElementChild ?? node)
|
|
142
|
+
: node;
|
|
122
143
|
rects.push(...Array.from(label.getClientRects(), textRect));
|
|
123
144
|
}
|
|
124
145
|
continue;
|
|
@@ -180,18 +201,20 @@ function withLiteralLayout(plain, measure) {
|
|
|
180
201
|
mirror.remove();
|
|
181
202
|
}
|
|
182
203
|
}
|
|
183
|
-
export function
|
|
204
|
+
export function literalRangesRects(plain, ranges) {
|
|
184
205
|
return (withLiteralLayout(plain, (text) => {
|
|
185
206
|
const range = plain.ownerDocument.createRange();
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
207
|
+
return ranges.map(({ from, to }) => {
|
|
208
|
+
range.setStart(text, from);
|
|
209
|
+
range.setEnd(text, from === to ? Math.min(to + 1, text.length) : to);
|
|
210
|
+
return Array.from(range.getClientRects(), (rect) => textRect({
|
|
211
|
+
left: rect.left,
|
|
212
|
+
right: from === to ? rect.left : rect.right,
|
|
213
|
+
top: rect.top,
|
|
214
|
+
bottom: rect.bottom,
|
|
215
|
+
}));
|
|
216
|
+
});
|
|
217
|
+
}) ?? ranges.map(() => []));
|
|
195
218
|
}
|
|
196
219
|
export function intersectsViewport(rect, viewport) {
|
|
197
220
|
return (viewport.width > 0 &&
|