Support ptab in r (#756)
* feat: add ptab * feat: wasm object * fix: suppoert ptab * spec: add read test for ptab * rc10 * rc11 * rc12main
parent
19b174da7c
commit
60d94921b0
|
@ -7,12 +7,23 @@ use crate::xml_builder::*;
|
||||||
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]
|
||||||
#[cfg_attr(feature = "wasm", derive(ts_rs::TS))]
|
#[cfg_attr(feature = "wasm", derive(ts_rs::TS))]
|
||||||
#[cfg_attr(feature = "wasm", ts(export))]
|
#[cfg_attr(feature = "wasm", ts(export))]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PositionalTab {
|
pub struct PositionalTab {
|
||||||
pub alignment: PositionalTabAlignmentType,
|
pub alignment: PositionalTabAlignmentType,
|
||||||
pub relative_to: PositionalTabRelativeTo,
|
pub relative_to: PositionalTabRelativeTo,
|
||||||
pub leader: TabLeaderType,
|
pub leader: TabLeaderType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for PositionalTab {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
alignment: PositionalTabAlignmentType::Left,
|
||||||
|
relative_to: PositionalTabRelativeTo::Margin,
|
||||||
|
leader: TabLeaderType::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PositionalTab {
|
impl PositionalTab {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
alignment: PositionalTabAlignmentType,
|
alignment: PositionalTabAlignmentType,
|
||||||
|
|
|
@ -29,6 +29,7 @@ pub enum RunChild {
|
||||||
Sym(Sym),
|
Sym(Sym),
|
||||||
DeleteText(DeleteText),
|
DeleteText(DeleteText),
|
||||||
Tab(Tab),
|
Tab(Tab),
|
||||||
|
PTab(PositionalTab),
|
||||||
Break(Break),
|
Break(Break),
|
||||||
Drawing(Box<Drawing>),
|
Drawing(Box<Drawing>),
|
||||||
Shape(Box<Shape>),
|
Shape(Box<Shape>),
|
||||||
|
@ -72,6 +73,12 @@ impl Serialize for RunChild {
|
||||||
t.serialize_field("type", "tab")?;
|
t.serialize_field("type", "tab")?;
|
||||||
t.end()
|
t.end()
|
||||||
}
|
}
|
||||||
|
RunChild::PTab(ref s) => {
|
||||||
|
let mut t = serializer.serialize_struct("PTab", 1)?;
|
||||||
|
t.serialize_field("type", "ptab")?;
|
||||||
|
t.serialize_field("data", s)?;
|
||||||
|
t.end()
|
||||||
|
}
|
||||||
RunChild::Break(ref s) => {
|
RunChild::Break(ref s) => {
|
||||||
let mut t = serializer.serialize_struct("Break", 2)?;
|
let mut t = serializer.serialize_struct("Break", 2)?;
|
||||||
t.serialize_field("type", "break")?;
|
t.serialize_field("type", "break")?;
|
||||||
|
@ -201,6 +208,11 @@ impl Run {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_ptab(mut self, ptab: PositionalTab) -> Run {
|
||||||
|
self.children.push(RunChild::PTab(ptab));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_image(mut self, pic: Pic) -> Run {
|
pub fn add_image(mut self, pic: Pic) -> Run {
|
||||||
self.children
|
self.children
|
||||||
.push(RunChild::Drawing(Box::new(Drawing::new().pic(pic))));
|
.push(RunChild::Drawing(Box::new(Drawing::new().pic(pic))));
|
||||||
|
@ -326,6 +338,7 @@ impl BuildXML for Run {
|
||||||
RunChild::Sym(t) => b = b.add_child(t),
|
RunChild::Sym(t) => b = b.add_child(t),
|
||||||
RunChild::DeleteText(t) => b = b.add_child(t),
|
RunChild::DeleteText(t) => b = b.add_child(t),
|
||||||
RunChild::Tab(t) => b = b.add_child(t),
|
RunChild::Tab(t) => b = b.add_child(t),
|
||||||
|
RunChild::PTab(t) => b = b.add_child(t),
|
||||||
RunChild::Break(t) => b = b.add_child(t),
|
RunChild::Break(t) => b = b.add_child(t),
|
||||||
RunChild::Drawing(t) => b = b.add_child(t),
|
RunChild::Drawing(t) => b = b.add_child(t),
|
||||||
RunChild::Shape(_t) => {
|
RunChild::Shape(_t) => {
|
||||||
|
|
|
@ -37,6 +37,7 @@ mod paragraph;
|
||||||
mod paragraph_property;
|
mod paragraph_property;
|
||||||
mod paragraph_property_change;
|
mod paragraph_property_change;
|
||||||
mod pic;
|
mod pic;
|
||||||
|
mod positional_tab;
|
||||||
mod read_zip;
|
mod read_zip;
|
||||||
mod rels;
|
mod rels;
|
||||||
mod run;
|
mod run;
|
||||||
|
@ -55,8 +56,8 @@ mod table_cell;
|
||||||
mod table_cell_borders;
|
mod table_cell_borders;
|
||||||
mod table_cell_margins;
|
mod table_cell_margins;
|
||||||
mod table_cell_property;
|
mod table_cell_property;
|
||||||
mod table_property;
|
|
||||||
mod table_position_property;
|
mod table_position_property;
|
||||||
|
mod table_property;
|
||||||
mod table_row;
|
mod table_row;
|
||||||
mod tabs;
|
mod tabs;
|
||||||
mod text_box_content;
|
mod text_box_content;
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
use std::io::Read;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use xml::attribute::OwnedAttribute;
|
||||||
|
use xml::reader::{EventReader, XmlEvent};
|
||||||
|
|
||||||
|
use crate::{PositionalTabAlignmentType, PositionalTabRelativeTo, TabLeaderType};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn read_leader(attributes: &[OwnedAttribute]) -> Result<TabLeaderType, ReaderError> {
|
||||||
|
for a in attributes {
|
||||||
|
let local_name = &a.name.local_name;
|
||||||
|
if local_name == "leader" {
|
||||||
|
let v = a.value.to_owned();
|
||||||
|
if let Ok(t) = TabLeaderType::from_str(&v) {
|
||||||
|
return Ok(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(ReaderError::TypeError(crate::TypeError::FromStrError))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_alignment(
|
||||||
|
attributes: &[OwnedAttribute],
|
||||||
|
) -> Result<PositionalTabAlignmentType, ReaderError> {
|
||||||
|
for a in attributes {
|
||||||
|
let local_name = &a.name.local_name;
|
||||||
|
if local_name == "alignment" {
|
||||||
|
let v = a.value.to_owned();
|
||||||
|
if let Ok(t) = PositionalTabAlignmentType::from_str(&v) {
|
||||||
|
return Ok(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(ReaderError::TypeError(crate::TypeError::FromStrError))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_relative_to(attributes: &[OwnedAttribute]) -> Result<PositionalTabRelativeTo, ReaderError> {
|
||||||
|
for a in attributes {
|
||||||
|
let local_name = &a.name.local_name;
|
||||||
|
if local_name == "alignment" {
|
||||||
|
let v = a.value.to_owned();
|
||||||
|
if let Ok(t) = PositionalTabRelativeTo::from_str(&v) {
|
||||||
|
return Ok(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(ReaderError::TypeError(crate::TypeError::FromStrError))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ElementReader for PositionalTab {
|
||||||
|
fn read<R: Read>(
|
||||||
|
r: &mut EventReader<R>,
|
||||||
|
attrs: &[OwnedAttribute],
|
||||||
|
) -> Result<Self, ReaderError> {
|
||||||
|
let mut tab = PositionalTab::default();
|
||||||
|
if let Ok(t) = read_alignment(attrs) {
|
||||||
|
tab = tab.alignment(t);
|
||||||
|
}
|
||||||
|
if let Ok(v) = read_relative_to(attrs) {
|
||||||
|
tab = tab.relative_to(v);
|
||||||
|
}
|
||||||
|
if let Ok(leader) = read_leader(attrs) {
|
||||||
|
tab = tab.leader(leader);
|
||||||
|
}
|
||||||
|
loop {
|
||||||
|
let e = r.next();
|
||||||
|
match e {
|
||||||
|
Ok(XmlEvent::EndElement { name, .. }) => {
|
||||||
|
let e = XMLElement::from_str(&name.local_name).unwrap();
|
||||||
|
if e == XMLElement::PTab {
|
||||||
|
return Ok(tab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => return Err(ReaderError::XMLReadError),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,6 +71,11 @@ impl ElementReader for Run {
|
||||||
XMLElement::Tab => {
|
XMLElement::Tab => {
|
||||||
run = run.add_tab();
|
run = run.add_tab();
|
||||||
}
|
}
|
||||||
|
XMLElement::PTab => {
|
||||||
|
if let Ok(v) = PositionalTab::read(r, &attributes) {
|
||||||
|
run = run.add_ptab(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
XMLElement::Sym => {
|
XMLElement::Sym => {
|
||||||
if let Some(font) = read(&attributes, "font") {
|
if let Some(font) = read(&attributes, "font") {
|
||||||
if let Some(char) = read(&attributes, "char") {
|
if let Some(char) = read(&attributes, "char") {
|
||||||
|
|
|
@ -79,6 +79,11 @@ impl ElementReader for RunProperty {
|
||||||
}
|
}
|
||||||
rp = rp.caps();
|
rp = rp.caps();
|
||||||
}
|
}
|
||||||
|
XMLElement::PTab => {
|
||||||
|
if let Ok(v) = PositionalTab::read(r, &attributes) {
|
||||||
|
rp = rp.ptab(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
XMLElement::Highlight => rp = rp.highlight(attributes[0].value.clone()),
|
XMLElement::Highlight => rp = rp.highlight(attributes[0].value.clone()),
|
||||||
XMLElement::Strike => {
|
XMLElement::Strike => {
|
||||||
if !read_bool(&attributes) {
|
if !read_bool(&attributes) {
|
||||||
|
|
|
@ -37,6 +37,7 @@ pub enum XMLElement {
|
||||||
Break,
|
Break,
|
||||||
Tab,
|
Tab,
|
||||||
Tabs,
|
Tabs,
|
||||||
|
PTab,
|
||||||
Sym,
|
Sym,
|
||||||
ParagraphStyle,
|
ParagraphStyle,
|
||||||
ParagraphPropertyChange,
|
ParagraphPropertyChange,
|
||||||
|
@ -289,6 +290,7 @@ impl FromStr for XMLElement {
|
||||||
"name" => Ok(XMLElement::Name),
|
"name" => Ok(XMLElement::Name),
|
||||||
"tab" => Ok(XMLElement::Tab),
|
"tab" => Ok(XMLElement::Tab),
|
||||||
"tabs" => Ok(XMLElement::Tabs),
|
"tabs" => Ok(XMLElement::Tabs),
|
||||||
|
"ptab" => Ok(XMLElement::PTab),
|
||||||
"br" => Ok(XMLElement::Break),
|
"br" => Ok(XMLElement::Break),
|
||||||
"ind" => Ok(XMLElement::Indent),
|
"ind" => Ok(XMLElement::Indent),
|
||||||
"numPr" => Ok(XMLElement::NumberingProperty),
|
"numPr" => Ok(XMLElement::NumberingProperty),
|
||||||
|
|
|
@ -11,6 +11,7 @@ use super::errors;
|
||||||
#[cfg_attr(feature = "wasm", derive(ts_rs::TS))]
|
#[cfg_attr(feature = "wasm", derive(ts_rs::TS))]
|
||||||
#[cfg_attr(feature = "wasm", ts(export))]
|
#[cfg_attr(feature = "wasm", ts(export))]
|
||||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub enum PositionalTabRelativeTo {
|
pub enum PositionalTabRelativeTo {
|
||||||
Indent,
|
Indent,
|
||||||
Margin,
|
Margin,
|
||||||
|
|
|
@ -672,3 +672,4 @@ export * from "./page-num";
|
||||||
export * from "./num-pages";
|
export * from "./num-pages";
|
||||||
export * from "./footer";
|
export * from "./footer";
|
||||||
export * from "./image";
|
export * from "./image";
|
||||||
|
export * from "./positional-tab";
|
||||||
|
|
|
@ -2,4 +2,4 @@ import type { PositionalTabAlignmentType } from "./PositionalTabAlignmentType";
|
||||||
import type { PositionalTabRelativeTo } from "./PositionalTabRelativeTo";
|
import type { PositionalTabRelativeTo } from "./PositionalTabRelativeTo";
|
||||||
import type { TabLeaderType } from "./TabLeaderType";
|
import type { TabLeaderType } from "./TabLeaderType";
|
||||||
|
|
||||||
export interface PositionalTab { alignment: PositionalTabAlignmentType, relative_to: PositionalTabRelativeTo, leader: TabLeaderType, }
|
export interface PositionalTab { alignment: PositionalTabAlignmentType, relativeTo: PositionalTabRelativeTo, leader: TabLeaderType, }
|
|
@ -1,2 +1,2 @@
|
||||||
|
|
||||||
export type PositionalTabRelativeTo = "Indent" | "Margin";
|
export type PositionalTabRelativeTo = "indent" | "margin";
|
|
@ -11,6 +11,9 @@ import { VertAlignType } from "../run";
|
||||||
import { FieldChar } from "./bindings/FieldChar";
|
import { FieldChar } from "./bindings/FieldChar";
|
||||||
import { InstrHyperlink } from "./bindings/InstrHyperlink";
|
import { InstrHyperlink } from "./bindings/InstrHyperlink";
|
||||||
import { InstrToC } from "./bindings/InstrToC";
|
import { InstrToC } from "./bindings/InstrToC";
|
||||||
|
import { PositionalTabAlignmentType } from "./bindings/PositionalTabAlignmentType";
|
||||||
|
import { PositionalTabRelativeTo } from "./bindings/PositionalTabRelativeTo";
|
||||||
|
import { TabLeaderType } from "./bindings/TabLeaderType";
|
||||||
|
|
||||||
export type TextBorderJSON = {
|
export type TextBorderJSON = {
|
||||||
borderType: BorderType;
|
borderType: BorderType;
|
||||||
|
@ -61,6 +64,7 @@ export type RunChildJSON =
|
||||||
| TabJSON
|
| TabJSON
|
||||||
| BreakJSON
|
| BreakJSON
|
||||||
| DrawingJSON
|
| DrawingJSON
|
||||||
|
| PtabJSON
|
||||||
| ShapeJSON
|
| ShapeJSON
|
||||||
| CommentRangeStartJSON
|
| CommentRangeStartJSON
|
||||||
| CommentRangeEndJSON
|
| CommentRangeEndJSON
|
||||||
|
@ -75,6 +79,15 @@ export type TextJSON = {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type PtabJSON = {
|
||||||
|
type: "ptab";
|
||||||
|
data: {
|
||||||
|
alignment: PositionalTabAlignmentType;
|
||||||
|
relativeTo: PositionalTabRelativeTo;
|
||||||
|
leader: TabLeaderType;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export type SymJSON = {
|
export type SymJSON = {
|
||||||
type: "sym";
|
type: "sym";
|
||||||
data: {
|
data: {
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { PositionalTabAlignmentType } from "./json/bindings/PositionalTabAlignmentType";
|
||||||
|
import { PositionalTabRelativeTo } from "./json/bindings/PositionalTabRelativeTo";
|
||||||
|
import { TabLeaderType } from "./json/bindings/TabLeaderType";
|
||||||
|
import {
|
||||||
|
createPositionalTab,
|
||||||
|
PositionalTabAlignmentType as _PositionalTabAlignmentType,
|
||||||
|
PositionalTabRelativeTo as _PositionalTabRelativeTo,
|
||||||
|
TabLeaderType as _TabLeaderType,
|
||||||
|
} from "./pkg/docx_wasm";
|
||||||
|
import { convertTabLeader } from "./tab-leader";
|
||||||
|
|
||||||
|
export class PositionalTab {
|
||||||
|
_alignment: PositionalTabAlignmentType = "left";
|
||||||
|
_relativeTo: PositionalTabRelativeTo = "margin";
|
||||||
|
_leader: TabLeaderType = "none";
|
||||||
|
|
||||||
|
alignment(t: PositionalTabAlignmentType) {
|
||||||
|
this._alignment = t;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
relativeTo(t: PositionalTabRelativeTo) {
|
||||||
|
this._relativeTo = t;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
leader(l: TabLeaderType) {
|
||||||
|
this._leader = l;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildWasmObject() {
|
||||||
|
const alignment = (() => {
|
||||||
|
if (this._alignment === "left") return _PositionalTabAlignmentType.Left;
|
||||||
|
if (this._alignment === "center")
|
||||||
|
return _PositionalTabAlignmentType.Center;
|
||||||
|
if (this._alignment === "right") return _PositionalTabAlignmentType.Right;
|
||||||
|
return _PositionalTabAlignmentType.Left;
|
||||||
|
})();
|
||||||
|
|
||||||
|
const relativeTo = (() => {
|
||||||
|
if (this._relativeTo === "indent") return _PositionalTabRelativeTo.Indent;
|
||||||
|
return _PositionalTabRelativeTo.Margin;
|
||||||
|
})();
|
||||||
|
|
||||||
|
const leader = convertTabLeader(this._leader);
|
||||||
|
|
||||||
|
return createPositionalTab(alignment, relativeTo, leader);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,8 +6,9 @@ import { Tab } from "./tab";
|
||||||
import { Break, BreakType } from "./break";
|
import { Break, BreakType } from "./break";
|
||||||
import { BorderType } from "./border";
|
import { BorderType } from "./border";
|
||||||
import { Image } from "./image";
|
import { Image } from "./image";
|
||||||
|
import { PositionalTab } from "./positional-tab";
|
||||||
|
|
||||||
export type RunChild = Text | DeleteText | Tab | Break | Image;
|
export type RunChild = Text | DeleteText | Tab | Break | Image | PositionalTab;
|
||||||
|
|
||||||
export type TextBorder = {
|
export type TextBorder = {
|
||||||
borderType: BorderType;
|
borderType: BorderType;
|
||||||
|
@ -193,6 +194,11 @@ export class Run {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addPositionalTab(ptab: PositionalTab) {
|
||||||
|
this.children.push(ptab);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
addBreak(type: BreakType) {
|
addBreak(type: BreakType) {
|
||||||
this.children.push(new Break(type));
|
this.children.push(new Break(type));
|
||||||
return this;
|
return this;
|
||||||
|
@ -290,6 +296,8 @@ export class Run {
|
||||||
run = run.add_delete_text(child.text);
|
run = run.add_delete_text(child.text);
|
||||||
} else if (child instanceof Tab) {
|
} else if (child instanceof Tab) {
|
||||||
run = run.add_tab();
|
run = run.add_tab();
|
||||||
|
} else if (child instanceof PositionalTab) {
|
||||||
|
run = run.add_ptab(child.buildWasmObject());
|
||||||
} else if (child instanceof Break) {
|
} else if (child instanceof Break) {
|
||||||
if (child.type === "column") {
|
if (child.type === "column") {
|
||||||
run = run.add_break(wasm.BreakType.Column);
|
run = run.add_break(wasm.BreakType.Column);
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import * as wasm from "./pkg";
|
||||||
|
import { TabLeaderType } from "./json/bindings/TabLeaderType";
|
||||||
|
|
||||||
|
export const convertTabLeader = (leader: TabLeaderType) => {
|
||||||
|
switch (leader) {
|
||||||
|
case "dot":
|
||||||
|
return wasm.TabLeaderType.Dot;
|
||||||
|
break;
|
||||||
|
case "heavy":
|
||||||
|
return wasm.TabLeaderType.Heavy;
|
||||||
|
case "hyphen":
|
||||||
|
return wasm.TabLeaderType.Hyphen;
|
||||||
|
case "middleDot":
|
||||||
|
return wasm.TabLeaderType.MiddleDot;
|
||||||
|
case "none":
|
||||||
|
return wasm.TabLeaderType.None;
|
||||||
|
case "underscore":
|
||||||
|
return wasm.TabLeaderType.Underscore;
|
||||||
|
default:
|
||||||
|
return wasm.TabLeaderType.None;
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "docx-wasm",
|
"name": "docx-wasm",
|
||||||
"version": "0.4.18-rc9",
|
"version": "0.4.18-rc12",
|
||||||
"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>",
|
||||||
|
|
|
@ -17,6 +17,7 @@ mod page_num;
|
||||||
mod page_num_type;
|
mod page_num_type;
|
||||||
mod paragraph;
|
mod paragraph;
|
||||||
mod pic;
|
mod pic;
|
||||||
|
mod positional_tab;
|
||||||
mod reader;
|
mod reader;
|
||||||
mod run;
|
mod run;
|
||||||
mod run_fonts;
|
mod run_fonts;
|
||||||
|
@ -49,6 +50,7 @@ pub use page_num::*;
|
||||||
pub use page_num_type::*;
|
pub use page_num_type::*;
|
||||||
pub use paragraph::*;
|
pub use paragraph::*;
|
||||||
pub use pic::*;
|
pub use pic::*;
|
||||||
|
pub use positional_tab::*;
|
||||||
pub use reader::*;
|
pub use reader::*;
|
||||||
pub use run::*;
|
pub use run::*;
|
||||||
pub use run_fonts::*;
|
pub use run_fonts::*;
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PositionalTab(docx_rs::PositionalTab);
|
||||||
|
|
||||||
|
#[wasm_bindgen(js_name = createPositionalTab)]
|
||||||
|
pub fn create_positional_tab(
|
||||||
|
alignment: docx_rs::PositionalTabAlignmentType,
|
||||||
|
relative_to: docx_rs::PositionalTabRelativeTo,
|
||||||
|
leader: docx_rs::TabLeaderType,
|
||||||
|
) -> PositionalTab {
|
||||||
|
PositionalTab(docx_rs::PositionalTab::new(alignment, relative_to, leader))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
impl PositionalTab {
|
||||||
|
pub fn alignment(mut self, alignment: docx_rs::PositionalTabAlignmentType) -> Self {
|
||||||
|
self.0 = self.0.alignment(alignment);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn relative_to(mut self, relative_to: docx_rs::PositionalTabRelativeTo) -> Self {
|
||||||
|
self.0 = self.0.relative_to(relative_to);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn leader(mut self, leader: docx_rs::TabLeaderType) -> Self {
|
||||||
|
self.0 = self.0.leader(leader);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PositionalTab {
|
||||||
|
pub fn take(self) -> docx_rs::PositionalTab {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,11 @@ impl Run {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_ptab(mut self, ptab: PositionalTab) -> Run {
|
||||||
|
self.0 = self.0.add_ptab(ptab.take());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_break(mut self, break_type: docx_rs::BreakType) -> Run {
|
pub fn add_break(mut self, break_type: docx_rs::BreakType) -> Run {
|
||||||
self.0
|
self.0
|
||||||
.children
|
.children
|
||||||
|
|
|
@ -41792,6 +41792,269 @@ Object {
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`reader should read ptab 1`] = `
|
||||||
|
Object {
|
||||||
|
"comments": Object {
|
||||||
|
"comments": Array [],
|
||||||
|
},
|
||||||
|
"commentsExtended": Object {
|
||||||
|
"children": Array [],
|
||||||
|
},
|
||||||
|
"contentType": Object {
|
||||||
|
"custom_xml_count": 1,
|
||||||
|
"footer_count": 0,
|
||||||
|
"header_count": 0,
|
||||||
|
"types": Object {
|
||||||
|
"/_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/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",
|
||||||
|
},
|
||||||
|
"web_extension_count": 1,
|
||||||
|
},
|
||||||
|
"customItemProps": Array [],
|
||||||
|
"customItemRels": Array [],
|
||||||
|
"customItems": Array [],
|
||||||
|
"docProps": Object {
|
||||||
|
"app": Object {},
|
||||||
|
"core": Object {
|
||||||
|
"config": Object {
|
||||||
|
"created": null,
|
||||||
|
"creator": null,
|
||||||
|
"description": null,
|
||||||
|
"language": null,
|
||||||
|
"lastModifiedBy": null,
|
||||||
|
"modified": null,
|
||||||
|
"revision": null,
|
||||||
|
"subject": null,
|
||||||
|
"title": null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"custom": Object {
|
||||||
|
"properties": Object {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"document": Object {
|
||||||
|
"children": Array [
|
||||||
|
Object {
|
||||||
|
"data": Object {
|
||||||
|
"children": Array [
|
||||||
|
Object {
|
||||||
|
"data": Object {
|
||||||
|
"children": Array [
|
||||||
|
Object {
|
||||||
|
"data": Object {
|
||||||
|
"alignment": "right",
|
||||||
|
"leader": "none",
|
||||||
|
"relativeTo": "margin",
|
||||||
|
},
|
||||||
|
"type": "ptab",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"data": Object {
|
||||||
|
"preserveSpace": true,
|
||||||
|
"text": "Hello world!!",
|
||||||
|
},
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"runProperty": Object {},
|
||||||
|
},
|
||||||
|
"type": "run",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"hasNumbering": false,
|
||||||
|
"id": "00000001",
|
||||||
|
"property": Object {
|
||||||
|
"runProperty": Object {},
|
||||||
|
"tabs": Array [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"type": "paragraph",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"hasNumbering": false,
|
||||||
|
"sectionProperty": Object {
|
||||||
|
"columns": 1,
|
||||||
|
"pageMargin": Object {
|
||||||
|
"bottom": 1701,
|
||||||
|
"footer": 992,
|
||||||
|
"gutter": 0,
|
||||||
|
"header": 851,
|
||||||
|
"left": 1701,
|
||||||
|
"right": 1701,
|
||||||
|
"top": 1985,
|
||||||
|
},
|
||||||
|
"pageSize": Object {
|
||||||
|
"h": 16838,
|
||||||
|
"orient": null,
|
||||||
|
"w": 11906,
|
||||||
|
},
|
||||||
|
"space": 425,
|
||||||
|
"textDirection": "lrTb",
|
||||||
|
"titlePg": false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"documentRels": Object {
|
||||||
|
"customXmlCount": 0,
|
||||||
|
"footerCount": 0,
|
||||||
|
"hasComments": false,
|
||||||
|
"hasFootnotes": false,
|
||||||
|
"hasNumberings": false,
|
||||||
|
"headerCount": 0,
|
||||||
|
"hyperlinks": Array [],
|
||||||
|
"images": Array [],
|
||||||
|
},
|
||||||
|
"fontTable": Object {},
|
||||||
|
"footnotes": Object {
|
||||||
|
"footnotes": Array [],
|
||||||
|
},
|
||||||
|
"hyperlinks": Array [],
|
||||||
|
"images": Array [],
|
||||||
|
"media": Array [],
|
||||||
|
"numberings": Object {
|
||||||
|
"abstractNums": Array [],
|
||||||
|
"numberings": Array [],
|
||||||
|
},
|
||||||
|
"rels": Object {
|
||||||
|
"rels": Array [
|
||||||
|
Array [
|
||||||
|
"http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
|
||||||
|
"rId1",
|
||||||
|
"docProps/core.xml",
|
||||||
|
],
|
||||||
|
Array [
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
|
||||||
|
"rId2",
|
||||||
|
"docProps/app.xml",
|
||||||
|
],
|
||||||
|
Array [
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
|
||||||
|
"rId3",
|
||||||
|
"word/document.xml",
|
||||||
|
],
|
||||||
|
Array [
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties",
|
||||||
|
"rId4",
|
||||||
|
"docProps/custom.xml",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"settings": Object {
|
||||||
|
"adjustLineHeightInTable": false,
|
||||||
|
"defaultTabStop": 840,
|
||||||
|
"docId": null,
|
||||||
|
"docVars": Array [],
|
||||||
|
"evenAndOddHeaders": false,
|
||||||
|
"zoom": 100,
|
||||||
|
},
|
||||||
|
"styles": Object {
|
||||||
|
"docDefaults": Object {
|
||||||
|
"paragraphPropertyDefault": Object {
|
||||||
|
"paragraphProperty": Object {
|
||||||
|
"runProperty": Object {},
|
||||||
|
"tabs": Array [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"runPropertyDefault": Object {
|
||||||
|
"runProperty": Object {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"styles": Array [
|
||||||
|
Object {
|
||||||
|
"basedOn": null,
|
||||||
|
"name": "Normal",
|
||||||
|
"next": null,
|
||||||
|
"paragraphProperty": Object {
|
||||||
|
"runProperty": Object {},
|
||||||
|
"tabs": Array [],
|
||||||
|
},
|
||||||
|
"runProperty": Object {},
|
||||||
|
"styleId": "Normal",
|
||||||
|
"styleType": "paragraph",
|
||||||
|
"tableCellProperty": Object {
|
||||||
|
"borders": null,
|
||||||
|
"gridSpan": null,
|
||||||
|
"shading": null,
|
||||||
|
"textDirection": null,
|
||||||
|
"verticalAlign": null,
|
||||||
|
"verticalMerge": null,
|
||||||
|
"width": null,
|
||||||
|
},
|
||||||
|
"tableProperty": Object {
|
||||||
|
"borders": Object {
|
||||||
|
"bottom": Object {
|
||||||
|
"borderType": "single",
|
||||||
|
"color": "000000",
|
||||||
|
"position": "bottom",
|
||||||
|
"size": 2,
|
||||||
|
"space": 0,
|
||||||
|
},
|
||||||
|
"insideH": Object {
|
||||||
|
"borderType": "single",
|
||||||
|
"color": "000000",
|
||||||
|
"position": "insideH",
|
||||||
|
"size": 2,
|
||||||
|
"space": 0,
|
||||||
|
},
|
||||||
|
"insideV": Object {
|
||||||
|
"borderType": "single",
|
||||||
|
"color": "000000",
|
||||||
|
"position": "insideV",
|
||||||
|
"size": 2,
|
||||||
|
"space": 0,
|
||||||
|
},
|
||||||
|
"left": Object {
|
||||||
|
"borderType": "single",
|
||||||
|
"color": "000000",
|
||||||
|
"position": "left",
|
||||||
|
"size": 2,
|
||||||
|
"space": 0,
|
||||||
|
},
|
||||||
|
"right": Object {
|
||||||
|
"borderType": "single",
|
||||||
|
"color": "000000",
|
||||||
|
"position": "right",
|
||||||
|
"size": 2,
|
||||||
|
"space": 0,
|
||||||
|
},
|
||||||
|
"top": Object {
|
||||||
|
"borderType": "single",
|
||||||
|
"color": "000000",
|
||||||
|
"position": "top",
|
||||||
|
"size": 2,
|
||||||
|
"space": 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"justification": "left",
|
||||||
|
"width": Object {
|
||||||
|
"width": 0,
|
||||||
|
"widthType": "auto",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"taskpanes": null,
|
||||||
|
"taskpanesRels": Object {
|
||||||
|
"rels": Array [],
|
||||||
|
},
|
||||||
|
"themes": Array [],
|
||||||
|
"webExtensions": Array [],
|
||||||
|
"webSettings": Object {
|
||||||
|
"divs": Array [],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`reader should read sectionProperty in ppr 1`] = `
|
exports[`reader should read sectionProperty in ppr 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"comments": Object {
|
"comments": Object {
|
||||||
|
@ -171837,6 +172100,31 @@ exports[`writer should write paragraph delete 3`] = `
|
||||||
</w:num></w:numbering>"
|
</w:num></w:numbering>"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`writer should write ptab 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=\\"rId5\\" Type=\\"http://schemas.microsoft.com/office/2011/relationships/commentsExtended\\" Target=\\"commentsExtended.xml\\" />
|
||||||
|
</Relationships>"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`writer should write ptab 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=\\"00000001\\"><w:pPr><w:rPr /></w:pPr><w:r><w:rPr /><w:ptab w:alignment=\\"right\\" w:relativeTo=\\"margin\\" w:leader=\\"none\\" /><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:cols w:space=\\"425\\" w:num=\\"1\\" />
|
||||||
|
</w:sectPr></w:body>
|
||||||
|
</w:document>"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`writer should write ptab 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 strike 1`] = `
|
exports[`writer should write strike 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\\">
|
||||||
|
|
|
@ -214,6 +214,12 @@ describe("reader", () => {
|
||||||
const json = w.readDocx(buffer);
|
const json = w.readDocx(buffer);
|
||||||
expect(json).toMatchSnapshot();
|
expect(json).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should read ptab", () => {
|
||||||
|
const buffer = readFileSync("../fixtures/ptab/ptab.docx");
|
||||||
|
const json = w.readDocx(buffer);
|
||||||
|
expect(json).toMatchSnapshot();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("writer", () => {
|
describe("writer", () => {
|
||||||
|
@ -1063,4 +1069,20 @@ describe("writer", () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should write ptab", () => {
|
||||||
|
const p = new w.Paragraph().addRun(
|
||||||
|
new w.Run()
|
||||||
|
.addPositionalTab(new w.PositionalTab().alignment("right"))
|
||||||
|
.addText("Hello world!!")
|
||||||
|
);
|
||||||
|
const buffer = new w.Docx().addParagraph(p).build();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeFileSync("../output/js/ptab.docx", buffer);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue