Support taskpane settings (#311)

* feat: Add some props

* feat: Add some ext props

* fix: taskpanes

* fix: property

* fix: test

* 0.0.200
main
bokuweb 2021-06-30 22:37:13 +09:00 committed by GitHub
parent da9461f310
commit 3f88474f47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
55 changed files with 1004 additions and 49 deletions

View File

@ -0,0 +1,21 @@
use docx_rs::*;
pub fn main() -> Result<(), DocxError> {
let path = std::path::Path::new("./output/web_ext.docx");
let file = std::fs::File::create(&path).unwrap();
Docx::new()
.taskpanes()
.web_extension(
WebExtension::new(
"7f33b723-fb58-4524-8733-dbedc4b7c095",
"1.0.0.0",
"developer",
"Registry",
)
.property("hello", "\"world\""),
)
.add_paragraph(Paragraph::new().add_run(Run::new().add_text("Hello")))
.build()
.pack(file)?;
Ok(())
}

View File

@ -10,6 +10,7 @@ use crate::xml_builder::*;
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct ContentTypes {
types: BTreeMap<String, String>,
web_extension_count: usize,
}
impl ContentTypes {
@ -83,12 +84,33 @@ impl ContentTypes {
);
self
}
pub fn add_taskpanes(mut self) -> Self {
self.types.insert(
"/word/webextensions/taskpanes.xml".to_owned(),
"application/vnd.ms-office.webextensiontaskpanes+xml".to_owned(),
);
self
}
pub fn add_web_extensions(mut self) -> Self {
self.types.insert(
format!(
"/word/webextensions/webextension{}.xml",
self.web_extension_count
),
"application/vnd.ms-office.webextension+xml".to_owned(),
);
self.web_extension_count += 1;
self
}
}
impl Default for ContentTypes {
fn default() -> Self {
ContentTypes {
types: BTreeMap::new(),
web_extension_count: 1,
}
}
}
@ -163,6 +185,12 @@ mod tests {
"application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"
.to_owned(),
);
assert_eq!(ContentTypes { types }, c);
assert_eq!(
ContentTypes {
types,
web_extension_count: 1
},
c
);
}
}

View File

@ -18,7 +18,10 @@ mod pic_id;
mod rels;
mod settings;
mod styles;
mod taskpanes;
mod taskpanes_rels;
mod web_settings;
mod webextension;
mod xml_docx;
pub(crate) use build_xml::BuildXML;
@ -39,7 +42,10 @@ pub use numberings::*;
pub use rels::*;
pub use settings::*;
pub use styles::*;
pub use taskpanes::*;
pub use taskpanes_rels::*;
pub use web_settings::*;
pub use webextension::*;
pub use xml_docx::*;
use serde::Serialize;
@ -61,6 +67,9 @@ pub struct Docx {
pub header: Header,
pub comments_extended: CommentsExtended,
pub web_settings: WebSettings,
pub taskpanes: Option<Taskpanes>,
pub taskpanes_rels: TaskpanesRels,
pub web_extensions: Vec<WebExtension>,
}
impl Default for Docx {
@ -95,6 +104,9 @@ impl Default for Docx {
header,
comments_extended,
web_settings,
taskpanes: None,
taskpanes_rels: TaskpanesRels::new(),
web_extensions: vec![],
}
}
}
@ -265,12 +277,29 @@ impl Docx {
self
}
pub fn taskpanes(mut self) -> Self {
self.taskpanes = Some(Taskpanes::new());
self.rels = self.rels.add_taskpanes_rel();
self.content_type = self.content_type.add_taskpanes();
self
}
pub fn web_extension(mut self, ext: WebExtension) -> Self {
self.web_extensions.push(ext);
self.taskpanes_rels = self.taskpanes_rels.add_rel();
self.content_type = self.content_type.add_web_extensions();
self
}
pub fn build(&mut self) -> XMLDocx {
self.reset();
self.update_comments();
let (image_ids, images) = self.create_images();
let web_extensions = self.web_extensions.iter().map(|ext| ext.build()).collect();
self.document_rels.image_ids = image_ids;
XMLDocx {
@ -287,6 +316,9 @@ impl Docx {
media: images,
header: self.header.build(),
comments_extended: self.comments_extended.build(),
taskpanes: self.taskpanes.map(|taskpanes| taskpanes.build()),
taskpanes_rels: self.taskpanes_rels.build(),
web_extensions,
}
}

View File

@ -39,13 +39,20 @@ impl Rels {
self
}
pub fn add_rel(
mut self,
id: impl Into<String>,
rel_type: impl Into<String>,
target: impl Into<String>,
) -> Self {
self.rels.push((rel_type.into(), id.into(), target.into()));
pub fn add_taskpanes_rel(mut self) -> Self {
self = self.add_rel(
"http://schemas.microsoft.com/office/2011/relationships/webextensiontaskpanes",
"word/webextensions/taskpanes.xml",
);
self
}
pub fn add_rel(mut self, rel_type: impl Into<String>, target: impl Into<String>) -> Self {
self.rels.push((
rel_type.into(),
format!("rId{}", self.rels.len() + 1),
target.into(),
));
self
}

View File

@ -0,0 +1,60 @@
use serde::{Deserialize, Serialize};
use crate::documents::BuildXML;
use crate::xml_builder::*;
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
pub struct Taskpanes {}
impl Taskpanes {
pub fn new() -> Self {
Default::default()
}
}
impl Default for Taskpanes {
fn default() -> Self {
Self {}
}
}
impl BuildXML for Taskpanes {
fn build(&self) -> Vec<u8> {
let b = XMLBuilder::new();
let b = b
.declaration(Some(true))
.open_taskpanes("http://schemas.microsoft.com/office/webextensions/taskpanes/2010/11")
.open_taskpane("", "1", "350", "1")
.webextensionref(
"http://schemas.openxmlformats.org/officeDocument/2006/relationships",
"rId1",
)
.close()
.close();
b.build()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(test)]
use pretty_assertions::assert_eq;
use std::str;
#[test]
fn test_build() {
let c = Taskpanes::new();
let b = c.build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wetp:taskpanes xmlns:wetp="http://schemas.microsoft.com/office/webextensions/taskpanes/2010/11">
<wetp:taskpane dockstate="" visibility="1" width="350" row="1">
<wetp:webextensionref xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="rId1" />
</wetp:taskpane>
</wetp:taskpanes>"#
);
}
}

View File

@ -0,0 +1,70 @@
use serde::{Deserialize, Serialize};
use crate::documents::BuildXML;
use crate::xml_builder::*;
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct TaskpanesRels {
pub rels: Vec<(String, String, String)>,
}
impl TaskpanesRels {
pub fn new() -> Self {
Default::default()
}
pub fn add_rel(mut self) -> Self {
let index = self.rels.len() + 1;
self.rels.push((
"http://schemas.microsoft.com/office/2011/relationships/webextension".to_string(),
format!("rId{}", index),
format!("webextension{}.xml", index),
));
self
}
pub fn find_target(&self, rel_type: &str) -> Option<&(String, String, String)> {
self.rels.iter().find(|rel| rel.0 == rel_type)
}
}
impl Default for TaskpanesRels {
fn default() -> Self {
TaskpanesRels { rels: Vec::new() }
}
}
impl BuildXML for TaskpanesRels {
fn build(&self) -> Vec<u8> {
let b = XMLBuilder::new();
let mut b = b
.declaration(Some(true))
.open_relationships("http://schemas.openxmlformats.org/package/2006/relationships");
for (k, id, v) in self.rels.iter() {
b = b.relationship(id, k, v);
}
b.close().build()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(test)]
use pretty_assertions::assert_eq;
use std::str;
#[test]
fn test_build() {
let c = TaskpanesRels::new().add_rel();
let b = c.build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.microsoft.com/office/2011/relationships/webextension" Target="webextension1.xml" />
</Relationships>"#
);
}
}

View File

@ -0,0 +1,113 @@
use serde::Serialize;
use crate::documents::BuildXML;
use crate::escape::escape;
use crate::xml_builder::*;
#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct WebExtensionProperty {
pub name: String,
pub value: String,
}
impl WebExtensionProperty {
pub fn new(name: impl Into<String>, value: impl Into<String>) -> Self {
Self {
name: name.into(),
value: value.into(),
}
}
}
#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct WebExtension {
pub id: String,
pub version: String,
pub store: String,
pub store_type: String,
pub properties: Vec<WebExtensionProperty>,
}
impl WebExtension {
pub fn new(
id: impl Into<String>,
version: impl Into<String>,
store: impl Into<String>,
store_type: impl Into<String>,
) -> Self {
Self {
id: id.into(),
version: version.into(),
store: store.into(),
store_type: store_type.into(),
properties: vec![],
}
}
pub fn property(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
self.properties
.push(WebExtensionProperty::new(name, escape(&value.into())));
self
}
}
impl BuildXML for WebExtension {
fn build(&self) -> Vec<u8> {
let b = XMLBuilder::new();
let mut b = b
.declaration(Some(true))
.open_webextension(
"http://schemas.microsoft.com/office/webextensions/webextension/2010/11",
&format!("{{{}}}", &self.id),
)
.webextension_reference(&self.id, &self.version, &self.store, &self.store_type)
.webextension_alternate_references()
.open_webextension_properties();
for p in self.properties.iter() {
b = b.webextension_property(&p.name, &p.value);
}
b.close()
.webextension_bindings()
.webextension_snapshot(
"http://schemas.openxmlformats.org/officeDocument/2006/relationships",
)
.close()
.build()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(test)]
use pretty_assertions::assert_eq;
use std::str;
#[test]
fn test_build() {
let c = WebExtension::new(
"7f33b723-fb58-4524-8733-dbedc4b7c095",
"1.0.0.0",
"developer",
"Registry",
)
.property("hello", "world");
let b = c.build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<we:webextension xmlns:we="http://schemas.microsoft.com/office/webextensions/webextension/2010/11" id="{7f33b723-fb58-4524-8733-dbedc4b7c095}">
<we:reference id="7f33b723-fb58-4524-8733-dbedc4b7c095" version="1.0.0.0" store="developer" storeType="Registry" />
<we:alternateReferences />
<we:properties>
<we:property name="hello" value="world" />
</we:properties>
<we:bindings />
<we:snapshot xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" />
</we:webextension>"#
);
}
}

View File

@ -19,6 +19,9 @@ pub struct XMLDocx {
pub media: Vec<(usize, Vec<u8>)>,
pub header: Vec<u8>,
pub comments_extended: Vec<u8>,
pub taskpanes: Option<Vec<u8>>,
pub taskpanes_rels: Vec<u8>,
pub web_extensions: Vec<Vec<u8>>,
}
impl XMLDocx {

View File

@ -13,20 +13,17 @@ impl FromXML for Rels {
match e {
Ok(XmlEvent::StartElement { attributes, .. }) => {
if depth == 1 {
let mut id = "".to_owned();
let mut rel_type = "".to_owned();
let mut target = "".to_owned();
for attr in attributes {
let name: &str = &attr.name.local_name;
if name == "Id" {
id = attr.value.clone();
} else if name == "Type" {
if name == "Type" {
rel_type = attr.value.clone();
} else if name == "Target" {
target = attr.value.clone();
}
}
s = s.add_rel(id, rel_type, target);
s = s.add_rel(rel_type, target);
}
depth += 1;
}

View File

@ -330,6 +330,34 @@ impl XMLBuilder {
open!(open_doc_vars, "w:docVars");
closed!(doc_var, "w:docVar", "w:name", "w:val");
// webextension
open!(open_webextension, "we:webextension", "xmlns:we", "id");
closed!(
webextension_reference,
"we:reference",
"id",
"version",
"store",
"storeType"
);
closed!(webextension_alternate_references, "we:alternateReferences");
open!(open_webextension_properties, "we:properties");
closed!(webextension_property, "we:property", "name", "value");
closed!(webextension_bindings, "we:bindings");
closed!(webextension_snapshot, "we:snapshot", "xmlns:r");
// taskpanes
open!(open_taskpanes, "wetp:taskpanes", "xmlns:wetp");
open!(
open_taskpane,
"wetp:taskpane",
"dockstate",
"visibility",
"width",
"row"
);
closed!(webextensionref, "wetp:webextensionref", "xmlns:r", "r:id");
// CommentExtended
// w15:commentEx w15:paraId="00000001" w15:paraIdParent="57D1BD7C" w15:done="0"
pub(crate) fn comment_extended(

View File

@ -56,6 +56,25 @@ where
}
}
// For now support only taskpanes
if let Some(taskpanes) = xml.taskpanes {
zip.add_directory("word/webextensions/", Default::default())?;
zip.start_file("word/webextensions/taskpanes.xml", options)?;
zip.write_all(&taskpanes)?;
zip.add_directory("word/webextensions/_rels", Default::default())?;
zip.start_file("word/webextensions/_rels/taskpanes.xml.rels", options)?;
zip.write_all(&xml.taskpanes_rels)?;
for (i, ext) in xml.web_extensions.iter().enumerate() {
zip.start_file(
format!("word/webextensions/webextension{}.xml", i + 1),
options,
)?;
zip.write_all(&ext)?;
}
}
zip.finish()?;
Ok(())
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,6 +18,7 @@ import { BookmarkEnd } from "./bookmark-end";
import { Settings } from "./settings";
import { DocProps } from "./doc-props";
import { Styles } from "./styles";
import { WebExtension } from "./webextension";
import {
SectionProperty,
PageMargin,
@ -78,6 +79,8 @@ export class Docx {
settings: Settings = new Settings();
docProps: DocProps = new DocProps();
sectionProperty: SectionProperty = new SectionProperty();
_taskpanes: boolean = false;
webextensions: WebExtension[] = [];
styles = new Styles();
addParagraph(p: Paragraph) {
@ -181,6 +184,16 @@ export class Docx {
return this;
}
taskpanes() {
this._taskpanes = true;
return this;
}
webextension(e: WebExtension) {
this.webextensions.push(e);
return this;
}
buildRunFonts = (fonts: RunFonts | undefined) => {
let f = wasm.createRunFonts();
if (fonts?._ascii) {
@ -858,6 +871,23 @@ export class Docx {
docx = docx.updated_at(this.docProps._updatedAt);
}
if (this._taskpanes) {
docx = docx.taskpanes();
for (const e of this.webextensions) {
let ext = wasm.createWebExtension(
e._id,
e._version,
e._store,
e._storeType
);
for (const [name, value] of Object.entries(e.properties)) {
ext = ext.property(name, value);
}
docx = docx.web_extension(ext);
}
}
return docx;
}
@ -904,3 +934,4 @@ export * from "./delete-text";
export * from "./level";
export * from "./tab";
export * from "./json";
export * from "./webextension";

View File

@ -0,0 +1,21 @@
export class WebExtension {
_id: string;
_version: string;
_store: string;
_storeType: string;
properties: {
[k: string]: string;
} = {};
constructor(id: string, version: string, store: string, storeType: string) {
this._id = id;
this._version = version;
this._store = store;
this._storeType = storeType;
}
property(k: string, v: string) {
this.properties[k] = v;
return this;
}
}

View File

@ -1,6 +1,6 @@
{
"name": "docx-wasm",
"version": "0.0.199",
"version": "0.0.200",
"main": "dist/node/index.js",
"browser": "dist/web/index.js",
"author": "bokuweb <bokuweb12@gmail.com>",

View File

@ -103,6 +103,16 @@ impl Docx {
self
}
pub fn taskpanes(mut self) -> Self {
self.0 = self.0.taskpanes();
self
}
pub fn web_extension(mut self, ext: WebExtension) -> Self {
self.0 = self.0.web_extension(ext.take());
self
}
pub fn doc_grid(
mut self,
grid_type: docx_rs::DocGridType,

View File

@ -16,6 +16,7 @@ mod table;
mod table_cell;
mod table_cell_border;
mod table_row;
mod web_extension;
pub use abstract_numbering::*;
pub use adaptors::*;
@ -35,3 +36,4 @@ pub use table::*;
pub use table_cell::*;
pub use table_cell_border::*;
pub use table_row::*;
pub use web_extension::*;

View File

@ -0,0 +1,29 @@
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
#[derive(Debug)]
pub struct WebExtension(docx_rs::WebExtension);
#[wasm_bindgen(js_name = createWebExtension)]
pub fn create_web_extension(
id: &str,
version: &str,
store: &str,
store_type: &str,
) -> WebExtension {
WebExtension(docx_rs::WebExtension::new(id, version, store, store_type))
}
impl WebExtension {
pub fn take(self) -> docx_rs::WebExtension {
self.0
}
}
#[wasm_bindgen]
impl WebExtension {
pub fn property(mut self, name: &str, value: &str) -> Self {
self.0 = self.0.property(name, value);
self
}
}

View File

@ -24,6 +24,7 @@ Object {
"/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
"/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
},
"web_extension_count": 1,
},
"docProps": Object {
"app": Object {},
@ -354,6 +355,11 @@ Object {
},
],
},
"taskpanes": null,
"taskpanesRels": Object {
"rels": Array [],
},
"webExtensions": Array [],
"webSettings": Object {
"divs": Array [],
},
@ -384,6 +390,7 @@ Object {
"/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
"/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
},
"web_extension_count": 1,
},
"docProps": Object {
"app": Object {},
@ -1366,6 +1373,11 @@ Object {
},
],
},
"taskpanes": null,
"taskpanesRels": Object {
"rels": Array [],
},
"webExtensions": Array [],
"webSettings": Object {
"divs": Array [
Object {
@ -1696,6 +1708,7 @@ Object {
"/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
"/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
},
"web_extension_count": 1,
},
"docProps": Object {
"app": Object {},
@ -2443,6 +2456,11 @@ Object {
},
],
},
"taskpanes": null,
"taskpanesRels": Object {
"rels": Array [],
},
"webExtensions": Array [],
"webSettings": Object {
"divs": Array [],
},
@ -2473,6 +2491,7 @@ Object {
"/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
"/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
},
"web_extension_count": 1,
},
"docProps": Object {
"app": Object {},
@ -5295,6 +5314,11 @@ Object {
},
],
},
"taskpanes": null,
"taskpanesRels": Object {
"rels": Array [],
},
"webExtensions": Array [],
"webSettings": Object {
"divs": Array [],
},
@ -5325,6 +5349,7 @@ Object {
"/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
"/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
},
"web_extension_count": 1,
},
"docProps": Object {
"app": Object {},
@ -8413,6 +8438,11 @@ Object {
},
],
},
"taskpanes": null,
"taskpanesRels": Object {
"rels": Array [],
},
"webExtensions": Array [],
"webSettings": Object {
"divs": Array [],
},
@ -9052,6 +9082,7 @@ Object {
"/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
"/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
},
"web_extension_count": 1,
},
"docProps": Object {
"app": Object {},
@ -12973,6 +13004,11 @@ Object {
},
],
},
"taskpanes": null,
"taskpanesRels": Object {
"rels": Array [],
},
"webExtensions": Array [],
"webSettings": Object {
"divs": Array [],
},
@ -13003,6 +13039,7 @@ Object {
"/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
"/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
},
"web_extension_count": 1,
},
"docProps": Object {
"app": Object {},
@ -14569,6 +14606,11 @@ Object {
},
],
},
"taskpanes": null,
"taskpanesRels": Object {
"rels": Array [],
},
"webExtensions": Array [],
"webSettings": Object {
"divs": Array [],
},
@ -14599,6 +14641,7 @@ Object {
"/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
"/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
},
"web_extension_count": 1,
},
"docProps": Object {
"app": Object {},
@ -15814,6 +15857,11 @@ Object {
},
],
},
"taskpanes": null,
"taskpanesRels": Object {
"rels": Array [],
},
"webExtensions": Array [],
"webSettings": Object {
"divs": Array [],
},
@ -15844,6 +15892,7 @@ Object {
"/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
"/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
},
"web_extension_count": 1,
},
"docProps": Object {
"app": Object {},
@ -16725,6 +16774,11 @@ Object {
},
],
},
"taskpanes": null,
"taskpanesRels": Object {
"rels": Array [],
},
"webExtensions": Array [],
"webSettings": Object {
"divs": Array [],
},
@ -17116,3 +17170,51 @@ exports[`writer should write tl2br and tr2bl cells 3`] = `
<w:abstractNumId w:val=\\"1\\" />
</w:num></w:numbering>"
`;
exports[`writer should write webextension 1`] = `""`;
exports[`writer should write webextension 2`] = `""`;
exports[`writer should write webextension 3`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<Relationships xmlns=\\"http://schemas.openxmlformats.org/package/2006/relationships\\">
<Relationship Id=\\"rId1\\" Type=\\"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties\\" Target=\\"docProps/core.xml\\" />
<Relationship Id=\\"rId2\\" Type=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties\\" Target=\\"docProps/app.xml\\" />
<Relationship Id=\\"rId3\\" Type=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument\\" Target=\\"word/document.xml\\" />
<Relationship Id=\\"rId4\\" Type=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties\\" Target=\\"docProps/custom.xml\\" />
<Relationship Id=\\"rId5\\" Type=\\"http://schemas.microsoft.com/office/2011/relationships/webextensiontaskpanes\\" Target=\\"word/webextensions/taskpanes.xml\\" />
</Relationships>"
`;
exports[`writer should write webextension 4`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<Relationships xmlns=\\"http://schemas.openxmlformats.org/package/2006/relationships\\">
<Relationship Id=\\"rId1\\" Type=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles\\" Target=\\"styles.xml\\" />
<Relationship Id=\\"rId2\\" Type=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable\\" Target=\\"fontTable.xml\\" />
<Relationship Id=\\"rId3\\" Type=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings\\" Target=\\"settings.xml\\" />
<Relationship Id=\\"rId4\\" Type=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships/header\\" Target=\\"header1.xml\\" />
<Relationship Id=\\"rId5\\" Type=\\"http://schemas.microsoft.com/office/2011/relationships/commentsExtended\\" Target=\\"commentsExtended.xml\\" />
</Relationships>"
`;
exports[`writer should write webextension 5`] = `""`;
exports[`writer should write webextension 6`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" standalone=\\"yes\\"?>
<Relationships xmlns=\\"http://schemas.openxmlformats.org/package/2006/relationships\\">
<Relationship Id=\\"rId1\\" Type=\\"http://schemas.microsoft.com/office/2011/relationships/webextension\\" Target=\\"webextension1.xml\\" />
</Relationships>"
`;
exports[`writer should write webextension 7`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" standalone=\\"yes\\"?>
<we:webextension xmlns:we=\\"http://schemas.microsoft.com/office/webextensions/webextension/2010/11\\" id=\\"{7f33b723-fb58-4524-8733-dbedc4b7c095}\\">
<we:reference id=\\"7f33b723-fb58-4524-8733-dbedc4b7c095\\" version=\\"1.0.0.0\\" store=\\"developer\\" storeType=\\"Registry\\" />
<we:alternateReferences />
<we:properties>
<we:property name=\\"hello\\" value=\\"&quot;world&quot;\\" />
</we:properties>
<we:bindings />
<we:snapshot xmlns:r=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\\" />
</we:webextension>"
`;

View File

@ -284,7 +284,7 @@ describe("writer", () => {
const p = new w.Paragraph().addRun(new w.Run().addText("Hello!!"));
const buffer = new w.Docx()
.addParagraph(p)
.customProperty('hello', '{"world": 0}')
.customProperty("hello", '{"world": 0}')
.build();
writeFileSync("../output/custom.docx", buffer);
const z = new Zip(Buffer.from(buffer));
@ -294,4 +294,27 @@ describe("writer", () => {
}
}
});
test("should write webextension", () => {
const p = new w.Paragraph().addRun(new w.Run().addText("Hello!!"));
const buffer = new w.Docx()
.addParagraph(p)
.taskpanes()
.webextension(
new w.WebExtension(
"7f33b723-fb58-4524-8733-dbedc4b7c095",
"1.0.0.0",
"developer",
"Registry"
).property("hello", '"world"')
)
.build();
writeFileSync("../output/webextension.docx", buffer);
const z = new Zip(Buffer.from(buffer));
for (const e of z.getEntries()) {
if (e.entryName.match(/webextension1.xml|_rels|taskpanes.xml.rel/)) {
expect(z.readAsText(e)).toMatchSnapshot();
}
}
});
});

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/custom-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes" />

357
test.json 100644
View File

@ -0,0 +1,357 @@
{
"contentType": {
"types": {
"/_rels/.rels": "application/vnd.openxmlformats-package.relationships+xml",
"/docProps/app.xml": "application/vnd.openxmlformats-officedocument.extended-properties+xml",
"/docProps/core.xml": "application/vnd.openxmlformats-package.core-properties+xml",
"/docProps/custom.xml": "application/vnd.openxmlformats-officedocument.custom-properties+xml",
"/word/_rels/document.xml.rels": "application/vnd.openxmlformats-package.relationships+xml",
"/word/comments.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml",
"/word/commentsExtended.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.commentsExtended+xml",
"/word/document.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
"/word/fontTable.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml",
"/word/header1.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml",
"/word/numbering.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
"/word/settings.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
"/word/styles.xml": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml"
}
},
"rels": {
"rels": [
[
"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
"rId1",
"docProps/core.xml"
],
[
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
"rId2",
"docProps/app.xml"
],
[
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
"rId3",
"word/document.xml"
],
[
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties",
"rId4",
"docProps/custom.xml"
]
]
},
"documentRels": {
"hasComments": false,
"hasNumberings": false,
"imageIds": []
},
"docProps": {
"app": {},
"core": {
"config": {
"created": null,
"creator": null,
"description": null,
"language": null,
"lastModifiedBy": null,
"modified": null,
"revision": null,
"subject": null,
"title": null
}
},
"custom": {
"properties": {
"hello": "world"
}
}
},
"styles": {
"docDefaults": {
"runPropertyDefault": {
"runProperty": {
"sz": null,
"szCs": null,
"color": null,
"highlight": null,
"vertAlign": null,
"underline": null,
"bold": null,
"boldCs": null,
"italic": null,
"italicCs": null,
"vanish": null,
"spacing": null,
"fonts": null,
"textBorder": null,
"del": null,
"ins": null
}
}
},
"styles": [
{
"styleId": "Normal",
"name": "Normal",
"styleType": "paragraph",
"runProperty": {
"sz": null,
"szCs": null,
"color": null,
"highlight": null,
"vertAlign": null,
"underline": null,
"bold": null,
"boldCs": null,
"italic": null,
"italicCs": null,
"vanish": null,
"spacing": null,
"fonts": null,
"textBorder": null,
"del": null,
"ins": null
},
"paragraphProperty": {
"runProperty": {
"sz": null,
"szCs": null,
"color": null,
"highlight": null,
"vertAlign": null,
"underline": null,
"bold": null,
"boldCs": null,
"italic": null,
"italicCs": null,
"vanish": null,
"spacing": null,
"fonts": null,
"textBorder": null,
"del": null,
"ins": null
},
"style": null,
"numberingProperty": null,
"alignment": null,
"indent": null,
"lineHeight": null,
"keepNext": false,
"keepLines": false,
"pageBreakBefore": false,
"windowControl": false,
"divId": null
},
"tableProperty": {
"width": {
"width": 0,
"widthType": "Auto"
},
"justification": "left",
"borders": {
"top": {
"borderType": "single",
"size": 2,
"color": "000000",
"position": "top",
"space": 0
},
"left": {
"borderType": "single",
"size": 2,
"color": "000000",
"position": "left",
"space": 0
},
"bottom": {
"borderType": "single",
"size": 2,
"color": "000000",
"position": "bottom",
"space": 0
},
"right": {
"borderType": "single",
"size": 2,
"color": "000000",
"position": "right",
"space": 0
},
"insideH": {
"borderType": "single",
"size": 2,
"color": "000000",
"position": "insideH",
"space": 0
},
"insideV": {
"borderType": "single",
"size": 2,
"color": "000000",
"position": "insideV",
"space": 0
}
},
"margins": {
"top": {
"val": 0,
"widthType": "DXA"
},
"left": {
"val": 55,
"widthType": "DXA"
},
"bottom": {
"val": 0,
"widthType": "DXA"
},
"right": {
"val": 55,
"widthType": "DXA"
}
},
"indent": null,
"style": null,
"layout": null
},
"tableCellProperty": {
"width": null,
"borders": null,
"gridSpan": null,
"verticalMerge": null,
"verticalAlign": null,
"textDirection": null,
"shading": null
},
"basedOn": "Normal"
}
]
},
"document": {
"children": [
{
"type": "paragraph",
"data": {
"id": "00000001",
"children": [
{
"type": "run",
"data": {
"runProperty": {
"sz": null,
"szCs": null,
"color": null,
"highlight": null,
"vertAlign": null,
"underline": null,
"bold": null,
"boldCs": null,
"italic": null,
"italicCs": null,
"vanish": null,
"spacing": null,
"fonts": null,
"textBorder": null,
"del": null,
"ins": null
},
"children": [
{
"type": "text",
"data": {
"preserveSpace": true,
"text": "Hello"
}
}
]
}
}
],
"property": {
"runProperty": {
"sz": null,
"szCs": null,
"color": null,
"highlight": null,
"vertAlign": null,
"underline": null,
"bold": null,
"boldCs": null,
"italic": null,
"italicCs": null,
"vanish": null,
"spacing": null,
"fonts": null,
"textBorder": null,
"del": null,
"ins": null
},
"style": null,
"numberingProperty": null,
"alignment": null,
"indent": null,
"lineHeight": null,
"keepNext": false,
"keepLines": false,
"pageBreakBefore": false,
"windowControl": false,
"divId": null
},
"hasNumbering": false
}
}
],
"sectionProperty": {
"pageSize": {
"w": 11906,
"h": 16838,
"orient": null
},
"pageMargin": {
"top": 1985,
"left": 1701,
"bottom": 1701,
"right": 1701,
"header": 851,
"footer": 992,
"gutter": 0
},
"columns": 425,
"docGrid": {
"gridType": "lines",
"linePitch": 360,
"charSpace": null
},
"headerReference": {
"headerType": "default",
"id": "rId4"
},
"sectionType": null
},
"hasNumbering": false
},
"comments": {
"comments": []
},
"numberings": {
"abstractNums": [],
"numberings": []
},
"settings": {
"defaultTabStop": 840,
"zoom": 100,
"docId": null,
"docVars": []
},
"fontTable": {},
"media": [],
"header": {
"children": []
},
"commentsExtended": {
"children": []
},
"webSettings": {
"divs": []
}
}