kindy-editor 1.0.1 → 2.0.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.
@@ -0,0 +1,267 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: Kindy Document Library API
4
+ version: 2.0.0
5
+ description: Host-side contract consumed by kindy-editor. Authentication is intentionally application-defined.
6
+ servers:
7
+ - url: https://document-api.example.com
8
+ tags:
9
+ - name: Documents
10
+ - name: Versions
11
+ - name: Artifacts
12
+ paths:
13
+ /documents:
14
+ get:
15
+ tags: [Documents]
16
+ operationId: listDocuments
17
+ parameters:
18
+ - $ref: '#/components/parameters/Search'
19
+ - $ref: '#/components/parameters/FolderId'
20
+ - $ref: '#/components/parameters/Page'
21
+ - $ref: '#/components/parameters/PageSize'
22
+ responses:
23
+ '200': { description: Document page, content: { application/json: { schema: { $ref: '#/components/schemas/DocumentPage' } } } }
24
+ post:
25
+ tags: [Documents]
26
+ operationId: createDocument
27
+ requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/CreateDocumentInput' } } } }
28
+ responses:
29
+ '201': { description: Created, content: { application/json: { schema: { $ref: '#/components/schemas/DocumentRecord' } } } }
30
+ /documents/import:
31
+ post:
32
+ tags: [Documents]
33
+ operationId: importDocument
34
+ requestBody:
35
+ required: true
36
+ content:
37
+ multipart/form-data:
38
+ schema:
39
+ type: object
40
+ required: [file, metadata, state]
41
+ properties:
42
+ file: { type: string, contentMediaType: application/vnd.openxmlformats-officedocument.wordprocessingml.document, contentEncoding: binary }
43
+ metadata: { type: string, description: JSON encoded CreateDocumentInput }
44
+ state: { type: string, description: JSON encoded KindyDocumentState }
45
+ compatibilityReport: { type: string, description: JSON encoded CompatibilityReport }
46
+ responses:
47
+ '201': { description: Imported, content: { application/json: { schema: { $ref: '#/components/schemas/DocumentRecord' } } } }
48
+ '422': { $ref: '#/components/responses/Error' }
49
+ /documents/{documentId}:
50
+ parameters: [{ $ref: '#/components/parameters/DocumentId' }]
51
+ get:
52
+ tags: [Documents]
53
+ operationId: getDocument
54
+ responses:
55
+ '200': { description: Document, content: { application/json: { schema: { $ref: '#/components/schemas/DocumentRecord' } } } }
56
+ '404': { $ref: '#/components/responses/Error' }
57
+ patch:
58
+ tags: [Documents]
59
+ operationId: updateDocument
60
+ requestBody: { required: true, content: { application/json: { schema: { type: object, additionalProperties: true } } } }
61
+ responses:
62
+ '200': { description: Updated document, content: { application/json: { schema: { $ref: '#/components/schemas/DocumentRecord' } } } }
63
+ /documents/{documentId}/state:
64
+ parameters: [{ $ref: '#/components/parameters/DocumentId' }]
65
+ get:
66
+ tags: [Documents]
67
+ operationId: loadDocumentState
68
+ parameters: [{ name: versionId, in: query, schema: { type: string } }]
69
+ responses:
70
+ '200': { description: Snapshot, content: { application/json: { schema: { $ref: '#/components/schemas/DocumentSnapshot' } } } }
71
+ '404': { $ref: '#/components/responses/Error' }
72
+ put:
73
+ tags: [Documents]
74
+ operationId: saveDocumentState
75
+ requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/SaveStateInput' } } } }
76
+ responses:
77
+ '200': { description: Save result, content: { application/json: { schema: { $ref: '#/components/schemas/SaveResult' } } } }
78
+ '409': { description: Base revision no longer current, content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } }
79
+ /documents/{documentId}/versions:
80
+ parameters: [{ $ref: '#/components/parameters/DocumentId' }]
81
+ get:
82
+ tags: [Versions]
83
+ operationId: listDocumentVersions
84
+ parameters: [{ $ref: '#/components/parameters/Page' }, { $ref: '#/components/parameters/PageSize' }]
85
+ responses:
86
+ '200': { description: Version page, content: { application/json: { schema: { $ref: '#/components/schemas/VersionPage' } } } }
87
+ /documents/{documentId}/versions/{versionId}/restore:
88
+ parameters: [{ $ref: '#/components/parameters/DocumentId' }, { $ref: '#/components/parameters/VersionId' }]
89
+ post:
90
+ tags: [Versions]
91
+ operationId: restoreDocumentVersion
92
+ responses:
93
+ '200': { description: Restored snapshot, content: { application/json: { schema: { $ref: '#/components/schemas/DocumentSnapshot' } } } }
94
+ '404': { $ref: '#/components/responses/Error' }
95
+ /documents/{documentId}/artifacts:
96
+ parameters: [{ $ref: '#/components/parameters/DocumentId' }]
97
+ post:
98
+ tags: [Artifacts]
99
+ operationId: storeDocumentArtifact
100
+ requestBody:
101
+ required: true
102
+ content:
103
+ multipart/form-data:
104
+ schema:
105
+ type: object
106
+ required: [file, format]
107
+ properties:
108
+ file: { type: string, contentEncoding: binary }
109
+ fileName: { type: string, description: Explicit filename for transports that do not preserve multipart Content-Disposition }
110
+ format: { $ref: '#/components/schemas/ArtifactFormat' }
111
+ versionId: { type: string }
112
+ compatibilityReport: { type: string }
113
+ responses:
114
+ '201': { description: Artifact, content: { application/json: { schema: { $ref: '#/components/schemas/DocumentArtifact' } } } }
115
+ /documents/{documentId}/artifacts/{artifactId}:
116
+ parameters: [{ $ref: '#/components/parameters/DocumentId' }, { name: artifactId, in: path, required: true, schema: { type: string } }]
117
+ get:
118
+ tags: [Artifacts]
119
+ operationId: getDocumentArtifact
120
+ responses:
121
+ '200': { description: Artifact metadata with a URL or an application-defined retrieval representation, content: { application/json: { schema: { $ref: '#/components/schemas/DocumentArtifact' } } } }
122
+ '404': { $ref: '#/components/responses/Error' }
123
+ /folders:
124
+ get:
125
+ operationId: listFolders
126
+ parameters: [{ $ref: '#/components/parameters/Search' }]
127
+ responses:
128
+ '200': { description: Folders, content: { application/json: { schema: { type: array, items: { $ref: '#/components/schemas/Folder' } } } } }
129
+ /templates:
130
+ get:
131
+ operationId: listTemplates
132
+ parameters: [{ $ref: '#/components/parameters/Search' }, { $ref: '#/components/parameters/Page' }, { $ref: '#/components/parameters/PageSize' }]
133
+ responses:
134
+ '200': { description: Template page, content: { application/json: { schema: { $ref: '#/components/schemas/DocumentPage' } } } }
135
+ components:
136
+ parameters:
137
+ DocumentId: { name: documentId, in: path, required: true, schema: { type: string } }
138
+ VersionId: { name: versionId, in: path, required: true, schema: { type: string } }
139
+ Search: { name: search, in: query, schema: { type: string } }
140
+ FolderId: { name: folderId, in: query, schema: { type: string } }
141
+ Page: { name: page, in: query, schema: { type: integer, minimum: 1, default: 1 } }
142
+ PageSize: { name: pageSize, in: query, schema: { type: integer, minimum: 1, maximum: 200, default: 20 } }
143
+ responses:
144
+ Error: { description: Error, content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } } }
145
+ schemas:
146
+ JsonContent: { type: object, additionalProperties: true }
147
+ KindyPageState:
148
+ type: object
149
+ required: [size, orientation, margin]
150
+ properties:
151
+ size: { type: object, required: [width, height], properties: { width: { type: number }, height: { type: number } } }
152
+ orientation: { enum: [portrait, landscape] }
153
+ margin: { type: object, required: [top, right, bottom, left], properties: { top: { type: number }, right: { type: number }, bottom: { type: number }, left: { type: number } } }
154
+ background: { type: string }
155
+ watermark: { type: object, additionalProperties: true }
156
+ sections: { type: array, items: { type: object, additionalProperties: true } }
157
+ additionalProperties: true
158
+ KindyDocumentState:
159
+ type: object
160
+ required: [schemaVersion, content, page, assets]
161
+ properties:
162
+ schemaVersion: { const: '2.0' }
163
+ content: { $ref: '#/components/schemas/JsonContent' }
164
+ page: { $ref: '#/components/schemas/KindyPageState' }
165
+ assets: { type: array, items: { type: object, required: [id, kind], properties: { id: { type: string }, kind: { type: string }, url: { type: string }, mimeType: { type: string } }, additionalProperties: true } }
166
+ DocumentRecord:
167
+ type: object
168
+ required: [id, title, fileName, updatedAt]
169
+ properties:
170
+ id: { type: string }
171
+ title: { type: string }
172
+ fileName: { type: string }
173
+ folderId: { type: [string, 'null'] }
174
+ tags: { type: array, items: { type: string } }
175
+ currentVersionId: { type: string }
176
+ currentRevisionId: { type: string }
177
+ isTemplate: { type: boolean }
178
+ createdAt: { type: string, format: date-time }
179
+ updatedAt: { type: string, format: date-time }
180
+ metadata: { type: object, additionalProperties: true }
181
+ capabilities: { type: object, additionalProperties: { type: boolean } }
182
+ originalSource:
183
+ $ref: '#/components/schemas/OriginalDocxSource'
184
+ OriginalDocxSource:
185
+ type: object
186
+ required: [artifactId, revisionId, format, fileName]
187
+ properties:
188
+ artifactId: { type: string }
189
+ revisionId: { type: string }
190
+ format: { const: original-docx }
191
+ fileName: { type: string }
192
+ compatibilityReport: { type: object, additionalProperties: true }
193
+ CreateDocumentInput:
194
+ type: object
195
+ required: [title]
196
+ properties:
197
+ title: { type: string }
198
+ fileName: { type: string }
199
+ folderId: { type: [string, 'null'] }
200
+ tags: { type: array, items: { type: string } }
201
+ templateId: { type: string }
202
+ state: { $ref: '#/components/schemas/KindyDocumentState' }
203
+ metadata: { type: object, additionalProperties: true }
204
+ DocumentVersion:
205
+ type: object
206
+ required: [id, documentId, number, revisionId, reason, createdAt]
207
+ properties:
208
+ id: { type: string }
209
+ documentId: { type: string }
210
+ number: { type: integer }
211
+ revisionId: { type: string }
212
+ reason: { enum: [create, import, autosave, manual, restore, template] }
213
+ createdAt: { type: string, format: date-time }
214
+ label: { type: string }
215
+ DocumentSnapshot:
216
+ type: object
217
+ required: [document, state, revisionId]
218
+ properties:
219
+ document: { $ref: '#/components/schemas/DocumentRecord' }
220
+ state: { $ref: '#/components/schemas/KindyDocumentState' }
221
+ revisionId: { type: string }
222
+ version: { $ref: '#/components/schemas/DocumentVersion' }
223
+ SaveStateInput:
224
+ type: object
225
+ required: [state, baseRevisionId, reason, clientMutationId]
226
+ properties:
227
+ state: { $ref: '#/components/schemas/KindyDocumentState' }
228
+ baseRevisionId: { type: string }
229
+ reason: { enum: [autosave, manual] }
230
+ clientMutationId: { type: string }
231
+ SaveResult:
232
+ type: object
233
+ required: [revisionId, savedAt]
234
+ properties:
235
+ revisionId: { type: string }
236
+ savedAt: { type: string, format: date-time }
237
+ version: { $ref: '#/components/schemas/DocumentVersion' }
238
+ ArtifactFormat: { enum: [docx, pdf, original-docx] }
239
+ DocumentArtifact:
240
+ type: object
241
+ required: [id, documentId, format, fileName, mimeType, createdAt]
242
+ properties:
243
+ id: { type: string }
244
+ documentId: { type: string }
245
+ versionId: { type: string }
246
+ format: { $ref: '#/components/schemas/ArtifactFormat' }
247
+ fileName: { type: string }
248
+ mimeType: { type: string }
249
+ size: { type: integer }
250
+ url: { type: string, format: uri }
251
+ createdAt: { type: string, format: date-time }
252
+ Folder:
253
+ type: object
254
+ required: [id, name]
255
+ properties: { id: { type: string }, name: { type: string }, parentId: { type: [string, 'null'] } }
256
+ DocumentPage:
257
+ type: object
258
+ required: [items, total, page, pageSize]
259
+ properties: { items: { type: array, items: { $ref: '#/components/schemas/DocumentRecord' } }, total: { type: integer }, page: { type: integer }, pageSize: { type: integer } }
260
+ VersionPage:
261
+ type: object
262
+ required: [items, total, page, pageSize]
263
+ properties: { items: { type: array, items: { $ref: '#/components/schemas/DocumentVersion' } }, total: { type: integer }, page: { type: integer }, pageSize: { type: integer } }
264
+ Error:
265
+ type: object
266
+ required: [code, message]
267
+ properties: { code: { type: string }, message: { type: string }, details: {} }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kindy-editor",
3
- "version": "1.0.1",
4
- "description": "A powerful document editor based on Vue3 and Tiptap3. Forked from Umo Editor and customized for personal use.",
3
+ "version": "2.0.0",
4
+ "description": "DOCX document library SDK and Vue 3 editor with a headless TypeScript core, powered by Tiptap/ProseMirror.",
5
5
  "keywords": [
6
6
  "docs editor",
7
7
  "document editor",
@@ -34,7 +34,19 @@
34
34
  "url": "https://github.com/hotienky/editor.git"
35
35
  },
36
36
  "files": [
37
- "dist"
37
+ "dist",
38
+ "docs/README.md",
39
+ "docs/getting-started.md",
40
+ "docs/ui-engine.md",
41
+ "docs/api-reference.md",
42
+ "docs/performance.md",
43
+ "docs/plugin-development.md",
44
+ "docs/completion-roadmap.md",
45
+ "openapi",
46
+ "CHANGELOG.md",
47
+ "GUIDE.md",
48
+ "CAPABILITIES.md",
49
+ "MIGRATION.md"
38
50
  ],
39
51
  "main": "./dist/kindy-editor.cjs",
40
52
  "module": "./dist/kindy-editor.js",
@@ -51,15 +63,38 @@
51
63
  },
52
64
  "./style": {
53
65
  "default": "./dist/kindy-editor.css"
66
+ },
67
+ "./core": {
68
+ "types": "./dist/types/core/index.d.ts",
69
+ "import": "./dist/kindy-core.js",
70
+ "require": "./dist/kindy-core.cjs"
71
+ },
72
+ "./openapi": {
73
+ "default": "./openapi/document-api.yaml"
54
74
  }
55
75
  },
56
76
  "scripts": {
57
- "build": "vite build",
77
+ "build": "node scripts/build.mjs",
78
+ "build:demo": "vite build --config vite.demo.config.js",
58
79
  "dev": "vite --port 9000 --open --force",
80
+ "preview": "vite preview",
81
+ "preview:demo": "vite preview --config vite.demo.config.js",
82
+ "docs:dev": "vitepress dev docs --port 9001 --open",
83
+ "docs:build": "vitepress build docs",
84
+ "docs:preview": "vitepress preview docs",
85
+ "test": "vitest run",
86
+ "test:e2e": "playwright test",
87
+ "test:package": "node scripts/test-packed-consumer.mjs",
88
+ "test:watch": "vitest",
89
+ "test:coverage": "vitest run --coverage",
90
+ "benchmark:long-doc": "node scripts/benchmark-long-document.mjs",
91
+ "benchmark:ci": "node scripts/benchmark-long-document.mjs --assert --output=.artifacts/long-document.json",
92
+ "typecheck": "tsc --noEmit",
59
93
  "format": "oxfmt --write .",
60
94
  "lint": "oxlint --fix src",
95
+ "lint:check": "oxlint src",
96
+ "test:libreoffice": "KINDY_TEST_LIBREOFFICE=1 vitest run src/codecs/__tests__/libreoffice.test.js",
61
97
  "analyzer": "vite-bundle-visualizer",
62
- "prepare": "husky",
63
98
  "prepublishOnly": "npm run build"
64
99
  },
65
100
  "dependencies": {
@@ -67,6 +102,7 @@
67
102
  "@floating-ui/dom": "1.7.5",
68
103
  "@tiptap/core": "3.20.0",
69
104
  "@tiptap/extension-bold": "3.20.0",
105
+ "@tiptap/extension-bubble-menu": "3.20.0",
70
106
  "@tiptap/extension-code-block": "3.20.0",
71
107
  "@tiptap/extension-code-block-lowlight": "3.20.0",
72
108
  "@tiptap/extension-collaboration": "3.20.0",
@@ -74,6 +110,7 @@
74
110
  "@tiptap/extension-document": "3.20.0",
75
111
  "@tiptap/extension-drag-handle": "3.16.0",
76
112
  "@tiptap/extension-drag-handle-vue-3": "3.16.0",
113
+ "@tiptap/extension-floating-menu": "3.20.0",
77
114
  "@tiptap/extension-horizontal-rule": "3.20.0",
78
115
  "@tiptap/extension-image": "3.20.0",
79
116
  "@tiptap/extension-invisible-characters": "3.20.0",
@@ -97,17 +134,18 @@
97
134
  "@tiptap/vue-3": "3.20.0",
98
135
  "@tiptap/y-tiptap": "3.0.2",
99
136
  "@tool-belt/type-predicates": "1.4.1",
100
- "@umoteam/editor-external": "10.1.0",
101
137
  "@vueuse/core": "14.2.1",
102
138
  "cropperjs": "^2.1.1",
139
+ "docx": "^9.7.1",
103
140
  "dom-to-image-more": "3.7.2",
104
141
  "es-drager": "1.2.11",
105
- "fast-glob": "3.3.3",
142
+ "fflate": "^0.8.3",
106
143
  "file-saver": "2.0.5",
107
144
  "hotkeys-js": "4.0.2",
108
145
  "jsbarcode": "3.12.3",
109
146
  "katex": "0.16.33",
110
147
  "lowlight": "3.3.0",
148
+ "mammoth": "^1.12.0",
111
149
  "nzh": "1.0.14",
112
150
  "pretty-bytes": "7.1.0",
113
151
  "pure-svg-code": "1.0.6",
@@ -118,9 +156,12 @@
118
156
  "yjs": "13.6.29"
119
157
  },
120
158
  "devDependencies": {
159
+ "@playwright/test": "^1.62.1",
121
160
  "@vitejs/plugin-vue": "^6.0.4",
122
161
  "@vue-macros/reactivity-transform": "^3.1.2",
162
+ "@vue/test-utils": "^2.4.11",
123
163
  "esbuild": "^0.28.1",
164
+ "happy-dom": "^20.11.2",
124
165
  "husky": "^9.1.7",
125
166
  "less": "^4.5.1",
126
167
  "less-loader": "^12.3.1",
@@ -130,17 +171,26 @@
130
171
  "postcss": "^8.5.6",
131
172
  "postcss-html": "^1.8.1",
132
173
  "tdesign-vue-next": "1.18.2",
174
+ "typescript": "^5.9.2",
133
175
  "unplugin-auto-import": "^21.0.0",
134
176
  "unplugin-vue": "^7.1.1",
135
177
  "unplugin-vue-components": "^31.0.0",
136
178
  "unplugin-vue-macros": "^2.14.5",
137
179
  "vite": "^7.3.1",
138
180
  "vite-bundle-visualizer": "^1.2.1",
139
- "vite-plugin-svg-icons": "^2.0.1",
181
+ "vitepress": "^1.6.4",
182
+ "vitest": "^4.1.10",
140
183
  "vue": "^3.5.29"
141
184
  },
142
185
  "overrides": {
143
- "rolldown": "^1.1.3"
186
+ "rolldown": "^1.1.3",
187
+ "uuid": "^11.1.1",
188
+ "postcss": {
189
+ "nanoid": "^3.3.18"
190
+ }
191
+ },
192
+ "peerDependencies": {
193
+ "vue": "^3.5.0"
144
194
  },
145
195
  "lint-staged": {
146
196
  "*.{js,vue,less}": [