Skip to content

Commit

Permalink
feat: Support w:textAlignment (#690)
Browse files Browse the repository at this point in the history
  • Loading branch information
bokuweb authored Mar 18, 2024
1 parent 6955cd0 commit 13b8d9b
Show file tree
Hide file tree
Showing 14 changed files with 171 additions and 2 deletions.
2 changes: 2 additions & 0 deletions docx-core/src/documents/elements/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ mod table_style;
mod table_width;
mod tabs;
mod text;
mod text_alignment;
mod text_border;
mod text_box;
mod text_box_content;
Expand Down Expand Up @@ -240,6 +241,7 @@ pub use table_style::*;
pub use table_width::*;
pub use tabs::*;
pub use text::*;
pub use text_alignment::*;
pub use text_border::*;
pub use text_box::*;
pub use text_box_content::*;
Expand Down
12 changes: 10 additions & 2 deletions docx-core/src/documents/elements/paragraph_property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use serde::Serialize;
use super::*;
use crate::documents::BuildXML;
use crate::types::{AlignmentType, SpecialIndentType};
use crate::xml_builder::*;
use crate::ParagraphBorderPosition;
use crate::{xml_builder::*, TextAlignmentType};

#[derive(Serialize, Debug, Clone, PartialEq, Default)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -42,6 +42,8 @@ pub struct ParagraphProperty {
pub borders: Option<ParagraphBorders>,
#[serde(skip_serializing_if = "Option::is_none")]
pub frame_property: Option<FrameProperty>,
#[serde(skip_serializing_if = "Option::is_none")]
pub text_alignment: Option<TextAlignment>,
}

// 17.3.1.26
Expand Down Expand Up @@ -145,6 +147,11 @@ impl ParagraphProperty {
self
}

pub fn text_alignment(mut self, s: TextAlignmentType) -> Self {
self.text_alignment = Some(TextAlignment::new(s));
self
}

pub(crate) fn hanging_chars(mut self, chars: i32) -> Self {
if let Some(indent) = self.indent {
self.indent = Some(indent.hanging_chars(chars));
Expand Down Expand Up @@ -192,7 +199,8 @@ fn inner_build(p: &ParagraphProperty) -> Vec<u8> {
.add_optional_child(&p.line_spacing)
.add_optional_child(&p.outline_lvl)
.add_optional_child(&p.paragraph_property_change)
.add_optional_child(&p.borders);
.add_optional_child(&p.borders)
.add_optional_child(&p.text_alignment);

if let Some(v) = p.keep_next {
if v {
Expand Down
5 changes: 5 additions & 0 deletions docx-core/src/documents/elements/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ impl Style {
self
}

pub fn text_alignment(mut self, alignment_type: TextAlignmentType) -> Self {
self.paragraph_property = self.paragraph_property.text_alignment(alignment_type);
self
}

pub fn indent(
mut self,
left: Option<i32>,
Expand Down
31 changes: 31 additions & 0 deletions docx-core/src/documents/elements/text_alignment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use serde::{Serialize, Serializer};

use crate::documents::BuildXML;
use crate::{xml_builder::*, TextAlignmentType};

#[derive(Debug, Clone, PartialEq)]
pub struct TextAlignment(pub TextAlignmentType);

impl TextAlignment {
pub fn new(val: TextAlignmentType) -> TextAlignment {
TextAlignment(val)
}
}

impl BuildXML for TextAlignment {
fn build(&self) -> Vec<u8> {
let b = XMLBuilder::new();
let v = format!("{}", self.0);
b.text_alignment(&v).build()
}
}

impl Serialize for TextAlignment {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let v = format!("{}", self.0);
serializer.serialize_str(&v)
}
}
6 changes: 6 additions & 0 deletions docx-core/src/reader/paragraph_property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ impl ElementReader for ParagraphProperty {
}
continue;
}
XMLElement::TextAlignment => {
if let Ok(v) = TextAlignmentType::from_str(&attributes[0].value) {
p = p.text_alignment(v);
}
continue;
}
XMLElement::ParagraphStyle => {
p = p.style(&attributes[0].value);
continue;
Expand Down
2 changes: 2 additions & 0 deletions docx-core/src/reader/xml_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ pub enum XMLElement {
Type,
PageNumType,
FrameProperty,
TextAlignment,
H,
HAnchor,
HSpace,
Expand Down Expand Up @@ -405,6 +406,7 @@ impl FromStr for XMLElement {
"sdt" => Ok(XMLElement::StructuredDataTag),
"pgNumType" => Ok(XMLElement::PageNumType),
"framePr" => Ok(XMLElement::FrameProperty),
"textAlignment" => Ok(XMLElement::TextAlignment),
"h" => Ok(XMLElement::H),
"hAnchor" => Ok(XMLElement::HAnchor),
"hSpace" => Ok(XMLElement::HSpace),
Expand Down
2 changes: 2 additions & 0 deletions docx-core/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub mod tab_leader_type;
pub mod tab_value_type;
pub mod table_alignment_type;
pub mod table_layout_type;
pub mod text_alignment_type;
pub mod text_direction_type;
pub mod vert_align_type;
pub mod vertical_align_type;
Expand Down Expand Up @@ -56,6 +57,7 @@ pub use tab_leader_type::*;
pub use tab_value_type::*;
pub use table_alignment_type::*;
pub use table_layout_type::*;
pub use text_alignment_type::*;
pub use text_direction_type::*;
pub use vert_align_type::*;
pub use vertical_align_type::*;
Expand Down
45 changes: 45 additions & 0 deletions docx-core/src/types/text_alignment_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use std::fmt;
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;

use serde::Serialize;

use super::errors;
use std::str::FromStr;

#[cfg_attr(feature = "wasm", wasm_bindgen, derive(ts_rs::TS), ts(export))]
#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum TextAlignmentType {
Auto,
Baseline,
Bottom,
Center,
Top,
}

impl fmt::Display for TextAlignmentType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
TextAlignmentType::Auto => write!(f, "auto"),
TextAlignmentType::Baseline => write!(f, "baseline"),
TextAlignmentType::Bottom => write!(f, "bottom"),
TextAlignmentType::Center => write!(f, "center"),
TextAlignmentType::Top => write!(f, "top"),
}
}
}

impl FromStr for TextAlignmentType {
type Err = errors::TypeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"auto" => Ok(TextAlignmentType::Auto),
"baseline" => Ok(TextAlignmentType::Baseline),
"bottom" => Ok(TextAlignmentType::Bottom),
"center" => Ok(TextAlignmentType::Center),
"top" => Ok(TextAlignmentType::Top),
_ => Err(errors::TypeError::FromStrError),
}
}
}
2 changes: 2 additions & 0 deletions docx-core/src/xml_builder/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ impl XMLBuilder {
// i.e. <w:szCs ... >
closed_with_usize!(sz_cs, "w:szCs");

closed_with_str!(text_alignment, "w:textAlignment");

closed!(field_character, "w:fldChar", "w:fldCharType", "w:dirty");

open!(open_instr_text, "w:instrText");
Expand Down
2 changes: 2 additions & 0 deletions docx-wasm/js/json/bindings/TextAlignmentType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

export type TextAlignmentType = "auto" | "baseline" | "bottom" | "center" | "top";
37 changes: 37 additions & 0 deletions docx-wasm/js/paragraph-property.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { RunProperty, createDefaultRunProperty } from "./run";

import * as wasm from "./pkg";
import { TextAlignmentType } from "./json/bindings/TextAlignmentType";

export type AlignmentType =
| "center"
Expand Down Expand Up @@ -51,6 +52,7 @@ export class LineSpacing {

export type ParagraphProperty = {
align?: AlignmentType;
textAlignment?: TextAlignmentType;
styleId?: string;
indent?: {
left: number;
Expand Down Expand Up @@ -113,6 +115,31 @@ export const createParagraphAlignment = (
}
};

export const createParagraphTextAlignment = (
align?: TextAlignmentType | undefined
): wasm.TextAlignmentType | null => {
switch (align) {
case "auto": {
return wasm.TextAlignmentType.Auto;
}
case "baseline": {
return wasm.TextAlignmentType.Baseline;
}
case "bottom": {
return wasm.TextAlignmentType.Bottom;
}
case "center": {
return wasm.TextAlignmentType.Center;
}
case "top": {
return wasm.TextAlignmentType.Top;
}
default: {
return null;
}
}
};

export class ParagraphPropertyChange {
_author: string = "";
_date: string = "";
Expand All @@ -133,6 +160,11 @@ export class ParagraphPropertyChange {
return this;
}

textAlignment(type: TextAlignmentType) {
this._property.textAlignment = type;
return this;
}

style(id: string) {
this._property.styleId = id;
return this;
Expand Down Expand Up @@ -209,6 +241,11 @@ export const setParagraphProperty = <T extends wasm.Paragraph | wasm.Style>(
target = target.align(alignment) as T;
}

const textAlignment = createParagraphTextAlignment(property.textAlignment);
if (textAlignment != null) {
target = target.text_alignment(textAlignment) as T;
}

if (typeof property.indent !== "undefined") {
const { indent } = property;
let kind;
Expand Down
5 changes: 5 additions & 0 deletions docx-wasm/src/paragraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ impl Paragraph {
self
}

pub fn text_alignment(mut self, alignment_type: docx_rs::TextAlignmentType) -> Paragraph {
self.0.property = self.0.property.text_alignment(alignment_type);
self
}

pub fn outline_lvl(mut self, level: usize) -> Paragraph {
self.0.property = self.0.property.outline_lvl(level);
self
Expand Down
5 changes: 5 additions & 0 deletions docx-wasm/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ impl Style {
self
}

pub fn text_alignment(mut self, alignment_type: docx_rs::TextAlignmentType) -> Self {
self.0.paragraph_property = self.0.paragraph_property.text_alignment(alignment_type);
self
}

pub fn indent(
mut self,
left: i32,
Expand Down
Loading

0 comments on commit 13b8d9b

Please sign in to comment.