diff --git a/src/file/core-properties/properties.ts b/src/file/core-properties/properties.ts index d51b1f23b7b..9019a5f8c3f 100644 --- a/src/file/core-properties/properties.ts +++ b/src/file/core-properties/properties.ts @@ -1,7 +1,7 @@ import { ICommentsOptions } from "@file/paragraph/run/comment-run"; import { ICompatibilityOptions } from "@file/settings/compatibility"; import { FontOptions } from "@file/fonts/font-table"; -import { StringContainer, XmlComponent } from "@file/xml-components"; +import { StringContainer, XmlAttributeComponent, XmlComponent } from "@file/xml-components"; import { dateTimeValue } from "@util/values"; import { ICustomPropertyOptions } from "../custom-properties"; @@ -71,15 +71,7 @@ export interface IPropertiesOptions { export class CoreProperties extends XmlComponent { public constructor(options: Omit) { super("cp:coreProperties"); - this.root.push( - new DocumentAttributes({ - cp: "http://schemas.openxmlformats.org/package/2006/metadata/core-properties", - dc: "http://purl.org/dc/elements/1.1/", - dcterms: "http://purl.org/dc/terms/", - dcmitype: "http://purl.org/dc/dcmitype/", - xsi: "http://www.w3.org/2001/XMLSchema-instance", - }), - ); + this.root.push(new DocumentAttributes(["cp", "dc", "dcterms", "dcmitype", "xsi"])); if (options.title) { this.root.push(new StringContainer("dc:title", options.title)); } @@ -106,11 +98,15 @@ export class CoreProperties extends XmlComponent { } } +class TimestampElementProperties extends XmlAttributeComponent<{ readonly type: string }> { + protected readonly xmlKeys = { type: "xsi:type" }; +} + class TimestampElement extends XmlComponent { public constructor(name: string) { super(name); this.root.push( - new DocumentAttributes({ + new TimestampElementProperties({ type: "dcterms:W3CDTF", }), ); diff --git a/src/file/document/document-attributes.ts b/src/file/document/document-attributes.ts index e919fa3de51..b5d9b336428 100644 --- a/src/file/document/document-attributes.ts +++ b/src/file/document/document-attributes.ts @@ -1,89 +1,60 @@ import { XmlAttributeComponent } from "@file/xml-components"; /* cSpell:disable */ -export interface IDocumentAttributesProperties { - readonly wpc?: string; - readonly mc?: string; - readonly o?: string; - readonly r?: string; - readonly m?: string; - readonly v?: string; - readonly wp14?: string; - readonly wp?: string; - readonly w10?: string; - readonly w?: string; - readonly w14?: string; - readonly w15?: string; - readonly wpg?: string; - readonly wpi?: string; - readonly wne?: string; - readonly wps?: string; - readonly Ignorable?: string; - readonly cp?: string; - readonly dc?: string; - readonly dcterms?: string; - readonly dcmitype?: string; - readonly xsi?: string; - readonly type?: string; - readonly cx?: string; - readonly cx1?: string; - readonly cx2?: string; - readonly cx3?: string; - readonly cx4?: string; - readonly cx5?: string; - readonly cx6?: string; - readonly cx7?: string; - readonly cx8?: string; - readonly aink?: string; - readonly am3d?: string; - readonly w16cex?: string; - readonly w16cid?: string; - readonly w16?: string; - readonly w16sdtdh?: string; - readonly w16se?: string; -} +export const DocumentAttributeNamespaces = { + wpc: "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas", + mc: "http://schemas.openxmlformats.org/markup-compatibility/2006", + o: "urn:schemas-microsoft-com:office:office", + r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships", + m: "http://schemas.openxmlformats.org/officeDocument/2006/math", + v: "urn:schemas-microsoft-com:vml", + wp14: "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing", + wp: "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", + w10: "urn:schemas-microsoft-com:office:word", + w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main", + w14: "http://schemas.microsoft.com/office/word/2010/wordml", + w15: "http://schemas.microsoft.com/office/word/2012/wordml", + wpg: "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup", + wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk", + wne: "http://schemas.microsoft.com/office/word/2006/wordml", + wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape", + cp: "http://schemas.openxmlformats.org/package/2006/metadata/core-properties", + dc: "http://purl.org/dc/elements/1.1/", + dcterms: "http://purl.org/dc/terms/", + dcmitype: "http://purl.org/dc/dcmitype/", + xsi: "http://www.w3.org/2001/XMLSchema-instance", + cx: "http://schemas.microsoft.com/office/drawing/2014/chartex", + cx1: "http://schemas.microsoft.com/office/drawing/2015/9/8/chartex", + cx2: "http://schemas.microsoft.com/office/drawing/2015/10/21/chartex", + cx3: "http://schemas.microsoft.com/office/drawing/2016/5/9/chartex", + cx4: "http://schemas.microsoft.com/office/drawing/2016/5/10/chartex", + cx5: "http://schemas.microsoft.com/office/drawing/2016/5/11/chartex", + cx6: "http://schemas.microsoft.com/office/drawing/2016/5/12/chartex", + cx7: "http://schemas.microsoft.com/office/drawing/2016/5/13/chartex", + cx8: "http://schemas.microsoft.com/office/drawing/2016/5/14/chartex", + aink: "http://schemas.microsoft.com/office/drawing/2016/ink", + am3d: "http://schemas.microsoft.com/office/drawing/2017/model3d", + w16cex: "http://schemas.microsoft.com/office/word/2018/wordml/cex", + w16cid: "http://schemas.microsoft.com/office/word/2016/wordml/cid", + w16: "http://schemas.microsoft.com/office/word/2018/wordml", + w16sdtdh: "http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash", + w16se: "http://schemas.microsoft.com/office/word/2015/wordml/symex", +}; /* cSpell:enable */ +export type DocumentAttributeNamespace = keyof typeof DocumentAttributeNamespaces; + +export type IDocumentAttributesProperties = Partial> & { + readonly Ignorable?: string; +}; + export class DocumentAttributes extends XmlAttributeComponent { protected readonly xmlKeys = { - wpc: "xmlns:wpc", - mc: "xmlns:mc", - o: "xmlns:o", - r: "xmlns:r", - m: "xmlns:m", - v: "xmlns:v", - wp14: "xmlns:wp14", - wp: "xmlns:wp", - w10: "xmlns:w10", - w: "xmlns:w", - w14: "xmlns:w14", - w15: "xmlns:w15", - wpg: "xmlns:wpg", - wpi: "xmlns:wpi", - wne: "xmlns:wne", - wps: "xmlns:wps", Ignorable: "mc:Ignorable", - cp: "xmlns:cp", - dc: "xmlns:dc", - dcterms: "xmlns:dcterms", - dcmitype: "xmlns:dcmitype", - xsi: "xmlns:xsi", - type: "xsi:type", - cx: "xmlns:cx", - cx1: "xmlns:cx1", - cx2: "xmlns:cx2", - cx3: "xmlns:cx3", - cx4: "xmlns:cx4", - cx5: "xmlns:cx5", - cx6: "xmlns:cx6", - cx7: "xmlns:cx7", - cx8: "xmlns:cx8", - aink: "xmlns:aink", - am3d: "xmlns:am3d", - w16cex: "xmlns:w16cex", - w16cid: "xmlns:w16cid", - w16: "xmlns:w16", - w16sdtdh: "xmlns:w16sdtdh", - w16se: "xmlns:w16se", + ...Object.fromEntries(Object.keys(DocumentAttributeNamespaces).map((key) => [key, `xmlns:${key}`])), }; + + public constructor(ns: readonly DocumentAttributeNamespace[], Ignorable?: string) { + super({ Ignorable, ...Object.fromEntries(ns.map((n) => [n, DocumentAttributeNamespaces[n]])) }); + } } diff --git a/src/file/document/document.ts b/src/file/document/document.ts index e1b098d9cb5..ecf2a172807 100644 --- a/src/file/document/document.ts +++ b/src/file/document/document.ts @@ -36,41 +36,43 @@ export class Document extends XmlComponent { public constructor(options: IDocumentOptions) { super("w:document"); this.root.push( - new DocumentAttributes({ - wpc: "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas", - mc: "http://schemas.openxmlformats.org/markup-compatibility/2006", - o: "urn:schemas-microsoft-com:office:office", - r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships", - m: "http://schemas.openxmlformats.org/officeDocument/2006/math", - v: "urn:schemas-microsoft-com:vml", - wp14: "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing", - wp: "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", - w10: "urn:schemas-microsoft-com:office:word", - w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main", - w14: "http://schemas.microsoft.com/office/word/2010/wordml", - w15: "http://schemas.microsoft.com/office/word/2012/wordml", - wpg: "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup", - wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk", - wne: "http://schemas.microsoft.com/office/word/2006/wordml", - wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape", - cx: "http://schemas.microsoft.com/office/drawing/2014/chartex", - cx1: "http://schemas.microsoft.com/office/drawing/2015/9/8/chartex", - cx2: "http://schemas.microsoft.com/office/drawing/2015/10/21/chartex", - cx3: "http://schemas.microsoft.com/office/drawing/2016/5/9/chartex", - cx4: "http://schemas.microsoft.com/office/drawing/2016/5/10/chartex", - cx5: "http://schemas.microsoft.com/office/drawing/2016/5/11/chartex", - cx6: "http://schemas.microsoft.com/office/drawing/2016/5/12/chartex", - cx7: "http://schemas.microsoft.com/office/drawing/2016/5/13/chartex", - cx8: "http://schemas.microsoft.com/office/drawing/2016/5/14/chartex", - aink: "http://schemas.microsoft.com/office/drawing/2016/ink", - am3d: "http://schemas.microsoft.com/office/drawing/2017/model3d", - w16cex: "http://schemas.microsoft.com/office/word/2018/wordml/cex", - w16cid: "http://schemas.microsoft.com/office/word/2016/wordml/cid", - w16: "http://schemas.microsoft.com/office/word/2018/wordml", - w16sdtdh: "http://schemas.microsoft.com/office/word/2020/wordml/sdtdatahash", - w16se: "http://schemas.microsoft.com/office/word/2015/wordml/symex", - Ignorable: "w14 w15 wp14", - }), + new DocumentAttributes( + [ + "wpc", + "mc", + "o", + "r", + "m", + "v", + "wp14", + "wp", + "w10", + "w", + "w14", + "w15", + "wpg", + "wpi", + "wne", + "wps", + "cx", + "cx1", + "cx2", + "cx3", + "cx4", + "cx5", + "cx6", + "cx7", + "cx8", + "aink", + "am3d", + "w16cex", + "w16cid", + "w16", + "w16sdtdh", + "w16se", + ], + "w14 w15 wp14", + ), ); this.body = new Body(); if (options.background) { diff --git a/src/file/numbering/numbering.ts b/src/file/numbering/numbering.ts index daf9ca38c78..d7e7440aede 100644 --- a/src/file/numbering/numbering.ts +++ b/src/file/numbering/numbering.ts @@ -37,25 +37,10 @@ export class Numbering extends XmlComponent { public constructor(options: INumberingOptions) { super("w:numbering"); this.root.push( - new DocumentAttributes({ - wpc: "http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas", - mc: "http://schemas.openxmlformats.org/markup-compatibility/2006", - o: "urn:schemas-microsoft-com:office:office", - r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships", - m: "http://schemas.openxmlformats.org/officeDocument/2006/math", - v: "urn:schemas-microsoft-com:vml", - wp14: "http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing", - wp: "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing", - w10: "urn:schemas-microsoft-com:office:word", - w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main", - w14: "http://schemas.microsoft.com/office/word/2010/wordml", - w15: "http://schemas.microsoft.com/office/word/2012/wordml", - wpg: "http://schemas.microsoft.com/office/word/2010/wordprocessingGroup", - wpi: "http://schemas.microsoft.com/office/word/2010/wordprocessingInk", - wne: "http://schemas.microsoft.com/office/word/2006/wordml", - wps: "http://schemas.microsoft.com/office/word/2010/wordprocessingShape", - Ignorable: "w14 w15 wp14", - }), + new DocumentAttributes( + ["wpc", "mc", "o", "r", "m", "v", "wp14", "wp", "w10", "w", "w14", "w15", "wpg", "wpi", "wne", "wps"], + "w14 w15 wp14", + ), ); const abstractNumbering = new AbstractNumbering(this.abstractNumUniqueNumericId(), [ diff --git a/src/file/styles/factory.ts b/src/file/styles/factory.ts index 63ac2571d2c..7bbddb8f2b5 100644 --- a/src/file/styles/factory.ts +++ b/src/file/styles/factory.ts @@ -39,14 +39,7 @@ export interface IDefaultStylesOptions { export class DefaultStylesFactory { public newInstance(options: IDefaultStylesOptions = {}): IStylesOptions { - const documentAttributes = new DocumentAttributes({ - mc: "http://schemas.openxmlformats.org/markup-compatibility/2006", - r: "http://schemas.openxmlformats.org/officeDocument/2006/relationships", - w: "http://schemas.openxmlformats.org/wordprocessingml/2006/main", - w14: "http://schemas.microsoft.com/office/word/2010/wordml", - w15: "http://schemas.microsoft.com/office/word/2012/wordml", - Ignorable: "w14 w15", - }); + const documentAttributes = new DocumentAttributes(["mc", "r", "w", "w14", "w15"], "w14 w15"); return { initialStyles: documentAttributes, importedStyles: [ diff --git a/src/patcher/from-docx.ts b/src/patcher/from-docx.ts index ff9b3ea8480..75b664d0bf9 100644 --- a/src/patcher/from-docx.ts +++ b/src/patcher/from-docx.ts @@ -1,6 +1,7 @@ import JSZip from "jszip"; import { Element, js2xml } from "xml-js"; +import { DocumentAttributeNamespaces } from "@file/document"; import { ConcreteHyperlink, ExternalHyperlink, ParagraphChild } from "@file/paragraph"; import { FileChild } from "@file/file-child"; import { IMediaData, Media } from "@file/media"; @@ -100,6 +101,24 @@ export const patchDocument = async i.name === "w:document"); + if (document) { + // We could check all namespaces from Document, but we'll instead + // check only those that may be used by our element types. + + // eslint-disable-next-line functional/immutable-data + document.attributes = document.attributes ?? {}; + for (const ns of ["mc", "wp", "r", "w15", "m"] as const) { + // eslint-disable-next-line functional/immutable-data + document.attributes[`xmlns:${ns}`] = DocumentAttributeNamespaces[ns]; + } + // eslint-disable-next-line functional/immutable-data + document.attributes["mc:Ignorable"] = `${document.attributes["mc:Ignorable"] || ""} w15`.trim(); + } + } + if (key.startsWith("word/") && !key.endsWith(".xml.rels")) { const context: IContext = { file,