Add SymbolRun to allow adding symbols inline

This commit is contained in:
James Montalvo
2019-10-01 12:29:07 -05:00
parent d2dded860d
commit dfb910defb
8 changed files with 207 additions and 5 deletions

View File

@ -2,7 +2,7 @@
> Everything (text, images, graphs etc) in OpenXML is organised in paragraphs. > Everything (text, images, graphs etc) in OpenXML is organised in paragraphs.
!> Paragraphs requires an understanding of [Sections](usage/sections.md). !> Paragraphs requires an understanding of [Sections](sections.md).
You can create `Paragraphs` in the following ways: You can create `Paragraphs` in the following ways:
@ -16,11 +16,15 @@ const paragraph = new Paragraph("Short hand Hello World");
### Children Method ### Children Method
This method is useful for adding different `text` with different styles or adding `images` inline. This method is useful for adding different [text](text.md) with different styles, [symbols](symbols.md), or adding [images](images.md) inline.
```ts ```ts
const paragraph = new Paragraph({ const paragraph = new Paragraph({
children: [new TextRun("Lorem Ipsum Foo Bar"), new TextRun("Hello World")], children: [
new TextRun("Lorem Ipsum Foo Bar"),
new TextRun("Hello World"),
new SymbolRun("F071"),
],
}); });
``` ```

53
docs/usage/symbols.md Normal file
View File

@ -0,0 +1,53 @@
# Symbol Runs
!> SymbolRuns require an understanding of [Paragraphs](paragraph.md).
You can add multiple `symbol runs` in `Paragraphs` along with [text runs](text.md) using the Paragraph's `children` property.
```ts
import { Paragraph, TextRun, SymbolRun } from "docx";
const paragraph = new Paragraph({
children: [
new TextRun("This is a checkbox: "),
new SymbolRun("F071")
],
});
```
## Specifying symbol font
By default symbol runs will use the `Wingdings` font. To switch fonts, pass an object instead of a string to the `SymbolRun` constructor and specify `char` and `symbolfont` properties:
```ts
const symbol = new SymbolRun({
char: "F071",
symbolfont: "Arial",
});
```
## Example symbols
Symbols are specified by their hexidecimal code. Ref http://officeopenxml.com/WPtextSpecialContent-symbol.php. Below are some examples.
- `F071`: empty checkbox
- `F043`: thumbs up
- `F04A`: smile
- `F04C`: frown
- `F022`: scissors
- `F0F0`: right arrow
- `F0FE`: checked box
## Typographical Emphasis
Symbol runs can have their display modified just like text runs. For example, they can be bolded and italicized:
```ts
const symbol = new SymbolRun({
char: "F071",
bold: true,
italics: true,
});
```
See the [text run](text.md) documentation for more info.

View File

@ -15,7 +15,7 @@ import { CenterTabStop, LeaderType, LeftTabStop, MaxRightTabStop, RightTabStop }
import { NumberProperties } from "./formatting/unordered-list"; import { NumberProperties } from "./formatting/unordered-list";
import { Bookmark, Hyperlink, OutlineLevel } from "./links"; import { Bookmark, Hyperlink, OutlineLevel } from "./links";
import { ParagraphProperties } from "./properties"; import { ParagraphProperties } from "./properties";
import { PictureRun, Run, SequentialIdentifier, TextRun } from "./run"; import { PictureRun, Run, SequentialIdentifier, SymbolRun, TextRun } from "./run";
interface ITabStopOptions { interface ITabStopOptions {
readonly position: number; readonly position: number;
@ -53,7 +53,7 @@ export interface IParagraphOptions {
readonly level: number; readonly level: number;
readonly custom?: boolean; readonly custom?: boolean;
}; };
readonly children?: Array<TextRun | PictureRun | Hyperlink>; readonly children?: Array<TextRun | PictureRun | Hyperlink | SymbolRun>;
} }
export class Paragraph extends XmlComponent { export class Paragraph extends XmlComponent {

View File

@ -1,4 +1,5 @@
export * from "./run"; export * from "./run";
export * from "./text-run"; export * from "./text-run";
export * from "./symbol-run";
export * from "./picture-run"; export * from "./picture-run";
export * from "./sequential-identifier"; export * from "./sequential-identifier";

View File

@ -0,0 +1,28 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
import { Symbol } from "./symbol";
describe("Symbol", () => {
describe("#constructor", () => {
// Note: if no character is given, the output is a MS Windows logo
it("creates an empty symbol run if no character is given", () => {
const s = new Symbol();
const f = new Formatter().format(s);
expect(f).to.deep.equal({ "w:sym": { _attr: { "w:char": "", "w:font": "Wingdings" } } });
});
it("creates the provided symbol with default font", () => {
const s = new Symbol("F071");
const f = new Formatter().format(s);
expect(f).to.deep.equal({ "w:sym": { _attr: { "w:char": "F071", "w:font": "Wingdings" } } });
});
it("creates the provided symbol with the provided font", () => {
const s = new Symbol("F071", "Arial");
const f = new Formatter().format(s);
expect(f).to.deep.equal({ "w:sym": { _attr: { "w:char": "F071", "w:font": "Arial" } } });
});
});
});

View File

@ -0,0 +1,20 @@
import { XmlAttributeComponent, XmlComponent } from "file/xml-components";
interface ISymbolAttributesProperties {
readonly char: string;
readonly symbolfont?: string;
}
class SymbolAttributes extends XmlAttributeComponent<ISymbolAttributesProperties> {
protected readonly xmlKeys = {
char: "w:char",
symbolfont: "w:font",
};
}
export class Symbol extends XmlComponent {
constructor(char: string = "", symbolfont: string = "Wingdings") {
super("w:sym");
this.root.push(new SymbolAttributes({ char: char, symbolfont: symbolfont }));
}
}

View File

@ -0,0 +1,76 @@
import { expect } from "chai";
import { Formatter } from "export/formatter";
import { UnderlineType } from "./underline";
import { SymbolRun } from "./symbol-run";
describe("SymbolRun", () => {
let run: SymbolRun;
describe("#constructor()", () => {
it("should create symbol run from text input", () => {
run = new SymbolRun("F071");
const f = new Formatter().format(run);
expect(f).to.deep.equal({
"w:r": [{ "w:sym": { _attr: { "w:char": "F071", "w:font": "Wingdings" } } }],
});
});
it("should create symbol run from object input with just 'char' specified", () => {
run = new SymbolRun({ char: "F071" });
const f = new Formatter().format(run);
expect(f).to.deep.equal({
"w:r": [{ "w:sym": { _attr: { "w:char": "F071", "w:font": "Wingdings" } } }],
});
});
it("should create symbol run from object input with just 'char' specified", () => {
run = new SymbolRun({ char: "F071", symbolfont: "Arial" });
const f = new Formatter().format(run);
expect(f).to.deep.equal({
"w:r": [{ "w:sym": { _attr: { "w:char": "F071", "w:font": "Arial" } } }],
});
});
it("should add other standard run properties", () => {
run = new SymbolRun({
char: "F071",
symbolfont: "Arial",
italics: true,
bold: true,
underline: {
color: "red",
type: UnderlineType.DOUBLE,
},
color: "green",
size: 40,
highlight: "yellow",
});
const f = new Formatter().format(run);
expect(f).to.deep.equal({
"w:r": [
{
"w:rPr": [
{ "w:b": { _attr: { "w:val": true } } },
{ "w:bCs": { _attr: { "w:val": true } } },
{ "w:i": { _attr: { "w:val": true } } },
{ "w:iCs": { _attr: { "w:val": true } } },
{ "w:u": { _attr: { "w:val": "double", "w:color": "red" } } },
{ "w:color": { _attr: { "w:val": "green" } } },
{ "w:sz": { _attr: { "w:val": 40 } } },
{ "w:szCs": { _attr: { "w:val": 40 } } },
{ "w:highlight": { _attr: { "w:val": "yellow" } } },
{ "w:highlightCs": { _attr: { "w:val": "yellow" } } },
],
},
{
"w:sym": { _attr: { "w:char": "F071", "w:font": "Arial" } },
},
],
});
});
});
});

View File

@ -0,0 +1,20 @@
import { IRunOptions, Run } from "./run";
import { Symbol } from "./run-components/symbol";
export interface ISymbolRunOptions extends IRunOptions {
readonly char: string;
readonly symbolfont?: string;
}
export class SymbolRun extends Run {
constructor(options: ISymbolRunOptions | string) {
if (typeof options === "string") {
super({});
this.root.push(new Symbol(options));
return;
}
super(options);
this.root.push(new Symbol(options.char, options.symbolfont));
}
}