diff --git a/doc/plugins/from_html.md b/doc/plugins/from_html.md
new file mode 100644
index 000000000..ad7468e77
--- /dev/null
+++ b/doc/plugins/from_html.md
@@ -0,0 +1,43 @@
+
+
+# from_html Plugin CSS Support
+This document lists the CSS styles supported by the from_html jsPDF plugin.
+Each style indicates restrictions and issues.
+This file is intended for development purposes and may not be up to date.
+Refer to the source code for the lastest developments.
+
+# Implemented
+
+* margin
+* margin-top
+* margin-right
+* margin-left
+* margin-bottom
+* padding
+* padding-top
+* padding-right
+* padding-left
+* padding-bottom
+* font-family
+* font-style
+* text-align
+* font-size
+* line-height
+* display
+* float
+* clear
+* page-break-before
+> Only _always_ is implemented.
+
+# Implemented But Not Merged
+* color
+
+# Not Implemented
+* page-break-after
\ No newline at end of file
diff --git a/jspdf.plugin.from_html.js b/jspdf.plugin.from_html.js
index 79395fcd9..9142c27f9 100644
--- a/jspdf.plugin.from_html.js
+++ b/jspdf.plugin.from_html.js
@@ -212,6 +212,8 @@
css["padding-left"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-left")) || 0;
css["padding-right"] = tmp && ResolveUnitedNumber(computedCSSElement("padding-right")) || 0;
+ css["page-break-before"] = computedCSSElement("page-break-before") || "auto";
+
//float and clearing of floats
css["float"] = FloatMap[computedCSSElement("cssFloat")] || "none";
css["clear"] = ClearMap[computedCSSElement("clear")] || "none";
@@ -838,6 +840,12 @@
paragraphspacing_after = ((blockstyle["margin-bottom"] || 0) + (blockstyle["padding-bottom"] || 0)) * fontToUnitRatio;
this.priorMarginBottom = blockstyle["margin-bottom"] || 0;
+ if (blockstyle['page-break-before'] === 'always'){
+ this.pdf.addPage();
+ this.y = 0;
+ paragraphspacing_before = ((blockstyle["margin-top"] || 0) + (blockstyle["padding-top"] || 0)) * fontToUnitRatio;
+ }
+
out = this.pdf.internal.write;
i = void 0;
l = void 0;
diff --git a/test/test_from_html_css_page_breaks.html b/test/test_from_html_css_page_breaks.html
new file mode 100644
index 000000000..dd62b69c7
--- /dev/null
+++ b/test/test_from_html_css_page_breaks.html
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+Test HTML
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/test_harness.js b/test/test_harness.js
new file mode 100644
index 000000000..b95456939
--- /dev/null
+++ b/test/test_harness.js
@@ -0,0 +1,147 @@
+onload = function() {
+
+ var harness = new pdf_test_harness();
+
+ var body = document.getElementsByTagName('body')[0];
+ body.style.display = 'flex';
+
+ var div = document.createElement('div');
+ div.setAttribute('style', 'position:fixed;height:20px;left:0;right:0;background:lightblue');
+ body.appendChild(div);
+ harness.header = div;
+
+ var div2 = document.createElement('div');
+ div2.setAttribute('style', 'position:fixed;display:flex;top:20px; bottom:0;left:0;right:0');
+ body.appendChild(div2);
+ harness.body = div2;
+
+ var btn1 = document.createElement('input');
+ btn1.setAttribute('type', 'radio');
+ btn1.setAttribute('name', 'view');
+ div.appendChild(btn1);
+ btn1.checked = true;
+
+ var lbl1 = document.createElement('label');
+ lbl1.setAttribute('for', 'btn1');
+ lbl1.innerHTML = 'PDF'
+ div.appendChild(lbl1);
+
+ var btn2 = document.createElement('input');
+ btn2.setAttribute('type', 'radio');
+ btn2.setAttribute('name', 'view');
+ div.appendChild(btn2);
+
+ var lbl2 = document.createElement('label');
+ lbl2.setAttribute('for', 'btn2');
+ lbl2.innerHTML = 'Source'
+ div.appendChild(lbl2);
+
+ var btn3 = document.createElement('input');
+ btn3.setAttribute('type', 'radio');
+ btn3.setAttribute('name', 'view');
+ div.appendChild(btn3);
+
+ var lbl3 = document.createElement('label');
+ lbl3.setAttribute('for', 'btn3');
+ lbl3.innerHTML = 'Both'
+ div.appendChild(lbl3);
+
+ harness.source = document.createElement('pre');
+ harness.source.setAttribute('style', 'margin-top:0;width:100%;height:100%;position:absolute;top:0px;bottom:0px;overflow:auto');
+ div2.appendChild(harness.source);
+
+ harness.iframe = document.createElement('iframe');
+ harness.iframe.setAttribute('style', 'width:100%;height:100%;position:absolute;overflow:auto;top:0px;bottom:0px');
+ div2.appendChild(harness.iframe);
+
+ if (pdf_test_harness.onload) {
+ harness.pdf = pdf_test_harness.onload(harness);
+ if (harness.message){
+ var popup = document.createElement('div');
+ popup.setAttribute('style', 'position:fixed;margin:auto;top:50px;background-color:beige;padding:1em;border:1px solid black');
+ popup.innerHTML = harness.message;
+ body.appendChild(popup);
+ popup.onclick = function(){
+ popup.parentNode.removeChild(popup);
+ }
+
+ }
+ }
+
+ harness.render('pdf');
+
+ btn1.onclick = function() {
+ harness.render('pdf');
+ }
+ btn2.onclick = function() {
+ harness.render('source');
+ }
+ btn3.onclick = function() {
+ harness.render('both');
+ }
+}
+
+pdf_test_harness = function(pdf) {
+ this.pdf = pdf;
+ this.onload = undefined;
+ this.iframe = undefined;
+
+ this.entityMap = {
+ "&" : "&",
+ "<" : "<",
+ ">" : ">",
+ '"' : '"',
+ "'" : ''',
+ "/" : '/'
+ };
+
+ this.escapeHtml = function(string) {
+ return String(string).replace(/[&<>"'\/]/g, function(s) {
+ return this.entityMap[s];
+ }.bind(this));
+ };
+
+ this.getParameterByName = function(name) {
+ name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
+ var regex = new RegExp("[\\?&]" + name + "=([^]*)"), results = regex.exec(location.search);
+ return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
+ };
+
+ this.setPdf = function(pdf) {
+ this.pdf = pdf;
+ this.rendered = undefined;
+ this.render(this.view);
+ };
+
+ // generate the pdf, the source code, or both
+ this.render = function(view) {
+ this.view = view;
+ //Current code only lets us render one time.
+ if (!this.rendered) {
+ this.rendered = this.pdf.output('datauristring');
+ this.iframe.src = this.rendered;
+ var raw = this.pdf.output();
+ raw = this.escapeHtml(raw);
+ this.source.innerHTML = raw;
+ }
+ if ('pdf' === view) {
+ this.source.style.display = 'none';
+ this.iframe.style.display = 'block';
+ this.iframe.style.width = '100%';
+ } else if ('source' === view) {
+ this.iframe.style.display = 'none';
+ this.source.style.display = 'block';
+ this.source.style.width = '100%';
+ }
+
+ if ('both' === view) {
+ raw = this.escapeHtml(raw);
+ this.iframe.style.width = '50%';
+ this.iframe.style.position = 'relative';
+ this.iframe.style.display = 'inline-block';
+ this.source.style.width = '50%';
+ this.source.style.position = 'relative';
+ this.source.style.display = 'inline-block';
+ }
+ }
+}
\ No newline at end of file