Support default fonts (#207)

* feat: support default font writer

* feat: Support default font by js

* fix: update snaps

* fix: update snaps
main
bokuweb 2020-12-14 15:01:23 +09:00 committed by GitHub
parent 1020f4bd04
commit 688632bca2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 375 additions and 67 deletions

16
Cargo.lock generated
View File

@ -239,9 +239,9 @@ dependencies = [
[[package]] [[package]]
name = "image" name = "image"
version = "0.23.11" version = "0.23.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f0a8345b33b082aedec2f4d7d4a926b845cee184cbe78b703413066564431b" checksum = "7ce04077ead78e39ae8610ad26216aed811996b043d47beed5090db674f9e9b5"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
"byteorder", "byteorder",
@ -258,9 +258,9 @@ dependencies = [
[[package]] [[package]]
name = "insta" name = "insta"
version = "1.1.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7e7528a20113cf7ca90eddfc2439c608188b6eafc0613964da2bd140c92acec" checksum = "863bf97e7130bf788f29a99bc4073735af6b8ecc3da6a39c23b3a688d2d3109a"
dependencies = [ dependencies = [
"console", "console",
"difference", "difference",
@ -300,9 +300,9 @@ checksum = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558"
[[package]] [[package]]
name = "linked-hash-map" name = "linked-hash-map"
version = "0.5.2" version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
[[package]] [[package]]
name = "log" name = "log"
@ -530,9 +530,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_yaml" name = "serde_yaml"
version = "0.8.11" version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7"
dependencies = [ dependencies = [
"dtoa", "dtoa",
"linked-hash-map", "linked-hash-map",

View File

@ -21,7 +21,7 @@ path = "src/lib.rs"
[dependencies] [dependencies]
xml-rs = "0.8.3" xml-rs = "0.8.3"
wasm-bindgen = "0.2.50" wasm-bindgen = "0.2.69"
thiserror = "1.0" thiserror = "1.0"
zip = { version = "0.5.6", default-features = false, features = ["deflate"] } zip = { version = "0.5.6", default-features = false, features = ["deflate"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
@ -30,4 +30,4 @@ image = "0.23.12"
[dev-dependencies] [dev-dependencies]
pretty_assertions = "0.6.1" pretty_assertions = "0.6.1"
insta = "1.1" insta = "1.3"

View File

@ -1,9 +1,10 @@
use serde::Serialize; use serde::Serialize;
use crate::documents::BuildXML;
use crate::xml_builder::*; use crate::xml_builder::*;
use crate::{documents::BuildXML, RunProperty};
use super::run_property_default::*; use super::run_property_default::*;
use super::RunFonts;
#[derive(Debug, Clone, PartialEq, Serialize)] #[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
@ -15,6 +16,26 @@ impl DocDefaults {
pub fn new() -> DocDefaults { pub fn new() -> DocDefaults {
Default::default() Default::default()
} }
pub fn size(mut self, size: usize) -> Self {
self.run_property_default = self.run_property_default.size(size);
self
}
pub fn spacing(mut self, spacing: i32) -> Self {
self.run_property_default = self.run_property_default.spacing(spacing);
self
}
pub fn fonts(mut self, font: RunFonts) -> Self {
self.run_property_default = self.run_property_default.fonts(font);
self
}
pub(crate) fn run_property(mut self, p: RunProperty) -> Self {
self.run_property_default = self.run_property_default.run_property(p);
self
}
} }
impl Default for DocDefaults { impl Default for DocDefaults {

View File

@ -1,6 +1,6 @@
use serde::Serialize; use serde::Serialize;
use super::RunProperty; use super::*;
use crate::documents::BuildXML; use crate::documents::BuildXML;
use crate::xml_builder::*; use crate::xml_builder::*;
@ -14,6 +14,26 @@ impl RunPropertyDefault {
pub fn new() -> RunPropertyDefault { pub fn new() -> RunPropertyDefault {
Default::default() Default::default()
} }
pub fn size(mut self, size: usize) -> Self {
self.run_property = self.run_property.size(size);
self
}
pub fn spacing(mut self, spacing: i32) -> Self {
self.run_property = self.run_property.spacing(spacing);
self
}
pub fn fonts(mut self, font: RunFonts) -> Self {
self.run_property = self.run_property.fonts(font);
self
}
pub(crate) fn run_property(mut self, p: RunProperty) -> Self {
self.run_property = p;
self
}
} }
impl Default for RunPropertyDefault { impl Default for RunPropertyDefault {

View File

@ -209,6 +209,21 @@ impl Docx {
self self
} }
pub fn default_size(mut self, size: usize) -> Self {
self.styles = self.styles.default_size(size);
self
}
pub fn default_spacing(mut self, spacing: i32) -> Self {
self.styles = self.styles.default_spacing(spacing);
self
}
pub fn default_fonts(mut self, font: RunFonts) -> Self {
self.styles = self.styles.default_fonts(font);
self
}
pub fn build(&mut self) -> XMLDocx { pub fn build(&mut self) -> XMLDocx {
self.update_comments(); self.update_comments();
let (image_ids, images) = self.create_images(); let (image_ids, images) = self.create_images();

View File

@ -1,6 +1,6 @@
use serde::Serialize; use serde::Serialize;
use super::{DocDefaults, Style}; use super::*;
use crate::documents::BuildXML; use crate::documents::BuildXML;
use crate::types::*; use crate::types::*;
use crate::xml_builder::*; use crate::xml_builder::*;
@ -21,6 +21,26 @@ impl Styles {
self.styles.push(style); self.styles.push(style);
self self
} }
pub fn default_size(mut self, size: usize) -> Self {
self.doc_defaults = self.doc_defaults.size(size);
self
}
pub fn default_spacing(mut self, spacing: i32) -> Self {
self.doc_defaults = self.doc_defaults.spacing(spacing);
self
}
pub fn default_fonts(mut self, font: RunFonts) -> Self {
self.doc_defaults = self.doc_defaults.fonts(font);
self
}
pub(crate) fn doc_defaults(mut self, doc_defaults: DocDefaults) -> Self {
self.doc_defaults = doc_defaults;
self
}
} }
impl Default for Styles { impl Default for Styles {

View File

@ -0,0 +1,39 @@
use std::io::Read;
use std::str::FromStr;
use xml::attribute::OwnedAttribute;
use xml::reader::{EventReader, XmlEvent};
use super::*;
impl ElementReader for DocDefaults {
fn read<R: Read>(
r: &mut EventReader<R>,
_attrs: &[OwnedAttribute],
) -> Result<Self, ReaderError> {
let mut doc_defaults = DocDefaults::new();
loop {
let e = r.next();
match e {
Ok(XmlEvent::StartElement {
attributes, name, ..
}) => {
let e = XMLElement::from_str(&name.local_name).unwrap();
if let XMLElement::RunProperty = e {
let run_pr = RunProperty::read(r, &attributes)?;
doc_defaults = doc_defaults.run_property(run_pr);
continue;
}
}
Ok(XmlEvent::EndElement { name, .. }) => {
let e = XMLElement::from_str(&name.local_name).unwrap();
if let XMLElement::DocDefaults = e {
return Ok(doc_defaults);
}
}
Err(_) => return Err(ReaderError::XMLReadError),
_ => {}
}
}
}
}

View File

@ -4,6 +4,7 @@ mod attributes;
mod bookmark_end; mod bookmark_end;
mod bookmark_start; mod bookmark_start;
mod delete; mod delete;
mod doc_defaults;
mod document; mod document;
mod document_rels; mod document_rels;
mod drawing; mod drawing;

View File

@ -56,7 +56,6 @@ impl ElementReader for Run {
run = run.size(usize::from_str(&attributes[0].value)?) run = run.size(usize::from_str(&attributes[0].value)?)
} }
XMLElement::Underline => { XMLElement::Underline => {
dbg!(&attributes);
run = run.underline(&attributes[0].value.clone()) run = run.underline(&attributes[0].value.clone())
} }
XMLElement::Italic => { XMLElement::Italic => {

View File

@ -35,6 +35,8 @@ impl ElementReader for RunProperty {
rp = rp.spacing(v) rp = rp.spacing(v)
} }
} }
// TODO: Implement later
XMLElement::RunFonts => {}
XMLElement::Underline => rp = rp.underline(&attributes[0].value.clone()), XMLElement::Underline => rp = rp.underline(&attributes[0].value.clone()),
XMLElement::Italic => { XMLElement::Italic => {
if !read_bool(&attributes) { if !read_bool(&attributes) {
@ -43,7 +45,6 @@ impl ElementReader for RunProperty {
rp = rp.italic(); rp = rp.italic();
} }
XMLElement::Vanish => rp = rp.vanish(), XMLElement::Vanish => rp = rp.vanish(),
// TODO: Add run fonts reader
_ => {} _ => {}
} }
} }

View File

@ -17,10 +17,18 @@ impl FromXML for Styles {
attributes, name, .. attributes, name, ..
}) => { }) => {
let e = XMLElement::from_str(&name.local_name).unwrap(); let e = XMLElement::from_str(&name.local_name).unwrap();
if let XMLElement::Style = e { match e {
let s = Style::read(&mut parser, &attributes)?; XMLElement::Style => {
styles = styles.add_style(s); let s = Style::read(&mut parser, &attributes)?;
continue; styles = styles.add_style(s);
continue;
}
XMLElement::DocDefaults => {
let d = DocDefaults::read(&mut parser, &attributes)?;
styles = styles.doc_defaults(d);
continue;
}
_ => {}
} }
} }
Ok(XmlEvent::EndElement { name, .. }) => { Ok(XmlEvent::EndElement { name, .. }) => {

View File

@ -14,6 +14,7 @@ pub enum XMLElement {
RunProperty, RunProperty,
Color, Color,
Underline, Underline,
RunFonts,
Size, Size,
SizeCs, SizeCs,
Spacing, Spacing,
@ -100,6 +101,8 @@ pub enum XMLElement {
TxbxContent, TxbxContent,
Pict, Pict,
DocId, DocId,
DocDefaults,
RunPropertyDefault,
SectionProperty, SectionProperty,
PageSize, PageSize,
PageMargin, PageMargin,
@ -257,7 +260,10 @@ impl FromStr for XMLElement {
"docId" => Ok(XMLElement::DocId), "docId" => Ok(XMLElement::DocId),
"sectPr" => Ok(XMLElement::SectionProperty), "sectPr" => Ok(XMLElement::SectionProperty),
"pgSz" => Ok(XMLElement::PageSize), "pgSz" => Ok(XMLElement::PageSize),
"rFonts" => Ok(XMLElement::RunFonts),
"pgMar" => Ok(XMLElement::PageMargin), "pgMar" => Ok(XMLElement::PageMargin),
"docDefaults" => Ok(XMLElement::DocDefaults),
"rPrDefault" => Ok(XMLElement::RunPropertyDefault),
_ => Ok(XMLElement::Unsupported), _ => Ok(XMLElement::Unsupported),
} }
} }

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

@ -0,0 +1,20 @@
import { RunProperty, RunFonts } from "./run";
export class DocDefaults {
runProperty: RunProperty;
size(size: number) {
this.runProperty = { ...this.runProperty, size };
return this;
}
fonts(fonts: RunFonts) {
this.runProperty = { ...this.runProperty, fonts };
return this;
}
spacing(spacing: number) {
this.runProperty = { ...this.runProperty, spacing };
return this;
}
}

View File

@ -5,7 +5,7 @@ import { DeleteText } from "./delete-text";
import { Table } from "./table"; import { Table } from "./table";
import { TableCell } from "./table-cell"; import { TableCell } from "./table-cell";
import { BorderType } from "./table-cell-border"; import { BorderType } from "./table-cell-border";
import { Run } from "./run"; import { Run, RunFonts } from "./run";
import { Text } from "./text"; import { Text } from "./text";
import { Tab } from "./tab"; import { Tab } from "./tab";
import { Break } from "./break"; import { Break } from "./break";
@ -16,6 +16,7 @@ import { Numbering } from "./numbering";
import { BookmarkStart } from "./bookmark-start"; import { BookmarkStart } from "./bookmark-start";
import { BookmarkEnd } from "./bookmark-end"; import { BookmarkEnd } from "./bookmark-end";
import { Settings } from "./settings"; import { Settings } from "./settings";
import { Styles } from "./styles";
import { SectionProperty, PageMargin } from "./section-property"; import { SectionProperty, PageMargin } from "./section-property";
import { DocxJSON } from "./json"; import { DocxJSON } from "./json";
@ -56,6 +57,7 @@ export class Docx {
numberings: Numbering[] = []; numberings: Numbering[] = [];
settings: Settings = new Settings(); settings: Settings = new Settings();
sectionProperty: SectionProperty = new SectionProperty(); sectionProperty: SectionProperty = new SectionProperty();
styles = new Styles();
addParagraph(p: Paragraph) { addParagraph(p: Paragraph) {
if (p.hasNumberings) { if (p.hasNumberings) {
@ -108,6 +110,38 @@ export class Docx {
return this; return this;
} }
defaultSize(size: number) {
this.styles.defaultSize(size);
return this;
}
defaultFonts(fonts: RunFonts) {
this.styles.defaultFonts(fonts);
return this;
}
defaultSpacing(spacing: number) {
this.styles.defaultSpacing(spacing);
return this;
}
buildRunFonts = (fonts: RunFonts | undefined) => {
let f = wasm.createRunFonts();
if (fonts?._ascii) {
f = f.ascii(fonts._ascii);
}
if (fonts?._hiAnsi) {
f = f.hi_ansi(fonts._hiAnsi);
}
if (fonts?._cs) {
f = f.cs(fonts._cs);
}
if (fonts?._eastAsia) {
f = f.east_asia(fonts._eastAsia);
}
return f;
};
buildRun(r: Run) { buildRun(r: Run) {
let run = wasm.createRun(); let run = wasm.createRun();
r.children.forEach((child) => { r.children.forEach((child) => {
@ -160,20 +194,8 @@ export class Docx {
run = run.spacing(r.property.spacing); run = run.spacing(r.property.spacing);
} }
let f = wasm.createRunFonts(); const fonts = this.buildRunFonts(r.property.fonts);
if (r.property.fonts?._ascii) { run = run.fonts(fonts);
f = f.ascii(r.property.fonts._ascii);
}
if (r.property.fonts?._hiAnsi) {
f = f.hi_ansi(r.property.fonts._hiAnsi);
}
if (r.property.fonts?._cs) {
f = f.cs(r.property.fonts._cs);
}
if (r.property.fonts?._eastAsia) {
f = f.east_asia(r.property.fonts._eastAsia);
}
run = run.fonts(f);
return run; return run;
} }
@ -611,6 +633,25 @@ export class Docx {
docx = docx.page_size(w, h); docx = docx.page_size(w, h);
} }
if (this.styles?.docDefaults) {
if (this.styles.docDefaults.runProperty?.fonts) {
const fonts = this.buildRunFonts(
this.styles.docDefaults.runProperty.fonts
);
docx = docx.default_fonts(fonts);
}
if (this.styles.docDefaults.runProperty?.size) {
docx = docx.default_size(this.styles.docDefaults.runProperty.size);
}
if (this.styles.docDefaults.runProperty?.spacing) {
docx = docx.default_spacing(
this.styles.docDefaults.runProperty.spacing
);
}
}
const buf = docx.build(this.hasNumberings); const buf = docx.build(this.hasNumberings);
docx.free(); docx.free();
return buf; return buf;
@ -631,6 +672,8 @@ export * from "./table-cell-borders";
export * from "./table-row"; export * from "./table-row";
export * from "./run"; export * from "./run";
export * from "./text"; export * from "./text";
export * from "./style";
export * from "./styles";
export * from "./comment"; export * from "./comment";
export * from "./comment-end"; export * from "./comment-end";
export * from "./numbering"; export * from "./numbering";

View File

@ -0,0 +1,32 @@
import { RunProperty } from "./run";
import { ParagraphProperty } from "./paragraph";
import { TableProperty } from "./table";
export type StyleType =
| "paragraph"
| "character"
| "numbering"
| "table"
| "unsupported";
export class Style {
_styleId: string;
_name: string;
_styleType: StyleType;
_runProperty: RunProperty;
_paragraphProperty: ParagraphProperty;
_tableProperty: TableProperty;
_basedOn: string | null;
constructor(id: string, type: StyleType) {
this._styleId = id;
this._styleType = type;
this._name = "";
this._runProperty = {};
this._paragraphProperty = { runProperty: {} };
this._tableProperty = {};
this._basedOn = null;
}
// TODO: Add setter
}

View File

@ -0,0 +1,23 @@
import { Style } from "./style";
import { DocDefaults } from "./doc-defaults";
import { RunFonts } from "./run";
export class Styles {
styles: Style[];
docDefaults = new DocDefaults();
defaultSize(size: number) {
this.docDefaults.size(size);
return this;
}
defaultFonts(fonts: RunFonts) {
this.docDefaults.fonts(fonts);
return this;
}
defaultSpacing(spacing: number) {
this.docDefaults.spacing(spacing);
return this;
}
}

View File

@ -13,7 +13,7 @@
"tsc:web": "tsc -p tsconfig.web.json", "tsc:web": "tsc -p tsconfig.web.json",
"tsc:node": "tsc -p tsconfig.node.json", "tsc:node": "tsc -p tsconfig.node.json",
"tsc": "run-p tsc:*", "tsc": "run-p tsc:*",
"test": "jest", "test": "npm run build && tsc && jest",
"build": "run-s wasm-pack tsc", "build": "run-s wasm-pack tsc",
"serve": "webpack-dev-server --open --config webpack.dev.js", "serve": "webpack-dev-server --open --config webpack.dev.js",
"prepublishOnly": "npm run build" "prepublishOnly": "npm run build"

View File

@ -58,6 +58,21 @@ impl Docx {
self self
} }
pub fn default_size(mut self, size: usize) -> Self {
self.0.styles = self.0.styles.default_size(size);
self
}
pub fn default_spacing(mut self, spacing: i32) -> Self {
self.0.styles = self.0.styles.default_spacing(spacing);
self
}
pub fn default_fonts(mut self, font: RunFonts) -> Self {
self.0.styles = self.0.styles.default_fonts(font.take());
self
}
pub fn build(&mut self, has_numberings: bool) -> Result<Vec<u8>, JsValue> { pub fn build(&mut self, has_numberings: bool) -> Result<Vec<u8>, JsValue> {
let buf = Vec::new(); let buf = Vec::new();
let mut cur = std::io::Cursor::new(buf); let mut cur = std::io::Cursor::new(buf);

View File

@ -1902,8 +1902,8 @@ Object {
"italic": null, "italic": null,
"italicCs": null, "italicCs": null,
"spacing": null, "spacing": null,
"sz": null, "sz": 21,
"szCs": null, "szCs": 21,
"underline": null, "underline": null,
"vanish": null, "vanish": null,
}, },
@ -4199,8 +4199,8 @@ Object {
"italic": null, "italic": null,
"italicCs": null, "italicCs": null,
"spacing": null, "spacing": null,
"sz": null, "sz": 21,
"szCs": null, "szCs": 21,
"underline": null, "underline": null,
"vanish": null, "vanish": null,
}, },
@ -5460,8 +5460,8 @@ Object {
"italic": null, "italic": null,
"italicCs": null, "italicCs": null,
"spacing": null, "spacing": null,
"sz": null, "sz": 21,
"szCs": null, "szCs": 21,
"underline": null, "underline": null,
"vanish": null, "vanish": null,
}, },
@ -5957,6 +5957,33 @@ Object {
} }
`; `;
exports[`writer should write default font 1`] = `
"<?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 default font 2`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" standalone=\\"yes\\"?>
<w:document xmlns:o=\\"urn:schemas-microsoft-com:office:office\\" xmlns:r=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\\" xmlns:v=\\"urn:schemas-microsoft-com:vml\\" xmlns:w=\\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\\" xmlns:w10=\\"urn:schemas-microsoft-com:office:word\\" xmlns:wp=\\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\\" xmlns:wps=\\"http://schemas.microsoft.com/office/word/2010/wordprocessingShape\\" xmlns:wpg=\\"http://schemas.microsoft.com/office/word/2010/wordprocessingGroup\\" xmlns:mc=\\"http://schemas.openxmlformats.org/markup-compatibility/2006\\" xmlns:wp14=\\"http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing\\" xmlns:w14=\\"http://schemas.microsoft.com/office/word/2010/wordml\\" xmlns:w15=\\"http://schemas.microsoft.com/office/word/2012/wordml\\" mc:Ignorable=\\"w14 wp14\\">
<w:body><w:p w14:paraId=\\"0000002e\\"><w:pPr><w:rPr /></w:pPr><w:r><w:rPr><w:rFonts /></w:rPr><w:t xml:space=\\"preserve\\">Hello world!!!!</w:t></w:r></w:p><w:sectPr><w:pgSz w:w=\\"11906\\" w:h=\\"16838\\" /><w:pgMar w:top=\\"1985\\" w:right=\\"1701\\" w:bottom=\\"1701\\" w:left=\\"1701\\" w:header=\\"851\\" w:footer=\\"992\\" w:gutter=\\"0\\" /><w:headerReference w:type=\\"default\\" r:id=\\"rId4\\" /><w:cols w:space=\\"425\\" />
<w:docGrid w:type=\\"lines\\" w:linePitch=\\"360\\" />
</w:sectPr></w:body>
</w:document>"
`;
exports[`writer should write default font 3`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\" standalone=\\"yes\\"?>
<w:numbering xmlns:r=\\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\\" xmlns:o=\\"urn:schemas-microsoft-com:office:office\\" xmlns:v=\\"urn:schemas-microsoft-com:vml\\" xmlns:w=\\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\\"><w:abstractNum w:abstractNumId=\\"1\\"><w:lvl w:ilvl=\\"0\\"><w:start w:val=\\"1\\" /><w:numFmt w:val=\\"decimal\\" /><w:lvlText w:val=\\"%1.\\" /><w:lvlJc w:val=\\"left\\" /><w:pPr><w:rPr /><w:ind w:left=\\"420\\" w:right=\\"0\\" w:hanging=\\"420\\" /></w:pPr><w:rPr /></w:lvl><w:lvl w:ilvl=\\"1\\"><w:start w:val=\\"1\\" /><w:numFmt w:val=\\"decimal\\" /><w:lvlText w:val=\\"(%2)\\" /><w:lvlJc w:val=\\"left\\" /><w:pPr><w:rPr /><w:ind w:left=\\"840\\" w:right=\\"0\\" w:hanging=\\"420\\" /></w:pPr><w:rPr /></w:lvl><w:lvl w:ilvl=\\"2\\"><w:start w:val=\\"1\\" /><w:numFmt w:val=\\"decimalEnclosedCircle\\" /><w:lvlText w:val=\\"%3\\" /><w:lvlJc w:val=\\"left\\" /><w:pPr><w:rPr /><w:ind w:left=\\"1260\\" w:right=\\"0\\" w:hanging=\\"420\\" /></w:pPr><w:rPr /></w:lvl><w:lvl w:ilvl=\\"3\\"><w:start w:val=\\"1\\" /><w:numFmt w:val=\\"decimal\\" /><w:lvlText w:val=\\"%4.\\" /><w:lvlJc w:val=\\"left\\" /><w:pPr><w:rPr /><w:ind w:left=\\"1680\\" w:right=\\"0\\" w:hanging=\\"420\\" /></w:pPr><w:rPr /></w:lvl><w:lvl w:ilvl=\\"4\\"><w:start w:val=\\"1\\" /><w:numFmt w:val=\\"decimal\\" /><w:lvlText w:val=\\"(%5)\\" /><w:lvlJc w:val=\\"left\\" /><w:pPr><w:rPr /><w:ind w:left=\\"2100\\" w:right=\\"0\\" w:hanging=\\"420\\" /></w:pPr><w:rPr /></w:lvl><w:lvl w:ilvl=\\"5\\"><w:start w:val=\\"1\\" /><w:numFmt w:val=\\"decimalEnclosedCircle\\" /><w:lvlText w:val=\\"%6\\" /><w:lvlJc w:val=\\"left\\" /><w:pPr><w:rPr /><w:ind w:left=\\"2520\\" w:right=\\"0\\" w:hanging=\\"420\\" /></w:pPr><w:rPr /></w:lvl><w:lvl w:ilvl=\\"6\\"><w:start w:val=\\"1\\" /><w:numFmt w:val=\\"decimal\\" /><w:lvlText w:val=\\"%7.\\" /><w:lvlJc w:val=\\"left\\" /><w:pPr><w:rPr /><w:ind w:left=\\"2940\\" w:right=\\"0\\" w:hanging=\\"420\\" /></w:pPr><w:rPr /></w:lvl><w:lvl w:ilvl=\\"7\\"><w:start w:val=\\"1\\" /><w:numFmt w:val=\\"decimal\\" /><w:lvlText w:val=\\"(%8)\\" /><w:lvlJc w:val=\\"left\\" /><w:pPr><w:rPr /><w:ind w:left=\\"3360\\" w:right=\\"0\\" w:hanging=\\"420\\" /></w:pPr><w:rPr /></w:lvl><w:lvl w:ilvl=\\"8\\"><w:start w:val=\\"1\\" /><w:numFmt w:val=\\"decimalEnclosedCircle\\" /><w:lvlText w:val=\\"%9\\" /><w:lvlJc w:val=\\"left\\" /><w:pPr><w:rPr /><w:ind w:left=\\"3780\\" w:right=\\"0\\" w:hanging=\\"420\\" /></w:pPr><w:rPr /></w:lvl></w:abstractNum><w:num w:numId=\\"1\\">
<w:abstractNumId w:val=\\"1\\" />
</w:num></w:numbering>"
`;
exports[`writer should write hello 1`] = ` exports[`writer should write hello 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?> "<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<Relationships xmlns=\\"http://schemas.openxmlformats.org/package/2006/relationships\\"> <Relationships xmlns=\\"http://schemas.openxmlformats.org/package/2006/relationships\\">

View File

@ -1,6 +1,5 @@
const w = require("../dist/node"); const w = require("../dist/node");
const { readFileSync, writeFileSync } = require("fs"); const { readFileSync, writeFileSync } = require("fs");
const path = require("path");
const Zip = require("adm-zip"); const Zip = require("adm-zip");
describe("reader", () => { describe("reader", () => {
@ -76,7 +75,26 @@ describe("writer", () => {
.addParagraph(p) .addParagraph(p)
.pageMargin({ top: 1000, left: 2000 }) .pageMargin({ top: 1000, left: 2000 })
.build(); .build();
writeFileSync("aa.docx", buf); const z = new Zip(Buffer.from(buf));
for (const e of z.getEntries()) {
if (e.entryName.match(/document.xml|numbering.xml/)) {
expect(z.readAsText(e)).toMatchSnapshot();
}
}
});
test("should write default font", () => {
const p = new w.Paragraph().addRun(new w.Run().addText("Hello world!!!!"));
const fonts = new w.RunFonts()
.eastAsia("Arial")
.ascii("Arial")
.hiAnsi("Arial");
const buf = new w.Docx()
.addParagraph(p)
.defaultSize(40)
.defaultFonts(fonts)
.build();
writeFileSync("default_font.docx", buf);
const z = new Zip(Buffer.from(buf)); const z = new Zip(Buffer.from(buf));
for (const e of z.getEntries()) { for (const e of z.getEntries()) {
if (e.entryName.match(/document.xml|numbering.xml/)) { if (e.entryName.match(/document.xml|numbering.xml/)) {