Compare commits

...

13 Commits

Author SHA1 Message Date
Wynd f5fda75a96 Small fix so it doesn't crash on my very specific case 2025-06-12 14:18:40 +03:00
Myriad-Dreamin 52af4afeec
feat(deps): update rust crate base64 to v0.22.1 (#817)
* feat(deps): update rust crate base64 to v0.22.1

* fix: update cargo.lcok
2025-06-09 19:13:51 +09:00
shenhunluo 50e6eddb08
add font stretch (#813)
Co-authored-by: 张德新 <zhangdexin@sinosoft.com.cn>
2025-05-02 21:32:58 +09:00
bokuweb d95137cb9f
Revert "Change Style RunProperty internal structs val to public (#814)" (#818)
This reverts commit fbe87945e0.
2025-05-02 21:32:26 +09:00
Carlos M. fbe87945e0
Change Style RunProperty internal structs val to public (#814) 2025-05-02 21:28:08 +09:00
bokuweb 077de5d561
Add titlepg (#816)
* feat: add title_pg

* chore: rc46

* fix: add title_pg

* fix: add title pg

* rc47

* rc48
2025-05-02 09:07:47 +09:00
bokuweb 4728e080a4
0.4.18-rc45 (#815) 2025-04-30 17:36:24 +09:00
bokuweb 6c1d6e89b2
fix: disable bool el (#811) 2025-03-31 17:35:53 +09:00
bokuweb a4c38a7b0e
feat: add shd for run (#810) 2025-03-12 15:31:09 +09:00
bokuweb 31c109aacb
Merge pull request #809 from bokuweb/support-dstrike-reader
feat: Support dstrike reader
2025-03-11 13:16:57 +09:00
bokuweb ab837bcba4 fix: 2025-03-11 13:10:42 +09:00
bokuweb 9fbc75d6b2 fix: test 2025-03-11 13:09:22 +09:00
bokuweb 0f65b00436 feat: Support dstrike reader 2025-03-11 13:02:55 +09:00
35 changed files with 3676 additions and 19 deletions

View File

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support `dstrike` - Support `dstrike`
- Update Add after for default toc styles #806 - Update Add after for default toc styles #806
- Update `Level` styles. - Update `Level` styles.
- Support `titlePg`
--> -->
## @0.4.17 (26. Apr, 2024) ## @0.4.17 (26. Apr, 2024)

4
Cargo.lock generated
View File

@ -28,9 +28,9 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.13.1" version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]] [[package]]
name = "bitflags" name = "bitflags"

View File

@ -29,7 +29,7 @@ thiserror = "1.0"
zip = { version = "0.6.3", default-features = false, features = ["deflate"] } zip = { version = "0.6.3", default-features = false, features = ["deflate"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = {version = "1.0" } serde_json = {version = "1.0" }
base64 = "0.13.1" base64 = "0.22.1"
image = { version = "0.24.4", default-features = false, features=["gif", "jpeg", "png", "bmp", "tiff"], optional = true } image = { version = "0.24.4", default-features = false, features=["gif", "jpeg", "png", "bmp", "tiff"], optional = true }
wasm-bindgen = { version = "0.2.78", optional = true } wasm-bindgen = { version = "0.2.78", optional = true }
ts-rs = { version = "6.1", optional = true } ts-rs = { version = "6.1", optional = true }

View File

@ -140,6 +140,11 @@ impl Document {
self self
} }
pub fn title_pg(mut self) -> Self {
self.section_property = self.section_property.title_pg();
self
}
pub fn page_size(mut self, size: PageSize) -> Self { pub fn page_size(mut self, size: PageSize) -> Self {
self.section_property = self.section_property.page_size(size); self.section_property = self.section_property.page_size(size);
self self

View File

@ -40,6 +40,10 @@ impl BuildXML for Bold {
&self, &self,
stream: xml::writer::EventWriter<W>, stream: xml::writer::EventWriter<W>,
) -> xml::writer::Result<xml::writer::EventWriter<W>> { ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
XMLBuilder::from(stream).b()?.into_inner() if self.val {
XMLBuilder::from(stream).b()?.into_inner()
} else {
XMLBuilder::from(stream).disable_bold()?.into_inner()
}
} }
} }

View File

@ -40,6 +40,10 @@ impl BuildXML for Dstrike {
&self, &self,
stream: xml::writer::EventWriter<W>, stream: xml::writer::EventWriter<W>,
) -> xml::writer::Result<xml::writer::EventWriter<W>> { ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
XMLBuilder::from(stream).dstrike()?.into_inner() if self.val {
XMLBuilder::from(stream).dstrike()?.into_inner()
} else {
XMLBuilder::from(stream).disable_dstrike()?.into_inner()
}
} }
} }

View File

@ -40,6 +40,10 @@ impl BuildXML for Italic {
&self, &self,
stream: xml::writer::EventWriter<W>, stream: xml::writer::EventWriter<W>,
) -> xml::writer::Result<xml::writer::EventWriter<W>> { ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
XMLBuilder::from(stream).i()?.into_inner() if self.val {
XMLBuilder::from(stream).i()?.into_inner()
} else {
XMLBuilder::from(stream).disable_italic()?.into_inner()
}
} }
} }

View File

@ -94,6 +94,7 @@ mod shading;
mod shape; mod shape;
mod spec_vanish; mod spec_vanish;
mod start; mod start;
mod stretch;
mod strike; mod strike;
mod structured_data_tag; mod structured_data_tag;
mod structured_data_tag_property; mod structured_data_tag_property;
@ -232,6 +233,7 @@ pub use shading::*;
pub use shape::*; pub use shape::*;
pub use spec_vanish::*; pub use spec_vanish::*;
pub use start::*; pub use start::*;
pub use stretch::*;
pub use strike::*; pub use strike::*;
pub use structured_data_tag::*; pub use structured_data_tag::*;
pub use structured_data_tag_property::*; pub use structured_data_tag_property::*;

View File

@ -263,6 +263,11 @@ impl Run {
self self
} }
pub fn stretch(mut self, v: i32) -> Run {
self.run_property = self.run_property.stretch(v);
self
}
pub fn color(mut self, color: impl Into<String>) -> Run { pub fn color(mut self, color: impl Into<String>) -> Run {
self.run_property = self.run_property.color(color); self.run_property = self.run_property.color(color);
self self

View File

@ -40,6 +40,8 @@ pub struct RunProperty {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub character_spacing: Option<CharacterSpacing>, pub character_spacing: Option<CharacterSpacing>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub stretch: Option<Stretch>,
#[serde(skip_serializing_if = "Option::is_none")]
pub fonts: Option<RunFonts>, pub fonts: Option<RunFonts>,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub text_border: Option<TextBorder>, pub text_border: Option<TextBorder>,
@ -169,6 +171,11 @@ impl RunProperty {
self self
} }
pub fn stretch(mut self, v: i32) -> RunProperty {
self.stretch = Some(Stretch::new(v));
self
}
pub fn text_border(mut self, b: TextBorder) -> Self { pub fn text_border(mut self, b: TextBorder) -> Self {
self.text_border = Some(b); self.text_border = Some(b);
self self
@ -222,6 +229,7 @@ impl BuildXML for RunProperty {
.add_optional_child(&self.del)? .add_optional_child(&self.del)?
.add_optional_child(&self.vert_align)? .add_optional_child(&self.vert_align)?
.add_optional_child(&self.character_spacing)? .add_optional_child(&self.character_spacing)?
.add_optional_child(&self.stretch)?
.add_optional_child(&self.style)? .add_optional_child(&self.style)?
.add_optional_child(&self.positional_tab)? .add_optional_child(&self.positional_tab)?
.add_optional_child(&self.shading)? .add_optional_child(&self.shading)?
@ -318,6 +326,16 @@ mod tests {
); );
} }
#[test]
fn test_stretch() {
let c = RunProperty::new().stretch(80);
let b = c.build();
assert_eq!(
str::from_utf8(&b).unwrap(),
r#"<w:rPr><w:w w:val="80" /></w:rPr>"#
);
}
#[test] #[test]
fn test_ptab() { fn test_ptab() {
let c = RunProperty::new().ptab(PositionalTab::new( let c = RunProperty::new().ptab(PositionalTab::new(

View File

@ -0,0 +1,55 @@
use crate::documents::BuildXML;
use crate::xml_builder::*;
use std::io::Write;
use serde::*;
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct Stretch {
value: i32,
}
impl Stretch {
pub fn new(s: i32) -> Stretch {
Self { value: s }
}
}
impl BuildXML for Stretch {
fn build_to<W: Write>(
&self,
stream: xml::writer::EventWriter<W>,
) -> xml::writer::Result<xml::writer::EventWriter<W>> {
XMLBuilder::from(stream).w(self.value)?.into_inner()
}
}
impl Serialize for Stretch {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_i32(self.value)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(test)]
use pretty_assertions::assert_eq;
use std::str;
#[test]
fn test_stretch() {
let b = Stretch::new(200).build();
assert_eq!(str::from_utf8(&b).unwrap(), r#"<w:w w:val="200" />"#);
}
#[test]
fn test_stretch_json() {
let s = Stretch { value: 100 };
assert_eq!(serde_json::to_string(&s).unwrap(), r#"100"#);
}
}

View File

@ -40,6 +40,10 @@ impl BuildXML for Strike {
&self, &self,
stream: xml::writer::EventWriter<W>, stream: xml::writer::EventWriter<W>,
) -> xml::writer::Result<xml::writer::EventWriter<W>> { ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
XMLBuilder::from(stream).strike()?.into_inner() if self.val {
XMLBuilder::from(stream).strike()?.into_inner()
} else {
XMLBuilder::from(stream).disable_strike()?.into_inner()
}
} }
} }

View File

@ -78,6 +78,7 @@ pub use web_settings::*;
pub use webextension::*; pub use webextension::*;
pub use xml_docx::*; pub use xml_docx::*;
use base64::Engine;
use serde::{ser, Serialize}; use serde::{ser, Serialize};
use self::image_collector::{collect_images_from_paragraph, collect_images_from_table}; use self::image_collector::{collect_images_from_paragraph, collect_images_from_table};
@ -96,7 +97,7 @@ impl ser::Serialize for Image {
where where
S: ser::Serializer, S: ser::Serializer,
{ {
let base64 = base64::display::Base64Display::with_config(&self.0, base64::STANDARD); let base64 = base64::engine::general_purpose::STANDARD.encode(&self.0);
serializer.collect_str(&base64) serializer.collect_str(&base64)
} }
} }
@ -106,7 +107,7 @@ impl ser::Serialize for Png {
where where
S: ser::Serializer, S: ser::Serializer,
{ {
let base64 = base64::display::Base64Display::with_config(&self.0, base64::STANDARD); let base64 = base64::engine::general_purpose::STANDARD.encode(&self.0);
serializer.collect_str(&base64) serializer.collect_str(&base64)
} }
} }
@ -457,6 +458,11 @@ impl Docx {
self self
} }
pub fn title_pg(mut self) -> Self {
self.document = self.document.title_pg();
self
}
pub fn page_size(mut self, w: u32, h: u32) -> Self { pub fn page_size(mut self, w: u32, h: u32) -> Self {
self.document = self.document.page_size(PageSize::new().size(w, h)); self.document = self.document.page_size(PageSize::new().size(w, h));
self self

View File

@ -67,7 +67,9 @@ impl ElementReader for Level {
is_lgl = Some(IsLgl::new()); is_lgl = Some(IsLgl::new());
} }
XMLElement::LevelText => { XMLElement::LevelText => {
level_text = LevelText::new(attributes[0].value.clone()); if !attributes.is_empty() {
level_text = LevelText::new(attributes[0].value.clone());
}
} }
XMLElement::LevelRestart => { XMLElement::LevelRestart => {
if let Ok(v) = u32::from_str(&attributes[0].value) { if let Ok(v) = u32::from_str(&attributes[0].value) {

View File

@ -418,6 +418,7 @@ pub fn read_docx(buf: &[u8]) -> Result<Docx, ReaderError> {
)?; )?;
let nums = Numberings::from_xml(&data[..])?; let nums = Numberings::from_xml(&data[..])?;
docx = docx.numberings(nums); docx = docx.numberings(nums);
docx.document_rels.has_numberings = true;
} }
} }

View File

@ -92,6 +92,13 @@ impl ElementReader for RunProperty {
} }
rp = rp.strike(); rp = rp.strike();
} }
XMLElement::Dstrike => {
if !read_bool(&attributes) {
rp.dstrike = Some(Dstrike::new().disable());
continue;
}
rp = rp.dstrike();
}
XMLElement::VertAlign => { XMLElement::VertAlign => {
if let Ok(v) = VertAlignType::from_str(&attributes[0].value) { if let Ok(v) = VertAlignType::from_str(&attributes[0].value) {
rp = rp.vert_align(v) rp = rp.vert_align(v)
@ -121,6 +128,11 @@ impl ElementReader for RunProperty {
} }
rp = rp.italic(); rp = rp.italic();
} }
XMLElement::Shading => {
if let Ok(shd) = Shading::read(r, &attributes) {
rp = rp.shading(shd);
}
}
XMLElement::Vanish => rp = rp.vanish(), XMLElement::Vanish => rp = rp.vanish(),
XMLElement::SpecVanish => rp = rp.spec_vanish(), XMLElement::SpecVanish => rp = rp.spec_vanish(),
XMLElement::TextBorder => { XMLElement::TextBorder => {

View File

@ -183,14 +183,39 @@ impl<W: Write> XMLBuilder<W> {
closed!(b, "w:b"); closed!(b, "w:b");
closed!(b_cs, "w:bCs"); closed!(b_cs, "w:bCs");
pub(crate) fn disable_bold(self) -> Result<Self> {
let f = "false";
self.write(XmlEvent::start_element("w:b").attr("w:val", &f))?
.close()
}
closed_with_str!(caps, "w:caps"); closed_with_str!(caps, "w:caps");
closed!(i, "w:i"); closed!(i, "w:i");
closed!(i_cs, "w:iCs"); closed!(i_cs, "w:iCs");
pub(crate) fn disable_italic(self) -> Result<Self> {
let f = "false";
self.write(XmlEvent::start_element("w:i").attr("w:val", &f))?
.close()
}
closed!(strike, "w:strike"); closed!(strike, "w:strike");
pub(crate) fn disable_strike(self) -> Result<Self> {
let f = "false";
self.write(XmlEvent::start_element("w:strike").attr("w:val", &f))?
.close()
}
closed!(dstrike, "w:dstrike"); closed!(dstrike, "w:dstrike");
pub(crate) fn disable_dstrike(self) -> Result<Self> {
let f = "false";
self.write(XmlEvent::start_element("w:dstrike").attr("w:val", &f))?
.close()
}
// Build w:style element // Build w:style element
// i.e. <w:style ... > // i.e. <w:style ... >
pub(crate) fn open_style(self, style_type: StyleType, id: &str) -> Result<Self> { pub(crate) fn open_style(self, style_type: StyleType, id: &str) -> Result<Self> {
@ -253,6 +278,12 @@ impl<W: Write> XMLBuilder<W> {
.close() .close()
} }
// i.e. <w:w ... >
pub(crate) fn w(self, s: i32) -> Result<Self> {
self.write(XmlEvent::start_element("w:w").attr("w:val", &format!("{}", s)))?
.close()
}
// i.e. <w:spacing ... > // i.e. <w:spacing ... >
pub(crate) fn line_spacing( pub(crate) fn line_spacing(
self, self,
@ -471,7 +502,7 @@ impl<W: Write> XMLBuilder<W> {
closed!(keep_lines, "w:keepLines"); closed!(keep_lines, "w:keepLines");
closed!(page_break_before, "w:pageBreakBefore"); closed!(page_break_before, "w:pageBreakBefore");
closed!(widow_control, "w:widowControl", "w:val"); closed!(widow_control, "w:widowControl", "w:val");
closed!(bidi,"w:bidi"); closed!(bidi, "w:bidi");
/* /*
<w:lvlOverride w:ilvl="0"> <w:lvlOverride w:ilvl="0">
<w:startOverride w:val="1"/> <w:startOverride w:val="1"/>

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

@ -152,6 +152,11 @@ export class Docx {
return this; return this;
} }
titlePg() {
this.sectionProperty.titlePg();
return this;
}
pageSize(w: number, h: number) { pageSize(w: number, h: number) {
this.sectionProperty.pageSize(w, h); this.sectionProperty.pageSize(w, h);
return this; return this;
@ -549,6 +554,10 @@ export class Docx {
} }
} }
if (this.sectionProperty._titlePg) {
docx = docx.title_pg();
}
if (this.sectionProperty._pageTypeNum) { if (this.sectionProperty._pageTypeNum) {
const { start, chapStyle } = this.sectionProperty._pageTypeNum; const { start, chapStyle } = this.sectionProperty._pageTypeNum;
const p = wasm.createPageNumType(start, chapStyle); const p = wasm.createPageNumType(start, chapStyle);

View File

@ -5,6 +5,7 @@ import {
CommentRangeEndJSON, CommentRangeEndJSON,
InsertJSONData, InsertJSONData,
DeleteJSONData, DeleteJSONData,
ShadingJSON,
} from ".."; } from "..";
import { BorderType } from "../border"; import { BorderType } from "../border";
import { VertAlignType } from "../run-property"; import { VertAlignType } from "../run-property";
@ -56,6 +57,7 @@ export type RunPropertyJSON = {
del?: DeleteJSONData | null; del?: DeleteJSONData | null;
strike?: boolean; strike?: boolean;
dstrike?: boolean; dstrike?: boolean;
shading?: ShadingJSON | null;
}; };
export type RunChildJSON = export type RunChildJSON =

View File

@ -1,6 +1,7 @@
import * as wasm from "./pkg/docx_wasm"; import * as wasm from "./pkg/docx_wasm";
import { BorderType } from "./border"; import { BorderType } from "./border";
import { Shading } from "./shading";
export type TextBorder = { export type TextBorder = {
borderType: BorderType; borderType: BorderType;
@ -38,6 +39,7 @@ export class RunProperty {
_textBorder?: TextBorder; _textBorder?: TextBorder;
_ins?: RunPropertyIns; _ins?: RunPropertyIns;
_del?: RunPropertyDel; _del?: RunPropertyDel;
_shading?: Shading;
style(style: string) { style(style: string) {
this._style = style; this._style = style;
@ -143,6 +145,15 @@ export class RunProperty {
}; };
return this; return this;
} }
shading(type: string, color: string, fill: string) {
const s = new Shading();
s.color(color);
s.fill(fill);
s.type(type);
this._shading = s;
return this;
}
} }
export const convertBorderType = (t: BorderType) => { export const convertBorderType = (t: BorderType) => {
@ -340,6 +351,14 @@ export const setRunProperty = <T extends wasm.Run | wasm.Style>(
target = target.fonts(fonts) as T; target = target.fonts(fonts) as T;
} }
if (property._shading != null) {
target = target.shading(
property._shading._type,
property._shading._color,
property._shading._fill
) as T;
}
return target; return target;
}; };
@ -429,5 +448,13 @@ export const createRunProperty = (property: RunProperty): wasm.RunProperty => {
target = target.fonts(fonts); target = target.fonts(fonts);
} }
if (property._shading != null) {
target = target.shading(
property._shading._type,
property._shading._color,
property._shading._fill
);
}
return target; return target;
}; };

View File

@ -160,6 +160,12 @@ export class Run {
return this; return this;
} }
shading(type: string, color: string, fill: string) {
this.property ??= createDefaultRunProperty();
this.property.shading(type, color, fill);
return this;
}
build() { build() {
let run = wasm.createRun(); let run = wasm.createRun();
this.children.forEach((child) => { this.children.forEach((child) => {

View File

@ -14,6 +14,7 @@ export class SectionProperty {
w: 11906, w: 11906,
h: 16838, h: 16838,
}; };
_titlePg: boolean | null = null;
_pageMargin: PageMargin | null = null; _pageMargin: PageMargin | null = null;
_docGrid: DocGrid | null = null; _docGrid: DocGrid | null = null;
_header: Header | null = null; _header: Header | null = null;
@ -24,6 +25,11 @@ export class SectionProperty {
_evenFooter: Footer | null = null; _evenFooter: Footer | null = null;
_pageTypeNum: PageNumType | null = null; _pageTypeNum: PageNumType | null = null;
titlePg() {
this._titlePg = true;
return this;
}
pageSize(w: number, h: number) { pageSize(w: number, h: number) {
this._pageSize.w = w; this._pageSize.w = w;
this._pageSize.h = h; this._pageSize.h = h;

View File

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

View File

@ -123,6 +123,11 @@ impl Docx {
self self
} }
pub fn title_pg(mut self) -> Docx {
self.0 = self.0.title_pg();
self
}
pub fn page_size(mut self, w: u32, h: u32) -> Docx { pub fn page_size(mut self, w: u32, h: u32) -> Docx {
self.0 = self.0.page_size(w, h); self.0 = self.0.page_size(w, h);
self self

View File

@ -1,5 +1,6 @@
use super::*; use super::*;
use docx_rs::{BorderType, TextBorder, VertAlignType}; use docx_rs::{BorderType, Shading, TextBorder, VertAlignType};
use std::str::FromStr;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen] #[wasm_bindgen]
@ -137,6 +138,15 @@ impl Run {
self self
} }
pub fn shading(mut self, t: &str, color: &str, fill: &str) -> Self {
let mut s = Shading::new().color(color).fill(fill);
if let Ok(t) = docx_rs::ShdType::from_str(t) {
s = s.shd_type(t);
}
self.0.run_property = self.0.run_property.shading(s);
self
}
pub fn text_border( pub fn text_border(
mut self, mut self,
border_type: BorderType, border_type: BorderType,

View File

@ -1,5 +1,7 @@
use super::*; use super::*;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
use std::str::FromStr;
#[wasm_bindgen] #[wasm_bindgen]
pub struct RunProperty(docx_rs::RunProperty); pub struct RunProperty(docx_rs::RunProperty);
@ -130,6 +132,15 @@ impl RunProperty {
self.0 = self.0.text_border(border); self.0 = self.0.text_border(border);
self self
} }
pub fn shading(mut self, t: &str, color: &str, fill: &str) -> Self {
let mut s = docx_rs::Shading::new().color(color).fill(fill);
if let Ok(t) = docx_rs::ShdType::from_str(t) {
s = s.shd_type(t);
}
self.0 = self.0.shading(s);
self
}
} }
impl RunProperty { impl RunProperty {

View File

@ -1,5 +1,6 @@
use super::*; use super::*;
use docx_rs::{BorderType, TextBorder, VertAlignType, WidthType}; use docx_rs::{BorderType, Shading, TextBorder, VertAlignType, WidthType};
use std::str::FromStr;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen] #[wasm_bindgen]
@ -63,6 +64,15 @@ impl Style {
self self
} }
pub fn shading(mut self, t: &str, color: &str, fill: &str) -> Self {
let mut s = Shading::new().color(color).fill(fill);
if let Ok(t) = docx_rs::ShdType::from_str(t) {
s = s.shd_type(t);
}
self.0.run_property = self.0.run_property.shading(s);
self
}
pub fn link(mut self, link: &str) -> Self { pub fn link(mut self, link: &str) -> Self {
self.0 = self.0.link(link); self.0 = self.0.link(link);
self self

File diff suppressed because it is too large Load Diff

View File

@ -220,6 +220,12 @@ describe("reader", () => {
const json = w.readDocx(buffer); const json = w.readDocx(buffer);
expect(json).toMatchSnapshot(); expect(json).toMatchSnapshot();
}); });
test("should read dstrike", () => {
const buffer = readFileSync("../fixtures/dstrike/dstrike.docx");
const json = w.readDocx(buffer);
expect(json).toMatchSnapshot();
});
}); });
describe("writer", () => { describe("writer", () => {
@ -464,6 +470,20 @@ describe("writer", () => {
} }
}); });
test("should write shd", () => {
const p = new w.Paragraph()
.addRun(new w.Run().addText("Hello "))
.addRun(new w.Run().addText("World!").shading("clear", "auto", "FFC000"));
const buffer = new w.Docx().addParagraph(p).build();
writeFileSync("../output/js/shading.docx", buffer);
const z = new Zip(Buffer.from(buffer));
for (const e of z.getEntries()) {
if (e.entryName.match(/document.xml|numbering.xml/)) {
expect(z.readAsText(e)).toMatchSnapshot();
}
}
});
test("should write page orientation", () => { test("should write page orientation", () => {
const p = new w.Paragraph().addRun(new w.Run().addText("Hello ")); const p = new w.Paragraph().addRun(new w.Run().addText("Hello "));
const buffer = new w.Docx() const buffer = new w.Docx()

Binary file not shown.

View File

@ -1 +1 @@
1.73 1.85