Skip to content

Commit

Permalink
v2.5.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Aymkdn committed Oct 25, 2023
1 parent 3ccb775 commit 03ace6a
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 45 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ Examples:

If you use `html-to-pdfmake` **in a Web browser**, then you could just pass [the option `imagesByReference`](https://github.com/Aymkdn/html-to-pdfmake#imagesbyreference) with the value `true` and the images will be passed by references (starting from PDFMake v0.1.67).

Otherwise the `src` attribute must be a **base64 encoded content** (as describe in the [PDFMake documentation](https://pdfmake.github.io/docs/document-definition-object/images/)) or a reference ([see more here](https://github.com/Aymkdn/html-to-pdfmake/issues/109#issue-932953144)).
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](https://pdfmake.github.io/docs/document-definition-object/images/)) or a reference ([see more here](https://github.com/Aymkdn/html-to-pdfmake/issues/109#issue-932953144)).

You can check [this Stackoverflow question](https://stackoverflow.com/questions/934012/get-image-data-in-javascript/42916772#42916772) to know the different ways to get a base64 encoded content from an image.

Expand Down
2 changes: 1 addition & 1 deletion browser.js

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion docs/browser-2.4.26.js

This file was deleted.

1 change: 1 addition & 0 deletions docs/browser-2.5.0.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ <h1>HTML to PDFMake convertor</h1>
<div id="pdf_ie" style="display:none;padding:3em">The PDF file is sent to you for download. Use a modern browser (like Chrome or Firefox) to display the PDF in this page.</div>
</div>
</div>
<script src="browser-2.4.26.js"></script>
<script src="browser-2.5.0.js"></script>
<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.js"></script>
<script>
Expand Down
Binary file modified example.pdf
Binary file not shown.
68 changes: 28 additions & 40 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,55 +209,68 @@ function htmlToPdfMake(htmlText, options) {

switch(nodeName) {
case "TABLE":{
var rowIndex, cellIndex;
var rowIndex;
// the format for the table is table.body[[], [], …]
ret.table = {body:[]};

var tbodies = (ret.stack || ret.text);
if (Array.isArray(tbodies)) {
rowIndex = 0;
// Array with All Rows including THEAD
var allRows = [];
var hasRowSpan = false; // TRUE if we have some rowspan
// first round is to deal with colspan
// for each THEAD / TBODY
tbodies.forEach(function(tbody) {
// for each row
var rows = (tbody.stack || tbody.text);
if (Array.isArray(rows)) {
// Add rows to allRows
allRows = allRows.concat(rows);
rows.forEach(function(row) {
var cells = (row.stack || row.text);
// for each cell
if (Array.isArray(cells)) {
cellIndex = 0;
ret.table.body[rowIndex] = [];
cells.forEach(function(cell) {
ret.table.body[rowIndex].push(cell);

// do we have a colSpan?
// if yes, insert empty cells due to colspan
if (cell.colSpan>1) {
i = cell.colSpan;
// do we have a rowSpan in addition of the colSpan?
_this.setRowSpan({rows:allRows, cell:cell, rowIndex:rowIndex, cellIndex:cellIndex});
// insert an empty cell for each colspan
while (--i > 0) {
ret.table.body[rowIndex].push({text:''});
// keep adding empty cell due to rowspan
_this.setRowSpan({rows:allRows, cell:cell, rowIndex:rowIndex, cellIndex:cellIndex});
cellIndex++;
}
} else {
// do we have a rowSpan ?
_this.setRowSpan({rows:allRows, cell:cell, rowIndex:rowIndex, cellIndex:cellIndex});
}

cellIndex++;
// do we have a rowSpan ?
if (cell.rowSpan > 1) hasRowSpan=true;
});
rowIndex++;
}
});
}
});

if (hasRowSpan) {
// we go through all again, just to deal with rowspan
ret.table.body.forEach(function(row, rowIndex) {
// for each row
row.forEach(function(cell, cellIndex) {
// do we have a rowSpan?
if (cell.rowSpan>1) {
var len = cell.rowSpan;
var colspan = (cell.colSpan ? cell.colSpan : 1);
for (var i=1; i <= len-1; i++) {
if (ret.table.body[rowIndex+i]) {
while (colspan--) ret.table.body[rowIndex+i].splice(cellIndex, 0, {text:''});
} else {
// if we have an empty <tr></tr>
cell.rowSpan--;
}
}
}
})
});
}
}

delete ret.stack;
Expand Down Expand Up @@ -524,31 +537,6 @@ function htmlToPdfMake(htmlText, options) {
return false;
}

/**
* Add empty cells due to rowspan
*
* @param {Object} params
* @param {Array} rows
* @param {Object} cell
* @param {Number} rowIndex Current row index
* @param {Number} cellIndex Current cell index
*/
this.setRowSpan = function(params) {
var cells;
if (params.cell.rowSpan) {
var len = params.cell.rowSpan;
for (var i=1; i <= len-1; i++) {
cells = (params.rows[params.rowIndex+i].text || params.rows[params.rowIndex+i].stack);
if (cells) cells.splice(params.cellIndex, 0, {text:''});
else {
// if we have an empty <tr></tr> after a row with rowspan, then we need to remove rowSpan
// cf https://github.com/Aymkdn/html-to-pdfmake/issues/189
params.cell.rowSpan--;
}
}
}
}

/**
* Apply style and classes from all the parents
*
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "html-to-pdfmake",
"version": "2.4.26",
"version": "2.5.0",
"description": "Convert HTML code to PDFMake",
"main": "index.js",
"scripts": {
Expand Down
15 changes: 15 additions & 0 deletions test/unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -1022,5 +1022,20 @@ test("unit tests", function(t) {
t.finish();
});

t.test("complex table with rowspan and colspan", function (t) {
var html = `<table><th colspan="3" rowspan="2">ABC</th><th colspan="13">DEF</th><th colspan="4" rowspan="2">GHI</th><th colspan="13">JKL</th></tr><tr><th colspan="10">123</th><th colspan="3">456</th><th colspan="10">789</th><th colspan="3">111</th></tr></table>`;
var ret = htmlToPdfMake(html, {window: window});
// [{"nodeName":"TABLE","marginBottom":5,"style":["html-table"],"table":{"body":[[{"text":"ABC","nodeName":"TH","bold":true,"fillColor":"#EEEEEE","style":["html-th","html-tr","html-tbody","html-table"],"rowSpan":2,"colSpan":3},{"text":""},{"text":""},{"text":"DEF","nodeName":"TH","bold":true,"fillColor":"#EEEEEE","style":["html-th","html-tr","html-tbody","html-table"],"colSpan":13},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":"GHI","nodeName":"TH","bold":true,"fillColor":"#EEEEEE","style":["html-th","html-tr","html-tbody","html-table"],"rowSpan":2,"colSpan":4},{"text":""},{"text":""},{"text":""},{"text":"JKL","nodeName":"TH","bold":true,"fillColor":"#EEEEEE","style":["html-th","html-tr","html-tbody","html-table"],"colSpan":13},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""}],[{"text":""},{"text":""},{"text":""},{"text":"123","nodeName":"TH","bold":true,"fillColor":"#EEEEEE","style":["html-th","html-tr","html-tbody","html-table"],"colSpan":10},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":"456","nodeName":"TH","bold":true,"fillColor":"#EEEEEE","style":["html-th","html-tr","html-tbody","html-table"],"colSpan":3},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":"789","nodeName":"TH","bold":true,"fillColor":"#EEEEEE","style":["html-th","html-tr","html-tbody","html-table"],"colSpan":10},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":""},{"text":"111","nodeName":"TH","bold":true,"fillColor":"#EEEEEE","style":["html-th","html-tr","html-tbody","html-table"],"colSpan":3},{"text":""},{"text":""}]]}}]
if (debug) console.log(JSON.stringify(ret));
t.check(Array.isArray(ret) && ret.length === 1, "return is OK");
ret = ret[0];
t.check(ret.table && ret.table.body, "table.body is here");
t.check(Array.isArray(ret.table.body) && ret.table.body.length===2, "table has 2 rows");
t.check(Array.isArray(ret.table.body[0]) && ret.table.body[0].length===33 && Array.isArray(ret.table.body[1]) && ret.table.body[1].length===33, "each row has 33 cells");
t.check(ret.table.body[0][0].text==="ABC" && ret.table.body[0][2].text==="" && ret.table.body[0][6].text==="" && ret.table.body[0][16].text==="GHI" && ret.table.body[0][19].text==="" && ret.table.body[0][21].text==="" && ret.table.body[0][24].text==="", "row #0 is OK");
t.check(ret.table.body[1][0].text==="" && ret.table.body[1][5].text==="" && ret.table.body[1][6].text==="" && ret.table.body[1][13].text==="456" && ret.table.body[1][19].text==="" && ret.table.body[1][21].text==="" && ret.table.body[1][30].text==="111", "row #1 is OK");
t.finish();
});

t.finish();
})

0 comments on commit 03ace6a

Please sign in to comment.