/
properties.ts
227 lines (190 loc) · 8.24 KB
/
properties.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
// http://officeopenxml.com/WPparagraphProperties.php
// https://c-rex.net/projects/samples/ooxml/e1/Part4/OOXML_P4_DOCX_suppressLineNumbers_topic_ID0ECJAO.html
/* eslint-disable functional/immutable-data */
import { IContext, IgnoreIfEmptyXmlComponent, IXmlableObject, OnOffElement, XmlComponent } from "@file/xml-components";
import { DocumentWrapper } from "../document-wrapper";
import { IShadingAttributesProperties, Shading } from "../shading";
import { Alignment, AlignmentType } from "./formatting/alignment";
import { Border, IBordersOptions, ThematicBreak } from "./formatting/border";
import { PageBreakBefore } from "./formatting/break";
import { IIndentAttributesProperties, Indent } from "./formatting/indent";
import { ISpacingProperties, Spacing } from "./formatting/spacing";
import { HeadingLevel, Style } from "./formatting/style";
import { TabStop, TabStopDefinition, TabStopType } from "./formatting/tab-stop";
import { NumberProperties } from "./formatting/unordered-list";
import { WordWrap } from "./formatting/word-wrap";
import { createFrameProperties, IFrameOptions } from "./frame/frame-properties";
import { OutlineLevel } from "./links";
import { IRunOptions, RunProperties } from ".";
export interface ILevelParagraphStylePropertiesOptions {
readonly alignment?: (typeof AlignmentType)[keyof typeof AlignmentType];
readonly thematicBreak?: boolean;
readonly contextualSpacing?: boolean;
readonly rightTabStop?: number;
readonly leftTabStop?: number;
readonly indent?: IIndentAttributesProperties;
readonly spacing?: ISpacingProperties;
/**
* Specifies that the paragraph (or at least part of it) should be rendered on the same page as the next paragraph when possible. If multiple paragraphs are to be kept together but they exceed a page, then the set of paragraphs begin on a new page and page breaks are used thereafter as needed.
*/
readonly keepNext?: boolean;
/**
* Specifies that all lines of the paragraph are to be kept on a single page when possible.
*/
readonly keepLines?: boolean;
readonly outlineLevel?: number;
}
export interface IParagraphStylePropertiesOptions extends ILevelParagraphStylePropertiesOptions {
readonly numbering?: {
readonly reference: string;
readonly level: number;
readonly instance?: number;
readonly custom?: boolean;
};
}
export interface IParagraphPropertiesOptions extends IParagraphStylePropertiesOptions {
readonly border?: IBordersOptions;
readonly heading?: (typeof HeadingLevel)[keyof typeof HeadingLevel];
readonly bidirectional?: boolean;
readonly pageBreakBefore?: boolean;
readonly tabStops?: readonly TabStopDefinition[];
readonly style?: string;
readonly bullet?: {
readonly level: number;
};
readonly shading?: IShadingAttributesProperties;
readonly widowControl?: boolean;
readonly frame?: IFrameOptions;
readonly suppressLineNumbers?: boolean;
readonly wordWrap?: boolean;
readonly overflowPunctuation?: boolean;
readonly scale?: number;
/**
* This element specifies whether inter-character spacing shall automatically be adjusted between regions of numbers and regions of East Asian text in the current paragraph. These regions shall be determined by the Unicode character values of the text content within the paragraph.
* This only works in Microsoft Word. It is not part of the ECMA-376 OOXML standard.
*/
readonly autoSpaceEastAsianText?: boolean;
/**
* Reference: ECMA-376, 3rd Edition (June, 2011), Fundamentals and Markup Language Reference § 17.3.1.29.
*/
readonly run?: IRunOptions;
}
export class ParagraphProperties extends IgnoreIfEmptyXmlComponent {
// eslint-disable-next-line functional/prefer-readonly-type
private readonly numberingReferences: { readonly reference: string; readonly instance: number }[] = [];
public constructor(options?: IParagraphPropertiesOptions) {
super("w:pPr");
if (!options) {
return this;
}
if (options.heading) {
this.push(new Style(options.heading));
}
if (options.bullet) {
this.push(new Style("ListParagraph"));
}
if (options.numbering) {
if (!options.style && !options.heading) {
if (!options.numbering.custom) {
this.push(new Style("ListParagraph"));
}
}
}
if (options.style) {
this.push(new Style(options.style));
}
if (options.keepNext !== undefined) {
this.push(new OnOffElement("w:keepNext", options.keepNext));
}
if (options.keepLines !== undefined) {
this.push(new OnOffElement("w:keepLines", options.keepLines));
}
if (options.pageBreakBefore) {
this.push(new PageBreakBefore());
}
if (options.frame) {
this.push(createFrameProperties(options.frame));
}
if (options.widowControl !== undefined) {
this.push(new OnOffElement("w:widowControl", options.widowControl));
}
if (options.bullet) {
this.push(new NumberProperties(1, options.bullet.level));
}
if (options.numbering) {
this.numberingReferences.push({
reference: options.numbering.reference,
instance: options.numbering.instance ?? 0,
});
this.push(new NumberProperties(`${options.numbering.reference}-${options.numbering.instance ?? 0}`, options.numbering.level));
}
if (options.border) {
this.push(new Border(options.border));
}
if (options.thematicBreak) {
this.push(new ThematicBreak());
}
if (options.shading) {
this.push(new Shading(options.shading));
}
if (options.wordWrap) {
this.push(new WordWrap());
}
if (options.overflowPunctuation) {
this.push(new OnOffElement("w:overflowPunct", options.overflowPunctuation));
}
/**
* FIX: Multitab support for Libre Writer
* Ensure there is only one w:tabs tag with multiple w:tab
*/
const tabDefinitions: readonly TabStopDefinition[] = [
...(options.rightTabStop !== undefined ? [{ type: TabStopType.RIGHT, position: options.rightTabStop }] : []),
...(options.tabStops ? options.tabStops : []),
...(options.leftTabStop !== undefined ? [{ type: TabStopType.LEFT, position: options.leftTabStop }] : []),
];
if (tabDefinitions.length > 0) {
this.push(new TabStop(tabDefinitions));
}
/**
* FIX - END
*/
if (options.bidirectional !== undefined) {
this.push(new OnOffElement("w:bidi", options.bidirectional));
}
if (options.spacing) {
this.push(new Spacing(options.spacing));
}
if (options.indent) {
this.push(new Indent(options.indent));
}
if (options.contextualSpacing !== undefined) {
this.push(new OnOffElement("w:contextualSpacing", options.contextualSpacing));
}
if (options.alignment) {
this.push(new Alignment(options.alignment));
}
if (options.outlineLevel !== undefined) {
this.push(new OutlineLevel(options.outlineLevel));
}
if (options.suppressLineNumbers !== undefined) {
this.push(new OnOffElement("w:suppressLineNumbers", options.suppressLineNumbers));
}
if (options.autoSpaceEastAsianText !== undefined) {
this.push(new OnOffElement("w:autoSpaceDN", options.autoSpaceEastAsianText));
}
if (options.run) {
this.push(new RunProperties(options.run));
}
}
public push(item: XmlComponent): void {
this.root.push(item);
}
public prepForXml(context: IContext): IXmlableObject | undefined {
if (context.viewWrapper instanceof DocumentWrapper) {
for (const reference of this.numberingReferences) {
context.file.Numbering.createConcreteNumberingInstance(reference.reference, reference.instance);
}
}
return super.prepForXml(context);
}
}