@a3s-lab/office 0.33.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -19
- package/dist/0~5809.js +123 -0
- package/dist/{0~7614.js → 0~7828.js} +376 -5
- package/dist/0~pdf-viewer.js +5 -1
- package/dist/0~presentation-editor.js +597 -71
- package/dist/0~spreadsheet-editor.js +166 -18
- package/dist/0~work-pptx-export.js +50 -14
- package/dist/0~work-pptx-import.js +21 -9
- package/dist/4121.js +122 -1
- package/dist/4560.js +33 -0
- package/dist/internal/features/work/editors/presentation-animation-panel.d.ts +11 -0
- package/dist/internal/features/work/editors/presentation-command-types.d.ts +16 -1
- package/dist/internal/features/work/editors/presentation-editor-focus.d.ts +2 -0
- package/dist/internal/features/work/editors/presentation-presenter-view.d.ts +2 -1
- package/dist/internal/features/work/editors/presentation-slide-canvas.d.ts +11 -3
- package/dist/internal/features/work/editors/presentation-text-editor.d.ts +7 -0
- package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +10 -0
- package/dist/internal/features/work/editors/spreadsheet-command-selection.d.ts +22 -1
- package/dist/internal/features/work/editors/use-presentation-animation-commands.d.ts +15 -0
- package/dist/internal/features/work/editors/use-presentation-selection.d.ts +1 -1
- package/dist/internal/features/work/work-pptx-animation.d.ts +13 -0
- package/dist/internal/features/work/work-pptx-groups.d.ts +4 -0
- package/dist/internal/features/work/work-presentation-animation-constraints.d.ts +4 -0
- package/dist/internal/features/work/work-presentation-animation.d.ts +20 -0
- package/dist/internal/features/work/work-presentation-clipboard.d.ts +10 -3
- package/dist/internal/features/work/work-types.d.ts +17 -0
- package/dist/office-kernel.wasm +0 -0
- package/dist/styles.css +123 -0
- package/package.json +19 -13
- package/dist/0~work-presentation-transition.js +0 -38
|
@@ -5315,6 +5315,70 @@ function spreadsheetCellFillRangeIsSafe(range) {
|
|
|
5315
5315
|
function sameSpreadsheetCellRange(left, right) {
|
|
5316
5316
|
return left.row[0] === right.row[0] && left.row[1] === right.row[1] && left.column[0] === right.column[0] && left.column[1] === right.column[1];
|
|
5317
5317
|
}
|
|
5318
|
+
function canEditSpreadsheetSelection(context) {
|
|
5319
|
+
return Boolean(context.editable && context.workbook && context.targetSheetId);
|
|
5320
|
+
}
|
|
5321
|
+
function spreadsheetLiveCommandRange(context) {
|
|
5322
|
+
const selection = spreadsheetLiveCommandSelection(context);
|
|
5323
|
+
return spreadsheetSingleRange(selection ?? context.fallbackRange);
|
|
5324
|
+
}
|
|
5325
|
+
function spreadsheetLiveCommandSelection(context) {
|
|
5326
|
+
return spreadsheetLiveCommandSelections(context)?.at(-1);
|
|
5327
|
+
}
|
|
5328
|
+
function spreadsheetLiveCommandSelections(context) {
|
|
5329
|
+
const shadow = context.selectionRef?.current;
|
|
5330
|
+
if (shadow?.sheetId === context.targetSheetId) return [
|
|
5331
|
+
shadow.selection
|
|
5332
|
+
];
|
|
5333
|
+
return context.workbook?.getSelection();
|
|
5334
|
+
}
|
|
5335
|
+
function acceptSpreadsheetSelectionChange(selectionRef, sheetId, selection) {
|
|
5336
|
+
const nextSelection = finiteSpreadsheetSelection(selection);
|
|
5337
|
+
const requested = selectionRef.requested;
|
|
5338
|
+
if (requested && (requested.sheetId !== sheetId || !sameSpreadsheetSelectionValue(requested.selection, nextSelection))) return null;
|
|
5339
|
+
const next = {
|
|
5340
|
+
sheetId,
|
|
5341
|
+
selection: nextSelection
|
|
5342
|
+
};
|
|
5343
|
+
selectionRef.current = next;
|
|
5344
|
+
return next;
|
|
5345
|
+
}
|
|
5346
|
+
function rememberSpreadsheetCommandSelection(context, selection) {
|
|
5347
|
+
if (!context.selectionRef || !context.targetSheetId) return;
|
|
5348
|
+
const next = {
|
|
5349
|
+
...selection,
|
|
5350
|
+
row: [
|
|
5351
|
+
...selection.row
|
|
5352
|
+
],
|
|
5353
|
+
column: [
|
|
5354
|
+
...selection.column
|
|
5355
|
+
]
|
|
5356
|
+
};
|
|
5357
|
+
context.selectionRef.current = {
|
|
5358
|
+
sheetId: context.targetSheetId,
|
|
5359
|
+
selection: next
|
|
5360
|
+
};
|
|
5361
|
+
context.selectionRef.requested = {
|
|
5362
|
+
sheetId: context.targetSheetId,
|
|
5363
|
+
selection: {
|
|
5364
|
+
...next,
|
|
5365
|
+
row: [
|
|
5366
|
+
...next.row
|
|
5367
|
+
],
|
|
5368
|
+
column: [
|
|
5369
|
+
...next.column
|
|
5370
|
+
]
|
|
5371
|
+
}
|
|
5372
|
+
};
|
|
5373
|
+
}
|
|
5374
|
+
function releaseSpreadsheetSelectionRequest(selectionRef) {
|
|
5375
|
+
selectionRef.requested = null;
|
|
5376
|
+
}
|
|
5377
|
+
function sameSpreadsheetSelectionValue(left, right) {
|
|
5378
|
+
const normalizedLeft = finiteSpreadsheetSelection(left);
|
|
5379
|
+
const normalizedRight = finiteSpreadsheetSelection(right);
|
|
5380
|
+
return normalizedLeft.row[0] === normalizedRight.row[0] && normalizedLeft.row[1] === normalizedRight.row[1] && normalizedLeft.column[0] === normalizedRight.column[0] && normalizedLeft.column[1] === normalizedRight.column[1] && normalizedLeft.row_focus === normalizedRight.row_focus && normalizedLeft.column_focus === normalizedRight.column_focus;
|
|
5381
|
+
}
|
|
5318
5382
|
function createSpreadsheetCellFillExtension() {
|
|
5319
5383
|
return createOfficeEditorExtension({
|
|
5320
5384
|
name: 'spreadsheetCellFill',
|
|
@@ -5365,9 +5429,11 @@ function materializeSpreadsheetCellFillRows(sheet, plan) {
|
|
|
5365
5429
|
}
|
|
5366
5430
|
function spreadsheetSelectedCellFillPlan(context, direction) {
|
|
5367
5431
|
if (!context.editable || !context.workbook || !context.targetSheetId || context.targetSheetId !== context.activeSheetId) return null;
|
|
5368
|
-
const selections = context
|
|
5432
|
+
const selections = spreadsheetLiveCommandSelections(context);
|
|
5369
5433
|
if (selections?.length !== 1) return null;
|
|
5370
|
-
const
|
|
5434
|
+
const selection = selections[0];
|
|
5435
|
+
if (!selection) return null;
|
|
5436
|
+
const plan = planSpreadsheetCellFill(selection, direction);
|
|
5371
5437
|
if (!plan) return null;
|
|
5372
5438
|
const sheet = context.content.sheets.find((candidate)=>candidate.id === context.targetSheetId);
|
|
5373
5439
|
return canApplySpreadsheetCellFill(sheet, plan) ? plan : null;
|
|
@@ -6323,13 +6389,6 @@ function applySelectedCellStyle(context, preset) {
|
|
|
6323
6389
|
function liveSpreadsheetCellStyleRange(context) {
|
|
6324
6390
|
return spreadsheetSingleRange(context.workbook?.getSelection()?.at(-1) ?? context.fallbackRange);
|
|
6325
6391
|
}
|
|
6326
|
-
function canEditSpreadsheetSelection(context) {
|
|
6327
|
-
return Boolean(context.editable && context.workbook && context.targetSheetId);
|
|
6328
|
-
}
|
|
6329
|
-
function spreadsheetLiveCommandRange(context) {
|
|
6330
|
-
const selection = context.workbook?.getSelection()?.at(-1);
|
|
6331
|
-
return spreadsheetSingleRange(selection ?? context.fallbackRange);
|
|
6332
|
-
}
|
|
6333
6392
|
const MAX_SPREADSHEET_ROWS = 1048576;
|
|
6334
6393
|
const spreadsheetPasteContentOptions = [
|
|
6335
6394
|
{
|
|
@@ -8493,7 +8552,7 @@ function updateSpreadsheetSelection(context, storage, update) {
|
|
|
8493
8552
|
if (!context.workbook || !context.targetSheetId) return false;
|
|
8494
8553
|
const sheet = context.content.sheets.find((candidate)=>candidate.id === context.targetSheetId);
|
|
8495
8554
|
if (!sheet) return false;
|
|
8496
|
-
const liveSelection = context
|
|
8555
|
+
const liveSelection = spreadsheetLiveCommandSelection(context) ?? context.fallbackRange;
|
|
8497
8556
|
const rememberedFocus = storage.focus;
|
|
8498
8557
|
const selection = rememberedFocus && spreadsheetSelectionContainsFocus(liveSelection, rememberedFocus) ? {
|
|
8499
8558
|
...liveSelection,
|
|
@@ -8507,6 +8566,7 @@ function updateSpreadsheetSelection(context, storage, update) {
|
|
|
8507
8566
|
], {
|
|
8508
8567
|
id: context.targetSheetId
|
|
8509
8568
|
});
|
|
8569
|
+
rememberSpreadsheetCommandSelection(context, next);
|
|
8510
8570
|
storage.focus = {
|
|
8511
8571
|
row: next.row_focus ?? next.row[1] ?? next.row[0] ?? 0,
|
|
8512
8572
|
column: next.column_focus ?? next.column[1] ?? next.column[0] ?? 0
|
|
@@ -10010,6 +10070,16 @@ function pasteCells(context, values) {
|
|
|
10010
10070
|
], {
|
|
10011
10071
|
id: context.targetSheetId
|
|
10012
10072
|
});
|
|
10073
|
+
rememberSpreadsheetCommandSelection(context, {
|
|
10074
|
+
row: [
|
|
10075
|
+
...range.row
|
|
10076
|
+
],
|
|
10077
|
+
column: [
|
|
10078
|
+
...range.column
|
|
10079
|
+
],
|
|
10080
|
+
row_focus: range.row[0],
|
|
10081
|
+
column_focus: range.column[0]
|
|
10082
|
+
});
|
|
10013
10083
|
} catch {}
|
|
10014
10084
|
syncSpreadsheetFormulaBar(context, data[0][0]);
|
|
10015
10085
|
return true;
|
|
@@ -25395,6 +25465,60 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25395
25465
|
const editorFocusOrigin = useOfficeEditorFocusOrigin();
|
|
25396
25466
|
const workbookRef = useRef(null);
|
|
25397
25467
|
const projectedWorkbookSheetsRef = useRef([]);
|
|
25468
|
+
useLayoutEffect(()=>{
|
|
25469
|
+
const container = spreadsheetCanvasRef.current;
|
|
25470
|
+
if (!container || preview) return;
|
|
25471
|
+
let pendingEditor = null;
|
|
25472
|
+
let pointerEnteredEditor = false;
|
|
25473
|
+
const moveEditorCaretToEnd = (editor)=>{
|
|
25474
|
+
if (document.activeElement !== editor || !editor.isConnected || !editor.textContent) return false;
|
|
25475
|
+
const selection = document.getSelection();
|
|
25476
|
+
if (!selection) return false;
|
|
25477
|
+
const range = document.createRange();
|
|
25478
|
+
range.selectNodeContents(editor);
|
|
25479
|
+
range.collapse(false);
|
|
25480
|
+
selection.removeAllRanges();
|
|
25481
|
+
selection.addRange(range);
|
|
25482
|
+
return true;
|
|
25483
|
+
};
|
|
25484
|
+
const handlePointerDown = (event)=>{
|
|
25485
|
+
pointerEnteredEditor = event.target instanceof Element && Boolean(event.target.closest('.luckysheet-cell-input'));
|
|
25486
|
+
};
|
|
25487
|
+
const handleFocusIn = (event)=>{
|
|
25488
|
+
const target = event.target;
|
|
25489
|
+
const editor = target instanceof Element ? target.closest('.luckysheet-cell-input') : null;
|
|
25490
|
+
if (!editor || pointerEnteredEditor) {
|
|
25491
|
+
pendingEditor = null;
|
|
25492
|
+
pointerEnteredEditor = false;
|
|
25493
|
+
return;
|
|
25494
|
+
}
|
|
25495
|
+
pendingEditor = editor;
|
|
25496
|
+
queueMicrotask(()=>{
|
|
25497
|
+
if (pendingEditor === editor && moveEditorCaretToEnd(editor)) pendingEditor = null;
|
|
25498
|
+
});
|
|
25499
|
+
};
|
|
25500
|
+
const observer = new MutationObserver(()=>{
|
|
25501
|
+
const editor = pendingEditor;
|
|
25502
|
+
if (!editor || document.activeElement !== editor) return;
|
|
25503
|
+
if (!editor.textContent) return;
|
|
25504
|
+
moveEditorCaretToEnd(editor);
|
|
25505
|
+
pendingEditor = null;
|
|
25506
|
+
});
|
|
25507
|
+
container.addEventListener('pointerdown', handlePointerDown, true);
|
|
25508
|
+
container.addEventListener('focusin', handleFocusIn, true);
|
|
25509
|
+
observer.observe(container, {
|
|
25510
|
+
characterData: true,
|
|
25511
|
+
childList: true,
|
|
25512
|
+
subtree: true
|
|
25513
|
+
});
|
|
25514
|
+
return ()=>{
|
|
25515
|
+
container.removeEventListener('pointerdown', handlePointerDown, true);
|
|
25516
|
+
container.removeEventListener('focusin', handleFocusIn, true);
|
|
25517
|
+
observer.disconnect();
|
|
25518
|
+
};
|
|
25519
|
+
}, [
|
|
25520
|
+
preview
|
|
25521
|
+
]);
|
|
25398
25522
|
const spreadsheetZoomRef = useRef(100);
|
|
25399
25523
|
const [workbookInstance, setWorkbookInstance] = useState(null);
|
|
25400
25524
|
const bindWorkbookInstance = useCallback((instance)=>{
|
|
@@ -25413,6 +25537,10 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25413
25537
|
const [panel, setPanel] = useState(null);
|
|
25414
25538
|
const panelTriggerRef = useRef(null);
|
|
25415
25539
|
const [selectionState, setSelectionState] = useState(null);
|
|
25540
|
+
const selectionStateRef = useRef({
|
|
25541
|
+
current: null,
|
|
25542
|
+
requested: null
|
|
25543
|
+
});
|
|
25416
25544
|
const formatPainterSelectionHandlerRef = useRef((_sheetId, _selection)=>void 0);
|
|
25417
25545
|
const [contextMenu, setContextMenu] = useState(null);
|
|
25418
25546
|
const [formatCellsDialog, setFormatCellsDialog] = useState(null);
|
|
@@ -25588,15 +25716,16 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25588
25716
|
collaborationView?.activateSheet(id);
|
|
25589
25717
|
if (previewRef.current) setPreviewActiveSheetId(id);
|
|
25590
25718
|
else setNavigationActiveSheetId(id);
|
|
25719
|
+
selectionStateRef.current.current = null;
|
|
25720
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
25591
25721
|
setSelectionState(null);
|
|
25592
25722
|
},
|
|
25593
25723
|
afterSelectionChange: (sheetId, selection)=>{
|
|
25594
|
-
|
|
25595
|
-
|
|
25596
|
-
|
|
25597
|
-
|
|
25598
|
-
|
|
25599
|
-
formatPainterSelectionHandlerRef.current(sheetId, selection);
|
|
25724
|
+
const next = acceptSpreadsheetSelectionChange(selectionStateRef.current, sheetId, selection);
|
|
25725
|
+
if (!next) return;
|
|
25726
|
+
collaborationView?.select(sheetId, next.selection);
|
|
25727
|
+
setSelectionState(next);
|
|
25728
|
+
formatPainterSelectionHandlerRef.current(sheetId, next.selection);
|
|
25600
25729
|
},
|
|
25601
25730
|
beforeUpdateCell: (row, column)=>{
|
|
25602
25731
|
const sheet = contentRef.current.sheets.find((candidate)=>candidate.id === activeSheetIdRef.current);
|
|
@@ -25876,6 +26005,8 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25876
26005
|
if (!sheet) return false;
|
|
25877
26006
|
activeSheetIdRef.current = sheetId;
|
|
25878
26007
|
if (collaborationView && !collaborationView.activateSheet(sheetId)) return false;
|
|
26008
|
+
selectionStateRef.current.current = null;
|
|
26009
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
25879
26010
|
setSelectionState(null);
|
|
25880
26011
|
if (previewRef.current) setPreviewActiveSheetId(sheetId);
|
|
25881
26012
|
try {
|
|
@@ -25910,7 +26041,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25910
26041
|
targetRow: activeCell.row,
|
|
25911
26042
|
targetColumn: activeCell.column
|
|
25912
26043
|
});
|
|
25913
|
-
|
|
26044
|
+
const nextSelection = {
|
|
25914
26045
|
sheetId,
|
|
25915
26046
|
selection: {
|
|
25916
26047
|
row: [
|
|
@@ -25922,7 +26053,21 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
25922
26053
|
row_focus: activeCell.row,
|
|
25923
26054
|
column_focus: activeCell.column
|
|
25924
26055
|
}
|
|
25925
|
-
}
|
|
26056
|
+
};
|
|
26057
|
+
selectionStateRef.current.current = nextSelection;
|
|
26058
|
+
selectionStateRef.current.requested = {
|
|
26059
|
+
sheetId,
|
|
26060
|
+
selection: {
|
|
26061
|
+
...nextSelection.selection,
|
|
26062
|
+
row: [
|
|
26063
|
+
...nextSelection.selection.row
|
|
26064
|
+
],
|
|
26065
|
+
column: [
|
|
26066
|
+
...nextSelection.selection.column
|
|
26067
|
+
]
|
|
26068
|
+
}
|
|
26069
|
+
};
|
|
26070
|
+
setSelectionState(nextSelection);
|
|
25926
26071
|
} catch {
|
|
25927
26072
|
return false;
|
|
25928
26073
|
}
|
|
@@ -26043,6 +26188,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
26043
26188
|
toggle: (attribute)=>richTextSelectionRef.current?.toggle(contentRef.current, acceptSpreadsheetCommandChange, attribute) ?? false
|
|
26044
26189
|
},
|
|
26045
26190
|
selection: selectionState,
|
|
26191
|
+
selectionRef: selectionStateRef.current,
|
|
26046
26192
|
table: spreadsheetTable.commandPort,
|
|
26047
26193
|
targetSheetGridSize,
|
|
26048
26194
|
targetSheetId: toolbarSheetId,
|
|
@@ -26150,6 +26296,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
26150
26296
|
if ('Escape' === event.key && isSpreadsheetCellEditingTarget(event.target)) requestAnimationFrame(()=>focusSpreadsheetGrid(spreadsheetCanvasRef.current));
|
|
26151
26297
|
};
|
|
26152
26298
|
const handleSpreadsheetKeyDownCapture = (event)=>{
|
|
26299
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
26153
26300
|
if ('Alt' === event.key && !event.repeat && event.target instanceof Element && event.target.closest('.fortune-sheet-overlay') && reserveAutoFilterAltKey()) {
|
|
26154
26301
|
event.preventDefault();
|
|
26155
26302
|
event.stopPropagation();
|
|
@@ -26158,6 +26305,7 @@ function SpreadsheetEditorSurface({ autoFocus = true, content, collaborationHist
|
|
|
26158
26305
|
handleSpreadsheetEditingEscape(event);
|
|
26159
26306
|
};
|
|
26160
26307
|
const handleSpreadsheetPointerDownCapture = (event)=>{
|
|
26308
|
+
releaseSpreadsheetSelectionRequest(selectionStateRef.current);
|
|
26161
26309
|
const controller = richTextSelectionRef.current;
|
|
26162
26310
|
if (!controller) return;
|
|
26163
26311
|
if (!isSpreadsheetRichTextFormatPointerTarget(event.target)) return void controller.clear();
|
|
@@ -3,7 +3,7 @@ import { normalizeRadarStyle, presentationChartShowsLegend, presentationChartAxe
|
|
|
3
3
|
import { directChildren, xmlNamespacePrefix, parseXml, firstDescendant, directChild, descendants, childPath, attribute } from "./4121.js";
|
|
4
4
|
import { workSpreadsheetChartAxisShowsMajorGridlinesByDefault, workSpreadsheetChartAxisDefaultLabelPosition, workSpreadsheetChartAxisIsCategoryAxis, workSpreadsheetChartAxisIsValueAxis } from "./8715.js";
|
|
5
5
|
import { presentationGroupPath, withPresentationDesign } from "./0~1403.js";
|
|
6
|
-
import { patchPptxChartLayoutAndSeriesStyles, patchPptxTransitions, patchPptxComments, patchPptxChartDataLabels, patchPptxChartSeriesAnalysis } from "./0~
|
|
6
|
+
import { patchPptxChartLayoutAndSeriesStyles, patchPptxTransitions, patchPptxComments, patchPptxChartDataLabels, patchPptxChartSeriesAnalysis, patchPptxAnimations } from "./0~7828.js";
|
|
7
7
|
const DRAWING_NAMESPACE = 'http://schemas.openxmlformats.org/drawingml/2006/main';
|
|
8
8
|
async function patchPptxChartAxes(buffer, slides) {
|
|
9
9
|
const charts = slides.flatMap((slide)=>slide.elements.flatMap((element)=>'chart' === element.type && element.chart ? [
|
|
@@ -270,27 +270,40 @@ const PRESENTATIONML_NAMESPACE = 'http://schemas.openxmlformats.org/presentation
|
|
|
270
270
|
const DRAWINGML_NAMESPACE = 'http://schemas.openxmlformats.org/drawingml/2006/main';
|
|
271
271
|
const GROUPABLE_PART = /^ppt\/(?:slides|slideLayouts|slideMasters)\/[^/]+\.xml$/;
|
|
272
272
|
class PptxGroupExportRegistry {
|
|
273
|
+
animatedElementKeys = new Set();
|
|
273
274
|
bindings = new Map();
|
|
275
|
+
bindingsByElement = new Map();
|
|
274
276
|
roleCounts = new Map();
|
|
275
277
|
markerSequence = 0;
|
|
276
278
|
get size() {
|
|
277
279
|
return this.bindings.size;
|
|
278
280
|
}
|
|
281
|
+
registerAnimatedElements(scope, elementIds) {
|
|
282
|
+
for (const elementId of elementIds)this.animatedElementKeys.add(exportElementKey(scope, elementId));
|
|
283
|
+
}
|
|
279
284
|
objectName(scope, element, role) {
|
|
280
285
|
const groupPath = presentationGroupPath(element);
|
|
281
|
-
|
|
286
|
+
const elementKey = exportElementKey(scope, element.id);
|
|
287
|
+
if (!groupPath.length && !this.animatedElementKeys.has(elementKey)) return;
|
|
288
|
+
const existing = this.bindingsByElement.get(elementKey);
|
|
289
|
+
if (existing) return existing.marker;
|
|
282
290
|
const roleCount = (this.roleCounts.get(role) ?? 0) + 1;
|
|
283
291
|
this.roleCounts.set(role, roleCount);
|
|
284
292
|
this.markerSequence += 1;
|
|
285
293
|
const marker = `${EXPORT_MARKER_PREFIX}${this.markerSequence}`;
|
|
286
|
-
|
|
294
|
+
const binding = {
|
|
287
295
|
displayName: `${pptxRoleName(role)} ${roleCount}`,
|
|
288
296
|
groupPath,
|
|
289
297
|
groupScope: scope,
|
|
290
298
|
marker
|
|
291
|
-
}
|
|
299
|
+
};
|
|
300
|
+
this.bindings.set(marker, binding);
|
|
301
|
+
this.bindingsByElement.set(elementKey, binding);
|
|
292
302
|
return marker;
|
|
293
303
|
}
|
|
304
|
+
markerForElement(scope, elementId) {
|
|
305
|
+
return this.bindingsByElement.get(exportElementKey(scope, elementId))?.marker;
|
|
306
|
+
}
|
|
294
307
|
binding(marker) {
|
|
295
308
|
return this.bindings.get(marker);
|
|
296
309
|
}
|
|
@@ -315,7 +328,7 @@ async function patchPptxNativeGroups(buffer, registry) {
|
|
|
315
328
|
}
|
|
316
329
|
for (const binding of registry.values()){
|
|
317
330
|
const count = found.get(binding.marker) ?? 0;
|
|
318
|
-
if (1 !== count) throw new Error(`PPTX
|
|
331
|
+
if (1 !== count) throw new Error(`PPTX export expected one generated object for ${binding.displayName}, but found ${count}.`);
|
|
319
332
|
}
|
|
320
333
|
return archive.generateAsync({
|
|
321
334
|
type: 'arraybuffer',
|
|
@@ -323,6 +336,7 @@ async function patchPptxNativeGroups(buffer, registry) {
|
|
|
323
336
|
});
|
|
324
337
|
}
|
|
325
338
|
function patchPptxShapeTree(shapeTree, registry, found) {
|
|
339
|
+
normalizePptxNonVisualIds(shapeTree);
|
|
326
340
|
const sceneNodes = directChildren(shapeTree).filter(isPptxSceneNode).map((node, order)=>{
|
|
327
341
|
const properties = firstDescendant(node, 'cNvPr');
|
|
328
342
|
const objectName = properties ? attribute(properties, 'name') : null;
|
|
@@ -342,9 +356,9 @@ function patchPptxShapeTree(shapeTree, registry, found) {
|
|
|
342
356
|
});
|
|
343
357
|
if (!sceneNodes.some((item)=>item.binding)) return false;
|
|
344
358
|
const roots = new Map();
|
|
345
|
-
const rootNodes = sceneNodes.filter((item)=>!item.binding);
|
|
359
|
+
const rootNodes = sceneNodes.filter((item)=>!item.binding?.groupPath.length);
|
|
346
360
|
for (const item of sceneNodes){
|
|
347
|
-
if (!item.binding) continue;
|
|
361
|
+
if (!item.binding?.groupPath.length) continue;
|
|
348
362
|
let siblings = roots;
|
|
349
363
|
let bucket;
|
|
350
364
|
for (const groupId of item.binding.groupPath){
|
|
@@ -378,7 +392,6 @@ function patchPptxShapeTree(shapeTree, registry, found) {
|
|
|
378
392
|
].sort((left, right)=>left.order - right.order);
|
|
379
393
|
const extensionList = directChild(shapeTree, 'extLst') ?? null;
|
|
380
394
|
for (const item of renderedRoots)shapeTree.insertBefore(item.node, extensionList);
|
|
381
|
-
normalizePptxNonVisualIds(shapeTree);
|
|
382
395
|
return true;
|
|
383
396
|
}
|
|
384
397
|
function renderPptxGroup(bucket, document, nextId, nextGroupNumber) {
|
|
@@ -492,6 +505,9 @@ function normalizePptxNonVisualIds(shapeTree) {
|
|
|
492
505
|
function groupBucketKey(scope, groupId) {
|
|
493
506
|
return `${scope}\u0000${groupId}`;
|
|
494
507
|
}
|
|
508
|
+
function exportElementKey(scope, elementId) {
|
|
509
|
+
return `${scope}\u0000${elementId}`;
|
|
510
|
+
}
|
|
495
511
|
function isPptxSceneNode(node) {
|
|
496
512
|
return [
|
|
497
513
|
'contentPart',
|
|
@@ -735,7 +751,9 @@ function createPptxExportState(artifact, PptxGenJS) {
|
|
|
735
751
|
if (!source.useLayoutBackground) slide.background = {
|
|
736
752
|
color: source.background.replace('#', '')
|
|
737
753
|
};
|
|
738
|
-
|
|
754
|
+
const groupScope = `slide:${source.id}`;
|
|
755
|
+
groups.registerAnimatedElements(groupScope, source.animations?.map((animation)=>animation.elementId) ?? []);
|
|
756
|
+
for (const element of source.elements)addPresentationElement(slide, element, presentation, slideWidth, slideHeight, groups, groupScope, element.placeholder ? binding?.placeholderNames.get(element.placeholder.key) : void 0);
|
|
739
757
|
if (source.notes?.trim()) slide.addNotes(source.notes);
|
|
740
758
|
}
|
|
741
759
|
return {
|
|
@@ -758,7 +776,8 @@ async function createPptxBlob(artifact, PptxGenJS) {
|
|
|
758
776
|
const withChartSeriesAnalysis = await patchPptxChartSeriesAnalysis(withChartAxes, slides);
|
|
759
777
|
const withTransitions = await patchPptxTransitions(withChartSeriesAnalysis, slides);
|
|
760
778
|
const withComments = await patchPptxComments(withTransitions, slides, 'presentation' === artifact.content.type ? artifact.content.width ?? 13.333 : 13.333, 'presentation' === artifact.content.type ? artifact.content.height ?? 7.5 : 7.5);
|
|
761
|
-
const
|
|
779
|
+
const withAnimations = await patchPptxAnimations(withComments, slides, groups);
|
|
780
|
+
const patched = await patchPptxNativeGroups(withAnimations, groups);
|
|
762
781
|
return new Blob([
|
|
763
782
|
patched
|
|
764
783
|
], {
|
|
@@ -886,8 +905,13 @@ function addPresentationElement(slide, element, presentation, slideWidth, slideH
|
|
|
886
905
|
});
|
|
887
906
|
return;
|
|
888
907
|
}
|
|
889
|
-
if ('shape' === element.type)
|
|
890
|
-
|
|
908
|
+
if ('shape' === element.type) {
|
|
909
|
+
const objectName = groups.objectName(groupScope, element, 'shape');
|
|
910
|
+
if (element.text || element.textRuns?.length) addText(slide, element, x, y, width, height, resolvedPlaceholder, objectName, pptxShapeType(presentation, element));
|
|
911
|
+
else addShape(slide, element, presentation, x, y, width, height, resolvedPlaceholder, objectName);
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
if ('text' === element.type) addText(slide, element, x, y, width, height, resolvedPlaceholder, groups.objectName(groupScope, element, 'text'));
|
|
891
915
|
}
|
|
892
916
|
function pptxChartData(chart) {
|
|
893
917
|
if (presentationChartUsesNumericXAxis(chart.type)) return [
|
|
@@ -926,7 +950,7 @@ function pptxLegendPosition(position) {
|
|
|
926
950
|
return 'r';
|
|
927
951
|
}
|
|
928
952
|
function addShape(slide, element, presentation, x, y, width, height, placeholder, objectName) {
|
|
929
|
-
const shapeType =
|
|
953
|
+
const shapeType = pptxShapeType(presentation, element);
|
|
930
954
|
const fillColor = element.fill.replace('#', '');
|
|
931
955
|
const borderColor = (element.borderColor ?? element.fill).replace('#', '');
|
|
932
956
|
const options = {
|
|
@@ -954,7 +978,7 @@ function addShape(slide, element, presentation, x, y, width, height, placeholder
|
|
|
954
978
|
};
|
|
955
979
|
slide.addShape(shapeType, options);
|
|
956
980
|
}
|
|
957
|
-
function addText(slide, element, x, y, width, height, placeholder, objectName) {
|
|
981
|
+
function addText(slide, element, x, y, width, height, placeholder, objectName, shape) {
|
|
958
982
|
const text = element.textRuns?.length ? element.textRuns.map((run)=>({
|
|
959
983
|
text: run.text,
|
|
960
984
|
options: {
|
|
@@ -989,9 +1013,14 @@ function addText(slide, element, x, y, width, height, placeholder, objectName) {
|
|
|
989
1013
|
valign: element.verticalAlign ?? 'middle',
|
|
990
1014
|
margin: 'transparent' === element.fill ? 0 : 10,
|
|
991
1015
|
breakLine: false,
|
|
1016
|
+
shape,
|
|
992
1017
|
fill: 'transparent' === element.fill ? void 0 : {
|
|
993
1018
|
color: element.fill.replace('#', '')
|
|
994
1019
|
},
|
|
1020
|
+
line: element.borderWidth && element.borderColor ? {
|
|
1021
|
+
color: element.borderColor.replace('#', ''),
|
|
1022
|
+
width: element.borderWidth
|
|
1023
|
+
} : void 0,
|
|
995
1024
|
hyperlink: element.href ? {
|
|
996
1025
|
url: element.href
|
|
997
1026
|
} : void 0,
|
|
@@ -1001,6 +1030,13 @@ function addText(slide, element, x, y, width, height, placeholder, objectName) {
|
|
|
1001
1030
|
} : {}
|
|
1002
1031
|
});
|
|
1003
1032
|
}
|
|
1033
|
+
function pptxShapeType(presentation, element) {
|
|
1034
|
+
if ('ellipse' === element.shapeType) return presentation.ShapeType.ellipse;
|
|
1035
|
+
if ('triangle' === element.shapeType) return presentation.ShapeType.triangle;
|
|
1036
|
+
if ('diamond' === element.shapeType) return presentation.ShapeType.diamond;
|
|
1037
|
+
if ('roundRect' === element.shapeType) return presentation.ShapeType.roundRect;
|
|
1038
|
+
return presentation.ShapeType.rect;
|
|
1039
|
+
}
|
|
1004
1040
|
async function presentationArrayBuffer(output) {
|
|
1005
1041
|
if (output instanceof ArrayBuffer) return output;
|
|
1006
1042
|
if (output instanceof Blob) return output.arrayBuffer();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { contentTypeForPart, directChildren, bytesToDataUrl, OoxmlPackage, firstDescendant, descendants, directChild, childPath, attribute, createOfficeId as createWorkId } from "./4121.js";
|
|
2
2
|
import { normalizeRadarStyle, normalizePresentationChartLegendPosition, presentationChartUsesNumericXAxis, normalizePresentationBubbleScale, normalizePresentationBubbleSizeRepresents, withPresentationChartLayout, normalizeDoughnutHoleSize, normalizePresentationScatterStyle } from "./0~work-presentation-charts.js";
|
|
3
|
-
import { loadPptxCommentAuthors, readPptxSlideComments, readPptxChartLayoutAndSeriesStyles, readPptxTransition, readPptxChartSeriesAnalysis, readPptxChartDataLabels } from "./0~
|
|
3
|
+
import { loadPptxCommentAuthors, readPptxSlideComments, readPptxChartLayoutAndSeriesStyles, readPptxAnimations, readPptxTransition, readPptxChartSeriesAnalysis, readPptxChartDataLabels } from "./0~7828.js";
|
|
4
4
|
import { parseXlsxChartAxes } from "./4166.js";
|
|
5
5
|
import { scaledPresentationVisuals } from "./0~work-presentation-visual-scale.js";
|
|
6
6
|
async function loadPptxTheme(archive, presentationRelationships) {
|
|
@@ -547,6 +547,7 @@ async function parseSlide(archive, slidePart, slideNumber, slideWidthEmu, slideH
|
|
|
547
547
|
theme,
|
|
548
548
|
issues,
|
|
549
549
|
imageBudget,
|
|
550
|
+
elementIdByPptxShapeId: new Map(),
|
|
550
551
|
location: `幻灯片 ${slideNumber}`
|
|
551
552
|
};
|
|
552
553
|
const design = await ensurePptxDesignDefinitions(archive, inheritance.layout, inheritance.master, context, designs);
|
|
@@ -554,6 +555,7 @@ async function parseSlide(archive, slidePart, slideNumber, slideWidthEmu, slideH
|
|
|
554
555
|
const shapeTree = firstDescendant(document1, 'spTree');
|
|
555
556
|
for (const child of shapeTree ? directChildren(shapeTree) : [])elements.push(...await parseSlideNode(child, context));
|
|
556
557
|
const resolvedElements = inheritPptxPlaceholderStyles(elements, design.master, design.layout);
|
|
558
|
+
const animationResult = readPptxAnimations(document1, context.elementIdByPptxShapeId);
|
|
557
559
|
const transition = readPptxTransition(document1);
|
|
558
560
|
const commentResult = await readPptxSlideComments(archive, relationships, commentAuthors, slideNumber, slideWidthEmu, slideHeightEmu);
|
|
559
561
|
if (commentResult.comments.length) addIssue(context, 'pptx.comments', 'Comments', `${commentResult.comments.length} traditional slide comment(s), authors, dates, and positions are preserved and editable.`, 'info');
|
|
@@ -564,7 +566,8 @@ async function parseSlide(archive, slidePart, slideNumber, slideWidthEmu, slideH
|
|
|
564
566
|
addIssue(context, 'pptx.transition', 'Slide transitions', transition.transition ? 'Basic slide transitions and advance timing are preserved, editable, and replayed in presentation preview.' : 'This slide transition is not editable and remains in the original PPTX only.', transition.transition ? 'info' : 'warning');
|
|
565
567
|
for (const diagnostic of transition.diagnostics)addIssue(context, diagnostic.code, 'Slide transitions', diagnostic.message);
|
|
566
568
|
}
|
|
567
|
-
if (
|
|
569
|
+
if (animationResult.animations.length) addIssue(context, 'pptx.animation', 'Animations', `${animationResult.animations.length} supported object entrance animation(s) are preserved, editable, replayed, and exported.`, 'info');
|
|
570
|
+
for (const diagnostic of animationResult.diagnostics)addIssue(context, diagnostic.code, 'Animations', diagnostic.message);
|
|
568
571
|
for (const relationship of relationships.values())if (relationship.type.includes('/audio') || relationship.type.includes('/video') || relationship.type.includes('/media')) addIssue(context, 'pptx.media', 'Embedded media', 'Audio and video remain in the original file but are not playable yet.');
|
|
569
572
|
else if (relationship.type.endsWith('/oleObject') || relationship.type.endsWith('/package')) addIssue(context, 'pptx.ole', 'Embedded objects', 'Embedded Office or OLE objects remain in the original file only.');
|
|
570
573
|
const slideBackground = readPptxBackground(document1, theme);
|
|
@@ -578,7 +581,8 @@ async function parseSlide(archive, slidePart, slideNumber, slideWidthEmu, slideH
|
|
|
578
581
|
elements: resolvedElements,
|
|
579
582
|
notes: await readSpeakerNotes(archive, relationships, context),
|
|
580
583
|
comments: commentResult.comments.length ? commentResult.comments : void 0,
|
|
581
|
-
transition: transition.transition
|
|
584
|
+
transition: transition.transition,
|
|
585
|
+
animations: animationResult.animations.length ? animationResult.animations : void 0
|
|
582
586
|
};
|
|
583
587
|
}
|
|
584
588
|
async function loadPptxPresentationDesigns(archive, relationships, slideWidthEmu, slideHeightEmu, theme, issues, imageBudget, registry) {
|
|
@@ -592,6 +596,7 @@ async function loadPptxPresentationDesigns(archive, relationships, slideWidthEmu
|
|
|
592
596
|
theme,
|
|
593
597
|
issues,
|
|
594
598
|
imageBudget,
|
|
599
|
+
elementIdByPptxShapeId: new Map(),
|
|
595
600
|
location: '母版与布局'
|
|
596
601
|
};
|
|
597
602
|
for (const relationship of relationships.values()){
|
|
@@ -659,6 +664,7 @@ function ensureFallbackPptxMaster(registry) {
|
|
|
659
664
|
async function parsePptxDesignElements(part, context) {
|
|
660
665
|
const partContext = {
|
|
661
666
|
...context,
|
|
667
|
+
elementIdByPptxShapeId: new Map(),
|
|
662
668
|
relationships: part.relationships,
|
|
663
669
|
placeholders: new Map()
|
|
664
670
|
};
|
|
@@ -712,24 +718,30 @@ function inheritPptxPlaceholderStyle(element, definition) {
|
|
|
712
718
|
};
|
|
713
719
|
}
|
|
714
720
|
async function parseSlideNode(node, context, transform) {
|
|
715
|
-
|
|
721
|
+
let elements;
|
|
722
|
+
if ('sp' === node.localName) elements = [
|
|
716
723
|
withImportedGroupTransform(parseShape(node, context, transform), transform)
|
|
717
724
|
];
|
|
718
|
-
if ('pic' === node.localName)
|
|
725
|
+
else if ('pic' === node.localName) elements = [
|
|
719
726
|
withImportedGroupTransform(await parsePicture(node, context, transform), transform)
|
|
720
727
|
];
|
|
721
|
-
if ('graphicFrame' === node.localName)
|
|
728
|
+
else if ('graphicFrame' === node.localName) elements = [
|
|
722
729
|
withImportedGroupTransform(await parseGraphicFrame(node, context, transform), transform)
|
|
723
730
|
];
|
|
724
|
-
if ('cxnSp' === node.localName)
|
|
731
|
+
else if ('cxnSp' === node.localName) elements = [
|
|
725
732
|
withImportedGroupTransform(parseConnector(node, context, transform), transform)
|
|
726
733
|
];
|
|
727
|
-
|
|
734
|
+
else {
|
|
735
|
+
if ('grpSp' === node.localName) return parseGroup(node, context, transform);
|
|
736
|
+
elements = [];
|
|
737
|
+
}
|
|
728
738
|
if ([
|
|
729
739
|
'contentPart',
|
|
730
740
|
'oleObj'
|
|
731
741
|
].includes(node.localName)) addIssue(context, 'pptx.content-part', 'Embedded content', 'An embedded slide object remains available in the original PPTX only.');
|
|
732
|
-
|
|
742
|
+
const pptxShapeId = attribute(firstDescendant(node, 'cNvPr') ?? node, 'id');
|
|
743
|
+
if (pptxShapeId && 1 === elements.length) context.elementIdByPptxShapeId.set(pptxShapeId, elements[0].id);
|
|
744
|
+
return elements;
|
|
733
745
|
}
|
|
734
746
|
function parseShape(node, context, transform) {
|
|
735
747
|
const box = elementBox(node, context, transform);
|