@a3s-lab/office 0.31.0 → 0.33.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.
Files changed (63) hide show
  1. package/README.md +63 -8
  2. package/dist/0~3539.js +2 -2
  3. package/dist/0~3557.js +1 -1
  4. package/dist/0~3635.js +1 -1
  5. package/dist/0~4808.js +1 -1
  6. package/dist/0~4980.js +1 -1
  7. package/dist/0~7048.js +1 -2
  8. package/dist/0~7240.js +1 -1
  9. package/dist/0~7614.js +1 -1
  10. package/dist/{0~6090.js → 0~8136.js} +71 -2
  11. package/dist/{0~4595.js → 0~9073.js} +3 -72
  12. package/dist/0~9445.js +1 -1
  13. package/dist/0~document-editor.js +1087 -6
  14. package/dist/0~markdown-editor.js +2 -2
  15. package/dist/0~pdf-page-organization-engine.js +187 -0
  16. package/dist/0~pdf-viewer.js +1014 -30
  17. package/dist/0~presentation-editor.js +2 -2
  18. package/dist/0~spreadsheet-editor.js +4 -3
  19. package/dist/0~work-docx-export.js +1 -1
  20. package/dist/0~work-docx-import.js +10 -27
  21. package/dist/0~work-docx-large-document-import.js +1 -1
  22. package/dist/0~work-office-diagnostics.js +3 -3
  23. package/dist/0~work-pptx-import.js +1 -1
  24. package/dist/{1544.js → 3266.js} +17 -1862
  25. package/dist/4121.js +13 -0
  26. package/dist/4166.js +3848 -0
  27. package/dist/{6282.js → 4174.js} +383 -10
  28. package/dist/9333.js +1849 -0
  29. package/dist/core.d.ts +1 -0
  30. package/dist/core.js +5259 -4
  31. package/dist/index.js +3 -3
  32. package/dist/internal/features/work/editors/document-compare-dialog.d.ts +14 -0
  33. package/dist/internal/features/work/editors/document-toolbar.d.ts +3 -1
  34. package/dist/internal/features/work/editors/pdf-editor-extensions.d.ts +11 -0
  35. package/dist/internal/features/work/editors/pdf-page-organization-engine.d.ts +2 -0
  36. package/dist/internal/features/work/editors/pdf-page-organization-plan.d.ts +10 -0
  37. package/dist/internal/features/work/editors/pdf-page-organization-types.d.ts +68 -0
  38. package/dist/internal/features/work/editors/pdf-page-organization-worker-client.d.ts +2 -0
  39. package/dist/internal/features/work/editors/pdf-page-organization-worker-protocol.d.ts +13 -0
  40. package/dist/internal/features/work/editors/pdf-page-organization.d.ts +3 -0
  41. package/dist/internal/features/work/editors/pdf-page-organization.worker.d.ts +1 -0
  42. package/dist/internal/features/work/editors/pdf-page-organizer-dialog.d.ts +17 -0
  43. package/dist/internal/features/work/editors/pdf-thumbnail-rail.d.ts +4 -0
  44. package/dist/internal/features/work/editors/pdf-toolbar.d.ts +2 -1
  45. package/dist/internal/features/work/editors/pdf-viewer.d.ts +3 -1
  46. package/dist/internal/features/work/editors/use-document-comparison.d.ts +9 -0
  47. package/dist/internal/features/work/editors/use-pdf-page-organization.d.ts +38 -0
  48. package/dist/internal/features/work/work-document-changes.d.ts +5 -0
  49. package/dist/internal/features/work/work-document-compare-diff.d.ts +38 -0
  50. package/dist/internal/features/work/work-document-compare-stability.d.ts +5 -0
  51. package/dist/internal/features/work/work-document-compare.d.ts +27 -0
  52. package/dist/office-kernel.wasm +0 -0
  53. package/dist/pdf-page-organization.worker.js +19667 -0
  54. package/dist/pdf-page-organization.worker.js.LICENSE.txt +14 -0
  55. package/dist/react.d.ts +1 -0
  56. package/dist/styles.css +509 -0
  57. package/dist/vue.d.ts +3 -1
  58. package/dist/vue.js +2 -0
  59. package/dist/web-component.d.ts +3 -1
  60. package/dist/web-component.js +9 -0
  61. package/docs/latest/en/browser-editor-architecture.md +52 -6
  62. package/package.json +10 -3
  63. package/dist/4104.js +0 -9336
@@ -11,8 +11,8 @@ import { Markdown } from "@tiptap/markdown";
11
11
  import starter_kit from "@tiptap/starter-kit";
12
12
  import { Bold, Code2, Columns2, Image, Italic, Link2, List, ListChecks, ListOrdered, Minus, PencilLine, Quote, Redo2, Strikethrough, Table2, Undo2, Unlink } from "lucide-react";
13
13
  import { mergeOfficeTiptapExtensions, documentPlainTextAsHtml, customSelectionMenuItems } from "./0~5050.js";
14
- import { OfficeSelect, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZoomControls, WorkOfficeStatusBar, Dialog, WorkOfficeRibbon, workspaceContextMenuPosition, WorkspaceContextMenu, WorkOfficeRibbonGroup, WorkOfficeRibbonButton, WorkOfficePreviewBar } from "./0~4595.js";
15
- import { button_Button, OfficeTiptapPresenceLayer, useOfficePublishPresenceLocation, stepOfficeZoom, office_text_field_OfficeTextField, useOfficeEditorWheelZoom, MarkdownSourcePresenceLayer } from "./0~6090.js";
14
+ import { OfficeSelect, isWorkspaceContextMenuKeyboardEvent, WorkOfficeZoomControls, WorkOfficeStatusBar, WorkOfficeRibbon, workspaceContextMenuPosition, WorkspaceContextMenu, WorkOfficeRibbonGroup, WorkOfficeRibbonButton, WorkOfficePreviewBar } from "./0~9073.js";
15
+ import { stepOfficeZoom, MarkdownSourcePresenceLayer, button_Button, OfficeTiptapPresenceLayer, useOfficePublishPresenceLocation, Dialog, office_text_field_OfficeTextField, useOfficeEditorWheelZoom } from "./0~8136.js";
16
16
  import { normalizeDocumentHref, DOCUMENT_LINK_VALIDATION_MESSAGE } from "./0~work-document-links.js";
17
17
  import { readOfficeMarkdownCollaboration as readWorkOfficeMarkdownCollaboration, createOfficeMarkdownCollaborationBinding as createWorkOfficeMarkdownCollaborationBinding } from "./2591.js";
18
18
  import { useOfficeEditorInitialFocus, useOfficeCollaborationLocationNavigator, WorkEditorLoadingState } from "./432.js";
@@ -0,0 +1,187 @@
1
+ import { PDFDocument, PDFName, degrees } from "pdf-lib";
2
+ import { validatedPdfPageSize, PdfPageOrganizationError, PDF_PAGE_ORGANIZATION_MAX_SOURCE_BYTES, validatedPdfInsertionIndex, validatedPdfSplitBoundaries, PDF_PAGE_ORGANIZATION_MAX_IMPORT_BYTES, validatedPdfPageOrder, validatedPdfPageIndexes } from "./0~pdf-viewer.js";
3
+ const RISKY_STRUCTURE_KEYS = [
4
+ 'AcroForm',
5
+ 'Outlines',
6
+ 'StructTreeRoot'
7
+ ];
8
+ const COPY_DIAGNOSTIC = {
9
+ code: 'pdf.pages.catalog-not-copied',
10
+ message: "Page-only exports do not copy document-level outlines, forms, tags, attachments, scripts, or signatures."
11
+ };
12
+ async function applyPdfPageOrganizationJob(job) {
13
+ const source = await loadBoundedPdf(job.source, PDF_PAGE_ORGANIZATION_MAX_SOURCE_BYTES, 'source');
14
+ assertPageCount(source.getPageCount());
15
+ if ('export' === job.kind) return exportPages(source, job.operation);
16
+ assertUnsigned(source);
17
+ return mutatePages(source, job.mutation, job.importSource);
18
+ }
19
+ async function mutatePages(source, mutation, importSource) {
20
+ const pageCount = source.getPageCount();
21
+ if ('rotate' === mutation.kind) {
22
+ const indexes = validatedPdfPageIndexes(mutation.pageIndexes, pageCount);
23
+ for (const pageIndex of indexes){
24
+ const page = source.getPage(pageIndex);
25
+ const current = page.getRotation().angle;
26
+ if (!Number.isSafeInteger(current) || current % 90 !== 0) throw new PdfPageOrganizationError('pdf.pages.unsupported-rotation', `Page ${pageIndex + 1} has unsupported rotation ${String(current)}.`);
27
+ page.setRotation(degrees(normalizeDegrees(current + mutation.degrees)));
28
+ }
29
+ return mutationResult(source);
30
+ }
31
+ if ('insert-blank' === mutation.kind) {
32
+ const index = validatedPdfInsertionIndex(mutation.index, pageCount);
33
+ const size = validatedPdfPageSize(mutation.size);
34
+ assertPageCount(pageCount + 1);
35
+ source.insertPage(index, [
36
+ size.width,
37
+ size.height
38
+ ]);
39
+ return mutationResult(source);
40
+ }
41
+ if ('delete' === mutation.kind) {
42
+ assertNoRiskyStructure(source);
43
+ const indexes = validatedPdfPageIndexes(mutation.pageIndexes, pageCount);
44
+ if (indexes.length >= pageCount) throw new PdfPageOrganizationError('pdf.pages.empty-document', 'A PDF must retain at least one page.');
45
+ for (const pageIndex of [
46
+ ...indexes
47
+ ].sort((left, right)=>right - left))source.removePage(pageIndex);
48
+ return mutationResult(source);
49
+ }
50
+ if ('reorder' === mutation.kind) {
51
+ assertNoRiskyStructure(source);
52
+ const pageOrder = validatedPdfPageOrder(mutation.pageOrder, pageCount);
53
+ const reordered = await PDFDocument.create({
54
+ updateMetadata: false
55
+ });
56
+ copyMetadata(source, reordered);
57
+ const pages = await reordered.copyPages(source, pageOrder);
58
+ for (const page of pages)reordered.addPage(page);
59
+ return mutationResult(reordered);
60
+ }
61
+ const index = validatedPdfInsertionIndex(mutation.index, pageCount);
62
+ if (!importSource) throw new PdfPageOrganizationError('pdf.pages.missing-import', 'Choose a PDF to merge before applying this operation.');
63
+ assertNoRiskyStructure(source);
64
+ const imported = await loadBoundedPdf(importSource, PDF_PAGE_ORGANIZATION_MAX_IMPORT_BYTES, 'import');
65
+ assertSafeImport(imported);
66
+ assertPageCount(pageCount + imported.getPageCount());
67
+ const copied = await source.copyPages(imported, imported.getPageIndices());
68
+ for(let offset = 0; offset < copied.length; offset += 1){
69
+ const page = copied[offset];
70
+ if (page) source.insertPage(index + offset, page);
71
+ }
72
+ return mutationResult(source);
73
+ }
74
+ async function exportPages(source, operation) {
75
+ const pageCount = source.getPageCount();
76
+ if ('extract' === operation.kind) {
77
+ const indexes = validatedPdfPageIndexes(operation.pageIndexes, pageCount, {
78
+ preserveOrder: true
79
+ });
80
+ return {
81
+ diagnostics: sourceHasRiskyStructure(source) ? [
82
+ COPY_DIAGNOSTIC
83
+ ] : [],
84
+ files: [
85
+ await copyPageRange(source, indexes)
86
+ ],
87
+ kind: 'exported'
88
+ };
89
+ }
90
+ const boundaries = validatedPdfSplitBoundaries(operation.splitAfterPageIndexes, pageCount);
91
+ const ranges = [];
92
+ let start = 0;
93
+ for (const boundary of boundaries){
94
+ ranges.push(range(start, boundary + 1));
95
+ start = boundary + 1;
96
+ }
97
+ ranges.push(range(start, pageCount));
98
+ return {
99
+ diagnostics: sourceHasRiskyStructure(source) ? [
100
+ COPY_DIAGNOSTIC
101
+ ] : [],
102
+ files: await Promise.all(ranges.map((indexes)=>copyPageRange(source, indexes))),
103
+ kind: 'exported'
104
+ };
105
+ }
106
+ async function copyPageRange(source, indexes) {
107
+ const output = await PDFDocument.create({
108
+ updateMetadata: false
109
+ });
110
+ copyMetadata(source, output);
111
+ const pages = await output.copyPages(source, indexes);
112
+ for (const page of pages)output.addPage(page);
113
+ return {
114
+ pageCount: indexes.length,
115
+ source: await output.save()
116
+ };
117
+ }
118
+ async function mutationResult(source) {
119
+ return {
120
+ diagnostics: [],
121
+ kind: 'mutated',
122
+ pageCount: source.getPageCount(),
123
+ source: await source.save()
124
+ };
125
+ }
126
+ async function loadBoundedPdf(source, byteLimit, label) {
127
+ const byteLength = source.byteLength;
128
+ if (byteLength < 5 || byteLength > byteLimit) throw new PdfPageOrganizationError('pdf.pages.source-limit', `The PDF ${label} must be between 5 bytes and ${byteLimit} bytes.`);
129
+ try {
130
+ const pdf = await PDFDocument.load(source, {
131
+ ignoreEncryption: false,
132
+ throwOnInvalidObject: true,
133
+ updateMetadata: false
134
+ });
135
+ if (pdf.isEncrypted) throw new PdfPageOrganizationError('pdf.pages.encrypted-source', `The encrypted PDF ${label} cannot be reorganized without an authenticated decryption provider.`);
136
+ return pdf;
137
+ } catch (error) {
138
+ if (error instanceof PdfPageOrganizationError) throw error;
139
+ const message = error instanceof Error ? error.message : String(error);
140
+ if (/encrypt/i.test(message)) throw new PdfPageOrganizationError('pdf.pages.encrypted-source', `The encrypted PDF ${label} cannot be reorganized without an authenticated decryption provider.`);
141
+ throw new PdfPageOrganizationError('pdf.pages.invalid-source', `The PDF ${label} is malformed or unsupported: ${message.slice(0, 240)}`);
142
+ }
143
+ }
144
+ function assertPageCount(pageCount) {
145
+ if (!Number.isSafeInteger(pageCount) || pageCount < 1 || pageCount > 4096) throw new PdfPageOrganizationError('pdf.pages.page-limit', "PDF page organization supports 1 to 4096 pages per result.");
146
+ }
147
+ function assertUnsigned(source) {
148
+ if (source.catalog.has(PDFName.of('Perms'))) throw new PdfPageOrganizationError('pdf.pages.signed-source', 'This PDF declares a signature permission dictionary. Rewriting it would invalidate its trust evidence.');
149
+ }
150
+ function assertNoRiskyStructure(source) {
151
+ if (!sourceHasRiskyStructure(source)) return;
152
+ throw new PdfPageOrganizationError('pdf.pages.risky-structure', 'Delete, reorder, and merge are disabled for PDFs with forms, outlines, or tagged structure because page references cannot be rewritten safely.');
153
+ }
154
+ function assertSafeImport(source) {
155
+ if (!sourceHasRiskyStructure(source) && !source.catalog.has(PDFName.of('Perms'))) return;
156
+ throw new PdfPageOrganizationError('pdf.pages.risky-import', 'The PDF selected for merge contains forms, outlines, tags, or signature permissions that cannot be copied safely.');
157
+ }
158
+ function sourceHasRiskyStructure(source) {
159
+ return RISKY_STRUCTURE_KEYS.some((key)=>source.catalog.has(PDFName.of(key)));
160
+ }
161
+ function copyMetadata(source, target) {
162
+ setIfDefined(source.getTitle(), (value)=>target.setTitle(value));
163
+ setIfDefined(source.getAuthor(), (value)=>target.setAuthor(value));
164
+ setIfDefined(source.getSubject(), (value)=>target.setSubject(value));
165
+ setIfDefined(source.getCreator(), (value)=>target.setCreator(value));
166
+ setIfDefined(source.getProducer(), (value)=>target.setProducer(value));
167
+ setIfDefined(source.getCreationDate(), (value)=>target.setCreationDate(value));
168
+ setIfDefined(source.getModificationDate(), (value)=>target.setModificationDate(value));
169
+ const keywords = source.getKeywords();
170
+ if (keywords) target.setKeywords([
171
+ keywords
172
+ ]);
173
+ }
174
+ function setIfDefined(value, setter) {
175
+ if (void 0 !== value) setter(value);
176
+ }
177
+ function normalizeDegrees(value) {
178
+ const normalized = (value % 360 + 360) % 360;
179
+ if (0 === normalized || 90 === normalized || 180 === normalized || 270 === normalized) return normalized;
180
+ throw new PdfPageOrganizationError('pdf.pages.unsupported-rotation', `PDF page rotation ${value} is not a multiple of 90 degrees.`);
181
+ }
182
+ function range(start, end) {
183
+ return Array.from({
184
+ length: Math.max(0, end - start)
185
+ }, (_, index)=>start + index);
186
+ }
187
+ export { applyPdfPageOrganizationJob };