UNPKG

3.08 kBJavaScriptView Raw
1'use strict';
2
3/* eslint-disable consistent-return */
4
5function isWhiteSpace(chr) {
6 return chr === 0x20 || chr === 0x09 || chr === 0x0D || chr === 0x0A;
7}
8
9// Filter NaN, Infinity, < 0
10function isFinitePositive(val) {
11 return typeof val === 'number' && isFinite(val) && val > 0;
12}
13
14function canBeSvg(buf) {
15 var i = 0, max = buf.length;
16
17 while (i < max && isWhiteSpace(buf[i])) i++;
18
19 if (i === max) return false;
20 return buf[i] === 0x3c; /* < */
21}
22
23
24var SVG_HEADER_RE = /<svg\s[^>]+>/;
25var SVG_WIDTH_RE = /[^-]\bwidth="([^%]+?)"|[^-]\bwidth='([^%]+?)'/;
26var SVG_HEIGHT_RE = /\bheight="([^%]+?)"|\bheight='([^%]+?)'/;
27var SVG_VIEWBOX_RE = /\bview[bB]ox="(.+?)"|\bview[bB]ox='(.+?)'/;
28var SVG_UNITS_RE = /in$|mm$|cm$|pt$|pc$|px$|em$|ex$/;
29
30function svgAttrs(str) {
31 var width = str.match(SVG_WIDTH_RE);
32 var height = str.match(SVG_HEIGHT_RE);
33 var viewbox = str.match(SVG_VIEWBOX_RE);
34
35 return {
36 width: width && (width[1] || width[2]),
37 height: height && (height[1] || height[2]),
38 viewbox: viewbox && (viewbox[1] || viewbox[2])
39 };
40}
41
42
43function units(str) {
44 if (!SVG_UNITS_RE.test(str)) return 'px';
45
46 return str.match(SVG_UNITS_RE)[0];
47}
48
49
50module.exports = function (data) {
51 if (!canBeSvg(data)) return;
52
53 var str = '';
54
55 for (var i = 0; i < data.length; i++) {
56 // 1. We can't rely on buffer features
57 // 2. Don't care about UTF16 because ascii is enougth for our goals
58 str += String.fromCharCode(data[i]);
59 }
60
61 if (!SVG_HEADER_RE.test(str)) return;
62
63 var attrs = svgAttrs(str.match(SVG_HEADER_RE)[0]);
64 var width = parseFloat(attrs.width);
65 var height = parseFloat(attrs.height);
66
67 // Extract from direct values
68
69 if (attrs.width && attrs.height) {
70 if (!isFinitePositive(width) || !isFinitePositive(height)) return;
71
72 return {
73 width: width,
74 height: height,
75 type: 'svg',
76 mime: 'image/svg+xml',
77 wUnits: units(attrs.width),
78 hUnits: units(attrs.height)
79 };
80 }
81
82 // Extract from viewbox
83
84 var parts = (attrs.viewbox || '').split(' ');
85 var viewbox = {
86 width: parts[2],
87 height: parts[3]
88 };
89 var vbWidth = parseFloat(viewbox.width);
90 var vbHeight = parseFloat(viewbox.height);
91
92 if (!isFinitePositive(vbWidth) || !isFinitePositive(vbHeight)) return;
93 if (units(viewbox.width) !== units(viewbox.height)) return;
94
95 var ratio = vbWidth / vbHeight;
96
97 if (attrs.width) {
98 if (!isFinitePositive(width)) return;
99
100 return {
101 width: width,
102 height: width / ratio,
103 type: 'svg',
104 mime: 'image/svg+xml',
105 wUnits: units(attrs.width),
106 hUnits: units(attrs.width)
107 };
108 }
109
110 if (attrs.height) {
111 if (!isFinitePositive(height)) return;
112
113 return {
114 width: height * ratio,
115 height: height,
116 type: 'svg',
117 mime: 'image/svg+xml',
118 wUnits: units(attrs.height),
119 hUnits: units(attrs.height)
120 };
121 }
122
123 return {
124 width: vbWidth,
125 height: vbHeight,
126 type: 'svg',
127 mime: 'image/svg+xml',
128 wUnits: units(viewbox.width),
129 hUnits: units(viewbox.height)
130 };
131};