@aicayzer/inkkit 0.0.7 → 0.0.9
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 +25 -2
- package/README.md +16 -16
- package/dist/callouts.js +6 -3
- package/dist/decorations.js +7 -6
- package/dist/editor.d.ts +86 -5
- package/dist/editor.js +767 -73
- package/dist/images.d.ts +1 -0
- package/dist/images.js +11 -0
- package/dist/index.d.ts +3 -2
- package/dist/labels.d.ts +28 -0
- package/dist/labels.js +26 -0
- package/dist/mermaid.js +6 -3
- package/dist/paste.d.ts +1 -0
- package/dist/paste.js +5 -1
- package/dist/references.js +5 -4
- package/dist/search.d.ts +2 -1
- package/dist/search.js +53 -22
- package/dist/selection.js +22 -10
- package/dist/source.d.ts +0 -1
- package/dist/source.js +0 -60
- package/dist/style.css +377 -299
- package/dist/tables.d.ts +10 -1
- package/dist/tables.js +87 -11
- package/dist/tasks.js +2 -0
- package/dist/text-ranges.d.ts +26 -0
- package/dist/text-ranges.js +228 -0
- package/dist/types.d.ts +40 -1
- package/package.json +4 -2
package/NOTICE
CHANGED
|
@@ -2,5 +2,28 @@ InkKit includes editor behavior and source from PadPad and Memos.
|
|
|
2
2
|
Copyright (c) 2026 August Cayzer. Licensed under the MIT License.
|
|
3
3
|
Sources: https://github.com/aicayzer/padpad and https://github.com/aicayzer/memos
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
The scoped table styles in src/style.css are adapted from prosemirror-tables.
|
|
6
|
+
Source: https://github.com/ProseMirror/prosemirror-tables
|
|
7
|
+
|
|
8
|
+
Copyright (C) 2015-2016 by Marijn Haverbeke <marijnh@gmail.com> and others
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in
|
|
18
|
+
all copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
26
|
+
THE SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Milkdown and other runtime dependencies retain their own licences. They are
|
|
29
|
+
installed as dependencies.
|
package/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# InkKit
|
|
2
2
|
|
|
3
|
-
InkKit is a
|
|
3
|
+
InkKit is a reusable Markdown editor for simple writing tools and richer document apps. It provides formatted editing, source preservation, portable clipboard content and optional host-managed images, while your app controls its appearance, files and interface.
|
|
4
|
+
|
|
5
|
+
Write in formatted or source mode with shared undo/redo. Edit tables, task lists, footnotes, reference links, highlights and callouts. Preview bounded Mermaid diagrams offline. Copy readable text and semantic HTML, explicitly copy Markdown source, or capture a complete printable document. Native hosts can use scoped readable-text ranges and demand-driven geometry with their own search controls and viewport insets. Unsupported syntax remains editable literal Markdown.
|
|
6
|
+
|
|
7
|
+
Host controls, read-only and text-input policies, command availability, scoped appearance, labels and shortcuts are available from 0.0.8. Check the [releases](https://github.com/aicayzer/inkkit/releases) for published versions and verification evidence.
|
|
4
8
|
|
|
5
9
|
```sh
|
|
6
10
|
npm install @aicayzer/inkkit
|
|
@@ -10,39 +14,35 @@ npm install @aicayzer/inkkit
|
|
|
10
14
|
import { InkKitEditor } from '@aicayzer/inkkit'
|
|
11
15
|
import '@aicayzer/inkkit/style.css'
|
|
12
16
|
|
|
13
|
-
const
|
|
17
|
+
const root = document.getElementById('editor')!
|
|
18
|
+
const editor = await InkKitEditor.mount(root, {
|
|
14
19
|
changed(text, generation) {
|
|
15
|
-
|
|
20
|
+
// Notify the host; capture a fresh snapshot when saving.
|
|
16
21
|
},
|
|
17
22
|
stateChanged(state) {
|
|
18
|
-
|
|
23
|
+
// Update the host's formatting controls.
|
|
19
24
|
},
|
|
20
25
|
openLink(href) {
|
|
21
|
-
|
|
26
|
+
// Open through the host.
|
|
22
27
|
},
|
|
23
28
|
copy(text) {
|
|
24
|
-
|
|
29
|
+
// Write code-block text to the clipboard.
|
|
25
30
|
},
|
|
26
31
|
})
|
|
32
|
+
|
|
27
33
|
editor.loadDocument({
|
|
28
34
|
documentId: 'note',
|
|
29
35
|
generation: 1,
|
|
30
36
|
format: 'md',
|
|
31
|
-
text: '# Hello\n',
|
|
37
|
+
text: '# Hello\n\nStart writing.\n',
|
|
32
38
|
})
|
|
33
39
|
const snapshot = editor.snapshot(1)
|
|
34
40
|
```
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
InkKit runs on the web and in offline web views. Hosts use its public TypeScript facade and own toolbars, menus, persistence, clipboard bridges, Print/PDF actions and image storage. Images require an adapter; private references stay opaque. TXT stays literal. RTF files and richer media are outside current support.
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
Start with the [feature guide](docs/supported-syntax.md) and [simple and rich integration examples](docs/integration.md). The [documentation index](docs/README.md) links to precise API, preservation, playground, verification and publication guidance.
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
See [supported syntax](docs/supported-syntax.md), [the host API](docs/api.md), [preservation and clipboard behavior](docs/preservation.md), [development](docs/development.md), and [releases](docs/releasing.md).
|
|
43
|
-
|
|
44
|
-
Delivery scope and release status are tracked in the [InkKit Project](https://github.com/users/aicayzer/projects/3) and [milestones](https://github.com/aicayzer/inkkit/milestones).
|
|
46
|
+
Scope and release status live in the [InkKit Project](https://github.com/users/aicayzer/projects/3) and [version milestones](https://github.com/aicayzer/inkkit/milestones). Optional media extensions are tracked there. Only documented, released features form the supported package contract.
|
|
45
47
|
|
|
46
48
|
MIT licensed. InkKit builds on the public PadPad and Memos editors; see [NOTICE](NOTICE).
|
|
47
|
-
|
|
48
|
-
Complete source/formatted editing, literal find/replace and replace-all, and current ordered headings/navigation are available through the public facade. Mode switching keeps document identity and history; unsupported or incomplete source and TXT remain saveable. Hosts own the editing controls and outline presentation. See the [API contracts](docs/api.md).
|
package/dist/callouts.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { $node, $prose, $remark } from '@milkdown/kit/utils';
|
|
2
|
+
import { editorLabels } from './labels.js';
|
|
2
3
|
import { remarkCtx } from '@milkdown/kit/core';
|
|
3
4
|
import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
|
|
4
5
|
import { defaultHandlers } from 'mdast-util-to-markdown';
|
|
@@ -238,7 +239,7 @@ export const calloutSchema = $node('inkkit_callout', (ctx) => ({
|
|
|
238
239
|
},
|
|
239
240
|
},
|
|
240
241
|
}));
|
|
241
|
-
export const calloutView = $prose(() => new Plugin({
|
|
242
|
+
export const calloutView = $prose((ctx) => new Plugin({
|
|
242
243
|
key: new PluginKey('inkkitCalloutView'),
|
|
243
244
|
props: {
|
|
244
245
|
nodeViews: {
|
|
@@ -266,8 +267,10 @@ export const calloutView = $prose(() => new Plugin({
|
|
|
266
267
|
dom.setAttribute('data-inkkit-folded', String(folded));
|
|
267
268
|
button.hidden = !node.attrs.fold;
|
|
268
269
|
button.setAttribute('aria-expanded', String(!folded));
|
|
269
|
-
button.setAttribute('aria-label', `${folded ?
|
|
270
|
-
button.textContent = folded
|
|
270
|
+
button.setAttribute('aria-label', `${folded ? editorLabels(ctx).expandCallout : editorLabels(ctx).collapseCallout} ${title.textContent}`);
|
|
271
|
+
button.textContent = folded
|
|
272
|
+
? editorLabels(ctx).expandCallout
|
|
273
|
+
: editorLabels(ctx).collapseCallout;
|
|
271
274
|
};
|
|
272
275
|
const toggle = () => {
|
|
273
276
|
folded = !folded;
|
package/dist/decorations.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { Plugin, PluginKey } from '@milkdown/kit/prose/state';
|
|
2
2
|
import { Decoration, DecorationSet } from '@milkdown/kit/prose/view';
|
|
3
3
|
import { $prose } from '@milkdown/kit/utils';
|
|
4
|
+
import { editorLabels } from './labels.js';
|
|
4
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>';
|
|
5
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>';
|
|
6
7
|
// The button reads the block's text when clicked, so the same widget can stay
|
|
7
8
|
// mounted while the block is edited.
|
|
8
|
-
function copyButton(onCopy) {
|
|
9
|
+
function copyButton(onCopy, label) {
|
|
9
10
|
const button = document.createElement('button');
|
|
10
11
|
button.type = 'button';
|
|
11
12
|
button.className = 'copy';
|
|
12
|
-
button.setAttribute('aria-label',
|
|
13
|
+
button.setAttribute('aria-label', label);
|
|
13
14
|
button.innerHTML = copyIcon;
|
|
14
15
|
button.addEventListener('mousedown', (event) => event.preventDefault());
|
|
15
16
|
button.addEventListener('click', () => {
|
|
@@ -25,7 +26,7 @@ function copyButton(onCopy) {
|
|
|
25
26
|
return button;
|
|
26
27
|
}
|
|
27
28
|
export function codeCopyPlugin(onCopy) {
|
|
28
|
-
return $prose(() => new Plugin({
|
|
29
|
+
return $prose((ctx) => new Plugin({
|
|
29
30
|
key: new PluginKey('codeCopy'),
|
|
30
31
|
props: {
|
|
31
32
|
decorations(state) {
|
|
@@ -33,7 +34,7 @@ export function codeCopyPlugin(onCopy) {
|
|
|
33
34
|
state.doc.descendants((node, pos) => {
|
|
34
35
|
if (node.type.name !== 'code_block')
|
|
35
36
|
return true;
|
|
36
|
-
widgets.push(Decoration.widget(pos + 1, () => copyButton(onCopy), {
|
|
37
|
+
widgets.push(Decoration.widget(pos + 1, () => copyButton(onCopy, editorLabels(ctx).copyCode), {
|
|
37
38
|
side: -1,
|
|
38
39
|
key: 'copy',
|
|
39
40
|
ignoreSelection: true,
|
|
@@ -45,7 +46,7 @@ export function codeCopyPlugin(onCopy) {
|
|
|
45
46
|
},
|
|
46
47
|
}));
|
|
47
48
|
}
|
|
48
|
-
export const placeholderPlugin = $prose(() => new Plugin({
|
|
49
|
+
export const placeholderPlugin = $prose((ctx) => new Plugin({
|
|
49
50
|
key: new PluginKey('placeholder'),
|
|
50
51
|
props: {
|
|
51
52
|
decorations(state) {
|
|
@@ -58,7 +59,7 @@ export const placeholderPlugin = $prose(() => new Plugin({
|
|
|
58
59
|
return DecorationSet.create(state.doc, [
|
|
59
60
|
Decoration.node(0, first.nodeSize, {
|
|
60
61
|
class: 'empty',
|
|
61
|
-
'data-placeholder':
|
|
62
|
+
'data-placeholder': editorLabels(ctx).placeholder,
|
|
62
63
|
}),
|
|
63
64
|
]);
|
|
64
65
|
},
|
package/dist/editor.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { type EditorLabels } from './labels.js';
|
|
1
2
|
import { type TableCommand, type TableOptions } from './tables.js';
|
|
2
|
-
import { type DocumentInput, type DocumentSnapshot, type ImageAdapter, type ClipboardInput, type ClipboardOutput, type PrintableDocument } from './types.js';
|
|
3
|
+
import { type DocumentInput, type DocumentSnapshot, type ImageAdapter, type ClipboardInput, type ClipboardOutput, type PrintableDocument, type TextRange, type ReadableTextSnapshot, type TextRect, type ViewportOptions, type ViewportSnapshot } from './types.js';
|
|
3
4
|
import { type Heading } from './outline.js';
|
|
4
5
|
export type Mark = 'bold' | 'italic' | 'strikethrough' | 'highlight' | 'code' | 'link';
|
|
5
6
|
export type Block = {
|
|
@@ -24,11 +25,55 @@ export interface CaretState {
|
|
|
24
25
|
quoted: boolean;
|
|
25
26
|
}
|
|
26
27
|
export type FormatCommand = 'heading' | 'paragraph' | 'bold' | 'italic' | 'strikethrough' | 'highlight' | 'code' | 'codeBlock' | 'quote' | 'bulletList' | 'orderedList' | 'taskList' | 'link';
|
|
27
|
-
/**
|
|
28
|
+
/** Host bindings by documented formatting, history or table shortcut name. */
|
|
28
29
|
export type Keymap = Record<string, string[]>;
|
|
30
|
+
export interface TextInputPreferences {
|
|
31
|
+
spellcheck?: boolean;
|
|
32
|
+
autocorrect?: boolean;
|
|
33
|
+
autocapitalize?: 'off' | 'none' | 'on' | 'sentences' | 'words' | 'characters';
|
|
34
|
+
}
|
|
35
|
+
export interface EditorOptions {
|
|
36
|
+
images?: ImageAdapter;
|
|
37
|
+
editable?: boolean;
|
|
38
|
+
textInput?: TextInputPreferences;
|
|
39
|
+
labels?: Partial<EditorLabels>;
|
|
40
|
+
keymap?: Keymap;
|
|
41
|
+
}
|
|
42
|
+
export interface CommandState {
|
|
43
|
+
documentId: string;
|
|
44
|
+
generation: number;
|
|
45
|
+
revision: number;
|
|
46
|
+
format: 'md' | 'txt';
|
|
47
|
+
mode: EditingMode;
|
|
48
|
+
editable: boolean;
|
|
49
|
+
composing: boolean;
|
|
50
|
+
pending: boolean;
|
|
51
|
+
caret: CaretState;
|
|
52
|
+
table?: {
|
|
53
|
+
row: number;
|
|
54
|
+
column: number;
|
|
55
|
+
rows: number;
|
|
56
|
+
columns: number;
|
|
57
|
+
};
|
|
58
|
+
commands: {
|
|
59
|
+
undo: boolean;
|
|
60
|
+
redo: boolean;
|
|
61
|
+
insertText: boolean;
|
|
62
|
+
paste: boolean;
|
|
63
|
+
replace: boolean;
|
|
64
|
+
replaceSource: boolean;
|
|
65
|
+
insertImages: boolean;
|
|
66
|
+
insertPaths: boolean;
|
|
67
|
+
insertFootnote: boolean;
|
|
68
|
+
editReferenceDefinition: boolean;
|
|
69
|
+
format: Record<FormatCommand, boolean>;
|
|
70
|
+
table: Record<TableCommand, boolean>;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
29
73
|
export interface EditorEvents {
|
|
30
74
|
changed(markdown: string, generation: number): void;
|
|
31
75
|
stateChanged(state: CaretState): void;
|
|
76
|
+
commandStateChanged?(state: CommandState): void;
|
|
32
77
|
openLink(href: string): void;
|
|
33
78
|
copy(text: string): void;
|
|
34
79
|
error?(error: Error): void;
|
|
@@ -57,18 +102,40 @@ export declare class InkKitEditor {
|
|
|
57
102
|
private pasteController;
|
|
58
103
|
private plain;
|
|
59
104
|
private root;
|
|
105
|
+
private ownsRootClass;
|
|
60
106
|
private clickHandler?;
|
|
61
107
|
private footnoteKeyHandler?;
|
|
62
108
|
private copyHandler?;
|
|
63
109
|
private originalSource;
|
|
64
110
|
private generation;
|
|
111
|
+
private reportingSuppressed;
|
|
65
112
|
private loading;
|
|
113
|
+
private readonly textIdentity;
|
|
114
|
+
private textScope?;
|
|
115
|
+
private viewportContainer?;
|
|
116
|
+
private viewportInsets;
|
|
117
|
+
private writable;
|
|
118
|
+
private inputPreferences;
|
|
119
|
+
private policyEpoch;
|
|
120
|
+
private literalKeys;
|
|
121
|
+
private configuredKeys;
|
|
122
|
+
private readOnlyKeys;
|
|
66
123
|
private changePlugin;
|
|
67
124
|
private keys;
|
|
68
125
|
private constructor();
|
|
69
126
|
private context;
|
|
70
127
|
private assertAlive;
|
|
71
128
|
private assertCurrent;
|
|
129
|
+
private assertMutation;
|
|
130
|
+
private get composing();
|
|
131
|
+
get editable(): boolean;
|
|
132
|
+
setEditable(editable: boolean): void;
|
|
133
|
+
setTextInputPreferences(preferences: TextInputPreferences): void;
|
|
134
|
+
private applyInputPolicy;
|
|
135
|
+
private publishCommandState;
|
|
136
|
+
commandState(expectedGeneration?: number): CommandState;
|
|
137
|
+
private canQuote;
|
|
138
|
+
private policyPlugin;
|
|
72
139
|
private get literalSurface();
|
|
73
140
|
get editingMode(): EditingMode;
|
|
74
141
|
private currentText;
|
|
@@ -89,11 +156,25 @@ export declare class InkKitEditor {
|
|
|
89
156
|
destroy(): Promise<void>;
|
|
90
157
|
private keymapPlugin;
|
|
91
158
|
private copySourceSelection;
|
|
92
|
-
static mount(root: HTMLElement, events: EditorEvents, options?:
|
|
93
|
-
images?: ImageAdapter;
|
|
94
|
-
}): Promise<InkKitEditor>;
|
|
159
|
+
static mount(root: HTMLElement, events: EditorEvents, options?: EditorOptions): Promise<InkKitEditor>;
|
|
95
160
|
loadDocument(input: DocumentInput): void;
|
|
96
161
|
reloadDocument(input: DocumentInput): void;
|
|
162
|
+
setViewport(options: ViewportOptions): void;
|
|
163
|
+
viewport(): ViewportSnapshot;
|
|
164
|
+
private readableScope;
|
|
165
|
+
textSnapshot(expectedGeneration?: number): ReadableTextSnapshot;
|
|
166
|
+
private validateTextRange;
|
|
167
|
+
selectTextRange(range: TextRange, options?: {
|
|
168
|
+
focus?: boolean;
|
|
169
|
+
reveal?: boolean;
|
|
170
|
+
}): void;
|
|
171
|
+
replaceTextRange(range: TextRange, text: string): boolean;
|
|
172
|
+
textRangeRects(range: TextRange): readonly TextRect[];
|
|
173
|
+
visibleTextRanges(snapshotId: string): readonly TextRange[];
|
|
174
|
+
revealTextRange(range: TextRange): void;
|
|
175
|
+
private revealRects;
|
|
176
|
+
private revealCurrentSelection;
|
|
177
|
+
private revealLiteralSelection;
|
|
97
178
|
private load;
|
|
98
179
|
find(text: string, expectedGeneration?: number): void;
|
|
99
180
|
replace(search: string, replacement: string, expectedGeneration?: number): boolean;
|