@pixerate/editor 0.20.0 → 0.22.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/README.md +24 -13
- package/dist/agent/index.cjs +8 -8
- package/dist/agent/index.d.cts +2 -2
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.js +2 -2
- package/dist/canvas/index.cjs +1269 -13
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +432 -6
- package/dist/canvas/index.d.ts +432 -6
- package/dist/canvas/index.js +1264 -8
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-U6NDQFOK.cjs → chunk-6M3BCTBD.cjs} +427 -138
- package/dist/chunk-6M3BCTBD.cjs.map +1 -0
- package/dist/{chunk-TVRC4KVT.cjs → chunk-AA4ZEVCC.cjs} +845 -90
- package/dist/chunk-AA4ZEVCC.cjs.map +1 -0
- package/dist/{chunk-LA7PEGU3.cjs → chunk-CL37JGFW.cjs} +4 -4
- package/dist/{chunk-LA7PEGU3.cjs.map → chunk-CL37JGFW.cjs.map} +1 -1
- package/dist/{chunk-A7DKIA72.js → chunk-DENSCKFC.js} +642 -69
- package/dist/chunk-DENSCKFC.js.map +1 -0
- package/dist/{chunk-4QPLEUL2.cjs → chunk-GVSMRPHB.cjs} +1046 -54
- package/dist/chunk-GVSMRPHB.cjs.map +1 -0
- package/dist/{chunk-KYRZDWM4.js → chunk-JJDLPEWL.js} +2 -2
- package/dist/{chunk-3TYMNULT.js → chunk-MJZBNWG7.js} +807 -52
- package/dist/chunk-MJZBNWG7.js.map +1 -0
- package/dist/{chunk-CYFJCKC4.js → chunk-QGHGJ56O.js} +997 -5
- package/dist/chunk-QGHGJ56O.js.map +1 -0
- package/dist/{chunk-GVW4P7BG.js → chunk-RU52I7QO.js} +305 -16
- package/dist/chunk-RU52I7QO.js.map +1 -0
- package/dist/{chunk-JYRIOFEN.cjs → chunk-SAZRENEZ.cjs} +647 -74
- package/dist/chunk-SAZRENEZ.cjs.map +1 -0
- package/dist/{controller-OUdxPY-X.d.ts → controller-B7GIybc4.d.cts} +139 -7
- package/dist/{controller-OUdxPY-X.d.cts → controller-B7GIybc4.d.ts} +139 -7
- package/dist/extensions/index.cjs +14 -4
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +3 -3
- package/dist/extensions/index.d.ts +3 -3
- package/dist/extensions/index.js +13 -3
- package/dist/{index-k3mFbPx_.d.cts → index-CCr_z9kF.d.cts} +3 -3
- package/dist/{index-Ng1pG7JE.d.ts → index-Ck6ajwXh.d.ts} +3 -3
- package/dist/index.cjs +250 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +294 -8
- package/dist/index.d.ts +294 -8
- package/dist/index.js +241 -7
- package/dist/index.js.map +1 -1
- package/dist/{registry-iAHbqkYt.d.cts → registry-GJI4gToU.d.cts} +15 -4
- package/dist/{registry-iAHbqkYt.d.ts → registry-GJI4gToU.d.ts} +15 -4
- package/dist/serializers/index.cjs +3 -3
- package/dist/serializers/index.d.cts +1 -1
- package/dist/serializers/index.d.ts +1 -1
- package/dist/serializers/index.js +2 -2
- package/dist/spreadsheet/index.cjs +7 -3
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +33 -4
- package/dist/spreadsheet/index.d.ts +33 -4
- package/dist/spreadsheet/index.js +6 -2
- package/dist/{track-changes-G8JcWB8b.d.cts → track-changes-BSF58RK0.d.cts} +92 -9
- package/dist/{track-changes-G8JcWB8b.d.ts → track-changes-BSF58RK0.d.ts} +92 -9
- package/dist/{types-DMe0vFB1.d.cts → types-CJ4U-HHI.d.cts} +1 -1
- package/dist/{types-DMe0vFB1.d.ts → types-CJ4U-HHI.d.ts} +1 -1
- package/package.json +11 -4
- package/dist/chunk-3TYMNULT.js.map +0 -1
- package/dist/chunk-4QPLEUL2.cjs.map +0 -1
- package/dist/chunk-A7DKIA72.js.map +0 -1
- package/dist/chunk-CYFJCKC4.js.map +0 -1
- package/dist/chunk-GVW4P7BG.js.map +0 -1
- package/dist/chunk-JYRIOFEN.cjs.map +0 -1
- package/dist/chunk-TVRC4KVT.cjs.map +0 -1
- package/dist/chunk-U6NDQFOK.cjs.map +0 -1
- /package/dist/{chunk-KYRZDWM4.js.map → chunk-JJDLPEWL.js.map} +0 -0
package/README.md
CHANGED
|
@@ -6,6 +6,8 @@ Framework bindings: [`@pixerate/editor-react`](https://www.npmjs.com/package/@pi
|
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @pixerate/editor
|
|
9
|
+
# only if you use @pixerate/editor/canvas (or the agent canvas planner):
|
|
10
|
+
npm install @dagrejs/dagre
|
|
9
11
|
```
|
|
10
12
|
|
|
11
13
|
## Prompt grammar
|
|
@@ -106,18 +108,20 @@ editor.commands.resolveComment(id); // also deleteComment, setActiveComment, foc
|
|
|
106
108
|
store.subscribe((snapshot) => save(store.toJSON()));
|
|
107
109
|
|
|
108
110
|
editor.commands.toggleTrackChanges();
|
|
109
|
-
getTrackedChanges(editor); // [{ id, type: "insertion" | "deletion", author, from, to, text, … }]
|
|
111
|
+
getTrackedChanges(editor); // [{ id, type: "insertion" | "deletion" | "format" | "block", author, from, to, text, description, … }]
|
|
110
112
|
editor.commands.acceptChange(id); // rejectChange, acceptAllChanges, rejectAllChanges: one undo step each
|
|
111
113
|
```
|
|
112
114
|
|
|
113
115
|
- **Comments** are `comment` marks holding a thread id; thread content lives in the headless `CommentStore` (`subscribe` / `getSnapshot`, cached snapshots, `toJSON` / `load`). Threads whose text is deleted are flagged `orphaned` and re-attach on undo.
|
|
114
|
-
- **Track changes** marks typed and pasted text with an `insertion` mark and keeps deleted text with a `deletion` mark (struck through). Deleting your own insertion really deletes it. IME composition is tracked once it ends.
|
|
115
|
-
- **
|
|
116
|
-
-
|
|
116
|
+
- **Track changes** marks typed and pasted text with an `insertion` mark and keeps deleted text with a `deletion` mark (struck through). Deleting your own insertion really deletes it. IME composition is tracked once it ends. Insertions and deletions inside code blocks are tracked too (`trackCodeBlocks: false` turns that off). Set the `TRACK_CHANGES_SKIP_META` transaction meta to apply a change untracked (e.g. `setContent`).
|
|
117
|
+
- **Tracked formatting** (`trackFormatting`, on by default): adding or removing marks (bold, italic, links, highlight, font size, …) on existing text records a `formatChange` mark holding the author, id and the `before` / `after` formatting, shown as a dotted underline. Descriptions read `Formatted: Bold`, `Removed formatting: Italic` or `Changed formatting: Font size`. Accept keeps the new formatting; reject restores the old. Adjacent or repeated formatting by the same author merges into one change, changing it back drops the record, and formatting a tracked insertion stays part of the insertion. Review marks, comments and bookmarks are never formatting (add more with `ignoredMarks`).
|
|
118
|
+
- **Tracked block changes** (`trackBlocks`, on by default): changing a textblock's type or attributes (paragraph ↔ heading, heading level, code block, alignment) or its wrappers (bulleted/numbered/task lists, indenting, outdenting, quotes) stores the previous state in a `blockChange` node attribute on `blockTypes` (paragraph, heading, code block), shown with a margin bar. Descriptions read `Changed Paragraph to Heading 2`, `Wrapped in Bulleted list`, `Changed alignment to Center`. Reject restores the type, attributes and nesting. Paragraph splits and joins are not tracked (a split-off block does not inherit the record). `describeFormatChange` and `describeBlockChange` build the descriptions.
|
|
119
|
+
- **Serializers** render tracked content as if all changes were accepted: `getEditorText`, `htmlToPlainText` and `getEditorMarkdown` drop deleted text and use the new formatting and block types by default. Pass `{ trackedChanges: "original" }` (as if rejected) or `"all"` (both). `resolveTrackedChanges(doc, view)` returns a resolved document. TipTap's own `editor.getText()` still includes deleted text.
|
|
120
|
+
- Both extensions are also available as `createRichTextPreset({ comments: true, trackChanges: true })`. Mark styles use Tailwind classes; override them via `commentClass` / `activeClass` and `insertionHTMLAttributes` / `deletionHTMLAttributes` / `formatChangeHTMLAttributes` / `blockChangeClass`.
|
|
117
121
|
|
|
118
122
|
## File import and rich clipboard
|
|
119
123
|
|
|
120
|
-
An import adapter registry maps file types (MIME types and extensions) to converters. Built-in `document` adapters cover markdown (`.md`, `.markdown`, `.mdown`, `.mkdn`, `.mkd`, `.Rmd`, `.md.txt`), HTML (sanitized with the same allowlist as markdown), plain text (`.txt`)
|
|
124
|
+
An import adapter registry maps file types (MIME types and extensions) to converters. Built-in `document` adapters cover markdown (`.md`, `.markdown`, `.mdown`, `.mkdn`, `.mkd`, `.Rmd`, `.md.txt`), HTML (sanitized with the same allowlist as markdown), plain text (`.txt`), RTF (best-effort text extraction) and DOCX (`.docx`, `.docm`, `.dotx`). The longest matching extension wins, then exact MIME types, then `priority`, then the most recent registration.
|
|
121
125
|
|
|
122
126
|
```ts
|
|
123
127
|
import { importFile, registerImportAdapter, getImportAccept } from "@pixerate/editor";
|
|
@@ -125,20 +129,27 @@ import { importFile, registerImportAdapter, getImportAccept } from "@pixerate/ed
|
|
|
125
129
|
const { adapterId, result } = await importFile(file); // result: { html, text }
|
|
126
130
|
input.accept = getImportAccept("document");
|
|
127
131
|
|
|
128
|
-
//
|
|
132
|
+
// Other formats are pluggable:
|
|
129
133
|
registerImportAdapter({
|
|
130
|
-
id: "
|
|
131
|
-
label: "
|
|
132
|
-
mimeTypes: ["application/vnd.
|
|
133
|
-
extensions: [".
|
|
134
|
+
id: "odt",
|
|
135
|
+
label: "OpenDocument text",
|
|
136
|
+
mimeTypes: ["application/vnd.oasis.opendocument.text"],
|
|
137
|
+
extensions: [".odt"],
|
|
134
138
|
target: "document",
|
|
135
139
|
async import(_file, ctx) {
|
|
136
|
-
const html = await
|
|
140
|
+
const html = await myOdtToHtml(await ctx.readArrayBuffer());
|
|
137
141
|
return { html, text: htmlToPlainText(html) };
|
|
138
142
|
},
|
|
139
143
|
});
|
|
140
144
|
```
|
|
141
145
|
|
|
146
|
+
### DOCX, PDF and zipped exports (no extra dependencies)
|
|
147
|
+
|
|
148
|
+
- **DOCX** (built in): `docxImportAdapter` reads `word/document.xml` (located via `_rels/.rels`), styles, numbering, relationships and footnotes / endnotes with the platform `DOMParser`, and maps headings (`Heading1`–`6`, `Title`, outline levels), bold / italic / underline / strike / super- and subscript, hyperlinks (including `HYPERLINK` fields), nested bulleted / numbered lists, tables (`colspan` / `rowspan`, header rows), line breaks, tabs and embedded PNG / JPEG / GIF / WebP images (as data URLs; dropped by the editor when the image extension is off). Output goes through `sanitizeImportedHtml`. **Tracked changes are imported as if accepted** (`w:ins` kept, `w:del` dropped); `createDocxImportAdapter({ trackedChanges: "original" })` imports them as if rejected. Text boxes, shapes, charts, equations, comments and layout are not imported. Without a global `DOMParser` (plain Node) it throws `ImportError("unsupported_environment")`; pass one with `createDocxImportAdapter({ DOMParser })`. Other options: `images`, `maxImageSize` (10 MiB), `zip` limits.
|
|
149
|
+
- **PDF** (opt-in, bring your own pdf.js): `registerImportAdapter(createPdfImportAdapter(pdfjs))` with any object shaped like `pdfjs-dist` (`getDocument({ data }).promise`, `page.getTextContent()`). Text items are grouped into lines by baseline and into paragraphs by larger-than-usual vertical gaps or blank lines; options `paragraphGap`, `maxPages`, `documentParams`. Text only. `pdfTextItemsToParagraphs` is exported for custom adapters.
|
|
150
|
+
- **Zipped exports** (opt-in): `registerImportAdapter(zipImportAdapter)` imports a `.zip` of markdown / HTML / text / DOCX files (Notion, Confluence, Obsidian exports) with the registry's other adapters — index / README files first, then natural path order — with a heading per file (Notion ids stripped from titles). The result adds `files` and `skipped` (unsupported types, nested archives, failures). Not registered by default because `.zip` is a generic container: claiming every dropped archive would steal drops from other handlers. `createZipImportAdapter({ headings, headingLevel, maxFiles, registry, zip })` customizes it.
|
|
151
|
+
- **ZIP reader**: `readZip(bytes, { maxEntries, maxTotalSize, unsafePaths })` parses the central directory (ZIP64 included) and lazily extracts stored / deflate entries via `DecompressionStream("deflate-raw")` (browsers, Node 18+), verifying CRC-32. It rejects encrypted entries, `..` / absolute names and archives over the entry or uncompressed-size caps (default 10 000 entries / 256 MiB, enforced on inflated bytes) with typed `ZipError`s. DOCX reads use 100 MiB / 5 000 entries.
|
|
152
|
+
|
|
142
153
|
`FileImport` (or `createRichTextPreset({ fileImport: true })`) inserts dropped or pasted files at the drop position, and `FileImportController` / `pickImportFiles` back file-picker buttons. `RichClipboard` (or `richClipboard: true`) also writes copied content as `application/x.pixerate.document+json` (ProseMirror slice JSON plus a schema signature) and prefers it on paste when the schemas match, falling back to HTML / plain text. Both are opt-in, and `EditorController` keeps them on plain text in `plainTextMode`.
|
|
143
154
|
|
|
144
155
|
## Agent tool registry
|
|
@@ -187,10 +198,10 @@ Each module is also available as a subpath import:
|
|
|
187
198
|
| `@pixerate/editor/history` | `HistoryManager`: a command-pattern undo/redo stack |
|
|
188
199
|
| `@pixerate/editor/spreadsheet` | `SpreadsheetController`, formula parser/evaluator and dependency graph, formula function registry (`registerFormulaFunction`, `listFormulaFunctions`, `searchFormulaFunctions`, `getFormulaSignature`) and autocomplete helpers (`getFormulaHints`, `applyFormulaSuggestion`) |
|
|
189
200
|
| `@pixerate/editor/image-editor` | `ImageEditorController` and Canvas 2D renderer: crop, adjustments, annotations, depth masks and AI hooks. Needs a DOM/canvas environment. |
|
|
190
|
-
| `@pixerate/editor/canvas` | Node-graph layout (dagre), placement, trajectories, displacement, clipboard and streaming layout helpers |
|
|
201
|
+
| `@pixerate/editor/canvas` | Node-graph layout (needs the optional `@dagrejs/dagre` peer), placement, trajectories, displacement, clipboard and streaming layout helpers |
|
|
191
202
|
| `@pixerate/editor/agent` | MCP tool schemas, a planner for agent-driven canvas edits, and the dynamic `ToolRegistry` with editor/spreadsheet tool providers |
|
|
192
203
|
|
|
193
|
-
The root entry (`@pixerate/editor`) re-exports everything, including TipTap.
|
|
204
|
+
The root entry (`@pixerate/editor`) re-exports everything except canvas, agent and image editor, including TipTap. Import from the narrowest subpath you need: `grammar`, `history`, `spreadsheet` and `image-editor` have no third-party imports, so a spreadsheet-only app bundles no TipTap, markdown or dagre code. The package is marked `sideEffects: false`, so unused root exports are also tree-shaken.
|
|
194
205
|
|
|
195
206
|
## License
|
|
196
207
|
|
package/dist/agent/index.cjs
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var _chunkAA4ZEVCCcjs = require('../chunk-AA4ZEVCC.cjs');
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _chunkSAZRENEZcjs = require('../chunk-SAZRENEZ.cjs');
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
@@ -762,7 +762,7 @@ function createToolRegistry(options) {
|
|
|
762
762
|
var toEditor = (target) => "commands" in target ? target : target.editor;
|
|
763
763
|
function replaceWithText(editor, from, to, text) {
|
|
764
764
|
const { state, view } = editor;
|
|
765
|
-
const tr = /[\r\n]/.test(text) ? state.tr.replace(from, to,
|
|
765
|
+
const tr = /[\r\n]/.test(text) ? state.tr.replace(from, to, _chunkAA4ZEVCCcjs.plainTextToSlice.call(void 0, text, state.schema)) : text ? state.tr.insertText(text, from, to) : state.tr.delete(from, to);
|
|
766
766
|
view.dispatch(tr.scrollIntoView());
|
|
767
767
|
}
|
|
768
768
|
function selectionInfo(editor) {
|
|
@@ -788,7 +788,7 @@ function createRichTextToolProvider(target, options) {
|
|
|
788
788
|
annotations: { readOnlyHint: true },
|
|
789
789
|
handler: ({ format = "text" }) => {
|
|
790
790
|
const ed = editor();
|
|
791
|
-
const content = format === "html" ? ed.getHTML() : format === "markdown" ?
|
|
791
|
+
const content = format === "html" ? ed.getHTML() : format === "markdown" ? _chunkAA4ZEVCCcjs.getEditorMarkdown.call(void 0, ed) : _chunkAA4ZEVCCcjs.getEditorText.call(void 0, ed);
|
|
792
792
|
return { format, content, selection: selectionInfo(ed), size: ed.state.doc.content.size };
|
|
793
793
|
}
|
|
794
794
|
};
|
|
@@ -855,7 +855,7 @@ var CELL_REF_REGEX = /^\$?([A-Za-z]{1,3})\$?(\d{1,7})$/;
|
|
|
855
855
|
function parseCell(ref) {
|
|
856
856
|
const match = CELL_REF_REGEX.exec(ref.trim());
|
|
857
857
|
if (!match) throw new Error(`Invalid cell reference "${ref}". Use A1 notation, e.g. "B3".`);
|
|
858
|
-
return { col:
|
|
858
|
+
return { col: _chunkSAZRENEZcjs.colNameToIndex.call(void 0, match[1].toUpperCase()), row: parseInt(match[2], 10) - 1 };
|
|
859
859
|
}
|
|
860
860
|
function createSpreadsheetToolProvider(controller, options) {
|
|
861
861
|
const lookup = (row, col) => {
|
|
@@ -896,14 +896,14 @@ function createSpreadsheetToolProvider(controller, options) {
|
|
|
896
896
|
const cell = controller.getCell(found.rowDef.id, found.colDef.id);
|
|
897
897
|
valueRow.push(_nullishCoalesce(cell.error, () => ( cell.value)));
|
|
898
898
|
rawRow.push(cell.raw);
|
|
899
|
-
const error = _nullishCoalesce(cell.error, () => ( (
|
|
900
|
-
if (error) errors.push({ cell: `${
|
|
899
|
+
const error = _nullishCoalesce(cell.error, () => ( (_chunkSAZRENEZcjs.isFormulaError.call(void 0, cell.value) ? cell.value : void 0)));
|
|
900
|
+
if (error) errors.push({ cell: `${_chunkSAZRENEZcjs.indexToColName.call(void 0, c)}${r + 1}`, error });
|
|
901
901
|
}
|
|
902
902
|
values.push(valueRow);
|
|
903
903
|
raw.push(rawRow);
|
|
904
904
|
}
|
|
905
905
|
return {
|
|
906
|
-
range: values.length && values[0].length ? `${
|
|
906
|
+
range: values.length && values[0].length ? `${_chunkSAZRENEZcjs.indexToColName.call(void 0, c0)}${r0 + 1}:${_chunkSAZRENEZcjs.indexToColName.call(void 0, c1)}${r1 + 1}` : null,
|
|
907
907
|
values,
|
|
908
908
|
raw,
|
|
909
909
|
errors,
|
package/dist/agent/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as CanvasNode, a as CanvasEdge, X as XYPosition, S as Side } from '../types-
|
|
1
|
+
import { C as CanvasNode, a as CanvasEdge, X as XYPosition, S as Side } from '../types-CJ4U-HHI.cjs';
|
|
2
2
|
import { Editor } from '@tiptap/core';
|
|
3
|
-
import {
|
|
3
|
+
import { S as SpreadsheetController } from '../controller-B7GIybc4.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Agent presence state for visual multiplayer/agent choreography.
|
package/dist/agent/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as CanvasNode, a as CanvasEdge, X as XYPosition, S as Side } from '../types-
|
|
1
|
+
import { C as CanvasNode, a as CanvasEdge, X as XYPosition, S as Side } from '../types-CJ4U-HHI.js';
|
|
2
2
|
import { Editor } from '@tiptap/core';
|
|
3
|
-
import {
|
|
3
|
+
import { S as SpreadsheetController } from '../controller-B7GIybc4.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Agent presence state for visual multiplayer/agent choreography.
|
package/dist/agent/index.js
CHANGED
|
@@ -2,12 +2,12 @@ import {
|
|
|
2
2
|
getEditorMarkdown,
|
|
3
3
|
getEditorText,
|
|
4
4
|
plainTextToSlice
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-MJZBNWG7.js";
|
|
6
6
|
import {
|
|
7
7
|
colNameToIndex,
|
|
8
8
|
indexToColName,
|
|
9
9
|
isFormulaError
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-DENSCKFC.js";
|
|
11
11
|
import {
|
|
12
12
|
ensureLayout,
|
|
13
13
|
getLayoutedNodes,
|