index.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. export var DataUri;
  2. (function (DataUri) {
  3. function isDataUrl(url) {
  4. const prefix = 'data:';
  5. return url.substr(0, prefix.length) === prefix;
  6. }
  7. DataUri.isDataUrl = isDataUrl;
  8. /**
  9. * Converts an image at `url` to base64-encoded data uri.
  10. * The mime type of the image is inferred from the `url` file extension.
  11. */
  12. function imageToDataUri(url, callback) {
  13. // No need to convert to data uri if it is already in data uri.
  14. if (!url || isDataUrl(url)) {
  15. // Keep the async nature of the function.
  16. setTimeout(() => callback(null, url));
  17. return;
  18. }
  19. const onError = () => {
  20. callback(new Error(`Failed to load image: ${url}`));
  21. };
  22. const onLoad = window.FileReader
  23. ? // chrome, IE10+
  24. (xhr) => {
  25. if (xhr.status === 200) {
  26. const reader = new FileReader();
  27. reader.onload = (evt) => {
  28. const dataUri = evt.target.result;
  29. callback(null, dataUri);
  30. };
  31. reader.onerror = onError;
  32. reader.readAsDataURL(xhr.response);
  33. }
  34. else {
  35. onError();
  36. }
  37. }
  38. : (xhr) => {
  39. const toString = (u8a) => {
  40. const CHUNK_SZ = 0x8000;
  41. const c = [];
  42. for (let i = 0; i < u8a.length; i += CHUNK_SZ) {
  43. c.push(String.fromCharCode.apply(null, u8a.subarray(i, i + CHUNK_SZ)));
  44. }
  45. return c.join('');
  46. };
  47. if (xhr.status === 200) {
  48. let suffix = url.split('.').pop() || 'png';
  49. if (suffix === 'svg') {
  50. suffix = 'svg+xml';
  51. }
  52. const meta = `data:image/${suffix};base64,`;
  53. const bytes = new Uint8Array(xhr.response);
  54. const base64 = meta + btoa(toString(bytes));
  55. callback(null, base64);
  56. }
  57. else {
  58. onError();
  59. }
  60. };
  61. const xhr = new XMLHttpRequest();
  62. xhr.responseType = window.FileReader ? 'blob' : 'arraybuffer';
  63. xhr.open('GET', url, true);
  64. xhr.addEventListener('error', onError);
  65. xhr.addEventListener('load', () => onLoad(xhr));
  66. xhr.send();
  67. }
  68. DataUri.imageToDataUri = imageToDataUri;
  69. function dataUriToBlob(dataUrl) {
  70. let uri = dataUrl.replace(/\s/g, '');
  71. uri = decodeURIComponent(uri);
  72. const index = uri.indexOf(',');
  73. const dataType = uri.slice(0, index); // e.g. 'data:image/jpeg;base64'
  74. const mime = dataType.split(':')[1].split(';')[0]; // e.g. 'image/jpeg'
  75. const data = uri.slice(index + 1);
  76. let decodedString;
  77. if (dataType.indexOf('base64') >= 0) {
  78. // data may be encoded in base64
  79. decodedString = atob(data);
  80. }
  81. else {
  82. // convert the decoded string to UTF-8
  83. decodedString = unescape(encodeURIComponent(data));
  84. }
  85. // write the bytes of the string to a typed array
  86. const ia = new Uint8Array(decodedString.length);
  87. for (let i = 0; i < decodedString.length; i += 1) {
  88. ia[i] = decodedString.charCodeAt(i);
  89. }
  90. return new Blob([ia], { type: mime });
  91. }
  92. DataUri.dataUriToBlob = dataUriToBlob;
  93. function downloadBlob(blob, fileName) {
  94. const msSaveBlob = window.navigator.msSaveBlob;
  95. if (msSaveBlob) {
  96. // requires IE 10+
  97. // pulls up a save dialog
  98. msSaveBlob(blob, fileName);
  99. }
  100. else {
  101. // other browsers
  102. // downloads directly in Chrome and Safari
  103. // presents a save/open dialog in Firefox
  104. // Firefox bug: `from` field in save dialog always shows `from:blob:`
  105. // https://bugzilla.mozilla.org/show_bug.cgi?id=1053327
  106. const url = window.URL.createObjectURL(blob);
  107. const link = document.createElement('a');
  108. link.href = url;
  109. link.download = fileName;
  110. document.body.appendChild(link);
  111. link.click();
  112. document.body.removeChild(link);
  113. // mark the url for garbage collection
  114. window.URL.revokeObjectURL(url);
  115. }
  116. }
  117. DataUri.downloadBlob = downloadBlob;
  118. function downloadDataUri(dataUrl, fileName) {
  119. const blob = dataUriToBlob(dataUrl);
  120. downloadBlob(blob, fileName);
  121. }
  122. DataUri.downloadDataUri = downloadDataUri;
  123. function parseViewBox(svg) {
  124. const matches = svg.match(/<svg[^>]*viewBox\s*=\s*(["']?)(.+?)\1[^>]*>/i);
  125. if (matches && matches[2]) {
  126. return matches[2].replace(/\s+/, ' ').split(' ');
  127. }
  128. return null;
  129. }
  130. function getNumber(str) {
  131. const ret = parseFloat(str);
  132. return Number.isNaN(ret) ? null : ret;
  133. }
  134. function svgToDataUrl(svg, options = {}) {
  135. let viewBox = null;
  136. const getNumberFromViewBox = (index) => {
  137. if (viewBox == null) {
  138. viewBox = parseViewBox(svg);
  139. }
  140. if (viewBox != null) {
  141. return getNumber(viewBox[index]);
  142. }
  143. return null;
  144. };
  145. const getNumberFromMatches = (reg) => {
  146. const matches = svg.match(reg);
  147. if (matches && matches[2]) {
  148. return getNumber(matches[2]);
  149. }
  150. return null;
  151. };
  152. let w = options.width;
  153. if (w == null) {
  154. w = getNumberFromMatches(/<svg[^>]*width\s*=\s*(["']?)(.+?)\1[^>]*>/i);
  155. }
  156. if (w == null) {
  157. w = getNumberFromViewBox(2);
  158. }
  159. if (w == null) {
  160. throw new Error('Can not parse width from svg string');
  161. }
  162. let h = options.height;
  163. if (h == null) {
  164. h = getNumberFromMatches(/<svg[^>]*height\s*=\s*(["']?)(.+?)\1[^>]*>/i);
  165. }
  166. if (h == null) {
  167. h = getNumberFromViewBox(3);
  168. }
  169. if (h == null) {
  170. throw new Error('Can not parse height from svg string');
  171. }
  172. const decoded = encodeURIComponent(svg)
  173. .replace(/'/g, '%27')
  174. .replace(/"/g, '%22');
  175. const header = 'data:image/svg+xml';
  176. const dataUrl = `${header},${decoded}`;
  177. return dataUrl;
  178. }
  179. DataUri.svgToDataUrl = svgToDataUrl;
  180. })(DataUri || (DataUri = {}));
  181. //# sourceMappingURL=index.js.map