nuvra 0.4.0 → 0.5.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 +179 -13
- package/dist/compare.vue.d.ts +19 -0
- package/dist/components/document-editor.vue.d.ts +49 -3
- package/dist/components/editor-canvas.vue.d.ts +6 -7
- package/dist/components/editor-changes.vue.d.ts +18 -0
- package/dist/components/editor-comments.vue.d.ts +32 -0
- package/dist/components/editor-footnote-form.vue.d.ts +19 -0
- package/dist/components/editor-outline.vue.d.ts +16 -0
- package/dist/components/editor-slash-menu.vue.d.ts +13 -0
- package/dist/components/editor-toolbar.vue.d.ts +24 -1
- package/dist/core/comments.d.ts +26 -0
- package/dist/core/dates.d.ts +8 -0
- package/dist/core/diff.d.ts +11 -0
- package/dist/core/document-templates.d.ts +22 -0
- package/dist/core/docx/export.d.ts +19 -0
- package/dist/core/docx/import.d.ts +19 -0
- package/dist/core/docx/zip.d.ts +23 -0
- package/dist/core/engine/dom.d.ts +31 -1
- package/dist/core/engine/editing.d.ts +11 -0
- package/dist/core/engine/engine.d.ts +144 -2
- package/dist/core/engine/input-rules.d.ts +3 -1
- package/dist/core/engine/marks.d.ts +50 -1
- package/dist/core/engine/schema.d.ts +7 -2
- package/dist/core/export.d.ts +6 -5
- package/dist/core/footnotes.d.ts +15 -0
- package/dist/core/icons.d.ts +1 -1
- package/dist/core/labels.d.ts +6 -2
- package/dist/core/locales/uz-cyrl.d.ts +3 -0
- package/dist/core/locales/uz.d.ts +64 -1
- package/dist/core/numbers.d.ts +19 -0
- package/dist/core/outline.d.ts +42 -0
- package/dist/core/page.d.ts +12 -2
- package/dist/core/pagination.d.ts +4 -1
- package/dist/core/signature.d.ts +15 -0
- package/dist/core/slash-commands.d.ts +19 -0
- package/dist/core/templates.d.ts +32 -0
- package/dist/core/transliterate.d.ts +13 -0
- package/dist/core/types.d.ts +1 -1
- package/dist/core/ui-state.d.ts +8 -0
- package/dist/editor.vue.d.ts +6 -2
- package/dist/export-DhHI3ZrQ.js +94 -0
- package/dist/export-DhHI3ZrQ.js.map +1 -0
- package/dist/footnotes-DBShImw7.js +11 -0
- package/dist/footnotes-DBShImw7.js.map +1 -0
- package/dist/form.vue.d.ts +39 -0
- package/dist/index.d.ts +26 -1
- package/dist/index.js +8005 -4236
- package/dist/index.js.map +1 -1
- package/dist/{page-DL7Oj2o8.js → page-DY5fdgcT.js} +10 -10
- package/dist/page-DY5fdgcT.js.map +1 -0
- package/dist/style.css +1 -1
- package/dist/zip-CpbwZtot.js +46 -0
- package/dist/zip-CpbwZtot.js.map +1 -0
- package/package.json +5 -2
- package/dist/export-VeTfgCEp.js +0 -117
- package/dist/export-VeTfgCEp.js.map +0 -1
- package/dist/page-DL7Oj2o8.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# nuvra
|
|
2
2
|
|
|
3
3
|
Word-style document editor for Vue 3. A real page view with paper sizes and margins, a lighter web view for
|
|
4
|
-
forms, tables, images, lists, find & replace, HTML source mode, printing
|
|
4
|
+
forms, tables, images, lists, find & replace, comments, HTML source mode, printing, export to HTML and Word files
|
|
5
|
+
(`.docx`) you can open again.
|
|
5
6
|
|
|
6
7
|
**[Documentation and live demo →](https://nuvra-docs.vercel.app)**
|
|
7
8
|
|
|
@@ -17,6 +18,11 @@ forms, tables, images, lists, find & replace, HTML source mode, printing and exp
|
|
|
17
18
|
the editor shows them, and the Word export uses Word's own header, footer and page fields.
|
|
18
19
|
- A ruler above the page for the margins and for the first line, left and right indents of a paragraph.
|
|
19
20
|
- A page watermark such as DRAFT or COPY, drawn behind the text of every page and carried into print, HTML and Word.
|
|
21
|
+
- Real `.docx` export and import, multilevel (1.1.1) numbering, a table of contents and a navigation pane.
|
|
22
|
+
- Footnotes at the bottom of their page, carried into print and Word.
|
|
23
|
+
- Comments with replies, tracked changes that round-trip with Word, a comparison of two versions, and templates
|
|
24
|
+
filled in as a form.
|
|
25
|
+
- A `/` command menu and a toolbar slot for your own commands and buttons.
|
|
20
26
|
|
|
21
27
|
## Installation
|
|
22
28
|
|
|
@@ -91,7 +97,10 @@ const uploadImage: DocumentImageUploadHandler = async file => {
|
|
|
91
97
|
| Prop | Type | Default | Description |
|
|
92
98
|
| ----------------- | --------------------------------- | -------- | -------------------------------------------------------------------------- |
|
|
93
99
|
| `v-model` | `string` | `''` | Document HTML; an empty document is an empty string. |
|
|
94
|
-
| `v-model:page` | `PageSettings` | A4 | Paper size, orientation
|
|
100
|
+
| `v-model:page` | `PageSettings` | A4 | Paper size, orientation, margins, headers, footers, watermark, numbering. |
|
|
101
|
+
| `v-model:comments`| `DocumentComment[]` | — | Comments; binding it turns the comment tools on. |
|
|
102
|
+
| `v-model:trackChanges` | `boolean` | `false` | Records edits as tracked changes. |
|
|
103
|
+
| `author` | `string` | `''` | Name written on new comments, replies and tracked changes. |
|
|
95
104
|
| `autofocus` | `boolean` | `false` | Places the caret at the end of the document once ready. |
|
|
96
105
|
| `canvasPadding` | `number \| string` | `50` | Gray space around the page or web sheet. |
|
|
97
106
|
| `defaultViewMode` | `'page' \| 'web'` | `'page'` | View shown first. |
|
|
@@ -103,10 +112,14 @@ const uploadImage: DocumentImageUploadHandler = async file => {
|
|
|
103
112
|
| `maxImageSizeMb` | `number` | `10` | Largest accepted image file. |
|
|
104
113
|
| `maxLength` | `number` | `0` | Character limit; `0` means unlimited. |
|
|
105
114
|
| `placeholder` | `string` | `''` | Text shown while the document is empty. |
|
|
115
|
+
| `ruler` | `boolean` | `true` | Shows the ruler in the page view. |
|
|
116
|
+
| `slashCommands` | `SlashCommand[]` | `[]` | Your own commands, listed first in the `/` menu. |
|
|
106
117
|
| `title` | `string` | `''` | Print title and exported file name. |
|
|
107
118
|
| `uploadImage` | `(file: File) => Promise<string>` | — | Uploads an image and resolves with its URL. |
|
|
119
|
+
| `variables` | `TemplateVariable[]` | `[]` | Template variables the user can insert. |
|
|
108
120
|
|
|
109
|
-
`Editor` accepts the same props except `v-model:page`, `
|
|
121
|
+
`Editor` accepts the same props except `v-model:page`, `v-model:comments`, `v-model:trackChanges`, `author`,
|
|
122
|
+
`defaultViewMode`, `height`, `ruler`, `slashCommands` and `title`.
|
|
110
123
|
|
|
111
124
|
Numbers are pixels; strings are used as CSS lengths (`'100%'`, `'50vh'`).
|
|
112
125
|
|
|
@@ -117,29 +130,182 @@ Numbers are pixels; strings are used as CSS lengths (`'100%'`, `'50vh'`).
|
|
|
117
130
|
| `focus` | — | The document received focus. |
|
|
118
131
|
| `blur` | — | The document lost focus; the model is up to date. |
|
|
119
132
|
| `uploadError` | `error: unknown` | An image was rejected or its upload failed. |
|
|
133
|
+
| `importError` | `error: unknown` | A Word file could not be read. |
|
|
120
134
|
|
|
121
135
|
### Exposed methods (`DocumentEditor` ref)
|
|
122
136
|
|
|
123
|
-
| Method
|
|
124
|
-
|
|
|
125
|
-
| `focus()`
|
|
126
|
-
| `getHTML()`
|
|
127
|
-
| `
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
137
|
+
| Method | Description |
|
|
138
|
+
| ------------------------- | ---------------------------------------------------------------- |
|
|
139
|
+
| `focus()` | Moves keyboard focus into the document. |
|
|
140
|
+
| `getHTML()` | Returns the document HTML, including edits not yet in the model. |
|
|
141
|
+
| `insertVariable(name)` | Inserts a template variable at the selection. |
|
|
142
|
+
| `updateTableOfContents()` | Inserts or refreshes the table of contents. |
|
|
143
|
+
| `importWord(file)` | Replaces the document with the content of a `.docx` file. |
|
|
144
|
+
| `print()` | Opens the browser print dialog. |
|
|
145
|
+
| `exportHtml()` | Downloads the document as an HTML page. |
|
|
146
|
+
| `exportWord()` | Downloads the document as a Word file (`.docx`). |
|
|
147
|
+
| `engine` | The editing engine (`DocumentEngine`), for advanced integrations. |
|
|
131
148
|
|
|
132
149
|
### Keyboard shortcuts
|
|
133
150
|
|
|
134
151
|
`Ctrl/⌘+B`, `I`, `U` — bold, italic, underline · `Ctrl/⌘+Shift+H` — highlight · `Ctrl/⌘+Z`, `Ctrl/⌘+Shift+Z` — undo,
|
|
135
|
-
redo · `Ctrl/⌘+F` — find · `Ctrl/⌘+H` — replace · `Ctrl/⌘+K` — link · `Ctrl/⌘+P` — print.
|
|
152
|
+
redo · `Ctrl/⌘+F` — find · `Ctrl/⌘+H` — replace · `Ctrl/⌘+K` — link · `Ctrl/⌘+Alt+M` — comment · `Ctrl/⌘+P` — print.
|
|
136
153
|
|
|
137
154
|
The full list, with Markdown-like input rules, is in the
|
|
138
155
|
[keyboard shortcuts guide](https://nuvra-docs.vercel.app/docs/keyboard-shortcuts).
|
|
139
156
|
|
|
157
|
+
## Templates and signatures
|
|
158
|
+
|
|
159
|
+
Pass `variables` to let users insert template variables with the toolbar's **{ }** menu or by typing `{{name}}`.
|
|
160
|
+
They are saved as `<span data-variable="name">{{name}}</span>`; `fillTemplate` replaces them with escaped values,
|
|
161
|
+
in the browser or on a Node server:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
import { type TemplateVariable, fillTemplate } from 'nuvra';
|
|
165
|
+
|
|
166
|
+
const variables: TemplateVariable[] = [
|
|
167
|
+
{ name: 'full_name', label: 'Full name' },
|
|
168
|
+
{ name: 'letter_date', label: 'Letter date' }
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
const letter = fillTemplate(template, { full_name: 'Aziz Karimov', letter_date: '14.09.2026' });
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The pen button inserts a signature block in the editor's language: a signature line, an “Approved” or “Agreed”
|
|
175
|
+
block, or the signatures of both parties of a contract. It is a borderless table, so it prints and exports to Word
|
|
176
|
+
without lines.
|
|
177
|
+
|
|
178
|
+
The document button inserts ready-made templates (official letter, order, application, certificate, act), and the
|
|
179
|
+
toolbar writes amounts in words (`15 000 000 (o‘n besh million)`), inserts long dates (`2026-yil 14-sentabr`) and
|
|
180
|
+
converts Uzbek text between the Latin and Cyrillic alphabets. The same helpers are exported: `getDocumentTemplate`,
|
|
181
|
+
`numberToWords`, `formatAmountInWords`, `parseAmount`, `formatLongDate` and `transliterate`.
|
|
182
|
+
|
|
183
|
+
### Filling a template as a form
|
|
184
|
+
|
|
185
|
+
`DocumentForm` shows a saved template as it will be printed, with an input in place of every variable. Fields of the
|
|
186
|
+
same variable share one value:
|
|
187
|
+
|
|
188
|
+
```vue
|
|
189
|
+
<script setup lang="ts">
|
|
190
|
+
import { ref } from 'vue';
|
|
191
|
+
import { DocumentForm } from 'nuvra';
|
|
192
|
+
|
|
193
|
+
const values = ref<Record<string, string>>({});
|
|
194
|
+
const form = ref<InstanceType<typeof DocumentForm>>();
|
|
195
|
+
|
|
196
|
+
const submit = () => {
|
|
197
|
+
if (form.value?.validate().length) return; // empty fields are marked and focused
|
|
198
|
+
const html = form.value?.getHTML(); // filled with fillTemplate
|
|
199
|
+
};
|
|
200
|
+
</script>
|
|
201
|
+
|
|
202
|
+
<template>
|
|
203
|
+
<DocumentForm ref="form" v-model="values" :template="template" :variables="variables" />
|
|
204
|
+
</template>
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Word files and long documents
|
|
208
|
+
|
|
209
|
+
"Download as Word (.docx)" in the "More" menu writes a real Office Open XML file with the page setup, headers and
|
|
210
|
+
footers with page fields, the watermark, lists, tables with merged cells, images, footnotes and tracked changes as
|
|
211
|
+
Word revisions. "Open Word file (.docx)" (or `importWord(file)`) loads one into the editor, footnotes and revisions
|
|
212
|
+
included; a file that cannot be read emits `importError`. `buildDocx` and `readDocx` do the same in your own code. A
|
|
213
|
+
document with several sections gets the page setup of its last section, and the content of a different first page
|
|
214
|
+
header is not imported.
|
|
215
|
+
|
|
216
|
+
### Footnotes
|
|
217
|
+
|
|
218
|
+
"Footnote" in the insert menu or the `/` menu adds a numbered reference and opens a small form for the note; clicking
|
|
219
|
+
a reference edits or deletes it. A footnote is saved in the reference, `<sup data-footnote="note text">1</sup>`, and
|
|
220
|
+
renumbered in document order. The page view draws the notes at the bottom of the sheet the reference is on, the web
|
|
221
|
+
view after the document; printing follows the sheets, and the Word export writes Word footnotes. Notes are plain text.
|
|
222
|
+
From code: `engine.insertFootnote(text)`, `setFootnoteText(element, text)`, `removeFootnote(element)`,
|
|
223
|
+
`getFootnotes()`.
|
|
224
|
+
|
|
225
|
+
For long documents the toolbar offers multilevel numbering (1., 1.1., 1.1.1., saved as `<ol data-numbering="legal">`),
|
|
226
|
+
a table of contents of the headings with page numbers (saved as `<table data-type="toc">`, refreshed with
|
|
227
|
+
`updateTableOfContents()`), and a navigation pane. `PageSettings` has `differentFirstPage` to hide the header, footer
|
|
228
|
+
and page number on the first page, and `firstPageNumber` for the number printed on it.
|
|
229
|
+
|
|
230
|
+
## Comments, tracked changes and comparison
|
|
231
|
+
|
|
232
|
+
Bind `v-model:comments` to turn comments on. The HTML keeps only the anchors, `<span data-comment="id">`; the
|
|
233
|
+
comments are plain data you store next to the document:
|
|
234
|
+
|
|
235
|
+
```vue
|
|
236
|
+
<script setup lang="ts">
|
|
237
|
+
import { ref } from 'vue';
|
|
238
|
+
import { DocumentEditor, type DocumentComment } from 'nuvra';
|
|
239
|
+
|
|
240
|
+
const html = ref('');
|
|
241
|
+
const comments = ref<DocumentComment[]>([]);
|
|
242
|
+
|
|
243
|
+
const save = () =>
|
|
244
|
+
fetch('/api/documents/42', {
|
|
245
|
+
method: 'PUT',
|
|
246
|
+
headers: { 'Content-Type': 'application/json' },
|
|
247
|
+
body: JSON.stringify({ html: html.value, comments: comments.value })
|
|
248
|
+
});
|
|
249
|
+
</script>
|
|
250
|
+
|
|
251
|
+
<template>
|
|
252
|
+
<DocumentEditor v-model="html" v-model:comments="comments" author="Aziz Karimov" @blur="save" />
|
|
253
|
+
</template>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Users select text and press "Add comment" (`Ctrl/⌘+Alt+M`); the "Comments" panel replies, resolves, reopens and
|
|
257
|
+
deletes them, and flags comments whose text was deleted.
|
|
258
|
+
|
|
259
|
+
### Tracked changes
|
|
260
|
+
|
|
261
|
+
Bind `v-model:trackChanges` (or press "Track changes") to record typing, deleting, cut and paste as tracked changes
|
|
262
|
+
by `author`. They are part of the HTML, `<ins data-change="id" data-author="…" data-time="…">` and `<del …>`, shown
|
|
263
|
+
and printed green-underlined and red-struck. The "Changes" panel accepts or rejects them one by one or all at once;
|
|
264
|
+
from code use `engine.getChanges()`, `engine.resolveChanges(accept, id?)` and `engine.selectChange(id)`. Formatting,
|
|
265
|
+
block changes (headings, lists, tables), Enter and joining paragraphs are not tracked. The Word export writes them as
|
|
266
|
+
revisions and the import reads Word revisions back.
|
|
267
|
+
|
|
268
|
+
```vue
|
|
269
|
+
<DocumentEditor v-model="html" v-model:track-changes="tracking" author="Aziz Karimov" />
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
`DocumentCompare` shows what changed between two versions: inserted words in green, deleted words struck through in
|
|
273
|
+
red. Unchanged blocks stay as they are, changed paragraphs are compared word by word, and added or removed blocks are
|
|
274
|
+
shown whole. `compareDocuments(before, after)` returns the same HTML and counts for your own view.
|
|
275
|
+
|
|
276
|
+
```vue
|
|
277
|
+
<DocumentCompare :before="previousVersion" :after="html" :height="600" />
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Commands and toolbar buttons
|
|
281
|
+
|
|
282
|
+
Typing `/` at the start of a line or after a space opens a command menu: headings, lists, table, page break, footnote,
|
|
283
|
+
table of contents, dates, signature blocks and your variables. `slashCommands` adds your own commands at the top, and the
|
|
284
|
+
`toolbar` slot adds your own buttons:
|
|
285
|
+
|
|
286
|
+
```vue
|
|
287
|
+
<script setup lang="ts">
|
|
288
|
+
import { DocumentEditor, type SlashCommand } from 'nuvra';
|
|
289
|
+
|
|
290
|
+
const slashCommands: SlashCommand[] = [
|
|
291
|
+
{ id: 'director', label: 'Director’s name', icon: 'pencil', run: engine => engine.insertText('A. Karimov') }
|
|
292
|
+
];
|
|
293
|
+
</script>
|
|
294
|
+
|
|
295
|
+
<template>
|
|
296
|
+
<DocumentEditor v-model="html" :slash-commands="slashCommands">
|
|
297
|
+
<template #toolbar="{ engine, disabled }">
|
|
298
|
+
<button type="button" class="doc-tb-button" :disabled="disabled" @mousedown.prevent @click="engine.insertText('✓')">
|
|
299
|
+
✓
|
|
300
|
+
</button>
|
|
301
|
+
</template>
|
|
302
|
+
</DocumentEditor>
|
|
303
|
+
</template>
|
|
304
|
+
```
|
|
305
|
+
|
|
140
306
|
## Languages
|
|
141
307
|
|
|
142
|
-
The interface ships in Uzbek (`uz`, the default), English (`en`) and Russian (`ru`). The translations are part of
|
|
308
|
+
The interface ships in Uzbek (`uz`, the default), Uzbek Cyrillic (`uzCyrl`), English (`en`) and Russian (`ru`). The translations are part of
|
|
143
309
|
the package and cannot be changed from outside; an app only picks the language.
|
|
144
310
|
|
|
145
311
|
For one editor, pass the locale (or just its code) to the `locale` prop:
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type EditorLocaleInput } from './core/labels';
|
|
2
|
+
import './styles/document-content.css';
|
|
3
|
+
import './styles/editor-ui.css';
|
|
4
|
+
interface Props {
|
|
5
|
+
/** HTML of the earlier version. */
|
|
6
|
+
before: string;
|
|
7
|
+
/** HTML of the later version. */
|
|
8
|
+
after: string;
|
|
9
|
+
/** Interface language: a built-in locale or its code; defaults to the app-wide language. */
|
|
10
|
+
locale?: EditorLocaleInput;
|
|
11
|
+
/** Height of the component, in pixels or any CSS length; `'auto'` grows with the document. */
|
|
12
|
+
height?: number | string;
|
|
13
|
+
}
|
|
14
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
15
|
+
height: number | string;
|
|
16
|
+
locale: EditorLocaleInput;
|
|
17
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
18
|
+
declare const _default: typeof __VLS_export;
|
|
19
|
+
export default _default;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { type DocumentComment } from '../core/comments';
|
|
1
2
|
import { DocumentEngine } from '../core/engine/engine';
|
|
2
3
|
import { type EditorLocaleInput } from '../core/labels';
|
|
3
4
|
import { type DocumentViewMode, type PageSettings } from '../core/page';
|
|
5
|
+
import type { SlashCommand } from '../core/slash-commands';
|
|
6
|
+
import type { TemplateVariable } from '../core/templates';
|
|
4
7
|
import type { DocumentImageUploadHandler } from '../core/types';
|
|
8
|
+
import { type EditorUiState } from '../core/ui-state';
|
|
5
9
|
import '../styles/document-content.css';
|
|
6
10
|
import '../styles/editor-ui.css';
|
|
7
11
|
/** A CSS length: numbers are pixels, strings are used as written (for example, `'100%'` or `'auto'`). */
|
|
@@ -11,6 +15,8 @@ interface Props {
|
|
|
11
15
|
autofocus?: boolean;
|
|
12
16
|
/** Gray space around the page or web sheet that separates the document from the editor frame. */
|
|
13
17
|
canvasPadding?: CssSize;
|
|
18
|
+
/** Name written as the author of new comments, replies and tracked changes. */
|
|
19
|
+
author?: string;
|
|
14
20
|
/** View shown first; form fields use the lighter web view. */
|
|
15
21
|
defaultViewMode?: DocumentViewMode;
|
|
16
22
|
/** Makes the document read-only and disables every editing control. */
|
|
@@ -29,22 +35,41 @@ interface Props {
|
|
|
29
35
|
minHeight?: CssSize;
|
|
30
36
|
/** Text shown while the document is empty; falls back to the translated default placeholder. */
|
|
31
37
|
placeholder?: string;
|
|
38
|
+
/** Commands of the host application, listed first in the `/` menu. */
|
|
39
|
+
slashCommands?: readonly SlashCommand[];
|
|
32
40
|
/** Shows the ruler above the sheet in the page view; users can also toggle it in the document menu. */
|
|
33
41
|
ruler?: boolean;
|
|
34
42
|
/** Used as the print title and the exported file name. */
|
|
35
43
|
title?: string;
|
|
36
44
|
/** Uploads an inserted image and resolves with its URL; without it images are embedded as data URLs. */
|
|
37
45
|
uploadImage?: DocumentImageUploadHandler;
|
|
46
|
+
/** Template variables the user can insert; typing `{{name}}` of one of them inserts it as well. */
|
|
47
|
+
variables?: readonly TemplateVariable[];
|
|
38
48
|
}
|
|
39
49
|
type __VLS_Props = Props;
|
|
50
|
+
type __VLS_Slots = {
|
|
51
|
+
/**
|
|
52
|
+
* Buttons of the host application, placed at the start of the toolbar's right-hand group. `engine` runs editing
|
|
53
|
+
* commands, `state` describes the formatting at the caret and `disabled` tells whether editing is possible.
|
|
54
|
+
*/
|
|
55
|
+
toolbar?: (props: {
|
|
56
|
+
engine: DocumentEngine;
|
|
57
|
+
state: EditorUiState;
|
|
58
|
+
disabled: boolean;
|
|
59
|
+
}) => unknown;
|
|
60
|
+
};
|
|
40
61
|
type __VLS_ModelProps = {
|
|
41
62
|
/** Document HTML. An empty document is written as an empty string; typing updates it after a short delay. */
|
|
42
63
|
modelValue?: string;
|
|
43
64
|
/** Paper size, orientation, and margins used by the page view, printing, and export. */
|
|
44
65
|
'page'?: PageSettings;
|
|
66
|
+
/** Whether edits are recorded as tracked changes; the toolbar can switch it. */
|
|
67
|
+
'trackChanges'?: boolean;
|
|
68
|
+
/** Comments on the document; binding it turns the comment tools on. The HTML keeps only their anchors. */
|
|
69
|
+
'comments'?: DocumentComment[] | undefined;
|
|
45
70
|
};
|
|
46
71
|
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
47
|
-
declare const
|
|
72
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
48
73
|
/** The editing engine, for advanced integrations. */
|
|
49
74
|
engine: import("vue").ShallowRef<DocumentEngine | null, DocumentEngine | null>;
|
|
50
75
|
/** Downloads the document as an HTML page. */
|
|
@@ -55,6 +80,12 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
55
80
|
focus: () => void | undefined;
|
|
56
81
|
/** Returns the document HTML, including edits not yet written to the model. */
|
|
57
82
|
getHTML: () => string;
|
|
83
|
+
/** Replaces the document with the content and page setup of a `.docx` file. */
|
|
84
|
+
importWord: (file: File) => Promise<void>;
|
|
85
|
+
/** Inserts the chip of a template variable at the selection. */
|
|
86
|
+
insertVariable: (name: string) => void | undefined;
|
|
87
|
+
/** Inserts the table of contents at the selection, or refreshes the existing one. */
|
|
88
|
+
updateTableOfContents: () => Promise<void>;
|
|
58
89
|
/** Opens the print dialog. */
|
|
59
90
|
print: () => Promise<void>;
|
|
60
91
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
@@ -62,28 +93,43 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {
|
|
|
62
93
|
blur: () => any;
|
|
63
94
|
"update:page": (value: PageSettings) => any;
|
|
64
95
|
uploadError: (error: unknown) => any;
|
|
96
|
+
importError: (error: unknown) => any;
|
|
65
97
|
"update:modelValue": (value: string) => any;
|
|
98
|
+
"update:trackChanges": (value: boolean) => any;
|
|
99
|
+
"update:comments": (value: DocumentComment[] | undefined) => any;
|
|
66
100
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
67
101
|
onFocus?: (() => any) | undefined;
|
|
68
102
|
onBlur?: (() => any) | undefined;
|
|
69
103
|
"onUpdate:page"?: ((value: PageSettings) => any) | undefined;
|
|
70
104
|
onUploadError?: ((error: unknown) => any) | undefined;
|
|
105
|
+
onImportError?: ((error: unknown) => any) | undefined;
|
|
71
106
|
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
107
|
+
"onUpdate:trackChanges"?: ((value: boolean) => any) | undefined;
|
|
108
|
+
"onUpdate:comments"?: ((value: DocumentComment[] | undefined) => any) | undefined;
|
|
72
109
|
}>, {
|
|
73
110
|
title: string;
|
|
74
111
|
height: CssSize;
|
|
112
|
+
locale: EditorLocaleInput;
|
|
75
113
|
ruler: boolean;
|
|
76
114
|
placeholder: string;
|
|
77
115
|
disabled: boolean;
|
|
78
116
|
minHeight: CssSize;
|
|
79
|
-
maxLength: number;
|
|
80
117
|
maxHeight: CssSize;
|
|
118
|
+
maxLength: number;
|
|
119
|
+
variables: readonly TemplateVariable[];
|
|
120
|
+
author: string;
|
|
81
121
|
autofocus: boolean;
|
|
82
122
|
canvasPadding: CssSize;
|
|
83
123
|
defaultViewMode: DocumentViewMode;
|
|
84
|
-
locale: EditorLocaleInput;
|
|
85
124
|
maxImageSizeMb: number;
|
|
125
|
+
slashCommands: readonly SlashCommand[];
|
|
86
126
|
uploadImage: DocumentImageUploadHandler;
|
|
87
127
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
128
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
88
129
|
declare const _default: typeof __VLS_export;
|
|
89
130
|
export default _default;
|
|
131
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
132
|
+
new (): {
|
|
133
|
+
$slots: S;
|
|
134
|
+
};
|
|
135
|
+
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ParagraphIndents } from '../core/engine/blocks';
|
|
2
2
|
import type { DocumentEngine } from '../core/engine/engine';
|
|
3
|
-
import { type
|
|
3
|
+
import { type SheetFootnote } from '../core/footnotes';
|
|
4
|
+
import { type DocumentViewMode, type PageMargins, type PageMetrics, type PageSettings } from '../core/page';
|
|
4
5
|
interface Props {
|
|
5
6
|
/** Grow with the content between the editor's min and max height instead of filling a fixed height. */
|
|
6
7
|
autoHeight: boolean;
|
|
@@ -10,10 +11,10 @@ interface Props {
|
|
|
10
11
|
documentTitle: string;
|
|
11
12
|
/** Engine working on the editable element; `null` until the parent has created it. */
|
|
12
13
|
engine: DocumentEngine | null;
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
|
|
14
|
+
/** Footnotes of every sheet, drawn at its bottom; the web view shows all of them after the document. */
|
|
15
|
+
footnotes: SheetFootnote[][];
|
|
16
|
+
/** Page setup: running texts, watermark and page numbering of every sheet. */
|
|
17
|
+
page: PageSettings;
|
|
17
18
|
/** Indents of the paragraph at the caret, shown by the ruler. */
|
|
18
19
|
indents: ParagraphIndents;
|
|
19
20
|
/** Page size and margins in pixels. */
|
|
@@ -24,8 +25,6 @@ interface Props {
|
|
|
24
25
|
rulerVisible: boolean;
|
|
25
26
|
/** Paginated sheets or a single web sheet. */
|
|
26
27
|
viewMode: DocumentViewMode;
|
|
27
|
-
/** Watermark drawn behind the text of every sheet. */
|
|
28
|
-
watermark?: PageWatermark;
|
|
29
28
|
/** Zoom in percent. */
|
|
30
29
|
zoom: number;
|
|
31
30
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TrackedChange } from '../core/engine/engine';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** Tracked changes in document order. */
|
|
4
|
+
changes: readonly TrackedChange[];
|
|
5
|
+
/** Read-only document: changes can be reviewed but not accepted or rejected. */
|
|
6
|
+
readonly: boolean | undefined;
|
|
7
|
+
}
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
+
select: (id: string) => any;
|
|
10
|
+
close: () => any;
|
|
11
|
+
resolve: (accept: boolean, id?: string | undefined) => any;
|
|
12
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
13
|
+
onSelect?: ((id: string) => any) | undefined;
|
|
14
|
+
onClose?: (() => any) | undefined;
|
|
15
|
+
onResolve?: ((accept: boolean, id?: string | undefined) => any) | undefined;
|
|
16
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
17
|
+
declare const _default: typeof __VLS_export;
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { DocumentComment } from '../core/comments';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** Comments in document order. */
|
|
4
|
+
comments: ReadonlyArray<DocumentComment>;
|
|
5
|
+
/** Ids of the comments whose text is still in the document. */
|
|
6
|
+
anchored: ReadonlySet<string>;
|
|
7
|
+
/** Comment at the caret, highlighted in the list. */
|
|
8
|
+
activeId: string | null;
|
|
9
|
+
/** Whether the form of a new comment is shown. */
|
|
10
|
+
drafting: boolean;
|
|
11
|
+
/** Read-only document: comments can be read but not changed. */
|
|
12
|
+
readonly: boolean | undefined;
|
|
13
|
+
}
|
|
14
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
15
|
+
select: (id: string) => any;
|
|
16
|
+
reply: (id: string, text: string) => any;
|
|
17
|
+
close: () => any;
|
|
18
|
+
remove: (id: string) => any;
|
|
19
|
+
resolve: (id: string, resolved: boolean) => any;
|
|
20
|
+
add: (text: string) => any;
|
|
21
|
+
cancelDraft: () => any;
|
|
22
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
23
|
+
onSelect?: ((id: string) => any) | undefined;
|
|
24
|
+
onReply?: ((id: string, text: string) => any) | undefined;
|
|
25
|
+
onClose?: (() => any) | undefined;
|
|
26
|
+
onRemove?: ((id: string) => any) | undefined;
|
|
27
|
+
onResolve?: ((id: string, resolved: boolean) => any) | undefined;
|
|
28
|
+
onAdd?: ((text: string) => any) | undefined;
|
|
29
|
+
onCancelDraft?: (() => any) | undefined;
|
|
30
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
31
|
+
declare const _default: typeof __VLS_export;
|
|
32
|
+
export default _default;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
/** The footnote reference being edited. */
|
|
3
|
+
reference: HTMLElement;
|
|
4
|
+
/** Element the form is positioned in; it must be positioned itself. */
|
|
5
|
+
container: HTMLElement;
|
|
6
|
+
/** Read-only document: the note is shown but cannot be changed. */
|
|
7
|
+
readonly: boolean | undefined;
|
|
8
|
+
}
|
|
9
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
10
|
+
cancel: () => any;
|
|
11
|
+
remove: () => any;
|
|
12
|
+
save: (text: string) => any;
|
|
13
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
14
|
+
onCancel?: (() => any) | undefined;
|
|
15
|
+
onRemove?: (() => any) | undefined;
|
|
16
|
+
onSave?: ((text: string) => any) | undefined;
|
|
17
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
18
|
+
declare const _default: typeof __VLS_export;
|
|
19
|
+
export default _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OutlineHeading } from '../core/outline';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** Headings of the document with the page each starts on, `null` outside the page view. */
|
|
4
|
+
headings: ReadonlyArray<OutlineHeading & {
|
|
5
|
+
page: number | null;
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
8
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
9
|
+
select: (heading: HTMLElement) => any;
|
|
10
|
+
close: () => any;
|
|
11
|
+
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
12
|
+
onSelect?: ((heading: HTMLElement) => any) | undefined;
|
|
13
|
+
onClose?: (() => any) | undefined;
|
|
14
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
declare const _default: typeof __VLS_export;
|
|
16
|
+
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DocumentEngine } from '../core/engine/engine';
|
|
2
|
+
import { type SlashCommand } from '../core/slash-commands';
|
|
3
|
+
interface Props {
|
|
4
|
+
/** Engine the commands run on. */
|
|
5
|
+
engine: DocumentEngine;
|
|
6
|
+
/** Every command the menu offers. */
|
|
7
|
+
commands: readonly SlashCommand[];
|
|
8
|
+
/** Element the menu is positioned in; it must be positioned itself. */
|
|
9
|
+
container: HTMLElement;
|
|
10
|
+
}
|
|
11
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DocumentEngine } from '../core/engine/engine';
|
|
2
2
|
import { type PageSettings } from '../core/page';
|
|
3
|
+
import type { TemplateVariable } from '../core/templates';
|
|
3
4
|
import type { DocumentMenuAction } from '../core/types';
|
|
4
5
|
import { type EditorUiState } from '../core/ui-state';
|
|
5
6
|
interface Props {
|
|
@@ -13,6 +14,16 @@ interface Props {
|
|
|
13
14
|
fullscreen: boolean;
|
|
14
15
|
/** Whether the formatting marks (pilcrows) are shown in the document. */
|
|
15
16
|
marksVisible: boolean;
|
|
17
|
+
/** Whether the navigation panel with the headings is open. */
|
|
18
|
+
outlineVisible: boolean;
|
|
19
|
+
/** Whether the host keeps comments (`v-model:comments`); the comment buttons are hidden otherwise. */
|
|
20
|
+
commentsEnabled: boolean;
|
|
21
|
+
/** Whether the comments panel is open. */
|
|
22
|
+
commentsVisible: boolean;
|
|
23
|
+
/** Whether edits are recorded as tracked changes. */
|
|
24
|
+
trackChanges: boolean;
|
|
25
|
+
/** Whether the tracked changes panel is open. */
|
|
26
|
+
changesVisible: boolean;
|
|
16
27
|
/** Current page settings, edited in the page setup popover. */
|
|
17
28
|
page: PageSettings;
|
|
18
29
|
/** Whether the ruler is shown above the sheet. */
|
|
@@ -23,8 +34,14 @@ interface Props {
|
|
|
23
34
|
state: EditorUiState;
|
|
24
35
|
/** Whether images are being uploaded, shown on the upload button. */
|
|
25
36
|
uploading: boolean;
|
|
37
|
+
/** Template variables offered by the variable menu; the menu is hidden without any. */
|
|
38
|
+
variables: ReadonlyArray<TemplateVariable>;
|
|
26
39
|
}
|
|
27
|
-
declare
|
|
40
|
+
declare var __VLS_604: {};
|
|
41
|
+
type __VLS_Slots = {} & {
|
|
42
|
+
default?: (props: typeof __VLS_604) => any;
|
|
43
|
+
};
|
|
44
|
+
declare const __VLS_base: import("vue").DefineComponent<Props, {
|
|
28
45
|
/** Opens the link popover. */
|
|
29
46
|
openLink: () => void;
|
|
30
47
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
@@ -38,5 +55,11 @@ declare const __VLS_export: import("vue").DefineComponent<Props, {
|
|
|
38
55
|
onInsertImages?: ((files: File[]) => any) | undefined;
|
|
39
56
|
"onUpdate:page"?: ((page: PageSettings) => any) | undefined;
|
|
40
57
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
58
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
41
59
|
declare const _default: typeof __VLS_export;
|
|
42
60
|
export default _default;
|
|
61
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
62
|
+
new (): {
|
|
63
|
+
$slots: S;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Comments on parts of a document. The document HTML only keeps the anchors, `<span data-comment="id">`; the comments
|
|
3
|
+
* themselves are plain data the host stores next to the document with `v-model:comments`.
|
|
4
|
+
*/
|
|
5
|
+
/** A reply in the thread of a comment. */
|
|
6
|
+
export interface DocumentCommentReply {
|
|
7
|
+
/** Unique id of the reply. */
|
|
8
|
+
id: string;
|
|
9
|
+
/** Text of the reply. */
|
|
10
|
+
text: string;
|
|
11
|
+
/** Name of the person who wrote it, when the host knows it. */
|
|
12
|
+
author?: string;
|
|
13
|
+
/** When it was written, as an ISO 8601 string. */
|
|
14
|
+
createdAt: string;
|
|
15
|
+
}
|
|
16
|
+
/** A comment anchored to a span of the document text. */
|
|
17
|
+
export interface DocumentComment extends DocumentCommentReply {
|
|
18
|
+
/** Whether the discussion is closed; resolved comments keep their anchor but are not highlighted. */
|
|
19
|
+
resolved?: boolean;
|
|
20
|
+
/** Replies in the order they were written. */
|
|
21
|
+
replies?: DocumentCommentReply[];
|
|
22
|
+
}
|
|
23
|
+
/** A new random id for a comment or a reply, usable as an HTML attribute value. */
|
|
24
|
+
export declare const createCommentId: () => string;
|
|
25
|
+
/** Comments in the order their anchors appear in the document; comments whose text was deleted come last. */
|
|
26
|
+
export declare const sortComments: (comments: readonly DocumentComment[], anchoredIds: readonly string[]) => DocumentComment[];
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { NumberWordsLocale } from './numbers';
|
|
2
|
+
/** A date as `dd.mm.yyyy`, the short form of Uzbek and Russian documents. */
|
|
3
|
+
export declare const formatShortDate: (date: Date) => string;
|
|
4
|
+
/**
|
|
5
|
+
* A date written out as official documents do: `2026-yil 14-sentabr`, `2026 йил 14 сентябрь`, `14 сентября 2026 г.`
|
|
6
|
+
* or `14 September 2026`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const formatLongDate: (date: Date, locale?: NumberWordsLocale) => string;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** What changed between two versions. */
|
|
2
|
+
export interface DocumentComparison {
|
|
3
|
+
/** Display HTML of the new version with insertions and deletions marked. */
|
|
4
|
+
html: string;
|
|
5
|
+
/** Number of inserted words, and of words in inserted blocks. */
|
|
6
|
+
insertions: number;
|
|
7
|
+
/** Number of deleted words, and of words in deleted blocks. */
|
|
8
|
+
deletions: number;
|
|
9
|
+
}
|
|
10
|
+
/** Compares two versions of a document and marks what was inserted and deleted in the new one. */
|
|
11
|
+
export declare const compareDocuments: (before: string, after: string) => DocumentComparison;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { EditorLabelKey, EditorLocaleCode } from './labels';
|
|
2
|
+
import type { TemplateVariable } from './templates';
|
|
3
|
+
/** Built-in document templates. */
|
|
4
|
+
export type DocumentTemplateId = 'letter' | 'order' | 'application' | 'certificate' | 'act';
|
|
5
|
+
/** A document template ready to be inserted into the editor. */
|
|
6
|
+
export interface DocumentTemplate {
|
|
7
|
+
/** Template identifier. */
|
|
8
|
+
id: DocumentTemplateId;
|
|
9
|
+
/** Document HTML with template variables. */
|
|
10
|
+
html: string;
|
|
11
|
+
/** Variables the template uses, with labels in the requested language. */
|
|
12
|
+
variables: TemplateVariable[];
|
|
13
|
+
}
|
|
14
|
+
/** Every built-in template with its menu label, in the order the menu lists them. */
|
|
15
|
+
export declare const DOCUMENT_TEMPLATES: ReadonlyArray<{
|
|
16
|
+
id: DocumentTemplateId;
|
|
17
|
+
label: EditorLabelKey;
|
|
18
|
+
}>;
|
|
19
|
+
/** Label of a built-in template variable in the editor's language, or `undefined` for other names. */
|
|
20
|
+
export declare const templateVariableLabel: (name: string, locale: EditorLocaleCode) => string | undefined;
|
|
21
|
+
/** A built-in document template in the editor's language, with the variables it uses. */
|
|
22
|
+
export declare const getDocumentTemplate: (id: DocumentTemplateId, locale?: EditorLocaleCode) => DocumentTemplate;
|