@aicayzer/inkkit 0.0.7 → 0.0.8

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 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
- Milkdown and other runtime dependencies retain their own licenses. They are
6
- installed as dependencies rather than embedded in this package.
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 TypeScript Markdown editor for offline web views and the web. It provides readable clipboard output, editable tables, optional host-managed images, and preservation of original Markdown and unsupported syntax.
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. Unsupported syntax remains editable literal Markdown.
6
+
7
+ **Version status:** 0.0.7 is published. This branch documents the **unpublished 0.0.8 candidate**, adding read-only and text-input policies, command availability, scoped appearance, labels and shortcuts. Installing from npm currently gets the published release; the new controls require the candidate.
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 editor = await InkKitEditor.mount(document.getElementById('editor')!, {
17
+ const root = document.getElementById('editor')!
18
+ const editor = await InkKitEditor.mount(root, {
14
19
  changed(text, generation) {
15
- /* Notify the host. */
20
+ // Notify the host; capture a fresh snapshot when saving.
16
21
  },
17
22
  stateChanged(state) {
18
- /* Update formatting controls. */
23
+ // Update the host's formatting controls.
19
24
  },
20
25
  openLink(href) {
21
- /* Open through the host. */
26
+ // Open through the host.
22
27
  },
23
28
  copy(text) {
24
- /* Write code-block text to the clipboard. */
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
- Markdown includes CommonMark, task lists, strikethrough, autolinks, GFM tables, editable footnotes and reference-style links, bounded callouts, highlights, author comments and offline Mermaid diagrams. Unsupported constructs remain literal Markdown. TXT mode treats all text literally. Images require a host adapter. RTF files remain outside the package scope.
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
- Table controls include complete row/column movement and explicit stable text or numeric sorting. Ordinary spreadsheet paste preserves cell boundaries, replaces selected cells and grows supported tables. Hosts call these operations through the public facade; each is undoable.
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
- `await editor.printableSnapshot(1)` returns a complete printable HTML document, print styles and portable image bytes. It excludes author comments, includes folded content and reports unavailable assets or a changed document. Client apps own Print/PDF commands, dialogs and file generation.
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). Planned search, viewport and media extensions are tracked there; they are not capabilities of this candidate.
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 ? 'Expand' : 'Collapse'} ${title.textContent}`);
270
- button.textContent = folded ? 'Expand' : 'Collapse';
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;
@@ -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', 'Copy');
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': 'Start typing…',
62
+ 'data-placeholder': editorLabels(ctx).placeholder,
62
63
  }),
63
64
  ]);
64
65
  },
package/dist/editor.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type EditorLabels } from './labels.js';
1
2
  import { type TableCommand, type TableOptions } from './tables.js';
2
3
  import { type DocumentInput, type DocumentSnapshot, type ImageAdapter, type ClipboardInput, type ClipboardOutput, type PrintableDocument } from './types.js';
3
4
  import { type Heading } from './outline.js';
@@ -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
- /** The bindings the app sets, by shortcut name; each runs a format command. */
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,36 @@ 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 writable;
114
+ private inputPreferences;
115
+ private policyEpoch;
116
+ private literalKeys;
117
+ private configuredKeys;
118
+ private readOnlyKeys;
66
119
  private changePlugin;
67
120
  private keys;
68
121
  private constructor();
69
122
  private context;
70
123
  private assertAlive;
71
124
  private assertCurrent;
125
+ private assertMutation;
126
+ private get composing();
127
+ get editable(): boolean;
128
+ setEditable(editable: boolean): void;
129
+ setTextInputPreferences(preferences: TextInputPreferences): void;
130
+ private applyInputPolicy;
131
+ private publishCommandState;
132
+ commandState(expectedGeneration?: number): CommandState;
133
+ private canQuote;
134
+ private policyPlugin;
72
135
  private get literalSurface();
73
136
  get editingMode(): EditingMode;
74
137
  private currentText;
@@ -89,9 +152,7 @@ export declare class InkKitEditor {
89
152
  destroy(): Promise<void>;
90
153
  private keymapPlugin;
91
154
  private copySourceSelection;
92
- static mount(root: HTMLElement, events: EditorEvents, options?: {
93
- images?: ImageAdapter;
94
- }): Promise<InkKitEditor>;
155
+ static mount(root: HTMLElement, events: EditorEvents, options?: EditorOptions): Promise<InkKitEditor>;
95
156
  loadDocument(input: DocumentInput): void;
96
157
  reloadDocument(input: DocumentInput): void;
97
158
  private load;