@w100n/documents 0.4.0 → 0.10.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/dist/SheetView-3XTEV2VT.css +319 -0
- package/dist/SheetView-3XTEV2VT.css.map +1 -0
- package/dist/SheetView-JYH2ZUZF.js +928 -0
- package/dist/SheetView-JYH2ZUZF.js.map +1 -0
- package/dist/TextEditor-X3X62R46.js +982 -0
- package/dist/TextEditor-X3X62R46.js.map +1 -0
- package/dist/caveat-cyrillic-XVO43JCM.woff2 +0 -0
- package/dist/caveat-latin-IUBKKMHQ.woff2 +0 -0
- package/dist/caveat-latin-ext-5S7R5SZN.woff2 +0 -0
- package/dist/chunk-CE3AADY6.js +3447 -0
- package/dist/chunk-CE3AADY6.js.map +1 -0
- package/dist/chunk-ISOOUYLI.js +150 -0
- package/dist/chunk-ISOOUYLI.js.map +1 -0
- package/dist/{chunk-KEV4R7W5.js → chunk-K364NAYP.js} +4 -1
- package/dist/chunk-K364NAYP.js.map +1 -0
- package/dist/chunk-QDH7EZAF.js +27 -0
- package/dist/chunk-QDH7EZAF.js.map +1 -0
- package/dist/chunk-SVRYWMES.js +196 -0
- package/dist/chunk-SVRYWMES.js.map +1 -0
- package/dist/chunk-TDP6OJET.js +31 -0
- package/dist/chunk-TDP6OJET.js.map +1 -0
- package/dist/chunk-TNSN4ZQ5.js +2909 -0
- package/dist/chunk-TNSN4ZQ5.js.map +1 -0
- package/dist/collab.cjs +6312 -0
- package/dist/collab.cjs.map +1 -0
- package/dist/collab.d.cts +39 -0
- package/dist/collab.d.ts +39 -0
- package/dist/collab.js +30 -0
- package/dist/collab.js.map +1 -0
- package/dist/grid-EI5JNZAA.js +88 -0
- package/dist/grid-EI5JNZAA.js.map +1 -0
- package/dist/index.cjs +12134 -457
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +2999 -95
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +143 -6
- package/dist/index.d.ts +143 -6
- package/dist/index.js +3377 -450
- package/dist/index.js.map +1 -1
- package/dist/memory.cjs +59 -7
- package/dist/memory.cjs.map +1 -1
- package/dist/memory.d.cts +7 -2
- package/dist/memory.d.ts +7 -2
- package/dist/memory.js +57 -8
- package/dist/memory.js.map +1 -1
- package/dist/pdfWrite-EM6GJDBF.js +76 -0
- package/dist/pdfWrite-EM6GJDBF.js.map +1 -0
- package/dist/types-B5oF25dn.d.cts +165 -0
- package/dist/types-B5oF25dn.d.ts +165 -0
- package/dist/write-DaVtTJCS.d.cts +6 -0
- package/dist/write-DaVtTJCS.d.ts +6 -0
- package/package.json +45 -3
- package/dist/chunk-KEV4R7W5.js.map +0 -1
- package/dist/types-DshXPnWA.d.cts +0 -62
- package/dist/types-DshXPnWA.d.ts +0 -62
package/dist/memory.cjs
CHANGED
|
@@ -33,6 +33,9 @@ var byExtension = {
|
|
|
33
33
|
pdf: "pdf",
|
|
34
34
|
xlsx: "sheet",
|
|
35
35
|
csv: "sheet",
|
|
36
|
+
xls: "sheet",
|
|
37
|
+
ods: "sheet",
|
|
38
|
+
tsv: "sheet",
|
|
36
39
|
html: "slides",
|
|
37
40
|
htm: "slides"
|
|
38
41
|
};
|
|
@@ -50,13 +53,19 @@ function kindOf(name, mimeType) {
|
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
// src/memory.ts
|
|
56
|
+
var mimes = { pdf: "application/pdf", docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", md: "text/markdown" };
|
|
53
57
|
var encode = (bytes) => typeof bytes === "string" ? new TextEncoder().encode(bytes).buffer : bytes;
|
|
54
|
-
function memoryHost({ me, spaces, files }) {
|
|
58
|
+
function memoryHost({ me, spaces, files, collab }) {
|
|
55
59
|
const find = (id) => {
|
|
56
60
|
const file = files.find((item) => item.id === id);
|
|
57
61
|
if (!file) throw new Error("document not found");
|
|
58
62
|
return file;
|
|
59
63
|
};
|
|
64
|
+
const own = (file, commentId) => {
|
|
65
|
+
const found = file.comments?.find((c) => c.id === commentId);
|
|
66
|
+
if (!found || found.author.id !== me.id) throw new Error("only the author changes a comment");
|
|
67
|
+
return found;
|
|
68
|
+
};
|
|
60
69
|
const summary = (file) => ({
|
|
61
70
|
id: file.id,
|
|
62
71
|
spaceId: file.spaceId,
|
|
@@ -67,30 +76,73 @@ function memoryHost({ me, spaces, files }) {
|
|
|
67
76
|
updatedBy: me,
|
|
68
77
|
folder: file.folder ?? null
|
|
69
78
|
});
|
|
79
|
+
const archive = (file, bytes, note) => {
|
|
80
|
+
const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? "2026-10-19T09:00:00Z", bytes: file.bytes, note: file.note }, ...file.versions ?? []];
|
|
81
|
+
const version = `v${versions.length + 1}`;
|
|
82
|
+
Object.assign(file, { versions, version, bytes, note, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
83
|
+
return version;
|
|
84
|
+
};
|
|
70
85
|
return {
|
|
71
86
|
me,
|
|
87
|
+
...collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {},
|
|
72
88
|
spaces: async () => spaces,
|
|
73
89
|
documents: async (spaceId) => files.filter((file) => file.spaceId === spaceId && kindOf(file.name)).map(summary),
|
|
74
|
-
document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),
|
|
90
|
+
document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),
|
|
75
91
|
versions: async (id) => {
|
|
76
92
|
const file = find(id);
|
|
77
93
|
return [
|
|
78
|
-
{ id: "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },
|
|
94
|
+
{ id: file.version ?? "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },
|
|
79
95
|
...(file.versions ?? []).map((v) => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false }))
|
|
80
96
|
];
|
|
81
97
|
},
|
|
82
98
|
content: async (id, versionId) => {
|
|
83
99
|
const file = find(id);
|
|
84
|
-
const old = versionId && versionId !== "current" ? file.versions?.find((v) => v.id === versionId) : void 0;
|
|
100
|
+
const old = versionId && versionId !== "current" && versionId !== file.version ? file.versions?.find((v) => v.id === versionId) : void 0;
|
|
85
101
|
return encode(old ? old.bytes : file.bytes);
|
|
86
102
|
},
|
|
87
103
|
restore: async (id, versionId) => {
|
|
88
104
|
const file = find(id);
|
|
89
105
|
const old = file.versions?.find((v) => v.id === versionId);
|
|
90
106
|
if (!old) throw new Error("version not found");
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
107
|
+
archive(file, old.bytes);
|
|
108
|
+
},
|
|
109
|
+
save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),
|
|
110
|
+
signatures: async (id) => [...find(id).signatures ?? []].reverse(),
|
|
111
|
+
sign: async (id, entry) => {
|
|
112
|
+
const file = find(id);
|
|
113
|
+
const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: (/* @__PURE__ */ new Date()).toISOString(), ...entry };
|
|
114
|
+
file.signatures = [...file.signatures ?? [], signature];
|
|
115
|
+
return signature;
|
|
116
|
+
},
|
|
117
|
+
comments: async (id) => [...find(id).comments ?? []],
|
|
118
|
+
comment: async (id, entry) => {
|
|
119
|
+
const file = find(id);
|
|
120
|
+
let n = (file.comments?.length ?? 0) + 1;
|
|
121
|
+
while (file.comments?.some((c) => c.id === `c${n}`)) n++;
|
|
122
|
+
const made = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: (/* @__PURE__ */ new Date()).toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };
|
|
123
|
+
file.comments = [...file.comments ?? [], made];
|
|
124
|
+
return made;
|
|
125
|
+
},
|
|
126
|
+
resolveComment: async (id, commentId, resolved) => {
|
|
127
|
+
const file = find(id);
|
|
128
|
+
file.comments = (file.comments ?? []).map((c) => c.id === commentId ? { ...c, resolved } : c);
|
|
129
|
+
},
|
|
130
|
+
editComment: async (id, commentId, body) => {
|
|
131
|
+
const file = find(id);
|
|
132
|
+
const mine = own(file, commentId);
|
|
133
|
+
const edited = { ...mine, body };
|
|
134
|
+
file.comments = file.comments.map((c) => c === mine ? edited : c);
|
|
135
|
+
return edited;
|
|
136
|
+
},
|
|
137
|
+
deleteComment: async (id, commentId) => {
|
|
138
|
+
const file = find(id);
|
|
139
|
+
own(file, commentId);
|
|
140
|
+
file.comments = file.comments.filter((c) => c.id !== commentId && c.replyTo !== commentId);
|
|
141
|
+
},
|
|
142
|
+
exportAs: async (id, format) => {
|
|
143
|
+
const file = find(id);
|
|
144
|
+
if ((format === "md" ? "markdown" : format) !== kindOf(file.name)) throw new Error("this format needs a converter on the host");
|
|
145
|
+
return new Blob([encode(file.bytes)], { type: mimes[format] });
|
|
94
146
|
}
|
|
95
147
|
};
|
|
96
148
|
}
|
package/dist/memory.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/memory.ts","../src/kinds.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { DocumentsHost, Person, Rights, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n};\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files }: { me: Person; spaces: Space[]; files: MemoryFile[] }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n return {\n me,\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),\n versions: async id => {\n const file = find(id);\n return [\n { id: 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n file.versions = [{ id: `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes }, ...(file.versions ?? [])];\n file.bytes = old.bytes;\n file.updatedAt = new Date().toISOString();\n },\n };\n}\n","import type { DocumentKind } from './types';\n\nconst byExtension: Record<string, DocumentKind> = {\n docx: 'docx', md: 'markdown', markdown: 'markdown', pdf: 'pdf', xlsx: 'sheet', csv: 'sheet', html: 'slides', htm: 'slides',\n};\n\nconst byMime: Record<string, DocumentKind> = {\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',\n 'text/markdown': 'markdown',\n 'application/pdf': 'pdf',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'sheet',\n 'text/csv': 'sheet',\n 'text/html': 'slides',\n};\n\nexport const kinds: DocumentKind[] = ['docx', 'markdown', 'pdf', 'sheet', 'slides'];\n\nexport function kindOf(name: string, mimeType?: string | null): DocumentKind | null {\n const extension = name.includes('.') ? name.split('.').pop()!.toLowerCase() : '';\n return byExtension[extension] ?? (mimeType ? byMime[mimeType.split(';')[0].trim().toLowerCase()] : undefined) ?? null;\n}\n\nexport function matches(doc: { name: string; kind: DocumentKind }, query: string, kind: DocumentKind | 'all') {\n const words = query.toLocaleLowerCase().split(/\\s+/).filter(Boolean);\n return (kind === 'all' || doc.kind === kind) && words.every(word => doc.name.toLocaleLowerCase().includes(word));\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/memory.ts","../src/kinds.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { Comment, DocumentsHost, Person, Rights, Signature, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n version?: string;\n note?: string;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n signatures?: Signature[];\n comments?: Comment[];\n};\n\nconst mimes = { pdf: 'application/pdf', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', md: 'text/markdown' };\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files, collab }: { me: Person; spaces: Space[]; files: MemoryFile[]; collab?: string }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const own = (file: MemoryFile, commentId: string) => {\n const found = file.comments?.find(c => c.id === commentId);\n if (!found || found.author.id !== me.id) throw new Error('only the author changes a comment');\n return found;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n const archive = (file: MemoryFile, bytes: Bytes, note?: string) => {\n const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes, note: file.note }, ...(file.versions ?? [])];\n const version = `v${versions.length + 1}`;\n Object.assign(file, { versions, version, bytes, note, updatedAt: new Date().toISOString() });\n return version;\n };\n return {\n me,\n ...(collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {}),\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),\n versions: async id => {\n const file = find(id);\n return [\n { id: file.version ?? 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' && versionId !== file.version ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n archive(file, old.bytes);\n },\n save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),\n signatures: async id => [...(find(id).signatures ?? [])].reverse(),\n sign: async (id, entry) => {\n const file = find(id);\n const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: new Date().toISOString(), ...entry };\n file.signatures = [...(file.signatures ?? []), signature];\n return signature;\n },\n comments: async id => [...(find(id).comments ?? [])],\n comment: async (id, entry) => {\n const file = find(id);\n let n = (file.comments?.length ?? 0) + 1;\n while (file.comments?.some(c => c.id === `c${n}`)) n++;\n const made: Comment = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: new Date().toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };\n file.comments = [...(file.comments ?? []), made];\n return made;\n },\n resolveComment: async (id, commentId, resolved) => {\n const file = find(id);\n file.comments = (file.comments ?? []).map(c => c.id === commentId ? { ...c, resolved } : c);\n },\n editComment: async (id, commentId, body) => {\n const file = find(id);\n const mine = own(file, commentId);\n const edited = { ...mine, body };\n file.comments = file.comments!.map(c => c === mine ? edited : c);\n return edited;\n },\n deleteComment: async (id, commentId) => {\n const file = find(id);\n own(file, commentId);\n file.comments = file.comments!.filter(c => c.id !== commentId && c.replyTo !== commentId);\n },\n exportAs: async (id, format) => {\n const file = find(id);\n if ((format === 'md' ? 'markdown' : format) !== kindOf(file.name)) throw new Error('this format needs a converter on the host');\n return new Blob([encode(file.bytes)], { type: mimes[format] });\n },\n };\n}\n","import type { DocumentKind } from './types';\n\nconst byExtension: Record<string, DocumentKind> = {\n docx: 'docx', md: 'markdown', markdown: 'markdown', pdf: 'pdf', xlsx: 'sheet', csv: 'sheet', xls: 'sheet', ods: 'sheet', tsv: 'sheet', html: 'slides', htm: 'slides',\n};\n\nconst byMime: Record<string, DocumentKind> = {\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',\n 'text/markdown': 'markdown',\n 'application/pdf': 'pdf',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'sheet',\n 'text/csv': 'sheet',\n 'text/html': 'slides',\n};\n\nexport const kinds: DocumentKind[] = ['docx', 'markdown', 'pdf', 'sheet', 'slides'];\n\nexport function kindOf(name: string, mimeType?: string | null): DocumentKind | null {\n const extension = name.includes('.') ? name.split('.').pop()!.toLowerCase() : '';\n return byExtension[extension] ?? (mimeType ? byMime[mimeType.split(';')[0].trim().toLowerCase()] : undefined) ?? null;\n}\n\nexport function matches(doc: { name: string; kind: DocumentKind }, query: string, kind: DocumentKind | 'all') {\n const words = query.toLocaleLowerCase().split(/\\s+/).filter(Boolean);\n return (kind === 'all' || doc.kind === kind) && words.every(word => doc.name.toLocaleLowerCase().includes(word));\n}\n"],"mappings":"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","names":[]}
|
package/dist/memory.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as Rights,
|
|
1
|
+
import { R as Rights, S as Signature, C as Comment, h as Person, j as Space, D as DocumentsHost } from './types-B5oF25dn.cjs';
|
|
2
2
|
|
|
3
3
|
type Bytes = ArrayBuffer | string;
|
|
4
4
|
type MemoryFile = {
|
|
@@ -7,6 +7,8 @@ type MemoryFile = {
|
|
|
7
7
|
name: string;
|
|
8
8
|
folder?: string;
|
|
9
9
|
bytes: Bytes;
|
|
10
|
+
version?: string;
|
|
11
|
+
note?: string;
|
|
10
12
|
updatedAt?: string;
|
|
11
13
|
rights?: Partial<Rights>;
|
|
12
14
|
versions?: {
|
|
@@ -15,11 +17,14 @@ type MemoryFile = {
|
|
|
15
17
|
bytes: Bytes;
|
|
16
18
|
note?: string;
|
|
17
19
|
}[];
|
|
20
|
+
signatures?: Signature[];
|
|
21
|
+
comments?: Comment[];
|
|
18
22
|
};
|
|
19
|
-
declare function memoryHost({ me, spaces, files }: {
|
|
23
|
+
declare function memoryHost({ me, spaces, files, collab }: {
|
|
20
24
|
me: Person;
|
|
21
25
|
spaces: Space[];
|
|
22
26
|
files: MemoryFile[];
|
|
27
|
+
collab?: string;
|
|
23
28
|
}): DocumentsHost;
|
|
24
29
|
|
|
25
30
|
export { type MemoryFile, memoryHost };
|
package/dist/memory.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as Rights,
|
|
1
|
+
import { R as Rights, S as Signature, C as Comment, h as Person, j as Space, D as DocumentsHost } from './types-B5oF25dn.js';
|
|
2
2
|
|
|
3
3
|
type Bytes = ArrayBuffer | string;
|
|
4
4
|
type MemoryFile = {
|
|
@@ -7,6 +7,8 @@ type MemoryFile = {
|
|
|
7
7
|
name: string;
|
|
8
8
|
folder?: string;
|
|
9
9
|
bytes: Bytes;
|
|
10
|
+
version?: string;
|
|
11
|
+
note?: string;
|
|
10
12
|
updatedAt?: string;
|
|
11
13
|
rights?: Partial<Rights>;
|
|
12
14
|
versions?: {
|
|
@@ -15,11 +17,14 @@ type MemoryFile = {
|
|
|
15
17
|
bytes: Bytes;
|
|
16
18
|
note?: string;
|
|
17
19
|
}[];
|
|
20
|
+
signatures?: Signature[];
|
|
21
|
+
comments?: Comment[];
|
|
18
22
|
};
|
|
19
|
-
declare function memoryHost({ me, spaces, files }: {
|
|
23
|
+
declare function memoryHost({ me, spaces, files, collab }: {
|
|
20
24
|
me: Person;
|
|
21
25
|
spaces: Space[];
|
|
22
26
|
files: MemoryFile[];
|
|
27
|
+
collab?: string;
|
|
23
28
|
}): DocumentsHost;
|
|
24
29
|
|
|
25
30
|
export { type MemoryFile, memoryHost };
|
package/dist/memory.js
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import {
|
|
3
3
|
kindOf
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-K364NAYP.js";
|
|
5
5
|
|
|
6
6
|
// src/memory.ts
|
|
7
|
+
var mimes = { pdf: "application/pdf", docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", md: "text/markdown" };
|
|
7
8
|
var encode = (bytes) => typeof bytes === "string" ? new TextEncoder().encode(bytes).buffer : bytes;
|
|
8
|
-
function memoryHost({ me, spaces, files }) {
|
|
9
|
+
function memoryHost({ me, spaces, files, collab }) {
|
|
9
10
|
const find = (id) => {
|
|
10
11
|
const file = files.find((item) => item.id === id);
|
|
11
12
|
if (!file) throw new Error("document not found");
|
|
12
13
|
return file;
|
|
13
14
|
};
|
|
15
|
+
const own = (file, commentId) => {
|
|
16
|
+
const found = file.comments?.find((c) => c.id === commentId);
|
|
17
|
+
if (!found || found.author.id !== me.id) throw new Error("only the author changes a comment");
|
|
18
|
+
return found;
|
|
19
|
+
};
|
|
14
20
|
const summary = (file) => ({
|
|
15
21
|
id: file.id,
|
|
16
22
|
spaceId: file.spaceId,
|
|
@@ -21,30 +27,73 @@ function memoryHost({ me, spaces, files }) {
|
|
|
21
27
|
updatedBy: me,
|
|
22
28
|
folder: file.folder ?? null
|
|
23
29
|
});
|
|
30
|
+
const archive = (file, bytes, note) => {
|
|
31
|
+
const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? "2026-10-19T09:00:00Z", bytes: file.bytes, note: file.note }, ...file.versions ?? []];
|
|
32
|
+
const version = `v${versions.length + 1}`;
|
|
33
|
+
Object.assign(file, { versions, version, bytes, note, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
34
|
+
return version;
|
|
35
|
+
};
|
|
24
36
|
return {
|
|
25
37
|
me,
|
|
38
|
+
...collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {},
|
|
26
39
|
spaces: async () => spaces,
|
|
27
40
|
documents: async (spaceId) => files.filter((file) => file.spaceId === spaceId && kindOf(file.name)).map(summary),
|
|
28
|
-
document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),
|
|
41
|
+
document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),
|
|
29
42
|
versions: async (id) => {
|
|
30
43
|
const file = find(id);
|
|
31
44
|
return [
|
|
32
|
-
{ id: "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },
|
|
45
|
+
{ id: file.version ?? "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },
|
|
33
46
|
...(file.versions ?? []).map((v) => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false }))
|
|
34
47
|
];
|
|
35
48
|
},
|
|
36
49
|
content: async (id, versionId) => {
|
|
37
50
|
const file = find(id);
|
|
38
|
-
const old = versionId && versionId !== "current" ? file.versions?.find((v) => v.id === versionId) : void 0;
|
|
51
|
+
const old = versionId && versionId !== "current" && versionId !== file.version ? file.versions?.find((v) => v.id === versionId) : void 0;
|
|
39
52
|
return encode(old ? old.bytes : file.bytes);
|
|
40
53
|
},
|
|
41
54
|
restore: async (id, versionId) => {
|
|
42
55
|
const file = find(id);
|
|
43
56
|
const old = file.versions?.find((v) => v.id === versionId);
|
|
44
57
|
if (!old) throw new Error("version not found");
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
archive(file, old.bytes);
|
|
59
|
+
},
|
|
60
|
+
save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),
|
|
61
|
+
signatures: async (id) => [...find(id).signatures ?? []].reverse(),
|
|
62
|
+
sign: async (id, entry) => {
|
|
63
|
+
const file = find(id);
|
|
64
|
+
const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: (/* @__PURE__ */ new Date()).toISOString(), ...entry };
|
|
65
|
+
file.signatures = [...file.signatures ?? [], signature];
|
|
66
|
+
return signature;
|
|
67
|
+
},
|
|
68
|
+
comments: async (id) => [...find(id).comments ?? []],
|
|
69
|
+
comment: async (id, entry) => {
|
|
70
|
+
const file = find(id);
|
|
71
|
+
let n = (file.comments?.length ?? 0) + 1;
|
|
72
|
+
while (file.comments?.some((c) => c.id === `c${n}`)) n++;
|
|
73
|
+
const made = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: (/* @__PURE__ */ new Date()).toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };
|
|
74
|
+
file.comments = [...file.comments ?? [], made];
|
|
75
|
+
return made;
|
|
76
|
+
},
|
|
77
|
+
resolveComment: async (id, commentId, resolved) => {
|
|
78
|
+
const file = find(id);
|
|
79
|
+
file.comments = (file.comments ?? []).map((c) => c.id === commentId ? { ...c, resolved } : c);
|
|
80
|
+
},
|
|
81
|
+
editComment: async (id, commentId, body) => {
|
|
82
|
+
const file = find(id);
|
|
83
|
+
const mine = own(file, commentId);
|
|
84
|
+
const edited = { ...mine, body };
|
|
85
|
+
file.comments = file.comments.map((c) => c === mine ? edited : c);
|
|
86
|
+
return edited;
|
|
87
|
+
},
|
|
88
|
+
deleteComment: async (id, commentId) => {
|
|
89
|
+
const file = find(id);
|
|
90
|
+
own(file, commentId);
|
|
91
|
+
file.comments = file.comments.filter((c) => c.id !== commentId && c.replyTo !== commentId);
|
|
92
|
+
},
|
|
93
|
+
exportAs: async (id, format) => {
|
|
94
|
+
const file = find(id);
|
|
95
|
+
if ((format === "md" ? "markdown" : format) !== kindOf(file.name)) throw new Error("this format needs a converter on the host");
|
|
96
|
+
return new Blob([encode(file.bytes)], { type: mimes[format] });
|
|
48
97
|
}
|
|
49
98
|
};
|
|
50
99
|
}
|
package/dist/memory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/memory.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { DocumentsHost, Person, Rights, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n};\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files }: { me: Person; spaces: Space[]; files: MemoryFile[] }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n return {\n me,\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),\n versions: async id => {\n const file = find(id);\n return [\n { id: 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n file.
|
|
1
|
+
{"version":3,"sources":["../src/memory.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { Comment, DocumentsHost, Person, Rights, Signature, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n version?: string;\n note?: string;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n signatures?: Signature[];\n comments?: Comment[];\n};\n\nconst mimes = { pdf: 'application/pdf', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', md: 'text/markdown' };\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files, collab }: { me: Person; spaces: Space[]; files: MemoryFile[]; collab?: string }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const own = (file: MemoryFile, commentId: string) => {\n const found = file.comments?.find(c => c.id === commentId);\n if (!found || found.author.id !== me.id) throw new Error('only the author changes a comment');\n return found;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n const archive = (file: MemoryFile, bytes: Bytes, note?: string) => {\n const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes, note: file.note }, ...(file.versions ?? [])];\n const version = `v${versions.length + 1}`;\n Object.assign(file, { versions, version, bytes, note, updatedAt: new Date().toISOString() });\n return version;\n };\n return {\n me,\n ...(collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {}),\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),\n versions: async id => {\n const file = find(id);\n return [\n { id: file.version ?? 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' && versionId !== file.version ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n archive(file, old.bytes);\n },\n save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),\n signatures: async id => [...(find(id).signatures ?? [])].reverse(),\n sign: async (id, entry) => {\n const file = find(id);\n const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: new Date().toISOString(), ...entry };\n file.signatures = [...(file.signatures ?? []), signature];\n return signature;\n },\n comments: async id => [...(find(id).comments ?? [])],\n comment: async (id, entry) => {\n const file = find(id);\n let n = (file.comments?.length ?? 0) + 1;\n while (file.comments?.some(c => c.id === `c${n}`)) n++;\n const made: Comment = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: new Date().toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };\n file.comments = [...(file.comments ?? []), made];\n return made;\n },\n resolveComment: async (id, commentId, resolved) => {\n const file = find(id);\n file.comments = (file.comments ?? []).map(c => c.id === commentId ? { ...c, resolved } : c);\n },\n editComment: async (id, commentId, body) => {\n const file = find(id);\n const mine = own(file, commentId);\n const edited = { ...mine, body };\n file.comments = file.comments!.map(c => c === mine ? edited : c);\n return edited;\n },\n deleteComment: async (id, commentId) => {\n const file = find(id);\n own(file, commentId);\n file.comments = file.comments!.filter(c => c.id !== commentId && c.replyTo !== commentId);\n },\n exportAs: async (id, format) => {\n const file = find(id);\n if ((format === 'md' ? 'markdown' : format) !== kindOf(file.name)) throw new Error('this format needs a converter on the host');\n return new Blob([encode(file.bytes)], { type: mimes[format] });\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// src/viewers/pdfWrite.ts
|
|
4
|
+
import { init } from "@embedpdf/pdfium";
|
|
5
|
+
import { PdfiumNative } from "@embedpdf/engines/pdfium";
|
|
6
|
+
import { PDF_FORM_FIELD_TYPE, PdfAnnotationSubtype, PdfBlendMode } from "@embedpdf/models";
|
|
7
|
+
var engine = null;
|
|
8
|
+
var rect = (box) => ({ origin: { x: box.x, y: box.y }, size: { width: box.w, height: box.h } });
|
|
9
|
+
var around = (boxes) => {
|
|
10
|
+
const x = Math.min(...boxes.map((b) => b.x));
|
|
11
|
+
const y = Math.min(...boxes.map((b) => b.y));
|
|
12
|
+
return { x, y, w: Math.max(...boxes.map((b) => b.x + b.w)) - x, h: Math.max(...boxes.map((b) => b.y + b.h)) - y };
|
|
13
|
+
};
|
|
14
|
+
var png = (url) => Uint8Array.from(atob(url.slice(url.indexOf(",") + 1)), (c) => c.charCodeAt(0)).buffer;
|
|
15
|
+
var types = { highlight: PdfAnnotationSubtype.HIGHLIGHT, underline: PdfAnnotationSubtype.UNDERLINE, strike: PdfAnnotationSubtype.STRIKEOUT };
|
|
16
|
+
function annotation(mark) {
|
|
17
|
+
const base = { id: mark.id, pageIndex: mark.page - 1, author: mark.author, created: new Date(mark.at), modified: new Date(mark.at) };
|
|
18
|
+
if (mark.kind === "note") {
|
|
19
|
+
return { ...base, type: PdfAnnotationSubtype.TEXT, rect: rect({ ...mark.spot, w: 20, h: 20 }), contents: mark.text, strokeColor: mark.color, opacity: 1 };
|
|
20
|
+
}
|
|
21
|
+
if (mark.kind === "ink") {
|
|
22
|
+
const spread = mark.width / 2 + 1;
|
|
23
|
+
const bounds = around(mark.lines.flat().map((p) => ({ x: p.x - spread, y: p.y - spread, w: spread * 2, h: spread * 2 })));
|
|
24
|
+
return { ...base, type: PdfAnnotationSubtype.INK, rect: rect(bounds), inkList: mark.lines.map((points) => ({ points })), strokeColor: mark.color, strokeWidth: mark.width, opacity: 1 };
|
|
25
|
+
}
|
|
26
|
+
if (mark.kind === "sign") return { ...base, type: PdfAnnotationSubtype.STAMP, rect: rect(mark.box) };
|
|
27
|
+
return {
|
|
28
|
+
...base,
|
|
29
|
+
type: types[mark.kind],
|
|
30
|
+
rect: rect(around(mark.rects)),
|
|
31
|
+
segmentRects: mark.rects.map(rect),
|
|
32
|
+
contents: mark.text,
|
|
33
|
+
strokeColor: mark.color,
|
|
34
|
+
opacity: 1,
|
|
35
|
+
...mark.kind === "highlight" ? { blendMode: PdfBlendMode.Multiply } : {}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function write(bytes, marks, fields) {
|
|
39
|
+
engine ?? (engine = init({}).then((module) => new PdfiumNative(module)));
|
|
40
|
+
const pdfium = await engine;
|
|
41
|
+
const doc = await pdfium.openDocumentBuffer({ id: Math.random().toString(36).slice(2), content: bytes.slice(0) }).toPromise();
|
|
42
|
+
try {
|
|
43
|
+
for (const n of new Set(fields.map((field) => field.page))) {
|
|
44
|
+
const page = doc.pages[n - 1];
|
|
45
|
+
const widgets = await pdfium.getPageAnnoWidgets(doc, page).toPromise();
|
|
46
|
+
for (const field of fields.filter((f) => f.page === n)) {
|
|
47
|
+
const centre = (r) => Math.hypot(r.origin.x + r.size.width / 2 - field.box.x - field.box.w / 2, r.origin.y + r.size.height / 2 - field.box.y - field.box.h / 2);
|
|
48
|
+
const widget = widgets.filter((w) => w.field.name === field.name).sort((a, b) => centre(a.rect) - centre(b.rect))[0];
|
|
49
|
+
if (!widget) continue;
|
|
50
|
+
const { type } = widget.field;
|
|
51
|
+
if (type === PDF_FORM_FIELD_TYPE.TEXTFIELD) {
|
|
52
|
+
await pdfium.setFormFieldValue(doc, page, widget, { kind: "text", text: String(field.value) }).toPromise();
|
|
53
|
+
} else if (type === PDF_FORM_FIELD_TYPE.CHECKBOX || type === PDF_FORM_FIELD_TYPE.RADIOBUTTON && field.value === true) {
|
|
54
|
+
await pdfium.setFormFieldValue(doc, page, widget, { kind: "checked", checked: field.value === true }).toPromise();
|
|
55
|
+
} else if ("options" in widget.field && Array.isArray(field.value)) {
|
|
56
|
+
for (const [index, option] of widget.field.options.entries()) {
|
|
57
|
+
const wanted = field.value.includes(option.label);
|
|
58
|
+
if (wanted !== option.isSelected) await pdfium.setFormFieldValue(doc, page, widget, { kind: "selection", index, isSelected: wanted }).toPromise();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
for (const mark of marks) {
|
|
64
|
+
const page = doc.pages[mark.page - 1];
|
|
65
|
+
if (mark.kind === "sign") await pdfium.createPageAnnotation(doc, page, annotation(mark), { data: png(mark.image), mimeType: "image/png" }).toPromise();
|
|
66
|
+
else await pdfium.createPageAnnotation(doc, page, annotation(mark)).toPromise();
|
|
67
|
+
}
|
|
68
|
+
return await pdfium.saveAsCopy(doc).toPromise();
|
|
69
|
+
} finally {
|
|
70
|
+
await pdfium.closeDocument(doc).toPromise();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export {
|
|
74
|
+
write
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=pdfWrite-EM6GJDBF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/viewers/pdfWrite.ts"],"sourcesContent":["import { init } from '@embedpdf/pdfium';\nimport { PdfiumNative } from '@embedpdf/engines/pdfium';\nimport { PDF_FORM_FIELD_TYPE, PdfAnnotationSubtype, PdfBlendMode, type PdfAnnotationObject, type Rect } from '@embedpdf/models';\nimport type { SignatureMethod } from '../types';\n\nexport type Point = { x: number; y: number };\nexport type Box = Point & { w: number; h: number };\n\nexport type Mark = { id: string; page: number; author: string; at: string } & (\n | { kind: 'highlight' | 'underline' | 'strike'; rects: Box[]; text: string; color: string }\n | { kind: 'note'; spot: Point; text: string; color: string }\n | { kind: 'ink'; lines: Point[][]; width: number; color: string }\n | { kind: 'sign'; box: Box; image: string; method: SignatureMethod }\n);\n\nexport type Field = { page: number; name: string; box: Box; value: string | boolean | string[] };\n\nlet engine: Promise<PdfiumNative> | null = null;\n\nconst rect = (box: Box): Rect => ({ origin: { x: box.x, y: box.y }, size: { width: box.w, height: box.h } });\n\nconst around = (boxes: Box[]): Box => {\n const x = Math.min(...boxes.map(b => b.x));\n const y = Math.min(...boxes.map(b => b.y));\n return { x, y, w: Math.max(...boxes.map(b => b.x + b.w)) - x, h: Math.max(...boxes.map(b => b.y + b.h)) - y };\n};\n\nconst png = (url: string) => Uint8Array.from(atob(url.slice(url.indexOf(',') + 1)), c => c.charCodeAt(0)).buffer;\n\nconst types = { highlight: PdfAnnotationSubtype.HIGHLIGHT, underline: PdfAnnotationSubtype.UNDERLINE, strike: PdfAnnotationSubtype.STRIKEOUT } as const;\n\nfunction annotation(mark: Mark): PdfAnnotationObject {\n const base = { id: mark.id, pageIndex: mark.page - 1, author: mark.author, created: new Date(mark.at), modified: new Date(mark.at) };\n if (mark.kind === 'note') {\n return { ...base, type: PdfAnnotationSubtype.TEXT, rect: rect({ ...mark.spot, w: 20, h: 20 }), contents: mark.text, strokeColor: mark.color, opacity: 1 };\n }\n if (mark.kind === 'ink') {\n const spread = mark.width / 2 + 1;\n const bounds = around(mark.lines.flat().map(p => ({ x: p.x - spread, y: p.y - spread, w: spread * 2, h: spread * 2 })));\n return { ...base, type: PdfAnnotationSubtype.INK, rect: rect(bounds), inkList: mark.lines.map(points => ({ points })), strokeColor: mark.color, strokeWidth: mark.width, opacity: 1 };\n }\n if (mark.kind === 'sign') return { ...base, type: PdfAnnotationSubtype.STAMP, rect: rect(mark.box) };\n return {\n ...base, type: types[mark.kind], rect: rect(around(mark.rects)), segmentRects: mark.rects.map(rect), contents: mark.text, strokeColor: mark.color, opacity: 1,\n ...(mark.kind === 'highlight' ? { blendMode: PdfBlendMode.Multiply } : {}),\n } as PdfAnnotationObject;\n}\n\nexport async function write(bytes: ArrayBuffer, marks: Mark[], fields: Field[]): Promise<ArrayBuffer> {\n engine ??= init({}).then(module => new PdfiumNative(module));\n const pdfium = await engine;\n const doc = await pdfium.openDocumentBuffer({ id: Math.random().toString(36).slice(2), content: bytes.slice(0) }).toPromise();\n try {\n for (const n of new Set(fields.map(field => field.page))) {\n const page = doc.pages[n - 1];\n const widgets = await pdfium.getPageAnnoWidgets(doc, page).toPromise();\n for (const field of fields.filter(f => f.page === n)) {\n const centre = (r: Rect) => Math.hypot(r.origin.x + r.size.width / 2 - field.box.x - field.box.w / 2, r.origin.y + r.size.height / 2 - field.box.y - field.box.h / 2);\n const widget = widgets.filter(w => w.field.name === field.name).sort((a, b) => centre(a.rect) - centre(b.rect))[0];\n if (!widget) continue;\n const { type } = widget.field;\n if (type === PDF_FORM_FIELD_TYPE.TEXTFIELD) {\n await pdfium.setFormFieldValue(doc, page, widget, { kind: 'text', text: String(field.value) }).toPromise();\n } else if (type === PDF_FORM_FIELD_TYPE.CHECKBOX || (type === PDF_FORM_FIELD_TYPE.RADIOBUTTON && field.value === true)) {\n await pdfium.setFormFieldValue(doc, page, widget, { kind: 'checked', checked: field.value === true }).toPromise();\n } else if ('options' in widget.field && Array.isArray(field.value)) {\n for (const [index, option] of widget.field.options.entries()) {\n const wanted = field.value.includes(option.label);\n if (wanted !== option.isSelected) await pdfium.setFormFieldValue(doc, page, widget, { kind: 'selection', index, isSelected: wanted }).toPromise();\n }\n }\n }\n }\n for (const mark of marks) {\n const page = doc.pages[mark.page - 1];\n if (mark.kind === 'sign') await pdfium.createPageAnnotation(doc, page, annotation(mark), { data: png(mark.image), mimeType: 'image/png' } as never).toPromise();\n else await pdfium.createPageAnnotation(doc, page, annotation(mark)).toPromise();\n }\n return await pdfium.saveAsCopy(doc).toPromise();\n } finally {\n await pdfium.closeDocument(doc).toPromise();\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
type DocumentKind = 'docx' | 'markdown' | 'pdf' | 'sheet' | 'slides';
|
|
2
|
+
type Language = 'en' | 'pl' | 'uk';
|
|
3
|
+
type Person = {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
avatarUrl?: string | null;
|
|
7
|
+
};
|
|
8
|
+
type Space = {
|
|
9
|
+
id: string;
|
|
10
|
+
name: string;
|
|
11
|
+
color?: string | null;
|
|
12
|
+
group?: string | null;
|
|
13
|
+
};
|
|
14
|
+
type Rights = {
|
|
15
|
+
view: boolean;
|
|
16
|
+
comment: boolean;
|
|
17
|
+
edit: boolean;
|
|
18
|
+
};
|
|
19
|
+
type DocumentSummary = {
|
|
20
|
+
id: string;
|
|
21
|
+
spaceId: string;
|
|
22
|
+
name: string;
|
|
23
|
+
kind: DocumentKind;
|
|
24
|
+
size: number;
|
|
25
|
+
updatedAt: string;
|
|
26
|
+
updatedBy?: Person | null;
|
|
27
|
+
thumbnailUrl?: string | null;
|
|
28
|
+
excerpt?: string | null;
|
|
29
|
+
folder?: string | null;
|
|
30
|
+
};
|
|
31
|
+
type DocumentFile = DocumentSummary & {
|
|
32
|
+
rights: Rights;
|
|
33
|
+
mimeType?: string | null;
|
|
34
|
+
exports?: ('pdf' | 'docx' | 'md')[];
|
|
35
|
+
live?: boolean;
|
|
36
|
+
convert?: 'xlsx';
|
|
37
|
+
};
|
|
38
|
+
type DocumentVersion = {
|
|
39
|
+
id: string;
|
|
40
|
+
createdAt: string;
|
|
41
|
+
size: number;
|
|
42
|
+
author?: Person | null;
|
|
43
|
+
note?: string | null;
|
|
44
|
+
current: boolean;
|
|
45
|
+
};
|
|
46
|
+
type Fetch = {
|
|
47
|
+
signal?: AbortSignal;
|
|
48
|
+
};
|
|
49
|
+
type SignatureMethod = 'typed' | 'drawn' | 'image';
|
|
50
|
+
type Signature = {
|
|
51
|
+
id: string;
|
|
52
|
+
signer: Person;
|
|
53
|
+
signedAt: string;
|
|
54
|
+
page: number;
|
|
55
|
+
method: SignatureMethod;
|
|
56
|
+
versionId: string | null;
|
|
57
|
+
};
|
|
58
|
+
type Comment = {
|
|
59
|
+
id: string;
|
|
60
|
+
documentId: string;
|
|
61
|
+
author: Person;
|
|
62
|
+
body: string;
|
|
63
|
+
createdAt: string;
|
|
64
|
+
quote: string;
|
|
65
|
+
replyTo: string | null;
|
|
66
|
+
resolved: boolean;
|
|
67
|
+
};
|
|
68
|
+
type GuestLink = {
|
|
69
|
+
id: string;
|
|
70
|
+
url: string;
|
|
71
|
+
comment: boolean;
|
|
72
|
+
download: boolean;
|
|
73
|
+
askName: boolean;
|
|
74
|
+
password: boolean;
|
|
75
|
+
endsAt: string | null;
|
|
76
|
+
ended: boolean;
|
|
77
|
+
createdAt: string;
|
|
78
|
+
createdBy: Person;
|
|
79
|
+
guests: {
|
|
80
|
+
name: string;
|
|
81
|
+
opens: number;
|
|
82
|
+
comments: number;
|
|
83
|
+
lastAt: string;
|
|
84
|
+
}[];
|
|
85
|
+
};
|
|
86
|
+
type LinkEntry = {
|
|
87
|
+
comment: boolean;
|
|
88
|
+
download: boolean;
|
|
89
|
+
askName: boolean;
|
|
90
|
+
endsAt: string | null;
|
|
91
|
+
password: string | null;
|
|
92
|
+
};
|
|
93
|
+
type GuestFile = {
|
|
94
|
+
id: string;
|
|
95
|
+
name: string;
|
|
96
|
+
mimeType: string;
|
|
97
|
+
size: number;
|
|
98
|
+
updatedAt: string;
|
|
99
|
+
sharedBy: string;
|
|
100
|
+
comment: boolean;
|
|
101
|
+
download: boolean;
|
|
102
|
+
bytes: ArrayBuffer;
|
|
103
|
+
};
|
|
104
|
+
interface GuestHost {
|
|
105
|
+
pdfWorker?: () => Worker;
|
|
106
|
+
open(entry: {
|
|
107
|
+
password?: string;
|
|
108
|
+
name?: string;
|
|
109
|
+
}, opts?: Fetch): Promise<GuestFile>;
|
|
110
|
+
comments(opts?: Fetch): Promise<Comment[]>;
|
|
111
|
+
comment(entry: {
|
|
112
|
+
body: string;
|
|
113
|
+
quote: string;
|
|
114
|
+
replyTo: string | null;
|
|
115
|
+
anchor: string;
|
|
116
|
+
name: string;
|
|
117
|
+
}): Promise<Comment>;
|
|
118
|
+
download(format: 'file' | 'pdf'): Promise<void>;
|
|
119
|
+
}
|
|
120
|
+
interface DocumentsHost {
|
|
121
|
+
me: Person;
|
|
122
|
+
pdfWorker?: () => Worker;
|
|
123
|
+
spaces(opts?: Fetch): Promise<Space[]>;
|
|
124
|
+
documents(spaceId: string, opts?: Fetch): Promise<DocumentSummary[]>;
|
|
125
|
+
everything?(opts?: Fetch): Promise<DocumentSummary[]>;
|
|
126
|
+
document(id: string, opts?: Fetch): Promise<DocumentFile>;
|
|
127
|
+
versions(id: string, opts?: Fetch): Promise<DocumentVersion[]>;
|
|
128
|
+
content(id: string, versionId?: string | null, opts?: Fetch): Promise<ArrayBuffer>;
|
|
129
|
+
restore?(id: string, versionId: string): Promise<void>;
|
|
130
|
+
save?(id: string, bytes: ArrayBuffer, note: string): Promise<{
|
|
131
|
+
versionId: string;
|
|
132
|
+
}>;
|
|
133
|
+
signatures?(id: string, opts?: Fetch): Promise<Signature[]>;
|
|
134
|
+
sign?(id: string, entry: {
|
|
135
|
+
versionId: string;
|
|
136
|
+
page: number;
|
|
137
|
+
method: SignatureMethod;
|
|
138
|
+
}): Promise<Signature>;
|
|
139
|
+
comments?(id: string, opts?: Fetch): Promise<Comment[]>;
|
|
140
|
+
comment?(id: string, entry: {
|
|
141
|
+
body: string;
|
|
142
|
+
quote: string;
|
|
143
|
+
replyTo: string | null;
|
|
144
|
+
anchor: string;
|
|
145
|
+
}): Promise<Comment>;
|
|
146
|
+
resolveComment?(id: string, commentId: string, resolved: boolean): Promise<void>;
|
|
147
|
+
editComment?(id: string, commentId: string, body: string): Promise<Comment>;
|
|
148
|
+
deleteComment?(id: string, commentId: string): Promise<void>;
|
|
149
|
+
exportAs?(id: string, format: 'pdf' | 'docx' | 'md'): Promise<Blob>;
|
|
150
|
+
copyAs?(id: string, format: 'xlsx'): Promise<DocumentSummary>;
|
|
151
|
+
links?(id: string, opts?: Fetch): Promise<GuestLink[]>;
|
|
152
|
+
share?(id: string, entry: LinkEntry): Promise<GuestLink>;
|
|
153
|
+
relink?(linkId: string, entry: LinkEntry): Promise<GuestLink>;
|
|
154
|
+
unshare?(linkId: string): Promise<void>;
|
|
155
|
+
collab?: {
|
|
156
|
+
url: string;
|
|
157
|
+
token: () => Promise<string>;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
type Place = {
|
|
161
|
+
spaceId: string | null;
|
|
162
|
+
documentId: string | null;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export type { Comment as C, DocumentsHost as D, Fetch as F, GuestHost as G, Language as L, Place as P, Rights as R, Signature as S, DocumentFile as a, DocumentKind as b, DocumentSummary as c, DocumentVersion as d, GuestFile as e, GuestLink as f, LinkEntry as g, Person as h, SignatureMethod as i, Space as j };
|