@aicayzer/inkkit 0.0.16 → 0.0.18
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/README.md +2 -0
- package/dist/callouts.d.ts +0 -1
- package/dist/callouts.js +12 -35
- package/dist/code-fences.js +6 -1
- package/dist/comments.d.ts +21 -0
- package/dist/comments.js +55 -4
- package/dist/core.d.ts +7 -0
- package/dist/core.js +2 -0
- package/dist/cursor.d.ts +2 -0
- package/dist/cursor.js +40 -0
- package/dist/dialect.js +109 -11
- package/dist/drop-placement.d.ts +19 -0
- package/dist/drop-placement.js +47 -0
- package/dist/editor.d.ts +32 -1
- package/dist/editor.js +293 -61
- package/dist/html-import.d.ts +13 -0
- package/dist/html-import.js +477 -0
- package/dist/image-blocks.d.ts +15 -0
- package/dist/image-blocks.js +44 -1
- package/dist/index.d.ts +1 -7
- package/dist/index.js +3 -2
- package/dist/link-safety.d.ts +17 -0
- package/dist/link-safety.js +29 -0
- package/dist/literals.d.ts +1 -0
- package/dist/literals.js +14 -9
- package/dist/mermaid.d.ts +21 -1
- package/dist/mermaid.js +92 -9
- package/dist/paste-html.d.ts +8 -0
- package/dist/paste-html.js +21 -0
- package/dist/paste.d.ts +7 -0
- package/dist/paste.js +152 -43
- package/dist/preserve.d.ts +19 -2
- package/dist/preserve.js +861 -124
- package/dist/print.js +2 -5
- package/dist/references.d.ts +2 -0
- package/dist/references.js +63 -13
- package/dist/scroll.d.ts +15 -0
- package/dist/scroll.js +27 -0
- package/dist/spreadsheet.d.ts +6 -1
- package/dist/spreadsheet.js +29 -15
- package/dist/style.css +11 -19
- package/dist/tables.js +24 -2
- package/package.json +12 -4
package/dist/print.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { clipboardContent } from './clipboard.js';
|
|
2
2
|
import { shareableFragment } from './comments.js';
|
|
3
|
+
import { isSafeLinkTarget } from './link-safety.js';
|
|
3
4
|
import { fileReference } from './linked-syntax.js';
|
|
4
5
|
import { sourceFrontmatter } from './literals.js';
|
|
5
6
|
import { diagramImage, renderDiagram } from './mermaid.js';
|
|
@@ -220,15 +221,11 @@ const printClasses = new Set([
|
|
|
220
221
|
'inkkit-print-diagram',
|
|
221
222
|
]);
|
|
222
223
|
function safeLink(value) {
|
|
223
|
-
if (
|
|
224
|
+
if (value.includes('\\') || !isSafeLinkTarget(value))
|
|
224
225
|
return undefined;
|
|
225
226
|
const href = value.trim();
|
|
226
227
|
if (!href)
|
|
227
228
|
return undefined;
|
|
228
|
-
// A colon in the first path component denotes a scheme, including an
|
|
229
|
-
// obfuscated one. Relative paths can still contain colons after a slash.
|
|
230
|
-
if (/^[^/?#]*:/.test(href) && !/^(https?:|mailto:)/i.test(href))
|
|
231
|
-
return undefined;
|
|
232
229
|
return href.replaceAll(' ', '%20');
|
|
233
230
|
}
|
|
234
231
|
function cleanSemantics(container, localIDs) {
|
package/dist/references.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface LocatedDefinition {
|
|
|
6
6
|
}
|
|
7
7
|
export declare const referenceDefinitions: (doc: ProseNode) => Map<string, LocatedDefinition>;
|
|
8
8
|
export declare const footnoteDefinitions: (doc: ProseNode) => Map<string, LocatedDefinition>;
|
|
9
|
+
/** Replaces each line break, with the whitespace around it, by one space. */
|
|
10
|
+
export declare function singleLine(value: string): string;
|
|
9
11
|
export declare const remarkReferencesPlugin: import("@milkdown/kit/utils").$Remark<"inkkitReferences", unknown>;
|
|
10
12
|
export declare const referenceLinks: import("@milkdown/kit/utils").$MarkSchema<"link">;
|
|
11
13
|
export declare const referenceDefinition: import("@milkdown/kit/utils").$Node;
|
package/dist/references.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { editorLabels } from './labels.js';
|
|
2
|
+
import { isSafeLinkTarget } from './link-safety.js';
|
|
2
3
|
import { $node, $remark, $prose } from '@milkdown/kit/utils';
|
|
3
4
|
import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
|
|
4
5
|
import { linkSchema } from '@milkdown/kit/preset/commonmark';
|
|
@@ -36,6 +37,38 @@ function contentShape(value) {
|
|
|
36
37
|
};
|
|
37
38
|
return JSON.stringify(clean(value));
|
|
38
39
|
}
|
|
40
|
+
/** Replaces each line break, with the whitespace around it, by one space. */
|
|
41
|
+
export function singleLine(value) {
|
|
42
|
+
return value.replace(/[ \t]*[\r\n][ \t\r\n]*/g, ' ');
|
|
43
|
+
}
|
|
44
|
+
function nullableSingleLine(value) {
|
|
45
|
+
return value == null ? value : singleLine(value);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A label is written as its authored text, so one that did not come from
|
|
49
|
+
* Markdown could close its brackets early or span lines. Line breaks become
|
|
50
|
+
* one space and an unescaped bracket is escaped. An authored label has no
|
|
51
|
+
* unescaped bracket, and source preservation keeps an unedited one as written.
|
|
52
|
+
*/
|
|
53
|
+
function writableLabel(label) {
|
|
54
|
+
const flat = singleLine(String(label));
|
|
55
|
+
let written = '';
|
|
56
|
+
for (let index = 0; index < flat.length; index++) {
|
|
57
|
+
const character = flat[index];
|
|
58
|
+
if (character === '\\') {
|
|
59
|
+
written += character;
|
|
60
|
+
if (index + 1 < flat.length)
|
|
61
|
+
written += flat[++index];
|
|
62
|
+
else
|
|
63
|
+
written += '\\';
|
|
64
|
+
}
|
|
65
|
+
else if (character === '[' || character === ']')
|
|
66
|
+
written += `\\${character}`;
|
|
67
|
+
else
|
|
68
|
+
written += character;
|
|
69
|
+
}
|
|
70
|
+
return written;
|
|
71
|
+
}
|
|
39
72
|
const labelPlaceholder = 'inkkit-authored-label';
|
|
40
73
|
const authoredLinkReference = (untyped, parent, state, info) => {
|
|
41
74
|
const node = untyped;
|
|
@@ -50,19 +83,19 @@ const authoredLinkReference = (untyped, parent, state, info) => {
|
|
|
50
83
|
node.referenceContent === contentShape(node.children);
|
|
51
84
|
if (node.referenceType !== 'full' &&
|
|
52
85
|
(unchanged || normaliseLabel(display) === normaliseLabel(node.identifier)))
|
|
53
|
-
return `[${unchanged ? node.label : display}]${node.referenceType === 'collapsed' ? '[]' : ''}`;
|
|
86
|
+
return `[${unchanged ? writableLabel(node.label) : display}]${node.referenceType === 'collapsed' ? '[]' : ''}`;
|
|
54
87
|
// Raw entity and escape spelling participates in reference matching.
|
|
55
88
|
return (full.slice(0, -labelPlaceholder.length - 2) +
|
|
56
|
-
`[${node.label ?? node.identifier}]`);
|
|
89
|
+
`[${writableLabel(node.label ?? node.identifier)}]`);
|
|
57
90
|
};
|
|
58
91
|
authoredLinkReference.peek = () => '[';
|
|
59
92
|
const authoredDefinition = (node, parent, state, info) => defaultHandlers
|
|
60
93
|
.definition({ ...node, label: labelPlaceholder, identifier: labelPlaceholder }, parent, state, info)
|
|
61
|
-
.replace(`[${labelPlaceholder}]:`, `[${
|
|
94
|
+
.replace(`[${labelPlaceholder}]:`, `[${writableLabel(node.label ?? node.identifier)}]:`);
|
|
62
95
|
const footnoteHandlers = gfmFootnoteToMarkdown().handlers;
|
|
63
|
-
const authoredFootnoteReference = (node) => `[^${
|
|
96
|
+
const authoredFootnoteReference = (node) => `[^${writableLabel(node.label ?? node.identifier)}]`;
|
|
64
97
|
authoredFootnoteReference.peek = () => '[';
|
|
65
|
-
const authoredFootnoteDefinition = (node, parent, state, info) => footnoteHandlers.footnoteDefinition({ ...node, label: labelPlaceholder, identifier: labelPlaceholder }, parent, state, info).replace(`[^${labelPlaceholder}]:`, `[^${
|
|
98
|
+
const authoredFootnoteDefinition = (node, parent, state, info) => footnoteHandlers.footnoteDefinition({ ...node, label: labelPlaceholder, identifier: labelPlaceholder }, parent, state, info).replace(`[^${labelPlaceholder}]:`, `[^${writableLabel(node.label ?? node.identifier)}]:`);
|
|
66
99
|
function remarkReferences() {
|
|
67
100
|
const data = this.data();
|
|
68
101
|
(data.micromarkExtensions ??= []).push(gfmFootnote());
|
|
@@ -137,8 +170,13 @@ export const referenceLinks = linkSchema.extendSchema((base) => (ctx) => {
|
|
|
137
170
|
tag: 'a[href]',
|
|
138
171
|
getAttrs(dom) {
|
|
139
172
|
const element = dom;
|
|
173
|
+
const href = element.getAttribute('href') ?? '';
|
|
174
|
+
// Imported HTML keeps the text of a link it cannot trust. Markdown
|
|
175
|
+
// source does not pass through here, so authored addresses stay.
|
|
176
|
+
if (!isSafeLinkTarget(href))
|
|
177
|
+
return false;
|
|
140
178
|
return {
|
|
141
|
-
href
|
|
179
|
+
href,
|
|
142
180
|
title: element.getAttribute('title'),
|
|
143
181
|
label: element.getAttribute('data-inkkit-label'),
|
|
144
182
|
identifier: element.getAttribute('data-inkkit-reference'),
|
|
@@ -211,12 +249,18 @@ export const referenceDefinition = $node('reference_definition', () => ({
|
|
|
211
249
|
parseDOM: [
|
|
212
250
|
{
|
|
213
251
|
tag: '[data-inkkit-reference-definition]',
|
|
214
|
-
getAttrs
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
252
|
+
getAttrs(dom) {
|
|
253
|
+
const url = dom.getAttribute('data-inkkit-url') ?? '';
|
|
254
|
+
if (!isSafeLinkTarget(url))
|
|
255
|
+
return false;
|
|
256
|
+
return {
|
|
257
|
+
label: dom.getAttribute('data-inkkit-label') ?? '',
|
|
258
|
+
identifier: dom.getAttribute('data-inkkit-reference-definition') ?? '',
|
|
259
|
+
url,
|
|
260
|
+
// Saved on one line, as the writer would save it.
|
|
261
|
+
title: nullableSingleLine(dom.getAttribute('data-inkkit-title')),
|
|
262
|
+
};
|
|
263
|
+
},
|
|
220
264
|
},
|
|
221
265
|
],
|
|
222
266
|
toDOM: (node) => [
|
|
@@ -244,7 +288,13 @@ export const referenceDefinition = $node('reference_definition', () => ({
|
|
|
244
288
|
toMarkdown: {
|
|
245
289
|
match: (node) => node.type.name === 'reference_definition',
|
|
246
290
|
runner: (state, node) => {
|
|
247
|
-
|
|
291
|
+
// A line break in a definition title is written as it is, and a blank
|
|
292
|
+
// line would end the definition.
|
|
293
|
+
const title = node.attrs.title;
|
|
294
|
+
state.addNode('definition', undefined, undefined, {
|
|
295
|
+
...node.attrs,
|
|
296
|
+
title: typeof title === 'string' ? singleLine(title) : title,
|
|
297
|
+
});
|
|
248
298
|
},
|
|
249
299
|
},
|
|
250
300
|
}));
|
package/dist/scroll.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Rounds a distance away from zero, to a whole number of pixels. */
|
|
2
|
+
export declare const scrollOutward: (distance: number) => number;
|
|
3
|
+
/**
|
|
4
|
+
* Scrolls an element by a distance and returns what it did not scroll. A
|
|
5
|
+
* scroll position is a whole number of pixels in some engines, so a fraction
|
|
6
|
+
* is rounded away from zero: rounded to nothing, a reveal would leave the last
|
|
7
|
+
* fraction of the target outside the element.
|
|
8
|
+
*/
|
|
9
|
+
export declare function scrollWholePixels(element: HTMLElement, vertical: number, horizontal: number, padding?: {
|
|
10
|
+
top: number;
|
|
11
|
+
bottom: number;
|
|
12
|
+
}): {
|
|
13
|
+
vertical: number;
|
|
14
|
+
horizontal: number;
|
|
15
|
+
};
|
package/dist/scroll.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Rounds a distance away from zero, to a whole number of pixels. */
|
|
2
|
+
export const scrollOutward = (distance) => distance > 0 ? Math.ceil(distance) : Math.floor(distance);
|
|
3
|
+
/**
|
|
4
|
+
* Scrolls an element by a distance and returns what it did not scroll. A
|
|
5
|
+
* scroll position is a whole number of pixels in some engines, so a fraction
|
|
6
|
+
* is rounded away from zero: rounded to nothing, a reveal would leave the last
|
|
7
|
+
* fraction of the target outside the element.
|
|
8
|
+
*/
|
|
9
|
+
export function scrollWholePixels(element, vertical, horizontal, padding = { top: 0, bottom: 0 }) {
|
|
10
|
+
const top = element.scrollTop, left = element.scrollLeft;
|
|
11
|
+
const target = top + scrollOutward(vertical);
|
|
12
|
+
const last = element.scrollHeight - element.clientHeight;
|
|
13
|
+
// Only padding is left beyond the target, so show it: a reveal that stops
|
|
14
|
+
// at the first or last line would otherwise hide that padding.
|
|
15
|
+
element.scrollTop =
|
|
16
|
+
vertical < 0 && target <= padding.top
|
|
17
|
+
? 0
|
|
18
|
+
: vertical > 0 && last > 0 && target >= last - padding.bottom
|
|
19
|
+
? last
|
|
20
|
+
: target;
|
|
21
|
+
element.scrollLeft += scrollOutward(horizontal);
|
|
22
|
+
const remaining = (distance, moved) => distance > 0 ? Math.max(0, distance - moved) : Math.min(0, distance - moved);
|
|
23
|
+
return {
|
|
24
|
+
vertical: remaining(vertical, element.scrollTop - top),
|
|
25
|
+
horizontal: remaining(horizontal, element.scrollLeft - left),
|
|
26
|
+
};
|
|
27
|
+
}
|
package/dist/spreadsheet.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import type { Ctx } from '@milkdown/kit/ctx';
|
|
2
2
|
import { type ClipboardInput } from './types.js';
|
|
3
|
-
|
|
3
|
+
/** Pastes a spreadsheet at the selection, or at `at` for a drop, which
|
|
4
|
+
* always lands outside a table. */
|
|
5
|
+
export declare function pasteSpreadsheet(ctx: Ctx, input: ClipboardInput, at?: {
|
|
6
|
+
from: number;
|
|
7
|
+
to: number;
|
|
8
|
+
}): boolean;
|
package/dist/spreadsheet.js
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { editorViewCtx } from '@milkdown/kit/core';
|
|
2
|
-
import { DOMParser as ProseParser, Fragment, } from '@milkdown/kit/prose/model';
|
|
2
|
+
import { DOMParser as ProseParser, Fragment, Slice, } from '@milkdown/kit/prose/model';
|
|
3
3
|
import { isInTable, selectedRect } from '@milkdown/kit/prose/tables';
|
|
4
4
|
import { InkKitError } from './types.js';
|
|
5
5
|
import { literalCommentSpans } from './comments.js';
|
|
6
|
+
import { restoreConvertedSpaces } from './paste-html.js';
|
|
7
|
+
import { importableSlice } from './html-import.js';
|
|
8
|
+
import { caretAfter } from './drop-placement.js';
|
|
6
9
|
import { normalizeTableAlignment } from './table-alignment.js';
|
|
7
10
|
import { dispatchTableOperation, editableTable, selectTableRectangle, } from './tables.js';
|
|
8
|
-
|
|
11
|
+
/** Pastes a spreadsheet at the selection, or at `at` for a drop, which
|
|
12
|
+
* always lands outside a table. */
|
|
13
|
+
export function pasteSpreadsheet(ctx, input, at) {
|
|
9
14
|
const view = ctx.get(editorViewCtx);
|
|
10
15
|
if (input.plainText || input.markdown != null)
|
|
11
16
|
return false;
|
|
12
|
-
const inTable = isInTable(view.state);
|
|
17
|
+
const inTable = !at && isInTable(view.state);
|
|
13
18
|
if (input.html &&
|
|
14
19
|
/data-inkkit-(?:markdown|reference|footnote|comment)/i.test(input.html)) {
|
|
15
20
|
if (inTable && /<table[\s>]/i.test(input.html))
|
|
@@ -56,13 +61,18 @@ export function pasteSpreadsheet(ctx, input) {
|
|
|
56
61
|
}
|
|
57
62
|
if (cursor < input.html.length)
|
|
58
63
|
children.push(schema.text(input.html.slice(cursor)));
|
|
59
|
-
|
|
64
|
+
// The source is kept only where it reads back as one literal block.
|
|
65
|
+
const content = importableSlice(ctx, new Slice(Fragment.from(schema.nodes.literal_markdown.create(null, children)), 0, 0)).content;
|
|
60
66
|
const selection = view.state.selection;
|
|
61
|
-
const tr =
|
|
62
|
-
|
|
63
|
-
selection.$from.parent.
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
const tr = at
|
|
68
|
+
? view.state.tr.replaceWith(at.from, at.to, content)
|
|
69
|
+
: selection.$from.parent.type.name === 'paragraph' &&
|
|
70
|
+
selection.empty &&
|
|
71
|
+
selection.$from.parent.content.size === 0
|
|
72
|
+
? view.state.tr.replaceWith(selection.$from.before(), selection.$from.after(), content)
|
|
73
|
+
: content.childCount === 1
|
|
74
|
+
? view.state.tr.replaceSelectionWith(content.firstChild)
|
|
75
|
+
: view.state.tr.replaceSelection(new Slice(content, 0, 0));
|
|
66
76
|
dispatchTableOperation(view, tr);
|
|
67
77
|
return true;
|
|
68
78
|
}
|
|
@@ -73,11 +83,13 @@ export function pasteSpreadsheet(ctx, input) {
|
|
|
73
83
|
const rows = grid.cells.map((row, index) => schema.nodes[index ? 'table_row' : 'table_header_row'].create(null, row.map((content, column) => schema.nodes[index ? 'table_cell' : 'table_header'].create({ alignment: grid.alignment?.[column] ?? 'left' }, schema.nodes.paragraph.create(null, content)))));
|
|
74
84
|
const table = schema.nodes.table.create(null, rows);
|
|
75
85
|
const selection = view.state.selection;
|
|
76
|
-
const tr =
|
|
77
|
-
|
|
78
|
-
selection.$from.parent.
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
const tr = at
|
|
87
|
+
? view.state.tr.replaceWith(at.from, at.to, table)
|
|
88
|
+
: selection.$from.parent.type.name === 'paragraph' &&
|
|
89
|
+
selection.empty &&
|
|
90
|
+
selection.$from.parent.content.size === 0
|
|
91
|
+
? view.state.tr.replaceWith(selection.$from.before(), selection.$from.after(), table)
|
|
92
|
+
: view.state.tr.replaceSelectionWith(table);
|
|
81
93
|
let tableStart = -1;
|
|
82
94
|
tr.doc.descendants((node, pos) => {
|
|
83
95
|
if (node === table)
|
|
@@ -85,7 +97,8 @@ export function pasteSpreadsheet(ctx, input) {
|
|
|
85
97
|
});
|
|
86
98
|
if (tableStart < 0)
|
|
87
99
|
reject();
|
|
88
|
-
|
|
100
|
+
// Selecting the new table would let the next keystroke replace it.
|
|
101
|
+
tr.setSelection(caretAfter(tr.doc, tableStart - 1 + table.nodeSize));
|
|
89
102
|
dispatchTableOperation(view, tr);
|
|
90
103
|
return true;
|
|
91
104
|
}
|
|
@@ -261,6 +274,7 @@ function htmlGrid(schema, html) {
|
|
|
261
274
|
for (const link of cell.querySelectorAll('a'))
|
|
262
275
|
if (!link.hasAttribute('href'))
|
|
263
276
|
reject();
|
|
277
|
+
restoreConvertedSpaces(cell);
|
|
264
278
|
const parsed = parser.parse(cell, { preserveWhitespace: true });
|
|
265
279
|
if (parsed.childCount === 0)
|
|
266
280
|
return Fragment.empty;
|
package/dist/style.css
CHANGED
|
@@ -684,24 +684,16 @@
|
|
|
684
684
|
border-radius: 4px;
|
|
685
685
|
}
|
|
686
686
|
|
|
687
|
-
/* Syntax colors: One
|
|
687
|
+
/* Syntax colors: One Light and One Dark hues without the blues, darkened or
|
|
688
|
+
lightened to WCAG AA contrast on the code background. light-dark() follows
|
|
689
|
+
the editor's color scheme, which a host can force. */
|
|
688
690
|
.inkkit-root {
|
|
689
691
|
--_inkkit-code-comment: var(--_inkkit-muted);
|
|
690
|
-
--_inkkit-code-keyword: #a626a4;
|
|
691
|
-
--_inkkit-code-string: #
|
|
692
|
-
--_inkkit-code-number: #
|
|
693
|
-
--_inkkit-code-title: #
|
|
694
|
-
--_inkkit-code-attr: #
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
@media (prefers-color-scheme: dark) {
|
|
698
|
-
.inkkit-root {
|
|
699
|
-
--_inkkit-code-keyword: #c678dd;
|
|
700
|
-
--_inkkit-code-string: #98c379;
|
|
701
|
-
--_inkkit-code-number: #d19a66;
|
|
702
|
-
--_inkkit-code-title: #e5c07b;
|
|
703
|
-
--_inkkit-code-attr: #e06c75;
|
|
704
|
-
}
|
|
692
|
+
--_inkkit-code-keyword: light-dark(#a626a4, #c77bde);
|
|
693
|
+
--_inkkit-code-string: light-dark(#3b763a, #98c379);
|
|
694
|
+
--_inkkit-code-number: light-dark(#8d6001, #d19a66);
|
|
695
|
+
--_inkkit-code-title: light-dark(#8d6101, #e5c07b);
|
|
696
|
+
--_inkkit-code-attr: light-dark(#c82c1e, #e37981);
|
|
705
697
|
}
|
|
706
698
|
|
|
707
699
|
.inkkit-root .hljs-comment,
|
|
@@ -898,8 +890,8 @@
|
|
|
898
890
|
.inkkit-root .inkkit-mermaid-preview {
|
|
899
891
|
padding: 16px;
|
|
900
892
|
overflow: auto;
|
|
901
|
-
background: #fff;
|
|
902
|
-
color: #222;
|
|
893
|
+
background: var(--inkkit-diagram-background, #fff);
|
|
894
|
+
color: var(--inkkit-diagram-text-color, #222);
|
|
903
895
|
}
|
|
904
896
|
.inkkit-root .inkkit-mermaid-preview svg {
|
|
905
897
|
display: block;
|
|
@@ -907,7 +899,7 @@
|
|
|
907
899
|
height: auto;
|
|
908
900
|
}
|
|
909
901
|
.inkkit-root .inkkit-mermaid-preview[data-state='error'] {
|
|
910
|
-
color: #9b2424;
|
|
902
|
+
color: var(--inkkit-diagram-error-color, #9b2424);
|
|
911
903
|
font-size: calc(var(--inkkit-font-size, 15px) * 0.9);
|
|
912
904
|
}
|
|
913
905
|
|
package/dist/tables.js
CHANGED
|
@@ -150,9 +150,31 @@ export function tableCommand(ctx, command, options) {
|
|
|
150
150
|
view.dispatch(tr);
|
|
151
151
|
return true;
|
|
152
152
|
}
|
|
153
|
+
if (command === 'addRowBefore' || command === 'addRowAfter') {
|
|
154
|
+
if (!isInTable(view.state))
|
|
155
|
+
return false;
|
|
156
|
+
const { tableStart } = selectedRect(view.state);
|
|
157
|
+
const add = command === 'addRowBefore' ? addRowBefore : addRowAfter;
|
|
158
|
+
return add(view.state, (tr) => {
|
|
159
|
+
// GFM keeps alignment once per column, so a new row's cells take the
|
|
160
|
+
// header's; otherwise they read back aligned and the edit is refused.
|
|
161
|
+
const table = tr.doc.nodeAt(tableStart - 1);
|
|
162
|
+
const map = TableMap.get(table);
|
|
163
|
+
for (let row = 1; row < map.height; row++)
|
|
164
|
+
for (let col = 0; col < map.width; col++) {
|
|
165
|
+
const offset = map.map[row * map.width + col];
|
|
166
|
+
const cell = table.nodeAt(offset);
|
|
167
|
+
const { alignment } = table.nodeAt(map.map[col]).attrs;
|
|
168
|
+
if (cell.attrs.alignment !== alignment)
|
|
169
|
+
tr.setNodeMarkup(tableStart + offset, undefined, {
|
|
170
|
+
...cell.attrs,
|
|
171
|
+
alignment,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
view.dispatch(tr);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
153
177
|
const actions = {
|
|
154
|
-
addRowBefore,
|
|
155
|
-
addRowAfter,
|
|
156
178
|
addColumnBefore,
|
|
157
179
|
addColumnAfter,
|
|
158
180
|
deleteRow,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aicayzer/inkkit",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "A preserving Markdown editor for offline web views and the web",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
"types": "./dist/index.d.ts",
|
|
14
14
|
"import": "./dist/index.js"
|
|
15
15
|
},
|
|
16
|
+
"./core": {
|
|
17
|
+
"types": "./dist/core.d.ts",
|
|
18
|
+
"import": "./dist/core.js"
|
|
19
|
+
},
|
|
16
20
|
"./style.css": "./dist/style.css"
|
|
17
21
|
},
|
|
18
22
|
"types": "./dist/index.d.ts",
|
|
@@ -23,7 +27,9 @@
|
|
|
23
27
|
"README.md"
|
|
24
28
|
],
|
|
25
29
|
"sideEffects": [
|
|
26
|
-
"**/*.css"
|
|
30
|
+
"**/*.css",
|
|
31
|
+
"./dist/index.js",
|
|
32
|
+
"./src/index.ts"
|
|
27
33
|
],
|
|
28
34
|
"publishConfig": {
|
|
29
35
|
"access": "public",
|
|
@@ -43,10 +49,11 @@
|
|
|
43
49
|
"build:playground": "vite build playground --config vite.config.ts",
|
|
44
50
|
"test:package": "node scripts/test-package.mjs",
|
|
45
51
|
"check": "pnpm typecheck && pnpm test && pnpm build && pnpm test:package",
|
|
46
|
-
"test:browser": "playwright test --project=chromium"
|
|
52
|
+
"test:browser": "playwright test --project=chromium",
|
|
53
|
+
"test:built-playground": "playwright test --config playwright.built.config.ts"
|
|
47
54
|
},
|
|
48
55
|
"dependencies": {
|
|
49
|
-
"@milkdown/kit": "7.22.
|
|
56
|
+
"@milkdown/kit": "7.22.3",
|
|
50
57
|
"dompurify": "3.4.16",
|
|
51
58
|
"lowlight": "^3.3.0",
|
|
52
59
|
"mdast-util-from-markdown": "^2.1.0",
|
|
@@ -66,6 +73,7 @@
|
|
|
66
73
|
"micromark-extension-highlight-mark": "1.2.0",
|
|
67
74
|
"micromark-util-normalize-identifier": "^2.0.1",
|
|
68
75
|
"micromark-util-types": "^2.0.3",
|
|
76
|
+
"prosemirror-drop-indicator": "0.1.4",
|
|
69
77
|
"prosemirror-search": "^1.1.1"
|
|
70
78
|
},
|
|
71
79
|
"devDependencies": {
|