diff --git a/.gitignore b/.gitignore index 53f1416525..4f8777b466 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,10 @@ node_modules build build-tests +# Documentation +docs/api/ +docs/.nojekyll + # VSCode .vscode/* !.vscode/settings.json diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..1df213c45d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,33 @@ +

+ clippy the assistant +

+ +

+ Easily generate .docx files with JS/TS. +

+ +--- + +# Welcome + +## Getting Started + +### Installation + +```sh +$ npm install --save docx +``` +Then you can `require` or `import` as usual: + +``` +let docx = require('docx'); +``` + +``` +import * as docx from 'docx' +``` + + +--- + +Made with 💖 diff --git a/docs/_sidebar.md b/docs/_sidebar.md new file mode 100644 index 0000000000..f94c9751d3 --- /dev/null +++ b/docs/_sidebar.md @@ -0,0 +1,27 @@ +* [Getting Started](/) + +* API + + * [Documentation](/api) + +* Usage + + * [Document](usage/document.md) + * [Paragraph](usage/paragraph.md) + * [Text](usage/text.md) + * [Image](usage/images.md) + * [Headers & Footers](usage/headers-and-footers.md) + * [Bullet Points](usage/bullet-points.md) + * [Numbering](usage/numbering.md) + * [Tab Stops](usage/tab-stops.md) + * Styling + * [Styling with JS](usage/styling-with-js.md) + * [Styling with XML](usage/styling-with-xml.md) +* Exporting + + * [Packers](usage/packers.md) + +* [Examples](usage/examples.md) + +* [Contribution Guidelines](contribution-guidelines.md) + diff --git a/docs/contribution-guidelines.md b/docs/contribution-guidelines.md new file mode 100644 index 0000000000..cb49368c38 --- /dev/null +++ b/docs/contribution-guidelines.md @@ -0,0 +1,35 @@ +# Contribution Guidelines + +## Writing Code + +* Include documentation reference(s) at the top of each file: + + ```ts + // http://officeopenxml.com/WPdocument.php + ``` + +* Follow Prettier standards, and consider using the [Prettier VSCode](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) plugin. + +* Follow the `TSLint` rules + +## Testing + +Please write a test of every file you make and suffix it with `.spec.ts`. + +Here is a template of a test: + +```ts +import { assert } from "chai"; + +describe("ClassName", () => { + beforeEach(() => { + // TODO + }); + + describe("#methodName()", () => { + it("should ", () => { + // TODO + }); + }); +}); +``` diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000000..9ff9bd26a2 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,23 @@ + + + + + docx - Generate .docx documents with JavaScript + + + + + + +
+ + + + diff --git a/docs/usage/bullet-points.md b/docs/usage/bullet-points.md new file mode 100644 index 0000000000..c2fb2987d0 --- /dev/null +++ b/docs/usage/bullet-points.md @@ -0,0 +1,21 @@ +# Bullet Points + +## Example + +To make a bullet point, simply make a paragraph into a bullet point: + +```js +var text = new docx.TextRun("Bullet points"); +var paragraph = new docx.Paragraph(text).bullet(); + +var text2 = new docx.TextRun("Are awesome"); +var paragraph2 = new docx.Paragraph(text2).bullet(); + +doc.addParagraph(paragraph); +doc.addParagraph(paragraph2); +``` + +### This will produce: + +* Bullet points +* Are awesome diff --git a/docs/usage/document.md b/docs/usage/document.md new file mode 100644 index 0000000000..f874502d3c --- /dev/null +++ b/docs/usage/document.md @@ -0,0 +1,35 @@ +# Document + +> The `Document` object is the starting point of your `.docx` journey, this is the literal Word Document. You add all your content such as `Paragraphs` to this `Document`, and at the end export it however you like. + +To create a new document, it is very easy: + +```js +var doc = new docx.Document(); +``` + +## Document properties + +You can add properties to the Word document by specifying options, for example: + +```js +var doc = new docx.Document({ + creator: "Dolan Miu", + description: "My extremely interesting document", + title: "My Document", +}); +``` + +### Full list of options: + +``` +creator +description +title +subject +keywords +lastModifiedBy +revision +``` + +You can mix and match whatever properties you want, or provide no properties. diff --git a/docs/usage/headers-and-footers.md b/docs/usage/headers-and-footers.md new file mode 100644 index 0000000000..8c3803cc3f --- /dev/null +++ b/docs/usage/headers-and-footers.md @@ -0,0 +1,47 @@ +# Headers and Footers + +## Example + +Creating Headers and footers is simple. Access the `Header` and `Footer` by doing so like this: + +```ts +doc.Header; +doc.Footer; +``` + +You can call the same methods as you would with a `File`: + +```ts +doc.Header.createParagraph("Header text"); +doc.Footer.createParagraph("Footer text"); +``` + +Even add images: + +```ts +doc.Header.createImage([PATH_TO_YOUR_IMAGE]); +doc.Footer.createImage([PATH_TO_YOUR_IMAGE]); +``` + +Refer to `demo8.js` for more information + +## Multiple Headers and Footers + +Also all the supported section properties are implemented according to: http://officeopenxml.com/WPsection.php + +### Example + +```ts + const header = this.document.createHeader(); + const footer = this.document.createFooter(); + + // Add new section with another header and footer + doc.addSection({ + headerId: header.Header.referenceId, + footerId: footer.Footer.referenceId, + pageNumberStart: 1, + pageNumberFormatType: docx.PageNumberFormat.DECIMAL, + }); +``` + + diff --git a/docs/usage/images.md b/docs/usage/images.md new file mode 100644 index 0000000000..bbd91d31fb --- /dev/null +++ b/docs/usage/images.md @@ -0,0 +1,156 @@ +# Images + +## Intro + +Adding images is very simple + +Simply call the `createImage` method: + +```ts +const image = doc.createImage([PATH_TO_YOUR_IMAGE]); +``` + +`docx` supports `jpeg`, `jpg`, `bmp`, `gif` and `png` + +Check `demo5.js` for an example + +## Positioning + +Images can be: + +* floating position of images +* Wrapped around the text +* Inline + +By default, picture are exported as `INLINE` elements. + +In Word this is found in: + +![Word Image Positiong](https://user-images.githubusercontent.com/34742290/41765548-b0946302-7604-11e8-96f9-166a9f0b8f39.png) + +### Usage + +The `PictureRun` element support various options to define the positioning of the element in the document. + +```ts +interface DrawingOptions { + position?: PlacementPosition; + textWrapping?: TextWrapping; + floating?: Floating; +} +``` + +can be passed when creating `PictureRun()` for example: + +```ts +const imageData = document.createImageData(filename, buffer, 903, 1149); + +new docx.PictureRun(imageData, { + position: docx.PlacementPosition.FLOATING, + floating: { + horizontalPosition: { + relative: HorizontalPositionRelativeFrom.PAGE, + align: HorizontalPositionAlign.LEFT, + }, + verticalPosition: { + relative: VerticalPositionRelativeFrom.PAGE, + align: VerticalPositionAlign.TOP, + }, + }, +}); +``` + +So, the first thing is to define the placement position: `INLINE` or `FLOATING`. Inline is the default one so there is no need to pass drawing options for inline. + +When placement position is FLOATING then we can use two options: + +### Wrap text + +for `drawingOptions.textWrapping` we can define various options. `textWrapping` has the following properties: + +```ts +interface TextWrapping { + textWrapStyle: TextWrapStyle; + wrapTextOption?: WrapTextOption; + distanceFromText?: Distance; +} + +enum TextWrapStyle { + NONE, + SQUARE, + TIGHT, + TOP_AND_BOTTOM, +} + +enum WrapTextOption { + BOTH_SIDES = "bothSides", + LEFT = "left", + RIGHT = "right", + LARGEST = "largest", +} +``` + +### Floating position + +When we want to position the image relative or absolute then we need to use option `drawingOptions.floating`: + +```ts +export interface Floating { + horizontalPosition: HorizontalPositionOptions; + verticalPosition: VerticalPositionOptions; + allowOverlap?: boolean; + lockAnchor?: boolean; + behindDocument?: boolean; + layoutInCell?: boolean; +} + +export interface HorizontalPositionOptions { + relative: HorizontalPositionRelativeFrom; + align?: HorizontalPositionAlign; + offset?: number; +} + +export interface VerticalPositionOptions { + relative: VerticalPositionRelativeFrom; + align?: VerticalPositionAlign; + offset?: number; +} + +export enum HorizontalPositionRelativeFrom { + CHARACTER = "character", + COLUMN = "column", + INSIDE_MARGIN = "insideMargin", + LEFT_MARGIN = "leftMargin", + MARGIN = "margin", + OUTSIDE_MARGIN = "outsideMargin", + PAGE = "page", + RIGHT_MARGIN = "rightMargin", +} + +export enum VerticalPositionRelativeFrom { + BOTTOM_MARGIN = "bottomMargin", + INSIDE_MARGIN = "insideMargin", + LINE = "line", + MARGIN = "margin", + OUTSIDE_MARGIN = "outsideMargin", + PAGE = "page", + PARAGRAPH = "paragraph", + TOP_MARGIN = "topMargin", +} + +export enum HorizontalPositionAlign { + CENTER = "center", + INSIDE = "inside", + LEFT = "left", + OUTSIDE = "outside", + RIGHT = "right", +} + +export enum VerticalPositionAlign { + BOTTOM = "bottom", + CENTER = "center", + INSIDE = "inside", + OUTSIDE = "outside", + TOP = "top", +} +``` diff --git a/docs/usage/numbering.md b/docs/usage/numbering.md new file mode 100644 index 0000000000..69a501b736 --- /dev/null +++ b/docs/usage/numbering.md @@ -0,0 +1,96 @@ +# Bullets and Numbering + +`docx` is quite flexible in its bullets and numbering system, allowing +the user great freedom in how bullets and numbers are to be styled and +displayed. E.g., numbers can be shown using Arabic numerals, roman +numerals, or even ordinal words ("one", "two", "three", ...). The +format also supports re-using bullets/numbering styles throughout the +document, so that different lists using the same style need not +redefine them. + +Because of this flexibility, bullets and numbering in DOCX involves a +couple of moving pieces: + +1. Document-level bullets/numbering definitions (abstract) +2. Document-level bullets/numbering definitions (concrete) +3. Paragraph-level bullets/numbering selection + +## Document-level bullets/numbering definitions (abstract) + +Every document contains a set of abstract bullets/numbering +definitions which define the formatting and layout of paragraphs using +those bullets/numbering. An abstract numbering system defines how +bullets/numbers are to be shown for lists, including any sublists that +may be used. Thus each abstract definition includes a series of +_levels_ which form a sequence starting at 0 indicating the top-level +list look and increasing from there to descibe the sublists, then +sub-sublists, etc. Each level includes the following properties: + +* **level**: This its 0-based index in the defintion stack +* **numberFormat**: This indicates how the bullet or number should be + generated. Options include `bullet` (meaning don't count), `decimal` + (arabic numerals), `upperRoman`, `lowerRoman`, `hex`, and many + more. +* **levelText**: This is a format string using the output of the + `numberFormat` function and generating a string to insert before + every item in the list. You may use `%1`, `%2`, ... to reference the + numbers from each numbering level before this one. Thus a level + text of `%d)` with a number format of `lowerLetter` would result in + the sequence "a)", "b)", ... +* and a few others, which you can see in the OXML spec section 17.9.6 + +## Document-level bullets/numbering defintions (concrete) + +Concrete definitions are sort of like concrete subclasses of the +abstract defintions. They indicate their parent and are allowed to +override certain level definitions. Thus two lists that differ only in +how sub-sub-lists are to be displayed can share the same abstract +numbering definition and have slightly different concrete definitions. + +## Paragraph-level bullets/numbering selection + +In order to use a bullets/numbering definition (which must be +concrete), paragraphs need to select it, similar to applying a CSS +class to an element, using both the concrete numbering definition ID +and the level number that the paragraph should be at. Additionally, MS +Word and LibreOffice typically apply a "ListParagraph" style to +paragraphs that are being numbered. + +## Using bullets/numbering in `docx` + +`docx` includes a pre-defined bullet style which you can add to your +paragraphs using `para.bullets()`. If you require different bullet +styles or numbering of any kind, you'll have to use the +`docx.Numbering` class. + +First you need to create a new numbering container class and use it to +create your abstract numbering style, define your levels, and creat +your concreate numbering style: + +```js +const numbering = new docx.Numbering(); + +const abstractNum = numbering.createAbstractNumbering(); +abstractNum.createLevel(0, "upperRoman", "%1", "start").addParagraphProperty(new Indent(720, 260)); +abstractNum.createLevel(1, "decimal", "%2.", "start").addParagraphProperty(new Indent(1440, 980)); +abstractNum.createLevel(2, "lowerLetter", "%3)", "start").addParagraphProperty(new Indent(2160, 1700)); + +const concrete = numbering.createConcreteNumbering(numberedAbstract); +``` + +You can then apply your concrete style to paragraphs using their +`#setNumbering` method: + +```js +topLevelP.setNumbering(concrete, 0); +subP.setNumbering(concrete, 1); +subSubP.setNumbering(concrete, 2); +``` + +Finally, you need to let your exporter know about your numbering +styles when you're ready to render the document: + +```js +const packer = new Packer(doc, undefined, undefined, numbering); +packer.pack(myOutput); +``` diff --git a/docs/usage/packers.md b/docs/usage/packers.md new file mode 100644 index 0000000000..2db1957b5e --- /dev/null +++ b/docs/usage/packers.md @@ -0,0 +1,67 @@ +# Packers + +I used the express exporter in my [website](http://www.dolan.bio). It's very useful, and is the preferred way if you want to make a downloadable file for a visitor. it is much better than generating a physical file on the server, and then passing a download link to that file. + +## File System Packer + +```js +const docx = require("docx"); + +const doc = new docx.Document(); +const exporter = new docx.LocalPacker(doc); +exporter.pack("My Document"); +// Word Document is in file system +``` + +## Buffer Packer + +```js +const docx = require("docx"); + +const doc = new docx.Document(); +const exporter = new docx.BufferPacker(doc); +const buffer = exporter.pack(); +``` + +## Stream Packer + +Creates a `node` `Readable` stream + +```js +const docx = require("docx"); + +const doc = new docx.Document(); +const exporter = new docx.StreamPacker(doc); +const buffer = exporter.pack(); +``` + +## Express Packer + +Simply use the exporter, and pass in the necessary parameters: + +```js +const docx = require("docx"); + +const doc = new docx.Document(); +const exporter = new docx.ExpressPacker(doc, res); +exporter.pack("My Document"); +``` + +where `res` is the response object obtained through the Express router. It is that simple. The file will begin downloading in the browser. + +## PDF Exporting + +You can export your word document as a PDF file like so: + +```js +const exporter = new docx.LocalPacker(doc); +exporter.packPdf("My Document"); + +// Express +const exporter = new docx.ExpressPacker(doc, res); +exporter.packPdf("My Document"); +``` + +## Browser based docx exporting + +It is on the bucket list. It has been requested by a few, and work is already on it diff --git a/docs/usage/paragraph.md b/docs/usage/paragraph.md new file mode 100644 index 0000000000..6f3ee39ac5 --- /dev/null +++ b/docs/usage/paragraph.md @@ -0,0 +1,113 @@ +# Paragraph + +> Everything (text, images, graphs etc) in OpenXML is organised in paragraphs. + +## Example + +You can add more text to the paragraph by doing this: + +```js +var paragraph = new docx.Paragraph(), +``` + +```js +var text = new docx.TextRun("Lorem Ipsum Foo Bar"); +var paragraph = new docx.Paragraph(); +paragraph.addRun(text); +``` + +```js +var paragraph = new docx.Paragraph("Short hand notation for adding text."); +``` + +After you create the paragraph, you must add the paragraph into the `document`: + +```js +doc.addParagraph(paragraph); +``` + +## Styles + +To create styles, please refer to the styling Wiki: https://github.com/dolanmiu/docx/wiki/Styling + +![Word 2013 Styles menu](http://content.gcflearnfree.org/topics/233/style_apply_choose.png "Word 2013 Styles menu") + +### Heading1 - Heading5 + +```js +paragraph.heading1(); +paragraph.heading2(); +paragraph.heading3(); +paragraph.heading4(); +paragraph.heading5(); +``` + +### Title + +```js +paragraph.title(); +``` + +## Text Alignment + +To change the text alignment of a paragraph, for center, left, right or justified: + +```js +paragraph.center(); +``` + +```js +paragraph.left(); +``` + +```js +paragraph.right(); +``` + +```js +paragraph.justified(); +``` + +### Example + +```js +paragraph.heading1().center(); +``` + +The above will create a `heading 1` which is `centered`. + +## Thematic Break + +To add a break in the page, simply add `.thematicBreak()` on a paragraph: + +```js +var paragraph = new docx.Paragraph("Amazing Heading").heading1().thematicBreak(); +``` + +The above example will create a heading with a page break directly under it. + +## Page Break + +To move to a new page (insert a page break), simply add `.pageBreak()` on a paragraph: + +```js +var paragraph = new docx.Paragraph("Amazing Heading").heading1().pageBreak(); +``` + +The above example will create a heading and start a new page immediately afterwards. + +### Page break before: + +This option (available in word) will make sure that the paragraph will start on a new page (if it's not already on a new page). + +```js +var paragraph = new docx.Paragraph("Hello World on another page").pageBreakBefore(); +``` + +![Page Break Before in Word](https://user-images.githubusercontent.com/34742290/40176503-df3a8398-59db-11e8-8b9c-d719f13aa8b4.png) + +Example: https://github.com/dolanmiu/docx/blob/master/demo/demo15.js + +## Page break control + +Paragraphs have `.keepLines()` and `.keepNext()` methods that allow restricting page breaks within and between paragraphs. See [this Microsoft article](https://support.office.com/en-us/article/Keep-lines-and-paragraphs-together-d72af534-926f-4c4b-830a-abfc2daa3bfa) for more details) diff --git a/docs/usage/styling-with-js.md b/docs/usage/styling-with-js.md new file mode 100644 index 0000000000..3e482bca14 --- /dev/null +++ b/docs/usage/styling-with-js.md @@ -0,0 +1,162 @@ +# Styling with JS + +## Example + +```js +const para = new Paragraph("To whom it may concern:").heading2().center(); + +const name = new TextRun("Name:") + .bold() + .font("Calibri") + .allCaps(); +``` + +## Available methods + +* For run formatting: + * `.bold()`, `.italic()`, `.smallCaps()`, `.allCaps()`, `.strike()`, `.doubleStrike()`, `.subScript()`, `.superScript()`: Set the formatting property to true + * `.underline(style="single", color=null)`: Set the underline style and color + * `.color(color)`: Set the text color, using 6 hex characters for RRGGBB (no leading `#`) + * `.size(halfPts)`: Set the font size, measured in half-points + * `.font(name)`: Set the run's font + * `.style(name)`: Apply a named run style +* For paragraph formatting: + * `.heading1()`, `.heading2()`, `.heading3()`, `.heading4()`, `.heading5()`, `.title()`: apply the appropriate style to the paragraph + * `.left()`, `.center()`, `.right()`, `.justified()`: set the paragraph's alignment + * `.thematicBreak()`, `.pageBreak()`: Insert a thick rule or a page break beneath the paragraph + * `.leftTabStop(position)`: Add a left tab stop (measured in TWIPs from the left) + * `.maxRightTabStop()`: Add a right tab stop at the far right + * `.bullet()`: Use the default bullet style + * `.setNumbering(numbering, indentLevel)`: Use a custom numbering format for the paragraph + * `.style(name)`: Apply a named paragraph style + * `.indent(start, hanging=0)`: Set the paragraph's indent level (in TWIPs) + * `.spacing({before=0, after=0, line=0})`: Set the line and before/after on the paragraph. Before/after is measured in TWIPs, line is measured in 240ths of a line + +Paragraph styles have all the run formatting methods, except `style()`, and `.left()`, `.center()`, `.right()`, `.justified()`, `.thematicBreak()`, `.leftTabStop(position)`, `.maxRightTabStop()`, `.indent(start, hanging=0)`, and `.spacing({before=0, after=0, line=0})` methods. + +## Detailed guide + +There are 4 items in DOCX that can be styled: + +* Characters: Attributes that can change within a paragraph. e.g., bold, italics, etc. +* Paragraphs: Attributes like indent, text alignment, line spacing, etc. +* Tables: Border styles, table formats, etc. +* List items: These are the numbers and bullets that are automatically inserted + +There are a few different ways of styling this content in DOCX, which somewhat resemble the HTML/CSS approach. In order of greatest to lowest priority: + +1. Direct formatting (AKA inline formatting) +2. Centrally defined styles (similar to external CSS) +3. Document defaults (similar to a `*` rule in CSS) + +Unlike CSS, less specific rules don't _necessarily_ override parent rules. The rules are a bit wonky, but if you're interested, see the [advanced formatting section](#Advanced formatting). + +### Direct formatting (AKA inline formatting) + +This is the type of formatting that your uncle uses when he types out documents: _N ... a ... m ... e ... :_ Then he grabs the mouse, highlights _Name:_ and moves over to the **B** for bold. This manner of formatting results in markup that is similar to writing `Name:` if you were typing out HTML. DOCX (the format) allows you to specify this for any of the four types of items. `docx` (the library) only supports this type of formatting for paragraphs and characters, using a _fluent_ api. Thus you could do: + +```js +const name = new TextRun("Name:") + .bold() + .font("Calibri") + .allCaps(); +``` + +Or for paragraph formatting: + +```js +const para = new Paragraph("To whom it may concern:").heading2().center(); +``` + +### Centrally defined styles (similar to external CSS) + +DOCX files contain a styles section separate from the main content, much like how HTML includes CSS files. Unlike CSS, DOCX distinguishes between styles meant for tables (which show up in the table formatting toolbar), styles for lists (which show up under bullets and numbering), and styles for runs and paragraphs, which show up as dropdowns offering standard styles, like "Heading 1", "Caption", or any custom styles defined in that document. . `docx` allows you to define these styles using a fluent interface as well. + +There are three parts to using custom styles with `docx`: + +1. Create a container object for the style definitions: + ```js + const myStyles = new docx.Styles(); + ``` +2. Define your custom styles, similar to the way you would format a paragraph or run + + ```js + // The first argument is an ID you use to apply the style to paragraphs + // The second argument is a human-friendly name to show in the UI + myStyles + .createParagraphStyle("myWonkyStyle", "My Wonky Style") + .basedOn("Normal") + .next("Normal") + .color("999999") + .italics() + .indent(720) // 720 TWIP === 720 / 20 pt === .5 in + .spacing({ line: 276 }); // 276 / 240 = 1.15x line spacing + + myStyles + .createParagraphStyle("Heading2", "Heading 2") + .basedOn("Normal") + .next("Normal") + .quickFormat() + .size(26) // 26 half-points === 13pt font + .bold() + .underline("double", "FF0000") + .spacing({ before: 240, after: 120 }); // TWIP for both + ``` + +3. When you generate your document, make sure to pass the `styles` container to the `Packer`: + + ```js + const packer = new Packer(doc, myStyles); + packer.pack(myOutStream); + ``` + +**Note**: If you are using the `.headingX` or `.title` methods of paragraphs, you must make sure to define `HeadingX` or `Title` styles for these. Otherwise they'll show up unstyled :(. If you are using the `.bullet` or `.setNumbering` methods, you need to define a `ListParagraph` style or the numbers may not show up. + +### Document defaults + +Setting document defaults acts like a `*` rule in CSS: it applies to every paragraph and run in the document, but at a low priority level. Other styles affecting this property will override these defaults. + +## Advanced formatting + +### Style inheritance + +Styles may define a `basedOn` attribute that references another style of the same type. In this case, any unspecified properties are inherited from the parent style. + +### Interactions between the 4 items + +In addition to the 3-layer hierarchy spelled above, there is some interaction between the 4 items that you can style. +For instance numbering styles may also specify some styling for paragraphs (typically indentation and tab stops); paragraphs may specify character formatting (e.g., heading font sizes); etc. + +The elements that each style may affect are summarized in the table below. So, e.g., table styles may specify table formatting, paragraph formatting, and character formatting. + +| Style type | Table | Paragraph | List item | Characters | +| :---------------- | :---: | :-------: | :-------: | :--------: | +| Document defaults | | X | | X | +| Table | X | X | | X | +| Paragraph | | X | X | X | +| Numbering | | X | X | | +| Character | | | | X | +| Direct formatting | X | X | X | X | + +To determine the value of a styling property, you must first identify whether it's a table, paragraph, list item, or character property. E.g., numbering definition is a list item property. Then you need to find the last row in the table for which that property has an "X" and the document has formatting of that type. So if a particular run was in a paragraph whose style specified color as `FF0000`, but it also had a character style specifying color as `00DD00`, then the character style (lower down on the table) would trump, and the character would have color `00DD00`. + +### Toggle properties + +The following properties are treated in a special manner; they're called toggle properties: + +* Bold +* All caps +* Small caps +* Italics +* Single strike-through +* Hidden +* Imprint +* Emboss +* Character outline +* Character shadow + +For these properties, the rules state the following conflict resolution in case the property is specified at multiple points for the same item: + +* Direct formatting trumps all if specified (either true or false) +* Otherwise, if the property is true in document defaults, the property is set to true +* Otherwise, the property's value is an XOR of its effective table, paragraph, and character values. (So specifying bold `true` on a table style and a paragraph style would result in non-bold text if a paragraph inside the table had that style) diff --git a/docs/usage/styling-with-xml.md b/docs/usage/styling-with-xml.md new file mode 100644 index 0000000000..ac3a757d36 --- /dev/null +++ b/docs/usage/styling-with-xml.md @@ -0,0 +1,47 @@ +# Styling with XML + +## Setup + +1. Create a new word document in Microsoft Word +2. Customise the styles on the Ribbon Bar. + For example, modify the `Normal`, `Heading 1`, `Heading 2` like so: + + ![image](https://user-images.githubusercontent.com/2917613/41195113-65edebfa-6c1f-11e8-97b4-77de2d60044a.png) + ![image](https://user-images.githubusercontent.com/2917613/41195126-ca99c36c-6c1f-11e8-9e58-19e5f69b3b87.png) + +3. You can even create a totally new `Style`: + + ![image](https://user-images.githubusercontent.com/2917613/41195135-f0f7862a-6c1f-11e8-8be4-dd6d8fe5be03.png) + ![image](https://user-images.githubusercontent.com/2917613/41195139-0ec52130-6c20-11e8-8fae-f6b44b43fdf8.png) + +4. Save +5. Re-name the saved `.docx` file to `.zip` and un-zip +6. Find `styles.xml` + + ![image](https://user-images.githubusercontent.com/2917613/41195178-bb9ba9c4-6c20-11e8-850e-a7a6ada9a2f6.png) + +## Usage + +Read the styles using `fs`, and put it into the `Document` object in the constructor: + +```js +const styles = fs.readFileSync("./styles.xml", "utf-8"); +const doc = new docx.Document({ + title: "Title", + externalStyles: styles, +}); +``` + +You can use paragraphs, `heading1()`, `heading2()` etc and it will be styled according to your `styles.xml` created earlier. You can even use your new style you made by calling the `style` method: + +```js +doc.createParagraph("Cool Heading Text").heading1(); + +let paragraph = new docx.Paragraph('This is a custom named style from the template "Cool New Style"'); +paragraph.style("Cool New Style"); +doc.addParagraph(paragraph); + +doc.createParagraph("Some normal text"); +``` + +Example: https://github.com/dolanmiu/docx/blob/master/demo/demo13.js diff --git a/docs/usage/tab-stops.md b/docs/usage/tab-stops.md new file mode 100644 index 0000000000..8447d03998 --- /dev/null +++ b/docs/usage/tab-stops.md @@ -0,0 +1,54 @@ +# Tab Stops + +> Tab stops are useful, if you are unclear of what they are, [here is a link explaining](https://en.wikipedia.org/wiki/Tab_stop). It enables side by side text which is nicely laid out without the need for tables, or constantly pressing space bar. + +**Note**: At the moment, the unit of measurement for a tab stop is counter intuitive for a human. It is using OpenXMLs own measuring system. For example, 2268 roughly translates to 3cm. Therefore in the future, I may consider changing it to percentages or even cm. + +![Word 2013 Tabs](http://www.teachucomp.com/wp-content/uploads/blog-4-22-2015-UsingTabStopsInWord-1024x577.png "Word 2013 Tab Stops") + +Simply call the relevant methods on the paragraph listed below. Then just add a `tab()` method call to a text object. Adding multiple `tabStops` will mean you would have to chain `tab()` until the desired `tabStop` is selected. Example is shown below. + +## Example + +```js +var paragraph = new docx.Paragraph().maxRightTabStop(); +var leftText = new docx.TextRun("Hey everyone").bold(); +var rightText = new docx.TextRun("11th November 2015").tab(); +paragraph.addRun(leftText); +paragraph.addRun(rightText); +``` +The example above will create a left aligned text, and a right aligned text on the same line. The laymans approach to this problem would be to either use text boxes or tables. YUK! + +```js +var paragraph = new docx.Paragraph(); +paragraph.maxRightTabStop(); +paragraph.leftTabStop(1000); +var text = new docx.TextRun("Second tab stop here I come!").tab().tab(); +paragraph.addRun(text); +``` + +The above shows the use of two tab stops, and how to select/use it. + +## Left Tab Stop +```js +paragraph.leftTabStop(2268); +``` +2268 is the distance from the left side. + +## Center Tab Stop +```js +paragraph.centerTabStop(2268); +``` +2268 is the distance from the left side. + +## Right Tab Stop +```js +paragraph.rightTabStop(2268); +``` +2268 is the distance from the left side. + +## Max Right Tab Stop +```js +paragraph.maxRightTabStop(); +``` +This will create a tab stop on the very edge of the right hand side. Handy for right aligning and left aligning text on the same line. diff --git a/docs/usage/text.md b/docs/usage/text.md new file mode 100644 index 0000000000..3ca98804bb --- /dev/null +++ b/docs/usage/text.md @@ -0,0 +1,84 @@ +# Text + +Paragraphs need `text run` objects. To create text: + +```js +var text = new docx.TextRun("My awesome text here for my university dissertation"); +paragraph.addRun(text); +``` + +Text objects have methods inside which changes the way the text is displayed. + +## Typographical Emphasis + +More info [here](https://english.stackexchange.com/questions/97081/what-is-the-typography-term-which-refers-to-the-usage-of-bold-italics-and-unde) + +### Bold + +```js +text.bold(); +``` + +### Italics + +```js +text.italic(); +``` + +### Underline + +```js +text.underline(); +``` + +### Strike through + +```js +text.strike(); +``` + +### Double strike through + +```js +text.doubleStrike(); +``` + +### Superscript + +```js +text.superScript(); +``` + +### Subscript + +```js +text.subScript(); +``` + +### All Capitals + +```js +text.allCaps(); +``` + +### Small Capitals + +```js +text.smallCaps(); +``` + +## Break + +Sometimes you would want to put text underneath another line of text but inside the same paragraph. + +```js +text.break(); +``` + +## Chaining + +What if you want to create a paragraph which is **_bold_** and **_italic_**? + +```js +paragraph.bold().italic(); +``` diff --git a/package.json b/package.json index 2eaf10efab..9e292bcb1c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "tsc": "rimraf ./build && tsc -p .", "webpack": "rimraf ./build && webpack", "demo": "npm run build && node ./demo", - "typedoc": "typedoc --out docs/ src/ --module commonjs --target ES6 --disableOutputCheck --excludePrivate --externalPattern \"**/*.spec.ts\"", + "typedoc": "typedoc --out docs/api/ src/ --module commonjs --target ES6 --disableOutputCheck --excludePrivate --externalPattern \"**/*.spec.ts\"", "style": "prettier -l \"src/**/*.ts\"", "style.fix": "prettier \"src/**/*.ts\" --write", "fix-types": "node types-absolute-fixer.js"