pdfmake 0.1.65 → 0.1.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,69 +1,74 @@
1
- {
2
- "name": "pdfmake",
3
- "version": "0.1.65",
4
- "description": "Client/server side PDF printing in pure JavaScript",
5
- "main": "src/printer.js",
6
- "browser": "build/pdfmake.js",
7
- "directories": {
8
- "test": "tests"
9
- },
10
- "dependencies": {
11
- "iconv-lite": "^0.5.1",
12
- "linebreak": "^1.0.2",
13
- "pdfkit": "^0.11.0",
14
- "svg-to-pdfkit": "^0.1.8"
15
- },
16
- "devDependencies": {
17
- "@babel/core": "^7.8.4",
18
- "@babel/plugin-transform-modules-commonjs": "^7.8.3",
19
- "@babel/preset-env": "^7.8.4",
20
- "babel-loader": "^8.0.6",
21
- "brfs": "^2.0.2",
22
- "eslint-plugin-jsdoc": "^21.0.0",
23
- "expose-loader": "^0.7.5",
24
- "fancy-log": "^1.3.3",
25
- "file-saver": "^2.0.2",
26
- "gulp": "^4.0.2",
27
- "gulp-each": "^0.5.0",
28
- "gulp-eslint": "^6.0.0",
29
- "gulp-file-contents-to-json": "^0.2.2",
30
- "gulp-spawn-mocha": "^6.0.0",
31
- "mocha": "^7.0.1",
32
- "rewire": "^4.0.1",
33
- "sinon": "^8.1.1",
34
- "string-replace-webpack-plugin": "^0.1.3",
35
- "transform-loader": "^0.2.4",
36
- "uglifyjs-webpack-plugin": "^2.2.0",
37
- "webpack": "^4.41.5"
38
- },
39
- "scripts": {
40
- "build": "gulp build",
41
- "test": "gulp",
42
- "playground": "node dev-playground/server.js"
43
- },
44
- "repository": {
45
- "type": "git",
46
- "url": "git://github.com/bpampuch/pdfmake.git"
47
- },
48
- "keywords": [
49
- "pdf",
50
- "javascript",
51
- "printing",
52
- "layout"
53
- ],
54
- "author": "Bartek Pampuch <bartosz.pampuch@gmail.com>",
55
- "license": "MIT",
56
- "bugs": {
57
- "url": "https://github.com/bpampuch/pdfmake/issues"
58
- },
59
- "homepage": "http://pdfmake.org",
60
- "config": {
61
- "blanket": {
62
- "pattern": "src",
63
- "data-cover-never": [
64
- "node_modules",
65
- "tests"
66
- ]
67
- }
68
- }
69
- }
1
+ {
2
+ "name": "pdfmake",
3
+ "version": "0.1.69",
4
+ "description": "Client/server side PDF printing in pure JavaScript",
5
+ "main": "src/printer.js",
6
+ "browser": "build/pdfmake.js",
7
+ "directories": {
8
+ "test": "tests"
9
+ },
10
+ "dependencies": {
11
+ "iconv-lite": "^0.6.2",
12
+ "linebreak": "^1.0.2",
13
+ "pdfkit": "^0.11.0",
14
+ "svg-to-pdfkit": "^0.1.8",
15
+ "xmldoc": "^1.1.2"
16
+ },
17
+ "devDependencies": {
18
+ "@babel/core": "^7.12.10",
19
+ "@babel/plugin-transform-modules-commonjs": "^7.12.1",
20
+ "@babel/preset-env": "^7.12.11",
21
+ "babel-loader": "^8.2.2",
22
+ "brfs": "^2.0.2",
23
+ "core-js": "^3.8.1",
24
+ "eslint-plugin-jsdoc": "^30.7.9",
25
+ "expose-loader": "^1.0.3",
26
+ "fancy-log": "^1.3.3",
27
+ "file-saver": "^2.0.5",
28
+ "gulp": "^4.0.2",
29
+ "gulp-each": "^0.5.0",
30
+ "gulp-eslint": "^6.0.0",
31
+ "gulp-file-contents-to-json": "^0.2.2",
32
+ "gulp-spawn-mocha": "^6.0.0",
33
+ "mocha": "7.2.0",
34
+ "rewire": "^5.0.0",
35
+ "sinon": "^9.2.2",
36
+ "string-replace-webpack-plugin": "^0.1.3",
37
+ "terser-webpack-plugin": "4.2.3",
38
+ "transform-loader": "^0.2.4",
39
+ "webpack": "^4.44.2"
40
+ },
41
+ "engines": {
42
+ "node": ">=8"
43
+ },
44
+ "scripts": {
45
+ "build": "gulp build",
46
+ "test": "gulp",
47
+ "playground": "node dev-playground/server.js"
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "git://github.com/bpampuch/pdfmake.git"
52
+ },
53
+ "keywords": [
54
+ "pdf",
55
+ "javascript",
56
+ "printing",
57
+ "layout"
58
+ ],
59
+ "author": "Bartek Pampuch <bartosz.pampuch@gmail.com>",
60
+ "license": "MIT",
61
+ "bugs": {
62
+ "url": "https://github.com/bpampuch/pdfmake/issues"
63
+ },
64
+ "homepage": "http://pdfmake.org",
65
+ "config": {
66
+ "blanket": {
67
+ "pattern": "src",
68
+ "data-cover-never": [
69
+ "node_modules",
70
+ "tests"
71
+ ]
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,88 @@
1
+ 'use strict';
2
+
3
+ // Internet Explorer polyfills
4
+ if (typeof window !== 'undefined' && !window.Promise) {
5
+ require('core-js/features/promise');
6
+ }
7
+ require('core-js/es/object/values');
8
+
9
+ var fetchUrl = function (url) {
10
+ return new Promise(function (resolve, reject) {
11
+ var xhr = new XMLHttpRequest();
12
+ xhr.open('GET', url, true);
13
+ xhr.responseType = 'arraybuffer';
14
+
15
+ xhr.onreadystatechange = function () {
16
+ if (xhr.readyState !== 4) {
17
+ return;
18
+ }
19
+
20
+ var ok = xhr.status >= 200 && xhr.status < 300;
21
+ if (!ok) {
22
+ setTimeout(function () {
23
+ reject(new TypeError('Failed to fetch (url: "' + url + '")'));
24
+ }, 0);
25
+ }
26
+ };
27
+
28
+ xhr.onload = function () {
29
+ var ok = xhr.status >= 200 && xhr.status < 300;
30
+ if (ok) {
31
+ resolve(xhr.response);
32
+ }
33
+ };
34
+
35
+ xhr.onerror = function () {
36
+ setTimeout(function () {
37
+ reject(new TypeError('Network request failed (url: "' + url + '")'));
38
+ }, 0);
39
+ };
40
+
41
+ xhr.ontimeout = function () {
42
+ setTimeout(function () {
43
+ reject(new TypeError('Network request failed (url: "' + url + '")'));
44
+ }, 0);
45
+ };
46
+
47
+ xhr.send();
48
+ });
49
+ };
50
+
51
+ function URLBrowserResolver(fs) {
52
+ this.fs = fs;
53
+ this.resolving = {};
54
+ }
55
+
56
+ URLBrowserResolver.prototype.resolve = function (url) {
57
+ if (!this.resolving[url]) {
58
+ var _this = this;
59
+ this.resolving[url] = new Promise(function (resolve, reject) {
60
+ if (url.toLowerCase().indexOf('https://') === 0 || url.toLowerCase().indexOf('http://') === 0) {
61
+ fetchUrl(url).then(function (buffer) {
62
+ _this.fs.writeFileSync(url, buffer);
63
+ resolve();
64
+ }, function (result) {
65
+ reject(result);
66
+ });
67
+ } else {
68
+ // cannot be resolved
69
+ resolve();
70
+ }
71
+ });
72
+ }
73
+
74
+ return this.resolving[url];
75
+ }
76
+
77
+ URLBrowserResolver.prototype.resolved = function () {
78
+ var _this = this;
79
+ return new Promise(function (resolve, reject) {
80
+ Promise.all(Object.values(_this.resolving)).then(function () {
81
+ resolve();
82
+ }, function (result) {
83
+ reject(result);
84
+ });
85
+ });
86
+ }
87
+
88
+ module.exports = URLBrowserResolver;
@@ -30,7 +30,7 @@ function canCreatePdf() {
30
30
  return true;
31
31
  }
32
32
 
33
- Document.prototype._createDoc = function (options) {
33
+ Document.prototype._createDoc = function (options, cb) {
34
34
  options = options || {};
35
35
  if (this.tableLayouts) {
36
36
  options.tableLayouts = this.tableLayouts;
@@ -41,9 +41,49 @@ Document.prototype._createDoc = function (options) {
41
41
  var printer = new PdfPrinter(this.fonts);
42
42
  require('fs').bindFS(this.vfs); // bind virtual file system to file system
43
43
 
44
- var doc = printer.createPdfKitDocument(this.docDefinition, options);
44
+ if (!isFunction(cb)) {
45
+ var doc = printer.createPdfKitDocument(this.docDefinition, options);
45
46
 
46
- return doc;
47
+ return doc;
48
+ }
49
+
50
+ var URLBrowserResolver = require('./URLBrowserResolver');
51
+ var urlResolver = new URLBrowserResolver(require('fs'));
52
+
53
+ for (var font in this.fonts) {
54
+ if (this.fonts.hasOwnProperty(font)) {
55
+ if (this.fonts[font].normal) {
56
+ urlResolver.resolve(this.fonts[font].normal);
57
+ }
58
+ if (this.fonts[font].bold) {
59
+ urlResolver.resolve(this.fonts[font].bold);
60
+ }
61
+ if (this.fonts[font].italics) {
62
+ urlResolver.resolve(this.fonts[font].italics);
63
+ }
64
+ if (this.fonts[font].bolditalics) {
65
+ urlResolver.resolve(this.fonts[font].bolditalics);
66
+ }
67
+ }
68
+ }
69
+
70
+ if (this.docDefinition.images) {
71
+ for (var image in this.docDefinition.images) {
72
+ if (this.docDefinition.images.hasOwnProperty(image)) {
73
+ urlResolver.resolve(this.docDefinition.images[image]);
74
+ }
75
+ }
76
+ }
77
+
78
+ var _this = this;
79
+
80
+ urlResolver.resolved().then(function () {
81
+ var doc = printer.createPdfKitDocument(_this.docDefinition, options);
82
+
83
+ cb(doc);
84
+ }, function (result) {
85
+ throw result;
86
+ });
47
87
  };
48
88
 
49
89
  Document.prototype._flushDoc = function (doc, callback) {
@@ -67,9 +107,12 @@ Document.prototype._getPages = function (options, cb) {
67
107
  if (!cb) {
68
108
  throw '_getPages is an async method and needs a callback argument';
69
109
  }
70
- var doc = this._createDoc(options);
71
- this._flushDoc(doc, function (ignoreBuffer, pages) {
72
- cb(pages);
110
+ var _this = this;
111
+
112
+ this._createDoc(options, function (doc) {
113
+ _this._flushDoc(doc, function (ignoreBuffer, pages) {
114
+ cb(pages);
115
+ });
73
116
  });
74
117
  };
75
118
 
@@ -203,15 +246,25 @@ Document.prototype.getBuffer = function (cb, options) {
203
246
  if (!cb) {
204
247
  throw 'getBuffer is an async method and needs a callback argument';
205
248
  }
206
- var doc = this._createDoc(options);
207
- this._flushDoc(doc, function (buffer) {
208
- cb(buffer);
249
+
250
+ var _this = this;
251
+
252
+ this._createDoc(options, function (doc) {
253
+ _this._flushDoc(doc, function (buffer) {
254
+ cb(buffer);
255
+ });
209
256
  });
210
257
  };
211
258
 
212
- Document.prototype.getStream = function (options) {
213
- var doc = this._createDoc(options);
214
- return doc;
259
+ Document.prototype.getStream = function (options, cb) {
260
+ if (!isFunction(cb)) {
261
+ var doc = this._createDoc(options);
262
+ return doc;
263
+ }
264
+
265
+ this._createDoc(options, function (doc) {
266
+ cb(doc);
267
+ });
215
268
  };
216
269
 
217
270
  module.exports = {
@@ -5,6 +5,12 @@ function VirtualFileSystem() {
5
5
  this.dataSystem = {};
6
6
  }
7
7
 
8
+ VirtualFileSystem.prototype.existsSync = function (filename) {
9
+ filename = fixFilename(filename);
10
+ return typeof this.fileSystem[filename] !== 'undefined'
11
+ || typeof this.dataSystem[filename] !== 'undefined';
12
+ }
13
+
8
14
  VirtualFileSystem.prototype.readFileSync = function (filename, options) {
9
15
  filename = fixFilename(filename);
10
16
 
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var fs = require('fs');
4
+
3
5
  function ImageMeasure(pdfKitDoc, imageDictionary) {
4
6
  this.pdfKitDoc = pdfKitDoc;
5
7
  this.imageDictionary = imageDictionary || {};
@@ -33,6 +35,10 @@ ImageMeasure.prototype.measureImage = function (src) {
33
35
  return src;
34
36
  }
35
37
 
38
+ if (fs.existsSync(img)) {
39
+ return fs.readFileSync(img);
40
+ }
41
+
36
42
  var index = img.indexOf('base64,');
37
43
  if (index < 0) {
38
44
  return that.imageDictionary[src];
package/src/printer.js CHANGED
@@ -207,6 +207,8 @@ function calculatePageHeight(pages, margins) {
207
207
  return item.item.getHeight();
208
208
  } else if (item.item._height) {
209
209
  return item.item._height;
210
+ } else if (item.type === 'vector') {
211
+ return item.item.y1 > item.item.y2 ? item.item.y1 : item.item.y2;
210
212
  } else {
211
213
  // TODO: add support for next item types
212
214
  return 0;
@@ -214,7 +216,7 @@ function calculatePageHeight(pages, margins) {
214
216
  }
215
217
 
216
218
  function getBottomPosition(item) {
217
- var top = item.item.y;
219
+ var top = item.item.y || 0;
218
220
  var height = getItemHeight(item);
219
221
  return top + height;
220
222
  }
@@ -406,6 +408,25 @@ function renderPages(pages, fontProvider, pdfKitDoc, progressCallback) {
406
408
  }
407
409
  }
408
410
 
411
+ /**
412
+ * Shift the "y" height of the text baseline up or down (superscript or subscript,
413
+ * respectively). The exact shift can / should be changed according to standard
414
+ * conventions.
415
+ *
416
+ * @param {number} y
417
+ * @param {any} inline
418
+ */
419
+ function offsetText(y, inline) {
420
+ var newY = y;
421
+ if (inline.sup) {
422
+ newY -= inline.fontSize * 0.75;
423
+ }
424
+ if (inline.sub) {
425
+ newY += inline.fontSize * 0.35;
426
+ }
427
+ return newY;
428
+ }
429
+
409
430
  function renderLine(line, x, y, pdfKitDoc) {
410
431
  function preparePageNodeRefLine(_pageNodeRef, inline) {
411
432
  var newWidth;
@@ -481,18 +502,20 @@ function renderLine(line, x, y, pdfKitDoc) {
481
502
 
482
503
  pdfKitDoc._font = inline.font;
483
504
  pdfKitDoc.fontSize(inline.fontSize);
484
- pdfKitDoc.text(inline.text, x + inline.x, y + shiftToBaseline, options);
505
+
506
+ var shiftedY = offsetText(y + shiftToBaseline, inline);
507
+ pdfKitDoc.text(inline.text, x + inline.x, shiftedY, options);
485
508
 
486
509
  if (inline.linkToPage) {
487
510
  var _ref = pdfKitDoc.ref({ Type: 'Action', S: 'GoTo', D: [inline.linkToPage, 0, 0] }).end();
488
- pdfKitDoc.annotate(x + inline.x, y + shiftToBaseline, inline.width, inline.height, {
511
+ pdfKitDoc.annotate(x + inline.x, shiftedY, inline.width, inline.height, {
489
512
  Subtype: 'Link',
490
513
  Dest: [inline.linkToPage - 1, 'XYZ', null, null, null]
491
514
  });
492
515
  }
493
516
 
494
517
  }
495
-
518
+ // Decorations won't draw correctly for superscript
496
519
  textDecorator.drawDecorations(line, x, y, pdfKitDoc);
497
520
  }
498
521
 
@@ -607,7 +630,18 @@ function renderVector(vector, pdfKitDoc) {
607
630
  function renderImage(image, x, y, pdfKitDoc) {
608
631
  var opacity = isNumber(image.opacity) ? image.opacity : 1;
609
632
  pdfKitDoc.opacity(opacity);
610
- pdfKitDoc.image(image.image, image.x, image.y, { width: image._width, height: image._height });
633
+ if (image.cover) {
634
+ var align = image.cover.align || 'center';
635
+ var valign = image.cover.valign || 'center';
636
+ var width = image.cover.width ? image.cover.width : image.width;
637
+ var height = image.cover.height ? image.cover.height : image.height;
638
+ pdfKitDoc.save();
639
+ pdfKitDoc.rect(image.x, image.y, width, height).clip();
640
+ pdfKitDoc.image(image.image, image.x, image.y, { cover: [width, height], align, valign });
641
+ pdfKitDoc.restore();
642
+ } else {
643
+ pdfKitDoc.image(image.image, image.x, image.y, { width: image._width, height: image._height });
644
+ }
611
645
  if (image.link) {
612
646
  pdfKitDoc.link(image.x, image.y, image._width, image._height, image.link);
613
647
  }
@@ -103,7 +103,9 @@ StyleContextStack.prototype.autopush = function (item) {
103
103
  'characterSpacing',
104
104
  'noWrap',
105
105
  'markerColor',
106
- 'leadingIndent'
106
+ 'leadingIndent',
107
+ 'sup',
108
+ 'sub'
107
109
  //'tableCellPadding'
108
110
  // 'cellBorder',
109
111
  // 'headerCellBorder',
package/src/svgMeasure.js CHANGED
@@ -1,106 +1,70 @@
1
1
  'use strict';
2
2
 
3
- function SVGMeasure() {
4
- }
3
+ var xmldoc = require('xmldoc');
5
4
 
6
- SVGMeasure.prototype.getSVGNode = function (svgString) {
7
- // remove newlines
8
- svgString = svgString.replace(/\r?\n|\r/g, "");
9
-
10
- var svgNodeMatches = svgString.match(/<svg(.*?)>/);
5
+ /** Strip unit postfix, parse number, but return undefined instead of NaN for bad input */
6
+ function stripUnits(textVal) {
7
+ var n = parseFloat(textVal);
8
+ if (typeof n !== 'number' || isNaN(n)) {
9
+ return undefined;
10
+ }
11
+ return n;
12
+ }
11
13
 
12
- if (svgNodeMatches) {
13
- // extract svg node <svg ... >
14
- return svgNodeMatches[0];
14
+ /** Make sure it's valid XML and the root tage is <svg/>, returns xmldoc DOM */
15
+ function parseSVG(svgString) {
16
+ var doc;
17
+
18
+ try {
19
+ doc = new xmldoc.XmlDocument(svgString);
20
+ } catch (err) {
21
+ throw new Error('SVGMeasure: ' + err);
15
22
  }
16
23
 
17
- return "";
18
- };
24
+ if (doc.name !== "svg") {
25
+ throw new Error('SVGMeasure: expected <svg> document');
26
+ }
19
27
 
20
- SVGMeasure.prototype.getHeightAndWidth = function (svgString) {
21
- var svgNode = this.getSVGNode(svgString);
28
+ return doc;
29
+ }
22
30
 
23
- var widthMatches = svgNode.match(/width="([0-9]+(\.[0-9]+)?)(em|ex|px|in|cm|mm|pt|pc|%)?"/);
24
- var heightMatches = svgNode.match(/height="([0-9]+(\.[0-9]+)?)(em|ex|px|in|cm|mm|pt|pc|%)?"/);
31
+ function SVGMeasure() {
32
+ }
25
33
 
26
- if (widthMatches || heightMatches) {
27
- return {
28
- width: widthMatches ? +widthMatches[1] : undefined,
29
- height: heightMatches ? +heightMatches[1] : undefined
30
- };
31
- }
32
- };
34
+ SVGMeasure.prototype.measureSVG = function (svgString) {
33
35
 
34
- SVGMeasure.prototype.getViewboxHeightAndWidth = function (svgString) {
35
- var svgNode = this.getSVGNode(svgString);
36
+ var doc = parseSVG(svgString);
36
37
 
37
- var viewboxMatches = svgNode.match(/viewBox="([+-]?(\d*\.)?\d+(,|\s+|,\s+)[+-]?(\d*\.)?\d+(,|\s+|,\s+)[+-]?(\d*\.)?\d+(,|\s+|,\s+)[+-]?(\d*\.)?\d+)"/);
38
- if (viewboxMatches) {
39
- var viewboxStr = viewboxMatches[1];
40
- var allVieboxEntries = viewboxStr.split(" ");
38
+ var docWidth = stripUnits(doc.attr.width);
39
+ var docHeight = stripUnits(doc.attr.height);
41
40
 
42
- var viewboxEntries = []; // weeding out empty strings
43
- for (var i = 0; i < allVieboxEntries.length; i++) {
44
- if (allVieboxEntries[i]) {
45
- viewboxEntries.push(allVieboxEntries[i]);
46
- }
41
+ if ((docWidth == undefined || docHeight == undefined) && typeof doc.attr.viewBox == 'string') {
42
+ var viewBoxParts = doc.attr.viewBox.split(/[,\s]+/);
43
+ if (viewBoxParts.length !== 4) {
44
+ throw new Error("Unexpected svg viewbox format, should have 4 entries but found: '" + doc.attr.viewBox + "'");
47
45
  }
48
-
49
- if (viewboxEntries.length === 4) {
50
- return { width: +viewboxEntries[2], height: +viewboxEntries[3] };
46
+ if (docWidth == undefined) {
47
+ docWidth = stripUnits(viewBoxParts[2]);
48
+ }
49
+ if (docHeight == undefined) {
50
+ docHeight = stripUnits(viewBoxParts[3]);
51
51
  }
52
-
53
- throw new Error("Unexpected svg viewbox format, should have 4 entries but found: '" + viewboxStr + "'");
54
52
  }
55
- };
56
-
57
- SVGMeasure.prototype.measureSVG = function (svgString) {
58
-
59
- var heightAndWidth = this.getHeightAndWidth(svgString);
60
- var viewboxHeightAndWidth = this.getViewboxHeightAndWidth(svgString);
61
53
 
62
- return heightAndWidth || viewboxHeightAndWidth || {};
54
+ return {
55
+ width: docWidth,
56
+ height: docHeight
57
+ };
63
58
  };
64
59
 
65
60
  SVGMeasure.prototype.writeDimensions = function (svgString, dimensions) {
66
61
 
67
- var svgNode = this.getSVGNode(svgString);
68
-
69
- if (svgNode) {
70
-
71
- var nodeDimensions = this.getHeightAndWidth(svgString);
72
-
73
- if (dimensions.width) {
74
-
75
- var newWidth = 'width="' + dimensions.width + '"';
62
+ var doc = parseSVG(svgString);
76
63
 
77
- if (nodeDimensions && nodeDimensions.width) {
78
- // replace existing width
79
- svgNode = svgNode.replace(/width="[0-9]+(\.[0-9]+)?(em|ex|px|in|cm|mm|pt|pc|%)?"/, newWidth);
80
- } else {
81
- // insert new width
82
- svgNode = svgNode.replace(">", " " + newWidth + ">");
83
- }
84
- }
85
-
86
- if (dimensions.height) {
87
-
88
- var newHeight = 'height="' + dimensions.height + '"';
89
-
90
- if (nodeDimensions && nodeDimensions.height) {
91
- // replace existing height
92
- svgNode = svgNode.replace(/height="[0-9]+(\.[0-9]+)?(em|ex|px|in|cm|mm|pt|pc|%)?"/, newHeight);
93
- } else {
94
- // insert new height
95
- svgNode = svgNode.replace(">", " " + newHeight + ">");
96
- }
97
- }
98
-
99
- // insert updated svg node
100
- return svgString.replace(/<svg(.*?)>/, svgNode);
101
- }
64
+ doc.attr.width = "" + dimensions.width;
65
+ doc.attr.height = "" + dimensions.height;
102
66
 
103
- return svgString;
67
+ return doc.toString();
104
68
  };
105
69
 
106
70
  module.exports = SVGMeasure;
package/src/textTools.js CHANGED
@@ -315,6 +315,13 @@ function measure(fontProvider, textArray, styleContextStack) {
315
315
  var preserveLeadingSpaces = getStyleProperty(item, styleContextStack, 'preserveLeadingSpaces', false);
316
316
  var preserveTrailingSpaces = getStyleProperty(item, styleContextStack, 'preserveTrailingSpaces', false);
317
317
  var opacity = getStyleProperty(item, styleContextStack, 'opacity', 1);
318
+ var sup = getStyleProperty(item, styleContextStack, 'sup', false);
319
+ var sub = getStyleProperty(item, styleContextStack, 'sub', false);
320
+
321
+ if ((sup || sub) && item.fontSize === undefined) {
322
+ // font size reduction taken from here: https://en.wikipedia.org/wiki/Subscript_and_superscript#Desktop_publishing
323
+ fontSize *= 0.58
324
+ }
318
325
 
319
326
  var font = fontProvider.provideFont(fontName, bold, italics);
320
327
 
@@ -352,6 +359,8 @@ function measure(fontProvider, textArray, styleContextStack) {
352
359
  item.linkToDestination = linkToDestination;
353
360
  item.noWrap = noWrap;
354
361
  item.opacity = opacity;
362
+ item.sup = sup;
363
+ item.sub = sub;
355
364
  });
356
365
 
357
366
  return normalized;