@a3s-lab/office 0.12.0 → 0.13.1
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 +112 -7
- package/dist/0~1403.js +20 -12
- package/dist/0~2805.js +241 -241
- package/dist/0~4980.js +1 -1
- package/dist/0~5050.js +1 -20
- package/dist/0~5093.js +547 -547
- package/dist/0~6090.js +63 -4
- package/dist/0~7048.js +31 -29
- package/dist/0~document-editor.js +694 -90
- package/dist/0~pdf-viewer.js +41 -10
- package/dist/0~presentation-editor.js +8 -6
- package/dist/0~spreadsheet-editor.js +11892 -9682
- package/dist/0~work-document-import-worker-client.js +237 -0
- package/dist/0~work-docx-export.js +1 -1
- package/dist/0~work-docx-import.js +1 -1
- package/dist/0~work-docx-large-document-import.js +559 -0
- package/dist/0~work-office-diagnostics.js +46 -32
- package/dist/4104.js +5070 -3112
- package/dist/432.js +51 -7
- package/dist/4476.js +201 -7
- package/dist/5184.js +24 -2
- package/dist/{8928.js → 6282.js} +2338 -93
- package/dist/8715.js +895 -888
- package/dist/9356.js +3 -1
- package/dist/core.js +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/features/work/editors/document-editor-support.d.ts +1 -9
- package/dist/internal/features/work/editors/document-external-content.d.ts +1 -1
- package/dist/internal/features/work/editors/office-menu-keyboard.d.ts +1 -0
- package/dist/internal/features/work/editors/presentation-slide-canvas.d.ts +3 -1
- package/dist/internal/features/work/editors/presentation-slide-thumbnail.d.ts +3 -2
- package/dist/internal/features/work/editors/presentation-thumbnail-rail.d.ts +2 -1
- package/dist/internal/features/work/editors/presentation-workspace.d.ts +2 -1
- package/dist/internal/features/work/editors/spreadsheet-border-ribbon.d.ts +5 -0
- package/dist/internal/features/work/editors/spreadsheet-calculation-projection.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-border-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-border-per-cell.d.ts +5 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-border.d.ts +28 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-fill-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-fill.d.ts +12 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-range.d.ts +14 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-style-command.d.ts +3 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-style-ribbon.d.ts +9 -0
- package/dist/internal/features/work/editors/spreadsheet-cell-style.d.ts +41 -0
- package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +293 -0
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +10 -4
- package/dist/internal/features/work/editors/spreadsheet-editor-ribbon.d.ts +3 -1
- package/dist/internal/features/work/editors/spreadsheet-editor-support.d.ts +8 -2
- package/dist/internal/features/work/editors/spreadsheet-home-format-ribbon.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-in-place-workbook-sync.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-number-format.d.ts +15 -3
- package/dist/internal/features/work/editors/spreadsheet-operation-projection.d.ts +14 -0
- package/dist/internal/features/work/editors/spreadsheet-structure-selection.d.ts +7 -0
- package/dist/internal/features/work/editors/use-document-pagination.d.ts +5 -0
- package/dist/internal/features/work/editors/use-presentation-design-commands.d.ts +2 -1
- package/dist/internal/features/work/editors/use-spreadsheet-workbook-sync.d.ts +2 -1
- package/dist/internal/features/work/spreadsheet-history-value.d.ts +1 -0
- package/dist/internal/features/work/spreadsheet-sparse.d.ts +6 -1
- package/dist/internal/features/work/work-document-chunk-geometry.d.ts +28 -0
- package/dist/internal/features/work/work-document-chunk-node.d.ts +23 -0
- package/dist/internal/features/work/work-document-extensions.d.ts +1 -0
- package/dist/internal/features/work/work-document-html-fingerprint.d.ts +15 -0
- package/dist/internal/features/work/work-document-import-worker-client.d.ts +13 -0
- package/dist/internal/features/work/work-document-import-worker-protocol.d.ts +36 -0
- package/dist/internal/features/work/work-document-import.worker.d.ts +1 -0
- package/dist/internal/features/work/work-document-incremental-layout.d.ts +1 -1
- package/dist/internal/features/work/work-document-integrity-index.d.ts +14 -0
- package/dist/internal/features/work/work-document-lazy-block.d.ts +3 -0
- package/dist/internal/features/work/work-document-lazy-html.d.ts +21 -0
- package/dist/internal/features/work/work-document-lazy-model.d.ts +29 -0
- package/dist/internal/features/work/work-document-lazy-pagination-measurement.d.ts +3 -0
- package/dist/internal/features/work/work-document-lazy-preview.d.ts +21 -0
- package/dist/internal/features/work/work-document-lazy-update.d.ts +14 -0
- package/dist/internal/features/work/work-document-model.d.ts +18 -2
- package/dist/internal/features/work/work-document-page-surface-registry.d.ts +16 -0
- package/dist/internal/features/work/work-document-pagination-dom.d.ts +1 -0
- package/dist/internal/features/work/work-document-pagination-types.d.ts +1 -0
- package/dist/internal/features/work/work-document-pagination.d.ts +1 -1
- package/dist/internal/features/work/work-document-text-statistics.d.ts +25 -0
- package/dist/internal/features/work/work-document-windowing.d.ts +23 -0
- package/dist/internal/features/work/work-docx-large-document-import.d.ts +35 -0
- package/dist/internal/features/work/work-docx-large-document-parser.d.ts +29 -0
- package/dist/internal/features/work/work-file-import.d.ts +5 -0
- package/dist/internal/features/work/work-file-io.d.ts +3 -3
- package/dist/internal/features/work/work-file-kind.d.ts +5 -0
- package/dist/internal/features/work/work-office-diagnostics.d.ts +10 -1
- package/dist/internal/features/work/work-ooxml-package.d.ts +8 -0
- package/dist/internal/features/work/work-presentation-layouts.d.ts +7 -1
- package/dist/internal/features/work/work-repository.d.ts +1 -0
- package/dist/internal/features/work/work-spreadsheet-compatibility-summary.d.ts +10 -0
- package/dist/internal/features/work/work-spreadsheet-file-export.d.ts +2 -0
- package/dist/internal/features/work/work-spreadsheet-file-import.d.ts +3 -0
- package/dist/internal/features/work/work-spreadsheet-import-diagnostics.d.ts +2 -0
- package/dist/internal/features/work/work-spreadsheet-import-worker-client.d.ts +6 -0
- package/dist/internal/features/work/work-spreadsheet-import-worker-protocol.d.ts +32 -0
- package/dist/internal/features/work/work-spreadsheet-import.worker.d.ts +1 -0
- package/dist/internal/features/work/work-spreadsheet-matrix-profile.d.ts +64 -0
- package/dist/internal/features/work/work-spreadsheet-package-scan-worker-client.d.ts +6 -0
- package/dist/internal/features/work/work-spreadsheet-package-scan-worker-protocol.d.ts +49 -0
- package/dist/internal/features/work/work-spreadsheet-package-scan.worker.d.ts +1 -0
- package/dist/internal/features/work/work-xlsx-cell-borders.d.ts +25 -0
- package/dist/internal/features/work/work-xlsx-cell-style-writer.d.ts +21 -0
- package/dist/internal/features/work/work-xlsx-cell-style-xml.d.ts +17 -0
- package/dist/internal/features/work/work-xlsx-cell-styles.d.ts +13 -0
- package/dist/internal/features/work/work-xlsx-colors.d.ts +6 -0
- package/dist/internal/features/work/work-xlsx-formula-diagnostics.d.ts +3 -1
- package/dist/internal/features/work/work-xlsx-formulas.d.ts +2 -1
- package/dist/internal/features/work/work-xlsx-interop.d.ts +8 -5
- package/dist/internal/features/work/work-xlsx-pivot-diagnostics.d.ts +2 -1
- package/dist/internal/features/work/work-xlsx-plain-fast-path.d.ts +54 -0
- package/dist/internal/features/work/work-xlsx-style-gate.d.ts +1 -0
- package/dist/internal/features/work/work-xlsx-worksheet-scan.d.ts +13 -0
- package/dist/internal/features/work/work-xlsx-worksheet.d.ts +12 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/office-kernel.worker.js +31 -29
- package/dist/react.d.ts +7 -1
- package/dist/styles.css +557 -3
- package/dist/work-document-import.worker.js +558 -0
- package/dist/work-spreadsheet-import.worker.js +24745 -0
- package/dist/work-spreadsheet-import.worker.js.LICENSE.txt +3 -0
- package/dist/work-spreadsheet-package-scan.worker.js +4161 -0
- package/dist/work-spreadsheet-package-scan.worker.js.LICENSE.txt +11 -0
- package/docs/latest/en/browser-editor-architecture.md +351 -15
- package/package.json +23 -3
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
import { documentSectionDomAttributes, applyDocumentPageGeometry, documentPaperSizeForGeometry, windowDocumentModel } from "./6282.js";
|
|
2
|
+
const LARGE_SIMPLE_DOCX_MINIMUM_LOGICAL_BLOCKS = 20000;
|
|
3
|
+
const WORD_TWIPS_PER_MILLIMETER = 1440 / 25.4;
|
|
4
|
+
const UNSUPPORTED_SIMPLE_WORD_ELEMENT = /<(?:\/)?(?!w:(?:t(?:bl(?:Grid|Layout|Pr|W)?|c(?:Pr|W)?|r)?|p(?:g(?:Mar|Sz))?|r|sectPr|body|document|gridCol)(?=[\s/>]))[A-Za-z_][\w.-]*:[A-Za-z_][\w.-]*(?=[\s/>])/;
|
|
5
|
+
const SIMPLE_WORD_ENVELOPE_ELEMENT = /<w:(document|body|sectPr)(?=[\s/>])/g;
|
|
6
|
+
const WORD_PARAGRAPH_CLOSE = '</w:p>';
|
|
7
|
+
const WORD_TABLE_CLOSE = '</w:tbl>';
|
|
8
|
+
const WORD_TABLE_CELL_CLOSE = '</w:tc>';
|
|
9
|
+
const WORD_TABLE_ROW_CLOSE = '</w:tr>';
|
|
10
|
+
const WORD_TEXT_CLOSE = '</w:t>';
|
|
11
|
+
function streamLargeSimpleDocxDocumentXml(source, options, sink) {
|
|
12
|
+
const minimumLogicalBlocks = positiveInteger(options.minimumLogicalBlocks, LARGE_SIMPLE_DOCX_MINIMUM_LOGICAL_BLOCKS);
|
|
13
|
+
const eligibilityStartedAt = largeDocxImportNow();
|
|
14
|
+
if (!simpleDocxXmlHasSupportedStructure(source)) {
|
|
15
|
+
recordLargeDocxImportMeasure('a3s-office.document.large-simple-eligibility', eligibilityStartedAt, largeDocxImportNow(), {
|
|
16
|
+
accepted: false
|
|
17
|
+
});
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
recordLargeDocxImportMeasure('a3s-office.document.large-simple-eligibility', eligibilityStartedAt, largeDocxImportNow(), {
|
|
21
|
+
accepted: true
|
|
22
|
+
});
|
|
23
|
+
const envelopeStartedAt = largeDocxImportNow();
|
|
24
|
+
const body = elementContentRange(source, 'body');
|
|
25
|
+
if (null === body) return null;
|
|
26
|
+
const layout = simpleDocumentLayout(source, body.start, body.end);
|
|
27
|
+
recordLargeDocxImportMeasure('a3s-office.document.large-simple-envelope', envelopeStartedAt, largeDocxImportNow());
|
|
28
|
+
let topLevelBlockCount = 0;
|
|
29
|
+
let paragraphCount = 0;
|
|
30
|
+
let standaloneParagraphCount = 0;
|
|
31
|
+
let tableRowCount = 0;
|
|
32
|
+
const contentStartedAt = largeDocxImportNow();
|
|
33
|
+
let blockCursor = body.start;
|
|
34
|
+
let paragraphStart = findWordStartTag(source, 'p', blockCursor, body.end);
|
|
35
|
+
let tableStart = findWordStartTag(source, 'tbl', blockCursor, body.end);
|
|
36
|
+
while(paragraphStart >= 0 || tableStart >= 0){
|
|
37
|
+
const blockStart = firstIndex(paragraphStart, tableStart);
|
|
38
|
+
const tagEnd = source.indexOf('>', blockStart);
|
|
39
|
+
if (tagEnd < 0 || tagEnd >= body.end) return null;
|
|
40
|
+
if (blockStart === paragraphStart) {
|
|
41
|
+
const contentEnd = source.indexOf(WORD_PARAGRAPH_CLOSE, tagEnd + 1);
|
|
42
|
+
if (contentEnd < 0 || contentEnd > body.end) return null;
|
|
43
|
+
sink.paragraph(simpleText(source, tagEnd + 1, contentEnd));
|
|
44
|
+
topLevelBlockCount += 1;
|
|
45
|
+
paragraphCount += 1;
|
|
46
|
+
standaloneParagraphCount += 1;
|
|
47
|
+
blockCursor = contentEnd + WORD_PARAGRAPH_CLOSE.length;
|
|
48
|
+
paragraphStart = findWordStartTag(source, 'p', blockCursor, body.end);
|
|
49
|
+
if (tableStart >= 0 && tableStart < blockCursor) tableStart = findWordStartTag(source, 'tbl', blockCursor, body.end);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const contentEnd = source.indexOf(WORD_TABLE_CLOSE, tagEnd + 1);
|
|
53
|
+
if (contentEnd < 0 || contentEnd > body.end) return null;
|
|
54
|
+
if (findWordStartTag(source, 'tbl', tagEnd + 1, contentEnd) >= 0) return null;
|
|
55
|
+
sink.tableStart();
|
|
56
|
+
const table = streamSimpleTableRows(source, tagEnd + 1, contentEnd, sink.tableRow);
|
|
57
|
+
if (!table) return null;
|
|
58
|
+
sink.tableEnd();
|
|
59
|
+
topLevelBlockCount += 1;
|
|
60
|
+
paragraphCount += table.paragraphCount;
|
|
61
|
+
tableRowCount += table.rowCount;
|
|
62
|
+
blockCursor = contentEnd + WORD_TABLE_CLOSE.length;
|
|
63
|
+
tableStart = findWordStartTag(source, 'tbl', blockCursor, body.end);
|
|
64
|
+
if (paragraphStart >= 0 && paragraphStart < blockCursor) paragraphStart = findWordStartTag(source, 'p', blockCursor, body.end);
|
|
65
|
+
}
|
|
66
|
+
if (!topLevelBlockCount) return null;
|
|
67
|
+
recordLargeDocxImportMeasure('a3s-office.document.large-simple-content', contentStartedAt, largeDocxImportNow(), {
|
|
68
|
+
paragraphs: paragraphCount,
|
|
69
|
+
tableRows: tableRowCount
|
|
70
|
+
});
|
|
71
|
+
const logicalBlockCount = tableRowCount + standaloneParagraphCount;
|
|
72
|
+
if (logicalBlockCount < minimumLogicalBlocks) return null;
|
|
73
|
+
return {
|
|
74
|
+
layout,
|
|
75
|
+
logicalBlockCount,
|
|
76
|
+
paragraphCount,
|
|
77
|
+
tableRowCount
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function simpleDocxXmlHasSupportedStructure(source) {
|
|
81
|
+
if (!source || source.includes('<!DOCTYPE') || source.includes('<![CDATA[')) return false;
|
|
82
|
+
if (UNSUPPORTED_SIMPLE_WORD_ELEMENT.test(source)) return false;
|
|
83
|
+
const counts = simpleDocxEnvelopeElementCounts(source);
|
|
84
|
+
return 1 === counts.document && 1 === counts.body && 1 === counts.sectPr;
|
|
85
|
+
}
|
|
86
|
+
function streamSimpleTableRows(source, start, end, visit) {
|
|
87
|
+
let paragraphCount = 0;
|
|
88
|
+
let rowCount = 0;
|
|
89
|
+
let rowCursor = start;
|
|
90
|
+
while(rowCursor < end){
|
|
91
|
+
const rowStart = findWordStartTag(source, 'tr', rowCursor, end);
|
|
92
|
+
if (rowStart < 0) break;
|
|
93
|
+
const rowTagEnd = source.indexOf('>', rowStart);
|
|
94
|
+
if (rowTagEnd < 0 || rowTagEnd >= end) return null;
|
|
95
|
+
const rowEnd = source.indexOf(WORD_TABLE_ROW_CLOSE, rowTagEnd + 1);
|
|
96
|
+
if (rowEnd < 0 || rowEnd > end) return null;
|
|
97
|
+
const cellParagraphCounts = [];
|
|
98
|
+
const texts = [];
|
|
99
|
+
let cellCursor = rowTagEnd + 1;
|
|
100
|
+
while(cellCursor < rowEnd){
|
|
101
|
+
const cellStart = findWordStartTag(source, 'tc', cellCursor, rowEnd);
|
|
102
|
+
if (cellStart < 0) break;
|
|
103
|
+
const cellTagEnd = source.indexOf('>', cellStart);
|
|
104
|
+
if (cellTagEnd < 0 || cellTagEnd >= rowEnd) return null;
|
|
105
|
+
const cellEnd = source.indexOf(WORD_TABLE_CELL_CLOSE, cellTagEnd + 1);
|
|
106
|
+
if (cellEnd < 0 || cellEnd > rowEnd) return null;
|
|
107
|
+
let cellParagraphCount = 0;
|
|
108
|
+
let paragraphCursor = cellTagEnd + 1;
|
|
109
|
+
while(paragraphCursor < cellEnd){
|
|
110
|
+
const paragraphStart = findWordStartTag(source, 'p', paragraphCursor, cellEnd);
|
|
111
|
+
if (paragraphStart < 0) break;
|
|
112
|
+
const paragraphTagEnd = source.indexOf('>', paragraphStart);
|
|
113
|
+
if (paragraphTagEnd < 0 || paragraphTagEnd >= cellEnd) return null;
|
|
114
|
+
const paragraphEnd = source.indexOf(WORD_PARAGRAPH_CLOSE, paragraphTagEnd + 1);
|
|
115
|
+
if (paragraphEnd < 0 || paragraphEnd > cellEnd) return null;
|
|
116
|
+
texts.push(simpleText(source, paragraphTagEnd + 1, paragraphEnd));
|
|
117
|
+
cellParagraphCount += 1;
|
|
118
|
+
paragraphCount += 1;
|
|
119
|
+
paragraphCursor = paragraphEnd + WORD_PARAGRAPH_CLOSE.length;
|
|
120
|
+
}
|
|
121
|
+
if (!cellParagraphCount) {
|
|
122
|
+
texts.push('');
|
|
123
|
+
cellParagraphCount = 1;
|
|
124
|
+
paragraphCount += 1;
|
|
125
|
+
}
|
|
126
|
+
cellParagraphCounts.push(cellParagraphCount);
|
|
127
|
+
cellCursor = cellEnd + WORD_TABLE_CELL_CLOSE.length;
|
|
128
|
+
}
|
|
129
|
+
if (!cellParagraphCounts.length) return null;
|
|
130
|
+
visit({
|
|
131
|
+
cellParagraphCounts,
|
|
132
|
+
texts
|
|
133
|
+
});
|
|
134
|
+
rowCount += 1;
|
|
135
|
+
rowCursor = rowEnd + WORD_TABLE_ROW_CLOSE.length;
|
|
136
|
+
}
|
|
137
|
+
return rowCount ? {
|
|
138
|
+
paragraphCount,
|
|
139
|
+
rowCount
|
|
140
|
+
} : null;
|
|
141
|
+
}
|
|
142
|
+
function simpleText(source, start, end) {
|
|
143
|
+
let result = '';
|
|
144
|
+
let cursor = start;
|
|
145
|
+
while(cursor < end){
|
|
146
|
+
const textStart = findWordStartTag(source, 't', cursor, end);
|
|
147
|
+
if (textStart < 0) break;
|
|
148
|
+
const tagEnd = source.indexOf('>', textStart);
|
|
149
|
+
if (tagEnd < 0 || tagEnd >= end) return '';
|
|
150
|
+
const textEnd = source.indexOf(WORD_TEXT_CLOSE, tagEnd + 1);
|
|
151
|
+
if (textEnd < 0 || textEnd > end) return '';
|
|
152
|
+
result += decodeXmlText(source.slice(tagEnd + 1, textEnd));
|
|
153
|
+
cursor = textEnd + WORD_TEXT_CLOSE.length;
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
function simpleDocumentLayout(source, bodyStart = 0, bodyEnd = source.length) {
|
|
158
|
+
const base = initialSimpleDocumentLayout();
|
|
159
|
+
const sectionCandidate = source.lastIndexOf('<w:sectPr', bodyEnd);
|
|
160
|
+
const sectionStart = sectionCandidate >= bodyStart && wordTagNameBoundary(source.charCodeAt(sectionCandidate + 9)) ? sectionCandidate : bodyStart;
|
|
161
|
+
const pageSizeTag = startTag(source, 'pgSz', sectionStart, bodyEnd);
|
|
162
|
+
const width = wordIntegerAttribute(pageSizeTag, 'w');
|
|
163
|
+
const height = wordIntegerAttribute(pageSizeTag, 'h');
|
|
164
|
+
const orientation = 'landscape' === wordAttribute(pageSizeTag, 'orient') ? 'landscape' : 'portrait';
|
|
165
|
+
const geometry = width && height ? {
|
|
166
|
+
width,
|
|
167
|
+
height,
|
|
168
|
+
orientation
|
|
169
|
+
} : null;
|
|
170
|
+
const pageMarginsTag = startTag(source, 'pgMar', sectionStart, bodyEnd);
|
|
171
|
+
const margins = {
|
|
172
|
+
top: wordMarginMillimeters(pageMarginsTag, 'top', base.margins.top),
|
|
173
|
+
right: wordMarginMillimeters(pageMarginsTag, 'right', base.margins.right),
|
|
174
|
+
bottom: wordMarginMillimeters(pageMarginsTag, 'bottom', base.margins.bottom),
|
|
175
|
+
left: wordMarginMillimeters(pageMarginsTag, 'left', base.margins.left)
|
|
176
|
+
};
|
|
177
|
+
const layout = {
|
|
178
|
+
...base,
|
|
179
|
+
margins,
|
|
180
|
+
orientation,
|
|
181
|
+
...geometry ? {
|
|
182
|
+
pageSize: documentPaperSizeForGeometry(geometry),
|
|
183
|
+
pageGeometry: geometry
|
|
184
|
+
} : {}
|
|
185
|
+
};
|
|
186
|
+
return geometry ? applyDocumentPageGeometry(layout, geometry) : layout;
|
|
187
|
+
}
|
|
188
|
+
function initialSimpleDocumentLayout() {
|
|
189
|
+
return {
|
|
190
|
+
pageSize: 'a4',
|
|
191
|
+
orientation: 'portrait',
|
|
192
|
+
margins: {
|
|
193
|
+
top: 25,
|
|
194
|
+
right: 23,
|
|
195
|
+
bottom: 25,
|
|
196
|
+
left: 23
|
|
197
|
+
},
|
|
198
|
+
columns: {
|
|
199
|
+
count: 1,
|
|
200
|
+
spacing: 12,
|
|
201
|
+
separator: false
|
|
202
|
+
},
|
|
203
|
+
breakAfter: 'nextPage',
|
|
204
|
+
headerText: void 0,
|
|
205
|
+
footerText: void 0,
|
|
206
|
+
showPageNumbers: false,
|
|
207
|
+
pageNumberStart: void 0,
|
|
208
|
+
pageChrome: {
|
|
209
|
+
differentFirstPage: false,
|
|
210
|
+
differentOddEvenPages: false,
|
|
211
|
+
default: {
|
|
212
|
+
headerHtml: '',
|
|
213
|
+
footerHtml: '',
|
|
214
|
+
showPageNumber: false
|
|
215
|
+
},
|
|
216
|
+
first: {
|
|
217
|
+
headerHtml: '',
|
|
218
|
+
footerHtml: '',
|
|
219
|
+
showPageNumber: false
|
|
220
|
+
},
|
|
221
|
+
even: {
|
|
222
|
+
headerHtml: '',
|
|
223
|
+
footerHtml: '',
|
|
224
|
+
showPageNumber: false
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function elementContentRange(source, localName) {
|
|
230
|
+
const start = findWordStartTag(source, localName, 0);
|
|
231
|
+
if (start < 0) return null;
|
|
232
|
+
const tagEnd = source.indexOf('>', start);
|
|
233
|
+
if (tagEnd < 0) return null;
|
|
234
|
+
const end = source.indexOf(`</w:${localName}>`, tagEnd + 1);
|
|
235
|
+
return end < 0 ? null : {
|
|
236
|
+
end,
|
|
237
|
+
start: tagEnd + 1
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function startTag(source, localName, searchStart = 0, searchEnd = source.length) {
|
|
241
|
+
const start = findWordStartTag(source, localName, searchStart, searchEnd);
|
|
242
|
+
if (start < 0) return '';
|
|
243
|
+
const end = source.indexOf('>', start);
|
|
244
|
+
return end < 0 || end >= searchEnd ? '' : source.slice(start, end + 1);
|
|
245
|
+
}
|
|
246
|
+
function wordAttribute(source, localName) {
|
|
247
|
+
const escaped = localName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
248
|
+
return new RegExp(`(?:[A-Za-z_][\\w.-]*:)?${escaped}="([^"]*)"`).exec(source)?.[1] ?? null;
|
|
249
|
+
}
|
|
250
|
+
function wordIntegerAttribute(source, localName) {
|
|
251
|
+
const value = Number(wordAttribute(source, localName));
|
|
252
|
+
return Number.isSafeInteger(value) && value > 0 ? value : null;
|
|
253
|
+
}
|
|
254
|
+
function wordMarginMillimeters(source, name, fallback) {
|
|
255
|
+
const value = wordAttribute(source, name);
|
|
256
|
+
if (null === value) return fallback;
|
|
257
|
+
const twips = Number(value);
|
|
258
|
+
return Number.isFinite(twips) && twips >= 0 ? Math.round(twips / WORD_TWIPS_PER_MILLIMETER * 100) / 100 : fallback;
|
|
259
|
+
}
|
|
260
|
+
function simpleDocxEnvelopeElementCounts(source) {
|
|
261
|
+
let body = 0;
|
|
262
|
+
let document = 0;
|
|
263
|
+
let sectPr = 0;
|
|
264
|
+
for (const match of source.matchAll(SIMPLE_WORD_ENVELOPE_ELEMENT))if ('body' === match[1]) body += 1;
|
|
265
|
+
else if ('document' === match[1]) document += 1;
|
|
266
|
+
else sectPr += 1;
|
|
267
|
+
return {
|
|
268
|
+
body,
|
|
269
|
+
document,
|
|
270
|
+
sectPr
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
function findWordStartTag(source, localName, start, end = source.length) {
|
|
274
|
+
const prefix = `<w:${localName}`;
|
|
275
|
+
let index = source.indexOf(prefix, start);
|
|
276
|
+
while(index >= 0 && index < end){
|
|
277
|
+
if (wordTagNameBoundary(source.charCodeAt(index + prefix.length))) return index;
|
|
278
|
+
index = source.indexOf(prefix, index + prefix.length);
|
|
279
|
+
}
|
|
280
|
+
return -1;
|
|
281
|
+
}
|
|
282
|
+
function firstIndex(left, right) {
|
|
283
|
+
if (left < 0) return right;
|
|
284
|
+
if (right < 0) return left;
|
|
285
|
+
return Math.min(left, right);
|
|
286
|
+
}
|
|
287
|
+
function wordTagNameBoundary(code) {
|
|
288
|
+
return 32 === code || 9 === code || 10 === code || 13 === code || 47 === code || 62 === code;
|
|
289
|
+
}
|
|
290
|
+
function decodeXmlText(value) {
|
|
291
|
+
if (!value.includes('&')) return value;
|
|
292
|
+
return value.replace(/&(?:#(\d+)|#x([\da-f]+)|(amp|apos|gt|lt|quot));/gi, (entity, decimal, hexadecimal, named)=>{
|
|
293
|
+
if (decimal) return safeCodePoint(Number.parseInt(decimal, 10), entity);
|
|
294
|
+
if (hexadecimal) return safeCodePoint(Number.parseInt(hexadecimal, 16), entity);
|
|
295
|
+
return ({
|
|
296
|
+
amp: '&',
|
|
297
|
+
apos: "'",
|
|
298
|
+
gt: '>',
|
|
299
|
+
lt: '<',
|
|
300
|
+
quot: '"'
|
|
301
|
+
})[named.toLowerCase()] ?? entity;
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
function safeCodePoint(value, fallback) {
|
|
305
|
+
if (!Number.isSafeInteger(value) || value < 0 || value > 0x10ffff) return fallback;
|
|
306
|
+
try {
|
|
307
|
+
return String.fromCodePoint(value);
|
|
308
|
+
} catch {
|
|
309
|
+
return fallback;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
function positiveInteger(value, fallback) {
|
|
313
|
+
const number = Number(value);
|
|
314
|
+
return Number.isSafeInteger(number) && number > 0 ? number : fallback;
|
|
315
|
+
}
|
|
316
|
+
function largeDocxImportNow() {
|
|
317
|
+
return globalThis.performance?.now?.() ?? Date.now();
|
|
318
|
+
}
|
|
319
|
+
function recordLargeDocxImportMeasure(name, start, end, detail) {
|
|
320
|
+
try {
|
|
321
|
+
globalThis.performance?.measure(name, {
|
|
322
|
+
detail,
|
|
323
|
+
end,
|
|
324
|
+
start
|
|
325
|
+
});
|
|
326
|
+
} catch {}
|
|
327
|
+
}
|
|
328
|
+
const HTML_SPECIAL_CHARACTER = /[&<>"]/;
|
|
329
|
+
async function parseLargeSimpleDocxPackage(archive, options = {}) {
|
|
330
|
+
if (!largeSimpleDocxPackageIsCandidate(archive)) return null;
|
|
331
|
+
return parseLargeSimpleDocxDocumentXml(await archive.text('word/document.xml'), options);
|
|
332
|
+
}
|
|
333
|
+
function largeSimpleDocxPackageIsCandidate(archive) {
|
|
334
|
+
const wordParts = archive.paths('word/');
|
|
335
|
+
return 1 === wordParts.length && wordParts[0]?.toLowerCase() === 'word/document.xml';
|
|
336
|
+
}
|
|
337
|
+
function parseLargeSimpleDocxDocumentXml(source, options = {}) {
|
|
338
|
+
const blocks = [];
|
|
339
|
+
const html = [];
|
|
340
|
+
let tableRows = null;
|
|
341
|
+
let tableHtml = null;
|
|
342
|
+
const streamed = streamLargeSimpleDocxDocumentXml(source, options, {
|
|
343
|
+
paragraph: (text)=>{
|
|
344
|
+
if (tableRows || tableHtml) throw new Error('A table stream cannot contain a top-level paragraph.');
|
|
345
|
+
const paragraph = createLargeSimpleDocxParagraph(text);
|
|
346
|
+
blocks.push(paragraph.node);
|
|
347
|
+
html.push(paragraph.html);
|
|
348
|
+
},
|
|
349
|
+
tableEnd: ()=>{
|
|
350
|
+
if (!tableRows || !tableHtml) throw new Error('A simple DOCX table stream was not started.');
|
|
351
|
+
const table = createLargeSimpleDocxTable(tableRows, tableHtml);
|
|
352
|
+
blocks.push(table.node);
|
|
353
|
+
html.push(table.html);
|
|
354
|
+
tableRows = null;
|
|
355
|
+
tableHtml = null;
|
|
356
|
+
},
|
|
357
|
+
tableRow: (row)=>{
|
|
358
|
+
if (!tableRows || !tableHtml) throw new Error('A simple DOCX table row has no owning table.');
|
|
359
|
+
const projected = createLargeSimpleDocxTableRow(row);
|
|
360
|
+
tableRows.push(projected.node);
|
|
361
|
+
tableHtml.push(projected.html);
|
|
362
|
+
},
|
|
363
|
+
tableStart: ()=>{
|
|
364
|
+
if (tableRows || tableHtml) throw new Error('Nested simple DOCX tables are not supported.');
|
|
365
|
+
tableRows = [];
|
|
366
|
+
tableHtml = [];
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
if (!streamed || tableRows || tableHtml || !blocks.length) return null;
|
|
370
|
+
return createLargeSimpleDocxParseResult(streamed, blocks, html, options);
|
|
371
|
+
}
|
|
372
|
+
function createLargeSimpleDocxParseResult(streamed, blocks, html, options = {}) {
|
|
373
|
+
const sectionId = 'document-section-1';
|
|
374
|
+
const projectionStartedAt = work_docx_large_document_import_largeDocxImportNow();
|
|
375
|
+
const sectionAttributes = documentSectionDomAttributes(streamed.layout, sectionId);
|
|
376
|
+
const canonicalHtml = `<section${htmlAttributes(sectionAttributes)}>${html.join('')}</section>`;
|
|
377
|
+
work_docx_large_document_import_recordLargeDocxImportMeasure('a3s-office.document.large-simple-html', projectionStartedAt, work_docx_large_document_import_largeDocxImportNow());
|
|
378
|
+
const windowingStartedAt = work_docx_large_document_import_largeDocxImportNow();
|
|
379
|
+
const root = windowDocumentModel({
|
|
380
|
+
type: 'doc',
|
|
381
|
+
content: [
|
|
382
|
+
{
|
|
383
|
+
type: 'documentSection',
|
|
384
|
+
attrs: documentSectionModelAttributes(streamed.layout, sectionId),
|
|
385
|
+
content: blocks
|
|
386
|
+
}
|
|
387
|
+
]
|
|
388
|
+
}, {
|
|
389
|
+
...options.windowing,
|
|
390
|
+
trustedIntegrityFeatures: 0
|
|
391
|
+
});
|
|
392
|
+
work_docx_large_document_import_recordLargeDocxImportMeasure('a3s-office.document.large-simple-windowing', windowingStartedAt, work_docx_large_document_import_largeDocxImportNow());
|
|
393
|
+
return {
|
|
394
|
+
html: canonicalHtml,
|
|
395
|
+
layout: streamed.layout,
|
|
396
|
+
logicalBlockCount: streamed.logicalBlockCount,
|
|
397
|
+
paragraphCount: streamed.paragraphCount,
|
|
398
|
+
root,
|
|
399
|
+
tableRowCount: streamed.tableRowCount
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
function createLargeSimpleDocxTable(rows, htmlRows) {
|
|
403
|
+
return {
|
|
404
|
+
html: `<table data-office-table-imported="true"><tbody>${htmlRows.join('')}</tbody></table>`,
|
|
405
|
+
node: {
|
|
406
|
+
type: 'table',
|
|
407
|
+
attrs: {
|
|
408
|
+
officeImported: true
|
|
409
|
+
},
|
|
410
|
+
content: rows
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
function createLargeSimpleDocxParagraph(text) {
|
|
415
|
+
return {
|
|
416
|
+
html: `<p>${escapeHtml(text)}</p>`,
|
|
417
|
+
node: {
|
|
418
|
+
type: 'paragraph',
|
|
419
|
+
...text ? {
|
|
420
|
+
content: [
|
|
421
|
+
{
|
|
422
|
+
type: 'text',
|
|
423
|
+
text
|
|
424
|
+
}
|
|
425
|
+
]
|
|
426
|
+
} : {}
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
function createLargeSimpleDocxTableRow(row) {
|
|
431
|
+
const cellNodes = [];
|
|
432
|
+
const cellHtml = [];
|
|
433
|
+
let textIndex = 0;
|
|
434
|
+
for (const paragraphCount of row.cellParagraphCounts){
|
|
435
|
+
const paragraphNodes = [];
|
|
436
|
+
let paragraphsHtml = '';
|
|
437
|
+
for(let index = 0; index < paragraphCount; index += 1){
|
|
438
|
+
const text = row.texts[textIndex] ?? '';
|
|
439
|
+
const projected = createLargeSimpleDocxParagraph(text);
|
|
440
|
+
paragraphNodes.push(projected.node);
|
|
441
|
+
paragraphsHtml += projected.html;
|
|
442
|
+
textIndex += 1;
|
|
443
|
+
}
|
|
444
|
+
cellNodes.push({
|
|
445
|
+
type: 'tableCell',
|
|
446
|
+
content: paragraphNodes
|
|
447
|
+
});
|
|
448
|
+
cellHtml.push(`<td>${paragraphsHtml}</td>`);
|
|
449
|
+
}
|
|
450
|
+
return {
|
|
451
|
+
html: `<tr>${cellHtml.join('')}</tr>`,
|
|
452
|
+
node: {
|
|
453
|
+
type: 'tableRow',
|
|
454
|
+
content: cellNodes
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
function largeSimpleDocxContent(result) {
|
|
459
|
+
return {
|
|
460
|
+
type: 'document',
|
|
461
|
+
html: result.html,
|
|
462
|
+
pageSize: result.layout.pageSize,
|
|
463
|
+
orientation: result.layout.orientation,
|
|
464
|
+
margins: result.layout.margins,
|
|
465
|
+
columns: result.layout.columns,
|
|
466
|
+
headerText: result.layout.headerText,
|
|
467
|
+
footerText: result.layout.footerText,
|
|
468
|
+
showPageNumbers: result.layout.showPageNumbers,
|
|
469
|
+
pageNumberStart: result.layout.pageNumberStart,
|
|
470
|
+
pageChrome: result.layout.pageChrome,
|
|
471
|
+
pageBorders: result.layout.pageBorders,
|
|
472
|
+
pageMargins: result.layout.pageMargins,
|
|
473
|
+
pageGeometry: result.layout.pageGeometry,
|
|
474
|
+
paperSource: result.layout.paperSource
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
function largeSimpleDocxCompatibilityReport(file, result) {
|
|
478
|
+
return {
|
|
479
|
+
sourceFormat: 'DOCX',
|
|
480
|
+
sourceName: file.name,
|
|
481
|
+
assessedAt: Date.now(),
|
|
482
|
+
issues: [
|
|
483
|
+
{
|
|
484
|
+
code: 'docx.page-layout',
|
|
485
|
+
feature: 'Page layout',
|
|
486
|
+
message: 'Paper size and margins are preserved; exact pagination and line wrapping may normalize.',
|
|
487
|
+
severity: 'warning'
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
code: 'docx.package-state',
|
|
491
|
+
feature: 'OOXML package state',
|
|
492
|
+
message: 'The plain source package remains attached for source-backed export.',
|
|
493
|
+
severity: 'info'
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
code: 'docx.large-document-windowing',
|
|
497
|
+
feature: 'Large document rendering',
|
|
498
|
+
message: `${result.logicalBlockCount} logical block(s) use bounded viewport rendering while the complete structured model remains editable.`,
|
|
499
|
+
severity: 'info'
|
|
500
|
+
},
|
|
501
|
+
...result.tableRowCount ? [
|
|
502
|
+
{
|
|
503
|
+
code: 'docx.tables',
|
|
504
|
+
feature: 'Tables',
|
|
505
|
+
message: `${result.tableRowCount} table row(s) remain editable and are joined into canonical DOCX tables on export.`,
|
|
506
|
+
severity: 'info'
|
|
507
|
+
}
|
|
508
|
+
] : []
|
|
509
|
+
]
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
function documentSectionModelAttributes(layout, id) {
|
|
513
|
+
const attributes = documentSectionDomAttributes(layout, id);
|
|
514
|
+
return {
|
|
515
|
+
id,
|
|
516
|
+
pageSize: layout.pageSize,
|
|
517
|
+
orientation: layout.orientation,
|
|
518
|
+
marginTop: layout.margins.top,
|
|
519
|
+
marginRight: layout.margins.right,
|
|
520
|
+
marginBottom: layout.margins.bottom,
|
|
521
|
+
marginLeft: layout.margins.left,
|
|
522
|
+
columnCount: layout.columns.count,
|
|
523
|
+
columnSpacing: layout.columns.spacing,
|
|
524
|
+
columnSeparator: layout.columns.separator,
|
|
525
|
+
columnLayout: attributes['data-section-column-layout'] ?? '',
|
|
526
|
+
breakAfter: layout.breakAfter,
|
|
527
|
+
headerText: layout.headerText ?? '',
|
|
528
|
+
footerText: layout.footerText ?? '',
|
|
529
|
+
showPageNumbers: Boolean(layout.showPageNumbers),
|
|
530
|
+
pageNumberStart: layout.pageNumberStart ?? null,
|
|
531
|
+
pageChrome: attributes['data-section-page-chrome'] ?? '',
|
|
532
|
+
pageBorders: attributes['data-section-page-borders'] ?? '',
|
|
533
|
+
pageMargins: attributes['data-section-page-margins'] ?? '',
|
|
534
|
+
pageGeometry: attributes['data-section-page-geometry'] ?? '',
|
|
535
|
+
paperSource: attributes['data-section-paper-source'] ?? '',
|
|
536
|
+
documentGridType: attributes['data-section-document-grid-type'] ?? '',
|
|
537
|
+
documentGridLinePitch: null
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
function htmlAttributes(attributes) {
|
|
541
|
+
return Object.entries(attributes).map(([name, value])=>` ${name}="${escapeHtml(value)}"`).join('');
|
|
542
|
+
}
|
|
543
|
+
function escapeHtml(value) {
|
|
544
|
+
if (!HTML_SPECIAL_CHARACTER.test(value)) return value;
|
|
545
|
+
return value.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"');
|
|
546
|
+
}
|
|
547
|
+
function work_docx_large_document_import_largeDocxImportNow() {
|
|
548
|
+
return globalThis.performance?.now?.() ?? Date.now();
|
|
549
|
+
}
|
|
550
|
+
function work_docx_large_document_import_recordLargeDocxImportMeasure(name, start, end, detail) {
|
|
551
|
+
try {
|
|
552
|
+
globalThis.performance?.measure(name, {
|
|
553
|
+
detail,
|
|
554
|
+
end,
|
|
555
|
+
start
|
|
556
|
+
});
|
|
557
|
+
} catch {}
|
|
558
|
+
}
|
|
559
|
+
export { createLargeSimpleDocxParagraph, createLargeSimpleDocxParseResult, createLargeSimpleDocxTable, largeSimpleDocxCompatibilityReport, largeSimpleDocxContent, largeSimpleDocxPackageIsCandidate, parseLargeSimpleDocxPackage };
|