├── .gitignore
├── redocx.png
├── demo
├── Memory.docx
├── HelloWorld.docx
├── word.js
└── word-memory.js
├── examples
├── concr.png
├── Hr.js
├── Image.js
├── Header.js
├── Footer.js
├── PageBreak.js
├── LineBreak.js
├── Text.js
├── List.js
└── Table.js
├── .travis.yml
├── src
├── components
│ ├── Footer.js
│ ├── Header.js
│ ├── WordDocument.js
│ ├── LineBreak.js
│ ├── PageBreak.js
│ ├── Hr.js
│ ├── index.js
│ ├── Root.js
│ ├── Bullet.js
│ ├── Number.js
│ ├── List.js
│ ├── HOC.js
│ ├── Image.js
│ ├── Document.js
│ ├── Table.js
│ └── Text.js
├── utils
│ ├── platform.js
│ ├── nodes.js
│ ├── renderUtils.js
│ └── createElement.js
├── index.js
├── renderer
│ ├── parse.js
│ ├── render.js
│ └── renderer.js
├── styles
│ └── styles.js
└── validators
│ └── componentValidators.js
├── .babelrc
├── __tests__
├── createElement.test.js
├── Hr.test.js
├── PageBreak.test.js
├── LineBreak.test.js
├── Footer.test.js
├── Header.test.js
├── Image.test.js
├── Document.test.js
├── __snapshots__
│ ├── styles.test.js.snap
│ ├── createElement.test.js.snap
│ ├── Hr.test.js.snap
│ ├── PageBreak.test.js.snap
│ ├── Table.test.js.snap
│ ├── Image.test.js.snap
│ └── LineBreak.test.js.snap
├── Table.test.js
├── styles.test.js
├── Text.test.js
└── Bullets.test.js
├── .eslintrc.js
├── docs
├── misc.md
├── styling.md
├── README.md
└── api.md
├── CONTRIBUTING.md
├── package.json
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | lib
3 | demo/text.docx
--------------------------------------------------------------------------------
/redocx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nitin42/redocx/HEAD/redocx.png
--------------------------------------------------------------------------------
/demo/Memory.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nitin42/redocx/HEAD/demo/Memory.docx
--------------------------------------------------------------------------------
/examples/concr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nitin42/redocx/HEAD/examples/concr.png
--------------------------------------------------------------------------------
/demo/HelloWorld.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nitin42/redocx/HEAD/demo/HelloWorld.docx
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "6"
4 | notifications:
5 | email: false
6 | script:
7 | - npm run test
--------------------------------------------------------------------------------
/src/components/Footer.js:
--------------------------------------------------------------------------------
1 | import hoc from './HOC';
2 |
3 | /**
4 | * Footer component
5 | */
6 | export default hoc('Footer', 'getFooter');
7 |
--------------------------------------------------------------------------------
/src/components/Header.js:
--------------------------------------------------------------------------------
1 | import hoc from './HOC';
2 |
3 | /**
4 | * Header component
5 | */
6 | export default hoc('Header', 'getHeader');
7 |
--------------------------------------------------------------------------------
/src/utils/platform.js:
--------------------------------------------------------------------------------
1 | const Platform = {
2 | OS: 'word',
3 | select: obj => ('word' in obj ? obj.word : obj.default),
4 | };
5 |
6 | export default Platform;
7 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "env",
5 | {
6 | "exclude": ["transform-regenerator"]
7 | }
8 | ],
9 | "stage-0",
10 | "react"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/__tests__/createElement.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {createElement} from '../src/utils/createElement';
3 |
4 | it('should create an element', () => {
5 | const inst = createElement('ROOT')
6 | expect(inst).toMatchSnapshot();
7 | })
--------------------------------------------------------------------------------
/__tests__/Hr.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Hr } from '../src/';
3 | import { testRenderer as render } from '../src/renderer/render';
4 |
5 | it('should draw a horizontal ruler', () => {
6 | expect(render(
)).toMatchSnapshot();
7 | })
--------------------------------------------------------------------------------
/__tests__/PageBreak.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { PageBreak } from '../src/';
3 | import { testRenderer as render } from '../src/renderer/render';
4 |
5 | it('should put a page break', () => {
6 | expect(render()).toMatchSnapshot();
7 | })
8 |
--------------------------------------------------------------------------------
/src/components/WordDocument.js:
--------------------------------------------------------------------------------
1 | import officegen from 'officegen';
2 |
3 | /**
4 | * This creates the document instance
5 | */
6 | class WordDocument {
7 | constructor() {
8 | this.doc = officegen('docx');
9 | }
10 | }
11 |
12 | export default WordDocument;
13 |
--------------------------------------------------------------------------------
/src/components/LineBreak.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This component adds a line break and should be called inside Text or List component
3 | */
4 | class LineBreak {
5 | constructor(root, props) {
6 | this.root = root;
7 | this.prop = props;
8 | this.name = 'LineBreak';
9 | }
10 | }
11 |
12 | export default LineBreak;
13 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "extends": "airbnb-base",
3 | "parser": "babel-eslint",
4 | "rules": {
5 | "no-await-in-loop": 0,
6 | "no-param-reassign": 0,
7 | "no-return-assign": 0,
8 | "no-return-await": 0,
9 | "no-console": 0,
10 | "no-unneeded-ternary": 0
11 | }
12 | };
--------------------------------------------------------------------------------
/examples/Hr.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Hr, Document, Text } from '../src/';
3 |
4 | class HrComponent extends Component {
5 | render () {
6 | return (
7 |
8 | Below is a horizontal ruler
9 |
10 |
11 | );
12 | }
13 | }
14 |
15 | export default HrComponent
--------------------------------------------------------------------------------
/examples/Image.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Image, Document } from '../src/';
3 |
4 | class ImageComponent extends Component {
5 | render () {
6 | return (
7 |
8 |
9 |
10 | );
11 | }
12 | }
13 |
14 | export default ImageComponent
--------------------------------------------------------------------------------
/examples/Header.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Header, Document } from '../src/';
3 |
4 | class HeaderComponent extends Component {
5 | render () {
6 | return (
7 |
8 |
9 |
10 | );
11 | }
12 | }
13 |
14 | export default HeaderComponent
--------------------------------------------------------------------------------
/examples/Footer.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Footer, Document } from '../src/';
3 |
4 | class FooterComponent extends Component {
5 | render () {
6 | return (
7 |
8 |
9 |
10 | );
11 | }
12 | }
13 |
14 | export default FooterComponent
--------------------------------------------------------------------------------
/src/components/PageBreak.js:
--------------------------------------------------------------------------------
1 | import Root from './Root';
2 |
3 | /**
4 | * This component adds a page break.
5 | */
6 | class PageBreak extends Root {
7 | constructor(root, props) {
8 | super(root, props);
9 | this.root = root;
10 | this.adder = this.root.doc.putPageBreak();
11 | }
12 |
13 | async render() {
14 | await this.adder;
15 | }
16 | }
17 |
18 | export default PageBreak;
19 |
--------------------------------------------------------------------------------
/examples/PageBreak.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { PageBreak, Document, Text, Image } from '../src/';
3 |
4 | class PageBreakComponent extends Component {
5 | render () {
6 | return (
7 |
8 | Hello World!
9 |
10 | Hello World!
11 |
12 | );
13 | }
14 | }
15 |
16 | export default PageBreakComponent
--------------------------------------------------------------------------------
/src/components/Hr.js:
--------------------------------------------------------------------------------
1 | import Root from './Root';
2 |
3 | /**
4 | * This component draw a horizontal line
5 | */
6 | class Hr extends Root {
7 | constructor(root, props) {
8 | super(root, props);
9 | this.root = root;
10 | this.name = 'Hr';
11 | }
12 |
13 | async render() {
14 | await (this.parent === null ? this.root.doc.createP().addHorizontalLine() : null);
15 | }
16 | }
17 |
18 | export default Hr;
19 |
--------------------------------------------------------------------------------
/__tests__/LineBreak.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { LineBreak, Text } from '../src/';
3 | import { testRenderer as render } from '../src/renderer/render';
4 |
5 | it('should add a line break', () => {
6 | expect(render()).toMatchSnapshot();
7 | })
8 |
9 | it('should add a line break when called inside a Text component', () => {
10 | expect(render()).toMatchSnapshot();
11 | })
12 |
--------------------------------------------------------------------------------
/examples/LineBreak.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { LineBreak, Document, Text } from '../src/';
3 |
4 | class LineBreakComponent extends Component {
5 | render () {
6 | return (
7 |
8 |
9 | Hello World!
10 |
11 | This is a new line!
12 |
13 |
14 | );
15 | }
16 | }
17 |
18 | export default LineBreakComponent
--------------------------------------------------------------------------------
/examples/Text.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Text, Document } from '../src/';
3 |
4 | const TextStyles = {
5 | color: 'red',
6 | fontSize: 30
7 | };
8 |
9 | class TextComponent extends Component {
10 | render() {
11 | return (
12 |
13 |
14 | Hello World!
15 |
16 |
17 | );
18 | }
19 | }
20 |
21 | export default TextComponent;
22 |
--------------------------------------------------------------------------------
/examples/List.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { List, BulletItem, Document } from '../src/';
3 |
4 | class ListComponent extends Component {
5 | render () {
6 | return (
7 |
8 |
9 | Item one
10 | Item two
11 | Item three
12 |
13 |
14 | );
15 | }
16 | }
17 |
18 | export default ListComponent
--------------------------------------------------------------------------------
/src/components/index.js:
--------------------------------------------------------------------------------
1 | import BulletItem from './Bullet';
2 | import Document from './Document';
3 | import Footer from './Footer';
4 | import Header from './Header';
5 | import Hr from './Hr';
6 | import Image from './Image';
7 | import NumberItem from './Number';
8 | import LineBreak from './LineBreak';
9 | import List from './List';
10 | import PageBreak from './PageBreak';
11 | import Table from './Table';
12 | import Text from './Text';
13 | import WordDocument from './WordDocument';
14 |
15 | export {
16 | BulletItem,
17 | Document,
18 | Footer,
19 | Header,
20 | Hr,
21 | Image,
22 | NumberItem,
23 | LineBreak,
24 | List,
25 | PageBreak,
26 | Table,
27 | Text,
28 | WordDocument,
29 | };
30 |
--------------------------------------------------------------------------------
/src/components/Root.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Base class that keeps track of parent and child nodes
3 | */
4 | class Root {
5 | parent = null;
6 | children = [];
7 |
8 | constructor(root, props) {
9 | this.root = root;
10 | this.props = props;
11 | }
12 |
13 | appendChild(child) {
14 | child.parent = this;
15 | this.children.push(child);
16 | }
17 |
18 | removeChild(child) {
19 | const index = this.children.indexOf(child);
20 |
21 | child.parent = null;
22 | this.children.splice(index, 1);
23 | }
24 |
25 | async renderChildren() {
26 | for (let i = 0; i < this.children.length; i += 1) {
27 | await this.children[i].render();
28 | }
29 | }
30 | }
31 |
32 | export default Root;
33 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { render } from './renderer/render';
2 | import Platform from './utils/platform';
3 |
4 | /**
5 | * Component name (input to createElement function call after transpilation with Babel)
6 | */
7 | const Text = 'TEXT';
8 | const Image = 'IMAGE';
9 | const List = 'LIST';
10 | const NumberItem = 'NUMBERITEM';
11 | const BulletItem = 'BULLETITEM';
12 | const LineBreak = 'LINEBREAK';
13 | const PageBreak = 'PAGEBREAK';
14 | const Document = 'DOCUMENT';
15 | const Hr = 'HR';
16 | const Table = 'TABLE';
17 | const Header = 'HEADER';
18 | const Footer = 'FOOTER';
19 |
20 | /**
21 | * Main export
22 | */
23 | export {
24 | Text,
25 | Image,
26 | List,
27 | Document,
28 | NumberItem,
29 | BulletItem,
30 | PageBreak,
31 | Hr,
32 | LineBreak,
33 | Table,
34 | Header,
35 | Footer,
36 | Platform,
37 | render,
38 | };
39 |
--------------------------------------------------------------------------------
/src/components/Bullet.js:
--------------------------------------------------------------------------------
1 | import Root from './Root';
2 | import { renderNodes } from '../utils/nodes';
3 |
4 | /**
5 | * This component renders a list of dots
6 | */
7 | class BulletItem extends Root {
8 | constructor(root, props) {
9 | super(root, props);
10 | this.root = root;
11 | this.props = props;
12 | this.adder = this.root.doc.createListOfDots();
13 | }
14 |
15 | appendChild(child) {
16 | this.children.push(child);
17 | }
18 |
19 | removeChild(child) {
20 | const index = this.children.indexOf(child);
21 | this.children.splice(index, 1);
22 | }
23 |
24 | async renderChildren(align, styles) {
25 | await renderNodes(align, null, styles, this.adder, this.children, this.props);
26 | }
27 |
28 | async render(align, styles) {
29 | await this.renderChildren(align, styles);
30 | }
31 | }
32 |
33 | export default BulletItem;
34 |
--------------------------------------------------------------------------------
/demo/word.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import TextComponent from '../examples/Text';
3 | import { render, Document, Text } from '../src/';
4 |
5 | // Uncomment any of the below component to see what they render
6 |
7 | import FooterComponent from '../examples/Footer';
8 | import HeaderComponent from '../examples/Header';
9 | import HrComponent from '../examples/Hr';
10 | import LineBreakComponent from '../examples/LineBreak';
11 | import PageBreakComponent from '../examples/PageBreak';
12 | import TableComponent from '../examples/Table';
13 | import ListComponent from '../examples/List';
14 | import ImageComponent from '../examples/Image';
15 |
16 | class MyDocument extends Component {
17 | render() {
18 | return (
19 |
20 |
21 |
22 | )
23 | }
24 | }
25 |
26 | render(, `${__dirname}/HelloWorld.docx`);
27 |
--------------------------------------------------------------------------------
/src/components/Number.js:
--------------------------------------------------------------------------------
1 | import Root from './Root';
2 | import { renderNodes } from '../utils/nodes';
3 |
4 | /**
5 | * Creates list of numbers (currently unstable)
6 | */
7 | class NumberItem extends Root {
8 | constructor(root, props) {
9 | super(root, props);
10 | this.root = root;
11 | this.props = props;
12 | this.adder = this.root.doc.createListOfNumbers();
13 | }
14 |
15 | appendChild(child) {
16 | this.children.push(child);
17 | }
18 |
19 | removeChild(child) {
20 | const index = this.children.indexOf(child);
21 | this.children.splice(index, 1);
22 | }
23 |
24 | async renderChildren(align, styles) {
25 | await renderNodes(align, null, styles, this.adder, this.children, this.props);
26 | }
27 |
28 | async render(align, styles) {
29 | await this.renderChildren(align, styles);
30 | }
31 | }
32 |
33 | export default NumberItem;
34 |
--------------------------------------------------------------------------------
/src/components/List.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This component renders a list of dots or numbers
3 | */
4 | class List {
5 | children = [];
6 |
7 | constructor(root, props) {
8 | this.root = root;
9 | this.props = props;
10 | }
11 |
12 | appendChild(child) {
13 | this.children.push(child);
14 | }
15 |
16 | removeChild(child) {
17 | const index = this.children.indexOf(child);
18 | this.children.splice(index, 1);
19 | }
20 |
21 | async renderChildren(align, styles) {
22 | // Override the styles and use List component styles
23 | // expected an assignment
24 | styles = this.props.style ? this.props.style : styles;
25 | for (let i = 0; i < this.children.length; i += 1) {
26 | await this.children[i].render(align, styles);
27 | }
28 | }
29 |
30 | async render(align, styles) {
31 | await this.renderChildren(align, styles);
32 | }
33 | }
34 |
35 | export default List;
36 |
--------------------------------------------------------------------------------
/src/renderer/parse.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Render the component (passed to docx generator instance)
3 | * This is similar to react-pdf https://github.com/diegomura/react-pdf/blob/master/packages/react-pdf/src/index.js
4 | * @param {Object} input Root component
5 | */
6 | const parse = (input) => {
7 | async function parseComponent(inputComponent) {
8 | // This property is accessed due to https://github.com/nitin42/redocx/blob/master/src/renderer/renderer.js#L32
9 | const document = inputComponent.document;
10 |
11 | await document.render();
12 | // Return the input component again because we rendered the children
13 | // which weren't wrapped inside a parent.
14 | // We async called the render method on all of the children.
15 | return inputComponent;
16 | }
17 |
18 | async function toBuffer() {
19 | return await parseComponent(input);
20 | }
21 |
22 | return {
23 | toBuffer,
24 | };
25 | };
26 |
27 | export default parse;
28 |
--------------------------------------------------------------------------------
/__tests__/Footer.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Footer, Document } from '../src/';
3 | import { testRenderer as render } from '../src/renderer/render';
4 |
5 | it('sanity check', () => {
6 | expect(render()).toMatchSnapshot();
7 | })
8 |
9 | it('should render a footer', () => {
10 | expect(render()).toMatchSnapshot();
11 | })
12 |
13 | it('should render a footer and align it', () => {
14 | expect(render()).toMatchSnapshot();
15 | })
16 |
17 | it('should render a footer and style it', () => {
18 | expect(render()).toMatchSnapshot();
19 | })
20 |
21 | it('can be aligned and styled by component', () => {
22 | const App = () => (
23 |
24 |
25 |
26 | )
27 |
28 | expect(render()).toMatchSnapshot();
29 | })
--------------------------------------------------------------------------------
/__tests__/Header.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Header, Document } from '../src/';
3 | import { testRenderer as render } from '../src/renderer/render';
4 |
5 | it('sanity check', () => {
6 | expect(render()).toMatchSnapshot();
7 | })
8 |
9 | it('should render a header', () => {
10 | expect(render()).toMatchSnapshot();
11 | })
12 |
13 | it('should render a header and align it', () => {
14 | expect(render()).toMatchSnapshot();
15 | })
16 |
17 | it('should render a header and style it', () => {
18 | expect(render()).toMatchSnapshot();
19 | })
20 |
21 | it('can be aligned and styled by component', () => {
22 | const App = () => (
23 |
24 |
25 |
26 | )
27 |
28 | expect(render()).toMatchSnapshot();
29 | })
--------------------------------------------------------------------------------
/examples/Table.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Table, Document } from '../src/';
3 |
4 | const tableStyle = {
5 | tableColWidth: 4261, // Width of each column
6 | tableSize: 24, // Table size
7 | tableColor: 'red', // Content color
8 | tableAlign: 'center', // Align content
9 | borders: true, // Borders
10 | };
11 |
12 | const HEADERS = [
13 | {
14 | value: 'Phone',
15 | styles: {
16 | color: 'red',
17 | bold: true,
18 | size: 10
19 | }
20 | },
21 | {
22 | value: 'Capacity',
23 | styles: {
24 | color: 'blue',
25 | bold: true,
26 | size: 10
27 | }
28 | }
29 | ]
30 |
31 | const DATA = [
32 | ['iPhone 7', '128GB'],
33 | ['iPhone 5SE', '64GB']
34 | ]
35 |
36 | class TableComponent extends Component {
37 | render() {
38 | return (
39 |
40 |
41 |
42 | );
43 | }
44 | }
45 |
46 | export default TableComponent;
--------------------------------------------------------------------------------
/docs/misc.md:
--------------------------------------------------------------------------------
1 | # Extra
2 |
3 | ## Top-Level Document Object
4 |
5 | The [render]() method returns a top-level document object. This object contains information about [document instance](https://github.com/Ziv-Barber/officegen#creating-the-document-object) which
6 | includes document information (author, description, title, etc) and the component instance, which further includes information about
7 | children, props, root instance.
8 |
9 | High level picture -
10 |
11 | ```
12 | document:
13 | Document {
14 | children: [ [Object] ],
15 | root: [Circular],
16 | props: { children: [Object] },
17 | adder:
18 | MakeDocxP {
19 | docType: 'docx',
20 | genPrivate: [Object],
21 | ogPluginsApi: [Object],
22 | msPluginsApi: [Object],
23 | genobj: [Object],
24 | data: [],
25 | extraSettings: {},
26 | options: [Object],
27 | mainPath: 'word',
28 | mainPathFile: 'document',
29 | relsMain: [Object],
30 | relsApp: [Object],
31 | filesList: [Object],
32 | srcFilesList: [Object] } } }
33 | ```
34 |
--------------------------------------------------------------------------------
/src/components/HOC.js:
--------------------------------------------------------------------------------
1 | import { renderNodes } from '../utils/nodes';
2 |
3 | /**
4 | * High order component for rendering header and footer
5 | * @param {string} component Component name
6 | * @param {string} fn Function name
7 | */
8 | function hoc(component, fn) {
9 | class _Component {
10 | children = [];
11 |
12 | constructor(root, props) {
13 | this.root = root;
14 | this.props = props;
15 | this.adder = fn === 'getHeader' ? this.root.doc.getHeader().createP() : this.root.doc.getFooter().createP();
16 | }
17 |
18 | appendChild(child) {
19 | this.children.push(child);
20 | }
21 |
22 | removeChild(child) {
23 | const index = this.children.indexOf(child);
24 | this.children.splice(index, 1);
25 | }
26 |
27 | async renderChildren(align, styles) {
28 | await renderNodes(align, this.props.align, styles, this.adder, this.children, this.props);
29 | }
30 |
31 | async render(align, styles) {
32 | await this.renderChildren(align, styles);
33 | }
34 | }
35 |
36 | return _Component;
37 | }
38 |
39 | export default hoc;
40 |
--------------------------------------------------------------------------------
/__tests__/Image.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Image } from '../src/';
3 | import { testRenderer as render } from '../src/renderer/render';
4 |
5 | it('sanity check', () => {
6 | expect(render()).toMatchSnapshot();
7 | })
8 |
9 | it('should render an image', () => {
10 | const App = () => (
11 |
12 | )
13 |
14 | expect(render()).toMatchSnapshot();
15 | })
16 |
17 | it('should render an image and align it', () => {
18 | const App = () => (
19 |
20 | )
21 |
22 | expect(render()).toMatchSnapshot();
23 | })
24 |
25 | it('should render an image and adjust it size with style prop', () => {
26 | const App = () => (
27 |
28 | )
29 |
30 | expect(render()).toMatchSnapshot();
31 | })
32 |
33 | it('should render an image and adjust it size with width and height prop', () => {
34 | const App = () => (
35 |
36 | )
37 |
38 | expect(render()).toMatchSnapshot();
39 | })
--------------------------------------------------------------------------------
/__tests__/Document.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Document, Text } from '../src/';
3 | import { testRenderer as render } from '../src/renderer/render';
4 |
5 | it('sanity check', () => {
6 | expect(render()).toMatchSnapshot();
7 | })
8 |
9 | it('should render the children type string', () => {
10 | expect(render(Hello!)).toMatchSnapshot();
11 | })
12 |
13 | it('should render the children component', () => {
14 | const App = () => (
15 |
16 | Hmm...
17 |
18 | )
19 |
20 | expect(render()).toMatchSnapshot();
21 | })
22 |
23 | it('should render the children component and align them', () => {
24 | const App = () => (
25 |
26 | Hmm...
27 |
28 | )
29 |
30 | expect(render()).toMatchSnapshot();
31 | })
32 |
33 | it('should render the children component and apply styles to them', () => {
34 | const App = () => (
35 |
36 | Hmm...
37 |
38 | )
39 |
40 | expect(render()).toMatchSnapshot();
41 | })
--------------------------------------------------------------------------------
/src/components/Image.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import { applyImageProps } from '../styles/styles';
3 | import { alignChildren } from '../utils/nodes';
4 | import Root from './Root';
5 |
6 | /**
7 | * We need the parent class because it keeps the track of the parent node and the -
8 | * Image component and calls the render method depending upon where the component -
9 | * lies. For example - If Image component is children of Text component -
10 | * then its parent is Text component not the main Document component so we avoid -
11 | * calling render method on it twice
12 | */
13 | class Image extends Root {
14 | constructor(root, props) {
15 | super(root, props);
16 | this.root = root;
17 | this.props = props;
18 | this.name = 'Image';
19 | }
20 |
21 | async renderImage(align) {
22 | this.adder = this.root.doc.createP();
23 |
24 | // Align the image with context by Document or through component prop 'align'
25 | alignChildren(this.adder, align, this.props.align);
26 |
27 | await this.adder.addImage(path.resolve(this.props.src), applyImageProps(this.props));
28 | }
29 |
30 | async render(align) {
31 | await (this.parent === null ? this.renderImage(align) : null);
32 | }
33 | }
34 |
35 | export default Image;
36 |
--------------------------------------------------------------------------------
/demo/word-memory.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import React, { Component } from 'react';
3 | import TextComponent from '../examples/Text';
4 | import { render, Document, Text } from '../src/';
5 |
6 | // Uncomment any of the below component to see what they render
7 |
8 | import FooterComponent from '../examples/Footer';
9 | import HeaderComponent from '../examples/Header';
10 | import HrComponent from '../examples/Hr';
11 | import LineBreakComponent from '../examples/LineBreak';
12 | import PageBreakComponent from '../examples/PageBreak';
13 | import TableComponent from '../examples/Table';
14 | import ListComponent from '../examples/List';
15 | import ImageComponent from '../examples/Image';
16 |
17 | class MyDocument extends Component {
18 | render() {
19 | return (
20 |
21 |
22 |
23 | );
24 | }
25 | }
26 |
27 | render().then((stream) => {
28 | fs.open('./demo/Memory.docx', 'w+', stream.length, null, (err, fd) => {
29 | if (err) {
30 | console.log(err);
31 | }
32 | fs.write(fd, stream.toBuffer(), (writeErr) => {
33 | if (writeErr) {
34 | console.log(writeErr);
35 | }
36 | console.log('Docx generated and saved to ./demo/Memory.docx');
37 | });
38 | });
39 | });
40 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/styles.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`children can be colored with a hex 1`] = `
4 | Object {
5 | "back": "ff0000",
6 | "bold": undefined,
7 | "border": undefined,
8 | "borderColor": false,
9 | "borderSize": undefined,
10 | "color": "ffffff",
11 | "font_face": undefined,
12 | "font_size": undefined,
13 | "highlight": false,
14 | "italic": undefined,
15 | "link": undefined,
16 | "underline": undefined,
17 | }
18 | `;
19 |
20 | exports[`children can be styled 1`] = `
21 | Object {
22 | "back": "ff0000",
23 | "bold": true,
24 | "border": true,
25 | "borderColor": "ffff33",
26 | "borderSize": "40",
27 | "color": "ffffff",
28 | "font_face": "Tahoma",
29 | "font_size": "40",
30 | "highlight": "ff2222",
31 | "italic": true,
32 | "link": "www.google.com",
33 | "underline": true,
34 | }
35 | `;
36 |
37 | exports[`image size can be adjusted with style prop 1`] = `
38 | Object {
39 | "cx": 200,
40 | "cy": 200,
41 | }
42 | `;
43 |
44 | exports[`image size can be adjusted with width and height prop 1`] = `
45 | Object {
46 | "cx": 200,
47 | "cy": 200,
48 | }
49 | `;
50 |
51 | exports[`table styles can be serialized according to open office xml layout 1`] = `
52 | Object {
53 | "align": "center",
54 | "b": true,
55 | "cellColWidth": 4261,
56 | "color": "ffe4e1",
57 | "fill": "ffffff",
58 | "fontFamily": "Tahoma",
59 | "sz": "20",
60 | "vAlign": "center",
61 | }
62 | `;
63 |
--------------------------------------------------------------------------------
/__tests__/Table.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Table } from '../src/';
3 | import { testRenderer as render } from '../src/renderer/render';
4 |
5 | const tableStyle = {
6 | tableColWidth: 4261, // Width of each column
7 | tableSize: 24, // Table size
8 | tableColor: 'red', // Content color
9 | tableAlign: 'center', // Align content
10 | borders: true, // Borders ? 😅
11 | };
12 |
13 | const HEADERS = [
14 | {
15 | value: 'Phone',
16 | styles: {
17 | color: 'red',
18 | bold: true,
19 | size: 10
20 | }
21 | },
22 | {
23 | value: 'Capacity',
24 | styles: {
25 | color: 'blue',
26 | bold: true,
27 | size: 10
28 | }
29 | }
30 | ]
31 |
32 | const DATA = [
33 | ['iPhone 7', '128GB'],
34 | ['iPhone 5SE', '64GB']
35 | ]
36 |
37 | it('should render a table with some data', () => {
38 | expect(render()).toMatchSnapshot();
39 | })
40 |
41 | it('should render a table with data and style prop', () => {
42 | const App = () => (
43 |
47 | )
48 |
49 | expect(render()).toMatchSnapshot();
50 | })
51 |
52 | it('should render a table with table style prop', () => {
53 | const App = () => (
54 |
59 | )
60 |
61 | expect(render()).toMatchSnapshot();
62 | })
--------------------------------------------------------------------------------
/src/utils/nodes.js:
--------------------------------------------------------------------------------
1 | import { applyStyles } from '../styles/styles';
2 |
3 | /**
4 | * This function renders the text content and apply the corresponding styles to it
5 | * @param {string} child Child node
6 | * @param {Object} props Component props
7 | * @param {Object} styles Style attributes
8 | * @param {Object} instance Document instance
9 | */
10 | async function renderText(child, props, styles, instance) {
11 | await instance.addText(child, (props.style ? applyStyles(props.style) : applyStyles(styles)));
12 | }
13 |
14 | /**
15 | *
16 | * @param {Object} instance Document instance
17 | * @param {string} alignWithContext Align (Document component)
18 | * @param {string} alignThroughProp Align prop
19 | */
20 | function alignChildren(instance, alignWithContext, alignThroughProp) {
21 | return instance.options.align = alignWithContext ? alignWithContext : alignThroughProp;
22 | }
23 |
24 | /**
25 | * This function renders all the text nodes
26 | * @param {string} alignWithContext Align (Document component)
27 | * @param {string} alignThroughProp Align prop
28 | * @param {Object} styles Style attributes
29 | * @param {Object} instance Document instance
30 | * @param {Array} children Child node
31 | * @param {Object} props Component props
32 | */
33 | async function renderNodes(alignWithContext, alignThroughProp, styles, instance, children, props) {
34 | alignChildren(instance, alignWithContext, alignThroughProp);
35 | for (let i = 0; i < children.length; i += 1) {
36 | if (typeof children[i] === 'string') {
37 | await renderText(children[i], props, styles, instance);
38 | }
39 | }
40 | }
41 |
42 | export { renderText, alignChildren, renderNodes };
43 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing guide
2 |
3 | I'm excited to have you helping out. Thank you so much for your time 😄
4 |
5 | ### Contributing
6 |
7 | #### Understanding the codebase
8 | `redocx` uses [officegen](https://github.com/Ziv-Barber/officegen) to generate the documents. So before you start working on adding a new feature or fixing a bug, take a look at the officegen [documentation](https://github.com/Ziv-Barber/officegen/blob/master/manual/README-docx.md) and [examples](https://github.com/Ziv-Barber/officegen/blob/master/examples/make_docx.js). This will make things easier for you. Also if you need any more help on using officegen and regarding it's documentation, ask me. I am at [NTulswani](https://twitter.com/NTulswani) on Twitter
9 |
10 | #### Setting up the environment
11 |
12 | Considering you've forked and cloned the repo on your system, switch to the directory and install the dependencies.
13 |
14 | ```
15 | cd redocx
16 | npm install
17 | ```
18 |
19 | #### Submitting pull requests
20 |
21 | * Create a new branch for the new feature: git checkout -b new-feature
22 | * Make your changes.
23 | * Test everything with `npm run test`.
24 | * Run `npm run lint` to check the syntax errors.
25 | * Commit your changes: git commit -m 'Added some new feature'
26 | * Push to the branch: git push origin new-feature
27 | * Submit a pull request with full remarks documenting your changes.
28 |
29 | #### Test the changes locally
30 |
31 | You can test your changes locally in the [demo](../demo) folder. Make your changes to [`word.js`](../demo/word.js) and run `npm run example`. This will render your views and components to `docx`.
32 |
33 |
34 | That's it! I am excited to see your pull request.
35 |
--------------------------------------------------------------------------------
/__tests__/styles.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { List, Document, BulletItem, NumberItem } from '../src/';
3 | import { applyStyles, applyImageProps, styleSerializer } from '../src/styles/styles';
4 |
5 | it('children can be colored with a hex', () => {
6 | const props = {
7 | color: '#ffffff',
8 | backgroundColor: '#ff0000'
9 | }
10 |
11 | expect(applyStyles(props)).toMatchSnapshot();
12 | })
13 |
14 | it('children can be styled', () => {
15 | const props = {
16 | color: '#ffffff',
17 | backgroundColor: '#ff0000',
18 | fontSize: '40',
19 | fontFace: 'Tahoma',
20 | bold: true,
21 | border: true,
22 | underline: true,
23 | italic: true,
24 | highlight: '#ff2222',
25 | borderSize: '40',
26 | borderColor: '#ff3',
27 | link: 'www.google.com'
28 | }
29 |
30 | expect(applyStyles(props)).toMatchSnapshot();
31 | })
32 |
33 | it('image size can be adjusted with style prop', () => {
34 | const props = {
35 | style: {
36 | width: '200',
37 | height: '200'
38 | }
39 | }
40 |
41 | expect(applyImageProps(props)).toMatchSnapshot()
42 | })
43 |
44 | it('image size can be adjusted with width and height prop', () => {
45 | const props = {
46 | width: '200',
47 | height: '200'
48 | }
49 |
50 | expect(applyImageProps(props)).toMatchSnapshot()
51 | })
52 |
53 | it('table styles can be serialized according to open office xml layout', () => {
54 | const styles = {
55 | bold: true,
56 | size: '20',
57 | color: 'mistyrose',
58 | align: 'center',
59 | vAlign: 'center',
60 | fontFamily: 'Tahoma',
61 | fill: '#ffffff',
62 | cellColWidth: 4261
63 | }
64 |
65 | expect(styleSerializer(styles)).toMatchSnapshot();
66 | })
67 |
--------------------------------------------------------------------------------
/src/utils/renderUtils.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import os from 'os';
3 | import execa from 'execa';
4 | import minimatch from 'minimatch';
5 |
6 | /* eslint-disable no-unused-expressions */
7 | /**
8 | * Open the doc app
9 | */
10 | function openDocApp(file) {
11 | os.platform() === 'darwin' ? execa.shell(`open -a pages ${path.resolve(file)}`) : null;
12 | }
13 |
14 | /**
15 | * Document element
16 | * @param {Object} element
17 | */
18 | function validateElement(element) {
19 | if (!element) {
20 | throw new Error('Render method expected an element.');
21 | }
22 |
23 | if (typeof element === 'string') {
24 | throw new Error("Invalid component element. Instead of passing string like 'text', pass a class or functional component. For example - ");
25 | }
26 |
27 | return true;
28 | }
29 |
30 | /**
31 | * Filepath for the document
32 | * @param {string} filePath
33 | */
34 | function validatePath(filePath) {
35 | if (filePath === null || filePath === undefined) {
36 | throw new Error('Please specify a file path for the document');
37 | }
38 |
39 | const fileName = path.basename(filePath);
40 | const pattern = '*.docx';
41 |
42 | if (!minimatch(fileName, pattern)) {
43 | throw new Error(`Invalid filename '${path.basename(filePath)}'. Make sure the extension is '.docx'`);
44 | }
45 | return true;
46 | }
47 |
48 | function Events(filePath, resolve, reject) {
49 | return {
50 | finalize: () => {
51 | console.log(`✨ Word document created at ${path.resolve(filePath)}.`);
52 | resolve();
53 | },
54 | error: () => {
55 | console.log('An error occurred while generating the document.');
56 | reject();
57 | },
58 | };
59 | }
60 |
61 | export { Events, openDocApp, validateElement, validatePath };
62 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "redocx",
3 | "description": "Create word documents with React",
4 | "version": "1.1.4",
5 | "repository": "https://github.com/nitin42/redocx",
6 | "main": "./lib/index.js",
7 | "author": "Nitin Tulswani",
8 | "license": "MIT",
9 | "files": [
10 | "lib"
11 | ],
12 | "scripts": {
13 | "build": "NODE_ENV=production babel src -d lib",
14 | "test": "jest",
15 | "test:watch": "jest --watch",
16 | "test:coverage": "jest --coverage",
17 | "example": "babel-node ./demo/word.js",
18 | "example-mem": "babel-node ./demo/word-memory.js",
19 | "lint": "eslint ./src",
20 | "prebuild": "rm -rf ./lib"
21 | },
22 | "lint-staged": {
23 | "*.js": [
24 | "prettier --single-quote --no-semi --write",
25 | "git add"
26 | ]
27 | },
28 | "jest": {
29 | "testEnvironment": "node"
30 | },
31 | "dependencies": {
32 | "chroma-js": "^1.3.4",
33 | "execa": "^0.8.0",
34 | "fbjs": "^0.8.4",
35 | "memory-streams": "0.1.3",
36 | "minimatch": "^3.0.4",
37 | "officegen": "^0.4.5",
38 | "react": "^16.0.0",
39 | "react-reconciler": "0.2.0",
40 | "validator": "^8.0.0"
41 | },
42 | "devDependencies": {
43 | "babel-cli": "^6.24.1",
44 | "babel-core": "^6.25.0",
45 | "babel-eslint": "7",
46 | "babel-polyfill": "^6.26.0",
47 | "babel-preset-env": "^1.6.0",
48 | "babel-preset-react": "^6.24.1",
49 | "babel-preset-stage-0": "^6.24.1",
50 | "diff-react": "^1.0.5",
51 | "eslint": "^4.4.1",
52 | "eslint-config-airbnb-base": "^11.3.1",
53 | "eslint-plugin-import": "^2.7.0",
54 | "jest": "^20.0.4",
55 | "lint-staged": "^4.2.1",
56 | "prettier": "^1.7.0"
57 | },
58 | "keywords": [
59 | "renderer",
60 | "react",
61 | "word documents",
62 | "custom renderer",
63 | "fiber"
64 | ]
65 | }
66 |
--------------------------------------------------------------------------------
/src/components/Document.js:
--------------------------------------------------------------------------------
1 | import { validateDocProps } from '../validators/componentValidators';
2 | import { applyStyles } from '../styles/styles';
3 |
4 | /**
5 | * This component wraps all the children (string, components) and renders them.
6 | * It only takes two props, 'align' for alignment of the document and 'info' for adding
7 | * document information like name of the author and description of the document.
8 | */
9 |
10 | class Document {
11 | // Store all the children here
12 | children = [];
13 |
14 | constructor(root, props) {
15 | this.root = root;
16 | this.props = props;
17 | // Create a new paragraph
18 | this.adder = this.root.doc.createP();
19 | // Align the children which are of type string
20 | this.adder.options.align = this.props.align;
21 | // Add document information
22 | Object.assign(this.root.doc.options, this.props.info ? this.props.info : {});
23 | // Validate the component props
24 | validateDocProps(this.props);
25 | }
26 |
27 | appendChild(child) {
28 | this.children.push(child);
29 | }
30 |
31 | removeChild(child) {
32 | const index = this.children.indexOf(child);
33 | this.children.splice(index, 1);
34 | }
35 |
36 | async renderChildren() {
37 | for (let i = 0; i < this.children.length; i += 1) {
38 | if (typeof this.children[i] === 'string') {
39 | // If not a component, render it as a paragraph
40 | await this.adder.addText(
41 | this.children[i], this.props.style ? applyStyles(this.props.style) : {},
42 | );
43 | } else if (typeof this.children[i] === 'object') {
44 | // Call render() for each component
45 | await this.children[i].render(this.props.align, this.props.style ? this.props.style : {});
46 | }
47 | }
48 | }
49 |
50 | async render() {
51 | await this.renderChildren();
52 | }
53 | }
54 |
55 | export default Document;
56 |
--------------------------------------------------------------------------------
/src/utils/createElement.js:
--------------------------------------------------------------------------------
1 | import {
2 | BulletItem,
3 | Document,
4 | Footer,
5 | Header,
6 | Hr,
7 | Image,
8 | NumberItem,
9 | LineBreak,
10 | List,
11 | PageBreak,
12 | Table,
13 | Text,
14 | WordDocument,
15 | } from '../components/index';
16 |
17 | // Stores the root container instance
18 | let ROOT_NODE_INSTANCE = null;
19 |
20 | /**
21 | * Updates the ref to ROOT_NODE_INSTANCE
22 | * @param {*} rootNode root instance
23 | */
24 | function getHostContextNode(rootNode) {
25 | if (typeof rootNode !== 'undefined') {
26 | return ROOT_NODE_INSTANCE = rootNode;
27 | }
28 |
29 | console.warn(`${rootNode} is not an instance of officegen docx constructor.`);
30 | // Lazily create the instance (escape hatch if the global state is mutated)
31 | return ROOT_NODE_INSTANCE = new WordDocument();
32 | }
33 |
34 | /**
35 | * Creates an element for a document
36 | * @param {string} type Element type
37 | * @param {Object} props Component props
38 | * @param {Object} root Root instance
39 | */
40 |
41 | function createElement(type, props) {
42 | // Hash table lookup is much better than evaluating each case with switch-case
43 | const COMPONENTS = {
44 | ROOT: () => new WordDocument(),
45 |
46 | DOCUMENT: () => new Document(ROOT_NODE_INSTANCE, props),
47 |
48 | TEXT: () => new Text(ROOT_NODE_INSTANCE, props),
49 | LIST: () => new List(ROOT_NODE_INSTANCE, props),
50 | NUMBERITEM: () => new NumberItem(ROOT_NODE_INSTANCE, props),
51 | BULLETITEM: () => new BulletItem(ROOT_NODE_INSTANCE, props),
52 |
53 | HR: () => new Hr(ROOT_NODE_INSTANCE, props),
54 |
55 | LINEBREAK: () => new LineBreak(ROOT_NODE_INSTANCE, props),
56 | PAGEBREAK: () => new PageBreak(ROOT_NODE_INSTANCE, props),
57 |
58 | TABLE: () => new Table(ROOT_NODE_INSTANCE, props),
59 |
60 | IMAGE: () => new Image(ROOT_NODE_INSTANCE, props),
61 |
62 | HEADER: () => new Header(ROOT_NODE_INSTANCE, props),
63 | FOOTER: () => new Footer(ROOT_NODE_INSTANCE, props),
64 |
65 | default: undefined,
66 | };
67 |
68 | return COMPONENTS[type]() || COMPONENTS.default;
69 | }
70 |
71 | export {
72 | createElement,
73 | getHostContextNode,
74 | };
75 |
--------------------------------------------------------------------------------
/src/components/Table.js:
--------------------------------------------------------------------------------
1 | import { styleSerializer } from '../styles/styles';
2 | import { validateTableProps, headerValidators, tableStyleValidators } from '../validators/componentValidators';
3 |
4 | /**
5 | * This component renders a table with props 'headers', 'data' and 'style' for styling the table
6 | */
7 | class Table {
8 | // Stores headers and corresponding data for the headers
9 | TABLE_DATA = [];
10 |
11 | // Table styles (required for rendering a table)
12 | defaultStyles = {
13 | tableColWidth: 2500,
14 | tableSize: 24,
15 | tableColor: 'black',
16 | tableAlign: 'left',
17 | borders: true,
18 | };
19 |
20 | constructor(root, props) {
21 | this.root = root;
22 | this.props = props;
23 | validateTableProps(this.props);
24 | headerValidators(this.props);
25 | tableStyleValidators(this.props);
26 | }
27 |
28 | // set the headers and serialize each cell's data (in accordance with open office xml)
29 | setHeaders(props) {
30 | const { headers } = props;
31 |
32 | headers.forEach((header) => {
33 | header.val = header.value;
34 | header.opts = header.styles;
35 | header.opts = styleSerializer(header.opts);
36 | delete header.value;
37 | delete header.styles;
38 | });
39 |
40 | // for (let i of headers) {
41 | // i.val = i.value;
42 | // i.opts = i.styles;
43 | // // serialize all the styles according to open office xml values
44 | // i.opts = styleSerializer(i.opts);
45 | // // Inefficient (performance bottleneck)
46 | // delete i.value;
47 | // delete i.styles;
48 | // }
49 |
50 | this.TABLE_DATA.push(headers);
51 | }
52 |
53 | // set the row data
54 | setData(props) {
55 | const { data } = props;
56 | data.forEach((item) => {
57 | this.TABLE_DATA.push(item);
58 | });
59 | }
60 |
61 | // Set everything and finally render a table 😅
62 | async renderTable() {
63 | this.setHeaders(this.props);
64 | this.setData(this.props);
65 | await this.root.doc.createTable(this.TABLE_DATA, this.props.style || this.defaultStyles);
66 | }
67 |
68 | async render() {
69 | await this.renderTable();
70 | }
71 | }
72 |
73 | export default Table;
74 |
--------------------------------------------------------------------------------
/src/renderer/render.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import streams from 'memory-streams';
3 | import { createElement } from '../utils/createElement';
4 | import { WordRenderer } from './renderer';
5 | import parse from './parse';
6 | import { validateElement, validatePath, Events, openDocApp } from '../utils/renderUtils';
7 |
8 |
9 | async function renderToFile(element, filePath) {
10 | const container = createElement('ROOT');
11 |
12 | validateElement(element);
13 |
14 | validatePath(filePath);
15 |
16 | const node = WordRenderer.createContainer(container);
17 |
18 | WordRenderer.updateContainer(element, node, null);
19 |
20 | const output = await parse(container).toBuffer();
21 | const stream = fs.createWriteStream(filePath);
22 |
23 | await new Promise((resolve, reject) => {
24 | output.doc.generate(stream, Events(filePath, resolve, reject));
25 |
26 | openDocApp(filePath);
27 | });
28 | }
29 |
30 | async function renderToMemory(element) {
31 | const container = createElement('ROOT');
32 |
33 | validateElement(element);
34 |
35 | const node = WordRenderer.createContainer(container);
36 |
37 | WordRenderer.updateContainer(element, node, null);
38 |
39 | const output = await parse(container).toBuffer();
40 | const stream = new streams.WritableStream();
41 |
42 | await new Promise((resolve, reject) => {
43 | output.doc.generate(stream);
44 | stream.on('finish', () => {
45 | resolve();
46 | });
47 | stream.on('error', () => {
48 | reject();
49 | });
50 | });
51 |
52 | return stream;
53 | }
54 |
55 | /**
56 | * This function renders the component
57 | * @param {Object} element
58 | * @param {string} filePath
59 | */
60 | async function render(element, filePath) {
61 | if (typeof filePath !== 'undefined') {
62 | return renderToFile(element, filePath);
63 | }
64 | return renderToMemory(element);
65 | }
66 |
67 | /**
68 | * Required for test the components
69 | */
70 | function testRenderer(element) {
71 | const container = createElement('ROOT');
72 | const node = WordRenderer.createContainer(container);
73 |
74 | WordRenderer.updateContainer(element, node, null);
75 |
76 | return container;
77 | }
78 |
79 | export { render, testRenderer };
80 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/createElement.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`should create an element 1`] = `
4 | WordDocument {
5 | "doc": officegen {
6 | "_events": Object {
7 | "afterGen": [Function],
8 | "beforeGen": [Function],
9 | "clearData": [Function],
10 | "clearDoc": [Function],
11 | "clearDocType": [Function],
12 | },
13 | "_eventsCount": 5,
14 | "_maxListeners": undefined,
15 | "addPageBreak": [Function],
16 | "addResourceToParse": [Function],
17 | "cbMakeDocxDocument": [Function],
18 | "createByJson": [Function],
19 | "createJson": [Function],
20 | "createListOfDots": [Function],
21 | "createListOfNumbers": [Function],
22 | "createP": [Function],
23 | "createTable": [Function],
24 | "data": Array [],
25 | "domain": null,
26 | "generate": [Function],
27 | "getFooter": [Function],
28 | "getHeader": [Function],
29 | "info": Object {
30 | "cp:category": Object {
31 | "data": "",
32 | "def_data": "",
33 | "element": "cp:category",
34 | },
35 | "cp:contentStatus": Object {
36 | "data": "",
37 | "def_data": "",
38 | "element": "cp:contentStatus",
39 | },
40 | "cp:keywords": Object {
41 | "data": "",
42 | "def_data": "",
43 | "element": "cp:keywords",
44 | },
45 | "dc:description": Object {
46 | "data": "",
47 | "def_data": "",
48 | "element": "dc:description",
49 | },
50 | "dc:subject": Object {
51 | "data": "",
52 | "def_data": "",
53 | "element": "dc:subject",
54 | },
55 | "dc:title": Object {
56 | "data": "",
57 | "def_data": "",
58 | "element": "dc:title",
59 | },
60 | },
61 | "options": Object {
62 | "type": "docx",
63 | },
64 | "putPageBreak": [Function],
65 | "setDescription": [Function],
66 | "setDocCategory": [Function],
67 | "setDocKeywords": [Function],
68 | "setDocStatus": [Function],
69 | "setDocSubject": [Function],
70 | "setDocTitle": [Function],
71 | "setTheme": [Function],
72 | "startNewDoc": [Function],
73 | "theme": null,
74 | },
75 | }
76 | `;
77 |
--------------------------------------------------------------------------------
/docs/styling.md:
--------------------------------------------------------------------------------
1 | # Styling 💄
2 |
3 | #### You can use [glamorous-redocx](https://github.com/nitin42/glamorous-redocx) to style the redocx components. Check it out because it's awesome!
4 |
5 | ## Style properties for the component
6 | Below are the style properties for Text, Document, List, Header, Footer, BulletItem and NumberItem components.
7 |
8 | | Property | Type | Default |
9 | | ------------- | ------------- | ------------- |
10 | | `backgroundColor` | `string` |
11 | | `bold` | `boolean` | `false` |
12 | | `border` | `string` |
13 | | `borderSize` | `number` |
14 | | `borderColor` | `string`
15 | | `color` | `string` |
16 | | `fontSize` | `number` |
17 | | `fontFace` | `string` |
18 | | `highlight` | `string` |
19 | | `italic` | `boolean` | `false` |
20 | | `link` | `string` | |
21 | | `underline` | `boolean` | `false`
22 |
23 | `border` can take values `'single'`, `'dashDotStroked'`, `'dashed'`, `'dashSmallGap'`, `'dotDash'`, `'dotDotDash'`, `'dotted'`, `'double'`, `'thick'`, etc.
24 |
25 | ## Style attributes for component
26 |
27 | | Property | Type | Default |
28 | | ------------- | ------------- | ------------- |
29 | | `width` | `number` |
30 | | `height` | `number` | |
31 |
32 | or you can pass a style object describing the image dimensions.
33 |
34 | ```
35 | { width: 200, height: 200 }
36 | ```
37 |
38 | ## component
39 |
40 | ### Style properties for each heading
41 |
42 | | Property | Type | Default |
43 | | ------------- | ------------- | ------------- |
44 | | `bold` | `boolean` | `false`
45 | | `size` | `number` | |
46 | | `color` | `string` | |
47 | | `align` | `string` | |
48 | | `valign` | `string` | |
49 | | `fontFamily` | `string` | |
50 | | `fill` | `string` | |
51 | | `cellColWidth` | `number` | |
52 |
53 | ### Table styles
54 |
55 | | Property | Type | Default |
56 | | ------------- | ------------- | ------------- |
57 | | `tableColWidth` | `number` |
58 | | `tableSize` | `number` | |
59 | | `tableColor` | `string` | |
60 | | `tableAlign` | `string` | |
61 | | `borders` | `boolean` | `false` |
62 |
63 | > I am experimenting with the [yoga](https://facebook.github.io/yoga/) layout. If that goes well, then flex layout will also be supported 😄
64 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Documentation
2 |
3 | ## Table of content
4 |
5 | * [Introduction](https://github.com/nitin42/redocx#introduction)
6 | * [API Reference](https://github.com/nitin42/redocx/blob/master/docs/api.md#api-reference)
7 | * [render](https://github.com/nitin42/redocx/blob/master/docs/api.md#renderelement-filepath)
8 | * [Document](https://github.com/nitin42/redocx/blob/master/docs/api.md#document-)
9 | * [Text](https://github.com/nitin42/redocx/blob/master/docs/api.md#text-)
10 | * [List](https://github.com/nitin42/redocx/blob/master/docs/api.md#list-)
11 | * [BulletItem](https://github.com/nitin42/redocx/blob/master/docs/api.md#bulletitem-)
12 | * [NumberItem](https://github.com/nitin42/redocx/blob/master/docs/api.md#numberitem--currently-unstable)
13 | * [Header](https://github.com/nitin42/redocx/blob/master/docs/api.md#header-)
14 | * [Footer](https://github.com/nitin42/redocx/blob/master/docs/api.md#footer-)
15 | * [Horizontal Line](https://github.com/nitin42/redocx/blob/master/docs/api.md#hr-)
16 | * [LineBreak](https://github.com/nitin42/redocx/blob/master/docs/api.md#linebreak-)
17 | * [PageBreak](https://github.com/nitin42/redocx/blob/master/docs/api.md#pagebreak-)
18 | * [Table](https://github.com/nitin42/redocx/blob/master/docs/api.md#table-)
19 | * [Image](https://github.com/nitin42/redocx/blob/master/docs/api.md#image-)
20 | * [Platform](https://github.com/nitin42/redocx/blob/master/docs/api.md#platform)
21 | * [Styling](https://github.com/nitin42/redocx/blob/master/docs/styling.md)
22 | * [Components](https://github.com/nitin42/redocx/blob/master/docs/styling.md#style-properties-for-the-component)
23 | * [Images](https://github.com/nitin42/redocx/blob/master/docs/styling.md#style-attributes-for-image--component)
24 | * [Table styles](https://github.com/nitin42/redocx/blob/master/docs/styling.md#table--component)
25 | * [Examples](../examples)
26 | * [Image](../examples/Image.js)
27 | * [Text](../examples/Text.js)
28 | * [List](../examples/List.js)
29 | * [Header](../examples/Header.js)
30 | * [Footer](../examples/Footer.js)
31 | * [Horizontal Line](../examples/Hr.js)
32 | * [PageBreak](../examples/PageBreak.js)
33 | * [Table](../examples/Table.js)
34 | * [Extra](./misc.md)
35 | * [Contributing](https://github.com/nitin42/redocx/blob/master/CONTRIBUTING.md)
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # redocx
2 | [](https://travis-ci.org/nitin42/redocx)
3 | 
4 | 
5 | 
6 |
7 | > Create word documents with React
8 |
9 |
10 |
11 |
12 |
13 | ## Introduction
14 |
15 | `redocx` is a library which lets you create word documents with React. It provides a set of components which renders your declarative views and components to word documents.
16 |
17 | #### Example
18 |
19 | A simple component that renders a "Hello World" text to a word document.
20 |
21 | ```js
22 | import React from 'react'
23 | import { render, Document, Text } from 'redocx'
24 |
25 | class App extends React.Component {
26 | render() {
27 | return (
28 |
29 | Hello World
30 |
31 | )
32 | }
33 | }
34 |
35 | render(, `${__dirname}/example.docx`)
36 | ```
37 |
38 | Let's get started!
39 |
40 |
41 | ## Install
42 |
43 | **Babel presets and cli**
44 |
45 | ```
46 | npm install --save-dev babel-cli babel-core babel-preset-env babel-preset-react babel-preset-stage-0
47 | ```
48 |
49 | **react and redocx**
50 |
51 | ```
52 | npm install --save react redocx
53 | ```
54 |
55 | ## Usage
56 |
57 | * Create a `.babelrc`
58 |
59 | ```
60 | {
61 | "presets": [
62 | "env",
63 | "stage-0",
64 | "react"
65 | ]
66 | }
67 | ```
68 |
69 | * After configuring babel and assuming you've already created a file `example.js` with [this](#example) example, run `babel-node example.js`. This will render your React component to word document.
70 |
71 |
72 | ## Demo
73 |
74 | ```
75 | git clone https://github.com/nitin42/redocx.git
76 | cd redocx
77 | npm install
78 | npm run example
79 | ```
80 |
81 | ## Documentation
82 |
83 | See the detailed documentation [here](./docs)
84 |
85 | ## Contributing
86 |
87 | [Contributing guide](https://github.com/nitin42/redocx/blob/master/CONTRIBUTING.md)
88 |
89 | ## License
90 |
91 | MIT
92 |
93 | [](https://app.codesponsor.io/link/FCRW65HPiwhNtebDx2tTc53E/nitin42/redocx)
94 |
95 |
--------------------------------------------------------------------------------
/__tests__/Text.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Document, Text, LineBreak, Image, Hr } from '../src/';
3 | import { testRenderer as render } from '../src/renderer/render';
4 |
5 | it('sanity check', () => {
6 | const App = () => (
7 | Hello World!
8 | )
9 | expect(render()).toMatchSnapshot();
10 | });
11 |
12 | it('should render the children', () => {
13 | const App = () => (
14 |
15 | Hello ! This is a test for rendering the children!
16 |
17 | )
18 |
19 | expect(render()).toMatchSnapshot();
20 | })
21 |
22 | it('should accept style prop', () => {
23 | const App = () => (
24 |
25 | I'm red!
26 |
27 | )
28 |
29 | expect(render()).toMatchSnapshot();
30 | })
31 |
32 | it('should accept align prop', () => {
33 | const App = () => (
34 |
35 | I'm centered!
36 |
37 | )
38 |
39 | expect(render()).toMatchSnapshot();
40 | })
41 |
42 | it('should render the children with a LineBreak component', () => {
43 | const App = () => (
44 |
45 | Hello World!
46 |
47 | This is a new line!
48 |
49 | )
50 |
51 | expect(render()).toMatchSnapshot()
52 | })
53 |
54 | it('should render the children with a Image component', () => {
55 | const App = () => (
56 |
57 | Hello World!
58 |
59 |
60 | )
61 |
62 | expect(render()).toMatchSnapshot()
63 | })
64 |
65 | it('should render the children with a Hr component', () => {
66 | const App = () => (
67 |
68 | Hello World!
69 |
70 |
71 | )
72 |
73 | expect(render()).toMatchSnapshot()
74 | })
75 |
76 | it('should render with intermediate components', () => {
77 | const App = () => (
78 |
79 | Hello World!
80 |
81 | This is a new line
82 |
83 |
84 |
85 |
86 | )
87 |
88 | expect(render()).toMatchSnapshot();
89 | })
90 |
91 | it('should align the children with context', () => {
92 | const App = () => (
93 |
94 | Hello ! I'm centered
95 |
96 | )
97 |
98 | expect(render()).toMatchSnapshot();
99 | })
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Hr.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`should draw a horizontal ruler 1`] = `
4 | WordDocument {
5 | "doc": officegen {
6 | "_events": Object {
7 | "afterGen": [Function],
8 | "beforeGen": [Function],
9 | "clearData": [Function],
10 | "clearDoc": [Function],
11 | "clearDocType": [Function],
12 | },
13 | "_eventsCount": 5,
14 | "_maxListeners": undefined,
15 | "addPageBreak": [Function],
16 | "addResourceToParse": [Function],
17 | "cbMakeDocxDocument": [Function],
18 | "createByJson": [Function],
19 | "createJson": [Function],
20 | "createListOfDots": [Function],
21 | "createListOfNumbers": [Function],
22 | "createP": [Function],
23 | "createTable": [Function],
24 | "data": Array [],
25 | "domain": null,
26 | "generate": [Function],
27 | "getFooter": [Function],
28 | "getHeader": [Function],
29 | "info": Object {
30 | "cp:category": Object {
31 | "data": "",
32 | "def_data": "",
33 | "element": "cp:category",
34 | },
35 | "cp:contentStatus": Object {
36 | "data": "",
37 | "def_data": "",
38 | "element": "cp:contentStatus",
39 | },
40 | "cp:keywords": Object {
41 | "data": "",
42 | "def_data": "",
43 | "element": "cp:keywords",
44 | },
45 | "dc:description": Object {
46 | "data": "",
47 | "def_data": "",
48 | "element": "dc:description",
49 | },
50 | "dc:subject": Object {
51 | "data": "",
52 | "def_data": "",
53 | "element": "dc:subject",
54 | },
55 | "dc:title": Object {
56 | "data": "",
57 | "def_data": "",
58 | "element": "dc:title",
59 | },
60 | },
61 | "options": Object {
62 | "type": "docx",
63 | },
64 | "putPageBreak": [Function],
65 | "setDescription": [Function],
66 | "setDocCategory": [Function],
67 | "setDocKeywords": [Function],
68 | "setDocStatus": [Function],
69 | "setDocSubject": [Function],
70 | "setDocTitle": [Function],
71 | "setTheme": [Function],
72 | "startNewDoc": [Function],
73 | "theme": null,
74 | },
75 | "document": Hr {
76 | "children": Array [],
77 | "name": "Hr",
78 | "parent": null,
79 | "props": Object {},
80 | "root": [Circular],
81 | },
82 | }
83 | `;
84 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/PageBreak.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`should put a page break 1`] = `
4 | WordDocument {
5 | "doc": officegen {
6 | "_events": Object {
7 | "afterGen": [Function],
8 | "beforeGen": [Function],
9 | "clearData": [Function],
10 | "clearDoc": [Function],
11 | "clearDocType": [Function],
12 | },
13 | "_eventsCount": 5,
14 | "_maxListeners": undefined,
15 | "addPageBreak": [Function],
16 | "addResourceToParse": [Function],
17 | "cbMakeDocxDocument": [Function],
18 | "createByJson": [Function],
19 | "createJson": [Function],
20 | "createListOfDots": [Function],
21 | "createListOfNumbers": [Function],
22 | "createP": [Function],
23 | "createTable": [Function],
24 | "data": Array [
25 | Object {
26 | "data": Array [
27 | Object {
28 | "page_break": true,
29 | },
30 | ],
31 | },
32 | ],
33 | "domain": null,
34 | "generate": [Function],
35 | "getFooter": [Function],
36 | "getHeader": [Function],
37 | "info": Object {
38 | "cp:category": Object {
39 | "data": "",
40 | "def_data": "",
41 | "element": "cp:category",
42 | },
43 | "cp:contentStatus": Object {
44 | "data": "",
45 | "def_data": "",
46 | "element": "cp:contentStatus",
47 | },
48 | "cp:keywords": Object {
49 | "data": "",
50 | "def_data": "",
51 | "element": "cp:keywords",
52 | },
53 | "dc:description": Object {
54 | "data": "",
55 | "def_data": "",
56 | "element": "dc:description",
57 | },
58 | "dc:subject": Object {
59 | "data": "",
60 | "def_data": "",
61 | "element": "dc:subject",
62 | },
63 | "dc:title": Object {
64 | "data": "",
65 | "def_data": "",
66 | "element": "dc:title",
67 | },
68 | },
69 | "options": Object {
70 | "type": "docx",
71 | },
72 | "putPageBreak": [Function],
73 | "setDescription": [Function],
74 | "setDocCategory": [Function],
75 | "setDocKeywords": [Function],
76 | "setDocStatus": [Function],
77 | "setDocSubject": [Function],
78 | "setDocTitle": [Function],
79 | "setTheme": [Function],
80 | "startNewDoc": [Function],
81 | "theme": null,
82 | },
83 | "document": PageBreak {
84 | "adder": Object {
85 | "data": Array [
86 | Object {
87 | "page_break": true,
88 | },
89 | ],
90 | },
91 | "children": Array [],
92 | "parent": null,
93 | "props": Object {},
94 | "root": [Circular],
95 | },
96 | }
97 | `;
98 |
--------------------------------------------------------------------------------
/src/styles/styles.js:
--------------------------------------------------------------------------------
1 | import chroma from 'chroma-js';
2 | import isHex from 'validator/lib/isHexadecimal';
3 |
4 | /**
5 | * Get the hex value or the color name
6 | * @param {string} value hex or color name
7 | */
8 | function getHexOrColor(value) {
9 | if (typeof value === 'undefined') {
10 | return isHex('undefined');
11 | } else if (isHex(value)) {
12 | return value.replace('#', '');
13 | }
14 | return chroma(value).hex().replace('#', '');
15 | }
16 |
17 | /**
18 | * Function to apply the styles to a component
19 | * @param {Object} props Component props
20 | */
21 | function applyStyles(props) {
22 | if (Object.keys(props) === 0) {
23 | return {};
24 | }
25 |
26 | const {
27 | backgroundColor,
28 | color,
29 | fontSize,
30 | fontFace,
31 | bold,
32 | border,
33 | underline,
34 | italic,
35 | highlight,
36 | borderSize,
37 | borderColor,
38 | link,
39 | } = props;
40 |
41 | return {
42 | back: getHexOrColor(backgroundColor),
43 | color: getHexOrColor(color),
44 | highlight: getHexOrColor(highlight),
45 | italic,
46 | underline,
47 | bold,
48 | border,
49 | borderColor: getHexOrColor(borderColor),
50 | borderSize,
51 | font_size: fontSize,
52 | font_face: fontFace,
53 | link,
54 | };
55 | }
56 |
57 | /**
58 | * Function to apply style attributes to component
59 | * @param {Object} props Component props
60 | */
61 | function imageProps(props) {
62 | const { width, height } = props;
63 |
64 | return {
65 | cx: parseInt(width, 10),
66 | cy: parseInt(height, 10),
67 | };
68 | }
69 |
70 | /**
71 | * Function to apply style attributes to component without style prop
72 | * @param {Object} Component props
73 | */
74 | function addStyles(props) {
75 | return {
76 | cx: props.width ? parseInt(props.width, 10) : null,
77 | cy: props.height ? parseInt(props.height, 10) : null,
78 | };
79 | }
80 |
81 | /**
82 | * Function to add related attributes with or without using style prop
83 | * @param {Object} props Component props
84 | */
85 | function applyImageProps(props) {
86 | return props.style ? imageProps(props.style) : addStyles(props);
87 | }
88 |
89 | /**
90 | * Function to serialize style properties for component according to open office xml
91 | * @param {Object} values style attributes for table
92 | */
93 | function styleSerializer(values) {
94 | const { bold, size, color, align, vAlign, fontFamily, fill, cellColWidth } = values;
95 |
96 | return {
97 | b: bold,
98 | sz: size,
99 | color: getHexOrColor(color),
100 | align,
101 | vAlign,
102 | fontFamily,
103 | fill: getHexOrColor(fill),
104 | cellColWidth,
105 | };
106 | }
107 |
108 | export { applyStyles, applyImageProps, styleSerializer };
109 |
--------------------------------------------------------------------------------
/__tests__/Bullets.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { List, Document, BulletItem, NumberItem } from '../src/';
3 | import { testRenderer as render } from '../src/renderer/render';
4 |
5 | it('sanity check', () => {
6 | expect(render(
)).toMatchSnapshot()
7 | })
8 |
9 | it('should render a list of dots', () => {
10 | const App = () => (
11 |
12 | One
13 | Two
14 |
15 | )
16 |
17 | expect(render()).toMatchSnapshot();
18 | })
19 |
20 | it('should render a list of numbers (currently unstable)', () => {
21 | const App = () => (
22 |
23 | One
24 | Two
25 |
26 | )
27 |
28 | expect(render()).toMatchSnapshot();
29 | })
30 |
31 | it('should render a list of dots with style prop', () => {
32 | const App = () => (
33 |
34 | One
35 | Two
36 |
37 | )
38 |
39 | expect(render()).toMatchSnapshot();
40 | })
41 |
42 | it('should render a list of dots with align prop', () => {
43 | const App = () => (
44 |
45 | One
46 | Two
47 |
48 | )
49 |
50 | expect(render()).toMatchSnapshot();
51 | })
52 |
53 | it('should render a list of dots and each item can be styled and aligned individually', () => {
54 | const App = () => (
55 |
56 | One
57 | Two
58 |
59 | )
60 |
61 | expect(render()).toMatchSnapshot();
62 | })
63 |
64 | it('should render a list of numbers with align prop', () => {
65 | const App = () => (
66 |
67 | One
68 | Two
69 |
70 | )
71 |
72 | expect(render()).toMatchSnapshot();
73 | })
74 |
75 | it('should render a list of numbers and each item can be styled and aligned individually', () => {
76 | const App = () => (
77 |
78 | One
79 | Two
80 |
81 | )
82 |
83 | expect(render()).toMatchSnapshot();
84 | })
85 |
86 | it('should render a list and aligned through context', () => {
87 | const App = () => (
88 |
89 |
90 | One
91 | Two
92 |
93 |
94 | )
95 |
96 | expect(render()).toMatchSnapshot();
97 | })
98 |
99 | it('should render a list and styled through context', () => {
100 | const App = () => (
101 |
102 |
103 | One
104 | Two
105 |
106 |
107 | )
108 |
109 | expect(render()).toMatchSnapshot();
110 | })
111 |
--------------------------------------------------------------------------------
/src/components/Text.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import Root from './Root';
3 | import { applyImageProps } from '../styles/styles';
4 | import { validateTextProps } from '../validators/componentValidators';
5 | import { alignChildren, renderText } from '../utils/nodes';
6 |
7 | /**
8 | * This component creates a new paragraph with every new instance and renders the children.
9 | * It wraps LineBreak and Image component as intermediate component and calls the corresponding
10 | * render method. This behaviour may change depending on new use cases (from open office xml)
11 | */
12 | class Text extends Root {
13 | constructor(root, props) {
14 | super(root, props);
15 | this.root = root;
16 | this.props = props;
17 | this.adder = this.root.doc.createP();
18 | validateTextProps(this.props);
19 | }
20 |
21 | appendChild(child) {
22 | this.children.push(child);
23 | }
24 |
25 | removeChild(child) {
26 | const index = this.children.indexOf(child);
27 | this.children.splice(index, 1);
28 | }
29 |
30 | setParent = (node, childName) => node.parent = (node.name === childName ? 'Text' : null);
31 |
32 | /**
33 | * Render intermediate components (LineBreak, Image and Hr)
34 | * Not enough use cases (couldn't derive more use cases from open office xml)
35 | */
36 | async renderIntermediateComponents(child, instance) {
37 | switch (child.name) {
38 | case 'LineBreak':
39 | // LineBreak component should not be called as an independent component.
40 | await instance.addLineBreak();
41 | break;
42 | case 'Image':
43 | // Here we keep track of render() method for Image component as this avoids rendering -
44 | // the Image component twice because Document component also calls render() method on all -
45 | // of its children. So we set its parent to 'Text' component and it calls render() once -
46 | // and avoids a second render() call by setting its parent to 'Text'. By default, if we -
47 | // call Image component as an independent component, it has a parent null || 'Document' -
48 | // so it calls the render() only once.
49 |
50 | this.setParent(child, 'Image');
51 | // child.name === 'Image' ? (child.parent = 'Text') : (child.parent = null);
52 | await instance.addImage(path.resolve(child.props.src), applyImageProps(child.props));
53 | break;
54 | case 'Hr':
55 | // Same thing happening here also!
56 | this.setParent(child, 'Hr');
57 | await instance.addHorizontalLine();
58 | break;
59 | default:
60 | break;
61 | }
62 | }
63 |
64 | async renderChildren(align, styles) {
65 | alignChildren(this.adder, align, this.props.align);
66 |
67 | for (let i = 0; i < this.children.length; i += 1) {
68 | if (typeof this.children[i] === 'string') {
69 | await renderText(this.children[i], this.props, styles, this.adder);
70 | } else {
71 | await this.renderIntermediateComponents(this.children[i], this.adder);
72 | }
73 | }
74 | }
75 |
76 | async render(align, styles) {
77 | await this.renderChildren(align, styles);
78 | }
79 | }
80 |
81 | export default Text;
82 |
--------------------------------------------------------------------------------
/src/renderer/renderer.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 |
3 | import emptyObject from 'fbjs/lib/emptyObject'
4 | const Reconciler = require('react-reconciler')
5 |
6 | import { createElement, getHostContextNode } from '../utils/createElement'
7 |
8 | const RendererHostConfig = {
9 | appendInitialChild(parentInstance, child) {
10 | if (parentInstance.appendChild) {
11 | parentInstance.appendChild(child)
12 | } else {
13 | parentInstance.document = child
14 | }
15 | },
16 |
17 | createInstance(type, props, internalInstanceHandle) {
18 | return createElement(type, props)
19 | },
20 |
21 | createTextInstance(text, rootContainerInstance, internalInstanceHandle) {
22 | return text
23 | },
24 |
25 | finalizeInitialChildren(wordElement, type, props) {
26 | return false
27 | },
28 |
29 | getPublicInstance(inst) {
30 | return inst
31 | },
32 |
33 | prepareForCommit() {
34 | // noop
35 | },
36 |
37 | prepareUpdate(wordElement, type, oldProps, newProps) {
38 | return true
39 | },
40 |
41 | resetAfterCommit() {
42 | // noop
43 | },
44 |
45 | resetTextContent(wordElement) {
46 | // Redocx does not have a text node like DOM
47 | },
48 |
49 | // If you've such use case where you need to provide data from the root instance,
50 | // see the below example. This may help you in creating your own custom renderer
51 |
52 | createInstance(type, props, internalInstanceHandle) {
53 | // 'internalInstanceHandle' is not transparent here. So use host context methods
54 | // to get data from roots
55 | return createElement(type, props)
56 | },
57 |
58 | // Use this current instance to pass data from root
59 | getRootHostContext(instance) {
60 | // getHostContextNode here updates the internal state of createElement and stores a ref to current instance
61 | return getHostContextNode(instance)
62 | },
63 |
64 | getChildHostContext() {
65 | return emptyObject
66 | },
67 |
68 | shouldSetTextContent(type, props) {
69 | return false // Redocx does not have a text node like DOM
70 | },
71 |
72 | now: () => {},
73 |
74 | useSyncScheduling: true,
75 |
76 | mutation: {
77 | appendChild(parentInstance, child) {
78 | if (parentInstance.appendChild) {
79 | parentInstance.appendChild(child)
80 | } else {
81 | parentInstance.document = child
82 | }
83 | },
84 |
85 | appendChildToContainer(parentInstance, child) {
86 | if (parentInstance.appendChild) {
87 | parentInstance.appendChild(child)
88 | } else {
89 | parentInstance.document = child
90 | }
91 | },
92 |
93 | removeChild(parentInstance, child) {
94 | parentInstance.removeChild(child)
95 | },
96 |
97 | removeChildFromContainer(parentInstance, child) {
98 | parentInstance.removeChild(child)
99 | },
100 |
101 | insertBefore(parentInstance, child, beforeChild) {
102 | // noob
103 | },
104 |
105 | commitUpdate(instance, updatePayload, type, oldProps, newProps) {
106 | // noop
107 | },
108 |
109 | commitMount(instance, updatePayload, type, oldProps, newProps) {
110 | // noop
111 | },
112 |
113 | commitTextUpdate(textInstance, oldText, newText) {
114 | textInstance.children = newText
115 | },
116 | },
117 | }
118 |
119 | const WordRenderer = Reconciler(RendererHostConfig)
120 |
121 | export { WordRenderer }
--------------------------------------------------------------------------------
/src/validators/componentValidators.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Validates props for component
3 | * @param {Object} props Component props
4 | */
5 | function validateDocProps(props) {
6 | const { info, align } = props;
7 | const infoSchema = ['author', 'description', 'keywords', 'orientation', 'subject', 'title'];
8 | const infoKeys = Object.keys(info || {});
9 | const alignValues = ['left', 'right', 'center', 'justify'];
10 |
11 | if (info && typeof info !== 'object') {
12 | throw new Error('\'info\' prop expected an information object.');
13 | }
14 |
15 | infoKeys.forEach((key) => {
16 | if (!infoSchema.includes(key)) {
17 | throw new Error(`'${key}' is an invalid property for document description.`);
18 | }
19 | });
20 |
21 | if (align && !alignValues.includes(align)) {
22 | throw new Error('\'align\' prop can only take \'left\', \'right\', \'center\' and \'justify\'');
23 | }
24 | }
25 |
26 | /**
27 | * Validates props for component
28 | * @param {Object} props Component props
29 | */
30 | function validateTableProps(props) {
31 | const { headers, data, style } = props;
32 | const knownProps = ['headers', 'data', 'style'];
33 |
34 | if (headers && !Array.isArray(headers)) {
35 | throw new Error('\'headers\' prop expected an array of object corresponding to the values for headers. For example - [{ value: \'Name\', styles: { color: \'mistyrose\' }}]');
36 | }
37 |
38 | if (data && !Array.isArray(data)) {
39 | throw new Error('\'data\' prop expected an array of array values for each cell in row. For example - Considering there are three headers, name, subject and marks, the values will be [[\'A\', \'Maths\', \'30\'], [\'B\', \'Computer Science\', \'40\']]');
40 | }
41 |
42 | if (style && typeof style !== 'object') {
43 | throw new Error('style prop expected an object of table styles.');
44 | }
45 |
46 | const keys = Object.keys(props);
47 |
48 | keys.forEach((key) => {
49 | if (!knownProps.includes(key)) {
50 | throw new Error(`Unknown prop '${key}' passed to component. Supported props are headers, data and style.`);
51 | }
52 | });
53 | }
54 |
55 | /**
56 | * Validates schema for headers prop in component
57 | * @param {Object} props Component props
58 | */
59 | function headerValidators(props) {
60 | const { headers } = props;
61 | const headerSchema = ['value', 'styles'];
62 | const styleSchema = ['bold', 'size', 'color', 'align', 'vAlign', 'fontFamily', 'fill'];
63 |
64 | headers.forEach((header) => {
65 | Object.keys(header).forEach((key) => {
66 | if (!headerSchema.includes(key)) {
67 | throw new Error(`'${key}' is not supported as a property for headers. Valid property names are 'value' and 'styles'.`);
68 | }
69 | });
70 | });
71 |
72 | headers.forEach((header) => {
73 | Object.keys(header.styles).forEach((key) => {
74 | if (!styleSchema.includes(key)) {
75 | throw new Error(`'${key}' is an invalid style property for header. Check the style value for header ${headers.indexOf(key) + 1}`);
76 | }
77 | });
78 | });
79 | }
80 |
81 | /**
82 | * Validates schema for style prop in component
83 | * (currently styles cannot be extended so style schema is needed)
84 | *
85 | * @param {Object} props Component props
86 | */
87 | function tableStyleValidators(props) {
88 | const { style } = props;
89 | const styleKeys = Object.keys(style || {});
90 | const tableStyleSchema = ['tableColWidth', 'tableSize', 'tableColor', 'tableAlign', 'borders'];
91 |
92 | styleKeys.forEach((key) => {
93 | if (!tableStyleSchema.includes(key)) {
94 | throw new Error(`'${key}' is an invalid style property for table style.`);
95 | }
96 | });
97 | }
98 |
99 | /**
100 | * Validates the props for Text component
101 | * @param {Object} props Component props
102 | */
103 | function validateTextProps(props) {
104 | const knownProps = ['style', 'align', 'children'];
105 | const takesProps = Object.keys(props || {});
106 |
107 | takesProps.forEach((prop) => {
108 | if (!knownProps.includes(prop)) {
109 | throw new Error(
110 | `Unknown prop '${prop}' passed to Text component. Supported props are 'style' and 'align'.`,
111 | );
112 | }
113 | });
114 | }
115 |
116 | export {
117 | validateDocProps,
118 | validateTableProps,
119 | headerValidators,
120 | tableStyleValidators,
121 | validateTextProps,
122 | };
123 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Table.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`should render a table with data and style prop 1`] = `
4 | WordDocument {
5 | "doc": officegen {
6 | "_events": Object {
7 | "afterGen": [Function],
8 | "beforeGen": [Function],
9 | "clearData": [Function],
10 | "clearDoc": [Function],
11 | "clearDocType": [Function],
12 | },
13 | "_eventsCount": 5,
14 | "_maxListeners": undefined,
15 | "addPageBreak": [Function],
16 | "addResourceToParse": [Function],
17 | "cbMakeDocxDocument": [Function],
18 | "createByJson": [Function],
19 | "createJson": [Function],
20 | "createListOfDots": [Function],
21 | "createListOfNumbers": [Function],
22 | "createP": [Function],
23 | "createTable": [Function],
24 | "data": Array [],
25 | "domain": null,
26 | "generate": [Function],
27 | "getFooter": [Function],
28 | "getHeader": [Function],
29 | "info": Object {
30 | "cp:category": Object {
31 | "data": "",
32 | "def_data": "",
33 | "element": "cp:category",
34 | },
35 | "cp:contentStatus": Object {
36 | "data": "",
37 | "def_data": "",
38 | "element": "cp:contentStatus",
39 | },
40 | "cp:keywords": Object {
41 | "data": "",
42 | "def_data": "",
43 | "element": "cp:keywords",
44 | },
45 | "dc:description": Object {
46 | "data": "",
47 | "def_data": "",
48 | "element": "dc:description",
49 | },
50 | "dc:subject": Object {
51 | "data": "",
52 | "def_data": "",
53 | "element": "dc:subject",
54 | },
55 | "dc:title": Object {
56 | "data": "",
57 | "def_data": "",
58 | "element": "dc:title",
59 | },
60 | },
61 | "options": Object {
62 | "type": "docx",
63 | },
64 | "putPageBreak": [Function],
65 | "setDescription": [Function],
66 | "setDocCategory": [Function],
67 | "setDocKeywords": [Function],
68 | "setDocStatus": [Function],
69 | "setDocSubject": [Function],
70 | "setDocTitle": [Function],
71 | "setTheme": [Function],
72 | "startNewDoc": [Function],
73 | "theme": null,
74 | },
75 | "document": Table {
76 | "TABLE_DATA": Array [],
77 | "defaultStyles": Object {
78 | "borders": true,
79 | "tableAlign": "left",
80 | "tableColWidth": 2500,
81 | "tableColor": "black",
82 | "tableSize": 24,
83 | },
84 | "props": Object {
85 | "data": Array [
86 | Array [
87 | "iPhone 7",
88 | "128GB",
89 | ],
90 | Array [
91 | "iPhone 5SE",
92 | "64GB",
93 | ],
94 | ],
95 | "headers": Array [
96 | Object {
97 | "styles": Object {
98 | "bold": true,
99 | "color": "red",
100 | "size": 10,
101 | },
102 | "value": "Phone",
103 | },
104 | Object {
105 | "styles": Object {
106 | "bold": true,
107 | "color": "blue",
108 | "size": 10,
109 | },
110 | "value": "Capacity",
111 | },
112 | ],
113 | },
114 | "root": [Circular],
115 | },
116 | }
117 | `;
118 |
119 | exports[`should render a table with some data 1`] = `
120 | WordDocument {
121 | "doc": officegen {
122 | "_events": Object {
123 | "afterGen": [Function],
124 | "beforeGen": [Function],
125 | "clearData": [Function],
126 | "clearDoc": [Function],
127 | "clearDocType": [Function],
128 | },
129 | "_eventsCount": 5,
130 | "_maxListeners": undefined,
131 | "addPageBreak": [Function],
132 | "addResourceToParse": [Function],
133 | "cbMakeDocxDocument": [Function],
134 | "createByJson": [Function],
135 | "createJson": [Function],
136 | "createListOfDots": [Function],
137 | "createListOfNumbers": [Function],
138 | "createP": [Function],
139 | "createTable": [Function],
140 | "data": Array [],
141 | "domain": null,
142 | "generate": [Function],
143 | "getFooter": [Function],
144 | "getHeader": [Function],
145 | "info": Object {
146 | "cp:category": Object {
147 | "data": "",
148 | "def_data": "",
149 | "element": "cp:category",
150 | },
151 | "cp:contentStatus": Object {
152 | "data": "",
153 | "def_data": "",
154 | "element": "cp:contentStatus",
155 | },
156 | "cp:keywords": Object {
157 | "data": "",
158 | "def_data": "",
159 | "element": "cp:keywords",
160 | },
161 | "dc:description": Object {
162 | "data": "",
163 | "def_data": "",
164 | "element": "dc:description",
165 | },
166 | "dc:subject": Object {
167 | "data": "",
168 | "def_data": "",
169 | "element": "dc:subject",
170 | },
171 | "dc:title": Object {
172 | "data": "",
173 | "def_data": "",
174 | "element": "dc:title",
175 | },
176 | },
177 | "options": Object {
178 | "type": "docx",
179 | },
180 | "putPageBreak": [Function],
181 | "setDescription": [Function],
182 | "setDocCategory": [Function],
183 | "setDocKeywords": [Function],
184 | "setDocStatus": [Function],
185 | "setDocSubject": [Function],
186 | "setDocTitle": [Function],
187 | "setTheme": [Function],
188 | "startNewDoc": [Function],
189 | "theme": null,
190 | },
191 | "document": Table {
192 | "TABLE_DATA": Array [],
193 | "defaultStyles": Object {
194 | "borders": true,
195 | "tableAlign": "left",
196 | "tableColWidth": 2500,
197 | "tableColor": "black",
198 | "tableSize": 24,
199 | },
200 | "props": Object {
201 | "data": Array [
202 | Array [
203 | "Nitin",
204 | ],
205 | ],
206 | "headers": Array [
207 | Object {
208 | "styles": Object {
209 | "color": "red",
210 | },
211 | "value": "Name",
212 | },
213 | ],
214 | },
215 | "root": [Circular],
216 | },
217 | }
218 | `;
219 |
220 | exports[`should render a table with table style prop 1`] = `
221 | WordDocument {
222 | "doc": officegen {
223 | "_events": Object {
224 | "afterGen": [Function],
225 | "beforeGen": [Function],
226 | "clearData": [Function],
227 | "clearDoc": [Function],
228 | "clearDocType": [Function],
229 | },
230 | "_eventsCount": 5,
231 | "_maxListeners": undefined,
232 | "addPageBreak": [Function],
233 | "addResourceToParse": [Function],
234 | "cbMakeDocxDocument": [Function],
235 | "createByJson": [Function],
236 | "createJson": [Function],
237 | "createListOfDots": [Function],
238 | "createListOfNumbers": [Function],
239 | "createP": [Function],
240 | "createTable": [Function],
241 | "data": Array [],
242 | "domain": null,
243 | "generate": [Function],
244 | "getFooter": [Function],
245 | "getHeader": [Function],
246 | "info": Object {
247 | "cp:category": Object {
248 | "data": "",
249 | "def_data": "",
250 | "element": "cp:category",
251 | },
252 | "cp:contentStatus": Object {
253 | "data": "",
254 | "def_data": "",
255 | "element": "cp:contentStatus",
256 | },
257 | "cp:keywords": Object {
258 | "data": "",
259 | "def_data": "",
260 | "element": "cp:keywords",
261 | },
262 | "dc:description": Object {
263 | "data": "",
264 | "def_data": "",
265 | "element": "dc:description",
266 | },
267 | "dc:subject": Object {
268 | "data": "",
269 | "def_data": "",
270 | "element": "dc:subject",
271 | },
272 | "dc:title": Object {
273 | "data": "",
274 | "def_data": "",
275 | "element": "dc:title",
276 | },
277 | },
278 | "options": Object {
279 | "type": "docx",
280 | },
281 | "putPageBreak": [Function],
282 | "setDescription": [Function],
283 | "setDocCategory": [Function],
284 | "setDocKeywords": [Function],
285 | "setDocStatus": [Function],
286 | "setDocSubject": [Function],
287 | "setDocTitle": [Function],
288 | "setTheme": [Function],
289 | "startNewDoc": [Function],
290 | "theme": null,
291 | },
292 | "document": Table {
293 | "TABLE_DATA": Array [],
294 | "defaultStyles": Object {
295 | "borders": true,
296 | "tableAlign": "left",
297 | "tableColWidth": 2500,
298 | "tableColor": "black",
299 | "tableSize": 24,
300 | },
301 | "props": Object {
302 | "data": Array [
303 | Array [
304 | "iPhone 7",
305 | "128GB",
306 | ],
307 | Array [
308 | "iPhone 5SE",
309 | "64GB",
310 | ],
311 | ],
312 | "headers": Array [
313 | Object {
314 | "styles": Object {
315 | "bold": true,
316 | "color": "red",
317 | "size": 10,
318 | },
319 | "value": "Phone",
320 | },
321 | Object {
322 | "styles": Object {
323 | "bold": true,
324 | "color": "blue",
325 | "size": 10,
326 | },
327 | "value": "Capacity",
328 | },
329 | ],
330 | "style": Object {
331 | "borders": true,
332 | "tableAlign": "center",
333 | "tableColWidth": 4261,
334 | "tableColor": "red",
335 | "tableSize": 24,
336 | },
337 | },
338 | "root": [Circular],
339 | },
340 | }
341 | `;
342 |
--------------------------------------------------------------------------------
/docs/api.md:
--------------------------------------------------------------------------------
1 | # API Reference
2 |
3 | * [render](#renderelement-filepath)
4 | * [Components](#components)
5 | * [Document](#document-)
6 | * [Text](#text-)
7 | * [List](#list-)
8 | * [BulletItem](#bulletitem-)
9 | * [NumberItem](#numberitem--currently-unstable)
10 | * [Header](#header-)
11 | * [Footer](#footer-)
12 | * [Horizontal Line](#hr-)
13 | * [LineBreak](#linebreak-)
14 | * [PageBreak](#pagebreak-)
15 | * [Table](#table-)
16 | * [Image](#image-)
17 | * [Platform](#platform)
18 |
19 |
20 | ## render(element, filepath)
21 |
22 | Renders a React element to word document with a filepath and returns a top-level [document object](https://github.com/nitin42/redocx/blob/master/docs/misc.md).
23 |
24 | ### parameters
25 |
26 | #### `element` (required)
27 |
28 | React element
29 |
30 | #### `filepath` (required)
31 |
32 | filepath for the document
33 |
34 | #### Example
35 |
36 | ```js
37 | const SampleDocument = () => (
38 |
39 | Hello World
40 |
41 | )
42 |
43 | render(, `${__dirname}/example.docx`)
44 | ```
45 |
46 | ### Render the documents to memory mapped stream
47 |
48 | You can also render the documents straight to memory mapped stream. For example -
49 |
50 | ```jsx
51 | import { Component } from 'react'
52 | import { Document, Text } from 'redocx'
53 |
54 | class App extends Component {
55 | render() {
56 | return (
57 |
58 | Hello World
59 |
60 | );
61 | }
62 | }
63 |
64 | render().then((stream) => {
65 | fs.open('sample.docx', 'w+', stream.length, null, (err, fd) => {
66 | if (err) {
67 | console.log(err);
68 | }
69 |
70 | fs.write(fd, stream.toBuffer(), (writeErr) => {
71 | if (writeErr) {
72 | console.log(writeErr);
73 | }
74 | console.log('Docx generated and saved to sample.docx');
75 | });
76 | });
77 | });
78 | ```
79 |
80 | ## Components
81 |
82 | ###
83 |
84 | Wrapper for the child components.
85 |
86 | #### Props
87 |
88 | | Prop | Type | Default | Description |
89 | | ------------- | ------------- | ------------- | ------------- |
90 | | `align` | `string` | `left` | align the child components |
91 | | `children` | `Node` | | |
92 | | `style` | `object` | `{}` | style the child components |
93 | | `info` | `object` | `{}` | information about the document such as author, subject, keywords and description of the document |
94 |
95 | #### Example
96 |
97 | ```js
98 | const DocumentComponent = () => (
99 |
104 | Hello World
105 |
106 | ```
107 |
108 | Data that you can pass into `info` prop -
109 |
110 | ```
111 | {
112 | author: string,
113 | description: string,
114 | keywords: string,
115 | orientation (default is 'portrait'): string,
116 | subject: string,
117 | title: string
118 | }
119 | ```
120 |
121 | ###
122 |
123 | Creates a new paragraph.
124 |
125 | #### Props
126 |
127 | | Prop | Type | Default | Description |
128 | | ------------- | ------------- | ------------- | ------------- |
129 | | `align` | `string` | `left` | align the text |
130 | | `children` | `Node`
131 | | `style` | `object` | `{}` | style the text |
132 |
133 | #### Example
134 |
135 | ```js
136 | const TextComponent = () => (
137 |
138 | Hello World
139 |
140 | )
141 | ```
142 |
143 | ###
144 |
145 | Wrapper for the list items (list of dots and numbers).
146 |
147 | #### Props
148 |
149 | | Prop | Type | Default | Description |
150 | | ------------- | ------------- | ------------- | ------------- |
151 | | `children` | `Node`
152 | | `style` | `object` | `{}` | style for all the list items |
153 |
154 | #### Example
155 |
156 | ```js
157 | const ListComponent = () => (
158 |
159 | Manchester United
160 | Chelsea
161 | Liverpool
162 |
163 | )
164 |
165 | ```
166 |
167 | ###
168 |
169 | Creates a list of dots
170 |
171 | #### Props
172 |
173 | | Prop | Type | Default | Description |
174 | | ------------- | ------------- | ------------- | ------------- |
175 | | `children` | `Node`
176 | | `style` | `object` | `{}` | style for each list item |
177 |
178 | #### Example
179 |
180 | ```js
181 | const ListDots = () => (
182 |
183 | Item one
184 | Item two
185 | Item three
186 |
187 | )
188 | ```
189 |
190 | ### (Currently unstable)
191 |
192 | Creates a list of numbers
193 |
194 | #### Props
195 |
196 | | Prop | Type | Default | Description |
197 | | ------------- | ------------- | ------------- | ------------- |
198 | | `children` | `Node`
199 | | `style` | `object` | `{}` | style for each list item |
200 |
201 | #### Example
202 |
203 | ```js
204 | const ListDots = () => (
205 |
206 | Item one
207 | Item two
208 | Item three
209 |
210 | )
211 | ```
212 |
213 | ###
214 |
215 | Creates a header for the document
216 |
217 | #### Props
218 |
219 | | Prop | Type | Default | Description |
220 | | ------------- | ------------- | ------------- | ------------- |
221 | | `align` | `string` | `left` | align the header
222 | | `children` | `Node`
223 | | `style` | `object` | `{}` | style for header |
224 |
225 | #### Example
226 |
227 | ```js
228 | const HeaderComponent = () => (
229 |
230 | This is a header
231 |
232 | )
233 | ```
234 |
235 | ###
236 |
237 | Creates a footer for the document
238 |
239 | #### Props
240 |
241 | | Prop | Type | Default | Description |
242 | | ------------- | ------------- | ------------- | ------------- |
243 | | `align` | `string` | `left` | align the footer
244 | | `children` | `Node`
245 | | `style` | `object` | `{}` | style for footer |
246 |
247 | #### Example
248 |
249 | ```js
250 | const HeaderComponent = () => (
251 |
254 | )
255 | ```
256 |
257 | ###
258 |
259 | Draws a horizontal line
260 |
261 | #### Example
262 |
263 | ```js
264 | const DrawHr = () =>
265 | ```
266 |
267 | ###
268 |
269 | Puts a line break
270 |
271 | #### Example
272 |
273 | ```js
274 | const LineBr = () =>
275 | ```
276 |
277 | ###
278 |
279 | Puts a page break
280 |
281 | #### Example
282 |
283 | ```js
284 | const PageBr = () =>
285 | ```
286 |
287 | ###
288 |
289 | Creates a table
290 |
291 | #### Props
292 |
293 | | Prop | Type | Default | Description |
294 | | ------------- | ------------- | ------------- | ------------- |
295 | | `headers` | `array` | `[]` | headings and corresponding style for each heading (array of objects where each object has two properties, `value` and `styles`) |
296 | | `data` | `array` | `[]` | data for each heading (array of arrays where each array contains data for each heading) |
297 | | `style` | `object` | `{}` | table styles |
298 |
299 | #### Example
300 |
301 | ```js
302 | const tableStyle = {
303 | tableColWidth: 4261, // Width of each column
304 | tableSize: 24, // Table size
305 | tableColor: 'red', // Content color
306 | tableAlign: 'center', // Align content
307 | borders: true, // Borders
308 | };
309 |
310 | const HEADERS = [
311 | {
312 | value: 'Phone',
313 | styles: {
314 | color: 'red',
315 | bold: true,
316 | size: 10
317 | }
318 | },
319 | {
320 | value: 'Capacity',
321 | styles: {
322 | color: 'blue',
323 | bold: true,
324 | size: 10
325 | }
326 | }
327 | ]
328 |
329 | const DATA = [
330 | ['iPhone 7', '128GB'],
331 | ['iPhone 5SE', '64GB']
332 | ]
333 |
334 | const TableComponent = () => (
335 |
336 | )
337 | ```
338 |
339 | ###
340 |
341 | Adds an image
342 |
343 | #### Props
344 |
345 | | Prop | Type | Default | Description |
346 | | ------------- | ------------- | ------------- | ------------- |
347 | | `src` | `string` | | image source |
348 | | `align` | `string` | `left` | align the image |
349 | | `width` | `number` | | width of the image |
350 | | `height` | `number` | | height of the image |
351 | | `style` | `object` | {} | style attributes of the image (height and image)|
352 |
353 |
354 | #### Example
355 |
356 | ```js
357 | const ImageComponent = () => (
358 |
359 | )
360 | ```
361 |
362 | ### Platform
363 |
364 | A lot of other custom renderers ([react-sketchapp](https://github.com/airbnb/react-sketchapp), [react-tv](https://github.com/raphamorim/react-tv) all have it). It's useful for platform differences within universal components.
365 |
366 | #### Usage
367 |
368 | ```js
369 | import { Platform } from 'redocx'
370 |
371 | Platform.OS // 'word'
372 |
373 | const obj = {
374 | word: { /** some platform specific code that you want to run **/ }
375 | }
376 |
377 | // Then use it like this
378 | Platform.select(obj)
379 | ```
380 |
381 | > It's still experimental and may change in future.
382 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/Image.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`sanity check 1`] = `
4 | WordDocument {
5 | "doc": officegen {
6 | "_events": Object {
7 | "afterGen": [Function],
8 | "beforeGen": [Function],
9 | "clearData": [Function],
10 | "clearDoc": [Function],
11 | "clearDocType": [Function],
12 | },
13 | "_eventsCount": 5,
14 | "_maxListeners": undefined,
15 | "addPageBreak": [Function],
16 | "addResourceToParse": [Function],
17 | "cbMakeDocxDocument": [Function],
18 | "createByJson": [Function],
19 | "createJson": [Function],
20 | "createListOfDots": [Function],
21 | "createListOfNumbers": [Function],
22 | "createP": [Function],
23 | "createTable": [Function],
24 | "data": Array [],
25 | "domain": null,
26 | "generate": [Function],
27 | "getFooter": [Function],
28 | "getHeader": [Function],
29 | "info": Object {
30 | "cp:category": Object {
31 | "data": "",
32 | "def_data": "",
33 | "element": "cp:category",
34 | },
35 | "cp:contentStatus": Object {
36 | "data": "",
37 | "def_data": "",
38 | "element": "cp:contentStatus",
39 | },
40 | "cp:keywords": Object {
41 | "data": "",
42 | "def_data": "",
43 | "element": "cp:keywords",
44 | },
45 | "dc:description": Object {
46 | "data": "",
47 | "def_data": "",
48 | "element": "dc:description",
49 | },
50 | "dc:subject": Object {
51 | "data": "",
52 | "def_data": "",
53 | "element": "dc:subject",
54 | },
55 | "dc:title": Object {
56 | "data": "",
57 | "def_data": "",
58 | "element": "dc:title",
59 | },
60 | },
61 | "options": Object {
62 | "type": "docx",
63 | },
64 | "putPageBreak": [Function],
65 | "setDescription": [Function],
66 | "setDocCategory": [Function],
67 | "setDocKeywords": [Function],
68 | "setDocStatus": [Function],
69 | "setDocSubject": [Function],
70 | "setDocTitle": [Function],
71 | "setTheme": [Function],
72 | "startNewDoc": [Function],
73 | "theme": null,
74 | },
75 | "document": Image {
76 | "children": Array [],
77 | "name": "Image",
78 | "parent": null,
79 | "props": Object {},
80 | "root": [Circular],
81 | },
82 | }
83 | `;
84 |
85 | exports[`should render an image 1`] = `
86 | WordDocument {
87 | "doc": officegen {
88 | "_events": Object {
89 | "afterGen": [Function],
90 | "beforeGen": [Function],
91 | "clearData": [Function],
92 | "clearDoc": [Function],
93 | "clearDocType": [Function],
94 | },
95 | "_eventsCount": 5,
96 | "_maxListeners": undefined,
97 | "addPageBreak": [Function],
98 | "addResourceToParse": [Function],
99 | "cbMakeDocxDocument": [Function],
100 | "createByJson": [Function],
101 | "createJson": [Function],
102 | "createListOfDots": [Function],
103 | "createListOfNumbers": [Function],
104 | "createP": [Function],
105 | "createTable": [Function],
106 | "data": Array [],
107 | "domain": null,
108 | "generate": [Function],
109 | "getFooter": [Function],
110 | "getHeader": [Function],
111 | "info": Object {
112 | "cp:category": Object {
113 | "data": "",
114 | "def_data": "",
115 | "element": "cp:category",
116 | },
117 | "cp:contentStatus": Object {
118 | "data": "",
119 | "def_data": "",
120 | "element": "cp:contentStatus",
121 | },
122 | "cp:keywords": Object {
123 | "data": "",
124 | "def_data": "",
125 | "element": "cp:keywords",
126 | },
127 | "dc:description": Object {
128 | "data": "",
129 | "def_data": "",
130 | "element": "dc:description",
131 | },
132 | "dc:subject": Object {
133 | "data": "",
134 | "def_data": "",
135 | "element": "dc:subject",
136 | },
137 | "dc:title": Object {
138 | "data": "",
139 | "def_data": "",
140 | "element": "dc:title",
141 | },
142 | },
143 | "options": Object {
144 | "type": "docx",
145 | },
146 | "putPageBreak": [Function],
147 | "setDescription": [Function],
148 | "setDocCategory": [Function],
149 | "setDocKeywords": [Function],
150 | "setDocStatus": [Function],
151 | "setDocSubject": [Function],
152 | "setDocTitle": [Function],
153 | "setTheme": [Function],
154 | "startNewDoc": [Function],
155 | "theme": null,
156 | },
157 | "document": Image {
158 | "children": Array [],
159 | "name": "Image",
160 | "parent": null,
161 | "props": Object {
162 | "src": "../src/concr.png",
163 | },
164 | "root": [Circular],
165 | },
166 | }
167 | `;
168 |
169 | exports[`should render an image and adjust it size with style prop 1`] = `
170 | WordDocument {
171 | "doc": officegen {
172 | "_events": Object {
173 | "afterGen": [Function],
174 | "beforeGen": [Function],
175 | "clearData": [Function],
176 | "clearDoc": [Function],
177 | "clearDocType": [Function],
178 | },
179 | "_eventsCount": 5,
180 | "_maxListeners": undefined,
181 | "addPageBreak": [Function],
182 | "addResourceToParse": [Function],
183 | "cbMakeDocxDocument": [Function],
184 | "createByJson": [Function],
185 | "createJson": [Function],
186 | "createListOfDots": [Function],
187 | "createListOfNumbers": [Function],
188 | "createP": [Function],
189 | "createTable": [Function],
190 | "data": Array [],
191 | "domain": null,
192 | "generate": [Function],
193 | "getFooter": [Function],
194 | "getHeader": [Function],
195 | "info": Object {
196 | "cp:category": Object {
197 | "data": "",
198 | "def_data": "",
199 | "element": "cp:category",
200 | },
201 | "cp:contentStatus": Object {
202 | "data": "",
203 | "def_data": "",
204 | "element": "cp:contentStatus",
205 | },
206 | "cp:keywords": Object {
207 | "data": "",
208 | "def_data": "",
209 | "element": "cp:keywords",
210 | },
211 | "dc:description": Object {
212 | "data": "",
213 | "def_data": "",
214 | "element": "dc:description",
215 | },
216 | "dc:subject": Object {
217 | "data": "",
218 | "def_data": "",
219 | "element": "dc:subject",
220 | },
221 | "dc:title": Object {
222 | "data": "",
223 | "def_data": "",
224 | "element": "dc:title",
225 | },
226 | },
227 | "options": Object {
228 | "type": "docx",
229 | },
230 | "putPageBreak": [Function],
231 | "setDescription": [Function],
232 | "setDocCategory": [Function],
233 | "setDocKeywords": [Function],
234 | "setDocStatus": [Function],
235 | "setDocSubject": [Function],
236 | "setDocTitle": [Function],
237 | "setTheme": [Function],
238 | "startNewDoc": [Function],
239 | "theme": null,
240 | },
241 | "document": Image {
242 | "children": Array [],
243 | "name": "Image",
244 | "parent": null,
245 | "props": Object {
246 | "src": "../src/concr.png",
247 | "style": Object {
248 | "height": "400",
249 | "width": "400",
250 | },
251 | },
252 | "root": [Circular],
253 | },
254 | }
255 | `;
256 |
257 | exports[`should render an image and adjust it size with width and height prop 1`] = `
258 | WordDocument {
259 | "doc": officegen {
260 | "_events": Object {
261 | "afterGen": [Function],
262 | "beforeGen": [Function],
263 | "clearData": [Function],
264 | "clearDoc": [Function],
265 | "clearDocType": [Function],
266 | },
267 | "_eventsCount": 5,
268 | "_maxListeners": undefined,
269 | "addPageBreak": [Function],
270 | "addResourceToParse": [Function],
271 | "cbMakeDocxDocument": [Function],
272 | "createByJson": [Function],
273 | "createJson": [Function],
274 | "createListOfDots": [Function],
275 | "createListOfNumbers": [Function],
276 | "createP": [Function],
277 | "createTable": [Function],
278 | "data": Array [],
279 | "domain": null,
280 | "generate": [Function],
281 | "getFooter": [Function],
282 | "getHeader": [Function],
283 | "info": Object {
284 | "cp:category": Object {
285 | "data": "",
286 | "def_data": "",
287 | "element": "cp:category",
288 | },
289 | "cp:contentStatus": Object {
290 | "data": "",
291 | "def_data": "",
292 | "element": "cp:contentStatus",
293 | },
294 | "cp:keywords": Object {
295 | "data": "",
296 | "def_data": "",
297 | "element": "cp:keywords",
298 | },
299 | "dc:description": Object {
300 | "data": "",
301 | "def_data": "",
302 | "element": "dc:description",
303 | },
304 | "dc:subject": Object {
305 | "data": "",
306 | "def_data": "",
307 | "element": "dc:subject",
308 | },
309 | "dc:title": Object {
310 | "data": "",
311 | "def_data": "",
312 | "element": "dc:title",
313 | },
314 | },
315 | "options": Object {
316 | "type": "docx",
317 | },
318 | "putPageBreak": [Function],
319 | "setDescription": [Function],
320 | "setDocCategory": [Function],
321 | "setDocKeywords": [Function],
322 | "setDocStatus": [Function],
323 | "setDocSubject": [Function],
324 | "setDocTitle": [Function],
325 | "setTheme": [Function],
326 | "startNewDoc": [Function],
327 | "theme": null,
328 | },
329 | "document": Image {
330 | "children": Array [],
331 | "name": "Image",
332 | "parent": null,
333 | "props": Object {
334 | "height": "400",
335 | "src": "../src/concr.png",
336 | "width": "400",
337 | },
338 | "root": [Circular],
339 | },
340 | }
341 | `;
342 |
343 | exports[`should render an image and align it 1`] = `
344 | WordDocument {
345 | "doc": officegen {
346 | "_events": Object {
347 | "afterGen": [Function],
348 | "beforeGen": [Function],
349 | "clearData": [Function],
350 | "clearDoc": [Function],
351 | "clearDocType": [Function],
352 | },
353 | "_eventsCount": 5,
354 | "_maxListeners": undefined,
355 | "addPageBreak": [Function],
356 | "addResourceToParse": [Function],
357 | "cbMakeDocxDocument": [Function],
358 | "createByJson": [Function],
359 | "createJson": [Function],
360 | "createListOfDots": [Function],
361 | "createListOfNumbers": [Function],
362 | "createP": [Function],
363 | "createTable": [Function],
364 | "data": Array [],
365 | "domain": null,
366 | "generate": [Function],
367 | "getFooter": [Function],
368 | "getHeader": [Function],
369 | "info": Object {
370 | "cp:category": Object {
371 | "data": "",
372 | "def_data": "",
373 | "element": "cp:category",
374 | },
375 | "cp:contentStatus": Object {
376 | "data": "",
377 | "def_data": "",
378 | "element": "cp:contentStatus",
379 | },
380 | "cp:keywords": Object {
381 | "data": "",
382 | "def_data": "",
383 | "element": "cp:keywords",
384 | },
385 | "dc:description": Object {
386 | "data": "",
387 | "def_data": "",
388 | "element": "dc:description",
389 | },
390 | "dc:subject": Object {
391 | "data": "",
392 | "def_data": "",
393 | "element": "dc:subject",
394 | },
395 | "dc:title": Object {
396 | "data": "",
397 | "def_data": "",
398 | "element": "dc:title",
399 | },
400 | },
401 | "options": Object {
402 | "type": "docx",
403 | },
404 | "putPageBreak": [Function],
405 | "setDescription": [Function],
406 | "setDocCategory": [Function],
407 | "setDocKeywords": [Function],
408 | "setDocStatus": [Function],
409 | "setDocSubject": [Function],
410 | "setDocTitle": [Function],
411 | "setTheme": [Function],
412 | "startNewDoc": [Function],
413 | "theme": null,
414 | },
415 | "document": Image {
416 | "children": Array [],
417 | "name": "Image",
418 | "parent": null,
419 | "props": Object {
420 | "align": "justify",
421 | "src": "../src/concr.png",
422 | },
423 | "root": [Circular],
424 | },
425 | }
426 | `;
427 |
--------------------------------------------------------------------------------
/__tests__/__snapshots__/LineBreak.test.js.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`should add a line break 1`] = `
4 | WordDocument {
5 | "doc": officegen {
6 | "_events": Object {
7 | "afterGen": [Function],
8 | "beforeGen": [Function],
9 | "clearData": [Function],
10 | "clearDoc": [Function],
11 | "clearDocType": [Function],
12 | },
13 | "_eventsCount": 5,
14 | "_maxListeners": undefined,
15 | "addPageBreak": [Function],
16 | "addResourceToParse": [Function],
17 | "cbMakeDocxDocument": [Function],
18 | "createByJson": [Function],
19 | "createJson": [Function],
20 | "createListOfDots": [Function],
21 | "createListOfNumbers": [Function],
22 | "createP": [Function],
23 | "createTable": [Function],
24 | "data": Array [],
25 | "domain": null,
26 | "generate": [Function],
27 | "getFooter": [Function],
28 | "getHeader": [Function],
29 | "info": Object {
30 | "cp:category": Object {
31 | "data": "",
32 | "def_data": "",
33 | "element": "cp:category",
34 | },
35 | "cp:contentStatus": Object {
36 | "data": "",
37 | "def_data": "",
38 | "element": "cp:contentStatus",
39 | },
40 | "cp:keywords": Object {
41 | "data": "",
42 | "def_data": "",
43 | "element": "cp:keywords",
44 | },
45 | "dc:description": Object {
46 | "data": "",
47 | "def_data": "",
48 | "element": "dc:description",
49 | },
50 | "dc:subject": Object {
51 | "data": "",
52 | "def_data": "",
53 | "element": "dc:subject",
54 | },
55 | "dc:title": Object {
56 | "data": "",
57 | "def_data": "",
58 | "element": "dc:title",
59 | },
60 | },
61 | "options": Object {
62 | "type": "docx",
63 | },
64 | "putPageBreak": [Function],
65 | "setDescription": [Function],
66 | "setDocCategory": [Function],
67 | "setDocKeywords": [Function],
68 | "setDocStatus": [Function],
69 | "setDocSubject": [Function],
70 | "setDocTitle": [Function],
71 | "setTheme": [Function],
72 | "startNewDoc": [Function],
73 | "theme": null,
74 | },
75 | "document": LineBreak {
76 | "name": "LineBreak",
77 | "prop": Object {},
78 | "root": [Circular],
79 | },
80 | }
81 | `;
82 |
83 | exports[`should add a line break when called inside a Text component 1`] = `
84 | WordDocument {
85 | "doc": officegen {
86 | "_events": Object {
87 | "afterGen": [Function],
88 | "beforeGen": [Function],
89 | "clearData": [Function],
90 | "clearDoc": [Function],
91 | "clearDocType": [Function],
92 | },
93 | "_eventsCount": 5,
94 | "_maxListeners": undefined,
95 | "addPageBreak": [Function],
96 | "addResourceToParse": [Function],
97 | "cbMakeDocxDocument": [Function],
98 | "createByJson": [Function],
99 | "createJson": [Function],
100 | "createListOfDots": [Function],
101 | "createListOfNumbers": [Function],
102 | "createP": [Function],
103 | "createTable": [Function],
104 | "data": Array [
105 | MakeDocxP {
106 | "data": Array [],
107 | "docType": "docx",
108 | "extraSettings": Object {},
109 | "filesList": Array [
110 | Object {
111 | "clear": "type",
112 | "ext": "rels",
113 | "type": "application/vnd.openxmlformats-package.relationships+xml",
114 | },
115 | Object {
116 | "clear": "type",
117 | "ext": "xml",
118 | "type": "application/xml",
119 | },
120 | Object {
121 | "clear": "type",
122 | "ext": "jpeg",
123 | "type": "image/jpeg",
124 | },
125 | Object {
126 | "clear": "type",
127 | "ext": "png",
128 | "type": "image/png",
129 | },
130 | Object {
131 | "clear": "type",
132 | "ext": "gif",
133 | "type": "image/gif",
134 | },
135 | Object {
136 | "clear": "type",
137 | "name": "/docProps/app.xml",
138 | "type": "application/vnd.openxmlformats-officedocument.extended-properties+xml",
139 | },
140 | Object {
141 | "clear": "type",
142 | "name": "/word/theme/theme1.xml",
143 | "type": "application/vnd.openxmlformats-officedocument.theme+xml",
144 | },
145 | Object {
146 | "clear": "type",
147 | "name": "/docProps/core.xml",
148 | "type": "application/vnd.openxmlformats-package.core-properties+xml",
149 | },
150 | Object {
151 | "clear": "type",
152 | "name": "/word/settings.xml",
153 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
154 | },
155 | Object {
156 | "clear": "type",
157 | "name": "/word/fontTable.xml",
158 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml",
159 | },
160 | Object {
161 | "clear": "type",
162 | "name": "/word/webSettings.xml",
163 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
164 | },
165 | Object {
166 | "clear": "type",
167 | "name": "/word/styles.xml",
168 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
169 | },
170 | Object {
171 | "clear": "type",
172 | "name": "/word/document.xml",
173 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
174 | },
175 | Object {
176 | "clear": "type",
177 | "name": "/word/numbering.xml",
178 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
179 | },
180 | ],
181 | "genPrivate": Object {
182 | "features": Object {
183 | "outputType": "zip",
184 | "type": Object {
185 | "docx": MakeDocPluginapi {
186 | "callbacksList": Object {
187 | "beforeGen": Array [
188 | [Function],
189 | ],
190 | "makeDocApi": Array [
191 | [Function],
192 | ],
193 | },
194 | "defValuesFunc": [Function],
195 | "docType": "docx",
196 | "genPrivate": [Circular],
197 | "genobj": [Circular],
198 | "ogPluginsApi": Object {
199 | "intAddAnyResourceToParse": [Function],
200 | "type": Object {
201 | "msoffice": Object {
202 | "addInfoType": [Function],
203 | "cbMakeMsOfficeBasicXml": [Function],
204 | "cbMakeRels": [Function],
205 | "makeOfficeGenerator": [Function],
206 | "makeUniqueID": [Function],
207 | },
208 | },
209 | },
210 | "plugsList": Array [
211 | MakeHeadfootPlugin {
212 | "docxData": Object {},
213 | "filesList": Array [
214 | Object {
215 | "clear": "type",
216 | "ext": "rels",
217 | "type": "application/vnd.openxmlformats-package.relationships+xml",
218 | },
219 | Object {
220 | "clear": "type",
221 | "ext": "xml",
222 | "type": "application/xml",
223 | },
224 | Object {
225 | "clear": "type",
226 | "ext": "jpeg",
227 | "type": "image/jpeg",
228 | },
229 | Object {
230 | "clear": "type",
231 | "ext": "png",
232 | "type": "image/png",
233 | },
234 | Object {
235 | "clear": "type",
236 | "ext": "gif",
237 | "type": "image/gif",
238 | },
239 | Object {
240 | "clear": "type",
241 | "name": "/docProps/app.xml",
242 | "type": "application/vnd.openxmlformats-officedocument.extended-properties+xml",
243 | },
244 | Object {
245 | "clear": "type",
246 | "name": "/word/theme/theme1.xml",
247 | "type": "application/vnd.openxmlformats-officedocument.theme+xml",
248 | },
249 | Object {
250 | "clear": "type",
251 | "name": "/docProps/core.xml",
252 | "type": "application/vnd.openxmlformats-package.core-properties+xml",
253 | },
254 | Object {
255 | "clear": "type",
256 | "name": "/word/settings.xml",
257 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
258 | },
259 | Object {
260 | "clear": "type",
261 | "name": "/word/fontTable.xml",
262 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml",
263 | },
264 | Object {
265 | "clear": "type",
266 | "name": "/word/webSettings.xml",
267 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
268 | },
269 | Object {
270 | "clear": "type",
271 | "name": "/word/styles.xml",
272 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
273 | },
274 | Object {
275 | "clear": "type",
276 | "name": "/word/document.xml",
277 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
278 | },
279 | Object {
280 | "clear": "type",
281 | "name": "/word/numbering.xml",
282 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
283 | },
284 | ],
285 | "mainPath": "word",
286 | "mainPathFile": "document",
287 | "msPluginsApi": Object {
288 | "addInfoType": [Function],
289 | "cbMakeMsOfficeBasicXml": [Function],
290 | "cbMakeRels": [Function],
291 | "makeOfficeGenerator": [Function],
292 | "makeUniqueID": [Function],
293 | },
294 | "ogPluginsApi": Object {
295 | "intAddAnyResourceToParse": [Function],
296 | "type": Object {
297 | "msoffice": Object {
298 | "addInfoType": [Function],
299 | "cbMakeMsOfficeBasicXml": [Function],
300 | "cbMakeRels": [Function],
301 | "makeOfficeGenerator": [Function],
302 | "makeUniqueID": [Function],
303 | },
304 | },
305 | },
306 | "pluginsman": [Circular],
307 | "relsApp": Array [
308 | Object {
309 | "clear": "type",
310 | "target": "styles.xml",
311 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
312 | },
313 | Object {
314 | "clear": "type",
315 | "target": "settings.xml",
316 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
317 | },
318 | Object {
319 | "clear": "type",
320 | "target": "webSettings.xml",
321 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",
322 | },
323 | Object {
324 | "clear": "type",
325 | "target": "fontTable.xml",
326 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
327 | },
328 | Object {
329 | "clear": "type",
330 | "target": "theme/theme1.xml",
331 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
332 | },
333 | Object {
334 | "clear": "type",
335 | "target": "numbering.xml",
336 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
337 | },
338 | ],
339 | "relsMain": Array [
340 | Object {
341 | "clear": "type",
342 | "target": "docProps/app.xml",
343 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
344 | },
345 | Object {
346 | "clear": "type",
347 | "target": "docProps/core.xml",
348 | "type": "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
349 | },
350 | Object {
351 | "clear": "type",
352 | "target": "word/document.xml",
353 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
354 | },
355 | ],
356 | "srcFilesList": Array [],
357 | },
358 | ],
359 | },
360 | "msoffice": Object {
361 | "main_path": "word",
362 | "main_path_file": "document",
363 | },
364 | },
365 | },
366 | "length": 0,
367 | "pages": Array [],
368 | "plugs": Object {
369 | "intAddAnyResourceToParse": [Function],
370 | "type": Object {
371 | "msoffice": Object {
372 | "addInfoType": [Function],
373 | "cbMakeMsOfficeBasicXml": [Function],
374 | "cbMakeRels": [Function],
375 | "makeOfficeGenerator": [Function],
376 | "makeUniqueID": [Function],
377 | },
378 | },
379 | },
380 | "resources": Array [
381 | Object {
382 | "callback": [Function],
383 | "data": Array [
384 | Object {
385 | "clear": "type",
386 | "target": "docProps/app.xml",
387 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
388 | },
389 | Object {
390 | "clear": "type",
391 | "target": "docProps/core.xml",
392 | "type": "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
393 | },
394 | Object {
395 | "clear": "type",
396 | "target": "word/document.xml",
397 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
398 | },
399 | ],
400 | "is_perment": true,
401 | "name": "_rels\\\\.rels",
402 | "removed_after_used": false,
403 | "type": "buffer",
404 | },
405 | Object {
406 | "callback": [Function],
407 | "data": null,
408 | "is_perment": true,
409 | "name": "[Content_Types].xml",
410 | "removed_after_used": false,
411 | "type": "buffer",
412 | },
413 | Object {
414 | "callback": [Function],
415 | "data": null,
416 | "is_perment": true,
417 | "name": "docProps\\\\core.xml",
418 | "removed_after_used": false,
419 | "type": "buffer",
420 | },
421 | Object {
422 | "callback": [Function],
423 | "data": null,
424 | "is_perment": true,
425 | "name": "word\\\\theme\\\\theme1.xml",
426 | "removed_after_used": false,
427 | "type": "buffer",
428 | },
429 | Object {
430 | "callback": [Function],
431 | "data": null,
432 | "is_perment": true,
433 | "name": "docProps\\\\app.xml",
434 | "removed_after_used": false,
435 | "type": "buffer",
436 | },
437 | Object {
438 | "callback": [Function],
439 | "data": null,
440 | "is_perment": true,
441 | "name": "word\\\\fontTable.xml",
442 | "removed_after_used": false,
443 | "type": "buffer",
444 | },
445 | Object {
446 | "callback": [Function],
447 | "data": null,
448 | "is_perment": true,
449 | "name": "word\\\\settings.xml",
450 | "removed_after_used": false,
451 | "type": "buffer",
452 | },
453 | Object {
454 | "callback": [Function],
455 | "data": null,
456 | "is_perment": true,
457 | "name": "word\\\\webSettings.xml",
458 | "removed_after_used": false,
459 | "type": "buffer",
460 | },
461 | Object {
462 | "callback": [Function],
463 | "data": null,
464 | "is_perment": true,
465 | "name": "word\\\\styles.xml",
466 | "removed_after_used": false,
467 | "type": "buffer",
468 | },
469 | Object {
470 | "callback": [Function],
471 | "data": Object {
472 | "data": [Circular],
473 | "docEndExtra": "",
474 | "docStartExtra": "",
475 | "docType": "document",
476 | },
477 | "is_perment": true,
478 | "name": "word\\\\document.xml",
479 | "removed_after_used": false,
480 | "type": "buffer",
481 | },
482 | Object {
483 | "callback": [Function],
484 | "data": null,
485 | "is_perment": true,
486 | "name": "word\\\\numbering.xml",
487 | "removed_after_used": false,
488 | "type": "buffer",
489 | },
490 | Object {
491 | "callback": [Function],
492 | "data": Array [
493 | Object {
494 | "clear": "type",
495 | "target": "styles.xml",
496 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
497 | },
498 | Object {
499 | "clear": "type",
500 | "target": "settings.xml",
501 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
502 | },
503 | Object {
504 | "clear": "type",
505 | "target": "webSettings.xml",
506 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",
507 | },
508 | Object {
509 | "clear": "type",
510 | "target": "fontTable.xml",
511 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
512 | },
513 | Object {
514 | "clear": "type",
515 | "target": "theme/theme1.xml",
516 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
517 | },
518 | Object {
519 | "clear": "type",
520 | "target": "numbering.xml",
521 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
522 | },
523 | ],
524 | "is_perment": true,
525 | "name": "word\\\\_rels\\\\document.xml.rels",
526 | "removed_after_used": false,
527 | "type": "buffer",
528 | },
529 | ],
530 | "type": Object {
531 | "docx": Object {},
532 | "msoffice": Object {
533 | "files_list": Array [
534 | Object {
535 | "clear": "type",
536 | "ext": "rels",
537 | "type": "application/vnd.openxmlformats-package.relationships+xml",
538 | },
539 | Object {
540 | "clear": "type",
541 | "ext": "xml",
542 | "type": "application/xml",
543 | },
544 | Object {
545 | "clear": "type",
546 | "ext": "jpeg",
547 | "type": "image/jpeg",
548 | },
549 | Object {
550 | "clear": "type",
551 | "ext": "png",
552 | "type": "image/png",
553 | },
554 | Object {
555 | "clear": "type",
556 | "ext": "gif",
557 | "type": "image/gif",
558 | },
559 | Object {
560 | "clear": "type",
561 | "name": "/docProps/app.xml",
562 | "type": "application/vnd.openxmlformats-officedocument.extended-properties+xml",
563 | },
564 | Object {
565 | "clear": "type",
566 | "name": "/word/theme/theme1.xml",
567 | "type": "application/vnd.openxmlformats-officedocument.theme+xml",
568 | },
569 | Object {
570 | "clear": "type",
571 | "name": "/docProps/core.xml",
572 | "type": "application/vnd.openxmlformats-package.core-properties+xml",
573 | },
574 | Object {
575 | "clear": "type",
576 | "name": "/word/settings.xml",
577 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
578 | },
579 | Object {
580 | "clear": "type",
581 | "name": "/word/fontTable.xml",
582 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml",
583 | },
584 | Object {
585 | "clear": "type",
586 | "name": "/word/webSettings.xml",
587 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
588 | },
589 | Object {
590 | "clear": "type",
591 | "name": "/word/styles.xml",
592 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
593 | },
594 | Object {
595 | "clear": "type",
596 | "name": "/word/document.xml",
597 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
598 | },
599 | Object {
600 | "clear": "type",
601 | "name": "/word/numbering.xml",
602 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
603 | },
604 | ],
605 | "rels_app": Array [
606 | Object {
607 | "clear": "type",
608 | "target": "styles.xml",
609 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
610 | },
611 | Object {
612 | "clear": "type",
613 | "target": "settings.xml",
614 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
615 | },
616 | Object {
617 | "clear": "type",
618 | "target": "webSettings.xml",
619 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",
620 | },
621 | Object {
622 | "clear": "type",
623 | "target": "fontTable.xml",
624 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
625 | },
626 | Object {
627 | "clear": "type",
628 | "target": "theme/theme1.xml",
629 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
630 | },
631 | Object {
632 | "clear": "type",
633 | "target": "numbering.xml",
634 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
635 | },
636 | ],
637 | "rels_main": Array [
638 | Object {
639 | "clear": "type",
640 | "target": "docProps/app.xml",
641 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
642 | },
643 | Object {
644 | "clear": "type",
645 | "target": "docProps/core.xml",
646 | "type": "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
647 | },
648 | Object {
649 | "clear": "type",
650 | "target": "word/document.xml",
651 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
652 | },
653 | ],
654 | "src_files_list": Array [],
655 | },
656 | },
657 | },
658 | "genobj": [Circular],
659 | "mainPath": "word",
660 | "mainPathFile": "document",
661 | "msPluginsApi": Object {
662 | "addInfoType": [Function],
663 | "cbMakeMsOfficeBasicXml": [Function],
664 | "cbMakeRels": [Function],
665 | "makeOfficeGenerator": [Function],
666 | "makeUniqueID": [Function],
667 | },
668 | "ogPluginsApi": Object {
669 | "intAddAnyResourceToParse": [Function],
670 | "type": Object {
671 | "msoffice": Object {
672 | "addInfoType": [Function],
673 | "cbMakeMsOfficeBasicXml": [Function],
674 | "cbMakeRels": [Function],
675 | "makeOfficeGenerator": [Function],
676 | "makeUniqueID": [Function],
677 | },
678 | },
679 | },
680 | "options": Object {},
681 | "relsApp": Array [
682 | Object {
683 | "clear": "type",
684 | "target": "styles.xml",
685 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
686 | },
687 | Object {
688 | "clear": "type",
689 | "target": "settings.xml",
690 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
691 | },
692 | Object {
693 | "clear": "type",
694 | "target": "webSettings.xml",
695 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",
696 | },
697 | Object {
698 | "clear": "type",
699 | "target": "fontTable.xml",
700 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
701 | },
702 | Object {
703 | "clear": "type",
704 | "target": "theme/theme1.xml",
705 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
706 | },
707 | Object {
708 | "clear": "type",
709 | "target": "numbering.xml",
710 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
711 | },
712 | ],
713 | "relsMain": Array [
714 | Object {
715 | "clear": "type",
716 | "target": "docProps/app.xml",
717 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
718 | },
719 | Object {
720 | "clear": "type",
721 | "target": "docProps/core.xml",
722 | "type": "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
723 | },
724 | Object {
725 | "clear": "type",
726 | "target": "word/document.xml",
727 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
728 | },
729 | ],
730 | "srcFilesList": Array [],
731 | },
732 | ],
733 | "domain": null,
734 | "generate": [Function],
735 | "getFooter": [Function],
736 | "getHeader": [Function],
737 | "info": Object {
738 | "cp:category": Object {
739 | "data": "",
740 | "def_data": "",
741 | "element": "cp:category",
742 | },
743 | "cp:contentStatus": Object {
744 | "data": "",
745 | "def_data": "",
746 | "element": "cp:contentStatus",
747 | },
748 | "cp:keywords": Object {
749 | "data": "",
750 | "def_data": "",
751 | "element": "cp:keywords",
752 | },
753 | "dc:description": Object {
754 | "data": "",
755 | "def_data": "",
756 | "element": "dc:description",
757 | },
758 | "dc:subject": Object {
759 | "data": "",
760 | "def_data": "",
761 | "element": "dc:subject",
762 | },
763 | "dc:title": Object {
764 | "data": "",
765 | "def_data": "",
766 | "element": "dc:title",
767 | },
768 | },
769 | "options": Object {
770 | "type": "docx",
771 | },
772 | "putPageBreak": [Function],
773 | "setDescription": [Function],
774 | "setDocCategory": [Function],
775 | "setDocKeywords": [Function],
776 | "setDocStatus": [Function],
777 | "setDocSubject": [Function],
778 | "setDocTitle": [Function],
779 | "setTheme": [Function],
780 | "startNewDoc": [Function],
781 | "theme": null,
782 | },
783 | "document": Text {
784 | "adder": MakeDocxP {
785 | "data": Array [],
786 | "docType": "docx",
787 | "extraSettings": Object {},
788 | "filesList": Array [
789 | Object {
790 | "clear": "type",
791 | "ext": "rels",
792 | "type": "application/vnd.openxmlformats-package.relationships+xml",
793 | },
794 | Object {
795 | "clear": "type",
796 | "ext": "xml",
797 | "type": "application/xml",
798 | },
799 | Object {
800 | "clear": "type",
801 | "ext": "jpeg",
802 | "type": "image/jpeg",
803 | },
804 | Object {
805 | "clear": "type",
806 | "ext": "png",
807 | "type": "image/png",
808 | },
809 | Object {
810 | "clear": "type",
811 | "ext": "gif",
812 | "type": "image/gif",
813 | },
814 | Object {
815 | "clear": "type",
816 | "name": "/docProps/app.xml",
817 | "type": "application/vnd.openxmlformats-officedocument.extended-properties+xml",
818 | },
819 | Object {
820 | "clear": "type",
821 | "name": "/word/theme/theme1.xml",
822 | "type": "application/vnd.openxmlformats-officedocument.theme+xml",
823 | },
824 | Object {
825 | "clear": "type",
826 | "name": "/docProps/core.xml",
827 | "type": "application/vnd.openxmlformats-package.core-properties+xml",
828 | },
829 | Object {
830 | "clear": "type",
831 | "name": "/word/settings.xml",
832 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
833 | },
834 | Object {
835 | "clear": "type",
836 | "name": "/word/fontTable.xml",
837 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml",
838 | },
839 | Object {
840 | "clear": "type",
841 | "name": "/word/webSettings.xml",
842 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
843 | },
844 | Object {
845 | "clear": "type",
846 | "name": "/word/styles.xml",
847 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
848 | },
849 | Object {
850 | "clear": "type",
851 | "name": "/word/document.xml",
852 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
853 | },
854 | Object {
855 | "clear": "type",
856 | "name": "/word/numbering.xml",
857 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
858 | },
859 | ],
860 | "genPrivate": Object {
861 | "features": Object {
862 | "outputType": "zip",
863 | "type": Object {
864 | "docx": MakeDocPluginapi {
865 | "callbacksList": Object {
866 | "beforeGen": Array [
867 | [Function],
868 | ],
869 | "makeDocApi": Array [
870 | [Function],
871 | ],
872 | },
873 | "defValuesFunc": [Function],
874 | "docType": "docx",
875 | "genPrivate": [Circular],
876 | "genobj": officegen {
877 | "_events": Object {
878 | "afterGen": [Function],
879 | "beforeGen": [Function],
880 | "clearData": [Function],
881 | "clearDoc": [Function],
882 | "clearDocType": [Function],
883 | },
884 | "_eventsCount": 5,
885 | "_maxListeners": undefined,
886 | "addPageBreak": [Function],
887 | "addResourceToParse": [Function],
888 | "cbMakeDocxDocument": [Function],
889 | "createByJson": [Function],
890 | "createJson": [Function],
891 | "createListOfDots": [Function],
892 | "createListOfNumbers": [Function],
893 | "createP": [Function],
894 | "createTable": [Function],
895 | "data": Array [
896 | [Circular],
897 | ],
898 | "domain": null,
899 | "generate": [Function],
900 | "getFooter": [Function],
901 | "getHeader": [Function],
902 | "info": Object {
903 | "cp:category": Object {
904 | "data": "",
905 | "def_data": "",
906 | "element": "cp:category",
907 | },
908 | "cp:contentStatus": Object {
909 | "data": "",
910 | "def_data": "",
911 | "element": "cp:contentStatus",
912 | },
913 | "cp:keywords": Object {
914 | "data": "",
915 | "def_data": "",
916 | "element": "cp:keywords",
917 | },
918 | "dc:description": Object {
919 | "data": "",
920 | "def_data": "",
921 | "element": "dc:description",
922 | },
923 | "dc:subject": Object {
924 | "data": "",
925 | "def_data": "",
926 | "element": "dc:subject",
927 | },
928 | "dc:title": Object {
929 | "data": "",
930 | "def_data": "",
931 | "element": "dc:title",
932 | },
933 | },
934 | "options": Object {
935 | "type": "docx",
936 | },
937 | "putPageBreak": [Function],
938 | "setDescription": [Function],
939 | "setDocCategory": [Function],
940 | "setDocKeywords": [Function],
941 | "setDocStatus": [Function],
942 | "setDocSubject": [Function],
943 | "setDocTitle": [Function],
944 | "setTheme": [Function],
945 | "startNewDoc": [Function],
946 | "theme": null,
947 | },
948 | "ogPluginsApi": Object {
949 | "intAddAnyResourceToParse": [Function],
950 | "type": Object {
951 | "msoffice": Object {
952 | "addInfoType": [Function],
953 | "cbMakeMsOfficeBasicXml": [Function],
954 | "cbMakeRels": [Function],
955 | "makeOfficeGenerator": [Function],
956 | "makeUniqueID": [Function],
957 | },
958 | },
959 | },
960 | "plugsList": Array [
961 | MakeHeadfootPlugin {
962 | "docxData": Object {},
963 | "filesList": Array [
964 | Object {
965 | "clear": "type",
966 | "ext": "rels",
967 | "type": "application/vnd.openxmlformats-package.relationships+xml",
968 | },
969 | Object {
970 | "clear": "type",
971 | "ext": "xml",
972 | "type": "application/xml",
973 | },
974 | Object {
975 | "clear": "type",
976 | "ext": "jpeg",
977 | "type": "image/jpeg",
978 | },
979 | Object {
980 | "clear": "type",
981 | "ext": "png",
982 | "type": "image/png",
983 | },
984 | Object {
985 | "clear": "type",
986 | "ext": "gif",
987 | "type": "image/gif",
988 | },
989 | Object {
990 | "clear": "type",
991 | "name": "/docProps/app.xml",
992 | "type": "application/vnd.openxmlformats-officedocument.extended-properties+xml",
993 | },
994 | Object {
995 | "clear": "type",
996 | "name": "/word/theme/theme1.xml",
997 | "type": "application/vnd.openxmlformats-officedocument.theme+xml",
998 | },
999 | Object {
1000 | "clear": "type",
1001 | "name": "/docProps/core.xml",
1002 | "type": "application/vnd.openxmlformats-package.core-properties+xml",
1003 | },
1004 | Object {
1005 | "clear": "type",
1006 | "name": "/word/settings.xml",
1007 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
1008 | },
1009 | Object {
1010 | "clear": "type",
1011 | "name": "/word/fontTable.xml",
1012 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml",
1013 | },
1014 | Object {
1015 | "clear": "type",
1016 | "name": "/word/webSettings.xml",
1017 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
1018 | },
1019 | Object {
1020 | "clear": "type",
1021 | "name": "/word/styles.xml",
1022 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
1023 | },
1024 | Object {
1025 | "clear": "type",
1026 | "name": "/word/document.xml",
1027 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
1028 | },
1029 | Object {
1030 | "clear": "type",
1031 | "name": "/word/numbering.xml",
1032 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
1033 | },
1034 | ],
1035 | "mainPath": "word",
1036 | "mainPathFile": "document",
1037 | "msPluginsApi": Object {
1038 | "addInfoType": [Function],
1039 | "cbMakeMsOfficeBasicXml": [Function],
1040 | "cbMakeRels": [Function],
1041 | "makeOfficeGenerator": [Function],
1042 | "makeUniqueID": [Function],
1043 | },
1044 | "ogPluginsApi": Object {
1045 | "intAddAnyResourceToParse": [Function],
1046 | "type": Object {
1047 | "msoffice": Object {
1048 | "addInfoType": [Function],
1049 | "cbMakeMsOfficeBasicXml": [Function],
1050 | "cbMakeRels": [Function],
1051 | "makeOfficeGenerator": [Function],
1052 | "makeUniqueID": [Function],
1053 | },
1054 | },
1055 | },
1056 | "pluginsman": [Circular],
1057 | "relsApp": Array [
1058 | Object {
1059 | "clear": "type",
1060 | "target": "styles.xml",
1061 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
1062 | },
1063 | Object {
1064 | "clear": "type",
1065 | "target": "settings.xml",
1066 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
1067 | },
1068 | Object {
1069 | "clear": "type",
1070 | "target": "webSettings.xml",
1071 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",
1072 | },
1073 | Object {
1074 | "clear": "type",
1075 | "target": "fontTable.xml",
1076 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
1077 | },
1078 | Object {
1079 | "clear": "type",
1080 | "target": "theme/theme1.xml",
1081 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
1082 | },
1083 | Object {
1084 | "clear": "type",
1085 | "target": "numbering.xml",
1086 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
1087 | },
1088 | ],
1089 | "relsMain": Array [
1090 | Object {
1091 | "clear": "type",
1092 | "target": "docProps/app.xml",
1093 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
1094 | },
1095 | Object {
1096 | "clear": "type",
1097 | "target": "docProps/core.xml",
1098 | "type": "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
1099 | },
1100 | Object {
1101 | "clear": "type",
1102 | "target": "word/document.xml",
1103 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
1104 | },
1105 | ],
1106 | "srcFilesList": Array [],
1107 | },
1108 | ],
1109 | },
1110 | "msoffice": Object {
1111 | "main_path": "word",
1112 | "main_path_file": "document",
1113 | },
1114 | },
1115 | },
1116 | "length": 0,
1117 | "pages": Array [],
1118 | "plugs": Object {
1119 | "intAddAnyResourceToParse": [Function],
1120 | "type": Object {
1121 | "msoffice": Object {
1122 | "addInfoType": [Function],
1123 | "cbMakeMsOfficeBasicXml": [Function],
1124 | "cbMakeRels": [Function],
1125 | "makeOfficeGenerator": [Function],
1126 | "makeUniqueID": [Function],
1127 | },
1128 | },
1129 | },
1130 | "resources": Array [
1131 | Object {
1132 | "callback": [Function],
1133 | "data": Array [
1134 | Object {
1135 | "clear": "type",
1136 | "target": "docProps/app.xml",
1137 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
1138 | },
1139 | Object {
1140 | "clear": "type",
1141 | "target": "docProps/core.xml",
1142 | "type": "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
1143 | },
1144 | Object {
1145 | "clear": "type",
1146 | "target": "word/document.xml",
1147 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
1148 | },
1149 | ],
1150 | "is_perment": true,
1151 | "name": "_rels\\\\.rels",
1152 | "removed_after_used": false,
1153 | "type": "buffer",
1154 | },
1155 | Object {
1156 | "callback": [Function],
1157 | "data": null,
1158 | "is_perment": true,
1159 | "name": "[Content_Types].xml",
1160 | "removed_after_used": false,
1161 | "type": "buffer",
1162 | },
1163 | Object {
1164 | "callback": [Function],
1165 | "data": null,
1166 | "is_perment": true,
1167 | "name": "docProps\\\\core.xml",
1168 | "removed_after_used": false,
1169 | "type": "buffer",
1170 | },
1171 | Object {
1172 | "callback": [Function],
1173 | "data": null,
1174 | "is_perment": true,
1175 | "name": "word\\\\theme\\\\theme1.xml",
1176 | "removed_after_used": false,
1177 | "type": "buffer",
1178 | },
1179 | Object {
1180 | "callback": [Function],
1181 | "data": null,
1182 | "is_perment": true,
1183 | "name": "docProps\\\\app.xml",
1184 | "removed_after_used": false,
1185 | "type": "buffer",
1186 | },
1187 | Object {
1188 | "callback": [Function],
1189 | "data": null,
1190 | "is_perment": true,
1191 | "name": "word\\\\fontTable.xml",
1192 | "removed_after_used": false,
1193 | "type": "buffer",
1194 | },
1195 | Object {
1196 | "callback": [Function],
1197 | "data": null,
1198 | "is_perment": true,
1199 | "name": "word\\\\settings.xml",
1200 | "removed_after_used": false,
1201 | "type": "buffer",
1202 | },
1203 | Object {
1204 | "callback": [Function],
1205 | "data": null,
1206 | "is_perment": true,
1207 | "name": "word\\\\webSettings.xml",
1208 | "removed_after_used": false,
1209 | "type": "buffer",
1210 | },
1211 | Object {
1212 | "callback": [Function],
1213 | "data": null,
1214 | "is_perment": true,
1215 | "name": "word\\\\styles.xml",
1216 | "removed_after_used": false,
1217 | "type": "buffer",
1218 | },
1219 | Object {
1220 | "callback": [Function],
1221 | "data": Object {
1222 | "data": Array [
1223 | [Circular],
1224 | ],
1225 | "docEndExtra": "",
1226 | "docStartExtra": "",
1227 | "docType": "document",
1228 | },
1229 | "is_perment": true,
1230 | "name": "word\\\\document.xml",
1231 | "removed_after_used": false,
1232 | "type": "buffer",
1233 | },
1234 | Object {
1235 | "callback": [Function],
1236 | "data": null,
1237 | "is_perment": true,
1238 | "name": "word\\\\numbering.xml",
1239 | "removed_after_used": false,
1240 | "type": "buffer",
1241 | },
1242 | Object {
1243 | "callback": [Function],
1244 | "data": Array [
1245 | Object {
1246 | "clear": "type",
1247 | "target": "styles.xml",
1248 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
1249 | },
1250 | Object {
1251 | "clear": "type",
1252 | "target": "settings.xml",
1253 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
1254 | },
1255 | Object {
1256 | "clear": "type",
1257 | "target": "webSettings.xml",
1258 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",
1259 | },
1260 | Object {
1261 | "clear": "type",
1262 | "target": "fontTable.xml",
1263 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
1264 | },
1265 | Object {
1266 | "clear": "type",
1267 | "target": "theme/theme1.xml",
1268 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
1269 | },
1270 | Object {
1271 | "clear": "type",
1272 | "target": "numbering.xml",
1273 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
1274 | },
1275 | ],
1276 | "is_perment": true,
1277 | "name": "word\\\\_rels\\\\document.xml.rels",
1278 | "removed_after_used": false,
1279 | "type": "buffer",
1280 | },
1281 | ],
1282 | "type": Object {
1283 | "docx": Object {},
1284 | "msoffice": Object {
1285 | "files_list": Array [
1286 | Object {
1287 | "clear": "type",
1288 | "ext": "rels",
1289 | "type": "application/vnd.openxmlformats-package.relationships+xml",
1290 | },
1291 | Object {
1292 | "clear": "type",
1293 | "ext": "xml",
1294 | "type": "application/xml",
1295 | },
1296 | Object {
1297 | "clear": "type",
1298 | "ext": "jpeg",
1299 | "type": "image/jpeg",
1300 | },
1301 | Object {
1302 | "clear": "type",
1303 | "ext": "png",
1304 | "type": "image/png",
1305 | },
1306 | Object {
1307 | "clear": "type",
1308 | "ext": "gif",
1309 | "type": "image/gif",
1310 | },
1311 | Object {
1312 | "clear": "type",
1313 | "name": "/docProps/app.xml",
1314 | "type": "application/vnd.openxmlformats-officedocument.extended-properties+xml",
1315 | },
1316 | Object {
1317 | "clear": "type",
1318 | "name": "/word/theme/theme1.xml",
1319 | "type": "application/vnd.openxmlformats-officedocument.theme+xml",
1320 | },
1321 | Object {
1322 | "clear": "type",
1323 | "name": "/docProps/core.xml",
1324 | "type": "application/vnd.openxmlformats-package.core-properties+xml",
1325 | },
1326 | Object {
1327 | "clear": "type",
1328 | "name": "/word/settings.xml",
1329 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml",
1330 | },
1331 | Object {
1332 | "clear": "type",
1333 | "name": "/word/fontTable.xml",
1334 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml",
1335 | },
1336 | Object {
1337 | "clear": "type",
1338 | "name": "/word/webSettings.xml",
1339 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml",
1340 | },
1341 | Object {
1342 | "clear": "type",
1343 | "name": "/word/styles.xml",
1344 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml",
1345 | },
1346 | Object {
1347 | "clear": "type",
1348 | "name": "/word/document.xml",
1349 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml",
1350 | },
1351 | Object {
1352 | "clear": "type",
1353 | "name": "/word/numbering.xml",
1354 | "type": "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml",
1355 | },
1356 | ],
1357 | "rels_app": Array [
1358 | Object {
1359 | "clear": "type",
1360 | "target": "styles.xml",
1361 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
1362 | },
1363 | Object {
1364 | "clear": "type",
1365 | "target": "settings.xml",
1366 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
1367 | },
1368 | Object {
1369 | "clear": "type",
1370 | "target": "webSettings.xml",
1371 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",
1372 | },
1373 | Object {
1374 | "clear": "type",
1375 | "target": "fontTable.xml",
1376 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
1377 | },
1378 | Object {
1379 | "clear": "type",
1380 | "target": "theme/theme1.xml",
1381 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
1382 | },
1383 | Object {
1384 | "clear": "type",
1385 | "target": "numbering.xml",
1386 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
1387 | },
1388 | ],
1389 | "rels_main": Array [
1390 | Object {
1391 | "clear": "type",
1392 | "target": "docProps/app.xml",
1393 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
1394 | },
1395 | Object {
1396 | "clear": "type",
1397 | "target": "docProps/core.xml",
1398 | "type": "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
1399 | },
1400 | Object {
1401 | "clear": "type",
1402 | "target": "word/document.xml",
1403 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
1404 | },
1405 | ],
1406 | "src_files_list": Array [],
1407 | },
1408 | },
1409 | },
1410 | "genobj": officegen {
1411 | "_events": Object {
1412 | "afterGen": [Function],
1413 | "beforeGen": [Function],
1414 | "clearData": [Function],
1415 | "clearDoc": [Function],
1416 | "clearDocType": [Function],
1417 | },
1418 | "_eventsCount": 5,
1419 | "_maxListeners": undefined,
1420 | "addPageBreak": [Function],
1421 | "addResourceToParse": [Function],
1422 | "cbMakeDocxDocument": [Function],
1423 | "createByJson": [Function],
1424 | "createJson": [Function],
1425 | "createListOfDots": [Function],
1426 | "createListOfNumbers": [Function],
1427 | "createP": [Function],
1428 | "createTable": [Function],
1429 | "data": Array [
1430 | [Circular],
1431 | ],
1432 | "domain": null,
1433 | "generate": [Function],
1434 | "getFooter": [Function],
1435 | "getHeader": [Function],
1436 | "info": Object {
1437 | "cp:category": Object {
1438 | "data": "",
1439 | "def_data": "",
1440 | "element": "cp:category",
1441 | },
1442 | "cp:contentStatus": Object {
1443 | "data": "",
1444 | "def_data": "",
1445 | "element": "cp:contentStatus",
1446 | },
1447 | "cp:keywords": Object {
1448 | "data": "",
1449 | "def_data": "",
1450 | "element": "cp:keywords",
1451 | },
1452 | "dc:description": Object {
1453 | "data": "",
1454 | "def_data": "",
1455 | "element": "dc:description",
1456 | },
1457 | "dc:subject": Object {
1458 | "data": "",
1459 | "def_data": "",
1460 | "element": "dc:subject",
1461 | },
1462 | "dc:title": Object {
1463 | "data": "",
1464 | "def_data": "",
1465 | "element": "dc:title",
1466 | },
1467 | },
1468 | "options": Object {
1469 | "type": "docx",
1470 | },
1471 | "putPageBreak": [Function],
1472 | "setDescription": [Function],
1473 | "setDocCategory": [Function],
1474 | "setDocKeywords": [Function],
1475 | "setDocStatus": [Function],
1476 | "setDocSubject": [Function],
1477 | "setDocTitle": [Function],
1478 | "setTheme": [Function],
1479 | "startNewDoc": [Function],
1480 | "theme": null,
1481 | },
1482 | "mainPath": "word",
1483 | "mainPathFile": "document",
1484 | "msPluginsApi": Object {
1485 | "addInfoType": [Function],
1486 | "cbMakeMsOfficeBasicXml": [Function],
1487 | "cbMakeRels": [Function],
1488 | "makeOfficeGenerator": [Function],
1489 | "makeUniqueID": [Function],
1490 | },
1491 | "ogPluginsApi": Object {
1492 | "intAddAnyResourceToParse": [Function],
1493 | "type": Object {
1494 | "msoffice": Object {
1495 | "addInfoType": [Function],
1496 | "cbMakeMsOfficeBasicXml": [Function],
1497 | "cbMakeRels": [Function],
1498 | "makeOfficeGenerator": [Function],
1499 | "makeUniqueID": [Function],
1500 | },
1501 | },
1502 | },
1503 | "options": Object {},
1504 | "relsApp": Array [
1505 | Object {
1506 | "clear": "type",
1507 | "target": "styles.xml",
1508 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
1509 | },
1510 | Object {
1511 | "clear": "type",
1512 | "target": "settings.xml",
1513 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
1514 | },
1515 | Object {
1516 | "clear": "type",
1517 | "target": "webSettings.xml",
1518 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings",
1519 | },
1520 | Object {
1521 | "clear": "type",
1522 | "target": "fontTable.xml",
1523 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
1524 | },
1525 | Object {
1526 | "clear": "type",
1527 | "target": "theme/theme1.xml",
1528 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme",
1529 | },
1530 | Object {
1531 | "clear": "type",
1532 | "target": "numbering.xml",
1533 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
1534 | },
1535 | ],
1536 | "relsMain": Array [
1537 | Object {
1538 | "clear": "type",
1539 | "target": "docProps/app.xml",
1540 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties",
1541 | },
1542 | Object {
1543 | "clear": "type",
1544 | "target": "docProps/core.xml",
1545 | "type": "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties",
1546 | },
1547 | Object {
1548 | "clear": "type",
1549 | "target": "word/document.xml",
1550 | "type": "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument",
1551 | },
1552 | ],
1553 | "srcFilesList": Array [],
1554 | },
1555 | "children": Array [
1556 | LineBreak {
1557 | "name": "LineBreak",
1558 | "prop": Object {},
1559 | "root": [Circular],
1560 | },
1561 | ],
1562 | "parent": null,
1563 | "props": Object {
1564 | "children": ,
1565 | },
1566 | "root": [Circular],
1567 | "setParent": [Function],
1568 | },
1569 | }
1570 | `;
1571 |
--------------------------------------------------------------------------------