diff --git a/demo/55-math.ts b/demo/55-math.ts
new file mode 100644
index 0000000000..2a240986d0
--- /dev/null
+++ b/demo/55-math.ts
@@ -0,0 +1,294 @@
+// Simple example to add text to a document
+// Import from 'docx' rather than '../build' if you install from npm
+import * as fs from "fs";
+import {
+ Document,
+ Math,
+ MathAngledBrackets,
+ MathCurlyBrackets,
+ MathFraction,
+ MathFunction,
+ MathPreSubSuperScript,
+ MathRadical,
+ MathRoundBrackets,
+ MathRun,
+ MathSquareBrackets,
+ MathSubScript,
+ MathSubSuperScript,
+ MathSum,
+ MathSuperScript,
+ Packer,
+ Paragraph,
+ TextRun,
+} from "../build";
+
+const doc = new Document();
+
+doc.addSection({
+ properties: {},
+ children: [
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathRun("2+2"),
+ new MathFraction({
+ numerator: [new MathRun("hi")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+ }),
+ new TextRun({
+ text: "Foo Bar",
+ bold: true,
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathFraction({
+ numerator: [
+ new MathRun("1"),
+ new MathRadical({
+ children: [new MathRun("2")],
+ }),
+ ],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathSum({
+ children: [new MathRun("test")],
+ }),
+ new MathSum({
+ children: [
+ new MathSuperScript({
+ children: [new MathRun("e")],
+ superScript: [new MathRun("2")],
+ }),
+ ],
+ subScript: [new MathRun("i")],
+ }),
+ new MathSum({
+ children: [
+ new MathRadical({
+ children: [new MathRun("i")],
+ }),
+ ],
+ subScript: [new MathRun("i")],
+ superScript: [new MathRun("10")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathSuperScript({
+ children: [new MathRun("test")],
+ superScript: [new MathRun("hello")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathSubScript({
+ children: [new MathRun("test")],
+ subScript: [new MathRun("hello")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathSubScript({
+ children: [new MathRun("x")],
+ subScript: [
+ new MathSuperScript({
+ children: [new MathRun("y")],
+ superScript: [new MathRun("2")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathSubSuperScript({
+ children: [new MathRun("test")],
+ superScript: [new MathRun("hello")],
+ subScript: [new MathRun("world")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathPreSubSuperScript({
+ children: [new MathRun("test")],
+ superScript: [new MathRun("hello")],
+ subScript: [new MathRun("world")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathSubScript({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+ subScript: [new MathRun("4")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathSubScript({
+ children: [
+ new MathRadical({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+ degree: [new MathRun("4")],
+ }),
+ ],
+ subScript: [new MathRun("x")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathRadical({
+ children: [new MathRun("4")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathFunction({
+ name: [
+ new MathSuperScript({
+ children: [new MathRun("cos")],
+ superScript: [new MathRun("-1")],
+ }),
+ ],
+ children: [new MathRun("100")],
+ }),
+ new MathRun("×"),
+ new MathFunction({
+ name: [new MathRun("sin")],
+ children: [new MathRun("360")],
+ }),
+ new MathRun("= x"),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathRoundBrackets({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+ }),
+ new MathSquareBrackets({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+ }),
+ new MathCurlyBrackets({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+ }),
+ new MathAngledBrackets({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ ],
+ }),
+ new Paragraph({
+ children: [
+ new Math({
+ children: [
+ new MathFraction({
+ numerator: [
+ new MathRadical({
+ children: [new MathRun("4")],
+ }),
+ ],
+ denominator: [new MathRun("2a")],
+ }),
+ ],
+ }),
+ ],
+ }),
+ ],
+});
+
+Packer.toBuffer(doc).then((buffer) => {
+ fs.writeFileSync("My Document.docx", buffer);
+});
diff --git a/docs/_sidebar.md b/docs/_sidebar.md
index 5d2ba31551..bcdb03c55f 100644
--- a/docs/_sidebar.md
+++ b/docs/_sidebar.md
@@ -21,6 +21,7 @@
* [Table of Contents](usage/table-of-contents.md)
* [Page Numbers](usage/page-numbers.md)
* [Change Tracking](usage/change-tracking.md)
+ * [Math](usage/math.md)
* Styling
* [Styling with JS](usage/styling-with-js.md)
* [Styling with XML](usage/styling-with-xml.md)
diff --git a/docs/images/math-example.png b/docs/images/math-example.png
new file mode 100644
index 0000000000..c92f8806f9
Binary files /dev/null and b/docs/images/math-example.png differ
diff --git a/docs/usage/math.md b/docs/usage/math.md
new file mode 100644
index 0000000000..1e8ab4f894
--- /dev/null
+++ b/docs/usage/math.md
@@ -0,0 +1,265 @@
+# Math
+
+!> Math requires an understanding of [Sections](usage/sections.md) and [Paragraphs](usage/paragraph.md).
+
+## Intro
+
+1. To add math, create a `Math` object
+2. Add `MathComponents` inside `Math`
+3. `MathComponents` can have nested `MathComponents` inside. e.g. A fraction where the numerator is a square root, and the demoninator as another fraction. More on `MathComponents` below
+4. Make sure to add the `Math` object inside a `Paragraph`
+
+## Example
+
+```ts
+new Math({
+ children: [
+ new MathRun("2+2"),
+ new MathFraction({
+ numerator: [new MathRun("hi")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+}),
+```
+
+This will produce:
+
+
+
+
+
+## Math Components
+
+`MathComponents` are the unit sized building blocks of an equation in `docx`. A `MathComponent` takes in more nested `MathComponents` until you reach `MathRun`, which has no children. `MathRun` is similar to a [TextRun](usage/text.md).
+
+### Math Run
+
+`MathRun` is the most basic `MathComponent`.
+
+#### Example
+
+```ts
+new MathRun("2+2");
+```
+
+```ts
+new MathRun("hello");
+```
+
+An example of it being used inside `Math`:
+
+```ts
+new Math({
+ children: [
+ new MathRun("2"),
+ new MathRun("+"),
+ new MathRun("2"),
+ ],
+}),
+```
+
+### Math Fraction
+
+`MathFractions` require a `numerator` and a `demoninator`, which are both a list of `MathComponents`
+
+#### Example
+
+```ts
+new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+}),
+```
+
+```ts
+new MathFraction({
+ numerator: [
+ new MathRun("1"),
+ new MathRadical({
+ children: [new MathRun("2")],
+ }),
+ ],
+ denominator: [new MathRun("2")],
+}),
+```
+
+An example of it being used inside `Math`:
+
+```ts
+new Math({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ new MathText("+"),
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ new MathText("= 1"),
+ ],
+}),
+```
+
+### Sum
+
+A `MathComponent` for `Σ`. It can take a `superScript` and/or `subScript` as arguments to add `MathComponents` (usually limits) on the top and bottom
+
+```ts
+new MathSum({
+ children: [new MathRun("i")],
+}),
+```
+
+```ts
+new MathSum({
+ children: [
+ new MathSuperScript({
+ children: [new MathRun("e")],
+ superScript: [new MathRun("2")],
+ })
+ ],
+ subScript: [new MathRun("i")],
+ superScript: [new MathRun("10")],
+}),
+```
+
+### Radicals
+
+A `MathComponent` for the `√` symbol. Examples include, square root, cube root etc. There is an optional `degree` parameter to specify the number of times the radicand is multiplied by itself. For example, `3` for cube root.
+
+```ts
+new MathRadical({
+ children: [new MathRun("2")],
+}),
+```
+
+Cube root example:
+
+```ts
+new MathRadical({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ new MathRun('+ 1'),
+ ],
+ degree: [new MathRun("3")],
+}),
+```
+
+### Super Script
+
+`MathSuperScripts` are the little numbers written to the top right of numbers or variables. It means the exponent or power if written by itself with the number or variable.
+
+```ts
+new MathSuperScript({
+ children: [new MathRun("x")],
+ superScript: [new MathRun("2")],
+}),
+```
+
+An example with cosine:
+
+```ts
+new MathSuperScript({
+ children: [new MathRun("cos")],
+ superScript: [new MathRun("-1")],
+}),
+```
+
+### Sub Script
+
+`MathSubScripts` are similar to `MathSuperScripts`, except the little number is written below.
+
+```ts
+new MathSubScript({
+ children: [new MathRun("F")],
+ subScript: [new MathRun("n-1")],
+}),
+```
+
+### Sub-Super Script
+
+`MathSubSuperScripts` are a combination of both `MathSuperScript` and `MathSubScript`.
+
+```ts
+new MathSubSuperScript({
+ children: [new MathRun("test")],
+ superScript: [new MathRun("hello")],
+ subScript: [new MathRun("world")],
+}),
+```
+
+### Function
+
+`MathFunctions` are a way of describing what happens to an input variable, in order to get the output result. It takes a `name` parameter to specify the name of the function.
+
+```ts
+new MathFunction({
+ name: [
+ new MathSuperScript({
+ children: [new MathRun("cos")],
+ superScript: [new MathRun("-1")],
+ }),
+ ],
+ children: [new MathRun("100")],
+}),
+```
+
+### Brackets
+
+#### Square brackets
+
+```ts
+new MathSquareBrackets({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+}),
+```
+
+#### Round brackets
+
+```ts
+new MathRoundBrackets({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+}),
+```
+
+#### Curly brackets
+
+```ts
+new MathCurlyBrackets({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+}),
+```
+
+#### Angled brackets
+
+```ts
+new MathAngledBrackets({
+ children: [
+ new MathFraction({
+ numerator: [new MathRun("1")],
+ denominator: [new MathRun("2")],
+ }),
+ ],
+}),
+```
diff --git a/package-lock.json b/package-lock.json
index d73f9f5d71..7d28a68d7d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1088,7 +1088,7 @@
},
"awesome-typescript-loader": {
"version": "3.5.0",
- "resolved": "http://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-3.5.0.tgz",
+ "resolved": "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-3.5.0.tgz",
"integrity": "sha512-qzgm9SEvodVkSi9QY7Me1/rujg+YBNMjayNSAyzNghwTEez++gXoPCwMvpbHRG7wrOkDCiF6dquvv9ESmUBAuw==",
"dev": true,
"requires": {
@@ -1665,7 +1665,7 @@
},
"chai": {
"version": "3.5.0",
- "resolved": "http://registry.npmjs.org/chai/-/chai-3.5.0.tgz",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz",
"integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=",
"dev": true,
"requires": {
@@ -2153,7 +2153,7 @@
},
"deep-eql": {
"version": "0.1.3",
- "resolved": "http://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz",
"integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=",
"dev": true,
"requires": {
@@ -4373,7 +4373,7 @@
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=",
"dev": true
},
"is-ci": {
@@ -4843,7 +4843,7 @@
},
"jsesc": {
"version": "1.3.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+ "resolved": "http://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
"dev": true
},
@@ -5098,7 +5098,7 @@
},
"load-json-file": {
"version": "1.1.0",
- "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true,
"requires": {
@@ -5395,7 +5395,7 @@
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
- "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
@@ -5585,7 +5585,7 @@
},
"ncp": {
"version": "1.0.1",
- "resolved": "http://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz",
+ "resolved": "https://registry.npmjs.org/ncp/-/ncp-1.0.1.tgz",
"integrity": "sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY=",
"dev": true
},
@@ -5603,7 +5603,7 @@
},
"next-tick": {
"version": "1.0.0",
- "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true
},
@@ -7116,7 +7116,7 @@
},
"safe-regex": {
"version": "1.1.0",
- "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"dev": true,
"requires": {
@@ -7719,7 +7719,7 @@
},
"strip-eof": {
"version": "1.0.0",
- "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+ "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=",
"dev": true
},
@@ -7996,10 +7996,13 @@
}
},
"tslint-immutable": {
- "version": "4.9.1",
- "resolved": "https://registry.npmjs.org/tslint-immutable/-/tslint-immutable-4.9.1.tgz",
- "integrity": "sha512-iIFCq08H4YyNIX0bV5N6fGQtAmjc4OQZKQCgBP5WHgQaITyGAHPVmAw+Yf7qe0zbRCvCDZdrdEC/191fLGFiww==",
- "dev": true
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/tslint-immutable/-/tslint-immutable-6.0.1.tgz",
+ "integrity": "sha512-3GQ6HffN64gLmT/N1YzyVMqyf6uBjMvhNaevK8B0K01/QC0OU5AQZrH4TjMHo1IdG3JpqsZvuRy9IW1LA3zjwA==",
+ "dev": true,
+ "requires": {
+ "tsutils": "^2.28.0 || ^3.0.0"
+ }
},
"tsutils": {
"version": "2.29.0",
@@ -8654,7 +8657,7 @@
},
"load-json-file": {
"version": "2.0.0",
- "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
"dev": true,
"requires": {
@@ -8855,7 +8858,7 @@
},
"winston": {
"version": "2.1.1",
- "resolved": "http://registry.npmjs.org/winston/-/winston-2.1.1.tgz",
+ "resolved": "https://registry.npmjs.org/winston/-/winston-2.1.1.tgz",
"integrity": "sha1-PJNJ0ZYgf9G9/51LxD73JRDjoS4=",
"dev": true,
"requires": {
diff --git a/package.json b/package.json
index 51e1b246c3..f9a27f0fcb 100644
--- a/package.json
+++ b/package.json
@@ -89,7 +89,7 @@
"sinon": "^9.0.2",
"ts-node": "^9.0.0",
"tslint": "^6.1.3",
- "tslint-immutable": "^4.9.0",
+ "tslint-immutable": "^6.0.1",
"typedoc": "^0.16.11",
"typescript": "2.9.2",
"webpack": "^3.10.0"
diff --git a/src/file/drawing/inline/inline.ts b/src/file/drawing/inline/inline.ts
index 7c40e7c3b3..bf83e36764 100644
--- a/src/file/drawing/inline/inline.ts
+++ b/src/file/drawing/inline/inline.ts
@@ -12,7 +12,7 @@ export class Inline extends XmlComponent {
private readonly extent: Extent;
private readonly graphic: Graphic;
- constructor(readonly mediaData: IMediaData, private readonly dimensions: IMediaDataDimensions) {
+ constructor(mediaData: IMediaData, private readonly dimensions: IMediaDataDimensions) {
super("wp:inline");
this.root.push(
diff --git a/src/file/paragraph/index.ts b/src/file/paragraph/index.ts
index 68a1b0b800..d68c1d7f03 100644
--- a/src/file/paragraph/index.ts
+++ b/src/file/paragraph/index.ts
@@ -3,3 +3,4 @@ export * from "./paragraph";
export * from "./properties";
export * from "./run";
export * from "./links";
+export * from "./math";
diff --git a/src/file/paragraph/math/brackets/index.ts b/src/file/paragraph/math/brackets/index.ts
new file mode 100644
index 0000000000..e6559cde29
--- /dev/null
+++ b/src/file/paragraph/math/brackets/index.ts
@@ -0,0 +1,4 @@
+export * from "./math-round-brackets";
+export * from "./math-square-brackets";
+export * from "./math-curly-brackets";
+export * from "./math-angled-brackets";
diff --git a/src/file/paragraph/math/brackets/math-angled-brackets.spec.ts b/src/file/paragraph/math/brackets/math-angled-brackets.spec.ts
new file mode 100644
index 0000000000..ccd73b192b
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-angled-brackets.spec.ts
@@ -0,0 +1,51 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathAngledBrackets } from "./math-angled-brackets";
+
+describe("MathAngledBrackets", () => {
+ describe("#constructor()", () => {
+ it("should create a MathAngledBrackets with correct root key", () => {
+ const mathAngledBrackets = new MathAngledBrackets({
+ children: [new MathRun("60")],
+ });
+
+ const tree = new Formatter().format(mathAngledBrackets);
+ expect(tree).to.deep.equal({
+ "m:d": [
+ {
+ "m:dPr": [
+ {
+ "m:begChr": {
+ _attr: {
+ "m:val": "〈",
+ },
+ },
+ },
+ {
+ "m:endChr": {
+ _attr: {
+ "m:val": "〉",
+ },
+ },
+ },
+ ],
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["60"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/brackets/math-angled-brackets.ts b/src/file/paragraph/math/brackets/math-angled-brackets.ts
new file mode 100644
index 0000000000..48fe0d415d
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-angled-brackets.ts
@@ -0,0 +1,20 @@
+// http://www.datypic.com/sc/ooxml/e-m_d-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+import { MathBase } from "../n-ary";
+import { MathBracketProperties } from "./math-bracket-properties";
+
+export class MathAngledBrackets extends XmlComponent {
+ constructor(options: { readonly children: MathComponent[] }) {
+ super("m:d");
+
+ this.root.push(
+ new MathBracketProperties({
+ beginningCharacter: "〈",
+ endingCharacter: "〉",
+ }),
+ );
+ this.root.push(new MathBase(options.children));
+ }
+}
diff --git a/src/file/paragraph/math/brackets/math-beginning-character.spec.ts b/src/file/paragraph/math/brackets/math-beginning-character.spec.ts
new file mode 100644
index 0000000000..bf9196c0a9
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-beginning-character.spec.ts
@@ -0,0 +1,22 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathBeginningCharacter } from "./math-beginning-character";
+
+describe("MathBeginningCharacter", () => {
+ describe("#constructor()", () => {
+ it("should create a MathBeginningCharacter with correct root key", () => {
+ const mathBeginningCharacter = new MathBeginningCharacter("[");
+
+ const tree = new Formatter().format(mathBeginningCharacter);
+ expect(tree).to.deep.equal({
+ "m:begChr": {
+ _attr: {
+ "m:val": "[",
+ },
+ },
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/brackets/math-beginning-character.ts b/src/file/paragraph/math/brackets/math-beginning-character.ts
new file mode 100644
index 0000000000..aa9e06d87a
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-beginning-character.ts
@@ -0,0 +1,14 @@
+// http://www.datypic.com/sc/ooxml/e-m_begChr-1.html
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+class MathBeginningCharacterAttributes extends XmlAttributeComponent<{ readonly character: string }> {
+ protected readonly xmlKeys = { character: "m:val" };
+}
+
+export class MathBeginningCharacter extends XmlComponent {
+ constructor(character: string) {
+ super("m:begChr");
+
+ this.root.push(new MathBeginningCharacterAttributes({ character }));
+ }
+}
diff --git a/src/file/paragraph/math/brackets/math-bracket-properties.spec.ts b/src/file/paragraph/math/brackets/math-bracket-properties.spec.ts
new file mode 100644
index 0000000000..d80976d8f6
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-bracket-properties.spec.ts
@@ -0,0 +1,45 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathBracketProperties } from "./math-bracket-properties";
+
+describe("MathBracketProperties", () => {
+ describe("#constructor()", () => {
+ it("should create a MathBracketProperties with correct root key", () => {
+ const mathBracketProperties = new MathBracketProperties();
+
+ const tree = new Formatter().format(mathBracketProperties);
+ expect(tree).to.deep.equal({
+ "m:dPr": {},
+ });
+ });
+
+ it("should create a MathBracketProperties with correct root key and add brackets", () => {
+ const mathBracketProperties = new MathBracketProperties({
+ beginningCharacter: "[",
+ endingCharacter: "]",
+ });
+
+ const tree = new Formatter().format(mathBracketProperties);
+ expect(tree).to.deep.equal({
+ "m:dPr": [
+ {
+ "m:begChr": {
+ _attr: {
+ "m:val": "[",
+ },
+ },
+ },
+ {
+ "m:endChr": {
+ _attr: {
+ "m:val": "]",
+ },
+ },
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/brackets/math-bracket-properties.ts b/src/file/paragraph/math/brackets/math-bracket-properties.ts
new file mode 100644
index 0000000000..5bba7bf935
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-bracket-properties.ts
@@ -0,0 +1,16 @@
+// http://www.datypic.com/sc/ooxml/e-m_dPr-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathBeginningCharacter } from "./math-beginning-character";
+import { MathEndingCharacter } from "./math-ending-char";
+
+export class MathBracketProperties extends XmlComponent {
+ constructor(options?: { readonly beginningCharacter: string; readonly endingCharacter: string }) {
+ super("m:dPr");
+
+ if (!!options) {
+ this.root.push(new MathBeginningCharacter(options.beginningCharacter));
+ this.root.push(new MathEndingCharacter(options.endingCharacter));
+ }
+ }
+}
diff --git a/src/file/paragraph/math/brackets/math-curly-brackets.spec.ts b/src/file/paragraph/math/brackets/math-curly-brackets.spec.ts
new file mode 100644
index 0000000000..d6defd57ef
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-curly-brackets.spec.ts
@@ -0,0 +1,51 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathCurlyBrackets } from "./math-curly-brackets";
+
+describe("MathCurlyBrackets", () => {
+ describe("#constructor()", () => {
+ it("should create a MathCurlyBrackets with correct root key", () => {
+ const mathCurlyBrackets = new MathCurlyBrackets({
+ children: [new MathRun("60")],
+ });
+
+ const tree = new Formatter().format(mathCurlyBrackets);
+ expect(tree).to.deep.equal({
+ "m:d": [
+ {
+ "m:dPr": [
+ {
+ "m:begChr": {
+ _attr: {
+ "m:val": "{",
+ },
+ },
+ },
+ {
+ "m:endChr": {
+ _attr: {
+ "m:val": "}",
+ },
+ },
+ },
+ ],
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["60"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/brackets/math-curly-brackets.ts b/src/file/paragraph/math/brackets/math-curly-brackets.ts
new file mode 100644
index 0000000000..ccce71e6a7
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-curly-brackets.ts
@@ -0,0 +1,20 @@
+// http://www.datypic.com/sc/ooxml/e-m_d-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+import { MathBase } from "../n-ary";
+import { MathBracketProperties } from "./math-bracket-properties";
+
+export class MathCurlyBrackets extends XmlComponent {
+ constructor(options: { readonly children: MathComponent[] }) {
+ super("m:d");
+
+ this.root.push(
+ new MathBracketProperties({
+ beginningCharacter: "{",
+ endingCharacter: "}",
+ }),
+ );
+ this.root.push(new MathBase(options.children));
+ }
+}
diff --git a/src/file/paragraph/math/brackets/math-ending-char.ts b/src/file/paragraph/math/brackets/math-ending-char.ts
new file mode 100644
index 0000000000..86d0a0a58c
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-ending-char.ts
@@ -0,0 +1,14 @@
+// http://www.datypic.com/sc/ooxml/e-m_endChr-1.html
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+class MathEndingCharacterAttributes extends XmlAttributeComponent<{ readonly character: string }> {
+ protected readonly xmlKeys = { character: "m:val" };
+}
+
+export class MathEndingCharacter extends XmlComponent {
+ constructor(character: string) {
+ super("m:endChr");
+
+ this.root.push(new MathEndingCharacterAttributes({ character }));
+ }
+}
diff --git a/src/file/paragraph/math/brackets/math-ending-character.spec.ts b/src/file/paragraph/math/brackets/math-ending-character.spec.ts
new file mode 100644
index 0000000000..ba28ac7840
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-ending-character.spec.ts
@@ -0,0 +1,22 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathEndingCharacter } from "./math-ending-char";
+
+describe("MathEndingCharacter", () => {
+ describe("#constructor()", () => {
+ it("should create a MathEndingCharacter with correct root key", () => {
+ const mathEndingCharacter = new MathEndingCharacter("]");
+
+ const tree = new Formatter().format(mathEndingCharacter);
+ expect(tree).to.deep.equal({
+ "m:endChr": {
+ _attr: {
+ "m:val": "]",
+ },
+ },
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/brackets/math-round-brackets.spec.ts b/src/file/paragraph/math/brackets/math-round-brackets.spec.ts
new file mode 100644
index 0000000000..5138e9d085
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-round-brackets.spec.ts
@@ -0,0 +1,36 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathRoundBrackets } from "./math-round-brackets";
+
+describe("MathRoundBrackets", () => {
+ describe("#constructor()", () => {
+ it("should create a MathRoundBrackets with correct root key", () => {
+ const mathRoundBrackets = new MathRoundBrackets({
+ children: [new MathRun("60")],
+ });
+
+ const tree = new Formatter().format(mathRoundBrackets);
+ expect(tree).to.deep.equal({
+ "m:d": [
+ {
+ "m:dPr": {},
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["60"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/brackets/math-round-brackets.ts b/src/file/paragraph/math/brackets/math-round-brackets.ts
new file mode 100644
index 0000000000..6fe60318a4
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-round-brackets.ts
@@ -0,0 +1,15 @@
+// http://www.datypic.com/sc/ooxml/e-m_d-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+import { MathBase } from "../n-ary";
+import { MathBracketProperties } from "./math-bracket-properties";
+
+export class MathRoundBrackets extends XmlComponent {
+ constructor(options: { readonly children: MathComponent[] }) {
+ super("m:d");
+
+ this.root.push(new MathBracketProperties());
+ this.root.push(new MathBase(options.children));
+ }
+}
diff --git a/src/file/paragraph/math/brackets/math-square-brackets.spec.ts b/src/file/paragraph/math/brackets/math-square-brackets.spec.ts
new file mode 100644
index 0000000000..b0e2ec9e26
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-square-brackets.spec.ts
@@ -0,0 +1,51 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathSquareBrackets } from "./math-square-brackets";
+
+describe("MathSquareBrackets", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSquareBrackets with correct root key", () => {
+ const mathSquareBrackets = new MathSquareBrackets({
+ children: [new MathRun("60")],
+ });
+
+ const tree = new Formatter().format(mathSquareBrackets);
+ expect(tree).to.deep.equal({
+ "m:d": [
+ {
+ "m:dPr": [
+ {
+ "m:begChr": {
+ _attr: {
+ "m:val": "[",
+ },
+ },
+ },
+ {
+ "m:endChr": {
+ _attr: {
+ "m:val": "]",
+ },
+ },
+ },
+ ],
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["60"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/brackets/math-square-brackets.ts b/src/file/paragraph/math/brackets/math-square-brackets.ts
new file mode 100644
index 0000000000..fdfe88a004
--- /dev/null
+++ b/src/file/paragraph/math/brackets/math-square-brackets.ts
@@ -0,0 +1,20 @@
+// http://www.datypic.com/sc/ooxml/e-m_d-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+import { MathBase } from "../n-ary";
+import { MathBracketProperties } from "./math-bracket-properties";
+
+export class MathSquareBrackets extends XmlComponent {
+ constructor(options: { readonly children: MathComponent[] }) {
+ super("m:d");
+
+ this.root.push(
+ new MathBracketProperties({
+ beginningCharacter: "[",
+ endingCharacter: "]",
+ }),
+ );
+ this.root.push(new MathBase(options.children));
+ }
+}
diff --git a/src/file/paragraph/math/fraction/index.ts b/src/file/paragraph/math/fraction/index.ts
new file mode 100644
index 0000000000..c8af438329
--- /dev/null
+++ b/src/file/paragraph/math/fraction/index.ts
@@ -0,0 +1,3 @@
+export * from "./math-fraction";
+export * from "./math-denominator";
+export * from "./math-numerator";
diff --git a/src/file/paragraph/math/fraction/math-denominator.spec.ts b/src/file/paragraph/math/fraction/math-denominator.spec.ts
new file mode 100644
index 0000000000..f2e7459e1e
--- /dev/null
+++ b/src/file/paragraph/math/fraction/math-denominator.spec.ts
@@ -0,0 +1,26 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathDenominator } from "./math-denominator";
+
+describe("MathDenominator", () => {
+ describe("#constructor()", () => {
+ it("should create a MathDenominator with correct root key", () => {
+ const mathDenominator = new MathDenominator([new MathRun("2+2")]);
+ const tree = new Formatter().format(mathDenominator);
+ expect(tree).to.deep.equal({
+ "m:den": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2+2"],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/fraction/math-denominator.ts b/src/file/paragraph/math/fraction/math-denominator.ts
new file mode 100644
index 0000000000..8df68bf4b0
--- /dev/null
+++ b/src/file/paragraph/math/fraction/math-denominator.ts
@@ -0,0 +1,13 @@
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+
+export class MathDenominator extends XmlComponent {
+ constructor(children: MathComponent[]) {
+ super("m:den");
+
+ for (const child of children) {
+ this.root.push(child);
+ }
+ }
+}
diff --git a/src/file/paragraph/math/fraction/math-fraction.spec.ts b/src/file/paragraph/math/fraction/math-fraction.spec.ts
new file mode 100644
index 0000000000..51cac646bf
--- /dev/null
+++ b/src/file/paragraph/math/fraction/math-fraction.spec.ts
@@ -0,0 +1,44 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathFraction } from "./math-fraction";
+
+describe("MathFraction", () => {
+ describe("#constructor()", () => {
+ it("should create a MathFraction with correct root key", () => {
+ const mathFraction = new MathFraction({
+ numerator: [new MathRun("2")],
+ denominator: [new MathRun("2")],
+ });
+ const tree = new Formatter().format(mathFraction);
+ expect(tree).to.deep.equal({
+ "m:f": [
+ {
+ "m:num": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:den": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/fraction/math-fraction.ts b/src/file/paragraph/math/fraction/math-fraction.ts
new file mode 100644
index 0000000000..84a803a872
--- /dev/null
+++ b/src/file/paragraph/math/fraction/math-fraction.ts
@@ -0,0 +1,19 @@
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+import { MathDenominator } from "./math-denominator";
+import { MathNumerator } from "./math-numerator";
+
+export interface IMathFractionOptions {
+ readonly numerator: MathComponent[];
+ readonly denominator: MathComponent[];
+}
+
+export class MathFraction extends XmlComponent {
+ constructor(options: IMathFractionOptions) {
+ super("m:f");
+
+ this.root.push(new MathNumerator(options.numerator));
+ this.root.push(new MathDenominator(options.denominator));
+ }
+}
diff --git a/src/file/paragraph/math/fraction/math-numerator.spec.ts b/src/file/paragraph/math/fraction/math-numerator.spec.ts
new file mode 100644
index 0000000000..e3aaf35c0e
--- /dev/null
+++ b/src/file/paragraph/math/fraction/math-numerator.spec.ts
@@ -0,0 +1,26 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathNumerator } from "./math-numerator";
+
+describe("MathNumerator", () => {
+ describe("#constructor()", () => {
+ it("should create a MathNumerator with correct root key", () => {
+ const mathNumerator = new MathNumerator([new MathRun("2+2")]);
+ const tree = new Formatter().format(mathNumerator);
+ expect(tree).to.deep.equal({
+ "m:num": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2+2"],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/fraction/math-numerator.ts b/src/file/paragraph/math/fraction/math-numerator.ts
new file mode 100644
index 0000000000..b7a49d9a75
--- /dev/null
+++ b/src/file/paragraph/math/fraction/math-numerator.ts
@@ -0,0 +1,13 @@
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+
+export class MathNumerator extends XmlComponent {
+ constructor(children: MathComponent[]) {
+ super("m:num");
+
+ for (const child of children) {
+ this.root.push(child);
+ }
+ }
+}
diff --git a/src/file/paragraph/math/function/index.ts b/src/file/paragraph/math/function/index.ts
new file mode 100644
index 0000000000..58243c2710
--- /dev/null
+++ b/src/file/paragraph/math/function/index.ts
@@ -0,0 +1,3 @@
+export * from "./math-function";
+export * from "./math-function-name";
+export * from "./math-function-properties";
diff --git a/src/file/paragraph/math/function/math-function-name.spec.ts b/src/file/paragraph/math/function/math-function-name.spec.ts
new file mode 100644
index 0000000000..8a37ee998e
--- /dev/null
+++ b/src/file/paragraph/math/function/math-function-name.spec.ts
@@ -0,0 +1,27 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathFunctionName } from "./math-function-name";
+
+describe("MathFunctionName", () => {
+ describe("#constructor()", () => {
+ it("should create a MathFunctionName with correct root key", () => {
+ const mathFunctionName = new MathFunctionName([new MathRun("2")]);
+
+ const tree = new Formatter().format(mathFunctionName);
+ expect(tree).to.deep.equal({
+ "m:fName": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2"],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/function/math-function-name.ts b/src/file/paragraph/math/function/math-function-name.ts
new file mode 100644
index 0000000000..e58488dd28
--- /dev/null
+++ b/src/file/paragraph/math/function/math-function-name.ts
@@ -0,0 +1,13 @@
+// http://www.datypic.com/sc/ooxml/e-m_fName-1.html
+import { XmlComponent } from "file/xml-components";
+import { MathComponent } from "../math-component";
+
+export class MathFunctionName extends XmlComponent {
+ constructor(children: MathComponent[]) {
+ super("m:fName");
+
+ for (const child of children) {
+ this.root.push(child);
+ }
+ }
+}
diff --git a/src/file/paragraph/math/function/math-function-properties.spec.ts b/src/file/paragraph/math/function/math-function-properties.spec.ts
new file mode 100644
index 0000000000..63ec2e4f60
--- /dev/null
+++ b/src/file/paragraph/math/function/math-function-properties.spec.ts
@@ -0,0 +1,18 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathFunctionProperties } from "./math-function-properties";
+
+describe("MathFunctionProperties", () => {
+ describe("#constructor()", () => {
+ it("should create a MathFunctionProperties with correct root key", () => {
+ const mathFunctionProperties = new MathFunctionProperties();
+
+ const tree = new Formatter().format(mathFunctionProperties);
+ expect(tree).to.deep.equal({
+ "m:funcPr": {},
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/function/math-function-properties.ts b/src/file/paragraph/math/function/math-function-properties.ts
new file mode 100644
index 0000000000..f6e8d608ac
--- /dev/null
+++ b/src/file/paragraph/math/function/math-function-properties.ts
@@ -0,0 +1,8 @@
+// http://www.datypic.com/sc/ooxml/e-m_radPr-1.html
+import { XmlComponent } from "file/xml-components";
+
+export class MathFunctionProperties extends XmlComponent {
+ constructor() {
+ super("m:funcPr");
+ }
+}
diff --git a/src/file/paragraph/math/function/math-function.spec.ts b/src/file/paragraph/math/function/math-function.spec.ts
new file mode 100644
index 0000000000..6ea02b6c9d
--- /dev/null
+++ b/src/file/paragraph/math/function/math-function.spec.ts
@@ -0,0 +1,48 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathFunction } from "./math-function";
+
+describe("MathFunction", () => {
+ describe("#constructor()", () => {
+ it("should create a MathFunction with correct root key", () => {
+ const mathFunction = new MathFunction({
+ name: [new MathRun("sin")],
+ children: [new MathRun("60")],
+ });
+
+ const tree = new Formatter().format(mathFunction);
+ expect(tree).to.deep.equal({
+ "m:func": [
+ {
+ "m:funcPr": {},
+ },
+ {
+ "m:fName": [
+ {
+ "m:r": [
+ {
+ "m:t": ["sin"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["60"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/function/math-function.ts b/src/file/paragraph/math/function/math-function.ts
new file mode 100644
index 0000000000..86b66392cc
--- /dev/null
+++ b/src/file/paragraph/math/function/math-function.ts
@@ -0,0 +1,22 @@
+// http://www.datypic.com/sc/ooxml/e-m_func-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+import { MathBase } from "../n-ary";
+import { MathFunctionName } from "./math-function-name";
+import { MathFunctionProperties } from "./math-function-properties";
+
+export interface IMathFunctionOptions {
+ readonly children: MathComponent[];
+ readonly name: MathComponent[];
+}
+
+export class MathFunction extends XmlComponent {
+ constructor(options: IMathFunctionOptions) {
+ super("m:func");
+
+ this.root.push(new MathFunctionProperties());
+ this.root.push(new MathFunctionName(options.name));
+ this.root.push(new MathBase(options.children));
+ }
+}
diff --git a/src/file/paragraph/math/index.ts b/src/file/paragraph/math/index.ts
new file mode 100644
index 0000000000..b42ec908f6
--- /dev/null
+++ b/src/file/paragraph/math/index.ts
@@ -0,0 +1,9 @@
+export * from "./math";
+export * from "./math-run";
+export * from "./fraction";
+export * from "./n-ary";
+export * from "./script";
+export * from "./math-component";
+export * from "./radical";
+export * from "./function";
+export * from "./brackets";
diff --git a/src/file/paragraph/math/math-component.ts b/src/file/paragraph/math/math-component.ts
new file mode 100644
index 0000000000..afe83235f4
--- /dev/null
+++ b/src/file/paragraph/math/math-component.ts
@@ -0,0 +1,21 @@
+import { MathAngledBrackets, MathCurlyBrackets, MathRoundBrackets, MathSquareBrackets } from "./brackets";
+import { MathFraction } from "./fraction";
+import { MathFunction } from "./function";
+import { MathRun } from "./math-run";
+import { MathSum } from "./n-ary";
+import { MathRadical } from "./radical";
+import { MathSubScript, MathSubSuperScript, MathSuperScript } from "./script";
+
+export type MathComponent =
+ | MathRun
+ | MathFraction
+ | MathSum
+ | MathSuperScript
+ | MathSubScript
+ | MathSubSuperScript
+ | MathRadical
+ | MathFunction
+ | MathRoundBrackets
+ | MathCurlyBrackets
+ | MathAngledBrackets
+ | MathSquareBrackets;
diff --git a/src/file/paragraph/math/math-run.spec.ts b/src/file/paragraph/math/math-run.spec.ts
new file mode 100644
index 0000000000..2773a0fb9c
--- /dev/null
+++ b/src/file/paragraph/math/math-run.spec.ts
@@ -0,0 +1,21 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "./math-run";
+
+describe("MathRun", () => {
+ describe("#constructor()", () => {
+ it("should create a MathRun with correct root key", () => {
+ const mathRun = new MathRun("2+2");
+ const tree = new Formatter().format(mathRun);
+ expect(tree).to.deep.equal({
+ "m:r": [
+ {
+ "m:t": ["2+2"],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/math-run.ts b/src/file/paragraph/math/math-run.ts
new file mode 100644
index 0000000000..0d2c48910f
--- /dev/null
+++ b/src/file/paragraph/math/math-run.ts
@@ -0,0 +1,12 @@
+// http://www.datypic.com/sc/ooxml/e-m_r-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathText } from "./math-text";
+
+export class MathRun extends XmlComponent {
+ constructor(text: string) {
+ super("m:r");
+
+ this.root.push(new MathText(text));
+ }
+}
diff --git a/src/file/paragraph/math/math-text.spec.ts b/src/file/paragraph/math/math-text.spec.ts
new file mode 100644
index 0000000000..0001816ed1
--- /dev/null
+++ b/src/file/paragraph/math/math-text.spec.ts
@@ -0,0 +1,17 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathText } from "./math-text";
+
+describe("MathText", () => {
+ describe("#constructor()", () => {
+ it("should create a MathText with correct root key", () => {
+ const mathText = new MathText("2+2");
+ const tree = new Formatter().format(mathText);
+ expect(tree).to.deep.equal({
+ "m:t": ["2+2"],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/math-text.ts b/src/file/paragraph/math/math-text.ts
new file mode 100644
index 0000000000..6087c7e611
--- /dev/null
+++ b/src/file/paragraph/math/math-text.ts
@@ -0,0 +1,9 @@
+import { XmlComponent } from "file/xml-components";
+
+export class MathText extends XmlComponent {
+ constructor(text: string) {
+ super("m:t");
+
+ this.root.push(text);
+ }
+}
diff --git a/src/file/paragraph/math/math.spec.ts b/src/file/paragraph/math/math.spec.ts
new file mode 100644
index 0000000000..d5c4f6f494
--- /dev/null
+++ b/src/file/paragraph/math/math.spec.ts
@@ -0,0 +1,38 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { Math } from "./math";
+import { MathRun } from "./math-run";
+
+describe("Math", () => {
+ describe("#constructor()", () => {
+ it("should create a Math with correct root key", () => {
+ const math = new Math({
+ children: [],
+ });
+ const tree = new Formatter().format(math);
+ expect(tree).to.deep.equal({
+ "m:oMath": {},
+ });
+ });
+
+ it("should be able to add children", () => {
+ const math = new Math({
+ children: [new MathRun("2+2")],
+ });
+ const tree = new Formatter().format(math);
+ expect(tree).to.deep.equal({
+ "m:oMath": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2+2"],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/math.ts b/src/file/paragraph/math/math.ts
new file mode 100644
index 0000000000..69ebae4dff
--- /dev/null
+++ b/src/file/paragraph/math/math.ts
@@ -0,0 +1,18 @@
+// http://www.datypic.com/sc/ooxml/e-m_oMath-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "./math-component";
+
+export interface IMathOptions {
+ readonly children: MathComponent[];
+}
+
+export class Math extends XmlComponent {
+ constructor(options: IMathOptions) {
+ super("m:oMath");
+
+ for (const child of options.children) {
+ this.root.push(child);
+ }
+ }
+}
diff --git a/src/file/paragraph/math/n-ary/index.ts b/src/file/paragraph/math/n-ary/index.ts
new file mode 100644
index 0000000000..6929544152
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/index.ts
@@ -0,0 +1,7 @@
+export * from "./math-accent-character";
+export * from "./math-base";
+export * from "./math-limit-location";
+export * from "./math-naray-properties";
+export * from "./math-sub-script";
+export * from "./math-sum";
+export * from "./math-super-script";
diff --git a/src/file/paragraph/math/n-ary/math-accent-character.spec.ts b/src/file/paragraph/math/n-ary/math-accent-character.spec.ts
new file mode 100644
index 0000000000..b414f4c744
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-accent-character.spec.ts
@@ -0,0 +1,22 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathAccentCharacter } from "./math-accent-character";
+
+describe("MathAccentCharacter", () => {
+ describe("#constructor()", () => {
+ it("should create a MathAccentCharacter with correct root key", () => {
+ const mathAccentCharacter = new MathAccentCharacter("∑");
+
+ const tree = new Formatter().format(mathAccentCharacter);
+ expect(tree).to.deep.equal({
+ "m:chr": {
+ _attr: {
+ "m:val": "∑",
+ },
+ },
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/n-ary/math-accent-character.ts b/src/file/paragraph/math/n-ary/math-accent-character.ts
new file mode 100644
index 0000000000..00182bd1f2
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-accent-character.ts
@@ -0,0 +1,14 @@
+// http://www.datypic.com/sc/ooxml/e-m_chr-1.html
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+class MathAccentCharacterAttributes extends XmlAttributeComponent<{ readonly accent: string }> {
+ protected readonly xmlKeys = { accent: "m:val" };
+}
+
+export class MathAccentCharacter extends XmlComponent {
+ constructor(accent: string) {
+ super("m:chr");
+
+ this.root.push(new MathAccentCharacterAttributes({ accent }));
+ }
+}
diff --git a/src/file/paragraph/math/n-ary/math-base.spec.ts b/src/file/paragraph/math/n-ary/math-base.spec.ts
new file mode 100644
index 0000000000..c282537970
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-base.spec.ts
@@ -0,0 +1,27 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathBase } from "./math-base";
+
+describe("MathBase", () => {
+ describe("#constructor()", () => {
+ it("should create a MathBase with correct root key", () => {
+ const mathBase = new MathBase([new MathRun("2+2")]);
+
+ const tree = new Formatter().format(mathBase);
+ expect(tree).to.deep.equal({
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2+2"],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/n-ary/math-base.ts b/src/file/paragraph/math/n-ary/math-base.ts
new file mode 100644
index 0000000000..6c2320439f
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-base.ts
@@ -0,0 +1,14 @@
+// http://www.datypic.com/sc/ooxml/e-m_e-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+
+export class MathBase extends XmlComponent {
+ constructor(children: MathComponent[]) {
+ super("m:e");
+
+ for (const child of children) {
+ this.root.push(child);
+ }
+ }
+}
diff --git a/src/file/paragraph/math/n-ary/math-limit-location.spec.ts b/src/file/paragraph/math/n-ary/math-limit-location.spec.ts
new file mode 100644
index 0000000000..426f3d0198
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-limit-location.spec.ts
@@ -0,0 +1,22 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathLimitLocation } from "./math-limit-location";
+
+describe("MathLimitLocation", () => {
+ describe("#constructor()", () => {
+ it("should create a MathLimitLocation with correct root key", () => {
+ const mathLimitLocation = new MathLimitLocation();
+
+ const tree = new Formatter().format(mathLimitLocation);
+ expect(tree).to.deep.equal({
+ "m:limLoc": {
+ _attr: {
+ "m:val": "undOvr",
+ },
+ },
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/n-ary/math-limit-location.ts b/src/file/paragraph/math/n-ary/math-limit-location.ts
new file mode 100644
index 0000000000..5504e1890d
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-limit-location.ts
@@ -0,0 +1,14 @@
+// http://www.datypic.com/sc/ooxml/e-m_limLoc-1.html
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+class MathLimitLocationAttributes extends XmlAttributeComponent<{ readonly value: string }> {
+ protected readonly xmlKeys = { value: "m:val" };
+}
+
+export class MathLimitLocation extends XmlComponent {
+ constructor() {
+ super("m:limLoc");
+
+ this.root.push(new MathLimitLocationAttributes({ value: "undOvr" }));
+ }
+}
diff --git a/src/file/paragraph/math/n-ary/math-naray-properties.spec.ts b/src/file/paragraph/math/n-ary/math-naray-properties.spec.ts
new file mode 100644
index 0000000000..70aa74a1c4
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-naray-properties.spec.ts
@@ -0,0 +1,133 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathNArayProperties } from "./math-naray-properties";
+
+describe("MathNArayProperties", () => {
+ describe("#constructor()", () => {
+ it("should create a MathNArayProperties with correct root key", () => {
+ const mathNArayProperties = new MathNArayProperties("∑", true, true);
+
+ const tree = new Formatter().format(mathNArayProperties);
+ expect(tree).to.deep.equal({
+ "m:naryPr": [
+ {
+ "m:chr": {
+ _attr: {
+ "m:val": "∑",
+ },
+ },
+ },
+ {
+ "m:limLoc": {
+ _attr: {
+ "m:val": "undOvr",
+ },
+ },
+ },
+ ],
+ });
+ });
+
+ it("should add super-script hide attributes", () => {
+ const mathNArayProperties = new MathNArayProperties("∑", false, true);
+
+ const tree = new Formatter().format(mathNArayProperties);
+ expect(tree).to.deep.equal({
+ "m:naryPr": [
+ {
+ "m:chr": {
+ _attr: {
+ "m:val": "∑",
+ },
+ },
+ },
+ {
+ "m:limLoc": {
+ _attr: {
+ "m:val": "undOvr",
+ },
+ },
+ },
+ {
+ "m:supHide": {
+ _attr: {
+ "m:val": 1,
+ },
+ },
+ },
+ ],
+ });
+ });
+
+ it("should add sub-script hide attributes", () => {
+ const mathNArayProperties = new MathNArayProperties("∑", true, false);
+
+ const tree = new Formatter().format(mathNArayProperties);
+ expect(tree).to.deep.equal({
+ "m:naryPr": [
+ {
+ "m:chr": {
+ _attr: {
+ "m:val": "∑",
+ },
+ },
+ },
+ {
+ "m:limLoc": {
+ _attr: {
+ "m:val": "undOvr",
+ },
+ },
+ },
+ {
+ "m:subHide": {
+ _attr: {
+ "m:val": 1,
+ },
+ },
+ },
+ ],
+ });
+ });
+
+ it("should add both super-script and sub-script hide attributes", () => {
+ const mathNArayProperties = new MathNArayProperties("∑", false, false);
+
+ const tree = new Formatter().format(mathNArayProperties);
+ expect(tree).to.deep.equal({
+ "m:naryPr": [
+ {
+ "m:chr": {
+ _attr: {
+ "m:val": "∑",
+ },
+ },
+ },
+ {
+ "m:limLoc": {
+ _attr: {
+ "m:val": "undOvr",
+ },
+ },
+ },
+ {
+ "m:supHide": {
+ _attr: {
+ "m:val": 1,
+ },
+ },
+ },
+ {
+ "m:subHide": {
+ _attr: {
+ "m:val": 1,
+ },
+ },
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/n-ary/math-naray-properties.ts b/src/file/paragraph/math/n-ary/math-naray-properties.ts
new file mode 100644
index 0000000000..f8e91e746a
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-naray-properties.ts
@@ -0,0 +1,24 @@
+// http://www.datypic.com/sc/ooxml/e-m_naryPr-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathAccentCharacter } from "./math-accent-character";
+import { MathLimitLocation } from "./math-limit-location";
+import { MathSubScriptHide } from "./math-sub-script-hide";
+import { MathSuperScriptHide } from "./math-super-script-hide";
+
+export class MathNArayProperties extends XmlComponent {
+ constructor(accent: string, hasSuperScript: boolean, hasSubScript: boolean) {
+ super("m:naryPr");
+
+ this.root.push(new MathAccentCharacter(accent));
+ this.root.push(new MathLimitLocation());
+
+ if (!hasSuperScript) {
+ this.root.push(new MathSuperScriptHide());
+ }
+
+ if (!hasSubScript) {
+ this.root.push(new MathSubScriptHide());
+ }
+ }
+}
diff --git a/src/file/paragraph/math/n-ary/math-sub-script-hide.spec.ts b/src/file/paragraph/math/n-ary/math-sub-script-hide.spec.ts
new file mode 100644
index 0000000000..2e9845172f
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-sub-script-hide.spec.ts
@@ -0,0 +1,22 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathSubScriptHide } from "./math-sub-script-hide";
+
+describe("MathSubScriptHide", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSubScriptHide with correct root key", () => {
+ const mathSubScriptHide = new MathSubScriptHide();
+
+ const tree = new Formatter().format(mathSubScriptHide);
+ expect(tree).to.deep.equal({
+ "m:subHide": {
+ _attr: {
+ "m:val": 1,
+ },
+ },
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/n-ary/math-sub-script-hide.ts b/src/file/paragraph/math/n-ary/math-sub-script-hide.ts
new file mode 100644
index 0000000000..ef735744e0
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-sub-script-hide.ts
@@ -0,0 +1,14 @@
+// http://www.datypic.com/sc/ooxml/e-m_subHide-1.html
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+class MathSubScriptHideAttributes extends XmlAttributeComponent<{ readonly hide: number }> {
+ protected readonly xmlKeys = { hide: "m:val" };
+}
+
+export class MathSubScriptHide extends XmlComponent {
+ constructor() {
+ super("m:subHide");
+
+ this.root.push(new MathSubScriptHideAttributes({ hide: 1 }));
+ }
+}
diff --git a/src/file/paragraph/math/n-ary/math-sub-script.spec.ts b/src/file/paragraph/math/n-ary/math-sub-script.spec.ts
new file mode 100644
index 0000000000..d342946b74
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-sub-script.spec.ts
@@ -0,0 +1,27 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathSubScriptElement } from "./math-sub-script";
+
+describe("MathSubScriptElement", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSubScriptElement with correct root key", () => {
+ const mathSubScriptElement = new MathSubScriptElement([new MathRun("2+2")]);
+
+ const tree = new Formatter().format(mathSubScriptElement);
+ expect(tree).to.deep.equal({
+ "m:sub": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2+2"],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/n-ary/math-sub-script.ts b/src/file/paragraph/math/n-ary/math-sub-script.ts
new file mode 100644
index 0000000000..48268312cf
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-sub-script.ts
@@ -0,0 +1,14 @@
+// http://www.datypic.com/sc/ooxml/e-m_sub-3.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+
+export class MathSubScriptElement extends XmlComponent {
+ constructor(children: MathComponent[]) {
+ super("m:sub");
+
+ for (const child of children) {
+ this.root.push(child);
+ }
+ }
+}
diff --git a/src/file/paragraph/math/n-ary/math-sum.spec.ts b/src/file/paragraph/math/n-ary/math-sum.spec.ts
new file mode 100644
index 0000000000..1e76815147
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-sum.spec.ts
@@ -0,0 +1,75 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathSum } from "./math-sum";
+
+describe("MathSum", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSum with correct root key", () => {
+ const mathSum = new MathSum({
+ children: [new MathRun("1")],
+ subScript: [new MathRun("2")],
+ superScript: [new MathRun("3")],
+ });
+
+ const tree = new Formatter().format(mathSum);
+ expect(tree).to.deep.equal({
+ "m:nary": [
+ {
+ "m:naryPr": [
+ {
+ "m:chr": {
+ _attr: {
+ "m:val": "∑",
+ },
+ },
+ },
+ {
+ "m:limLoc": {
+ _attr: {
+ "m:val": "undOvr",
+ },
+ },
+ },
+ ],
+ },
+ {
+ "m:sub": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:sup": [
+ {
+ "m:r": [
+ {
+ "m:t": ["3"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["1"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/n-ary/math-sum.ts b/src/file/paragraph/math/n-ary/math-sum.ts
new file mode 100644
index 0000000000..af14730bbf
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-sum.ts
@@ -0,0 +1,32 @@
+// http://www.datypic.com/sc/ooxml/e-m_nary-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+import { MathBase } from "./math-base";
+import { MathNArayProperties } from "./math-naray-properties";
+import { MathSubScriptElement } from "./math-sub-script";
+import { MathSuperScriptElement } from "./math-super-script";
+
+export interface IMathSumOptions {
+ readonly children: MathComponent[];
+ readonly subScript?: MathComponent[];
+ readonly superScript?: MathComponent[];
+}
+
+export class MathSum extends XmlComponent {
+ constructor(options: IMathSumOptions) {
+ super("m:nary");
+
+ this.root.push(new MathNArayProperties("∑", !!options.superScript, !!options.subScript));
+
+ if (!!options.subScript) {
+ this.root.push(new MathSubScriptElement(options.subScript));
+ }
+
+ if (!!options.superScript) {
+ this.root.push(new MathSuperScriptElement(options.superScript));
+ }
+
+ this.root.push(new MathBase(options.children));
+ }
+}
diff --git a/src/file/paragraph/math/n-ary/math-super-script-hide.spec.ts b/src/file/paragraph/math/n-ary/math-super-script-hide.spec.ts
new file mode 100644
index 0000000000..89a28564ac
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-super-script-hide.spec.ts
@@ -0,0 +1,22 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathSuperScriptHide } from "./math-super-script-hide";
+
+describe("MathSuperScriptHide", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSuperScriptHide with correct root key", () => {
+ const mathSuperScriptHide = new MathSuperScriptHide();
+
+ const tree = new Formatter().format(mathSuperScriptHide);
+ expect(tree).to.deep.equal({
+ "m:supHide": {
+ _attr: {
+ "m:val": 1,
+ },
+ },
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/n-ary/math-super-script-hide.ts b/src/file/paragraph/math/n-ary/math-super-script-hide.ts
new file mode 100644
index 0000000000..a55c15a7ad
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-super-script-hide.ts
@@ -0,0 +1,14 @@
+// http://www.datypic.com/sc/ooxml/e-m_subHide-1.html
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+class MathSuperScriptHideAttributes extends XmlAttributeComponent<{ readonly hide: number }> {
+ protected readonly xmlKeys = { hide: "m:val" };
+}
+
+export class MathSuperScriptHide extends XmlComponent {
+ constructor() {
+ super("m:supHide");
+
+ this.root.push(new MathSuperScriptHideAttributes({ hide: 1 }));
+ }
+}
diff --git a/src/file/paragraph/math/n-ary/math-super-script.spec.ts b/src/file/paragraph/math/n-ary/math-super-script.spec.ts
new file mode 100644
index 0000000000..10e037eba3
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-super-script.spec.ts
@@ -0,0 +1,27 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathSuperScriptElement } from "./math-super-script";
+
+describe("MathSuperScriptElement", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSuperScriptElement with correct root key", () => {
+ const mathSuperScriptElement = new MathSuperScriptElement([new MathRun("2+2")]);
+
+ const tree = new Formatter().format(mathSuperScriptElement);
+ expect(tree).to.deep.equal({
+ "m:sup": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2+2"],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/n-ary/math-super-script.ts b/src/file/paragraph/math/n-ary/math-super-script.ts
new file mode 100644
index 0000000000..8d8386addc
--- /dev/null
+++ b/src/file/paragraph/math/n-ary/math-super-script.ts
@@ -0,0 +1,14 @@
+// http://www.datypic.com/sc/ooxml/e-m_sup-3.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+
+export class MathSuperScriptElement extends XmlComponent {
+ constructor(children: MathComponent[]) {
+ super("m:sup");
+
+ for (const child of children) {
+ this.root.push(child);
+ }
+ }
+}
diff --git a/src/file/paragraph/math/radical/index.ts b/src/file/paragraph/math/radical/index.ts
new file mode 100644
index 0000000000..78240ccd13
--- /dev/null
+++ b/src/file/paragraph/math/radical/index.ts
@@ -0,0 +1,3 @@
+export * from "./math-degree";
+export * from "./math-radical";
+export * from "./math-radical-properties";
diff --git a/src/file/paragraph/math/radical/math-degree-hide.spec.ts b/src/file/paragraph/math/radical/math-degree-hide.spec.ts
new file mode 100644
index 0000000000..0c3f335a13
--- /dev/null
+++ b/src/file/paragraph/math/radical/math-degree-hide.spec.ts
@@ -0,0 +1,22 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathDegreeHide } from "./math-degree-hide";
+
+describe("MathDegreeHide", () => {
+ describe("#constructor()", () => {
+ it("should create a MathDegreeHide with correct root key", () => {
+ const mathDegreeHide = new MathDegreeHide();
+
+ const tree = new Formatter().format(mathDegreeHide);
+ expect(tree).to.deep.equal({
+ "m:degHide": {
+ _attr: {
+ "m:val": 1,
+ },
+ },
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/radical/math-degree-hide.ts b/src/file/paragraph/math/radical/math-degree-hide.ts
new file mode 100644
index 0000000000..c1b9dd2ae5
--- /dev/null
+++ b/src/file/paragraph/math/radical/math-degree-hide.ts
@@ -0,0 +1,14 @@
+// http://www.datypic.com/sc/ooxml/e-m_degHide-1.html
+import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
+
+class MathDegreeHideAttributes extends XmlAttributeComponent<{ readonly hide: number }> {
+ protected readonly xmlKeys = { hide: "m:val" };
+}
+
+export class MathDegreeHide extends XmlComponent {
+ constructor() {
+ super("m:degHide");
+
+ this.root.push(new MathDegreeHideAttributes({ hide: 1 }));
+ }
+}
diff --git a/src/file/paragraph/math/radical/math-degree.spec.ts b/src/file/paragraph/math/radical/math-degree.spec.ts
new file mode 100644
index 0000000000..3d1f17dfa8
--- /dev/null
+++ b/src/file/paragraph/math/radical/math-degree.spec.ts
@@ -0,0 +1,36 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathDegree } from "./math-degree";
+
+describe("MathDegree", () => {
+ describe("#constructor()", () => {
+ it("should create a MathDegree with correct root key", () => {
+ const mathDegree = new MathDegree();
+
+ const tree = new Formatter().format(mathDegree);
+ expect(tree).to.deep.equal({
+ "m:deg": {},
+ });
+ });
+
+ it("should create a MathDegree with correct root key with child", () => {
+ const mathDegree = new MathDegree([new MathRun("2")]);
+
+ const tree = new Formatter().format(mathDegree);
+ expect(tree).to.deep.equal({
+ "m:deg": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2"],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/radical/math-degree.ts b/src/file/paragraph/math/radical/math-degree.ts
new file mode 100644
index 0000000000..79923bbde8
--- /dev/null
+++ b/src/file/paragraph/math/radical/math-degree.ts
@@ -0,0 +1,15 @@
+// http://www.datypic.com/sc/ooxml/e-m_deg-1.html
+import { XmlComponent } from "file/xml-components";
+import { MathComponent } from "../math-component";
+
+export class MathDegree extends XmlComponent {
+ constructor(children?: MathComponent[]) {
+ super("m:deg");
+
+ if (!!children) {
+ for (const child of children) {
+ this.root.push(child);
+ }
+ }
+ }
+}
diff --git a/src/file/paragraph/math/radical/math-radical-properties.spec.ts b/src/file/paragraph/math/radical/math-radical-properties.spec.ts
new file mode 100644
index 0000000000..12d29a2962
--- /dev/null
+++ b/src/file/paragraph/math/radical/math-radical-properties.spec.ts
@@ -0,0 +1,35 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRadicalProperties } from "./math-radical-properties";
+
+describe("MathRadicalProperties", () => {
+ describe("#constructor()", () => {
+ it("should create a MathRadicalProperties with correct root key", () => {
+ const mathRadicalProperties = new MathRadicalProperties(true);
+
+ const tree = new Formatter().format(mathRadicalProperties);
+ expect(tree).to.deep.equal({
+ "m:radPr": {},
+ });
+ });
+
+ it("should create a MathRadicalProperties with correct root key with degree hide", () => {
+ const mathRadicalProperties = new MathRadicalProperties(false);
+
+ const tree = new Formatter().format(mathRadicalProperties);
+ expect(tree).to.deep.equal({
+ "m:radPr": [
+ {
+ "m:degHide": {
+ _attr: {
+ "m:val": 1,
+ },
+ },
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/radical/math-radical-properties.ts b/src/file/paragraph/math/radical/math-radical-properties.ts
new file mode 100644
index 0000000000..b4e90ed4df
--- /dev/null
+++ b/src/file/paragraph/math/radical/math-radical-properties.ts
@@ -0,0 +1,13 @@
+// http://www.datypic.com/sc/ooxml/e-m_radPr-1.html
+import { XmlComponent } from "file/xml-components";
+import { MathDegreeHide } from "./math-degree-hide";
+
+export class MathRadicalProperties extends XmlComponent {
+ constructor(hasDegree: boolean) {
+ super("m:radPr");
+
+ if (!hasDegree) {
+ this.root.push(new MathDegreeHide());
+ }
+ }
+}
diff --git a/src/file/paragraph/math/radical/math-radical.spec.ts b/src/file/paragraph/math/radical/math-radical.spec.ts
new file mode 100644
index 0000000000..e388edece4
--- /dev/null
+++ b/src/file/paragraph/math/radical/math-radical.spec.ts
@@ -0,0 +1,48 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../math-run";
+import { MathRadical } from "./math-radical";
+
+describe("MathRadical", () => {
+ describe("#constructor()", () => {
+ it("should create a MathRadical with correct root key", () => {
+ const mathRadical = new MathRadical({
+ children: [new MathRun("e")],
+ degree: [new MathRun("2")],
+ });
+
+ const tree = new Formatter().format(mathRadical);
+ expect(tree).to.deep.equal({
+ "m:rad": [
+ {
+ "m:radPr": {},
+ },
+ {
+ "m:deg": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["e"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/radical/math-radical.ts b/src/file/paragraph/math/radical/math-radical.ts
new file mode 100644
index 0000000000..1469867a5f
--- /dev/null
+++ b/src/file/paragraph/math/radical/math-radical.ts
@@ -0,0 +1,22 @@
+// http://www.datypic.com/sc/ooxml/e-m_rad-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../math-component";
+import { MathBase } from "../n-ary";
+import { MathDegree } from "./math-degree";
+import { MathRadicalProperties } from "./math-radical-properties";
+
+export interface IMathRadicalOptions {
+ readonly children: MathComponent[];
+ readonly degree?: MathComponent[];
+}
+
+export class MathRadical extends XmlComponent {
+ constructor(options: IMathRadicalOptions) {
+ super("m:rad");
+
+ this.root.push(new MathRadicalProperties(!!options.degree));
+ this.root.push(new MathDegree(options.degree));
+ this.root.push(new MathBase(options.children));
+ }
+}
diff --git a/src/file/paragraph/math/script/index.ts b/src/file/paragraph/math/script/index.ts
new file mode 100644
index 0000000000..a83e54975e
--- /dev/null
+++ b/src/file/paragraph/math/script/index.ts
@@ -0,0 +1,4 @@
+export * from "./super-script";
+export * from "./sub-script";
+export * from "./sub-super-script";
+export * from "./pre-sub-super-script";
diff --git a/src/file/paragraph/math/script/pre-sub-super-script/index.ts b/src/file/paragraph/math/script/pre-sub-super-script/index.ts
new file mode 100644
index 0000000000..8660a75017
--- /dev/null
+++ b/src/file/paragraph/math/script/pre-sub-super-script/index.ts
@@ -0,0 +1,2 @@
+export * from "./math-pre-sub-super-script-function";
+export * from "./math-pre-sub-super-script-function-properties";
diff --git a/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function-properties.spec.ts b/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function-properties.spec.ts
new file mode 100644
index 0000000000..a6f1d5383e
--- /dev/null
+++ b/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function-properties.spec.ts
@@ -0,0 +1,17 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+import { MathPreSubSuperScriptProperties } from "./math-pre-sub-super-script-function-properties";
+
+describe("MathPreSubSuperScriptProperties", () => {
+ describe("#constructor()", () => {
+ it("should create a MathPreSubSuperScriptProperties with correct root key", () => {
+ const mathPreSubSuperScriptProperties = new MathPreSubSuperScriptProperties();
+
+ const tree = new Formatter().format(mathPreSubSuperScriptProperties);
+ expect(tree).to.deep.equal({
+ "m:sPrePr": {},
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function-properties.ts b/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function-properties.ts
new file mode 100644
index 0000000000..fed0cb3564
--- /dev/null
+++ b/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function-properties.ts
@@ -0,0 +1,8 @@
+// http://www.datypic.com/sc/ooxml/e-m_sPrePr-1.html
+import { XmlComponent } from "file/xml-components";
+
+export class MathPreSubSuperScriptProperties extends XmlComponent {
+ constructor() {
+ super("m:sPrePr");
+ }
+}
diff --git a/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function.spec.ts b/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function.spec.ts
new file mode 100644
index 0000000000..20d00a639d
--- /dev/null
+++ b/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function.spec.ts
@@ -0,0 +1,60 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../../math-run";
+import { MathPreSubSuperScript } from "./math-pre-sub-super-script-function";
+
+describe("MathPreSubScript", () => {
+ describe("#constructor()", () => {
+ it("should create a MathPreSubScript with correct root key", () => {
+ const mathPreSubScript = new MathPreSubSuperScript({
+ children: [new MathRun("e")],
+ subScript: [new MathRun("2")],
+ superScript: [new MathRun("5")],
+ });
+
+ const tree = new Formatter().format(mathPreSubScript);
+ expect(tree).to.deep.equal({
+ "m:sPre": [
+ {
+ "m:sPrePr": {},
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["e"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:sub": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:sup": [
+ {
+ "m:r": [
+ {
+ "m:t": ["5"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function.ts b/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function.ts
new file mode 100644
index 0000000000..3a58675b0f
--- /dev/null
+++ b/src/file/paragraph/math/script/pre-sub-super-script/math-pre-sub-super-script-function.ts
@@ -0,0 +1,23 @@
+// http://www.datypic.com/sc/ooxml/e-m_sPre-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../../math-component";
+import { MathBase, MathSubScriptElement, MathSuperScriptElement } from "../../n-ary";
+import { MathPreSubSuperScriptProperties } from "./math-pre-sub-super-script-function-properties";
+
+export interface IMathPreSubSuperScriptOptions {
+ readonly children: MathComponent[];
+ readonly subScript: MathComponent[];
+ readonly superScript: MathComponent[];
+}
+
+export class MathPreSubSuperScript extends XmlComponent {
+ constructor(options: IMathPreSubSuperScriptOptions) {
+ super("m:sPre");
+
+ this.root.push(new MathPreSubSuperScriptProperties());
+ this.root.push(new MathBase(options.children));
+ this.root.push(new MathSubScriptElement(options.subScript));
+ this.root.push(new MathSuperScriptElement(options.superScript));
+ }
+}
diff --git a/src/file/paragraph/math/script/sub-script/index.ts b/src/file/paragraph/math/script/sub-script/index.ts
new file mode 100644
index 0000000000..0f1c27fe51
--- /dev/null
+++ b/src/file/paragraph/math/script/sub-script/index.ts
@@ -0,0 +1,2 @@
+export * from "./math-sub-script-function";
+export * from "./math-sub-script-function-properties";
diff --git a/src/file/paragraph/math/script/sub-script/math-sub-script-function-properties.spec.ts b/src/file/paragraph/math/script/sub-script/math-sub-script-function-properties.spec.ts
new file mode 100644
index 0000000000..be229e066b
--- /dev/null
+++ b/src/file/paragraph/math/script/sub-script/math-sub-script-function-properties.spec.ts
@@ -0,0 +1,17 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+import { MathSubScriptProperties } from "./math-sub-script-function-properties";
+
+describe("MathSubScriptProperties", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSubScriptProperties with correct root key", () => {
+ const mathSubScriptProperties = new MathSubScriptProperties();
+
+ const tree = new Formatter().format(mathSubScriptProperties);
+ expect(tree).to.deep.equal({
+ "m:sSubPr": {},
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/script/sub-script/math-sub-script-function-properties.ts b/src/file/paragraph/math/script/sub-script/math-sub-script-function-properties.ts
new file mode 100644
index 0000000000..bf37b1d885
--- /dev/null
+++ b/src/file/paragraph/math/script/sub-script/math-sub-script-function-properties.ts
@@ -0,0 +1,8 @@
+// http://www.datypic.com/sc/ooxml/e-m_sSubPr-1.html
+import { XmlComponent } from "file/xml-components";
+
+export class MathSubScriptProperties extends XmlComponent {
+ constructor() {
+ super("m:sSubPr");
+ }
+}
diff --git a/src/file/paragraph/math/script/sub-script/math-sub-script-function.spec.ts b/src/file/paragraph/math/script/sub-script/math-sub-script-function.spec.ts
new file mode 100644
index 0000000000..a3ea8d680c
--- /dev/null
+++ b/src/file/paragraph/math/script/sub-script/math-sub-script-function.spec.ts
@@ -0,0 +1,48 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../../math-run";
+import { MathSubScript } from "./math-sub-script-function";
+
+describe("MathSubScript", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSubScript with correct root key", () => {
+ const mathSubScript = new MathSubScript({
+ children: [new MathRun("e")],
+ subScript: [new MathRun("2")],
+ });
+
+ const tree = new Formatter().format(mathSubScript);
+ expect(tree).to.deep.equal({
+ "m:sSub": [
+ {
+ "m:sSubPr": {},
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["e"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:sub": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/script/sub-script/math-sub-script-function.ts b/src/file/paragraph/math/script/sub-script/math-sub-script-function.ts
new file mode 100644
index 0000000000..319d4d1f1a
--- /dev/null
+++ b/src/file/paragraph/math/script/sub-script/math-sub-script-function.ts
@@ -0,0 +1,21 @@
+// http://www.datypic.com/sc/ooxml/e-m_sSub-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../../math-component";
+import { MathBase, MathSubScriptElement } from "../../n-ary";
+import { MathSubScriptProperties } from "./math-sub-script-function-properties";
+
+export interface IMathSubScriptOptions {
+ readonly children: MathComponent[];
+ readonly subScript: MathComponent[];
+}
+
+export class MathSubScript extends XmlComponent {
+ constructor(options: IMathSubScriptOptions) {
+ super("m:sSub");
+
+ this.root.push(new MathSubScriptProperties());
+ this.root.push(new MathBase(options.children));
+ this.root.push(new MathSubScriptElement(options.subScript));
+ }
+}
diff --git a/src/file/paragraph/math/script/sub-super-script/index.ts b/src/file/paragraph/math/script/sub-super-script/index.ts
new file mode 100644
index 0000000000..88ddeb69fa
--- /dev/null
+++ b/src/file/paragraph/math/script/sub-super-script/index.ts
@@ -0,0 +1,2 @@
+export * from "./math-sub-super-script-function";
+export * from "./math-sub-super-script-function-properties";
diff --git a/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function-properties.spec.ts b/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function-properties.spec.ts
new file mode 100644
index 0000000000..b0f934823a
--- /dev/null
+++ b/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function-properties.spec.ts
@@ -0,0 +1,17 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+import { MathSubSuperScriptProperties } from "./math-sub-super-script-function-properties";
+
+describe("MathSubSuperScriptProperties", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSubSuperScriptProperties with correct root key", () => {
+ const mathSubSuperScriptProperties = new MathSubSuperScriptProperties();
+
+ const tree = new Formatter().format(mathSubSuperScriptProperties);
+ expect(tree).to.deep.equal({
+ "m:sSubSupPr": {},
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function-properties.ts b/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function-properties.ts
new file mode 100644
index 0000000000..b3218a7d3a
--- /dev/null
+++ b/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function-properties.ts
@@ -0,0 +1,8 @@
+// http://www.datypic.com/sc/ooxml/e-m_sSubSupPr-1.html
+import { XmlComponent } from "file/xml-components";
+
+export class MathSubSuperScriptProperties extends XmlComponent {
+ constructor() {
+ super("m:sSubSupPr");
+ }
+}
diff --git a/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function.spec.ts b/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function.spec.ts
new file mode 100644
index 0000000000..68a86fb26b
--- /dev/null
+++ b/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function.spec.ts
@@ -0,0 +1,60 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../../math-run";
+import { MathSubSuperScript } from "./math-sub-super-script-function";
+
+describe("MathSubScript", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSubScript with correct root key", () => {
+ const mathSubScript = new MathSubSuperScript({
+ children: [new MathRun("e")],
+ subScript: [new MathRun("2")],
+ superScript: [new MathRun("5")],
+ });
+
+ const tree = new Formatter().format(mathSubScript);
+ expect(tree).to.deep.equal({
+ "m:sSubSup": [
+ {
+ "m:sSubSupPr": {},
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["e"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:sub": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:sup": [
+ {
+ "m:r": [
+ {
+ "m:t": ["5"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function.ts b/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function.ts
new file mode 100644
index 0000000000..c382c9ff4c
--- /dev/null
+++ b/src/file/paragraph/math/script/sub-super-script/math-sub-super-script-function.ts
@@ -0,0 +1,23 @@
+// http://www.datypic.com/sc/ooxml/e-m_sSubSup-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../../math-component";
+import { MathBase, MathSubScriptElement, MathSuperScriptElement } from "../../n-ary";
+import { MathSubSuperScriptProperties } from "./math-sub-super-script-function-properties";
+
+export interface IMathSubSuperScriptOptions {
+ readonly children: MathComponent[];
+ readonly subScript: MathComponent[];
+ readonly superScript: MathComponent[];
+}
+
+export class MathSubSuperScript extends XmlComponent {
+ constructor(options: IMathSubSuperScriptOptions) {
+ super("m:sSubSup");
+
+ this.root.push(new MathSubSuperScriptProperties());
+ this.root.push(new MathBase(options.children));
+ this.root.push(new MathSubScriptElement(options.subScript));
+ this.root.push(new MathSuperScriptElement(options.superScript));
+ }
+}
diff --git a/src/file/paragraph/math/script/super-script/index.ts b/src/file/paragraph/math/script/super-script/index.ts
new file mode 100644
index 0000000000..2864fe9ac5
--- /dev/null
+++ b/src/file/paragraph/math/script/super-script/index.ts
@@ -0,0 +1,2 @@
+export * from "./math-super-script-function";
+export * from "./math-super-script-function-properties";
diff --git a/src/file/paragraph/math/script/super-script/math-super-script-function-properties.spec.ts b/src/file/paragraph/math/script/super-script/math-super-script-function-properties.spec.ts
new file mode 100644
index 0000000000..f95920f152
--- /dev/null
+++ b/src/file/paragraph/math/script/super-script/math-super-script-function-properties.spec.ts
@@ -0,0 +1,17 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+import { MathSuperScriptProperties } from "./math-super-script-function-properties";
+
+describe("MathSuperScriptProperties", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSuperScriptProperties with correct root key", () => {
+ const mathSuperScriptProperties = new MathSuperScriptProperties();
+
+ const tree = new Formatter().format(mathSuperScriptProperties);
+ expect(tree).to.deep.equal({
+ "m:sSupPr": {},
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/script/super-script/math-super-script-function-properties.ts b/src/file/paragraph/math/script/super-script/math-super-script-function-properties.ts
new file mode 100644
index 0000000000..ea5dbac20b
--- /dev/null
+++ b/src/file/paragraph/math/script/super-script/math-super-script-function-properties.ts
@@ -0,0 +1,8 @@
+// http://www.datypic.com/sc/ooxml/e-m_sSupPr-1.html
+import { XmlComponent } from "file/xml-components";
+
+export class MathSuperScriptProperties extends XmlComponent {
+ constructor() {
+ super("m:sSupPr");
+ }
+}
diff --git a/src/file/paragraph/math/script/super-script/math-super-script-function.spec.ts b/src/file/paragraph/math/script/super-script/math-super-script-function.spec.ts
new file mode 100644
index 0000000000..ae3740360b
--- /dev/null
+++ b/src/file/paragraph/math/script/super-script/math-super-script-function.spec.ts
@@ -0,0 +1,48 @@
+import { expect } from "chai";
+
+import { Formatter } from "export/formatter";
+
+import { MathRun } from "../../math-run";
+import { MathSuperScript } from "./math-super-script-function";
+
+describe("MathSuperScript", () => {
+ describe("#constructor()", () => {
+ it("should create a MathSuperScript with correct root key", () => {
+ const mathSuperScript = new MathSuperScript({
+ children: [new MathRun("e")],
+ superScript: [new MathRun("2")],
+ });
+
+ const tree = new Formatter().format(mathSuperScript);
+ expect(tree).to.deep.equal({
+ "m:sSup": [
+ {
+ "m:sSupPr": {},
+ },
+ {
+ "m:e": [
+ {
+ "m:r": [
+ {
+ "m:t": ["e"],
+ },
+ ],
+ },
+ ],
+ },
+ {
+ "m:sup": [
+ {
+ "m:r": [
+ {
+ "m:t": ["2"],
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ });
+ });
+ });
+});
diff --git a/src/file/paragraph/math/script/super-script/math-super-script-function.ts b/src/file/paragraph/math/script/super-script/math-super-script-function.ts
new file mode 100644
index 0000000000..eeffdf124a
--- /dev/null
+++ b/src/file/paragraph/math/script/super-script/math-super-script-function.ts
@@ -0,0 +1,21 @@
+// http://www.datypic.com/sc/ooxml/e-m_sSup-1.html
+import { XmlComponent } from "file/xml-components";
+
+import { MathComponent } from "../../math-component";
+import { MathBase, MathSuperScriptElement } from "../../n-ary";
+import { MathSuperScriptProperties } from "./math-super-script-function-properties";
+
+export interface IMathSuperScriptOptions {
+ readonly children: MathComponent[];
+ readonly superScript: MathComponent[];
+}
+
+export class MathSuperScript extends XmlComponent {
+ constructor(options: IMathSuperScriptOptions) {
+ super("m:sSup");
+
+ this.root.push(new MathSuperScriptProperties());
+ this.root.push(new MathBase(options.children));
+ this.root.push(new MathSuperScriptElement(options.superScript));
+ }
+}
diff --git a/src/file/paragraph/paragraph.spec.ts b/src/file/paragraph/paragraph.spec.ts
index 04cc8af8e4..0b8e9acd00 100644
--- a/src/file/paragraph/paragraph.spec.ts
+++ b/src/file/paragraph/paragraph.spec.ts
@@ -5,8 +5,9 @@ import { stub } from "sinon";
import { Formatter } from "export/formatter";
import { EMPTY_OBJECT } from "file/xml-components";
+import { File } from "../file";
import { AlignmentType, HeadingLevel, LeaderType, PageBreak, TabStopPosition, TabStopType } from "./formatting";
-import { Bookmark } from "./links";
+import { Bookmark, HyperlinkRef } from "./links";
import { Paragraph } from "./paragraph";
describe("Paragraph", () => {
@@ -759,4 +760,23 @@ describe("Paragraph", () => {
});
});
});
+
+ describe("#prepForXml", () => {
+ it("should set paragraph outline level to the given value", () => {
+ const paragraph = new Paragraph({
+ children: [new HyperlinkRef("myAnchorId")],
+ });
+ const fileMock = ({
+ HyperlinkCache: {
+ myAnchorId: "test",
+ },
+ // tslint:disable-next-line: no-any
+ } as any) as File;
+ paragraph.prepForXml(fileMock);
+ const tree = new Formatter().format(paragraph);
+ expect(tree).to.deep.equal({
+ "w:p": ["test"],
+ });
+ });
+ });
});
diff --git a/src/file/paragraph/paragraph.ts b/src/file/paragraph/paragraph.ts
index 856c34aacf..60efb0da34 100644
--- a/src/file/paragraph/paragraph.ts
+++ b/src/file/paragraph/paragraph.ts
@@ -3,9 +3,10 @@ import { FootnoteReferenceRun } from "file/footnotes/footnote/run/reference-run"
import { IXmlableObject, XmlComponent } from "file/xml-components";
import { File } from "../file";
-import { InsertedTextRun, DeletedTextRun } from "../track-revision";
+import { DeletedTextRun, InsertedTextRun } from "../track-revision";
import { PageBreak } from "./formatting/page-break";
import { Bookmark, HyperlinkRef } from "./links";
+import { Math } from "./math";
import { IParagraphPropertiesOptions, ParagraphProperties } from "./properties";
import { PictureRun, Run, SequentialIdentifier, SymbolRun, TextRun } from "./run";
@@ -22,6 +23,7 @@ export interface IParagraphOptions extends IParagraphPropertiesOptions {
| HyperlinkRef
| InsertedTextRun
| DeletedTextRun
+ | Math
)[];
}
diff --git a/src/file/settings/settings.ts b/src/file/settings/settings.ts
index 2fa4a27f0a..d828d21fb5 100644
--- a/src/file/settings/settings.ts
+++ b/src/file/settings/settings.ts
@@ -1,7 +1,7 @@
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
import { Compatibility } from "./compatibility";
-import { UpdateFields } from "./update-fields";
import { TrackRevisions } from "./track-revisions";
+import { UpdateFields } from "./update-fields";
export interface ISettingsAttributesProperties {
readonly wpc?: string;
@@ -46,8 +46,8 @@ export class SettingsAttributes extends XmlAttributeComponent {
describe("#constructor", () => {
diff --git a/src/file/track-revision/track-revision-components/deleted-text-run.ts b/src/file/track-revision/track-revision-components/deleted-text-run.ts
index 2342f70104..56d384b31b 100644
--- a/src/file/track-revision/track-revision-components/deleted-text-run.ts
+++ b/src/file/track-revision/track-revision-components/deleted-text-run.ts
@@ -1,12 +1,11 @@
-import { IChangedAttributesProperties, ChangeAttributes } from "../track-revision";
import { XmlComponent } from "file/xml-components";
-import { IRunOptions, RunProperties, IRunPropertiesOptions, FootnoteReferenceRun } from "../../index";
+import { FootnoteReferenceRun, IRunOptions, IRunPropertiesOptions, RunProperties } from "../../index";
import { Break } from "../../paragraph/run/break";
-import { Begin, Separate, End } from "../../paragraph/run/field";
+import { Begin, End, Separate } from "../../paragraph/run/field";
import { PageNumber } from "../../paragraph/run/run";
-
-import { DeletedPage, DeletedNumberOfPages, DeletedNumberOfPagesSection } from "./deleted-page-number";
+import { ChangeAttributes, IChangedAttributesProperties } from "../track-revision";
+import { DeletedNumberOfPages, DeletedNumberOfPagesSection, DeletedPage } from "./deleted-page-number";
import { DeletedText } from "./deleted-text";
interface IDeletedRunOptions extends IRunPropertiesOptions, IChangedAttributesProperties {
diff --git a/src/file/track-revision/track-revision-components/inserted-text-run.ts b/src/file/track-revision/track-revision-components/inserted-text-run.ts
index 49bd7f53ae..3d39e92c1c 100644
--- a/src/file/track-revision/track-revision-components/inserted-text-run.ts
+++ b/src/file/track-revision/track-revision-components/inserted-text-run.ts
@@ -1,6 +1,7 @@
-import { IChangedAttributesProperties, ChangeAttributes } from "../track-revision";
import { XmlComponent } from "file/xml-components";
-import { TextRun, IRunOptions } from "../../index";
+
+import { IRunOptions, TextRun } from "../../index";
+import { ChangeAttributes, IChangedAttributesProperties } from "../track-revision";
interface IInsertedRunOptions extends IChangedAttributesProperties, IRunOptions {}
diff --git a/tslint.json b/tslint.json
index d6eb606eba..cb979f920a 100644
--- a/tslint.json
+++ b/tslint.json
@@ -21,6 +21,8 @@
"no-duplicate-imports": true,
"unnecessary-constructor": true,
"file-name-casing": [true, "kebab-case"],
+ "interface-name": [true, "always-prefix"],
+ "ordered-imports": true,
// Functional Programming Rules
"no-parameter-reassignment": true,
"readonly-keyword": true,