fix: Ensure necessary namespaces are in patched doc (#2698)
* refactor: Extract timestamp properties In preparation for reworking DocumentAttributes. * refactor: Consolidate namespaces * fix: Ensure necessary namespaces are in patched doc Fixes #2697 * Fix tsc and ESLint errors * Fix CSpell * Add a test to fix code coverage failure
This commit is contained in:
@ -8,11 +8,14 @@
|
||||
// words - list of words to be always considered correct
|
||||
"words": [
|
||||
"Abjad",
|
||||
"aink",
|
||||
"aiueo",
|
||||
"ATLEAST",
|
||||
"chosung",
|
||||
"clippy",
|
||||
"datas",
|
||||
"dcmitype",
|
||||
"dcterms",
|
||||
"docsify",
|
||||
"dolan",
|
||||
"execa",
|
||||
@ -32,6 +35,7 @@
|
||||
"panose",
|
||||
"rels",
|
||||
"rsid",
|
||||
"sdtdh",
|
||||
"twip",
|
||||
"twips",
|
||||
"Xmlable",
|
||||
|
2
.github/workflows/default.yml
vendored
2
.github/workflows/default.yml
vendored
@ -65,5 +65,5 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Dependencies
|
||||
run: npm ci --force
|
||||
- name: Prettier
|
||||
- name: CSpell
|
||||
run: npm run cspell
|
||||
|
@ -2,7 +2,7 @@ import { FontOptions } from "@file/fonts/font-table";
|
||||
import { ICommentsOptions } from "@file/paragraph/run/comment-run";
|
||||
import { IHyphenationOptions } from "@file/settings";
|
||||
import { ICompatibilityOptions } from "@file/settings/compatibility";
|
||||
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";
|
||||
@ -75,15 +75,7 @@ export type 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));
|
||||
}
|
||||
@ -110,11 +102,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",
|
||||
}),
|
||||
);
|
||||
|
@ -1,89 +1,60 @@
|
||||
import { XmlAttributeComponent } from "@file/xml-components";
|
||||
import { AttributeMap, XmlAttributeComponent } from "@file/xml-components";
|
||||
|
||||
/* cSpell:disable */
|
||||
export type 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}`])),
|
||||
} as AttributeMap<IDocumentAttributesProperties>;
|
||||
|
||||
public constructor(ns: readonly DocumentAttributeNamespace[], Ignorable?: string) {
|
||||
super({ Ignorable, ...Object.fromEntries(ns.map((n) => [n, DocumentAttributeNamespaces[n]])) });
|
||||
}
|
||||
}
|
||||
|
@ -37,41 +37,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) {
|
||||
|
@ -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(), [
|
||||
|
@ -144,6 +144,10 @@ describe("External styles factory", () => {
|
||||
expect(() => new ExternalStylesFactory().newInstance(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo/>`)).to.throw(
|
||||
"can not find styles element",
|
||||
);
|
||||
|
||||
expect(() => new ExternalStylesFactory().newInstance(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`)).to.throw(
|
||||
"can not find styles element",
|
||||
);
|
||||
});
|
||||
|
||||
it("should parse styles elements", () => {
|
||||
|
@ -38,14 +38,7 @@ export type 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: [
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { BaseXmlComponent, IContext } from "./base";
|
||||
import { IXmlAttribute, IXmlableObject } from "./xmlable-object";
|
||||
|
||||
type AttributeMap<T> = Record<keyof T, string>;
|
||||
export type AttributeMap<T> = Record<keyof T, string>;
|
||||
|
||||
export type AttributeData = Record<string, boolean | number | string>;
|
||||
export type AttributePayload<T> = { readonly [P in keyof T]: { readonly key: string; readonly value: T[P] } };
|
||||
|
@ -2,6 +2,7 @@ import JSZip from "jszip";
|
||||
import { Element, js2xml } from "xml-js";
|
||||
|
||||
import { ImageReplacer } from "@export/packer/image-replacer";
|
||||
import { DocumentAttributeNamespaces } from "@file/document";
|
||||
import { IViewWrapper } from "@file/document-wrapper";
|
||||
import { File } from "@file/file";
|
||||
import { FileChild } from "@file/file-child";
|
||||
@ -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,
|
||||
|
Reference in New Issue
Block a user