features.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.FEATURES = exports.loadSerializedSVG = exports.createForeignObjectSVG = void 0;
  4. var css_line_break_1 = require("css-line-break");
  5. var testRangeBounds = function (document) {
  6. var TEST_HEIGHT = 123;
  7. if (document.createRange) {
  8. var range = document.createRange();
  9. if (range.getBoundingClientRect) {
  10. var testElement = document.createElement('boundtest');
  11. testElement.style.height = TEST_HEIGHT + "px";
  12. testElement.style.display = 'block';
  13. document.body.appendChild(testElement);
  14. range.selectNode(testElement);
  15. var rangeBounds = range.getBoundingClientRect();
  16. var rangeHeight = Math.round(rangeBounds.height);
  17. document.body.removeChild(testElement);
  18. if (rangeHeight === TEST_HEIGHT) {
  19. return true;
  20. }
  21. }
  22. }
  23. return false;
  24. };
  25. var testIOSLineBreak = function (document) {
  26. var testElement = document.createElement('boundtest');
  27. testElement.style.width = '50px';
  28. testElement.style.display = 'block';
  29. testElement.style.fontSize = '12px';
  30. testElement.style.letterSpacing = '0px';
  31. testElement.style.wordSpacing = '0px';
  32. document.body.appendChild(testElement);
  33. var range = document.createRange();
  34. testElement.innerHTML = typeof ''.repeat === 'function' ? '👨'.repeat(10) : '';
  35. var node = testElement.firstChild;
  36. var textList = css_line_break_1.toCodePoints(node.data).map(function (i) { return css_line_break_1.fromCodePoint(i); });
  37. var offset = 0;
  38. var prev = {};
  39. // ios 13 does not handle range getBoundingClientRect line changes correctly #2177
  40. var supports = textList.every(function (text, i) {
  41. range.setStart(node, offset);
  42. range.setEnd(node, offset + text.length);
  43. var rect = range.getBoundingClientRect();
  44. offset += text.length;
  45. var boundAhead = rect.x > prev.x || rect.y > prev.y;
  46. prev = rect;
  47. if (i === 0) {
  48. return true;
  49. }
  50. return boundAhead;
  51. });
  52. document.body.removeChild(testElement);
  53. return supports;
  54. };
  55. var testCORS = function () { return typeof new Image().crossOrigin !== 'undefined'; };
  56. var testResponseType = function () { return typeof new XMLHttpRequest().responseType === 'string'; };
  57. var testSVG = function (document) {
  58. var img = new Image();
  59. var canvas = document.createElement('canvas');
  60. var ctx = canvas.getContext('2d');
  61. if (!ctx) {
  62. return false;
  63. }
  64. img.src = "data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>";
  65. try {
  66. ctx.drawImage(img, 0, 0);
  67. canvas.toDataURL();
  68. }
  69. catch (e) {
  70. return false;
  71. }
  72. return true;
  73. };
  74. var isGreenPixel = function (data) {
  75. return data[0] === 0 && data[1] === 255 && data[2] === 0 && data[3] === 255;
  76. };
  77. var testForeignObject = function (document) {
  78. var canvas = document.createElement('canvas');
  79. var size = 100;
  80. canvas.width = size;
  81. canvas.height = size;
  82. var ctx = canvas.getContext('2d');
  83. if (!ctx) {
  84. return Promise.reject(false);
  85. }
  86. ctx.fillStyle = 'rgb(0, 255, 0)';
  87. ctx.fillRect(0, 0, size, size);
  88. var img = new Image();
  89. var greenImageSrc = canvas.toDataURL();
  90. img.src = greenImageSrc;
  91. var svg = exports.createForeignObjectSVG(size, size, 0, 0, img);
  92. ctx.fillStyle = 'red';
  93. ctx.fillRect(0, 0, size, size);
  94. return exports.loadSerializedSVG(svg)
  95. .then(function (img) {
  96. ctx.drawImage(img, 0, 0);
  97. var data = ctx.getImageData(0, 0, size, size).data;
  98. ctx.fillStyle = 'red';
  99. ctx.fillRect(0, 0, size, size);
  100. var node = document.createElement('div');
  101. node.style.backgroundImage = "url(" + greenImageSrc + ")";
  102. node.style.height = size + "px";
  103. // Firefox 55 does not render inline <img /> tags
  104. return isGreenPixel(data)
  105. ? exports.loadSerializedSVG(exports.createForeignObjectSVG(size, size, 0, 0, node))
  106. : Promise.reject(false);
  107. })
  108. .then(function (img) {
  109. ctx.drawImage(img, 0, 0);
  110. // Edge does not render background-images
  111. return isGreenPixel(ctx.getImageData(0, 0, size, size).data);
  112. })
  113. .catch(function () { return false; });
  114. };
  115. var createForeignObjectSVG = function (width, height, x, y, node) {
  116. var xmlns = 'http://www.w3.org/2000/svg';
  117. var svg = document.createElementNS(xmlns, 'svg');
  118. var foreignObject = document.createElementNS(xmlns, 'foreignObject');
  119. svg.setAttributeNS(null, 'width', width.toString());
  120. svg.setAttributeNS(null, 'height', height.toString());
  121. foreignObject.setAttributeNS(null, 'width', '100%');
  122. foreignObject.setAttributeNS(null, 'height', '100%');
  123. foreignObject.setAttributeNS(null, 'x', x.toString());
  124. foreignObject.setAttributeNS(null, 'y', y.toString());
  125. foreignObject.setAttributeNS(null, 'externalResourcesRequired', 'true');
  126. svg.appendChild(foreignObject);
  127. foreignObject.appendChild(node);
  128. return svg;
  129. };
  130. exports.createForeignObjectSVG = createForeignObjectSVG;
  131. var loadSerializedSVG = function (svg) {
  132. return new Promise(function (resolve, reject) {
  133. var img = new Image();
  134. img.onload = function () { return resolve(img); };
  135. img.onerror = reject;
  136. img.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(new XMLSerializer().serializeToString(svg));
  137. });
  138. };
  139. exports.loadSerializedSVG = loadSerializedSVG;
  140. exports.FEATURES = {
  141. get SUPPORT_RANGE_BOUNDS() {
  142. 'use strict';
  143. var value = testRangeBounds(document);
  144. Object.defineProperty(exports.FEATURES, 'SUPPORT_RANGE_BOUNDS', { value: value });
  145. return value;
  146. },
  147. get SUPPORT_WORD_BREAKING() {
  148. 'use strict';
  149. var value = exports.FEATURES.SUPPORT_RANGE_BOUNDS && testIOSLineBreak(document);
  150. Object.defineProperty(exports.FEATURES, 'SUPPORT_WORD_BREAKING', { value: value });
  151. return value;
  152. },
  153. get SUPPORT_SVG_DRAWING() {
  154. 'use strict';
  155. var value = testSVG(document);
  156. Object.defineProperty(exports.FEATURES, 'SUPPORT_SVG_DRAWING', { value: value });
  157. return value;
  158. },
  159. get SUPPORT_FOREIGNOBJECT_DRAWING() {
  160. 'use strict';
  161. var value = typeof Array.from === 'function' && typeof window.fetch === 'function'
  162. ? testForeignObject(document)
  163. : Promise.resolve(false);
  164. Object.defineProperty(exports.FEATURES, 'SUPPORT_FOREIGNOBJECT_DRAWING', { value: value });
  165. return value;
  166. },
  167. get SUPPORT_CORS_IMAGES() {
  168. 'use strict';
  169. var value = testCORS();
  170. Object.defineProperty(exports.FEATURES, 'SUPPORT_CORS_IMAGES', { value: value });
  171. return value;
  172. },
  173. get SUPPORT_RESPONSE_TYPE() {
  174. 'use strict';
  175. var value = testResponseType();
  176. Object.defineProperty(exports.FEATURES, 'SUPPORT_RESPONSE_TYPE', { value: value });
  177. return value;
  178. },
  179. get SUPPORT_CORS_XHR() {
  180. 'use strict';
  181. var value = 'withCredentials' in new XMLHttpRequest();
  182. Object.defineProperty(exports.FEATURES, 'SUPPORT_CORS_XHR', { value: value });
  183. return value;
  184. },
  185. get SUPPORT_NATIVE_TEXT_SEGMENTATION() {
  186. 'use strict';
  187. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  188. var value = !!(typeof Intl !== 'undefined' && Intl.Segmenter);
  189. Object.defineProperty(exports.FEATURES, 'SUPPORT_NATIVE_TEXT_SEGMENTATION', { value: value });
  190. return value;
  191. }
  192. };
  193. //# sourceMappingURL=features.js.map