@bendyline/squisq-formats 2.1.0 → 2.2.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/LICENSE +21 -0
- package/NOTICE.md +20 -0
- package/README.md +1 -1
- package/dist/{chunk-NNHKUXKA.js → chunk-26ISNJ7Y.js} +85 -65
- package/dist/{chunk-NKAJPJ4G.js → chunk-2JJ5RFDZ.js} +0 -1
- package/dist/{chunk-WQSHGBLN.js → chunk-3NKXBZSR.js} +193 -42
- package/dist/{chunk-KURGXM4I.js → chunk-4V3KCHAP.js} +3 -4
- package/dist/{chunk-MLX2BOJC.js → chunk-6RQOV3B3.js} +1 -2
- package/dist/{chunk-EW54IRRS.js → chunk-6S6GU3ZG.js} +5 -6
- package/dist/{chunk-FE6OJV6O.js → chunk-7AWFHP5U.js} +1 -1
- package/dist/{chunk-RFAPOKHJ.js → chunk-AD2WT564.js} +59 -9
- package/dist/{chunk-O3GVVND4.js → chunk-AONELFLA.js} +0 -1
- package/dist/{chunk-SC67HYQJ.js → chunk-EJTNGKEA.js} +5 -8
- package/dist/chunk-GX7RAUME.js +121 -0
- package/dist/{chunk-SSUPBUF5.js → chunk-IIQYS2YH.js} +0 -1
- package/dist/{chunk-RLU7UFYU.js → chunk-IPN56VLW.js} +83 -58
- package/dist/{chunk-DTDF6QDP.js → chunk-JE6LSIHE.js} +81 -20
- package/dist/{chunk-U4MRIFKL.js → chunk-JU2RHXUB.js} +0 -1
- package/dist/{chunk-4VUWTSGM.js → chunk-K6XRMVPW.js} +64 -31
- package/dist/{chunk-ODL3SSPT.js → chunk-KXOZMWBS.js} +0 -1
- package/dist/chunk-OGS5VCGJ.js +446 -0
- package/dist/{chunk-GVS2XXV6.js → chunk-PJXJI2LY.js} +449 -57
- package/dist/{chunk-74GO3FVS.js → chunk-PU7REGWV.js} +5 -8
- package/dist/{chunk-PN52A5AA.js → chunk-SBUW7NHR.js} +0 -1
- package/dist/{chunk-QFLDYKCR.js → chunk-TAAENIRB.js} +5 -8
- package/dist/{chunk-7ARKUCQT.js → chunk-X2DEAXNK.js} +54 -2
- package/dist/container/index.js +1 -2
- package/dist/csv/index.d.ts +27 -2
- package/dist/csv/index.js +1 -2
- package/dist/docx/index.d.ts +5 -1
- package/dist/docx/index.js +9 -11
- package/dist/epub/index.d.ts +2 -0
- package/dist/epub/index.js +5 -6
- package/dist/{export-D2NkylDT.d.ts → export-D9msROJS.d.ts} +18 -6
- package/dist/extract-MN7LA3NL.js +13 -0
- package/dist/html/index.d.ts +11 -4
- package/dist/html/index.js +3 -4
- package/dist/images-ESPQKVTW.js +6 -0
- package/dist/{import-K8mfc0fz.d.ts → import-C3htUTss.d.ts} +5 -1
- package/dist/{import-DTkDxHmZ.d.ts → import-C8whCC7_.d.ts} +6 -0
- package/dist/index.d.ts +7 -7
- package/dist/index.js +28 -26
- package/dist/infer/index.d.ts +3 -3
- package/dist/infer/index.js +7 -9
- package/dist/{layouts-BHrgZ5FS.d.ts → layouts-CTdPlB-u.d.ts} +1 -1
- package/dist/layouts-DRWZGSPD.js +10 -0
- package/dist/{mapTheme-IR27S6IV.js → mapTheme-4TWH25FT.js} +1 -2
- package/dist/ooxml/index.d.ts +3 -3
- package/dist/ooxml/index.js +14 -13
- package/dist/pdf/index.d.ts +18 -0
- package/dist/pdf/index.js +2 -3
- package/dist/pptx/index.d.ts +4 -4
- package/dist/pptx/index.js +11 -13
- package/dist/{reader-B9L8Ucbj.d.ts → reader-B_m1aKZC.d.ts} +30 -1
- package/dist/registry/index.d.ts +21 -5
- package/dist/registry/index.js +9 -6
- package/dist/{themeReader-DJKErl_j.d.ts → themeReader-DCtwC83Q.d.ts} +1 -1
- package/dist/xlsx/index.d.ts +3 -3
- package/dist/xlsx/index.js +6 -7
- package/package.json +6 -3
- package/dist/chunk-4VUWTSGM.js.map +0 -1
- package/dist/chunk-6M7Z25LA.js +0 -46
- package/dist/chunk-6M7Z25LA.js.map +0 -1
- package/dist/chunk-74GO3FVS.js.map +0 -1
- package/dist/chunk-7ARKUCQT.js.map +0 -1
- package/dist/chunk-DTDF6QDP.js.map +0 -1
- package/dist/chunk-EW54IRRS.js.map +0 -1
- package/dist/chunk-FE6OJV6O.js.map +0 -1
- package/dist/chunk-GVS2XXV6.js.map +0 -1
- package/dist/chunk-KURGXM4I.js.map +0 -1
- package/dist/chunk-MLX2BOJC.js.map +0 -1
- package/dist/chunk-NKAJPJ4G.js.map +0 -1
- package/dist/chunk-NNHKUXKA.js.map +0 -1
- package/dist/chunk-O3GVVND4.js.map +0 -1
- package/dist/chunk-ODL3SSPT.js.map +0 -1
- package/dist/chunk-PN52A5AA.js.map +0 -1
- package/dist/chunk-QFLDYKCR.js.map +0 -1
- package/dist/chunk-RFAPOKHJ.js.map +0 -1
- package/dist/chunk-RLU7UFYU.js.map +0 -1
- package/dist/chunk-SC67HYQJ.js.map +0 -1
- package/dist/chunk-SSUPBUF5.js.map +0 -1
- package/dist/chunk-U4MRIFKL.js.map +0 -1
- package/dist/chunk-UGYF5AZE.js +0 -275
- package/dist/chunk-UGYF5AZE.js.map +0 -1
- package/dist/chunk-WQSHGBLN.js.map +0 -1
- package/dist/chunk-YRT7GQ5Y.js +0 -28
- package/dist/chunk-YRT7GQ5Y.js.map +0 -1
- package/dist/container/index.js.map +0 -1
- package/dist/csv/index.js.map +0 -1
- package/dist/docx/index.js.map +0 -1
- package/dist/epub/index.js.map +0 -1
- package/dist/extract-OJ7ZQV6P.js +0 -15
- package/dist/extract-OJ7ZQV6P.js.map +0 -1
- package/dist/html/index.js.map +0 -1
- package/dist/images-7FBWPKE3.js +0 -7
- package/dist/images-7FBWPKE3.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/infer/index.js.map +0 -1
- package/dist/layouts-5VDIRPIJ.js +0 -12
- package/dist/layouts-5VDIRPIJ.js.map +0 -1
- package/dist/mapTheme-IR27S6IV.js.map +0 -1
- package/dist/ooxml/index.js.map +0 -1
- package/dist/pdf/index.js.map +0 -1
- package/dist/pptx/index.js.map +0 -1
- package/dist/registry/index.js.map +0 -1
- package/dist/xlsx/index.js.map +0 -1
- package/src/__tests__/container.test.ts +0 -230
- package/src/__tests__/convert.test.ts +0 -495
- package/src/__tests__/csvImport.test.ts +0 -84
- package/src/__tests__/docxExport.test.ts +0 -491
- package/src/__tests__/docxImport.test.ts +0 -531
- package/src/__tests__/epub.test.ts +0 -649
- package/src/__tests__/exportThemeReconciliation.test.ts +0 -87
- package/src/__tests__/formatRegistry.test.ts +0 -174
- package/src/__tests__/html.test.ts +0 -439
- package/src/__tests__/htmlImport.test.ts +0 -57
- package/src/__tests__/inferTheme.test.ts +0 -135
- package/src/__tests__/lossyWarnings.test.ts +0 -146
- package/src/__tests__/ooxml.test.ts +0 -271
- package/src/__tests__/ooxmlCancellation.test.ts +0 -113
- package/src/__tests__/ooxmlThemeReader.test.ts +0 -92
- package/src/__tests__/pdfExport.test.ts +0 -322
- package/src/__tests__/pdfImport.test.ts +0 -384
- package/src/__tests__/plainHtml.test.ts +0 -417
- package/src/__tests__/plainHtmlBundle.test.ts +0 -253
- package/src/__tests__/pptxExport.test.ts +0 -138
- package/src/__tests__/pptxImport.test.ts +0 -145
- package/src/__tests__/pptxInferFixtures.ts +0 -314
- package/src/__tests__/pptxLayoutInfer.test.ts +0 -395
- package/src/__tests__/roundTrip.test.ts +0 -201
- package/src/__tests__/roundTripAssets.test.ts +0 -50
- package/src/__tests__/roundTripMatrix.fixtures.ts +0 -86
- package/src/__tests__/roundTripMatrix.helpers.ts +0 -154
- package/src/__tests__/roundTripMatrix.test.ts +0 -142
- package/src/__tests__/sharedContainer.test.ts +0 -41
- package/src/__tests__/sharedImages.test.ts +0 -61
- package/src/__tests__/xlsxExport.test.ts +0 -164
- package/src/__tests__/xlsxImport.test.ts +0 -80
- package/src/__tests__/zipSafety.test.ts +0 -317
- package/src/container/index.ts +0 -94
- package/src/csv/index.ts +0 -188
- package/src/docx/export.ts +0 -1375
- package/src/docx/import.ts +0 -1250
- package/src/docx/index.ts +0 -26
- package/src/docx/styles.ts +0 -145
- package/src/epub/export.ts +0 -968
- package/src/epub/index.ts +0 -20
- package/src/html/docsHtmlBundle.ts +0 -373
- package/src/html/htmlTemplate.ts +0 -385
- package/src/html/imageUtils.ts +0 -61
- package/src/html/import.ts +0 -297
- package/src/html/index.ts +0 -212
- package/src/html/plainHtml.ts +0 -790
- package/src/html/plainHtmlBundle.ts +0 -421
- package/src/index.ts +0 -109
- package/src/infer/extract.ts +0 -127
- package/src/infer/index.ts +0 -199
- package/src/infer/mapTheme.ts +0 -176
- package/src/infer/types.ts +0 -27
- package/src/ooxml/index.ts +0 -111
- package/src/ooxml/namespaces.ts +0 -217
- package/src/ooxml/readUtils.ts +0 -44
- package/src/ooxml/reader.ts +0 -318
- package/src/ooxml/themeReader.ts +0 -197
- package/src/ooxml/types.ts +0 -103
- package/src/ooxml/writer.ts +0 -339
- package/src/ooxml/xmlUtils.ts +0 -123
- package/src/pdf/export.ts +0 -1084
- package/src/pdf/import.ts +0 -1164
- package/src/pdf/index.ts +0 -29
- package/src/pdf/styles.ts +0 -180
- package/src/pptx/export.ts +0 -1184
- package/src/pptx/import.ts +0 -455
- package/src/pptx/index.ts +0 -52
- package/src/pptx/layouts.ts +0 -1222
- package/src/pptx/styles.ts +0 -96
- package/src/pptx/templates.ts +0 -187
- package/src/registry/convert.ts +0 -433
- package/src/registry/defaultFormats.ts +0 -413
- package/src/registry/errors.ts +0 -46
- package/src/registry/index.ts +0 -43
- package/src/registry/registry.ts +0 -48
- package/src/registry/types.ts +0 -170
- package/src/shared/boundedZipArchive.ts +0 -383
- package/src/shared/container.ts +0 -28
- package/src/shared/fidelity.ts +0 -130
- package/src/shared/images.ts +0 -44
- package/src/shared/inlineRuns.ts +0 -99
- package/src/shared/text.ts +0 -41
- package/src/shared/zipEntryCount.ts +0 -151
- package/src/shared/zipLimits.ts +0 -296
- package/src/shared/zipSafety.ts +0 -19
- package/src/xlsx/export.ts +0 -253
- package/src/xlsx/import.ts +0 -160
- package/src/xlsx/index.ts +0 -35
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import type { MarkdownBlockNode, MarkdownDocument } from '@bendyline/squisq/markdown';
|
|
3
|
-
import type { Transition } from '@bendyline/squisq/schemas';
|
|
4
|
-
import { TRANSITION_TYPES } from '@bendyline/squisq/schemas';
|
|
5
|
-
import { markdownDocToPptx } from '../pptx/export';
|
|
6
|
-
import { openPackage, getPartXml } from '../ooxml/reader';
|
|
7
|
-
import { NS_PML, NS_PML_2010 } from '../ooxml/namespaces';
|
|
8
|
-
|
|
9
|
-
function docWithSecondSlideTransition(transition: Transition): MarkdownDocument {
|
|
10
|
-
return {
|
|
11
|
-
type: 'document',
|
|
12
|
-
children: [
|
|
13
|
-
{
|
|
14
|
-
type: 'heading',
|
|
15
|
-
depth: 2,
|
|
16
|
-
children: [{ type: 'text', value: 'One' }],
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
type: 'paragraph',
|
|
20
|
-
children: [{ type: 'text', value: 'Intro' }],
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
type: 'heading',
|
|
24
|
-
depth: 2,
|
|
25
|
-
children: [{ type: 'text', value: 'Two' }],
|
|
26
|
-
attributes: {
|
|
27
|
-
params: {
|
|
28
|
-
transition: transition.type,
|
|
29
|
-
...(transition.duration !== undefined
|
|
30
|
-
? { transitionDuration: String(transition.duration) }
|
|
31
|
-
: {}),
|
|
32
|
-
...(transition.direction ? { transitionDirection: transition.direction } : {}),
|
|
33
|
-
},
|
|
34
|
-
blockMeta: { transition },
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
type: 'paragraph',
|
|
39
|
-
children: [{ type: 'text', value: 'Body' }],
|
|
40
|
-
},
|
|
41
|
-
],
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function docWithAllTransitions(): MarkdownDocument {
|
|
46
|
-
const children: MarkdownBlockNode[] = [
|
|
47
|
-
{
|
|
48
|
-
type: 'heading',
|
|
49
|
-
depth: 2,
|
|
50
|
-
children: [{ type: 'text', value: 'Transition Gallery' }],
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
type: 'paragraph',
|
|
54
|
-
children: [{ type: 'text', value: 'Intro slide before transition checks.' }],
|
|
55
|
-
},
|
|
56
|
-
];
|
|
57
|
-
|
|
58
|
-
for (const type of TRANSITION_TYPES) {
|
|
59
|
-
const transition: Transition = { type, duration: 0.8 };
|
|
60
|
-
children.push(
|
|
61
|
-
{
|
|
62
|
-
type: 'heading',
|
|
63
|
-
depth: 2,
|
|
64
|
-
children: [{ type: 'text', value: type }],
|
|
65
|
-
attributes: {
|
|
66
|
-
params: { transition: type, transitionDuration: '0.8' },
|
|
67
|
-
blockMeta: { transition },
|
|
68
|
-
},
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
type: 'paragraph',
|
|
72
|
-
children: [{ type: 'text', value: `Transition token: ${type}` }],
|
|
73
|
-
},
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return { type: 'document', children };
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
describe('markdownDocToPptx transitions', () => {
|
|
81
|
-
it('writes valid transition XML for every shared transition token', async () => {
|
|
82
|
-
const pkg = await openPackage(await markdownDocToPptx(docWithAllTransitions()));
|
|
83
|
-
|
|
84
|
-
for (let i = 0; i < TRANSITION_TYPES.length; i++) {
|
|
85
|
-
const type = TRANSITION_TYPES[i];
|
|
86
|
-
const slide = await getPartXml(pkg, `ppt/slides/slide${i + 2}.xml`);
|
|
87
|
-
expect(slide, type).not.toBeNull();
|
|
88
|
-
|
|
89
|
-
const transitions = slide!.getElementsByTagNameNS(NS_PML, 'transition');
|
|
90
|
-
if (type === 'cut') {
|
|
91
|
-
expect(transitions, type).toHaveLength(0);
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
expect(transitions, type).toHaveLength(1);
|
|
96
|
-
expect(transitions[0].getAttribute('spd'), type).toBe('med');
|
|
97
|
-
|
|
98
|
-
const childElements = Array.from(transitions[0].childNodes).filter(
|
|
99
|
-
(node): node is Element => node.nodeType === 1,
|
|
100
|
-
);
|
|
101
|
-
expect(childElements, type).toHaveLength(1);
|
|
102
|
-
expect([NS_PML, NS_PML_2010], type).toContain(childElements[0].namespaceURI);
|
|
103
|
-
|
|
104
|
-
if (childElements[0].namespaceURI === NS_PML_2010) {
|
|
105
|
-
expect(slide!.documentElement.getAttribute('mc:Ignorable'), type).toContain('p14');
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it('writes standard PresentationML transition XML', async () => {
|
|
111
|
-
const md = docWithSecondSlideTransition({
|
|
112
|
-
type: 'checkerboard',
|
|
113
|
-
duration: 1.3,
|
|
114
|
-
direction: 'vertical',
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
const pkg = await openPackage(await markdownDocToPptx(md));
|
|
118
|
-
const slide = await getPartXml(pkg, 'ppt/slides/slide2.xml');
|
|
119
|
-
const transition = slide!.getElementsByTagNameNS(NS_PML, 'transition')[0];
|
|
120
|
-
const checker = transition.getElementsByTagNameNS(NS_PML, 'checker')[0];
|
|
121
|
-
|
|
122
|
-
expect(transition.getAttribute('spd')).toBe('slow');
|
|
123
|
-
expect(checker.getAttribute('dir')).toBe('vert');
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('writes PowerPoint 2010 transition XML when needed', async () => {
|
|
127
|
-
const md = docWithSecondSlideTransition({ type: 'flash', duration: 0.4 });
|
|
128
|
-
|
|
129
|
-
const pkg = await openPackage(await markdownDocToPptx(md));
|
|
130
|
-
const slide = await getPartXml(pkg, 'ppt/slides/slide2.xml');
|
|
131
|
-
const transition = slide!.getElementsByTagNameNS(NS_PML, 'transition')[0];
|
|
132
|
-
const flash = transition.getElementsByTagNameNS(NS_PML_2010, 'flash')[0];
|
|
133
|
-
|
|
134
|
-
expect(transition.getAttribute('spd')).toBe('fast');
|
|
135
|
-
expect(flash).toBeDefined();
|
|
136
|
-
expect(slide!.documentElement.getAttribute('mc:Ignorable')).toBe('p14');
|
|
137
|
-
});
|
|
138
|
-
});
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for PPTX import: pptxToMarkdownDoc. Builds a minimal .pptx fixture with
|
|
3
|
-
* the shared OOXML writer, then imports it.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { describe, expect, it } from 'vitest';
|
|
7
|
-
import type {
|
|
8
|
-
MarkdownDocument,
|
|
9
|
-
MarkdownHeading,
|
|
10
|
-
MarkdownList,
|
|
11
|
-
MarkdownParagraph,
|
|
12
|
-
MarkdownText,
|
|
13
|
-
} from '@bendyline/squisq/markdown';
|
|
14
|
-
import { readCustomThemesFromFrontmatter } from '@bendyline/squisq/doc';
|
|
15
|
-
import { NS_DRAWINGML, NS_PML, NS_R, REL_OFFICE_DOCUMENT, REL_SLIDE } from '../ooxml/namespaces';
|
|
16
|
-
import { createPackage } from '../ooxml/writer';
|
|
17
|
-
import { xmlDeclaration } from '../ooxml/xmlUtils';
|
|
18
|
-
import { markdownDocToPptx } from '../pptx/export';
|
|
19
|
-
import { pptxToContainer, pptxToMarkdownDoc } from '../pptx/import';
|
|
20
|
-
|
|
21
|
-
/** Distinctive PNG-signature-prefixed payload so round-trip fidelity is checkable. */
|
|
22
|
-
const IMAGE_BYTES = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 1, 2, 3, 4, 5]);
|
|
23
|
-
|
|
24
|
-
async function buildTestPptx(): Promise<ArrayBuffer> {
|
|
25
|
-
const pkg = createPackage();
|
|
26
|
-
|
|
27
|
-
pkg.addPart(
|
|
28
|
-
'ppt/presentation.xml',
|
|
29
|
-
`${xmlDeclaration()}<p:presentation xmlns:p="${NS_PML}" xmlns:r="${NS_R}">` +
|
|
30
|
-
`<p:sldIdLst><p:sldId id="256" r:id="rId1"/></p:sldIdLst></p:presentation>`,
|
|
31
|
-
'application/xml',
|
|
32
|
-
);
|
|
33
|
-
pkg.addPart(
|
|
34
|
-
'ppt/slides/slide1.xml',
|
|
35
|
-
`${xmlDeclaration()}<p:sld xmlns:p="${NS_PML}" xmlns:a="${NS_DRAWINGML}"><p:cSld><p:spTree>` +
|
|
36
|
-
`<p:sp><p:nvSpPr><p:nvPr><p:ph type="title"/></p:nvPr></p:nvSpPr>` +
|
|
37
|
-
`<p:txBody><a:p><a:r><a:t>My Title</a:t></a:r></a:p></p:txBody></p:sp>` +
|
|
38
|
-
`<p:sp><p:txBody>` +
|
|
39
|
-
`<a:p><a:r><a:t>First bullet</a:t></a:r></a:p>` +
|
|
40
|
-
`<a:p><a:r><a:t>Second bullet</a:t></a:r></a:p>` +
|
|
41
|
-
`</p:txBody></p:sp>` +
|
|
42
|
-
`</p:spTree></p:cSld></p:sld>`,
|
|
43
|
-
'application/xml',
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
pkg.addRelationship('', {
|
|
47
|
-
id: 'rId1',
|
|
48
|
-
type: REL_OFFICE_DOCUMENT,
|
|
49
|
-
target: 'ppt/presentation.xml',
|
|
50
|
-
});
|
|
51
|
-
pkg.addRelationship('ppt/presentation.xml', {
|
|
52
|
-
id: 'rId1',
|
|
53
|
-
type: REL_SLIDE,
|
|
54
|
-
target: 'slides/slide1.xml',
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return pkg.toArrayBuffer();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
describe('pptxToMarkdownDoc', () => {
|
|
61
|
-
it('imports a slide as a heading + bullet list', async () => {
|
|
62
|
-
const doc = await pptxToMarkdownDoc(await buildTestPptx());
|
|
63
|
-
expect(doc.type).toBe('document');
|
|
64
|
-
|
|
65
|
-
const heading = doc.children[0] as MarkdownHeading;
|
|
66
|
-
expect(heading.type).toBe('heading');
|
|
67
|
-
expect(heading.depth).toBe(2);
|
|
68
|
-
expect((heading.children[0] as MarkdownText).value).toBe('My Title');
|
|
69
|
-
|
|
70
|
-
const list = doc.children[1] as MarkdownList;
|
|
71
|
-
expect(list.type).toBe('list');
|
|
72
|
-
expect(list.children).toHaveLength(2);
|
|
73
|
-
const firstItemPara = list.children[0]!.children[0] as MarkdownParagraph;
|
|
74
|
-
expect((firstItemPara.children[0] as MarkdownText).value).toBe('First bullet');
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('pptxToContainer (embedded image import)', () => {
|
|
79
|
-
const deckWithImage: MarkdownDocument = {
|
|
80
|
-
type: 'document',
|
|
81
|
-
children: [
|
|
82
|
-
{ type: 'heading', depth: 2, children: [{ type: 'text', value: 'Picture Slide' }] },
|
|
83
|
-
{ type: 'paragraph', children: [{ type: 'image', url: 'photo.png', alt: 'A photo' }] },
|
|
84
|
-
],
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
async function buildDeck(): Promise<ArrayBuffer> {
|
|
88
|
-
return markdownDocToPptx(deckWithImage, {
|
|
89
|
-
images: new Map([['photo.png', IMAGE_BYTES.buffer]]),
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
it('extracts embedded images into the container and references them', async () => {
|
|
94
|
-
const container = await pptxToContainer(await buildDeck());
|
|
95
|
-
|
|
96
|
-
// The extracted image exists at the docx-style images/imageN.ext path.
|
|
97
|
-
expect(await container.exists('images/image1.png')).toBe(true);
|
|
98
|
-
|
|
99
|
-
// The bytes survived the round-trip verbatim.
|
|
100
|
-
const bytes = await container.readFile('images/image1.png');
|
|
101
|
-
expect(bytes).not.toBeNull();
|
|
102
|
-
expect(new Uint8Array(bytes!)).toEqual(IMAGE_BYTES);
|
|
103
|
-
|
|
104
|
-
// The markdown references the extracted image (no dangling ref).
|
|
105
|
-
const markdown = await container.readDocument();
|
|
106
|
-
expect(markdown).toContain('images/image1.png');
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('does not emit dangling image refs without extractImages', async () => {
|
|
110
|
-
const doc = await pptxToMarkdownDoc(await buildDeck());
|
|
111
|
-
const hasImage = doc.children.some(
|
|
112
|
-
(b) => b.type === 'paragraph' && b.children.some((c) => c.type === 'image'),
|
|
113
|
-
);
|
|
114
|
-
expect(hasImage).toBe(false);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
describe('theme inference defaults (ON)', () => {
|
|
119
|
-
const simpleDoc: MarkdownDocument = {
|
|
120
|
-
type: 'document',
|
|
121
|
-
children: [{ type: 'heading', depth: 2, children: [{ type: 'text', value: 'Hello' }] }],
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
it('carries the deck theme in frontmatter on an export → import round trip', async () => {
|
|
125
|
-
const deck = await markdownDocToPptx(simpleDoc, {});
|
|
126
|
-
const imported = await pptxToMarkdownDoc(deck);
|
|
127
|
-
// The exporter writes the stock Office theme part; import infers it.
|
|
128
|
-
expect(imported.frontmatter?.['squisq-theme']).toBe('custom-office-theme');
|
|
129
|
-
const themes = readCustomThemesFromFrontmatter(imported.frontmatter);
|
|
130
|
-
expect(themes).toHaveLength(1);
|
|
131
|
-
expect(themes![0]!.seedColors?.primary).toBe('#4472c4');
|
|
132
|
-
expect(themes![0]!.seedColors?.background).toBe('#ffffff');
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('produces the legacy frontmatter-free import when inference is disabled', async () => {
|
|
136
|
-
const deck = await markdownDocToPptx(simpleDoc, {});
|
|
137
|
-
const imported = await pptxToMarkdownDoc(deck, { inferTheme: false, inferLayouts: false });
|
|
138
|
-
expect(imported.frontmatter).toBeUndefined();
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
it('imports decks without theme parts cleanly (no frontmatter, no failure)', async () => {
|
|
142
|
-
const doc = await pptxToMarkdownDoc(await buildTestPptx());
|
|
143
|
-
expect(doc.frontmatter).toBeUndefined();
|
|
144
|
-
});
|
|
145
|
-
});
|
|
@@ -1,314 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Programmatic OOXML fixtures for theme/layout inference tests: themed PPTX
|
|
3
|
-
* decks (theme + master + layouts + slides, fully wired relationships) plus
|
|
4
|
-
* minimal themed DOCX/XLSX packages. Built with the package's own writer —
|
|
5
|
-
* no binary fixtures checked in.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
CONTENT_TYPE_DOCX_DOCUMENT,
|
|
10
|
-
CONTENT_TYPE_PPTX_PRESENTATION,
|
|
11
|
-
CONTENT_TYPE_PPTX_SLIDE,
|
|
12
|
-
CONTENT_TYPE_PPTX_SLIDE_LAYOUT,
|
|
13
|
-
CONTENT_TYPE_PPTX_SLIDE_MASTER,
|
|
14
|
-
CONTENT_TYPE_PPTX_THEME,
|
|
15
|
-
CONTENT_TYPE_XLSX_WORKBOOK,
|
|
16
|
-
NS_DRAWINGML,
|
|
17
|
-
NS_PML,
|
|
18
|
-
NS_R,
|
|
19
|
-
NS_WML,
|
|
20
|
-
REL_OFFICE_DOCUMENT,
|
|
21
|
-
REL_SLIDE,
|
|
22
|
-
REL_SLIDE_LAYOUT,
|
|
23
|
-
REL_SLIDE_MASTER,
|
|
24
|
-
REL_THEME,
|
|
25
|
-
} from '../ooxml/namespaces';
|
|
26
|
-
import { createPackage } from '../ooxml/writer';
|
|
27
|
-
import { xmlDeclaration } from '../ooxml/xmlUtils';
|
|
28
|
-
|
|
29
|
-
export const SLDSZ = { cx: 12192000, cy: 6858000 };
|
|
30
|
-
|
|
31
|
-
// ── Theme XML ────────────────────────────────────────────────────────
|
|
32
|
-
|
|
33
|
-
export interface ThemeXmlOptions {
|
|
34
|
-
name?: string;
|
|
35
|
-
dk1?: string; // inner color XML, e.g. '<a:srgbClr val="111111"/>'
|
|
36
|
-
lt1?: string;
|
|
37
|
-
dk2?: string;
|
|
38
|
-
lt2?: string;
|
|
39
|
-
accents?: string[]; // hex values without '#', accent1..N (missing slots omitted)
|
|
40
|
-
hlink?: string;
|
|
41
|
-
majorFont?: string;
|
|
42
|
-
minorFont?: string;
|
|
43
|
-
omitFontScheme?: boolean;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function buildThemeXml(opts: ThemeXmlOptions = {}): string {
|
|
47
|
-
const accents = opts.accents ?? ['4472c4', 'ed7d31', 'a5a5a5', 'ffc000', '5b9bd5', '70ad47'];
|
|
48
|
-
const accentXml = accents
|
|
49
|
-
.map((hex, i) => `<a:accent${i + 1}><a:srgbClr val="${hex}"/></a:accent${i + 1}>`)
|
|
50
|
-
.join('');
|
|
51
|
-
const fontScheme = opts.omitFontScheme
|
|
52
|
-
? ''
|
|
53
|
-
: `<a:fontScheme name="Test">` +
|
|
54
|
-
`<a:majorFont><a:latin typeface="${opts.majorFont ?? 'Playfair Display'}"/></a:majorFont>` +
|
|
55
|
-
`<a:minorFont><a:latin typeface="${opts.minorFont ?? 'Aptos'}"/></a:minorFont>` +
|
|
56
|
-
`</a:fontScheme>`;
|
|
57
|
-
return (
|
|
58
|
-
xmlDeclaration() +
|
|
59
|
-
`<a:theme xmlns:a="${NS_DRAWINGML}" name="${opts.name ?? 'Fixture Theme'}">` +
|
|
60
|
-
`<a:themeElements>` +
|
|
61
|
-
`<a:clrScheme name="Test">` +
|
|
62
|
-
`<a:dk1>${opts.dk1 ?? '<a:srgbClr val="1a1a2e"/>'}</a:dk1>` +
|
|
63
|
-
`<a:lt1>${opts.lt1 ?? '<a:srgbClr val="fdfdf8"/>'}</a:lt1>` +
|
|
64
|
-
`<a:dk2>${opts.dk2 ?? '<a:srgbClr val="30304a"/>'}</a:dk2>` +
|
|
65
|
-
`<a:lt2>${opts.lt2 ?? '<a:srgbClr val="efefe4"/>'}</a:lt2>` +
|
|
66
|
-
accentXml +
|
|
67
|
-
`<a:hlink>${opts.hlink ?? '<a:srgbClr val="0563c1"/>'}</a:hlink>` +
|
|
68
|
-
`<a:folHlink><a:srgbClr val="954f72"/></a:folHlink>` +
|
|
69
|
-
`</a:clrScheme>` +
|
|
70
|
-
fontScheme +
|
|
71
|
-
`</a:themeElements>` +
|
|
72
|
-
`</a:theme>`
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// ── PresentationML fragments ─────────────────────────────────────────
|
|
77
|
-
|
|
78
|
-
export interface PhSpOptions {
|
|
79
|
-
/** ph@type; omit for a plain body placeholder. */
|
|
80
|
-
type?: string;
|
|
81
|
-
idx?: number;
|
|
82
|
-
/** EMU geometry; omit xfrm entirely when absent. */
|
|
83
|
-
rect?: { x: number; y: number; cx: number; cy: number };
|
|
84
|
-
/** a:lvl1pPr defRPr attributes, e.g. 'sz="4400" b="1"'. */
|
|
85
|
-
lvl1DefRPr?: string;
|
|
86
|
-
/** ph@orient value (e.g. 'vert'). */
|
|
87
|
-
orient?: string;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/** A placeholder `p:sp` for a layout/master/slide part. */
|
|
91
|
-
export function phSp(opts: PhSpOptions, id = 2): string {
|
|
92
|
-
const typeAttr = opts.type ? ` type="${opts.type}"` : '';
|
|
93
|
-
const idxAttr = opts.idx !== undefined ? ` idx="${opts.idx}"` : '';
|
|
94
|
-
const orientAttr = opts.orient ? ` orient="${opts.orient}"` : '';
|
|
95
|
-
const xfrm = opts.rect
|
|
96
|
-
? `<a:xfrm><a:off x="${opts.rect.x}" y="${opts.rect.y}"/>` +
|
|
97
|
-
`<a:ext cx="${opts.rect.cx}" cy="${opts.rect.cy}"/></a:xfrm>`
|
|
98
|
-
: '';
|
|
99
|
-
const lstStyle = opts.lvl1DefRPr
|
|
100
|
-
? `<a:lstStyle><a:lvl1pPr><a:defRPr ${opts.lvl1DefRPr}/></a:lvl1pPr></a:lstStyle>`
|
|
101
|
-
: `<a:lstStyle/>`;
|
|
102
|
-
return (
|
|
103
|
-
`<p:sp><p:nvSpPr><p:cNvPr id="${id}" name="ph${id}"/><p:cNvSpPr/>` +
|
|
104
|
-
`<p:nvPr><p:ph${typeAttr}${idxAttr}${orientAttr}/></p:nvPr></p:nvSpPr>` +
|
|
105
|
-
`<p:spPr>${xfrm}</p:spPr>` +
|
|
106
|
-
`<p:txBody><a:bodyPr/>${lstStyle}<a:p><a:endParaRPr/></a:p></p:txBody></p:sp>`
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export interface LayoutXmlOptions {
|
|
111
|
-
name?: string;
|
|
112
|
-
type?: string;
|
|
113
|
-
/** Raw p:sp strings (use phSp / decorSp). */
|
|
114
|
-
shapes?: string[];
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export function layoutXml(opts: LayoutXmlOptions = {}): string {
|
|
118
|
-
const typeAttr = opts.type ? ` type="${opts.type}"` : '';
|
|
119
|
-
return (
|
|
120
|
-
xmlDeclaration() +
|
|
121
|
-
`<p:sldLayout xmlns:a="${NS_DRAWINGML}" xmlns:r="${NS_R}" xmlns:p="${NS_PML}"${typeAttr}>` +
|
|
122
|
-
`<p:cSld${opts.name !== undefined ? ` name="${opts.name}"` : ''}><p:spTree>` +
|
|
123
|
-
`<p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr/>` +
|
|
124
|
-
(opts.shapes ?? []).join('') +
|
|
125
|
-
`</p:spTree></p:cSld></p:sldLayout>`
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export interface SlideTextShape {
|
|
130
|
-
phType?: string;
|
|
131
|
-
phIdx?: number;
|
|
132
|
-
texts: string[];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/** A slide with a title shape plus arbitrary placeholder text shapes. */
|
|
136
|
-
export function slideXml(title: string | null, shapes: SlideTextShape[] = []): string {
|
|
137
|
-
const titleSp = title
|
|
138
|
-
? `<p:sp><p:nvSpPr><p:nvPr><p:ph type="title"/></p:nvPr></p:nvSpPr>` +
|
|
139
|
-
`<p:txBody><a:p><a:r><a:t>${title}</a:t></a:r></a:p></p:txBody></p:sp>`
|
|
140
|
-
: '';
|
|
141
|
-
const bodySps = shapes
|
|
142
|
-
.map((s) => {
|
|
143
|
-
const typeAttr = s.phType ? ` type="${s.phType}"` : '';
|
|
144
|
-
const idxAttr = s.phIdx !== undefined ? ` idx="${s.phIdx}"` : '';
|
|
145
|
-
const paras = s.texts.map((t) => `<a:p><a:r><a:t>${t}</a:t></a:r></a:p>`).join('');
|
|
146
|
-
return (
|
|
147
|
-
`<p:sp><p:nvSpPr><p:nvPr><p:ph${typeAttr}${idxAttr}/></p:nvPr></p:nvSpPr>` +
|
|
148
|
-
`<p:txBody>${paras}</p:txBody></p:sp>`
|
|
149
|
-
);
|
|
150
|
-
})
|
|
151
|
-
.join('');
|
|
152
|
-
return (
|
|
153
|
-
xmlDeclaration() +
|
|
154
|
-
`<p:sld xmlns:p="${NS_PML}" xmlns:a="${NS_DRAWINGML}" xmlns:r="${NS_R}"><p:cSld><p:spTree>` +
|
|
155
|
-
titleSp +
|
|
156
|
-
bodySps +
|
|
157
|
-
`</p:spTree></p:cSld></p:sld>`
|
|
158
|
-
);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// ── Whole-deck builder ───────────────────────────────────────────────
|
|
162
|
-
|
|
163
|
-
export interface FixtureSlide {
|
|
164
|
-
xml: string;
|
|
165
|
-
/** Index into `layouts`; omit for a slide with no layout relationship. */
|
|
166
|
-
layoutIndex?: number;
|
|
167
|
-
/** Extra relationships for this slide (e.g. image embeds). */
|
|
168
|
-
rels?: Array<{ id: string; type: string; target: string }>;
|
|
169
|
-
/** Binary media parts referenced by `rels`, keyed by package path. */
|
|
170
|
-
media?: Array<{ path: string; data: Uint8Array; contentType: string }>;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export interface ThemedPptxOptions {
|
|
174
|
-
themeXml?: string | null; // null = omit the theme part entirely
|
|
175
|
-
/** Attribute string for <p:clrMap …/>; default light mapping. */
|
|
176
|
-
clrMapAttrs?: string;
|
|
177
|
-
/** Raw p:sp strings placed in the master's spTree (for inheritance tests). */
|
|
178
|
-
masterShapes?: string[];
|
|
179
|
-
layouts?: string[]; // layout part XMLs (layoutXml())
|
|
180
|
-
slides?: FixtureSlide[];
|
|
181
|
-
sldSz?: { cx: number; cy: number };
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export async function buildThemedPptx(opts: ThemedPptxOptions = {}): Promise<ArrayBuffer> {
|
|
185
|
-
const pkg = createPackage();
|
|
186
|
-
const slides = opts.slides ?? [{ xml: slideXml('My Title', [{ texts: ['First bullet'] }]) }];
|
|
187
|
-
const layouts = opts.layouts ?? [];
|
|
188
|
-
const sldSz = opts.sldSz ?? SLDSZ;
|
|
189
|
-
|
|
190
|
-
const sldIds = slides.map((_, i) => `<p:sldId id="${256 + i}" r:id="rIdS${i + 1}"/>`).join('');
|
|
191
|
-
pkg.addPart(
|
|
192
|
-
'ppt/presentation.xml',
|
|
193
|
-
`${xmlDeclaration()}<p:presentation xmlns:p="${NS_PML}" xmlns:r="${NS_R}">` +
|
|
194
|
-
`<p:sldMasterIdLst><p:sldMasterId id="2147483648" r:id="rIdM1"/></p:sldMasterIdLst>` +
|
|
195
|
-
`<p:sldIdLst>${sldIds}</p:sldIdLst>` +
|
|
196
|
-
`<p:sldSz cx="${sldSz.cx}" cy="${sldSz.cy}"/>` +
|
|
197
|
-
`</p:presentation>`,
|
|
198
|
-
CONTENT_TYPE_PPTX_PRESENTATION,
|
|
199
|
-
);
|
|
200
|
-
pkg.addRelationship('', {
|
|
201
|
-
id: 'rId1',
|
|
202
|
-
type: REL_OFFICE_DOCUMENT,
|
|
203
|
-
target: 'ppt/presentation.xml',
|
|
204
|
-
});
|
|
205
|
-
pkg.addRelationship('ppt/presentation.xml', {
|
|
206
|
-
id: 'rIdM1',
|
|
207
|
-
type: REL_SLIDE_MASTER,
|
|
208
|
-
target: 'slideMasters/slideMaster1.xml',
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
// Master (carries the clrMap + optional inheritable placeholder geometry).
|
|
212
|
-
const layoutIds = layouts
|
|
213
|
-
.map((_, i) => `<p:sldLayoutId id="${2147483649 + i}" r:id="rIdL${i + 1}"/>`)
|
|
214
|
-
.join('');
|
|
215
|
-
pkg.addPart(
|
|
216
|
-
'ppt/slideMasters/slideMaster1.xml',
|
|
217
|
-
`${xmlDeclaration()}<p:sldMaster xmlns:a="${NS_DRAWINGML}" xmlns:r="${NS_R}" xmlns:p="${NS_PML}">` +
|
|
218
|
-
`<p:cSld name="Fixture Master"><p:spTree>` +
|
|
219
|
-
`<p:nvGrpSpPr><p:cNvPr id="1" name=""/><p:cNvGrpSpPr/><p:nvPr/></p:nvGrpSpPr><p:grpSpPr/>` +
|
|
220
|
-
(opts.masterShapes ?? []).join('') +
|
|
221
|
-
`</p:spTree></p:cSld>` +
|
|
222
|
-
`<p:clrMap ${opts.clrMapAttrs ?? 'bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2"'}` +
|
|
223
|
-
` accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4"` +
|
|
224
|
-
` accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/>` +
|
|
225
|
-
`<p:sldLayoutIdLst>${layoutIds}</p:sldLayoutIdLst>` +
|
|
226
|
-
`</p:sldMaster>`,
|
|
227
|
-
CONTENT_TYPE_PPTX_SLIDE_MASTER,
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
if (opts.themeXml !== null) {
|
|
231
|
-
pkg.addPart('ppt/theme/theme1.xml', opts.themeXml ?? buildThemeXml(), CONTENT_TYPE_PPTX_THEME);
|
|
232
|
-
pkg.addRelationship('ppt/slideMasters/slideMaster1.xml', {
|
|
233
|
-
id: 'rIdT1',
|
|
234
|
-
type: REL_THEME,
|
|
235
|
-
target: '../theme/theme1.xml',
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
layouts.forEach((xml, i) => {
|
|
240
|
-
const path = `ppt/slideLayouts/slideLayout${i + 1}.xml`;
|
|
241
|
-
pkg.addPart(path, xml, CONTENT_TYPE_PPTX_SLIDE_LAYOUT);
|
|
242
|
-
pkg.addRelationship('ppt/slideMasters/slideMaster1.xml', {
|
|
243
|
-
id: `rIdL${i + 1}`,
|
|
244
|
-
type: REL_SLIDE_LAYOUT,
|
|
245
|
-
target: `../slideLayouts/slideLayout${i + 1}.xml`,
|
|
246
|
-
});
|
|
247
|
-
pkg.addRelationship(path, {
|
|
248
|
-
id: 'rIdM1',
|
|
249
|
-
type: REL_SLIDE_MASTER,
|
|
250
|
-
target: '../slideMasters/slideMaster1.xml',
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
slides.forEach((slide, i) => {
|
|
255
|
-
const path = `ppt/slides/slide${i + 1}.xml`;
|
|
256
|
-
pkg.addPart(path, slide.xml, CONTENT_TYPE_PPTX_SLIDE);
|
|
257
|
-
pkg.addRelationship('ppt/presentation.xml', {
|
|
258
|
-
id: `rIdS${i + 1}`,
|
|
259
|
-
type: REL_SLIDE,
|
|
260
|
-
target: `slides/slide${i + 1}.xml`,
|
|
261
|
-
});
|
|
262
|
-
if (slide.layoutIndex !== undefined) {
|
|
263
|
-
pkg.addRelationship(path, {
|
|
264
|
-
id: 'rIdLo1',
|
|
265
|
-
type: REL_SLIDE_LAYOUT,
|
|
266
|
-
target: `../slideLayouts/slideLayout${slide.layoutIndex + 1}.xml`,
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
for (const rel of slide.rels ?? []) pkg.addRelationship(path, rel);
|
|
270
|
-
for (const media of slide.media ?? []) {
|
|
271
|
-
pkg.addBinaryPart(media.path, media.data, media.contentType);
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
return pkg.toArrayBuffer();
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// ── DOCX / XLSX minimal themed packages ──────────────────────────────
|
|
279
|
-
|
|
280
|
-
export async function buildThemedDocx(themeXml?: string): Promise<ArrayBuffer> {
|
|
281
|
-
const pkg = createPackage();
|
|
282
|
-
pkg.addPart(
|
|
283
|
-
'word/document.xml',
|
|
284
|
-
`${xmlDeclaration()}<w:document xmlns:w="${NS_WML}"><w:body>` +
|
|
285
|
-
`<w:p><w:r><w:t>Hello</w:t></w:r></w:p></w:body></w:document>`,
|
|
286
|
-
CONTENT_TYPE_DOCX_DOCUMENT,
|
|
287
|
-
);
|
|
288
|
-
pkg.addPart('word/theme/theme1.xml', themeXml ?? buildThemeXml(), CONTENT_TYPE_PPTX_THEME);
|
|
289
|
-
pkg.addRelationship('', { id: 'rId1', type: REL_OFFICE_DOCUMENT, target: 'word/document.xml' });
|
|
290
|
-
pkg.addRelationship('word/document.xml', {
|
|
291
|
-
id: 'rId2',
|
|
292
|
-
type: REL_THEME,
|
|
293
|
-
target: 'theme/theme1.xml',
|
|
294
|
-
});
|
|
295
|
-
return pkg.toArrayBuffer();
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
export async function buildThemedXlsx(themeXml?: string): Promise<ArrayBuffer> {
|
|
299
|
-
const pkg = createPackage();
|
|
300
|
-
pkg.addPart(
|
|
301
|
-
'xl/workbook.xml',
|
|
302
|
-
`${xmlDeclaration()}<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">` +
|
|
303
|
-
`<sheets/></workbook>`,
|
|
304
|
-
CONTENT_TYPE_XLSX_WORKBOOK,
|
|
305
|
-
);
|
|
306
|
-
pkg.addPart('xl/theme/theme1.xml', themeXml ?? buildThemeXml(), CONTENT_TYPE_PPTX_THEME);
|
|
307
|
-
pkg.addRelationship('', { id: 'rId1', type: REL_OFFICE_DOCUMENT, target: 'xl/workbook.xml' });
|
|
308
|
-
pkg.addRelationship('xl/workbook.xml', {
|
|
309
|
-
id: 'rId2',
|
|
310
|
-
type: REL_THEME,
|
|
311
|
-
target: 'theme/theme1.xml',
|
|
312
|
-
});
|
|
313
|
-
return pkg.toArrayBuffer();
|
|
314
|
-
}
|