fix: add before/after contents and with_instr_text in toc (#582)
* fix * refactor js * fix: add before/after contents in toc * fix * fixmain
parent
c4f9ba0e7e
commit
7f2dace81c
|
@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
|
|||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## docx-wasm@0.0.276-rc39 (13. Dec, 2022)
|
||||
|
||||
- Support before/after contents in ToC.
|
||||
- Support Toc from instrText.
|
||||
|
||||
## docx-wasm@0.0.276-rc38 (7. Dec, 2022)
|
||||
|
||||
- fix #584 Remove `%` from width.
|
||||
|
|
|
@ -71,6 +71,10 @@ impl InstrToC {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
pub fn with_instr_text(s: &str) -> Self {
|
||||
Self::from_str(s).expect("should convert to InstrToC")
|
||||
}
|
||||
|
||||
pub fn heading_styles_range(mut self, start: usize, end: usize) -> Self {
|
||||
self.heading_styles_range = Some((start, end));
|
||||
self
|
||||
|
@ -429,4 +433,18 @@ mod tests {
|
|||
.add_style_with_level(StyleWithLevel::new("MySpectacularStyle2", 4))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn with_instr_text() {
|
||||
let s = r#"TOC \o "1-3" \h \z \u"#;
|
||||
let i = InstrToC::with_instr_text(s);
|
||||
assert_eq!(
|
||||
i,
|
||||
InstrToC::new()
|
||||
.heading_styles_range(1, 3)
|
||||
.use_applied_paragraph_line_level()
|
||||
.hide_tab_and_page_numbers_in_webview()
|
||||
.hyperlink()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,6 +142,11 @@ impl StructuredDataTag {
|
|||
self.property = self.property.data_binding(d);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn alias(mut self, v: impl Into<String>) -> Self {
|
||||
self.property = self.property.alias(v);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl BuildXML for StructuredDataTag {
|
||||
|
|
|
@ -1,9 +1,38 @@
|
|||
use serde::ser::{SerializeStruct, Serializer};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::documents::*;
|
||||
use crate::types::*;
|
||||
use crate::xml_builder::*;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum TocContent {
|
||||
Paragraph(Box<Paragraph>),
|
||||
Table(Box<Table>),
|
||||
}
|
||||
|
||||
impl Serialize for TocContent {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match *self {
|
||||
TocContent::Paragraph(ref p) => {
|
||||
let mut t = serializer.serialize_struct("Paragraph", 2)?;
|
||||
t.serialize_field("type", "paragraph")?;
|
||||
t.serialize_field("data", p)?;
|
||||
t.end()
|
||||
}
|
||||
TocContent::Table(ref c) => {
|
||||
let mut t = serializer.serialize_struct("Table", 2)?;
|
||||
t.serialize_field("type", "table")?;
|
||||
t.serialize_field("data", c)?;
|
||||
t.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_TOCTOC_topic_ID0ELZO1.html
|
||||
// This struct is only used by writers
|
||||
#[derive(Serialize, Debug, Clone, PartialEq, Default)]
|
||||
|
@ -14,6 +43,12 @@ pub struct TableOfContents {
|
|||
pub dirty: bool,
|
||||
pub alias: Option<String>,
|
||||
pub page_ref_placeholder: Option<String>,
|
||||
// it is inserted in before toc.
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub before_contents: Vec<TocContent>,
|
||||
// it is inserted in after toc.
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub after_contents: Vec<TocContent>,
|
||||
}
|
||||
|
||||
impl TableOfContents {
|
||||
|
@ -21,6 +56,14 @@ impl TableOfContents {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
pub fn with_instr_text(s: &str) -> Self {
|
||||
let instr = InstrToC::with_instr_text(s);
|
||||
Self {
|
||||
instr,
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn heading_styles_range(mut self, start: usize, end: usize) -> Self {
|
||||
self.instr = self.instr.heading_styles_range(start, end);
|
||||
self
|
||||
|
@ -60,6 +103,27 @@ impl TableOfContents {
|
|||
self.dirty = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_before_paragraph(mut self, p: Paragraph) -> Self {
|
||||
self.before_contents
|
||||
.push(TocContent::Paragraph(Box::new(p)));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_after_paragraph(mut self, p: Paragraph) -> Self {
|
||||
self.after_contents.push(TocContent::Paragraph(Box::new(p)));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_before_table(mut self, t: Table) -> Self {
|
||||
self.before_contents.push(TocContent::Table(Box::new(t)));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_after_table(mut self, t: Table) -> Self {
|
||||
self.after_contents.push(TocContent::Table(Box::new(t)));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl BuildXML for TableOfContents {
|
||||
|
@ -77,15 +141,36 @@ impl BuildXML for TableOfContents {
|
|||
);
|
||||
let p2 = Paragraph::new().add_run(Run::new().add_field_char(FieldCharType::End, false));
|
||||
|
||||
XMLBuilder::new()
|
||||
let mut b = XMLBuilder::new()
|
||||
.open_structured_tag()
|
||||
.add_child(&p)
|
||||
.open_structured_tag_content()
|
||||
.add_child(&p1)
|
||||
.add_child(&p2)
|
||||
.close()
|
||||
.close()
|
||||
.build()
|
||||
.open_structured_tag_content();
|
||||
|
||||
for c in self.before_contents.iter() {
|
||||
match c {
|
||||
TocContent::Paragraph(p) => {
|
||||
b = b.add_child(p);
|
||||
}
|
||||
TocContent::Table(t) => {
|
||||
b = b.add_child(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b = b.add_child(&p1).add_child(&p2);
|
||||
|
||||
for c in self.after_contents.iter() {
|
||||
match c {
|
||||
TocContent::Paragraph(p) => {
|
||||
b = b.add_child(p);
|
||||
}
|
||||
TocContent::Table(t) => {
|
||||
b = b.add_child(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.close().close().build()
|
||||
} else {
|
||||
let items: Vec<TableOfContentsItem> = self
|
||||
.items
|
||||
|
@ -100,14 +185,37 @@ impl BuildXML for TableOfContents {
|
|||
item
|
||||
})
|
||||
.collect();
|
||||
XMLBuilder::new()
|
||||
|
||||
let mut b = XMLBuilder::new()
|
||||
.open_structured_tag()
|
||||
.add_child(&p)
|
||||
.open_structured_tag_content()
|
||||
.add_child(&items)
|
||||
.close()
|
||||
.close()
|
||||
.build()
|
||||
.open_structured_tag_content();
|
||||
|
||||
for c in self.before_contents.iter() {
|
||||
match c {
|
||||
TocContent::Paragraph(p) => {
|
||||
b = b.add_child(p);
|
||||
}
|
||||
TocContent::Table(t) => {
|
||||
b = b.add_child(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b = b.add_child(&items);
|
||||
|
||||
for c in self.after_contents.iter() {
|
||||
match c {
|
||||
TocContent::Paragraph(p) => {
|
||||
b = b.add_child(p);
|
||||
}
|
||||
TocContent::Table(t) => {
|
||||
b = b.add_child(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.close().close().build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ use thiserror::Error;
|
|||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum DocxError {
|
||||
#[error("FromStr error.{0}")]
|
||||
ConvertError(String),
|
||||
#[error("Failed to write XML to buffer.")]
|
||||
EmitterError(#[from] xml::writer::Error),
|
||||
#[error("Failed to zip XML documents.")]
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import { Paragraph } from "./paragraph";
|
||||
import { Table } from "./table";
|
||||
|
||||
import * as wasm from "./pkg";
|
||||
|
||||
export class Comment {
|
||||
id: number;
|
||||
_author: string;
|
||||
|
@ -31,4 +33,25 @@ export class Comment {
|
|||
this._parentCommentId = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
build() {
|
||||
let comment = wasm.createComment(this.id);
|
||||
this.children.forEach((child) => {
|
||||
if (child instanceof Paragraph) {
|
||||
comment = comment.add_paragraph(child.build());
|
||||
} else if (child instanceof Table) {
|
||||
// TODO: Support later
|
||||
}
|
||||
});
|
||||
if (this._author) {
|
||||
comment = comment.author(this._author);
|
||||
}
|
||||
if (this._date) {
|
||||
comment = comment.date(this._date);
|
||||
}
|
||||
if (this._parentCommentId) {
|
||||
comment = comment.parent_comment_id(this._parentCommentId);
|
||||
}
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { Run } from "./run";
|
||||
|
||||
import * as wasm from "./pkg";
|
||||
|
||||
export class Delete {
|
||||
run: Run;
|
||||
|
||||
|
@ -19,4 +21,16 @@ export class Delete {
|
|||
this._date = date;
|
||||
return this;
|
||||
}
|
||||
|
||||
build() {
|
||||
const run = this.run.build();
|
||||
let del = wasm.createDelete(run);
|
||||
if (this._author) {
|
||||
del = del.author(this._author);
|
||||
}
|
||||
if (this._date) {
|
||||
del = del.date(this._date);
|
||||
}
|
||||
return del;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,34 @@ export class Hyperlink {
|
|||
this.children.push(end);
|
||||
return this;
|
||||
}
|
||||
|
||||
build() {
|
||||
let hyperlink = wasm.createHyperlink(this.v, convertHyperlinkType(this));
|
||||
|
||||
this.children.forEach((child) => {
|
||||
if (child instanceof Run) {
|
||||
const run = child.build();
|
||||
hyperlink = hyperlink.add_run(run);
|
||||
} else if (child instanceof Insert) {
|
||||
const insert = child.build();
|
||||
hyperlink = hyperlink.add_insert(insert);
|
||||
} else if (child instanceof Delete) {
|
||||
const del = child.build();
|
||||
hyperlink = hyperlink.add_delete(del);
|
||||
} else if (child instanceof BookmarkStart) {
|
||||
hyperlink = hyperlink.add_bookmark_start(child.id, child.name);
|
||||
} else if (child instanceof BookmarkEnd) {
|
||||
hyperlink = hyperlink.add_bookmark_end(child.id);
|
||||
} else if (child instanceof Comment) {
|
||||
const comment = child.build();
|
||||
hyperlink = hyperlink.add_comment_start(comment);
|
||||
} else if (child instanceof CommentEnd) {
|
||||
hyperlink = hyperlink.add_comment_end(child.id);
|
||||
}
|
||||
});
|
||||
|
||||
return hyperlink;
|
||||
}
|
||||
}
|
||||
|
||||
export const convertHyperlinkType = (link: Hyperlink): wasm.HyperlinkType => {
|
||||
|
|
|
@ -1,18 +1,8 @@
|
|||
import { Paragraph } from "./paragraph";
|
||||
import { ParagraphProperty, setParagraphProperty } from "./paragraph-property";
|
||||
import { Insert } from "./insert";
|
||||
import { Delete } from "./delete";
|
||||
import { convertHyperlinkType, Hyperlink } from "./hyperlink";
|
||||
import { DeleteText } from "./delete-text";
|
||||
import { setTableProperty, Table } from "./table";
|
||||
import { ParagraphProperty } from "./paragraph-property";
|
||||
import { Table } from "./table";
|
||||
import { TableOfContents } from "./table-of-contents";
|
||||
import { TableCell, toTextDirectionWasmType } from "./table-cell";
|
||||
import { convertBorderType, Run, RunFonts, setRunProperty } from "./run";
|
||||
import { Text } from "./text";
|
||||
import { Tab } from "./tab";
|
||||
import { Break } from "./break";
|
||||
import { Comment } from "./comment";
|
||||
import { CommentEnd } from "./comment-end";
|
||||
import { RunFonts } from "./run";
|
||||
import { AbstractNumbering } from "./abstract-numbering";
|
||||
import { Numbering } from "./numbering";
|
||||
import { BookmarkStart } from "./bookmark-start";
|
||||
|
@ -24,7 +14,6 @@ import { Styles } from "./styles";
|
|||
import { WebExtension } from "./webextension";
|
||||
import { Footer } from "./footer";
|
||||
import { Header } from "./header";
|
||||
import { Image } from "./image";
|
||||
|
||||
import {
|
||||
SectionProperty,
|
||||
|
@ -44,6 +33,7 @@ export class Docx {
|
|||
| BookmarkEnd
|
||||
| TableOfContents
|
||||
)[] = [];
|
||||
|
||||
hasNumberings = false;
|
||||
abstractNumberings: AbstractNumbering[] = [];
|
||||
numberings: Numbering[] = [];
|
||||
|
@ -233,122 +223,6 @@ export class Docx {
|
|||
return f;
|
||||
};
|
||||
|
||||
buildRun(r: Run) {
|
||||
let run = wasm.createRun();
|
||||
r.children.forEach((child) => {
|
||||
if (child instanceof Text) {
|
||||
run = run.add_text(child.text);
|
||||
} else if (child instanceof DeleteText) {
|
||||
run = run.add_delete_text(child.text);
|
||||
} else if (child instanceof Tab) {
|
||||
run = run.add_tab();
|
||||
} else if (child instanceof Break) {
|
||||
if (child.type === "column") {
|
||||
run = run.add_break(wasm.BreakType.Column);
|
||||
} else if (child.type === "page") {
|
||||
run = run.add_break(wasm.BreakType.Page);
|
||||
} else if (child.type === "textWrapping") {
|
||||
run = run.add_break(wasm.BreakType.TextWrapping);
|
||||
}
|
||||
} else if (child instanceof Image) {
|
||||
let pic = wasm.createPic(child.data);
|
||||
if (child.w != null && child.h != null) {
|
||||
pic = pic.size(child.w, child.h);
|
||||
}
|
||||
if (child._floating) {
|
||||
pic = pic.floating();
|
||||
}
|
||||
if (child._offsetX != null) {
|
||||
pic = pic.offset_x(child._offsetX);
|
||||
}
|
||||
if (child._offsetY != null) {
|
||||
pic = pic.offset_x(child._offsetY);
|
||||
}
|
||||
if (child.rot != null) {
|
||||
pic = pic.rotate(child.rot);
|
||||
}
|
||||
run = run.add_image(pic);
|
||||
}
|
||||
});
|
||||
|
||||
run = setRunProperty(run, r.property) as wasm.Run;
|
||||
|
||||
return run;
|
||||
}
|
||||
|
||||
buildHyperlink(link: Hyperlink) {
|
||||
let hyperlink = wasm.createHyperlink(link.v, convertHyperlinkType(link));
|
||||
|
||||
link.children.forEach((child) => {
|
||||
if (child instanceof Run) {
|
||||
const run = this.buildRun(child);
|
||||
hyperlink = hyperlink.add_run(run);
|
||||
} else if (child instanceof Insert) {
|
||||
const insert = this.buildInsert(child);
|
||||
hyperlink = hyperlink.add_insert(insert);
|
||||
} else if (child instanceof Delete) {
|
||||
const del = this.buildDelete(child);
|
||||
hyperlink = hyperlink.add_delete(del);
|
||||
} else if (child instanceof BookmarkStart) {
|
||||
hyperlink = hyperlink.add_bookmark_start(child.id, child.name);
|
||||
} else if (child instanceof BookmarkEnd) {
|
||||
hyperlink = hyperlink.add_bookmark_end(child.id);
|
||||
} else if (child instanceof Comment) {
|
||||
const comment = this.buildComment(child);
|
||||
hyperlink = hyperlink.add_comment_start(comment);
|
||||
} else if (child instanceof CommentEnd) {
|
||||
hyperlink = hyperlink.add_comment_end(child.id);
|
||||
}
|
||||
});
|
||||
|
||||
return hyperlink;
|
||||
}
|
||||
|
||||
buildInsert(i: Insert) {
|
||||
const run = this.buildRun(i.run);
|
||||
let insert = wasm.createInsert(run);
|
||||
if (i._author) {
|
||||
insert = insert.author(i._author);
|
||||
}
|
||||
if (i._date) {
|
||||
insert = insert.date(i._date);
|
||||
}
|
||||
return insert;
|
||||
}
|
||||
|
||||
buildDelete(d: Delete) {
|
||||
const run = this.buildRun(d.run);
|
||||
let del = wasm.createDelete(run);
|
||||
if (d._author) {
|
||||
del = del.author(d._author);
|
||||
}
|
||||
if (d._date) {
|
||||
del = del.date(d._date);
|
||||
}
|
||||
return del;
|
||||
}
|
||||
|
||||
buildComment(c: Comment) {
|
||||
let comment = wasm.createComment(c.id);
|
||||
c.children.forEach((child) => {
|
||||
if (child instanceof Paragraph) {
|
||||
comment = comment.add_paragraph(this.buildParagraph(child));
|
||||
} else if (child instanceof Table) {
|
||||
// TODO:
|
||||
}
|
||||
});
|
||||
if (c._author) {
|
||||
comment = comment.author(c._author);
|
||||
}
|
||||
if (c._date) {
|
||||
comment = comment.date(c._date);
|
||||
}
|
||||
if (c._parentCommentId) {
|
||||
comment = comment.parent_comment_id(c._parentCommentId);
|
||||
}
|
||||
return comment;
|
||||
}
|
||||
|
||||
buildLineSpacing(p: ParagraphProperty): wasm.LineSpacing | null {
|
||||
const { lineSpacing } = p;
|
||||
if (lineSpacing == null) return null;
|
||||
|
@ -394,267 +268,6 @@ export class Docx {
|
|||
return spacing;
|
||||
}
|
||||
|
||||
buildParagraph(p: Paragraph) {
|
||||
let paragraph = wasm.createParagraph();
|
||||
p.children.forEach((child) => {
|
||||
if (child instanceof Run) {
|
||||
const run = this.buildRun(child);
|
||||
paragraph = paragraph.add_run(run);
|
||||
} else if (child instanceof Insert) {
|
||||
const insert = this.buildInsert(child);
|
||||
paragraph = paragraph.add_insert(insert);
|
||||
} else if (child instanceof Delete) {
|
||||
const del = this.buildDelete(child);
|
||||
paragraph = paragraph.add_delete(del);
|
||||
} else if (child instanceof Hyperlink) {
|
||||
const hyperlink = this.buildHyperlink(child);
|
||||
paragraph = paragraph.add_hyperlink(hyperlink);
|
||||
} else if (child instanceof BookmarkStart) {
|
||||
paragraph = paragraph.add_bookmark_start(child.id, child.name);
|
||||
} else if (child instanceof BookmarkEnd) {
|
||||
paragraph = paragraph.add_bookmark_end(child.id);
|
||||
} else if (child instanceof Comment) {
|
||||
const comment = this.buildComment(child);
|
||||
paragraph = paragraph.add_comment_start(comment);
|
||||
} else if (child instanceof CommentEnd) {
|
||||
paragraph = paragraph.add_comment_end(child.id);
|
||||
}
|
||||
});
|
||||
|
||||
paragraph = setParagraphProperty(paragraph, p.property);
|
||||
|
||||
if (typeof p.property.styleId !== "undefined") {
|
||||
paragraph = paragraph.style(p.property.styleId);
|
||||
}
|
||||
|
||||
if (p.property.runProperty.del) {
|
||||
paragraph = paragraph.delete(
|
||||
p.property.runProperty.del.author,
|
||||
p.property.runProperty.del.date
|
||||
);
|
||||
}
|
||||
|
||||
if (p.property.runProperty.ins) {
|
||||
paragraph = paragraph.insert(
|
||||
p.property.runProperty.ins.author,
|
||||
p.property.runProperty.ins.date
|
||||
);
|
||||
}
|
||||
|
||||
if (p.property.paragraphPropertyChange) {
|
||||
let change = wasm.createParagraphPropertyChange();
|
||||
change = change
|
||||
.author(p.property.paragraphPropertyChange._author)
|
||||
.date(p.property.paragraphPropertyChange._date);
|
||||
|
||||
if (p.property.paragraphPropertyChange._property.numbering) {
|
||||
change = change.numbering(
|
||||
p.property.paragraphPropertyChange._property.numbering.id,
|
||||
p.property.paragraphPropertyChange._property.numbering.level
|
||||
);
|
||||
}
|
||||
// TODO: add style, indent, alignment
|
||||
paragraph = paragraph.paragraph_property_change(change);
|
||||
}
|
||||
|
||||
return paragraph;
|
||||
}
|
||||
|
||||
buildTable(t: Table) {
|
||||
let table = wasm.createTable();
|
||||
t.rows.forEach((r) => {
|
||||
let row = wasm.createTableRow();
|
||||
r.cells.forEach((c) => {
|
||||
const cell = this.buildCell(c);
|
||||
row = row.add_cell(cell);
|
||||
});
|
||||
|
||||
if (r.height) {
|
||||
row = row.row_height(r.height);
|
||||
}
|
||||
|
||||
if (r.del) {
|
||||
row = row.delete(r.del.author, r.del.date);
|
||||
}
|
||||
|
||||
if (r.ins) {
|
||||
row = row.insert(r.ins.author, r.ins.date);
|
||||
}
|
||||
|
||||
if (r.hRule) {
|
||||
switch (r.hRule) {
|
||||
case "auto": {
|
||||
row = row.height_rule(wasm.HeightRule.Auto);
|
||||
break;
|
||||
}
|
||||
case "atLeast": {
|
||||
row = row.height_rule(wasm.HeightRule.AtLeast);
|
||||
break;
|
||||
}
|
||||
case "exact": {
|
||||
row = row.height_rule(wasm.HeightRule.Exact);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
table = table.add_row(row);
|
||||
});
|
||||
|
||||
table = table.set_grid(new Uint32Array(t.grid));
|
||||
|
||||
if (t.property.styleId) {
|
||||
table = table.style(t.property.styleId);
|
||||
}
|
||||
|
||||
table = setTableProperty(table, t.property);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
buildCell(c: TableCell) {
|
||||
let cell = wasm.createTableCell();
|
||||
c.children.forEach((c) => {
|
||||
if (c instanceof Paragraph) {
|
||||
const paragraph = this.buildParagraph(c);
|
||||
cell = cell.add_paragraph(paragraph);
|
||||
} else if (c instanceof Table) {
|
||||
const table = this.buildTable(c);
|
||||
cell = cell.add_table(table);
|
||||
}
|
||||
});
|
||||
|
||||
if (c.property.verticalMerge === "continue") {
|
||||
cell = cell.vertical_merge(wasm.VMergeType.Continue);
|
||||
} else if (c.property.verticalMerge === "restart") {
|
||||
cell = cell.vertical_merge(wasm.VMergeType.Restart);
|
||||
}
|
||||
|
||||
switch (c.property.verticalAlign) {
|
||||
case "top": {
|
||||
cell = cell.vertical_align(wasm.VAlignType.Top);
|
||||
break;
|
||||
}
|
||||
case "center": {
|
||||
cell = cell.vertical_align(wasm.VAlignType.Center);
|
||||
break;
|
||||
}
|
||||
case "bottom": {
|
||||
cell = cell.vertical_align(wasm.VAlignType.Bottom);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof c.property.gridSpan !== "undefined") {
|
||||
cell = cell.grid_span(c.property.gridSpan);
|
||||
}
|
||||
|
||||
if (typeof c.property.width !== "undefined") {
|
||||
cell = cell.width(c.property.width);
|
||||
}
|
||||
|
||||
if (typeof c.property.textDirection !== "undefined") {
|
||||
cell = cell.text_direction(
|
||||
toTextDirectionWasmType(c.property.textDirection)
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof c.property.borders !== "undefined") {
|
||||
cell = this.buildCellBorders(c, cell);
|
||||
}
|
||||
|
||||
if (typeof c.property.shading !== "undefined") {
|
||||
cell = cell.shading(
|
||||
c.property.shading._type,
|
||||
c.property.shading._color,
|
||||
c.property.shading._fill
|
||||
);
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
buildCellBorders(js: TableCell, cell: wasm.TableCell): wasm.TableCell {
|
||||
if (js.property.borders.top) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Top)
|
||||
.size(js.property.borders.top._size)
|
||||
.color(js.property.borders.top._color)
|
||||
.border_type(convertBorderType(js.property.borders.top._border_type));
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (js.property.borders.right) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Right)
|
||||
.size(js.property.borders.right._size)
|
||||
.color(js.property.borders.right._color)
|
||||
.border_type(convertBorderType(js.property.borders.right._border_type));
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (js.property.borders.bottom) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Bottom)
|
||||
.size(js.property.borders.bottom._size)
|
||||
.color(js.property.borders.bottom._color)
|
||||
.border_type(
|
||||
convertBorderType(js.property.borders.bottom._border_type)
|
||||
);
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (js.property.borders.left) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Left)
|
||||
.size(js.property.borders.left._size)
|
||||
.color(js.property.borders.left._color)
|
||||
.border_type(convertBorderType(js.property.borders.left._border_type));
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (js.property.borders.insideH) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.InsideH)
|
||||
.size(js.property.borders.insideH._size)
|
||||
.color(js.property.borders.insideH._color)
|
||||
.border_type(
|
||||
convertBorderType(js.property.borders.insideH._border_type)
|
||||
);
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (js.property.borders.insideV) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.InsideV)
|
||||
.size(js.property.borders.insideV._size)
|
||||
.color(js.property.borders.insideV._color)
|
||||
.border_type(
|
||||
convertBorderType(js.property.borders.insideV._border_type)
|
||||
);
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (js.property.borders.tl2br) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Tl2br)
|
||||
.size(js.property.borders.tl2br._size)
|
||||
.color(js.property.borders.tl2br._color)
|
||||
.border_type(convertBorderType(js.property.borders.tl2br._border_type));
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (js.property.borders.tr2bl) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Tr2bl)
|
||||
.size(js.property.borders.tr2bl._size)
|
||||
.color(js.property.borders.tr2bl._color)
|
||||
.border_type(convertBorderType(js.property.borders.tr2bl._border_type));
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
buildLevel(l: Level) {
|
||||
let level = wasm.createLevel(l.id, l.start, l.format, l.text, l.jc);
|
||||
|
||||
|
@ -716,10 +329,10 @@ export class Docx {
|
|||
|
||||
this.children.forEach((child) => {
|
||||
if (child instanceof Paragraph) {
|
||||
let p = this.buildParagraph(child);
|
||||
let p = child.build();
|
||||
docx = docx.add_paragraph(p);
|
||||
} else if (child instanceof Table) {
|
||||
let t = this.buildTable(child);
|
||||
let t = child.build();
|
||||
docx = docx.add_table(t);
|
||||
} else if (child instanceof BookmarkStart) {
|
||||
docx = docx.add_bookmark_start(child.id, child.name);
|
||||
|
@ -779,9 +392,9 @@ export class Docx {
|
|||
let header = wasm.createHeader();
|
||||
this.sectionProperty._header.children.forEach((c) => {
|
||||
if (c instanceof Paragraph) {
|
||||
header = header.add_paragraph(this.buildParagraph(c));
|
||||
header = header.add_paragraph(c.build());
|
||||
} else {
|
||||
header = header.add_table(this.buildTable(c));
|
||||
header = header.add_table(c.build());
|
||||
}
|
||||
});
|
||||
docx = docx.header(header);
|
||||
|
@ -791,9 +404,9 @@ export class Docx {
|
|||
let header = wasm.createHeader();
|
||||
this.sectionProperty._firstHeader.children.forEach((c) => {
|
||||
if (c instanceof Paragraph) {
|
||||
header = header.add_paragraph(this.buildParagraph(c));
|
||||
header = header.add_paragraph(c.build());
|
||||
} else {
|
||||
header = header.add_table(this.buildTable(c));
|
||||
header = header.add_table(c.build());
|
||||
}
|
||||
});
|
||||
docx = docx.first_header(header);
|
||||
|
@ -803,9 +416,9 @@ export class Docx {
|
|||
let header = wasm.createHeader();
|
||||
this.sectionProperty._evenHeader.children.forEach((c) => {
|
||||
if (c instanceof Paragraph) {
|
||||
header = header.add_paragraph(this.buildParagraph(c));
|
||||
header = header.add_paragraph(c.build());
|
||||
} else {
|
||||
header = header.add_table(this.buildTable(c));
|
||||
header = header.add_table(c.build());
|
||||
}
|
||||
});
|
||||
docx = docx.even_header(header);
|
||||
|
@ -815,9 +428,9 @@ export class Docx {
|
|||
let footer = wasm.createFooter();
|
||||
this.sectionProperty._footer.children.forEach((c) => {
|
||||
if (c instanceof Paragraph) {
|
||||
footer = footer.add_paragraph(this.buildParagraph(c));
|
||||
footer = footer.add_paragraph(c.build());
|
||||
} else {
|
||||
footer = footer.add_table(this.buildTable(c));
|
||||
footer = footer.add_table(c.build());
|
||||
}
|
||||
});
|
||||
docx = docx.footer(footer);
|
||||
|
@ -827,9 +440,9 @@ export class Docx {
|
|||
let footer = wasm.createFooter();
|
||||
this.sectionProperty._firstFooter.children.forEach((c) => {
|
||||
if (c instanceof Paragraph) {
|
||||
footer = footer.add_paragraph(this.buildParagraph(c));
|
||||
footer = footer.add_paragraph(c.build());
|
||||
} else {
|
||||
footer = footer.add_table(this.buildTable(c));
|
||||
footer = footer.add_table(c.build());
|
||||
}
|
||||
});
|
||||
docx = docx.first_footer(footer);
|
||||
|
@ -839,9 +452,9 @@ export class Docx {
|
|||
let footer = wasm.createFooter();
|
||||
this.sectionProperty._evenFooter.children.forEach((c) => {
|
||||
if (c instanceof Paragraph) {
|
||||
footer = footer.add_paragraph(this.buildParagraph(c));
|
||||
footer = footer.add_paragraph(c.build());
|
||||
} else {
|
||||
footer = footer.add_table(this.buildTable(c));
|
||||
footer = footer.add_table(c.build());
|
||||
}
|
||||
});
|
||||
docx = docx.even_footer(footer);
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { Run } from "./run";
|
||||
|
||||
import * as wasm from "./pkg";
|
||||
|
||||
export class Insert {
|
||||
run: Run;
|
||||
_author: string | null = null;
|
||||
|
@ -17,4 +19,16 @@ export class Insert {
|
|||
this._date = date;
|
||||
return this;
|
||||
}
|
||||
|
||||
build() {
|
||||
const run = this.run.build();
|
||||
let insert = wasm.createInsert(run);
|
||||
if (this._author) {
|
||||
insert = insert.author(this._author);
|
||||
}
|
||||
if (this._date) {
|
||||
insert = insert.date(this._date);
|
||||
}
|
||||
return insert;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
AlignmentType,
|
||||
SpecialIndentKind,
|
||||
ParagraphPropertyChange,
|
||||
setParagraphProperty,
|
||||
} from "./paragraph-property";
|
||||
import { Insert } from "./insert";
|
||||
import { Delete } from "./delete";
|
||||
|
@ -15,6 +16,8 @@ import { Comment } from "./comment";
|
|||
import { CommentEnd } from "./comment-end";
|
||||
import { Hyperlink } from "./hyperlink";
|
||||
|
||||
import * as wasm from "./pkg";
|
||||
|
||||
export type ParagraphChild =
|
||||
| Run
|
||||
| Insert
|
||||
|
@ -155,4 +158,70 @@ export class Paragraph {
|
|||
this.property.paragraphPropertyChange = propertyChange;
|
||||
return this;
|
||||
}
|
||||
|
||||
build() {
|
||||
let paragraph = wasm.createParagraph();
|
||||
this.children.forEach((child) => {
|
||||
if (child instanceof Run) {
|
||||
const run = child.build();
|
||||
paragraph = paragraph.add_run(run);
|
||||
} else if (child instanceof Insert) {
|
||||
const insert = child.build();
|
||||
paragraph = paragraph.add_insert(insert);
|
||||
} else if (child instanceof Delete) {
|
||||
const del = child.build();
|
||||
paragraph = paragraph.add_delete(del);
|
||||
} else if (child instanceof Hyperlink) {
|
||||
const hyperlink = child.build();
|
||||
paragraph = paragraph.add_hyperlink(hyperlink);
|
||||
} else if (child instanceof BookmarkStart) {
|
||||
paragraph = paragraph.add_bookmark_start(child.id, child.name);
|
||||
} else if (child instanceof BookmarkEnd) {
|
||||
paragraph = paragraph.add_bookmark_end(child.id);
|
||||
} else if (child instanceof Comment) {
|
||||
const comment = child.build();
|
||||
paragraph = paragraph.add_comment_start(comment);
|
||||
} else if (child instanceof CommentEnd) {
|
||||
paragraph = paragraph.add_comment_end(child.id);
|
||||
}
|
||||
});
|
||||
|
||||
paragraph = setParagraphProperty(paragraph, this.property);
|
||||
|
||||
if (typeof this.property.styleId !== "undefined") {
|
||||
paragraph = paragraph.style(this.property.styleId);
|
||||
}
|
||||
|
||||
if (this.property.runProperty.del) {
|
||||
paragraph = paragraph.delete(
|
||||
this.property.runProperty.del.author,
|
||||
this.property.runProperty.del.date
|
||||
);
|
||||
}
|
||||
|
||||
if (this.property.runProperty.ins) {
|
||||
paragraph = paragraph.insert(
|
||||
this.property.runProperty.ins.author,
|
||||
this.property.runProperty.ins.date
|
||||
);
|
||||
}
|
||||
|
||||
if (this.property.paragraphPropertyChange) {
|
||||
let change = wasm.createParagraphPropertyChange();
|
||||
change = change
|
||||
.author(this.property.paragraphPropertyChange._author)
|
||||
.date(this.property.paragraphPropertyChange._date);
|
||||
|
||||
if (this.property.paragraphPropertyChange._property.numbering) {
|
||||
change = change.numbering(
|
||||
this.property.paragraphPropertyChange._property.numbering.id,
|
||||
this.property.paragraphPropertyChange._property.numbering.level
|
||||
);
|
||||
}
|
||||
// TODO: add style, indent, alignment
|
||||
paragraph = paragraph.paragraph_property_change(change);
|
||||
}
|
||||
|
||||
return paragraph;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -280,6 +280,49 @@ export class Run {
|
|||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
build() {
|
||||
let run = wasm.createRun();
|
||||
this.children.forEach((child) => {
|
||||
if (child instanceof Text) {
|
||||
run = run.add_text(child.text);
|
||||
} else if (child instanceof DeleteText) {
|
||||
run = run.add_delete_text(child.text);
|
||||
} else if (child instanceof Tab) {
|
||||
run = run.add_tab();
|
||||
} else if (child instanceof Break) {
|
||||
if (child.type === "column") {
|
||||
run = run.add_break(wasm.BreakType.Column);
|
||||
} else if (child.type === "page") {
|
||||
run = run.add_break(wasm.BreakType.Page);
|
||||
} else if (child.type === "textWrapping") {
|
||||
run = run.add_break(wasm.BreakType.TextWrapping);
|
||||
}
|
||||
} else if (child instanceof Image) {
|
||||
let pic = wasm.createPic(child.data);
|
||||
if (child.w != null && child.h != null) {
|
||||
pic = pic.size(child.w, child.h);
|
||||
}
|
||||
if (child._floating) {
|
||||
pic = pic.floating();
|
||||
}
|
||||
if (child._offsetX != null) {
|
||||
pic = pic.offset_x(child._offsetX);
|
||||
}
|
||||
if (child._offsetY != null) {
|
||||
pic = pic.offset_x(child._offsetY);
|
||||
}
|
||||
if (child.rot != null) {
|
||||
pic = pic.rotate(child.rot);
|
||||
}
|
||||
run = run.add_image(pic);
|
||||
}
|
||||
});
|
||||
|
||||
run = setRunProperty(run, this.property) as wasm.Run;
|
||||
|
||||
return run;
|
||||
}
|
||||
}
|
||||
|
||||
export const setRunProperty = <T extends wasm.Run | wasm.Style>(
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Shading } from "./shading";
|
|||
import { TableCellBorders, PositionKeys } from "./table-cell-borders";
|
||||
import { TableCellBorderPosition, TableCellBorder } from "./table-cell-border";
|
||||
import * as wasm from "./pkg";
|
||||
import { convertBorderType } from "./run";
|
||||
|
||||
export type VMergeType = "restart" | "continue";
|
||||
|
||||
|
@ -118,16 +119,166 @@ export class TableCell {
|
|||
}
|
||||
|
||||
setBorder(border: TableCellBorder) {
|
||||
this.property.borders[
|
||||
border.position.toLowerCase() as PositionKeys
|
||||
] = border;
|
||||
this.property.borders[border.position.toLowerCase() as PositionKeys] =
|
||||
border;
|
||||
return this;
|
||||
}
|
||||
|
||||
clearBorder(position: TableCellBorderPosition) {
|
||||
this.property.borders[
|
||||
position.toLowerCase() as PositionKeys
|
||||
] = new TableCellBorder(position).border_type("nil");
|
||||
this.property.borders[position.toLowerCase() as PositionKeys] =
|
||||
new TableCellBorder(position).border_type("nil");
|
||||
return this;
|
||||
}
|
||||
|
||||
buildCellBorders(cell: wasm.TableCell): wasm.TableCell {
|
||||
if (this.property.borders.top) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Top)
|
||||
.size(this.property.borders.top._size)
|
||||
.color(this.property.borders.top._color)
|
||||
.border_type(convertBorderType(this.property.borders.top._border_type));
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (this.property.borders.right) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Right)
|
||||
.size(this.property.borders.right._size)
|
||||
.color(this.property.borders.right._color)
|
||||
.border_type(
|
||||
convertBorderType(this.property.borders.right._border_type)
|
||||
);
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (this.property.borders.bottom) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Bottom)
|
||||
.size(this.property.borders.bottom._size)
|
||||
.color(this.property.borders.bottom._color)
|
||||
.border_type(
|
||||
convertBorderType(this.property.borders.bottom._border_type)
|
||||
);
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (this.property.borders.left) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Left)
|
||||
.size(this.property.borders.left._size)
|
||||
.color(this.property.borders.left._color)
|
||||
.border_type(
|
||||
convertBorderType(this.property.borders.left._border_type)
|
||||
);
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (this.property.borders.insideH) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.InsideH)
|
||||
.size(this.property.borders.insideH._size)
|
||||
.color(this.property.borders.insideH._color)
|
||||
.border_type(
|
||||
convertBorderType(this.property.borders.insideH._border_type)
|
||||
);
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (this.property.borders.insideV) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.InsideV)
|
||||
.size(this.property.borders.insideV._size)
|
||||
.color(this.property.borders.insideV._color)
|
||||
.border_type(
|
||||
convertBorderType(this.property.borders.insideV._border_type)
|
||||
);
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (this.property.borders.tl2br) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Tl2br)
|
||||
.size(this.property.borders.tl2br._size)
|
||||
.color(this.property.borders.tl2br._color)
|
||||
.border_type(
|
||||
convertBorderType(this.property.borders.tl2br._border_type)
|
||||
);
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
if (this.property.borders.tr2bl) {
|
||||
const border = wasm
|
||||
.createTableCellBorder(wasm.TableCellBorderPosition.Tr2bl)
|
||||
.size(this.property.borders.tr2bl._size)
|
||||
.color(this.property.borders.tr2bl._color)
|
||||
.border_type(
|
||||
convertBorderType(this.property.borders.tr2bl._border_type)
|
||||
);
|
||||
cell = cell.set_border(border);
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
build() {
|
||||
let cell = wasm.createTableCell();
|
||||
this.children.forEach((c) => {
|
||||
if (c instanceof Paragraph) {
|
||||
const paragraph = c.build();
|
||||
cell = cell.add_paragraph(paragraph);
|
||||
} else if (c instanceof Table) {
|
||||
const table = c.build();
|
||||
cell = cell.add_table(table);
|
||||
}
|
||||
});
|
||||
|
||||
if (this.property.verticalMerge === "continue") {
|
||||
cell = cell.vertical_merge(wasm.VMergeType.Continue);
|
||||
} else if (this.property.verticalMerge === "restart") {
|
||||
cell = cell.vertical_merge(wasm.VMergeType.Restart);
|
||||
}
|
||||
|
||||
switch (this.property.verticalAlign) {
|
||||
case "top": {
|
||||
cell = cell.vertical_align(wasm.VAlignType.Top);
|
||||
break;
|
||||
}
|
||||
case "center": {
|
||||
cell = cell.vertical_align(wasm.VAlignType.Center);
|
||||
break;
|
||||
}
|
||||
case "bottom": {
|
||||
cell = cell.vertical_align(wasm.VAlignType.Bottom);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof this.property.gridSpan !== "undefined") {
|
||||
cell = cell.grid_span(this.property.gridSpan);
|
||||
}
|
||||
|
||||
if (typeof this.property.width !== "undefined") {
|
||||
cell = cell.width(this.property.width);
|
||||
}
|
||||
|
||||
if (typeof this.property.textDirection !== "undefined") {
|
||||
cell = cell.text_direction(
|
||||
toTextDirectionWasmType(this.property.textDirection)
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof this.property.borders !== "undefined") {
|
||||
cell = this.buildCellBorders(cell);
|
||||
}
|
||||
|
||||
if (typeof this.property.shading !== "undefined") {
|
||||
cell = cell.shading(
|
||||
this.property.shading._type,
|
||||
this.property.shading._color,
|
||||
this.property.shading._fill
|
||||
);
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import { Paragraph } from "./paragraph";
|
||||
import * as wasm from "./pkg";
|
||||
import { Table } from "./table";
|
||||
|
||||
import { TableOfContentsItem } from "./table-of-contents-item";
|
||||
|
||||
export class TableOfContents {
|
||||
_instrText?: string;
|
||||
_headingStylesRange: [number, number] | null = null;
|
||||
_styleWithLevels: { styleId: string; level: number }[] = [];
|
||||
_hyperlink = false;
|
||||
|
@ -11,6 +14,32 @@ export class TableOfContents {
|
|||
_dirty = false;
|
||||
_items: TableOfContentsItem[] = [];
|
||||
_pageRefPlaceholder = "";
|
||||
_beforeContents: (Paragraph | Table)[] = [];
|
||||
_afterContents: (Paragraph | Table)[] = [];
|
||||
|
||||
constructor(instrText?: string) {
|
||||
this._instrText = instrText;
|
||||
}
|
||||
|
||||
addBeforeParagraph(p: Paragraph) {
|
||||
this._beforeContents.push(p);
|
||||
return this;
|
||||
}
|
||||
|
||||
addBeforeTable(t: Table) {
|
||||
this._beforeContents.push(t);
|
||||
return this;
|
||||
}
|
||||
|
||||
addAfterParagraph(p: Paragraph) {
|
||||
this._afterContents.push(p);
|
||||
return this;
|
||||
}
|
||||
|
||||
addAfterTable(t: Table) {
|
||||
this._afterContents.push(t);
|
||||
return this;
|
||||
}
|
||||
|
||||
headingStylesRange = (r: [number, number]) => {
|
||||
this._headingStylesRange = r;
|
||||
|
@ -53,7 +82,9 @@ export class TableOfContents {
|
|||
};
|
||||
|
||||
buildWasmObject = () => {
|
||||
let toc = wasm.createTableOfContents();
|
||||
let toc = this._instrText
|
||||
? wasm.createTableOfContentsWithInstrText(this._instrText)
|
||||
: wasm.createTableOfContents();
|
||||
if (this._headingStylesRange) {
|
||||
toc = toc.heading_styles_range(
|
||||
this._headingStylesRange[0],
|
||||
|
@ -89,6 +120,22 @@ export class TableOfContents {
|
|||
toc = toc.add_item(item.buildWasmObject());
|
||||
}
|
||||
|
||||
for (const c of this._beforeContents) {
|
||||
if (c instanceof Paragraph) {
|
||||
toc = toc.add_before_paragraph(c.build());
|
||||
} else if (c instanceof Table) {
|
||||
toc = toc.add_before_table(c.build());
|
||||
}
|
||||
}
|
||||
|
||||
for (const c of this._afterContents) {
|
||||
if (c instanceof Paragraph) {
|
||||
toc = toc.add_after_paragraph(c.build());
|
||||
} else if (c instanceof Table) {
|
||||
toc = toc.add_after_table(c.build());
|
||||
}
|
||||
}
|
||||
|
||||
return toc;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -104,6 +104,57 @@ export class Table {
|
|||
this.property.cellMargins.bottom = { val: v, type: t };
|
||||
return this;
|
||||
}
|
||||
|
||||
build() {
|
||||
let table = wasm.createTable();
|
||||
this.rows.forEach((r) => {
|
||||
let row = wasm.createTableRow();
|
||||
r.cells.forEach((c) => {
|
||||
const cell = c.build();
|
||||
row = row.add_cell(cell);
|
||||
});
|
||||
|
||||
if (r.height) {
|
||||
row = row.row_height(r.height);
|
||||
}
|
||||
|
||||
if (r.del) {
|
||||
row = row.delete(r.del.author, r.del.date);
|
||||
}
|
||||
|
||||
if (r.ins) {
|
||||
row = row.insert(r.ins.author, r.ins.date);
|
||||
}
|
||||
|
||||
if (r.hRule) {
|
||||
switch (r.hRule) {
|
||||
case "auto": {
|
||||
row = row.height_rule(wasm.HeightRule.Auto);
|
||||
break;
|
||||
}
|
||||
case "atLeast": {
|
||||
row = row.height_rule(wasm.HeightRule.AtLeast);
|
||||
break;
|
||||
}
|
||||
case "exact": {
|
||||
row = row.height_rule(wasm.HeightRule.Exact);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
table = table.add_row(row);
|
||||
});
|
||||
|
||||
table = table.set_grid(new Uint32Array(this.grid));
|
||||
|
||||
if (this.property.styleId) {
|
||||
table = table.style(this.property.styleId);
|
||||
}
|
||||
|
||||
table = setTableProperty(table, this.property);
|
||||
|
||||
return table;
|
||||
}
|
||||
}
|
||||
|
||||
export const convertWidthType = (t: string) => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "docx-wasm",
|
||||
"version": "0.0.276-rc38",
|
||||
"version": "0.0.276-rc39",
|
||||
"main": "dist/node/index.js",
|
||||
"browser": "dist/web/index.js",
|
||||
"author": "bokuweb <bokuweb12@gmail.com>",
|
||||
|
|
|
@ -11,6 +11,11 @@ pub fn create_table_of_contents() -> TableOfContents {
|
|||
TableOfContents(docx_rs::TableOfContents::new())
|
||||
}
|
||||
|
||||
#[wasm_bindgen(js_name = createTableOfContentsWithInstrText)]
|
||||
pub fn create_table_of_contents_with_instr_text(s: &str) -> TableOfContents {
|
||||
TableOfContents(docx_rs::TableOfContents::with_instr_text(s))
|
||||
}
|
||||
|
||||
impl TableOfContents {
|
||||
pub fn take(self) -> docx_rs::TableOfContents {
|
||||
self.0
|
||||
|
@ -61,4 +66,24 @@ impl TableOfContents {
|
|||
self.0.dirty = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_before_paragraph(mut self, p: Paragraph) -> Self {
|
||||
self.0 = self.0.add_before_paragraph(p.take());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_after_paragraph(mut self, p: Paragraph) -> Self {
|
||||
self.0 = self.0.add_after_paragraph(p.take());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_before_table(mut self, t: Table) -> Self {
|
||||
self.0 = self.0.add_before_table(t.take());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_after_table(mut self, t: Table) -> Self {
|
||||
self.0 = self.0.add_after_table(t.take());
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151916,6 +151916,27 @@ Object {
|
|||
}
|
||||
`;
|
||||
|
||||
exports[`writer should write ToC with instrText 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 ToC with instrText 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:sdt><w:sdtPr><w:rPr /><w:alias w:val=\\"Table of contents\\" />
|
||||
</w:sdtPr><w:sdtContent><w:p w14:paraId=\\"00000001\\"><w:pPr><w:rPr /></w:pPr><w:r><w:rPr /><w:t xml:space=\\"preserve\\">Before contents</w:t></w:r></w:p><w:p w14:paraId=\\"00000001\\"><w:pPr><w:rPr /></w:pPr><w:r><w:rPr /><w:fldChar w:fldCharType=\\"begin\\" w:dirty=\\"true\\" /><w:instrText>TOC \\\\u</w:instrText><w:fldChar w:fldCharType=\\"separate\\" w:dirty=\\"false\\" /></w:r></w:p><w:p w14:paraId=\\"00000002\\"><w:pPr><w:rPr /></w:pPr><w:r><w:rPr /><w:fldChar w:fldCharType=\\"end\\" w:dirty=\\"false\\" /></w:r></w:p><w:p w14:paraId=\\"00000002\\"><w:pPr><w:rPr /></w:pPr><w:r><w:rPr /><w:t xml:space=\\"preserve\\">After contents</w:t></w:r></w:p></w:sdtContent>
|
||||
</w:sdt><w:p w14:paraId=\\"00000003\\"><w:pPr><w:rPr /><w:pStyle w:val=\\"Heading1\\" /><w:pageBreakBefore />
|
||||
</w:pPr><w:r><w:rPr /><w:t xml:space=\\"preserve\\">Hello!!</w:t></w:r></w:p><w:p w14:paraId=\\"00000004\\"><w:pPr><w:rPr /><w:pStyle w:val=\\"Heading2\\" /><w:pageBreakBefore />
|
||||
</w:pPr><w:r><w:rPr /><w:t xml:space=\\"preserve\\">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:docGrid w:type=\\"lines\\" w:linePitch=\\"360\\" /></w:sectPr></w:body>
|
||||
</w:document>"
|
||||
`;
|
||||
|
||||
exports[`writer should write ToC with items 1`] = `
|
||||
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
|
||||
<Relationships xmlns=\\"http://schemas.openxmlformats.org/package/2006/relationships\\">
|
||||
|
@ -152780,7 +152801,7 @@ exports[`writer should write paragraph delete 1`] = `
|
|||
exports[`writer should write paragraph delete 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:del w:id=\\"0\\" w:author=\\"bokuweb\\" w:date=\\"2021-12-23T18:16:00Z\\" /></w:rPr><w:numPr><w:numId w:val=\\"1\\" /><w:ilvl w:val=\\"0\\" /></w:numPr></w:pPr><w:r><w:rPr /><w:t xml:space=\\"preserve\\">Hello world!!</w:t></w:r></w:p><w:p w14:paraId=\\"00000002\\"><w:pPr><w:rPr /><w:numPr><w:numId w:val=\\"1\\" /><w:ilvl w:val=\\"0\\" /></w:numPr></w:pPr><w:r><w:rPr /><w:t xml:space=\\"preserve\\">Foo</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:docGrid w:type=\\"lines\\" w:linePitch=\\"360\\" /></w:sectPr></w:body>
|
||||
<w:body><w:p w14:paraId=\\"00000003\\"><w:pPr><w:rPr><w:del w:id=\\"0\\" w:author=\\"bokuweb\\" w:date=\\"2021-12-23T18:16:00Z\\" /></w:rPr><w:numPr><w:numId w:val=\\"1\\" /><w:ilvl w:val=\\"0\\" /></w:numPr></w:pPr><w:r><w:rPr /><w:t xml:space=\\"preserve\\">Hello world!!</w:t></w:r></w:p><w:p w14:paraId=\\"00000004\\"><w:pPr><w:rPr /><w:numPr><w:numId w:val=\\"1\\" /><w:ilvl w:val=\\"0\\" /></w:numPr></w:pPr><w:r><w:rPr /><w:t xml:space=\\"preserve\\">Foo</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:docGrid w:type=\\"lines\\" w:linePitch=\\"360\\" /></w:sectPr></w:body>
|
||||
</w:document>"
|
||||
`;
|
||||
|
||||
|
|
|
@ -756,6 +756,45 @@ describe("writer", () => {
|
|||
}
|
||||
});
|
||||
|
||||
test("should write ToC with instrText", () => {
|
||||
const before = new w.Paragraph().addRun(
|
||||
new w.Run().addText("Before contents")
|
||||
);
|
||||
const after = new w.Paragraph().addRun(
|
||||
new w.Run().addText("After contents")
|
||||
);
|
||||
const p1 = new w.Paragraph()
|
||||
.addRun(new w.Run().addText("Hello!!"))
|
||||
.pageBreakBefore(true)
|
||||
.style("Heading1");
|
||||
const style1 = new w.Style("Heading1", "paragraph").name("Heading 1");
|
||||
const p2 = new w.Paragraph()
|
||||
.addRun(new w.Run().addText("World"))
|
||||
.pageBreakBefore(true)
|
||||
.style("Heading2");
|
||||
const style2 = new w.Style("Heading2", "paragraph").name("Heading 2");
|
||||
const buffer = new w.Docx()
|
||||
.addTableOfContents(
|
||||
new w.TableOfContents(`TOC \o "1-3" \h \z \\u`)
|
||||
.alias("Table of contents")
|
||||
.addBeforeParagraph(before)
|
||||
.addAfterParagraph(after)
|
||||
.dirty()
|
||||
)
|
||||
.addParagraph(p1)
|
||||
.addParagraph(p2)
|
||||
.addStyle(style1)
|
||||
.addStyle(style2)
|
||||
.build();
|
||||
writeFileSync("../output/js/toc_with_instr_text.docx", buffer);
|
||||
const z = new Zip(Buffer.from(buffer));
|
||||
for (const e of z.getEntries()) {
|
||||
if (e.entryName.match(/document.xml/)) {
|
||||
expect(z.readAsText(e)).toMatchSnapshot();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("should write paragraph delete", () => {
|
||||
const p1 = new w.Paragraph()
|
||||
.addRun(new w.Run().addText("Hello world!!"))
|
||||
|
|
Loading…
Reference in New Issue