diff --git a/lib/files/src/StylesXml.ts b/lib/files/src/StylesXml.ts index 1fe7d8f2..1dcf226e 100644 --- a/lib/files/src/StylesXml.ts +++ b/lib/files/src/StylesXml.ts @@ -193,7 +193,7 @@ export class StylesXml extends XmlFile { } ) ) - ) + ) : null, }) ) @@ -390,7 +390,7 @@ export class StylesXml extends XmlFile { }), {} ), - } + } : {}), }, }; @@ -421,7 +421,13 @@ export class StylesXml extends XmlFile { location: string ): Promise { if (archive.hasFile(location)) { - const theme = await ThemeXml.fromArchive(archive); + let theme: ThemeXml | undefined; + try { + theme = await ThemeXml.fromArchive(archive); + } catch (_) { + // no-op + // something happened, the theme document couldn't be read. + } const dom = await archive.readXml(location); return this.fromDom(dom, location, theme); } diff --git a/lib/files/test/StylesXml.test.ts b/lib/files/test/StylesXml.test.ts index c2d32ba7..fb600734 100644 --- a/lib/files/test/StylesXml.test.ts +++ b/lib/files/test/StylesXml.test.ts @@ -1,7 +1,12 @@ import { expect } from 'std/expect'; import { describe, it } from 'std/testing/bdd'; +import { Docx } from '../../Docx.ts'; +import { Paragraph } from '../../components/document/src/Paragraph.ts'; +import { Section } from '../../components/document/src/Section.ts'; +import { Text } from '../../components/document/src/Text.ts'; import { serialize } from '../../utilities/src/dom.ts'; +import { pt } from '../../utilities/src/length.ts'; import { StylesXml } from '../src/StylesXml.ts'; describe('Styles', () => { @@ -83,4 +88,39 @@ describe('Styles', () => { color: '000000', }); }); + + it('can read a document with no theme', async () => { + const docx = Docx.fromNothing(); + const style = docx.document.styles.add({ + id: 'Text', + name: 'Text', + type: 'paragraph', + text: { + fontSize: pt(9), + }, + }); + docx.document.set([ + new Section({}, new Paragraph({ style }, new Text({}, 'foo'))), + ]); + const archive = await docx.toArchive(); + + // word/theme/theme1.xml is the default location for the first theme that is included in a document. + let theme: string | null; + try { + theme = await archive.readText('word/theme/theme1.xml'); + } catch (_) { + theme = null; + } + // It shouldn't be there. + expect(theme).toBeFalsy(); + + // styles.xml is the default location for the first theme that is included in a document. + // This call shouldn't crash if there's no theme. + const styles = await StylesXml.fromArchive(archive, 'styles.xml'); + expect(styles).toBeTruthy(); + + // Same here, shouldn't crash when loading the whole doc. + const fromArchive = Docx.fromArchive(archive); + expect(fromArchive).toBeTruthy(); + }); });