Support ptab in r (#756)

* feat: add ptab

* feat: wasm object

* fix: suppoert ptab

* spec: add read test for ptab

* rc10

* rc11

* rc12
main
bokuweb 2024-10-15 18:30:05 +09:00 committed by GitHub
parent 19b174da7c
commit 60d94921b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 573 additions and 5 deletions

View File

@ -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,

View File

@ -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) => {

View File

@ -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;

View File

@ -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),
_ => {}
}
}
}
}

View File

@ -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") {

View File

@ -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) {

View File

@ -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),

View File

@ -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,

View File

@ -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";

View File

@ -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, }

View File

@ -1,2 +1,2 @@
export type PositionalTabRelativeTo = "Indent" | "Margin"; export type PositionalTabRelativeTo = "indent" | "margin";

View File

@ -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: {

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;
}
};

View File

@ -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>",

View File

@ -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::*;

View File

@ -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
}
}

View File

@ -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

View File

@ -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\\">

View File

@ -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.