Skip to content

Commit 7c555c7

Browse files
committed
Merge pull request #249 from danielhusar/master
Add support for lists in from html plugin, fixes #140
2 parents 583f101 + 57388f4 commit 7c555c7

File tree

2 files changed

+122
-69
lines changed

2 files changed

+122
-69
lines changed

jspdf.plugin.from_html.js

+53-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
44
* 2014 Juan Pablo Gaviria, https://github.com/juanpgaviria
55
* 2014 Diego Casorran, https://github.com/diegocr
6+
* 2014 Daniel Husar, https://github.com/danielhusar
67
*
78
* Permission is hereby granted, free of charge, to any person obtaining
89
* a copy of this software and associated documentation files (the
@@ -85,6 +86,16 @@
8586
return name;
8687
};
8788
ResolveUnitedNumber = function(css_line_height_string) {
89+
90+
//IE8 issues
91+
css_line_height_string = css_line_height_string === "auto" ? "0px" : css_line_height_string;
92+
if (css_line_height_string.indexOf("em") > -1 && !isNaN(Number(css_line_height_string.replace("em", "")))) {
93+
css_line_height_string = Number(css_line_height_string.replace("em", "")) * 18.719 + "px";
94+
}
95+
if (css_line_height_string.indexOf("pt") > -1 && !isNaN(Number(css_line_height_string.replace("pt", "")))) {
96+
css_line_height_string = Number(css_line_height_string.replace("pt", "")) * 1.333 + "px";
97+
}
98+
8899
var normal, undef, value;
89100
undef = void 0;
90101
normal = 16.00;
@@ -237,8 +248,9 @@
237248
OBJECT : 1,
238249
EMBED : 1
239250
};
251+
var listCount = 1;
240252
DrillForContent = function(element, renderer, elementHandlers) {
241-
var cn, cns, fragmentCSS, i, isBlock, l, px2pt, table2json;
253+
var cn, cns, fragmentCSS, i, isBlock, l, px2pt, table2json, cb;
242254
cns = element.childNodes;
243255
cn = void 0;
244256
fragmentCSS = GetCSS(element);
@@ -275,21 +287,51 @@
275287
margins: renderer.pdf.margins_doc
276288
});
277289
renderer.y = renderer.pdf.lastCellPos.y + renderer.pdf.lastCellPos.h + 20;
290+
} else if (cn.nodeName === "OL" || cn.nodeName === "UL") {
291+
listCount = 1;
292+
if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
293+
DrillForContent(cn, renderer, elementHandlers);
294+
}
295+
renderer.y += 10;
296+
} else if (cn.nodeName === "LI") {
297+
var temp = renderer.x;
298+
renderer.x += cn.parentNode.nodeName === "UL" ? 22 : 10;
299+
renderer.y += 3;
300+
if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
301+
DrillForContent(cn, renderer, elementHandlers);
302+
}
303+
renderer.x = temp;
278304
} else {
279305
if (!elementHandledElsewhere(cn, renderer, elementHandlers)) {
280306
DrillForContent(cn, renderer, elementHandlers);
281307
}
282308
}
283309
} else if (cn.nodeType === 3) {
284-
renderer.addText(cn.nodeValue, fragmentCSS);
310+
var value = cn.nodeValue;
311+
if (cn.nodeValue && cn.parentNode.nodeName === "LI") {
312+
if (cn.parentNode.parentNode.nodeName === "OL") {
313+
value = listCount++ + '. ' + value;
314+
} else {
315+
var fontPx = fragmentCSS["font-size"] * 16;
316+
var radius = 2;
317+
if(fontPx > 20){
318+
radius = 3;
319+
}
320+
cb = function(x, y){
321+
this.pdf.circle(x, y, radius, 'FD');
322+
};
323+
}
324+
}
325+
renderer.addText(value, fragmentCSS);
285326
} else if (typeof cn === "string") {
286327
renderer.addText(cn, fragmentCSS);
287328
}
288329
}
289330
i++;
290331
}
332+
291333
if (isBlock) {
292-
return renderer.setBlockBoundary();
334+
return renderer.setBlockBoundary(cb);
293335
}
294336
};
295337
images = {};
@@ -413,8 +455,8 @@
413455
font = this.pdf.internal.getFont(style["font-family"], style["font-style"]);
414456
return this.pdf.internal.write("/" + font.id, (defaultFontSize * style["font-size"]).toFixed(2), "Tf", "(" + this.pdf.internal.pdfEscape(text) + ") Tj");
415457
};
416-
Renderer.prototype.renderParagraph = function() {
417-
var blockstyle, defaultFontSize, fontToUnitRatio, fragments, i, l, line, lines, maxLineHeight, out, paragraphspacing_after, paragraphspacing_before, priorblockstype, styles;
458+
Renderer.prototype.renderParagraph = function(cb) {
459+
var blockstyle, defaultFontSize, fontToUnitRatio, fragments, i, l, line, lines, maxLineHeight, out, paragraphspacing_after, paragraphspacing_before, priorblockstype, styles, fontSize;
418460
fragments = PurgeWhiteSpace(this.paragraph.text);
419461
styles = this.paragraph.style;
420462
blockstyle = this.paragraph.blockstyle;
@@ -448,6 +490,7 @@
448490
while (i !== l) {
449491
if (line[i][0].trim()) {
450492
maxLineHeight = Math.max(maxLineHeight, line[i][1]["line-height"], line[i][1]["font-size"]);
493+
fontSize = line[i][1]["font-size"] * 7;
451494
}
452495
i++;
453496
}
@@ -462,11 +505,14 @@
462505
}
463506
this.y += maxLineHeight * fontToUnitRatio;
464507
}
508+
if (cb && typeof cb === "function") {
509+
cb.call(this, this.x - 9, this.y - fontSize/2);
510+
}
465511
out("ET", "Q");
466512
return this.y += paragraphspacing_after;
467513
};
468-
Renderer.prototype.setBlockBoundary = function() {
469-
return this.renderParagraph();
514+
Renderer.prototype.setBlockBoundary = function(cb) {
515+
return this.renderParagraph(cb);
470516
};
471517
Renderer.prototype.setBlockStyle = function(css) {
472518
return this.paragraph.blockstyle = css;

libs/polyfill.js

+69-62
Original file line numberDiff line numberDiff line change
@@ -99,26 +99,33 @@
9999
return dec;
100100
};
101101
}
102-
103-
if (!Array.prototype.map) {
104-
Array.prototype.map = function(fun /*, thisArg */) {
105-
if (this === void 0 || this === null || typeof fun !== "function")
102+
103+
if (!Array.prototype.map) {
104+
Array.prototype.map = function(fun /*, thisArg */) {
105+
if (this === void 0 || this === null || typeof fun !== "function")
106106
throw new TypeError();
107-
108-
var t = Object(this), len = t.length >>> 0, res = new Array(len);
109-
var thisArg = arguments.length > 1 ? arguments[1] : void 0;
110-
for (var i = 0; i < len; i++) {
111-
// NOTE: Absolute correctness would demand Object.defineProperty
112-
// be used. But this method is fairly new, and failure is
113-
// possible only if Object.prototype or Array.prototype
114-
// has a property |i| (very unlikely), so use a less-correct
115-
// but more portable alternative.
116-
if (i in t)
117-
res[i] = fun.call(thisArg, t[i], i, t);
107+
108+
var t = Object(this), len = t.length >>> 0, res = new Array(len);
109+
var thisArg = arguments.length > 1 ? arguments[1] : void 0;
110+
for (var i = 0; i < len; i++) {
111+
// NOTE: Absolute correctness would demand Object.defineProperty
112+
// be used. But this method is fairly new, and failure is
113+
// possible only if Object.prototype or Array.prototype
114+
// has a property |i| (very unlikely), so use a less-correct
115+
// but more portable alternative.
116+
if (i in t)
117+
res[i] = fun.call(thisArg, t[i], i, t);
118118
}
119-
120-
return res;
121-
};
119+
120+
return res;
121+
};
122+
}
123+
124+
125+
if(!Array.isArray) {
126+
Array.isArray = function(arg) {
127+
return Object.prototype.toString.call(arg) === '[object Array]';
128+
};
122129
}
123130

124131
if (!Array.prototype.forEach) {
@@ -135,55 +142,55 @@
135142
}
136143
};
137144
}
138-
139-
if (!Object.keys) {
140-
Object.keys = (function () {
145+
146+
if (!Object.keys) {
147+
Object.keys = (function () {
141148
'use strict';
142-
143-
var hasOwnProperty = Object.prototype.hasOwnProperty,
144-
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
145-
dontEnums = ['toString','toLocaleString','valueOf','hasOwnProperty',
146-
'isPrototypeOf','propertyIsEnumerable','constructor'],
149+
150+
var hasOwnProperty = Object.prototype.hasOwnProperty,
151+
hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
152+
dontEnums = ['toString','toLocaleString','valueOf','hasOwnProperty',
153+
'isPrototypeOf','propertyIsEnumerable','constructor'],
147154
dontEnumsLength = dontEnums.length;
148-
149-
return function (obj) {
150-
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
151-
throw new TypeError();
152-
}
155+
156+
return function (obj) {
157+
if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) {
158+
throw new TypeError();
159+
}
153160
var result = [], prop, i;
154-
155-
for (prop in obj) {
156-
if (hasOwnProperty.call(obj, prop)) {
157-
result.push(prop);
158-
}
161+
162+
for (prop in obj) {
163+
if (hasOwnProperty.call(obj, prop)) {
164+
result.push(prop);
165+
}
166+
}
167+
168+
if (hasDontEnumBug) {
169+
for (i = 0; i < dontEnumsLength; i++) {
170+
if (hasOwnProperty.call(obj, dontEnums[i])) {
171+
result.push(dontEnums[i]);
172+
}
173+
}
159174
}
160-
161-
if (hasDontEnumBug) {
162-
for (i = 0; i < dontEnumsLength; i++) {
163-
if (hasOwnProperty.call(obj, dontEnums[i])) {
164-
result.push(dontEnums[i]);
165-
}
166-
}
167-
}
168-
return result;
169-
};
170-
}());
175+
return result;
176+
};
177+
}());
171178
}
172179

173-
if (!String.prototype.trim) {
174-
String.prototype.trim = function () {
175-
return this.replace(/^\s+|\s+$/g, '');
176-
};
177-
}
178-
if (!String.prototype.trimLeft) {
179-
String.prototype.trimLeft = function() {
180-
return this.replace(/^\s+/g, "");
181-
};
182-
}
183-
if (!String.prototype.trimRight) {
184-
String.prototype.trimRight = function() {
185-
return this.replace(/\s+$/g, "");
186-
};
180+
if (!String.prototype.trim) {
181+
String.prototype.trim = function () {
182+
return this.replace(/^\s+|\s+$/g, '');
183+
};
184+
}
185+
if (!String.prototype.trimLeft) {
186+
String.prototype.trimLeft = function() {
187+
return this.replace(/^\s+/g, "");
188+
};
187189
}
188-
190+
if (!String.prototype.trimRight) {
191+
String.prototype.trimRight = function() {
192+
return this.replace(/\s+$/g, "");
193+
};
194+
}
195+
189196
})(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this);

0 commit comments

Comments
 (0)