Easily generate .docx files with HTML and CSS.
beautiful-docx
is a wrapper around docx
library that allows you to create beautiful .docx documents using HTML and CSS (inline styles) instead of JS objects.
This library is different from other available HTML to DOCX converters because of the following features (among others):
- table of content generation
- page numbering
- custom page sizes and margins
- paragraph first line indentation
- automatic or manual images downloading
- table and image sizing and positioning
The library is writted with TypeScript and is fully covered with unit tests.
beautiful-docx
is created and maintained by Flexum. PRs are welcome. Contact us at opensource@flexum.io.
Here's an example of an HTML document that allows you to generate the following file (utilizing these parameters):
Click to open TOC
Supported: a, article, blockquote, br, caption, col, colgroup, div, figure, h1-h6, i, img, li, ol, p, s, del, section, strong, table, tbody, td, tfoot, th, tr, u, ul, em, span, sub, sup, b, pre, aside, html, body, main, header, footer, nav
Custom elements: page-break, table-of-contents
Unsupported: abbr, address, cite, code, dd, din, dl, dt, figcaption, hr, ins, kbd, mark, picture, q, small, time
npm install beautiful-docx
Start with creating a converter instance. You may pass options object as an argument.
The converter exposes a generateDocx
method that receives an HTML string and returns a buffer containing the final document.
import { DocxGenerator } from 'beautiful-docx';
import * as fs from 'fs';
const html = `
<div>
<p>Example</p>
</div>
`;
const docxGenerator = new DocxGenerator({
page: {
size: {
width: 5.5,
height: 8,
},
},
});
const buffer = await docxGenerator.generateDocx(html);
fs.writeFileSync('example.docx', buffer);
Options is an object with the following fields.
Sets document page settings.
-
orientation: PageOrientation
Page orientation.
Available values:
'portrait'
,'landscape'
Default:
'portrait'
Example:
import { PageOrientation } from 'beautiful-docx'; const options = { page: { orientation: PageOrientation.Portrait, }, };
-
size: PageSize
Page width and height in inches.
-
width: number
-
height: number
You can use ready-made page sizes -
PageFormat
Available values:
A3, A4, A5, A6
;Default:
A4
(8.3’x11.7’)Example:
import { PageFormat } from 'beautiful-docx'; const options = { page: { sizes: PageFormat.A4, }, };
const options = { page: { sizes: { width: 8.3, height: 11.7, }, }, };
-
-
margins: object
Page margins in millimeters.
-
top: number
Default: 25.4
-
left: number
Default: 25.4
-
bottom: number
Default: 25.4
-
right: number
Default: 25.4
Example:
const options = { page: { margins: { top: 25, left: 25, right: 20, bottom: 25, }, }, };
-
-
numbering: false | NumberingOptions
Responsible for displaying page numbering.
-
start: number
Default:
1
-
type: NumberFormat
Default:
NumberFormat.DECIMAL
-
align: AlignmentType
Default:
AlignmentType.CENTER
Example:
const options = { page: { numbering: { type: NumberFormat.LOWER_LETTER, align: AlignmentType.END, }, }, };
-
Configuration of font sizes and font-family.
-
baseSize: number
Base text font size in points.
Default:
12
Example:
const options = { font: { baseSize: 11, }, };
-
headersSizes: object
Header font sizes of different levels-
h1: number
Default:
19.5
-
h2: number
Default:
16.5
-
h3: number
Default:
15
-
h4: number
Default:
13.5
-
h5: number
Default:
12
-
h6: number
Default:
10.5
Example:
const options = { font: { headersSizes: { h1: 22, h2: 20, h3: 18, h4: 16, }, }, };
-
-
baseFontFamily: string
Font family for base text
Available values: any Microsoft Office Word font.
Default:
'Arial'
Example:
const options = { font: { baseFontFamily: 'Times New Roman', }, };
-
headersFontFamily: string
Font family for headers.
Available values: any Microsoft Office Word font.
Default:
'Arial'
Example:
const options = { font: { headersFontFamily: 'Times New Roman', }, };
Properties of tables.
-
cellPaddings: object
Table cell paddings configuration in pixels
-
top: number
Default:
5
-
left: number
Default:
5
-
right: number
Default:
5
-
bottom: number
Default:
5
Example:
const options = { table: { cellPaddings: { top: 10, left: 15, }, }, };
-
The images
parameter allows you to preload the images used in the html
.
This is an object in which the urls
of the images are the keys, and the Buffer
with the image is the value.
If you do not pass the images
parameter, the images will be automatically loaded from the src
attributes of the img
tags.
Example:
const imageSourceUrl = 'https://example.com/image.png';
const html = `
<img src="${imageSourceUrl}" />
`;
const res = await axios.get(imageSourceUrl, { responseType: 'arraybuffer' });
const imageBuffer = Buffer.from(res.data, 'binary');
const options = {
images: {
[imageSourceUrl]: imageBuffer,
},
};
Vertical indents between lines ratio.
Default: 1
Example:
const options: {
verticalSpaces: 1.15;
};
If false
, adds an indent for the first line of the paragraph.
Indentation is ignored for the first paragraph in a block.
Default: true
Example:
const options: {
textIndentation: false;
};
The beautiful-docx
library supports various types of html
input content.
Will be reformatted into a paragraph with appropriate content.
Example:
const html = 'Some plain text'; // transforms to: <p>Some plain text</p>
The library supports the following inline elements: 'strong', 'i', 'u', 's', 'br'
.
Each inline element on the top level will be wrapped with <p>
, for example:
Example:
const html = `
<strong>strong</strong>
<i>italic</i>
`;
// transforms to:
// <p><strong>strong</strong></p>
// <p><i>italic</i></p>
To avoid this you should keep inline elements within block elements.
The library allows the following container elements: 'div', 'article', 'section', 'html', 'body', 'aside', 'main', 'header', 'aside', 'footer', 'nav', 'pre'
.
The library effectively ignores these elements and treats the inner content as a top-level content.
Example:
const html = `
<div>plain text</div>
<section><p>paragraph</p></section>
`;
// transforms to:
// <p>plain text</p>
// <p>paragraph</p>
The library supports the following block elements: 'p', 'h1', 'h2', 'h3', 'h4', 'ul', 'ol', 'figure', 'blockquote', 'table', 'img'
.
Block elements cannot be nested in other block elements, except for the cases provided for in the exceptions (see the description for each specific element).
Example:
const html = `
<h1>H1 Example</h1>
<h2>H2 Example</h2>
<h3>H3 Example</h3>
<h4>H4 Example</h4>
<p>paragraph with <i>italic</i> text</p>
<ol>
<li>List Item</li>
<li>List Item</li>
<li>List Item</li>
</ol>
`;
Supported custom elements: page-break
, table-of-contents
.
Custom elements are used to insert additional content.
Container elements.
Can be nested in:
- document root
- other container element
Supported content:
- root content
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<section>
<article>
<div>
<p>Paragraph</p>
</div>
</article>
</section>
`;
Converts to a paragraph with text.
Can be nested in:
- document root
- container element
li
(known issue: displayed with a new line)blockquote
caption
td
Supported content:
- plain text
- inline-tags
img
Attributes: not supported
Inline-styles:
-
text-align
- horizontal text positionAvailable values:
justify
,left
,center
,right
Default:
left
Extra:
By default, text-indent
is added for paragraphs (except the first paragraph in each block). This can be disabled by passing ignoreIndentation: true
.
If necessary, you can add vertical indents between paragraphs. For this, you need to pass the parameter verticalSpaces
.
Example:
const html = `
<p style='text-align: center'>Paragraph 1</p>
<p>Paragraph 2</p>
<ul>
<li>
<p>List item</p>
</li>
</ul>
`;
Block elements. They are converted into headings of the appropriate level. Participate in table-of-contents
formation.
Can be nested in:
- document root
- container element
li
(partial support - displayed from a new line)caption
td
Supported content:
- plain text
- inline elements
img
Attributes: not supported
Inline-styles:
-
text-align
- horizontal text positionAvailable values:
justify
,left
,center
,right
Default:
left
Extra:
For headings, you can set the font size
and font-family
. To do this, you need to pass the appropriate parameters: font.headersSizes
, font.headersFontFamily
.
Example:
const html = `
<h1 style='text-align: center'>Page Title</h1>
<h2><i>Page subtitle</i></h2>
`;
Block elements. Convert to lists.
Can be nested in:
- document root
- container element
li
- are displayed as lower-level listscaption
td
Supported content:
li
- plain text - not recommended. Displayed from a new line as a paragraph
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<ul>
<li>List item
<ol>
<li>List Item</li>
<li>List Item</li>
<li>List Item</li>
</ol>
</li>
<li>List item</li>
<ul>
`;
Block element. Displayed as a list item.
Can be nested in:
ul
Supported content:
- plain text - displayed as a list item
- root content - is displayed from a new line as plain text
ul
- nested list
Attributes: not supported
Inline-styles:
-
text-align
- horizontal text positionAvailable values:
justify
,left
,center
,right
Default:
left
Example:
const html = `
<ul>
<li>List item
<ol>
<li>List Item</li>
<li>List Item</li>
<li>List Item</li>
</ol>
</li>
<li>List item</li>
<ul>
`;
Block element.
Can be nested in:
- document root
- container element
li
caption
td
Supported content:
img
table
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<figure>
<img src='https://example.com/image.png'/>
</figure>
<figure>
<table>
<tbody>
<tr>
<td>Example</td>
</tr>
</tbody>
</table>
</figure>
`;
Inline-block element. Responsible for displaying images.
Can be nested in:
- document root
- container element
li
caption
td
figure
Supported content: not supported
Attributes:
-
src
URL to download the image.
Inline-styles:
-
float
Necessary for horizontal image positioning. Without an attribute - the image will be located in the center of the page
Available values:
left, right, center
Default:
center
-
width
Image width. Available units -
%, px, vw
If you do not specify the width, it will be automatically calculated from the initial dimensions of the image. If the width of the image is greater than the dimensions of the page - the image will be displayed on the entire width of the page.
If you set the width in
%
orvw
- the width will be calculated based on the page size.If you set the width in
px
- the width of the image will be equal to the value, but not more than the width of the page. Image height is calculated automatically based on image width and aspect ratio.
Extra:
Image orientation is calculated automatically based on file metadata.
Images for insertion can be preloaded (if they are found locally on the device or server). To do this, you need to download the image as a buffer and insert it into the images
options parameter.
If a paragraph is found after the image, the image will be "linked" to this paragraph. If there is no paragraph after the image, it will be created automatically.
Example:
const url = 'https://example.com/image.png';
const html = `
<figure>
<img src='${url}'/>
</figure>
<img style='width: 100px; float: right' src='${url}'/>
<img style='width: 50%; float: left' src='${url}'/>
`;
Block element. Displayed as italic text with left border.
Can be nested in:
- document root
- container element
li
(partial support - displayed from a new line)caption
td
Supported content:
- plain text
- root content - is displayed from a new line as plain text
Attributes: not supported
Inline-styles:
-
text-align
- horizontal text positionAvailable values:
justify
,left
,center
,right
Default:
left
Example:
const html = `
<blockquote>
Premature Optimization Is the Root of All Evil
<blockquote>
`;
Block element. Responsible for displaying tables.
Can be nested in:
- document root
- container element
li
td
figure
Supported content:
thead
tr
tfoot
tr
colgroup
caption
Attributes: not supported
Inline-styles:
-
width
Supported units:
%
,px
,pt
,vw
,auto
,em
,rem
Without the attribute or with
auto
value - the table will stretch to the entire width of the pagevh
value ignored.em
,rem
sets table width relative tooptions.font.baseSize
value
Example:
const html = `
<table>
<caption>Table</caption>
<colgroup>
<col style="width:30%;">
<col style="width:70%;">
</colgroup>
<tbody>
<tr>
<td>First</td>
<td>Second</td>
</tr>
<tr>
<td>First</td>
<td>Second</td>
</tr>
</tbody>
</table>
`;
Block element. Responsible for displaying the table header.
Can be nested in:
table
Supported content:
- root-content (except table)
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<table>
<caption>Table</caption>
<tbody>
<tr>
<td>Cell</td>
</tr>
</tbody>
</table>
`;
Responsible for displaying rows of the table with a header.
Can be nested in:
table
Supported content:
tr
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<table>
<thead>
<tr>
<td>Cell</td>
</tr>
</thead>
</table>
`;
Responsible for displaying the body of the table.
Can be nested in:
table
Supported content:
tr
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<table>
<tbody>
<tr>
<td>Cell</td>
</tr>
</tbody>
</table>
`;
Responsible for displaying the footer of the table.
Can be nested in:
table
Supported content:
tr
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<table>
<tfoot>
<tr>
<td>Cell</td>
</tr>
</tfoot>
</table>
`;
Responsible for displaying table rows.
Can be nested in:
table
tbody
thead
tfoot
Supported content:
td
th
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<table>
<tbody>
<tr>
<td>Cell</td>
</tr>
</tbody>
</table>
`;
Responsible for setting column widths and styles for those columns.
Can be nested in:
table
Supported content:
col
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<table>
<colgroup>
<col style="width:30%;">
<col style="width:70%;">
</colgroup>
<tbody>
<tr>
<td>First</td>
<td>Second</td>
</tr>
<tr>
<td>First</td>
<td>Second</td>
</tr>
</tbody>
</table>
`;
Responsible for table cells and their display.
Can be nested in:
tbody
tr
thead
tfoot
Supported content:
- root content
Attributes:
-
rowspan, colspan
To merge cells into one horizontally and vertically.
Default:
1
Inline-styles:
-
background-color
Cell background.
Default:
transparent
If the cell is inside
thead
- default background will be -#F2F2F2
-
border
Sets the table cell border.
Format:
{widht} {style} {color}
Default:
4px solid #bfbfbf
-
border-width
Default:
4px
-
border-color
Default:
#bfbfbf
-
border-style
Default:
solid
The border-width, border-color, border-style
styles are more specific and overwrite the border
value if it is passed.
-
vertical-align
Vertical content positioning
Available values:
top, bottom, center
Default:
center
-
padding
Internal cell indents
Format:
{top} {right} {bottom} {left}
{top} {left, right} {bottom}
{top, bottom} {left, right}
{top, left, right, bottom}
Default value:
5px
-
padding-left
,padding-right
,padding-top
,padding-bottom
Indent accordingly for each side of the cell.
Default:
5px
Also, the internal indents of the table cells can be set for the entire table through the options parameter table.cellPaddings
.
Values written through the style
property have greater specificity than values passed through parameters and are overwritten accordingly.
Values specific to each side of the cell have greater specificity than padding values and are overwritten accordingly.
Example:
const html = `
<table>
<colgroup>
<col style="width:30%;">
<col style="width:70%;">
</colgroup>
<tbody>
<tr>
<td style="border: 5px solid #000; padding: 10px">First</td>
<td rowspan="2">Second</td>
</tr>
<tr>
<td>First</td>
</tr>
</tbody>
</table>
`;
Responsible for setting the width of the column.
Can be nested in:
colgroup
Supported content: not supported
Attributes: not supported
Inline-styles:
-
width
Responsible for the width of the table columns. Supported units:
%
,px
,pt
,vw
,auto
,em
,rem
Without the attribute or with
auto
value - the size of the column will be automatically calculated from the width of the table and the number of columns.vh
value ignored.em
,rem
sets table columns width relative tooptions.font.baseSize
valueIf the number of
col
does not correspond to the number of columns - the size of the columns will be automatically calculated from the width of the table and the number of columns
Example:
const html = `
<table>
<colgroup>
<col style="width:30%;">
<col style="width:70%;">
</colgroup>
<tbody>
<tr>
<td>First</td>
<td>Second</td>
</tr>
<tr>
<td>First</td>
<td>Second</td>
</tr>
</tbody>
</table>
`;
Inline element. Adds a line break.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
p
h1-h6
When present in the root of the document or container elements, it add line break to previous paragraph
Supported content: not supported
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<p>some text <br/> new line<p>
`;
Inline element. Makes the text bold.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
p
h1-h6
If there are containers in the root of the document or tags - it is wrapped in a paragraph, which is why it is displayed from a new line.
Supported content:
- plain text
- inline-tags
Attributes: not supported
Inline-styles:
color
background-color
Example:
const html = `
<p>some text <strong>strong</strong><p>
`;
Inline element. Makes the text italic.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
p
h1-h6
If there are containers in the root of the document or tags - it is wrapped in a paragraph, which is why it is displayed from a new line.
Supported content:
- plain text
- inline-tags
Attributes: not supported
Inline-styles:
color
background-color
Example:
const html = `
<p>some text <i>italic</i><p>
`;
Inline element. Makes the text underlined.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
p
h1-h6
If there are containers in the root of the document or tags - it is wrapped in a paragraph, which is why it is displayed from a new line.
Supported content:
- plain text
- inline-tags
Attributes: not supported
Inline-styles:
color
background-color
Example:
const html = `
<p>some text <u>underlined</u><p>
`;
Inline element. Makes the text crossed out.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
p
h1-h6
If there are containers in the root of the document or tags - it is wrapped in a paragraph, which is why it is displayed from a new line.
Supported content:
- plain text
- inline-tags
Attributes: not supported
Inline-styles:
color
background-color
Example:
const html = `
<p>some text <s>strikethrough</s><p>
`;
Inline element. Makes the text crossed out.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
p
h1-h6
If there are containers in the root of the document or tags - it is wrapped in a paragraph, which is why it is displayed from a new line.
Supported content:
- plain text
- inline-tags
Attributes: not supported
Inline-styles:
color
background-color
Example:
const html = `
<p>some text <del>strikethrough</del><p>
`;
Inline element. Contains other inline elements.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
p
h1-h6
If there are containers in the root of the document or tags - it is wrapped in a paragraph, which is why it is displayed from a new line.
Supported content:
- plain text
- inline-tags
Attributes: not supported
Inline-styles:
color
background-color
Example:
const html = `
<p>some text <span>another text</span><p>
`;
Inline element. Defines subscript text.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
p
h1-h6
If there are containers in the root of the document or tags - it is wrapped in a paragraph, which is why it is displayed from a new line.
Supported content:
- plain text
- inline-tags
Attributes: not supported
Inline-styles:
color
background-color
Example:
const html = `
<p>some text <sub>subscripted text</sub><p>
`;
Inline element. Defines superscript text.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
p
h1-h6
If there are containers in the root of the document or tags - it is wrapped in a paragraph, which is why it is displayed from a new line.
Supported content:
- plain text
- inline-tags
Attributes: not supported
Inline-styles:
color
background-color
Example:
const html = `
<p>some text <sup>superscripted text</sup><p>
`;
Inline element. Inserts a link.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
p
h1-h6
If there are containers in the root of the document or tags - it is wrapped in a paragraph, which is why it is displayed from a new line.
Supported content:
- plain text
- inline-tags
Attributes:
-
href
The
URL
of the page that should open when clicked.
Inline-styles: not supported
Example:
const html = `
<p>some text <a href='https://example.com'>example.com</a><p>
`;
Adds a page break.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
Supported content: not supported
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<p>Page 1</p>
<page-break/>
<p>Page 2</p>
`;
Adds a table of contents to the document, automatically generated based on the headings.
Can be nested in:
- document root
- container element
li
blockquote
caption
td
Supported content: not supported
Attributes: not supported
Inline-styles: not supported
Example:
const html = `
<table-of-contents/>
<h1>H1 Example</h1>
<h2>H2 Example</h2>
<h3>H3 Example</h3>
<h4>H4 Example</h4>
`;
(Made with contrib.rocks)