Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Ensure necessary namespaces are in patched doc #2698

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions src/file/core-properties/properties.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -71,15 +71,7 @@ export interface IPropertiesOptions {
export class CoreProperties extends XmlComponent {
public constructor(options: Omit<IPropertiesOptions, "sections">) {
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));
}
Expand All @@ -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",
}),
);
Expand Down
129 changes: 50 additions & 79 deletions src/file/document/document-attributes.ts
Original file line number Diff line number Diff line change
@@ -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<Record<DocumentAttributeNamespace, string>> & {
readonly Ignorable?: string;
};

export class DocumentAttributes extends XmlAttributeComponent<IDocumentAttributesProperties> {
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]])) });
}
}
72 changes: 37 additions & 35 deletions src/file/document/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
23 changes: 4 additions & 19 deletions src/file/numbering/numbering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(), [
Expand Down
9 changes: 1 addition & 8 deletions src/file/styles/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down
19 changes: 19 additions & 0 deletions src/patcher/from-docx.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -100,6 +101,24 @@ export const patchDocument = async <T extends PatchDocumentOutputType = PatchDoc
}

const json = toJson(await value.async("text"));

if (key === "word/document.xml") {
const document = json.elements?.find((i) => 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,
Expand Down