Giter Club home page Giter Club logo

html-to-pdfmake's Introduction

html-to-pdfmake

pdfmake permits to easily create a PDF with JavaScript; however there is no support of HTML code, so I decided to create a module to handle this feature.

Online Demo

You can find the online demo at https://aymkdn.github.io/html-to-pdfmake/index.html

How to use

This module will convert some basic and valid HTML code to its equivalent in pdfmake.

If you need to convert a complex HTML, check some online solutions, like Doppio, or you could try to convert your HTML to canvas, and then to export it to PDF.

Node

npm install html-to-pdfmake
var htmlToPdfmake = require("html-to-pdfmake");
// or:
// import htmlToPdfmake from "html-to-pdfmake"

Example:

var pdfMake = require("pdfmake/build/pdfmake");
var pdfFonts = require("pdfmake/build/vfs_fonts");
pdfMake.vfs = pdfFonts.pdfMake.vfs;
var htmlToPdfmake = require("html-to-pdfmake");

var html = htmlToPdfmake(`
  <div>
    <h1>My title</h1>
    <p>
      This is a sentence with a <strong>bold word</strong>, <em>one in italic</em>,
      and <u>one with underline</u>. And finally <a href="https://www.somewhere.com">a link</a>.
    </p>
  </div>
`);

/*
it will return:
{
  stack:[
    {
      text: 'My title',
      fontSize: 24,
      bold: true,
      marginBottom: 5,
      style: ['html-h1']
    },
    {
      text: [
        {
          text: 'This is a sentence with a '
        },
        {
          text: 'bold word',
          bold: true,
          style: ['html-strong']
        },
        {
          text: ', '
        },
        {
          text: 'one in italic',
          italics: true,
          style: ['html-em']
        },
        {
          text: ', and '
        },
        {
          text: 'one with underline',
          decoration: 'underline',
          style: ['html-u']
        },
        {
          text: '. And finally '
        },
        {
          text: 'a link',
          color: 'blue',
          decoration: 'underline',
          link: 'https://www.somewhere.com',
          style: ['html-a']
        },
        {
          text: '.'
        }
      ],
      margin: [0, 5, 0, 10],
      style: ['html-p']
    }
  ],
  style: ['html-div']
}
 */

Browser

<script src="https://cdn.jsdelivr.net/npm/html-to-pdfmake/browser.js"></script>

Example:

<!doctype html>
<html lang='en'>
<head>
  <meta charset='utf-8'>
  <title>my example</title>
  <!-- pdfmake files: -->
  <script src='https://cdn.jsdelivr.net/npm/pdfmake@latest/build/pdfmake.min.js'></script>
  <script src='https://cdn.jsdelivr.net/npm/pdfmake@latest/build/vfs_fonts.min.js'></script>
  <!-- html-to-pdfmake file: -->
  <script src="https://cdn.jsdelivr.net/npm/html-to-pdfmake/browser.js"></script>
</head>
<body>
  […]
  <script>
    var val = htmlToPdfmake("your html code here");
    var dd = {content:val};
    pdfMake.createPdf(dd).download();
  </script>
</body>
</html>

Documentation

Options

Some options can be passed to htmlToPdfmake function as a second argument.

window

If you use Node, then you'll have to pass the window object (see below).

defaultStyles

You can overwrite the default styles using defaultStyles (see below).

removeExtraBlanks

In some cases, you may see some extra blank spaces in the PDF. Because removing them could be quite resource consuming, the option is false by default.

showHidden

By default the display:none elements won't be parsed. Set this option to true to display the hidden elements in the PDF.

removeTagClasses

By default we add a class html-TAG for each node. It's possible to remove these CSS classes by using removeTagClasses:true.

ignoreStyles

You can define a list of style properties that should not be parsed. For example, to ignore font-family:

htmlToPdfmake("[the html code here]", {ignoreStyles:['font-family']})

imagesByReference

If you're using html-to-pdfmake in a web browser with images, then you can set this option to true and it will automatically load your images in your PDF using the {images} option of PDFMake.

Using this option will change the output of html-to-pdfmake that will return an object with {content, images}.

Example:

var ret = htmlToPdfmake(`<img src="https://picsum.photos/seed/picsum/200">`, {
  imagesByReference:true
});
// 'ret' contains:
//  {
//    "content":[
//      [
//        {
//          "nodeName":"IMG",
//          "image":"img_ref_0",
//          "style":["html-img"]
//        }
//      ]
//    ],
//    "images":{
//      "img_ref_0":"https://picsum.photos/seed/picsum/200"
//    }
//  }

var dd = {
  content:ret.content,
  images:ret.images
}
pdfMake.createPdf(dd).download();

You can use the "custom headers" too by passing a JSON string in either src, or data-src:

<div>
  <img src="https://picsum.photos/id/1080/367/267" data-src="{&quot;url&quot;:&quot;https://picsum.photos/id/1080/367/267&quot;,&quot;headers&quot;:{&quot;myheader&quot;:&quot;123&quot;}}" />
  <img src="https://picsum.photos/seed/picsum/200/300" data-src='{"url":"https://picsum.photos/seed/picsum/200/300","headers":{"myheader":"123"}}' />
</div>

fontSizes

You can overwrite the default sizes for the old HTML4 tag <font> by using fontSizes. It must be an array with 7 values (see below).

tableAutoSize

By passing tableAutoSize with true, then the program will try to define widths and heights for the tables, based on CSS properties width and height that have been provided to TH or TD.

Example:

var html = htmlToPdfmake(`<table>
  <tr style="height:100px">
    <td style="width:250px">height:100px / width:250px</td>
    <td>height:100px / width:'auto'</td>
  </tr>
  <tr>
    <td style="width:100px">Here it will use 250px for the width because we have to use the largest col's width</td>
    <td style="height:200px">height:200px / width:'auto'</td>
  </tr>
</table>`, {
  tableAutoSize:true
});

// it will return something like:
[ {
    "table": {
      "body": [ [  ] ],
      "widths": [ 188, "auto" ],
      "heights": [ 75, 151 ]
    }
} ]

replaceText

By passing replaceText as a function with two parameters (text and nodes) you can modify the text of all the nodes in your HTML document.

Example:

var html = htmlToPdfmake(`<p style='text-align: justify;'>Lorem Ipsum is simply d-ummy text of th-e printing and typese-tting industry. Lorem Ipsum has b-een the industry's standard dummy text ever since the 1500s</p>`, {
  replaceText:function(text, nodes) {
    // 'nodes' contains all the parent nodes for the text
    return text.replace(/-/g, "\\u2011"); // it will replace any occurrence of '-' with '\\u2011' in "Lorem Ipsum is simply d-ummy text […] dummy text ever since the 1500s"
  }
});

customTag

If your HTML code doesn't use regular HTML tags, then you can use customTag to define your own result.

Example with a QR code generator:

var html = htmlToPdfMake(`<code typecode="QR" style="foreground:black;background:yellow;fit:300px">texto in code</code>`, {,
  customTag:function(params) {
    var ret = params.ret;
    var element = params.element;
    var parents = params.parents;
    switch(ret.nodeName) {
      case "CODE": {
        ret = this.applyStyle({ret:ret, parents:parents.concat([element])});
        ret.qr = ret.text[0].text;
        switch(element.getAttribute("typecode")){
          case 'QR':
            delete ret.text;
            ret.nodeName='QR';
            if(!ret.style || !Array.isArray(ret.style)){
              ret.style = [];
            }
            ret.style.push('html-qr');
            break;
        }
        break;
      }
    }
    return ret;
  }
});

HTML tags supported

The below HTML tags are supported:

  • A (with external and internal links)
  • DIV / P / SPAN
  • B / STRONG
  • I / EM
  • S
  • UL / OL / LI
  • TABLE / THEAD / TBODY / TFOOTER / TR / TH / TD
  • H1 to H6
  • FONT
  • IMG
  • SVG
  • SUP / SUB
  • PRE

CSS properties supported

CSS can create very complex design, however this framework can only handle the most simple HTML / CSS. The support of CSS style is limited and might not work in all cases with all values:

  • background-color
  • border
  • color
  • font-family
  • font-style (with italic)
  • font-weight (with bold)
  • height
  • margin
  • line-height
  • text-align
  • text-decoration
  • text-indent
  • white-space (with break-spaces and pre*)
  • width

Default styles

I've defined some default styles for the supported element.

For example, using a <STRONG> will display the word in bold. Or, a link will appear in blue with an underline, and so on...

Here is the list of defaults styles:

{
    b: {bold:true},
    strong: {bold:true},
    u: {decoration:'underline'},
    s: {decoration: 'lineThrough'},
    em: {italics:true},
    i: {italics:true},
    h1: {fontSize:24, bold:true, marginBottom:5},
    h2: {fontSize:22, bold:true, marginBottom:5},
    h3: {fontSize:20, bold:true, marginBottom:5},
    h4: {fontSize:18, bold:true, marginBottom:5},
    h5: {fontSize:16, bold:true, marginBottom:5},
    h6: {fontSize:14, bold:true, marginBottom:5},
    a: {color:'blue', decoration:'underline'},
    strike: {decoration: 'lineThrough'},
    p: {margin:[0, 5, 0, 10]},
    ul: {marginBottom:5},
    li: {marginLeft:5},
    table: {marginBottom:5},
    th: {bold:true, fillColor:'#EEEEEE'}
  }

For the old HTML4 tag <font>, the size attributes can have a value from 1 to 7, which will be converted to 10pt, 14pt, 16pt, 18pt, 20pt, 24pt, or 28pt.

Please, note that the above default styles are stronger than the ones defined in the style classes. Read below how to overwrite them.

Customize style

Each converted element will have an associated style-class called html-tagname.

For example, if you want all <STRONG> tags to be highlighted with a yellow backgroud you can use html-strong in the styles definition:

var html = htmlToPdfmake(`
  <p>
    This sentence has <strong>a highlighted word</strong>, but not only.
  </p>
  `);

var docDefinition = {
  content: [
    html
  ],
  styles:{
    'html-strong':{
      background:'yellow' // it will add a yellow background to all <STRONG> elements
    }
  }
};

var pdfDocGenerator = pdfMake.createPdf(docDefinition);

CSS class and style

The class and styles for the elements will also be added.

var html = htmlToPdfmake(`
  <p>
    This sentence has <span style="font-weight:bold" class="red">a bold and red word</span>.
  </p>
  `);

/*
It returns:
{
  text: [
    {
      text: 'This sentence has '
    },
    {
      text: 'a bold and red word',
      style: ['red', 'html-span'], // 'red' added because of `class="red"`
      bold: true // added because of `style="font-weight:bold"`
    },
    {
      text: '.'
    }
  ],
  margin: [0, 5, 0, 10],
  style: ['html-p']
}
*/

var docDefinition = {
 content: [
   html
 ],
 styles:{
   red:{ // we define the class called "red"
     color:'red'
   }
 }
};

var pdfDocGenerator = pdfMake.createPdf(docDefinition);

Please, note that the default styles are stronger than the ones defined in the style classes. For example, if you define a class html-a to change all links in purple, then it won't work because the default styles will overwrite it:

var docDefinition = {
 content: [
   html
 ],
 styles:{
   'html-a':{
     color:'purple' // it won't work: all links will remain 'blue'
   }
 }
};

To make it work, you have to either delete the default styles, or change it with a new value. Starting v1.1.0, an option parameter is available as a second parameter.

Example: you want <li> to not have a margin-left, and <a> to be 'purple' and without 'underline' style:

var html = htmlToPdfmake('<ul><li>this is <a href="...">a link</a></li><li>another item</li><li class="with-margin">3rd item with a margin</li></ul>', {
  defaultStyles:{ // change the default styles
    a:{ // for <A>
      color:'purple', // all links should be 'purple'
      decoration:'' // remove underline
    },
    li:'' // remove all default styles for <LI>
  }
});

var docDefinition = {
 content: [
   html
 ],
 styles:{
   'with-margin':{
     marginLeft: 30 // apply a margin with the specific class is used
   }
 }
};

Units

PDFMake uses pt units for the numbers. html-to-pdfmake will check the inline style to see if a number with unit is provided, then it will convert it to pt.

It only works for px, pt, em and rem (for em/rem it's based on 1rem = 16px);

Examples:

  • font-size:16px will be converted to fontSize:12
  • margin:1em will be converted to margin:12

<img>

If you use html-to-pdfmake in a Web browser, then you could just pass the option imagesByReference with the value true and the images will be passed by references (starting from PDFMake v0.1.67).

Otherwise, for example when using this library with Node instead of a Web browser, the src attribute must be a base64 encoded content (as describe in the PDFMake documentation) or a reference (see more here).

You can check this Stackoverflow question to know the different ways to get a base64 encoded content from an image.

page break

You can use pageBreakBefore and a CSS class that you'll apply to your elements to identify when to add a page break:

var html = htmlToPdfmake(`
  <div>
    <h1>My title on page 1</h1>
    <p>
      This is my paragraph on page 1.
    </p>
    <h1 class="pdf-pagebreak-before">My title on page 2</h1>
    <p>This is my paragraph on page 2.</p>
  </div>
`);

var docDefinition = {
  content: [
    html
  ],
  pageBreakBefore: function(currentNode) {
    return currentNode.style && currentNode.style.indexOf('pdf-pagebreak-before') > -1;
  }
};

var pdfDocGenerator = pdfMake.createPdf(docDefinition);

See example.js to see another example.

Special properties

PDFMake provides some special attributes, like widths or heights for table, or fit for image, and more. To apply these special attributes, you have to use the attribute data-pdfmake on your HTML elements, and then pass the special attributes as a JSON string.

<!-- Example with `widths:[100,"*","auto"]` and `heights:40` to apply to a `table`. -->

<table data-pdfmake="{'widths':[100,'*','auto'],'heights':40}">
  <tr>
    <td colspan="3">Table with <b>widths=[100,"*","auto"]</b> and <b>heights=40</b></td>
  </tr>
  <tr>
    <td>Cell1</td>
    <td>Cell2</td>
    <td>Cell3</td>
  </tr>
</table>

The expression provided by data-pdfmake must be a valid JSON string because it will be translated with JSON.parse().

<hr>

An <hr> can also be customized using data-pdfmake. Some default styles are applied to this element:

{
  left:0, // the left position
  width:514, // should be OK with a A4 page
  color:'black', // the color of the line
  thickness:0.5, // how thick the line must be
  margin:[0,12,0,12] // same order as PDFMake, meaning: [left, top, right, bottom]
}

See the example.js file to see a <hr> example.

Use with Node

To use it in a Node script you need to install jsdom:

npm install jsdom

Then in your JS file:

var pdfMake = require("pdfmake/build/pdfmake");
var pdfFonts = require("pdfmake/build/vfs_fonts");
pdfMake.vfs = pdfFonts.pdfMake.vfs;
var fs = require('fs');
var jsdom = require("jsdom");
var { JSDOM } = jsdom;
var { window } = new JSDOM("");
var htmlToPdfMake = require("html-to-pdfmake");

var html = htmlToPdfMake(`<div>the html code</div>`, {window:window});

var docDefinition = {
  content: [
    html
  ]
};

var pdfDocGenerator = pdfMake.createPdf(docDefinition);
pdfDocGenerator.getBuffer(function(buffer) {
  fs.writeFileSync('example.pdf', buffer);
});

Examples

You can find more examples in example.js which will create example.pdf:

npm install
node example.js

Donate

You can support my work by making a donation, or by visiting my Github Sponsors page. Thank you!

html-to-pdfmake's People

Contributors

alfonso-g-h avatar arunbanswal avatar aymkdn avatar danhobbs75 avatar dependabot[bot] avatar ematochkina avatar eyesonlynet avatar gustavoquinalha avatar jcubes avatar luicfrr avatar nag167 avatar pateltilak avatar vitale232 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

html-to-pdfmake's Issues

window is not defined

I tried html-to-pdfmake with node and i get this error window is not defined, i tried passing the global but it seems that it needs DOMParser or something and i have no clue.

tableAutoSize produces null when using percentages

When using percentages for widths in the an html table here:

<table style="width: 100%;">
	<thead>
		<tr>
			<th colspan="4" style="width: 100%; text-align: center;">
				<div style="text-align: center;">Test Table</div>
			</th>
		</tr>
	</thead>
	<tbody>
		<tr>
			<td style="width: 25%;">test1</td>
			<td style="width: 25%;">test2</td>
			<td style="width: 25%;">test3</td>
			<td style="width: 25%;">test4</td>
		</tr>
		<tr>
			<td style="width: 25%;">test5</td>
			<td style="width: 25%;">test6</td>
			<td style="width: 25%;">test7</td>
			<td style="width: 25%;">test8</td>
		</tr>
	</tbody>
</table>

Which looks like this:

Test Table
test1 test2 test3 test4
test5 test6 test7 test8

When converting it with {tableAutoSize: true}, the first column width is null, causing issues with pdfMake.

[
    {
        "nodeName": "TABLE",
        "table": {
            "body": [
                [
                    {
                        "nodeName": "TH",
                        "stack": [
                            {
                                "text": "Test Table",
                                "nodeName": "DIV",
                                "bold": true,
                                "fillColor": "#EEEEEE",
                                "alignment": "center",
                                "style": [
                                    "html-div",
                                    "html-th",
                                    "html-tr",
                                    "html-thead",
                                    "html-table"
                                ]
                            }
                        ],
                        "colSpan": 4,
                        "bold": true,
                        "fillColor": "#EEEEEE",
                        "width": "100%",
                        "style": [
                            "html-th",
                            "html-tr",
                            "html-thead",
                            "html-table"
                        ]
                    },
                    {
                        "text": ""
                    },
                    {
                        "text": ""
                    },
                    {
                        "text": ""
                    }
                ],
                [
                    {
                        "text": "test1",
                        "nodeName": "TD",
                        "width": "25%",
                        "style": [
                            "html-td",
                            "html-tr",
                            "html-tbody",
                            "html-table"
                        ]
                    },
                    {
                        "text": "test2",
                        "nodeName": "TD",
                        "width": "25%",
                        "style": [
                            "html-td",
                            "html-tr",
                            "html-tbody",
                            "html-table"
                        ]
                    },
                    {
                        "text": "test3",
                        "nodeName": "TD",
                        "width": "25%",
                        "style": [
                            "html-td",
                            "html-tr",
                            "html-tbody",
                            "html-table"
                        ]
                    },
                    {
                        "text": "test4",
                        "nodeName": "TD",
                        "width": "25%",
                        "style": [
                            "html-td",
                            "html-tr",
                            "html-tbody",
                            "html-table"
                        ]
                    }
                ],
                [
                    {
                        "text": "test5",
                        "nodeName": "TD",
                        "width": "25%",
                        "style": [
                            "html-td",
                            "html-tr",
                            "html-tbody",
                            "html-table"
                        ]
                    },
                    {
                        "text": "test6",
                        "nodeName": "TD",
                        "width": "25%",
                        "style": [
                            "html-td",
                            "html-tr",
                            "html-tbody",
                            "html-table"
                        ]
                    },
                    {
                        "text": "test7",
                        "nodeName": "TD",
                        "width": "25%",
                        "style": [
                            "html-td",
                            "html-tr",
                            "html-tbody",
                            "html-table"
                        ]
                    },
                    {
                        "text": "test8",
                        "nodeName": "TD",
                        "width": "25%",
                        "style": [
                            "html-td",
                            "html-tr",
                            "html-tbody",
                            "html-table"
                        ]
                    }
                ]
            ],
            "widths": [
                null,
                "25%",
                "25%",
                "25%"
            ],
            "heights": [
                "auto",
                "auto",
                "auto"
            ]
        },
        "marginBottom": 5,
        "width": "100%",
        "style": [
            "html-table"
        ]
    }
]

Thank you for making this tool, it's been a great help.

Issue with bold and br element

I have the following input html string:

<p><b>Text 1 Bold<br> continue with bold in new line 1<br>continue with bold in new line 2</b><br> simple text <br> simple text <br><b>another bold line</b><br></p>

The output I get is as follows ( can be tested in pdfmake playground) :

var dd = {
	content: [
        {
          "text": [
            {
              "stack": [
                {
                  "text": "Text 1 Bold",
                  "bold": true
                },
                "\n",
                {
                  "text": " continue with bold in new line 1",
                  "bold": true
                },
                "\n",
                {
                  "text": "continue with bold in new line 2",
                  "bold": true
                }
              ],
              "style": [
                "html-b"
              ]
            },
            "\n",
            {
              "text": " simple text "
            },
            "\n",
            {
              "text": " simple text "
            },
            "\n",
            {
              "text": "another bold line",
              "bold": true,
              "style": [
                "html-b"
              ]
            },
            "\n"
          ],
          "margin": [
            0,
            5,
            0,
            10
          ],
          "style": [
            "html-p"
          ]
        }
	]
} 

which results in some text truncation :

result

The desired output :
expected

Unable to process ngx-quill styles

Hi, I've used ngx-quill to let users edit their content and then using html-to-pdfmake (for HTML support) generating the PDF. As I've used ngx-quill the styles are defined as per ngx-quill, html-to-pdfmake doesn't seem to parse them. For example, edited this in my ngx-quill editor, the html form is: <p class="ql-align-justify ql-indent-2">hi</p> after passing this html input to html-to-pdf the indentation didn't work in PDF generated. Is there a way to fix this? Thanks

Add strikethrough support and problem with margin in <li>

<p>Here I am.</p><p><br></p><p>I'm another sentence two lines down. <s>Some strike through.</s></p><p><br></p><ul><li>list item 1</li><li class="ql-indent-1">list item 1.2</li><li>list item 2</li></ul><p><br></p><p><br></p>

this produces
Screen Shot 2019-09-17 at 2 18 23 PM

Here is the same output in our UI's text field which uses the vue2-editor package

Screen Shot 2019-09-17 at 2 19 50 PM

There are 3 problems:
No strike through
2nd sentence is on line 2 instead of line 3.
Lists aren't displayed at all.

Thank you.

Originally posted by @SunnysideAaron in #8 (comment)

Window is not defined when running on NodeJS

Hi there!

Does this module work within NodeJS??
I'm getting the following error

ReferenceError: window is not defined
server-api    |     at module.exports (/usr/src/app/server-api/node_modules/html-to-pdfmake/index.js:36:60)

I can see in the code it expects a window to be present ...

Thanks!

Angular support

Hi

Do you have support for Angular?
If I try to run it, I get the following error:
Object(...) is not a function

I try to import it like this:
import { htmlToPdfMake } from 'html-to-pdfmake';

And then run it like this:
const result = htmlToPdfMake('

test
');

Thanks!

img support

Hi,
I need to convert img tag to pdf, someday you will add the element?

Adding colspan to th giving _minWidth error

Hi ,
I have a table with below code
<table class='table table-sm table-bordered table-responsive-sm custom-border'> <thead class='table-light'> <tr> <th colspan="2">Header</th> </tr> </thead> <tbody> <tr> <td>Data1</td> <td>Data2</td> </tr> </tbody> </table>

The output of above html will be :

Header
Data1 Data2
When I converted this html to pdf then I am getting below error

ERROR TypeError: Cannot read property '_minWidth' of undefined at getMinMax (pdfmake.js:61732) at extendWidthsForColSpans (pdfmake.js:61706) at DocMeasure.measureTable (pdfmake.js:61615) at pdfmake.js:61081 at StyleContextStack.auto (pdfmake.js:18428) at DocMeasure.measureNode (pdfmake.js:61068) at DocMeasure.measureVerticalContainer (pdfmake.js:61311) at pdfmake.js:61075 at StyleContextStack.auto (pdfmake.js:18428) at DocMeasure.measureNode (pdfmake.js:61068

Bower install

Hi,
is there any way to install with bower ?
Thanks

div style properties overrule inner span style properties

Hi again, sorry for coming up with another issue.

I'm using tinyMCE to generate the HTML code, and unfortunately, tinyMCE generates font-size properties even in the surrounding divs and even if they aren't even needed.
For both examples, I used the test site you provided.
So, when trying to convert this

<div style="font-size: 7pt;"><span style="font-size: 11pt;">asda<strong>sd</strong>dad</span></div>
<div style="font-size: 7pt;">&nbsp;</div>
<div style="font-size: 7pt;"><span style="font-size: 11pt;">ublubub</span></div>
<div style="font-size: 7pt;">&nbsp;</div>
<div style="font-size: 7pt;"><span style="font-size: 11pt;">asdasd</span></div>
<div style="font-size: 7pt;">&nbsp;</div>
<div style="font-size: 7pt;"><span style="font-size: 11pt;">kl&ouml;asd<em>asd<u>asdasd</u></em></span></div>
<div style="font-size: 7pt;">&nbsp;</div>

I get the following result:

[
  {
    "text": [
      {
        "text": "asda",
        "style": [
          "html-span"
        ]
      },
      {
        "text": "sd",
        "style": [
          "html-strong",
          "html-span"
        ],
        "bold": true
      },
      {
        "text": "dad",
        "style": [
          "html-span"
        ]
      }
    ],
    "style": [
      "html-span",
      "html-div"
    ],
    "fontSize": 7
  },
  {
    "text": " ",
    "fontSize": 7,
    "style": [
      "html-div"
    ]
  },
  {
    "text": "ublubub",
    "style": [
      "html-span",
      "html-div"
    ],
    "fontSize": 7
  },
  {
    "text": " ",
    "fontSize": 7,
    "style": [
      "html-div"
    ]
  },
  {
    "text": "asdasd",
    "style": [
      "html-span",
      "html-div"
    ],
    "fontSize": 7
  },
  {
    "text": " ",
    "fontSize": 7,
    "style": [
      "html-div"
    ]
  },
  {
    "text": [
      {
        "text": "klöasd",
        "style": [
          "html-span"
        ]
      },
      {
        "text": [
          {
            "text": "asd",
            "style": [
              "html-em",
              "html-span"
            ],
            "italics": true
          },
          {
            "text": "asdasd",
            "style": [
              "html-u",
              "html-em",
              "html-span"
            ],
            "decoration": "underline",
            "italics": true
          }
        ],
        "italics": true,
        "style": [
          "html-em",
          "html-span"
        ]
      }
    ],
    "style": [
      "html-span",
      "html-div"
    ],
    "fontSize": 7
  },
  {
    "text": " ",
    "fontSize": 7,
    "style": [
      "html-div"
    ]
  }
]

And it looks like this:
image

where the font size is 7 instead of the 11 of the span.

Additionally, <br> tags cause some weird behavior as well. It appears to variate the font-size in some lines, but not in all.

Example:

<div style="font-family: segoe ui; font-size: 7pt;"><span style="font-size: 11pt;">asda<strong>sd</strong>dad</span><br></div>
<div style="font-family: segoe ui; font-size: 7pt;">&nbsp;<br></div>
<div style="font-family: segoe ui; font-size: 7pt;"><span style="font-size: 11pt;">ublubub</span><br></div>
<div style="font-family: segoe ui; font-size: 7pt;">&nbsp;<br></div>
<div style="font-family: segoe ui; font-size: 7pt;"><span style="font-size: 11pt;">asdasd</span><br></div>
<div style="font-family: segoe ui; font-size: 7pt;">&nbsp;<br></div>
<div style="font-family: segoe ui; font-size: 7pt;"><span style="font-size: 11pt;">kl&ouml;asd<em>asd<u>asdasd</u></em></span><br></div>
<div style="font-family: segoe ui; font-size: 7pt;">&nbsp;<br></div>

And the output:

[
  {
    "text": [
      {
        "text": [
          {
            "text": "asda",
            "style": [
              "html-span"
            ]
          },
          {
            "text": "sd",
            "style": [
              "html-strong",
              "html-span"
            ],
            "bold": true
          },
          {
            "text": "dad",
            "style": [
              "html-span"
            ]
          }
        ],
        "style": [
          "html-span"
        ],
        "fontSize": 11
      },
      "\n"
    ],
    "style": [
      "html-div"
    ],
    "fontFamily": "segoeui",
    "fontSize": 7
  },
  {
    "text": [
      {
        "text": " "
      },
      "\n"
    ],
    "style": [
      "html-div"
    ],
    "fontFamily": "segoeui",
    "fontSize": 7
  },
  {
    "text": [
      {
        "text": "ublubub",
        "style": [
          "html-span"
        ],
        "fontSize": 11
      },
      "\n"
    ],
    "style": [
      "html-div"
    ],
    "fontFamily": "segoeui",
    "fontSize": 7
  },
  {
    "text": [
      {
        "text": " "
      },
      "\n"
    ],
    "style": [
      "html-div"
    ],
    "fontFamily": "segoeui",
    "fontSize": 7
  },
  {
    "text": [
      {
        "text": "asdasd",
        "style": [
          "html-span"
        ],
        "fontSize": 11
      },
      "\n"
    ],
    "style": [
      "html-div"
    ],
    "fontFamily": "segoeui",
    "fontSize": 7
  },
  {
    "text": [
      {
        "text": " "
      },
      "\n"
    ],
    "style": [
      "html-div"
    ],
    "fontFamily": "segoeui",
    "fontSize": 7
  },
  {
    "text": [
      {
        "text": [
          {
            "text": "klöasd",
            "style": [
              "html-span"
            ]
          },
          {
            "text": [
              {
                "text": "asd",
                "style": [
                  "html-em",
                  "html-span"
                ],
                "italics": true
              },
              {
                "text": "asdasd",
                "style": [
                  "html-u",
                  "html-em",
                  "html-span"
                ],
                "decoration": "underline",
                "italics": true
              }
            ],
            "italics": true,
            "style": [
              "html-em",
              "html-span"
            ]
          }
        ],
        "style": [
          "html-span"
        ],
        "fontSize": 11
      },
      "\n"
    ],
    "style": [
      "html-div"
    ],
    "fontFamily": "segoeui",
    "fontSize": 7
  },
  {
    "text": [
      {
        "text": " "
      },
      "\n"
    ],
    "style": [
      "html-div"
    ],
    "fontFamily": "segoeui",
    "fontSize": 7
  }
]

which then looks like this:
image

Strange issue rendering svg

Hi, I have a problem that may be due to parsing.

I have several HTML data from a database, all al paragraphs which have some math formulas that are parsed and replaced by SVG. All this data can be rendered in browsers well, with the SVG formulas rendering ok.

<p>La soja es uno de los cultivos con mayor importancia económica en Argentina. De su procesamiento industrial, el tegumento es separado y desechado o utilizado para nutrición animal. Sin embargo, ha demostrado ser una fuente de polifenoles, entre otros compuestos. El objetivo del trabajo fue determinar la composición química del tegumento de soja amarilla, el contenido de polifenoles, flavonoides y actividad antioxidante de diferentes extractos y fracciones purificadas. Se determinó la composición química proximal del tegumento y se obtuvieron cuatro extractos a partir del tegumento desengrasado: 1) Extracto crudo (EC): obtenido por maceración con una mezcla de etanol-agua (70:30 v/v); 2) Fracción de acetato de etilo (FAE): obtenida por partición del EC con acetato de etilo y agua; 3) Fracción acuosa (FA): separada de la partición anterior; y 4) Extracto de digestión (ED): obtenido por digestión química del tegumento extraído del proceso 1). Sobre cada extracto se determinó: rendimiento de extracción, contenido de fenoles y flavonoides, y capacidad antioxidante (DPPH•, ABTS•+, FRAP y Rancimat). Los datos se analizaron mediante ANOVA y test DGC <svg xmlns:xlink="http://www.w3.org/1999/xlink" width="9.107ex" height="2.509ex" style="vertical-align: -0.671ex;" viewBox="0 -791.3 3921.2 1080.4" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-labelledby="MathJax-SVG-1-Title"><title id="MathJax-SVG-1-Title">\\alpha=0,05</title><defs aria-hidden="true"><path stroke-width="1" id="E1-MJMATHI-3B1" d="M34 156Q34 270 120 356T309 442Q379 442 421 402T478 304Q484 275 485 237V208Q534 282 560 374Q564 388 566 390T582 393Q603 393 603 385Q603 376 594 346T558 261T497 161L486 147L487 123Q489 67 495 47T514 26Q528 28 540 37T557 60Q559 67 562 68T577 70Q597 70 597 62Q597 56 591 43Q579 19 556 5T512 -10H505Q438 -10 414 62L411 69L400 61Q390 53 370 41T325 18T267 -2T203 -11Q124 -11 79 39T34 156ZM208 26Q257 26 306 47T379 90L403 112Q401 255 396 290Q382 405 304 405Q235 405 183 332Q156 292 139 224T121 120Q121 71 146 49T208 26Z"></path><path stroke-width="1" id="E1-MJMAIN-3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"></path><path stroke-width="1" id="E1-MJMAIN-30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"></path><path stroke-width="1" id="E1-MJMAIN-2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z"></path><path stroke-width="1" id="E1-MJMAIN-35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)" aria-hidden="true"> <use xlink:href="#E1-MJMATHI-3B1" x="0" y="0"></use> <use xlink:href="#E1-MJMAIN-3D" x="918" y="0"></use> <use xlink:href="#E1-MJMAIN-30" x="1974" y="0"></use> <use xlink:href="#E1-MJMAIN-2C" x="2475" y="0"></use><g transform="translate(2920,0)"> <use xlink:href="#E1-MJMAIN-30"></use> <use xlink:href="#E1-MJMAIN-35" x="500" y="0"></use></g></g></svg> en InfoStat. El tegumento presentó 52,63% de carbohidratos, 10,88% de proteínas, 11,73% de materia grasa, 8,32% de cenizas y 16,43% de humedad. El desengrasado utilizando un equipo Soxhlet tuvo un rendimiento de 11,56%, y el desengrasado en frío de 11,82%, sin diferencias significativas. La extracción convencional (EC) presentó un rendimiento de 7,79 mg/g, contenido de polifenoles 35,71 mg EAG/g extracto seco y flavonoides 1,12 mg EQ/g. Las fracciones resultantes del proceso de partición (FAE y FA) mostraron diferencias significativas en sus rendimientos de extracción y contenidos de fenoles y flavonoides totales. FA contuvo mayor materia seca (7,83 mg/g) que FAE (0,15 mg/g). No obstante, FAE presentó el mayor contenido de fenoles (65,49 mg EAG/g es) y FA de flavonoides (2,99 mg EQ/g es). El extracto obtenido por digestión (ED) presentó el menor rendimiento de extracción (0,48 mg/g), fenoles (13,67 mg EAG/g) y flavonoides (2,43 mg EQ/g). Por otro lado, FAE mostró la mejor actividad DPPH• y FRAP (101,61 µg/mL y 31,34 mg EAA/g, respectivamente), y junto a ED la mejor capacidad de secuestrar el catión ABTS•+ (76,14 y 69,48 mg Trolox/g, respectivamente). Por último, FA y el antioxidante artificial BHT tuvieron los mejores tiempos de inducción en Rancimat sin presentar diferencias estadísticamente significativas entre ellas (13,165 y 13,365 horas). En general, el tegumento de soja presenta compuestos fenólicos y actividad antioxidante. La partición con solvente usando acetato de etilo es un método que permite el incremento del contenido de fenoles totales y la capacidad antioxidante de los extractos del tegumento. La digestión química del tegumento permitió obtener un extracto con capacidad antioxidante ABTS•+, y con contenidos intermedios de fenoles y flavonoides, en relación a los otros extractos.</p>

The problem is I need to make a PDF and for this I am using pdfMake. But when I pipe this result into html-to-pdfmake I get this.

[ { text:
     [ { text:
          'La soja es uno de los cultivos con mayor importancia económica en Argentina. De su procesamiento industrial, el tegumento es separado y desechado o utilizado para nutrición animal. Sin embargo, ha demostrado ser una fuente de polifenoles, entre otros compuestos. El objetivo del trabajo fue determinar la composición química del tegumento de soja amarilla, el contenido de polifenoles, flavonoides y actividad antioxidante de diferentes extractos y fracciones purificadas. Se determinó la composición química proximal del tegumento y se obtuvieron cuatro extractos a partir del tegumento desengrasado: 1) Extracto crudo (EC): obtenido por maceración con una mezcla de etanol-agua (70:30 v/v); 2) Fracción de acetato de etilo (FAE): obtenida por partición del EC con acetato de etilo y agua; 3) Fracción acuosa (FA): separada de la partición anterior; y 4) Extracto de digestión (ED): obtenido por digestión química del tegumento extraído del proceso 1). Sobre cada extracto se determinó: rendimiento de extracción, contenido de fenoles y flavonoides, y capacidad antioxidante (DPPH•, ABTS•+, FRAP y Rancimat). Los datos se analizaron mediante ANOVA y test DGC ',
         style: [ 'html-p' ] },
       { svg:
          '<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="9.107ex" height="2.509ex" style="vertical-align: -0.671ex;" viewBox="0 -791.3 3921.2 1080.4" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-labelledby="MathJax-SVG-1-Title"><title id="MathJax-SVG-1-Title">\\alpha=0,05</title><defs aria-hidden="true"><path stroke-width="1" id="E1-MJMATHI-3B1" d="M34 156Q34 270 120 356T309 442Q379 442 421 402T478 304Q484 275 485 237V208Q534 282 560 374Q564 388 566 390T582 393Q603 393 603 385Q603 376 594 346T558 261T497 161L486 147L487 123Q489 67 495 47T514 26Q528 28 540 37T557 60Q559 67 562 68T577 70Q597 70 597 62Q597 56 591 43Q579 19 556 5T512 -10H505Q438 -10 414 62L411 69L400 61Q390 53 370 41T325 18T267 -2T203 -11Q124 -11 79 39T34 156ZM208 26Q257 26 306 47T379 90L403 112Q401 255 396 290Q382 405 304 405Q235 405 183 332Q156 292 139 224T121 120Q121 71 146 49T208 26Z"></path><path stroke-width="1" id="E1-MJMAIN-3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"></path><path stroke-width="1" id="E1-MJMAIN-30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"></path><path stroke-width="1" id="E1-MJMAIN-2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z"></path><path stroke-width="1" id="E1-MJMAIN-35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)" aria-hidden="true"> <use xlink:href="#E1-MJMATHI-3B1" x="0" y="0"></use> <use xlink:href="#E1-MJMAIN-3D" x="918" y="0"></use> <use xlink:href="#E1-MJMAIN-30" x="1974" y="0"></use> <use xlink:href="#E1-MJMAIN-2C" x="2475" y="0"></use><g transform="translate(2920,0)"> <use xlink:href="#E1-MJMAIN-30"></use> <use xlink:href="#E1-MJMAIN-35" x="500" y="0"></use></g></g></svg>',
         style: [ 'html-svg' ] },
       { text:
          ' en InfoStat. El tegumento presentó 52,63% de carbohidratos, 10,88% de proteínas, 11,73% de materia grasa, 8,32% de cenizas y 16,43% de humedad. El desengrasado utilizando un equipo Soxhlet tuvo un rendimiento de 11,56%, y el desengrasado en frío de 11,82%, sin diferencias significativas. La extracción convencional (EC) presentó un rendimiento de 7,79 mg/g, contenido de polifenoles 35,71 mg EAG/g extracto seco y flavonoides 1,12 mg EQ/g. Las fracciones resultantes del proceso de partición (FAE y FA) mostraron diferencias significativas en sus rendimientos de extracción y contenidos de fenoles y flavonoides totales. FA contuvo mayor materia seca (7,83 mg/g) que FAE (0,15 mg/g). No obstante, FAE presentó el mayor contenido de fenoles (65,49 mg EAG/g es) y FA de flavonoides (2,99 mg EQ/g es). El extracto obtenido por digestión (ED) presentó el menor rendimiento de extracción (0,48 mg/g), fenoles (13,67 mg EAG/g) y flavonoides (2,43 mg EQ/g). Por otro lado, FAE mostró la mejor actividad DPPH• y FRAP (101,61 µg/mL y 31,34 mg EAA/g, respectivamente), y junto a ED la mejor capacidad de secuestrar el catión ABTS•+ (76,14 y 69,48 mg Trolox/g, respectivamente). Por último, FA y el antioxidante artificial BHT tuvieron los mejores tiempos de inducción en Rancimat sin presentar diferencias estadísticamente significativas entre ellas (13,165 y 13,365 horas). En general, el tegumento de soja presenta compuestos fenólicos y actividad antioxidante. La partición con solvente usando acetato de etilo es un método que permite el incremento del contenido de fenoles totales y la capacidad antioxidante de los extractos del tegumento. La digestión química del tegumento permitió obtener un extracto con capacidad antioxidante ABTS•+, y con contenidos intermedios de fenoles y flavonoides, en relación a los otros extractos.',
         style: [ 'html-p' ] } ],
    margin: [ 0, 5, 0, 10 ],
    style: [ 'html-p' ] } ]

but this, when added to pdfMake's content array, won't render the SVGS, everything would be rendered but the SVGs.

I tried playing around with this and found that if I take everything from the outside text: then the SVG formula will render but in its own row.

let docDefinition = {
	content: [
 [ { text:
          'La soja es uno de los cultivos con mayor importancia económica en Argentina. De su procesamiento industrial, el tegumento es separado y desechado o utilizado para nutrición animal. Sin embargo, ha demostrado ser una fuente de polifenoles, entre otros compuestos. El objetivo del trabajo fue determinar la composición química del tegumento de soja amarilla, el contenido de polifenoles, flavonoides y actividad antioxidante de diferentes extractos y fracciones purificadas. Se determinó la composición química proximal del tegumento y se obtuvieron cuatro extractos a partir del tegumento desengrasado: 1) Extracto crudo (EC): obtenido por maceración con una mezcla de etanol-agua (70:30 v/v); 2) Fracción de acetato de etilo (FAE): obtenida por partición del EC con acetato de etilo y agua; 3) Fracción acuosa (FA): separada de la partición anterior; y 4) Extracto de digestión (ED): obtenido por digestión química del tegumento extraído del proceso 1). Sobre cada extracto se determinó: rendimiento de extracción, contenido de fenoles y flavonoides, y capacidad antioxidante (DPPH•, ABTS•+, FRAP y Rancimat). Los datos se analizaron mediante ANOVA y test DGC ',
        },
       { svg:
          '<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="9.107ex" height="2.509ex" style="vertical-align: -0.671ex;" viewBox="0 -791.3 3921.2 1080.4" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-labelledby="MathJax-SVG-1-Title"><title id="MathJax-SVG-1-Title">\\alpha=0,05</title><defs aria-hidden="true"><path stroke-width="1" id="E1-MJMATHI-3B1" d="M34 156Q34 270 120 356T309 442Q379 442 421 402T478 304Q484 275 485 237V208Q534 282 560 374Q564 388 566 390T582 393Q603 393 603 385Q603 376 594 346T558 261T497 161L486 147L487 123Q489 67 495 47T514 26Q528 28 540 37T557 60Q559 67 562 68T577 70Q597 70 597 62Q597 56 591 43Q579 19 556 5T512 -10H505Q438 -10 414 62L411 69L400 61Q390 53 370 41T325 18T267 -2T203 -11Q124 -11 79 39T34 156ZM208 26Q257 26 306 47T379 90L403 112Q401 255 396 290Q382 405 304 405Q235 405 183 332Q156 292 139 224T121 120Q121 71 146 49T208 26Z"></path><path stroke-width="1" id="E1-MJMAIN-3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"></path><path stroke-width="1" id="E1-MJMAIN-30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"></path><path stroke-width="1" id="E1-MJMAIN-2C" d="M78 35T78 60T94 103T137 121Q165 121 187 96T210 8Q210 -27 201 -60T180 -117T154 -158T130 -185T117 -194Q113 -194 104 -185T95 -172Q95 -168 106 -156T131 -126T157 -76T173 -3V9L172 8Q170 7 167 6T161 3T152 1T140 0Q113 0 96 17Z"></path><path stroke-width="1" id="E1-MJMAIN-35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z"></path></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)" aria-hidden="true"> <use xlink:href="#E1-MJMATHI-3B1" x="0" y="0"></use> <use xlink:href="#E1-MJMAIN-3D" x="918" y="0"></use> <use xlink:href="#E1-MJMAIN-30" x="1974" y="0"></use> <use xlink:href="#E1-MJMAIN-2C" x="2475" y="0"></use><g transform="translate(2920,0)"> <use xlink:href="#E1-MJMAIN-30"></use> <use xlink:href="#E1-MJMAIN-35" x="500" y="0"></use></g></g></svg>',
		  fit: [50, 50],
         },
       { text:
          ' en InfoStat. El tegumento presentó 52,63% de carbohidratos, 10,88% de proteínas, 11,73% de materia grasa, 8,32% de cenizas y 16,43% de humedad. El desengrasado utilizando un equipo Soxhlet tuvo un rendimiento de 11,56%, y el desengrasado en frío de 11,82%, sin diferencias significativas. La extracción convencional (EC) presentó un rendimiento de 7,79 mg/g, contenido de polifenoles 35,71 mg EAG/g extracto seco y flavonoides 1,12 mg EQ/g. Las fracciones resultantes del proceso de partición (FAE y FA) mostraron diferencias significativas en sus rendimientos de extracción y contenidos de fenoles y flavonoides totales. FA contuvo mayor materia seca (7,83 mg/g) que FAE (0,15 mg/g). No obstante, FAE presentó el mayor contenido de fenoles (65,49 mg EAG/g es) y FA de flavonoides (2,99 mg EQ/g es). El extracto obtenido por digestión (ED) presentó el menor rendimiento de extracción (0,48 mg/g), fenoles (13,67 mg EAG/g) y flavonoides (2,43 mg EQ/g). Por otro lado, FAE mostró la mejor actividad DPPH• y FRAP (101,61 µg/mL y 31,34 mg EAA/g, respectivamente), y junto a ED la mejor capacidad de secuestrar el catión ABTS•+ (76,14 y 69,48 mg Trolox/g, respectivamente). Por último, FA y el antioxidante artificial BHT tuvieron los mejores tiempos de inducción en Rancimat sin presentar diferencias estadísticamente significativas entre ellas (13,165 y 13,365 horas). En general, el tegumento de soja presenta compuestos fenólicos y actividad antioxidante. La partición con solvente usando acetato de etilo es un método que permite el incremento del contenido de fenoles totales y la capacidad antioxidante de los extractos del tegumento. La digestión química del tegumento permitió obtener un extracto con capacidad antioxidante ABTS•+, y con contenidos intermedios de fenoles y flavonoides, en relación a los otros extractos.',
         } ],
	],
};

The above example renders the alpha formula but when I add the original result from this library the alpha formula will be blank

I can't understand what may be going wrong.

Width style parameter isn't correctly converted if it is a floating point number

Just noticed that floating point numbers are not correctly converted if used inside a style attribute. Instead a whitespace is inserted between predecimal and decimal.

For example

<img style="width:1051.45px" src="data:image/png;base64,iVBO..."/>

is being converted to:

[ { "image": "data:image/png;base64,iVBO...", "style": [ "html-img" ], "width": "1051 45" } ]

This results in pdfmake not being able to parse the width and detecting it as NaN.

Would be nice if this could be fixed, because otherwise I have to inspect the DOM myself and pre-fix my content before piping it into html-to-pdfmake. :)

Wrong url for pdfmake librairies

Hi! Just to let you know the src for pdfmake and vfs_fonts lead to a 404.

You need to update the Readme :

<script src='https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.66/pdfmake.min.js'></script> <script src='https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.66/vfs_fonts.min.js'></script>

Cheers!

Browser fails with [email protected]

Hi! I an absolutely new to both JavaScript and html-to-pdfmake.
I tried to run a html-to-pdfmake browser. It works nice with [email protected], but with last branch 0.2.0 it fails.
(I copied 0.2.0 files to my local HD and much simplified index.html. Initial run is OK, but when trying to refresh, it freezes. With 0.1.57 version it works normally.)

Parse CSS rules

How about parsing CSS so you can omit the styles property?

{
  content: [
    htmlToPdfmake(`
      <style>
        p {
          color: red;
          transition: margin-left 2s; /* Properties unknown to pdfmake are ignored */
        }
      </style>
      <p>hi</pi>
    `)
  ]
}

instead of

{
  content: [
    htmlToPdfmake(`
      <p>hi</pi>
    `)
  ],
  styles:{
     red:{
        color:'red'
     }
  }
}

Even better, in a browser environment:

const el = document.getElementById('my-element')
htmlToPdfmake(el)

where htmlToPdfmake traverses el and all of its children and reads their style properties and transforms them properly.

Does that make sense to you?

As a sidenote, I am somewhat confused why there is no way in any library or browser, to do a simple pdfBlob = window.printWithoutUserInteraction(). There are printing previews and the like in place for all browsers, but you cant utilize them with Javascript and without user interaction (?)

This repo is great, thanks for your efforts

<div> force Linebreaks

First of all: great work, it helped me so much already.

Now to the issue:
When using <div> instead of <p> tags, html-to-pdfmake forces a new line after every span.

Example with <div>:

<div>
	<span>hello</span><span>&nbsp;</span><span>world</span>
</div>

The result of html-to-pdfmake with this example:

[
  {
    "stack": [
      {
        "text": "hello",
        "style": [
          "html-span"
        ]
      },
      {
        "text": " ",
        "style": [
          "html-span"
        ]
      },
      {
        "text": "world",
        "style": [
          "html-span"
        ]
      }
    ],
    "style": [
      "html-div"
    ]
  }
]

Same example with <p>:

<p>
<span>hello</span><span>&nbsp;</span><span>world</span>
</p>

And the result:

[
  {
    "text": [
      {
        "text": "hello",
        "style": [
          "html-span",
          "html-p"
        ]
      },
      {
        "text": " ",
        "style": [
          "html-span",
          "html-p"
        ]
      },
      {
        "text": "world",
        "style": [
          "html-span",
          "html-p"
        ]
      }
    ],
    "margin": [
      0,
      5,
      0,
      10
    ],
    "style": [
      "html-p"
    ]
  }
]

The reason for this is that using a substructure in a div always creates a stack in the generated doc definition.

Style personalization

Hello
Nice work
How to personalize font style (Hx, ...), margin of elements (p, div, ...) ?
Can you add examples in documentation (H1 in red 24pt, p with margin-top 12pt, ...) ?
Thanks

Bold or Italic incorrect adds new line in pdf

Version: v.1.0.6

It seems that using mutiple tags translates poorly to pdfmake.

eg. if this data sent to html-to-pdfmake:

<ul><li> Excepturi quos <strong>accusantium</strong> autem impedit. </li></ul>

It gets printed in the pdf as three lines:

  • Excepturi quos
    accusantium
    autem impedit.

It should be:

  • Excepturi quos accusantium autem impedit.

background color in span

Hi

I've got an html span element with the background color set to initial:

This is results in a black background for the entire html content.

image

I want to override the 'initial' value to 'white' using the default style parameter for the htmlToPdfmake, but can't seem to do this for the span element.

image

Can you please recommend an approach?

Thanks

error parse table

ver 2.0.6

Uncaught (in promise) TypeError: cells.forEach is not a function parseElement http://127.0.0.1:8005/static/plugins/jsPDF-1.5.3/html-to-pdfmake.js?v=609:1 parseElement http://127.0.0.1:8005/static/plugins/jsPDF-1.5.3/html-to-pdfmake.js?v=609:1 parseElement http://127.0.0.1:8005/static/plugins/jsPDF-1.5.3/html-to-pdfmake.js?v=609:1 parseElement http://127.0.0.1:8005/static/plugins/jsPDF-1.5.3/html-to-pdfmake.js?v=609:1 parseElement http://127.0.0.1:8005/static/plugins/jsPDF-1.5.3/html-to-pdfmake.js?v=609:1 convertHtml http://127.0.0.1:8005/static/plugins/jsPDF-1.5.3/html-to-pdfmake.js?v=609:1 exports http://127.0.0.1:8005/static/plugins/jsPDF-1.5.3/html-to-pdfmake.js?v=609:1

<table id="table1" class="table-multi table table-striped table-bordered table1 dataTable" role="grid" style="width: 100%;" data-status="2" width="100%" cellspacing="0"> <thead> <tr role="row" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"><th rowspan="4" class="sorting_disabled" colspan="1" style="width: 216px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Наименование муниципального района (городского округа)</th><th rowspan="4" class="sorting_disabled" colspan="1" style="width: 237px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Площадь муниципального района (городского округа), км2 (тыс. км2)</th><th data-a-text-rotation="90" rowspan="4" class="sorting_disabled" colspan="1" style="width: 20px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Наименование участкового лесничества</th><th colspan="8" rowspan="1" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Площадь земель, на которых расположены леса</th><th data-a-text-rotation="90" rowspan="4" class="sorting_disabled" colspan="1" style="width: 20px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Лесистость территории, %</th><th colspan="3" rowspan="2" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Запас древесины</th><th colspan="2" rowspan="2" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Кроме того, площадь лесов, в отношении которых лесоустройство не проводилось</th><th rowspan="4" class="sorting_disabled" colspan="1" style="width: 94px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Всего площадь лесов</th></tr> <tr role="row" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"><th rowspan="3" data-a-text-rotation="90" class="sorting_disabled" colspan="1" style="width: 20px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">всего лесов, в отношении которых имеются материалы лесоустройства</th><th colspan="3" rowspan="1" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">в том числе по целевому назначению лесов</th><th rowspan="3" data-a-text-rotation="90" class="sorting_disabled" colspan="1" style="width: 20px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">лесные земли</th><th colspan="3" rowspan="1" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">в том числе занятые лесными насаждениями (покрытые лесной растительностью)</th></tr> <tr role="row" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"><th data-a-text-rotation="90" rowspan="2" class="sorting_disabled" colspan="1" style="width: 44px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">защитные</th><th data-a-text-rotation="90" rowspan="2" class="sorting_disabled" colspan="1" style="width: 44px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">эксплуатационные</th><th data-a-text-rotation="90" rowspan="2" class="sorting_disabled" colspan="1" style="width: 44px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">резервные</th><th data-a-text-rotation="90" rowspan="2" class="sorting_disabled" colspan="1" style="width: 22px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">всего</th><th colspan="2" rowspan="1" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">из них лесными насаждениями с преобладанием древесных пород</th><th data-a-text-rotation="90" rowspan="2" class="sorting_disabled" colspan="1" style="width: 20px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">общий</th><th colspan="2" rowspan="1" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">в том числе лесных насаждений с преобладанием древесных пород</th><th rowspan="2" class="sorting_disabled" colspan="1" style="width: 42px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Всего</th><th rowspan="2" class="sorting_disabled" colspan="1" style="width: 276px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">в том числе занятые лесными насаждениями (покрытые лесной растительностью)</th></tr> <tr role="row" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"><th data-a-text-rotation="90" class="sorting_disabled" rowspan="1" colspan="1" style="width: 118px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">хвойных</th><th data-a-text-rotation="90" class="sorting_disabled" rowspan="1" colspan="1" style="width: 118px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">твердолиственных</th><th data-a-text-rotation="90" class="sorting_disabled" rowspan="1" colspan="1" style="width: 109px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">хвойных</th><th data-a-text-rotation="90" class="sorting_disabled" rowspan="1" colspan="1" style="width: 109px;" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">твердолиственных</th></tr> <tr class="addmy" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">1</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">2</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">3</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">4</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">5</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">6</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">7</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">8</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">9</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">10</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">11</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">12</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">13</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">14</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">15</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">16</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">17</th><th class="text-center" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">18</th></tr></thead> <tbody><tr role="row" class="odd" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Белозерское</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">5398</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Конец-Слободское</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">675.0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">675.0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">472.0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">452</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">220</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"></td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">69.022</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">31.750</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">31.750</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"></td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"></td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">675.0</td></tr><tr role="row" class="even" data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Белозерское</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"></td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">Итого</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">675.0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">675.0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">472.0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">452</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">220</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">0</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"></td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">69.022</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">31.750</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">31.750</td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"></td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"></td><td data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman">675.0</td></tr></tbody> <tfoot><tr data-b-a-s="thin" data-a-h="center" data-a-wrap="true" data-f-name="Times New Roman"></tr></tfoot> </table>

PDF appears this space between <p></p> how do i fix it?

I have a little problem generating the PDF appears this space between

how do i fix it? I believe the error is being caused by the conversion when adding the margin: [0,5,0,10].
Thanks.

Code:

  {
    "stack": [
      {
        "text": [
          {
            "text": "Bem vindo Winicius Lima, ao seu mais novo ",
            "style": [
              "html-span",
              "html-p",
              "marginP"
            ]
          },
          {
            "text": "editor de petições,",
            "style": [
              "html-span",
              "html-strong",
              "html-p",
              "marginP"
            ],
            "bold": true
          },
          {
            "text": " onde toda a",
            "style": [
              "html-span",
              "html-p",
              "marginP"
            ]
          },
          {
            "text": " mágica ",
            "style": [
              "html-span",
              "html-em",
              "html-p",
              "marginP"
            ],
            "italics": true
          },
          {
            "text": "acontece. ",
            "style": [
              "html-span",
              "html-p",
              "marginP"
            ]
          }
        ],
        "margin": [
          0,
          5,
          0,
          10
        ],
        "style": [
          "html-p",
          "marginP"
        ],
        "_margin": [
          0,
          5,
          0,
          10
        ],
        "_inlines": [],
        "_minWidth": 52.34765625,
        "_maxWidth": 497.384765625,
        "positions": [
          {
            "pageNumber": 1,
            "pageOrientation": "portrait",
            "pageInnerHeight": 761.89,
            "pageInnerWidth": 475.28,
            "left": 60,
            "top": 45,
            "verticalRatio": 0.006562627150901049,
            "horizontalRatio": 0
          },
          {
            "pageNumber": 1,
            "pageOrientation": "portrait",
            "pageInnerHeight": 761.89,
            "pageInnerWidth": 475.28,
            "left": 60,
            "top": 59.0625,
            "verticalRatio": 0.02502001601281025,
            "horizontalRatio": 0
          }
        ],
        "resetXY": "fn()"
      },
      {
        "text": "Experimente, e não se esqueça de sugerir novas funcionalidades!",
        "style": [
          "html-span",
          "html-p",
          "marginP"
        ],
        "margin": [
          0,
          5,
          0,
          10
        ],
        "_margin": [
          0,
          5,
          0,
          10
        ],
        "_inlines": [],
        "_minWidth": 88.107421875,
        "_maxWidth": 346.740234375,
        "positions": [
          {
            "pageNumber": 1,
            "pageOrientation": "portrait",
            "pageInnerHeight": 761.89,
            "pageInnerWidth": 475.28,
            "left": 60,
            "top": 88.125,
            "verticalRatio": 0.06316528632742259,
            "horizontalRatio": 0
          }
        ],
        "resetXY": "fn()"
      },
      {
        "text": [
          {
            "text": "",
            "style": [
              "html-span",
              "html-span",
              "html-span",
              "html-p",
              "marginP"
            ]
          },
          {
            "text": "\n"
          }
        ],
        "style": [
          "html-span",
          "html-p",
          "marginP"
        ],
        "margin": [
          0,
          5,
          0,
          10
        ],
        "_margin": [
          0,
          5,
          0,
          10
        ],
        "_inlines": [],
        "_minWidth": 0,
        "_maxWidth": 0,
        "positions": [
          {
            "pageNumber": 1,
            "pageOrientation": "portrait",
            "pageInnerHeight": 761.89,
            "pageInnerWidth": 475.28,
            "left": 60,
            "top": 117.1875,
            "verticalRatio": 0.10131055664203494,
            "horizontalRatio": 0
          }
        ],
        "resetXY": "fn()"
      },
      {
        "text": "Winicius Lima.",
        "style": [
          "html-span",
          "html-blockquote"
        ],
        "_margin": null,
        "_inlines": [],
        "_minWidth": 45.087890625,
        "_maxWidth": 77.630859375,
        "positions": [
          {
            "pageNumber": 1,
            "pageOrientation": "portrait",
            "pageInnerHeight": 761.89,
            "pageInnerWidth": 475.28,
            "left": 60,
            "top": 141.25,
            "verticalRatio": 0.13289319980574624,
            "horizontalRatio": 0
          }
        ],
        "resetXY": "fn()"
      }
    ],
    "style": [
      "html-div"
    ],
    "_margin": null,
    "_minWidth": 88.107421875,
    "_maxWidth": 497.384765625,
    "positions": [
      {
        "pageNumber": 1,
        "pageOrientation": "portrait",
        "pageInnerHeight": 761.89,
        "pageInnerWidth": 475.28,
        "left": 60,
        "top": 45,
        "verticalRatio": 0.006562627150901049,
        "horizontalRatio": 0
      },
      {
        "pageNumber": 1,
        "pageOrientation": "portrait",
        "pageInnerHeight": 761.89,
        "pageInnerWidth": 475.28,
        "left": 60,
        "top": 59.0625,
        "verticalRatio": 0.02502001601281025,
        "horizontalRatio": 0
      },
      {
        "pageNumber": 1,
        "pageOrientation": "portrait",
        "pageInnerHeight": 761.89,
        "pageInnerWidth": 475.28,
        "left": 60,
        "top": 88.125,
        "verticalRatio": 0.06316528632742259,
        "horizontalRatio": 0
      },
      {
        "pageNumber": 1,
        "pageOrientation": "portrait",
        "pageInnerHeight": 761.89,
        "pageInnerWidth": 475.28,
        "left": 60,
        "top": 117.1875,
        "verticalRatio": 0.10131055664203494,
        "horizontalRatio": 0
      },
      {
        "pageNumber": 1,
        "pageOrientation": "portrait",
        "pageInnerHeight": 761.89,
        "pageInnerWidth": 475.28,
        "left": 60,
        "top": 141.25,
        "verticalRatio": 0.13289319980574624,
        "horizontalRatio": 0
      }
    ],
    "resetXY": "fn()"
  }
]

Multilevel list type

Hi,

Can you help me, I want to achieve something like this
image

my html

<ul style="list-style-type: square;"">
 <li>First</li>
 <li>Second
 <ul style="list-style-type: lower-roman;">
  <li>Sub of Second</li>
  <li>Another Sub</li>
 </ul>
 </li>
 <li>Third</li>
 <li>Fourth</li>
</ul>

Thanks

`data-pdfmake` with table

I can't repeat this example:

<div data-pdfmake="{&quot;layout&quot;:&quot;noBorders&quot;}">
    <table><tr><td>Hello</td><td>World</td></tr></table>
 </div>

In the log I get the following code:

[
  { text: '', style: [] },
  { nodeName: 'DIV', stack: [ [Object] ], layout: 'noBorders' }
]

Originally posted by @etoktaev in #26 (comment)

Mathjax SVG not being converted well to PDFMAKE objects.

I have this code I made to export a database of scientific articles to pdf, it has formulas from mathjax that use latex. Mathjax-node can convert their formulas to SVG. I made the code so it replaces all formulas from each article with svg, and then I would "pipe" each article through html-to-pdfmake to get the corresponding pdfmake objects and print a pdf. But each formula gets an empty value. Mathjax svgs work, on chrome but they seem to not be working on pdfmake. Maybe that is the problem?

Here is the code


let fonts = {
  Raleway: {
    normal: 'fonts/Raleway/Raleway-Regular.ttf',
    bold: 'fonts/Raleway/Raleway-Bold.ttf',
    italics: 'fonts/Raleway/Raleway-Italic.ttf',
    bolditalics: 'fonts/Raleway/Raleway-MediumItalic.ttf',
  },
  Roboto: {
    normal: 'fonts/Roboto/Roboto-Regular.ttf',
    bold: 'fonts/Roboto/Roboto-Bold.ttf',
    italics: 'fonts/Roboto/Roboto-Italic.ttf',
    bolditalics: 'fonts/Roboto/Roboto-MediumItalic.ttf',
  },
  Baskervville: {
   normal: 'fonts/Baskervville/Baskervville-Regular.ttf',
   italics: 'fonts/Baskervville/Baskervville-Italic.ttf',
  },
  Caslon: { 
  normal:'fonts/Caslon/LibreCaslonText-Regular.ttf',
  italics:'fonts/Caslon/LibreCaslonText-Italic.ttf',
  bold:'fonts/Caslon/LibreCaslonText-Bold.ttf',
  bolditalics: 'fonts/Caslon/LibreCaslonText-Bold.ttf',
  }
};

let docDefinition = {
  pageSize: 'A4',
  pageMargins: [ 70, 105, 70, 50 ],
  header: {
  image: 'images/logo50anosfinal.png', width: 100, height: 51,  alignment: 'center', margin: [0,20,0,0]
  },
  footer: function(currentPage, pageCount) { return {text: currentPage.toString(), alignment: 'right', margin: [ 70 , 0 ]} },  
 content: [],
 styles: { 
  title: {
    fontSize: 11,
    lineHeight: 1.1,	  
    font: 'Raleway',
	alignment: 'left',
	margin: [0,25,0,15]
  },
  authors: {
    fontSize: 9,
    font: 'Roboto',
	alignment: 'left',
	//margin: [0,0]
  },
  body: {
	 fontSize: 8,
	 alignment: 'justify',
     font: 'Roboto',
	 margin: [0,0,0,25] 
  },
  'html-h4':{
	  fontSize: 8,
	  font: 'Roboto',
	  bold:true
  }
 },
 defaultStyle: {
    font: 'Roboto',
	fontSize: 10,
	alignment: 'justify',
  }	
};

let options = {
  
};

const mjAPI = require("mathjax-node");

mjAPI.config({
  MathJax: {
    // traditional MathJax configuration
  }
});
mjAPI.start();

const mongoClient = require('mongodb').MongoClient;

const PdfPrinter = require('pdfmake');
const printer = new PdfPrinter(fonts);

const htmlToPdfmake = require("html-to-pdfmake");
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const { window } = new JSDOM("");

const fs = require('fs');

const connUrl = "mongodb://localhost:host:18909";

const client = new mongoClient(connUrl, {useUnifiedTopology:true});

mongoClient.connect(connUrl, function(err, db) {
  if (err) throw err;
  var dbo = db.db("cytallocal");
	
  var pipeline= [ { $lookup: { from:"areas", localField: "current.area", foreignField: "_id", as: "area" } },  { $lookup: { from:"payments", localField: "user", foreignField: "user", as: "payment" } }, { $lookup: { from:"users", localField: "user", foreignField: "_id", as: "userdata" } } ];

   dbo.collection("abstracts").aggregate(pipeline).toArray( async function(err, results) {
     if (err) throw err;
     let count = 0;  
     for (let result of results) {
        
       let statusDetail = getStatusDetail(result);
       if(statusDetail === "accredited") {
            
        
	     let title = result.current.title.toUpperCase(); 
		 let absBody = result.current.body;
		  let area = result.area[0].name; 
     	 let authors = result.current.authors;
         let workplaces = result.current.workplaces;	 
          
	     docDefinition.content.push( { text: `${title}`, style: 'title', pageBreak:'before'});
	      
	   const authorsWithScripts = authors.map( (author, index) => { 
	      return toTitleCase(author) + superscripts[++ index] });
		 docDefinition.content.push({text:`${authorsWithScripts.join(', ')}\n\n\n`, style:'authors'});
		 let mathbody = await bodyMathreplacer(absBody);
		 console.log*mathbody);
		 let htmlSvgBody = htmlToPdfmake(mathbody, window);
		
	    
	     docDefinition.content.push(htmlSvgBody);  
	   }
        
     
     } 
   
    let pdfDoc = printer.createPdfKitDocument(docDefinition, options);
    pdfDoc.pipe(fs.createWriteStream( Date.now() + 'libro.pdf' ));
    pdfDoc.end();	   	   
    db.close();
  });
});
const getStatusDetail = (result) => {
if( result.payment.length  > 0 ) {
	
 return result.payment[0].status_detail ;
} else { return 'nada';}
}

const lastReview = (abstract) => {
  if (abstract.current.reviews.length) {
    return abstract.current.reviews[abstract.current.reviews.length - 1];
  }
  for (let i = abstract.prev.length; i > 0; --i) {
    if (abstract.prev[i - 1].reviews.length) {
      return abstract.prev[i - 1].reviews[abstract.prev[i - 1].reviews.length - 1];
    }
  }
};

const superscripts = {
      0: '\u2070',
      1: '\u00B9',
      2: '\u00B2',
      3: '\u00B3',
      4: '\u2074',
      5: '\u2075',
      6: '\u2076',
      7: '\u2077',
      8: '\u2078',
      9: '\u2079',
    };

const toTitleCase = (s) => s.toLowerCase().split(' ').map(word => word.charAt(0).toUpperCase() + word.substring(1)).join(' ');

const mathJaxToSVG = (formula) => {
  mjAPI.typeset({
  math: formula.substring(2, formula.length - 2),
  format: "TeX", // or "inline-TeX", "MathML"
  html:true,      // or svg:true, or html:true
}, function (data) {
  if (!data.errors) {
     console.log(data.html);	 
	 return data.html;	 
  }
});}


// An async replace function for javascript.
const asyncStringReplace = async (str, regex, aReplacer) => {
    const substrs = [];
    let match;
    let i = 0;
    while ((match = regex.exec(str)) !== null) {
        // put non matching string
        substrs.push(str.slice(i, match.index));
        // call the async replacer function with the matched array spreaded
        substrs.push(aReplacer(...match));
        i = regex.lastIndex;
    }
    // put the rest of str
    substrs.push(str.slice(i));
    // wait for aReplacer calls to finish and join them back into string
    return (await Promise.all(substrs)).join('');
};



// @body: the articlebody
//Replaces all formulas from the article body with mathjax generated SVGs.
const bodyMathreplacer = async body => {
   const regex = /\\\((.*?)\\\)/gm;
    return await asyncStringReplace(body, regex, async (body) => {
        return await mathJaxToSVG(body);
    });
};

"HR" misbehave on re-render...

I'm using your awesome script with React.js.
The issue I encountered is with the <hr /> element.

Background:
I've setup a button that will generate a PDF from some content, the issue is that if you click the button multiple times, basically to generate the same report multiple times the <hr /> keeps adding all this spacing above and to the right of it and with each newly generated instance the gaps are getting bigger.

Here's some code snippet to try to reproduce this:

const html = htmlToPdfmake(`
    <div>
      <h1>My title</h1>
      <p>
        This is some example content...
      </p>
      <hr />
    </div>`);

  const docDefinition = {
    content: [
      html,
    ]
  };

  const pdfDocGenerator = () => {
    pdfMake.createPdf(docDefinition).open();
  };

  return (
    <Button onClick={pdfDocGenerator}>Open PDF</Button>
  );

Here's some screenshots to demonstrate the issue.

First open:

image

Second open:

image

Third open:

image

and so on...
Thanks

Multiple text decoration values are not inherited

When parsing an html string with multiple text decorations, only the last one is being applied to the child.

Sample input:
<p><u><s>Test</s></u></p>

Expected Result:
The "Test" text has both strikethrough and underline styles applied to it.

Actual Result:
Only the strikethrough (lineThrough) decoration is applied to the element.

[
  {
    "text": [
      {
        "text": [
          {
            "text": "Test",
            "nodeName": "S",
            "decoration": "lineThrough",
            "style": [
              "html-s",
              "html-u",
              "html-p"
            ]
          }
        ],
        "nodeName": "U",
        "decoration": "underline",
        "style": [
          "html-u",
          "html-p"
        ]
      }
    ],
    "nodeName": "P",
    "margin": [
      0,
      5,
      0,
      10
    ],
    "style": [
      "html-p"
    ]
  }
]

The PDFMake docs say that the decoration property should be a string, but string[] is also being parsed correctly and applies multiple decorations to an element.

I'm not sure if this is a PDFMake style inheritance issue or if this is something that could be fixed by traversing the elements tree and merging the decoration props into an array in html-to-pdfmake.

Text align and Italic

It does not handle text-align style and <em> tag:

< p style="text-align: center;"> <span style="font-size: 14px;"><em><strong>testing...</strong></em></span> < /p>

result:

{ "text":"testing...", "bold":true, "style":["html-strong","html-em","html-span","html-p"] }

Tag class name as style

I have the following html string with class names:

<span class="fr-img-caption fr-fic fr-dib" style="width: 166px;">
  <span class="fr-img-wrap">
    <img src="...base64string">
    <span class="fr-inner">Image tag</span>
  </span>
</span>

output:

[
  {
    "stack": [
      {
        "image": "...base64string",
        "style": [
          "html-img"
        ]
      },
      {
        "text": "Image tag",
        "style": [
          "fr-inner", // span class
          "html-span"
        ]
      }
    ],
    "style": [
      "html-span",
      "html-span"
      // class was not inserted here
    ]
  }
]

The last span tag has 'fr-inner' inside his style array, but the parent ones do not. Is it possible to insert these class names inside their style array?

ol lists not restarting numbering on sub items

when I switch my lists over to ordered lists the numbering doesn't reset for each sublist. Example from our UI:
Screen Shot 2019-09-23 at 3 18 23 PM
Example output from html-to-pdfmake
Screen Shot 2019-09-23 at 3 18 14 PM

I'm unable to output the code being passed to pdfmake because I get an error when I convert to ordered lists

stringify.js:4 Uncaught (in promise) TypeError: Converting circular structure to JSON
--> starting at object with constructor 'r'
| property '_root' -> object with constructor 'n'
--- property 'document' closes the circle
at Object.stringify ()
at stringify (stringify.js:4)
at VueComponent._callee$ (VisitNote.vue?5ab0890e:241)
at tryCatch (runtime.js:62)
at Generator.invoke [as _invoke] (runtime.js:296)
at Generator.prototype. [as next] (runtime.js:114)
at step (asyncToGenerator.js:17)
at asyncToGenerator.js:35
at new Promise ()
at new F (_export.js:36)

here is a part of the code of what is being passed to pdfmake when the list is unordered
{
"ul": [
{
"text": "hjk",
"style": ["html-li"],
"_margin": [5, 0, 0, 0],
"_inlines": [],
"_minWidth": 20.556640625,
"_maxWidth": 20.556640625,
"listMarker": {
"canvas": [
{
"x": 27,
"y": 137.0859375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 37.8671875,
"top": 129.953125,
"verticalRatio": 0.0754578927492447,
"horizontalRatio": 0.031236341783216784
}
]
}, {
"text": "lk",
"style": ["ql-indent-1", "html-li"],
"_margin": [25, 0, 0, 0],
"_inlines": [],
"_minWidth": 33.994140625,
"_maxWidth": 33.994140625,
"listMarker": {
"canvas": [
{
"x": 47,
"y": 151.1484375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 57.8671875,
"top": 144.015625,
"verticalRatio": 0.09670033987915408,
"horizontalRatio": 0.06620137674825174
}
]
}, {
"text": "sflkf",
"style": ["ql-indent-2", "html-li"],
"_margin": [45, 0, 0, 0],
"_inlines": [],
"_minWidth": 68.25,
"_maxWidth": 68.25,
"listMarker": {
"canvas": [
{
"x": 67,
"y": 165.2109375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 77.8671875,
"top": 158.078125,
"verticalRatio": 0.11794278700906344,
"horizontalRatio": 0.10116641171328672
}
]
}, {
"text": "lkfjsdf",
"style": ["ql-indent-3", "html-li"],
"_margin": [65, 0, 0, 0],
"_inlines": [],
"_minWidth": 98.146484375,
"_maxWidth": 98.146484375,
"listMarker": {
"canvas": [
{
"x": 87,
"y": 179.2734375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 97.8671875,
"top": 172.140625,
"verticalRatio": 0.1391852341389728,
"horizontalRatio": 0.13613144667832167
}
]
}, {
"text": "kldfsj",
"style": ["ql-indent-4", "html-li"],
"_margin": [85, 0, 0, 0],
"_inlines": [],
"_minWidth": 113.98046875,
"_maxWidth": 113.98046875,
"listMarker": {
"canvas": [
{
"x": 107,
"y": 193.3359375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 117.8671875,
"top": 186.203125,
"verticalRatio": 0.16042768126888218,
"horizontalRatio": 0.17109648164335664
}
]
}, {
"text": "dkslfjl",
"style": ["ql-indent-5", "html-li"],
"_margin": [105, 0, 0, 0],
"_inlines": [],
"_minWidth": 136.892578125,
"_maxWidth": 136.892578125,
"listMarker": {
"canvas": [
{
"x": 127,
"y": 207.3984375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 137.8671875,
"top": 200.265625,
"verticalRatio": 0.18167012839879154,
"horizontalRatio": 0.20606151660839161
}
]
}, {
"text": "ksdflj",
"style": ["ql-indent-6", "html-li"],
"_margin": [125, 0, 0, 0],
"_inlines": [],
"_minWidth": 153.716796875,
"_maxWidth": 153.716796875,
"listMarker": {
"canvas": [
{
"x": 147,
"y": 221.4609375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 157.8671875,
"top": 214.328125,
"verticalRatio": 0.2029125755287009,
"horizontalRatio": 0.24102655157342656
}
]
}, {
"text": "fskldj",
"style": ["ql-indent-7", "html-li"],
"_margin": [145, 0, 0, 0],
"_inlines": [],
"_minWidth": 173.98046875,
"_maxWidth": 173.98046875,
"listMarker": {
"canvas": [
{
"x": 167,
"y": 235.5234375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 177.8671875,
"top": 228.390625,
"verticalRatio": 0.22415502265861026,
"horizontalRatio": 0.27599158653846156
}
]
}, {
"text": "fdslka",
"style": ["ql-indent-8", "html-li"],
"_margin": [165, 0, 0, 0],
"_inlines": [],
"_minWidth": 197.501953125,
"_maxWidth": 197.501953125,
"listMarker": {
"canvas": [
{
"x": 187,
"y": 249.5859375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 197.8671875,
"top": 242.453125,
"verticalRatio": 0.24539746978851965,
"horizontalRatio": 0.3109566215034965
}
]
}, {
"text": "nine",
"style": ["ql-indent-8", "html-li"],
"_margin": [165, 0, 0, 0],
"_inlines": [],
"_minWidth": 187.51171875,
"_maxWidth": 187.51171875,
"listMarker": {
"canvas": [
{
"x": 187,
"y": 263.6484375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 197.8671875,
"top": 256.515625,
"verticalRatio": 0.266639916918429,
"horizontalRatio": 0.3109566215034965
}
]
}, {
"text": "klj",
"style": ["html-li"],
"_margin": [5, 0, 0, 0],
"_inlines": [],
"_minWidth": 16.859375,
"_maxWidth": 16.859375,
"listMarker": {
"canvas": [
{
"x": 27,
"y": 277.7109375,
"r1": 2,
"r2": 2,
"type": "ellipse",
"color": "black"
}
],
"_maxWidth": 12.8671875,
"_minWidth": 12.8671875,
"_maxHeight": 14.0625,
"_minHeight": 14.0625
},
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 37.8671875,
"top": 270.578125,
"verticalRatio": 0.2878823640483384,
"horizontalRatio": 0.031236341783216784
}
]
}
],
"style": ["html-ul"],
"marginBottom": 5,
"_margin": [0, 0, 0, 5],
"type": "disc",
"_gapSize": {
"width": 12.8671875,
"height": 14.0625,
"fontSize": 12,
"lineHeight": 1,
"ascender": 11.1328125,
"descender": -2.9296875
},
"_minWidth": 210.369140625,
"_maxWidth": 210.369140625,
"positions": [
{
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 37.8671875,
"top": 129.953125,
"verticalRatio": 0.0754578927492447,
"horizontalRatio": 0.031236341783216784
}, {
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 57.8671875,
"top": 144.015625,
"verticalRatio": 0.09670033987915408,
"horizontalRatio": 0.06620137674825174
}, {
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 77.8671875,
"top": 158.078125,
"verticalRatio": 0.11794278700906344,
"horizontalRatio": 0.10116641171328672
}, {
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 97.8671875,
"top": 172.140625,
"verticalRatio": 0.1391852341389728,
"horizontalRatio": 0.13613144667832167
}, {
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 117.8671875,
"top": 186.203125,
"verticalRatio": 0.16042768126888218,
"horizontalRatio": 0.17109648164335664
}, {
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 137.8671875,
"top": 200.265625,
"verticalRatio": 0.18167012839879154,
"horizontalRatio": 0.20606151660839161
}, {
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 157.8671875,
"top": 214.328125,
"verticalRatio": 0.2029125755287009,
"horizontalRatio": 0.24102655157342656
}, {
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 177.8671875,
"top": 228.390625,
"verticalRatio": 0.22415502265861026,
"horizontalRatio": 0.27599158653846156
}, {
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 197.8671875,
"top": 242.453125,
"verticalRatio": 0.24539746978851965,
"horizontalRatio": 0.3109566215034965
}, {
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 197.8671875,
"top": 256.515625,
"verticalRatio": 0.266639916918429,
"horizontalRatio": 0.3109566215034965
}, {
"pageNumber": 1,
"pageOrientation": "portrait",
"pageInnerHeight": 662,
"pageInnerWidth": 572,
"left": 37.8671875,
"top": 270.578125,
"verticalRatio": 0.2878823640483384,
"horizontalRatio": 0.031236341783216784
}
]
}

probably a lot of unrelated cruft. One of the big things that I noticed was that html-to-pdfmake seems to rely on styles to indent some items. but when I check lists on the pdfmake sandbox http://pdfmake.org/playground.html the sublists items have their own ul or ol tags.

p inside td

Hi,

I'm having a styling problem with the following html. Can you please help me figure this out?

<table border="1">
<tr>
<td>
<p><p> </p></p><p>BEN VE AİLEM</p><p><p> </p></p><p><span style="color: rgb(91, 155, 213);">ICH UND MEINE FAMILIE</span></p><p><p> </p></p><p><span style="color: rgb(91, 155, 213);"> </span></p><p><p> </p></p><p>Tanışma</p><p><p> </p></p><p><span style="color: rgb(91, 155, 213);">Kennenlernen</span></p><p><p> </p></p><p><span style="color: rgb(84, 141, 212);"> </span></p>
</td>
</tr>
</table>

The problem also exists in the playground.

image

Header font size is not overridden

stack:[
    {
      text: 'My title h4',
      fontSize: 18,
      bold: true,
      marginBottom: 5,
      style: ['html-h4']
    },
]
const docDefinition = {
    content: [
        html
    ],
    styles: {
        'html-h4': {
            fontSize: 10,
            color: 'purple',
        },
    },
};

Color "purple" applied but font size not

Single column tables doesn't work

Hi and thanks for a nice project!

I was trying out your demo page when I noticed that single column tables does not work.
Example 1:

<table>
  <tr>
    <td>Single Cell</td>
  </tr>
</table>

This throws an error Uncaught TypeError: Cannot read property 'length' of undefined in docPrepocessor.js.
However, the problem seems to stem from the conversion from HTML to pdfMake code in index.js/parseElement function, inside the switch case for "table". When only one td is defined the stack property doesn't exist and the body array is not correctly filled.

Related to this and probably stemming from the same function is the following problem.
Example 2:

<table>
  <tr><td>ROW 1 Single Cell</td></tr>
  <tr><td>ROW 2 Single Cell</td></tr>
</table>

In this case the demo shows two cells but only on one row. Like this...

ROW 1 Single CellROW 2 Single Cell

Rowspan doesn't work when thead tbody tags are present in HTML

When HTML contains thead, tbody in table, Library fails to render PDF.

This Works (Example from unit test):

<table>
        <tr>
          <th>Col A</th>
          <th>Col B</th>
          <th>Col C</th>
          <th>Col D</th>
        </tr>
        <tr>
          <td>Cell A1</td>
          <td rowspan="2">
            Cell B1 & B2
          </td>
          <td>Cell C1</td>
          <td rowspan="2">
            Cell D1 & D2
          </td>
        </tr>
        <tr>
          <td>Cell A2</td>
          <td>Cell C2</td>
        </tr>
        <tr>
          <td>Cell A3</td>
          <td colspan="2">Cell B3 & C3</td>
          <td>Cell D3</td>
        </tr>
        <tr>
          <td rowspan="2" colspan="3">
            Cell A4 & A5 & B4 & B5 & C4 & C5
          </td>
          <td>Cell D4</td>
        </tr>
        <tr>
          <td>Cell D5</td>
        </tr>
  </table>

This doesn't Work:

<table>
    <thead>
        <tr>
          <th>Col A</th>
          <th>Col B</th>
          <th>Col C</th>
          <th>Col D</th>
        </tr>
    </thead>
    <tbody>
        <tr>
          <td>Cell A1</td>
          <td rowspan="2">
            Cell B1 & B2
          </td>
          <td>Cell C1</td>
          <td rowspan="2">
            Cell D1 & D2
          </td>
        </tr>
        <tr>
          <td>Cell A2</td>
          <td>Cell C2</td>
        </tr>
        <tr>
          <td>Cell A3</td>
          <td colspan="2">Cell B3 & C3</td>
          <td>Cell D3</td>
        </tr>
        <tr>
          <td rowspan="2" colspan="3">
            Cell A4 & A5 & B4 & B5 & C4 & C5
          </td>
          <td>Cell D4</td>
        </tr>
        <tr>
          <td>Cell D5</td>
        </tr>
    </tbody>
  </table>

It can be verified by entering Input as mentioned above at https://aymkdn.github.io/html-to-pdfmake/index.html

Cannot read property 'push' of undefined

Took me a while to track this down, but this somewhat useless but valid markup causes the function to crash with the subject message:

<table>
  <tr>
    <td><br /></td>
  </tr>
</table>

css object-fit not supported

i am trying to add object-fit:cover property to image style like this
<img style="width:200px;height:200px;object-fit:cover" src="'data:image/jpeg;base64,........'" >
but it does not take any effect.
Is object-fit css property supported or not

Server side error: "window is not defined"

Hi @Aymkdn,

Thank you for creating a very useful package.

I have successfully implemented the package client side, but I am struggling with implementation on the server side (nodejs) firebase cloud functions.

I receive the error "window is not defined" at runtime.

I assume it has something to do with the way I am importing the packages?

var pdfMake = require("pdfmake/build/pdfmake"); var pdfFonts = require("pdfmake/build/vfs_fonts"); pdfMake.vfs = pdfFonts.pdfMake.vfs; var htmlToPdfMake = require("html-to-pdfmake");

Can we include Video tags also?

I have videos in my HTML, but when I pass in here, it all omits the videos and doesn't provide in html collections. How can we include it?

Add fillcolor if TD have backgroundColor

Dear,

Congratulations for the initiative.
I don't know if it was the best solution, but it solved my problem.
I made the following change to the code to solve the background color problem in TD, as an example:

  <table data-pdfmake="{&quot;widths&quot;:[&quot;*&quot;]}">
     <tbody>
        <tr>
           <td style="background-color: #7a0000;">​​​​&#160;<strong style="color: #ffffff;">Objetivo</strong></td>
        </tr>
     </tbody>
  </table>

image

Table border issue

Hi
I am unable to delete table border.
I tried with normal inline css..
I given a class for the table and applied style for the created class as per the document. Still I am not able to remove border.
Can you please help me to sort this issue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.