html2canvas-pro 2.1.0 → 2.2.0

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.
Files changed (266) hide show
  1. package/dist/html2canvas-pro.esm.js +10226 -10526
  2. package/dist/html2canvas-pro.esm.js.map +1 -1
  3. package/dist/html2canvas-pro.js +10869 -11171
  4. package/dist/html2canvas-pro.js.map +1 -1
  5. package/dist/html2canvas-pro.min.js +8 -8
  6. package/dist/lib/config.js +0 -22
  7. package/dist/lib/core/cache-storage.js +3 -40
  8. package/dist/lib/core/constants.js +25 -0
  9. package/dist/lib/core/context.js +1 -0
  10. package/dist/lib/core/features.js +3 -2
  11. package/dist/lib/core/validator.js +3 -3
  12. package/dist/lib/css/grouped/background-styles.js +36 -0
  13. package/dist/lib/css/grouped/border-styles.js +75 -0
  14. package/dist/lib/css/grouped/font-styles.js +93 -0
  15. package/dist/lib/css/grouped/layout-styles.js +127 -0
  16. package/dist/lib/css/index.js +74 -46
  17. package/dist/lib/css/layout/text.js +7 -6
  18. package/dist/lib/css/property-descriptors/background-blend-mode.js +41 -0
  19. package/dist/lib/css/property-descriptors/border-image-repeat.js +42 -0
  20. package/dist/lib/css/property-descriptors/border-image-slice.js +45 -0
  21. package/dist/lib/css/property-descriptors/border-image-source.js +21 -0
  22. package/dist/lib/css/property-descriptors/border-radius.js +1 -1
  23. package/dist/lib/css/property-descriptors/box-decoration-break.js +18 -0
  24. package/dist/lib/css/property-descriptors/counter-increment.js +17 -12
  25. package/dist/lib/css/property-descriptors/counter-reset.js +4 -12
  26. package/dist/lib/css/property-descriptors/filter.js +76 -0
  27. package/dist/lib/css/property-descriptors/font-variant-ligatures.js +34 -0
  28. package/dist/lib/css/property-descriptors/object-fit.js +1 -1
  29. package/dist/lib/css/property-descriptors/object-position.js +42 -0
  30. package/dist/lib/css/property-descriptors/visibility.js +1 -1
  31. package/dist/lib/css/property-descriptors/zoom.js +18 -0
  32. package/dist/lib/css/syntax/parser.js +0 -1
  33. package/dist/lib/css/types/color.js +5 -1
  34. package/dist/lib/css/types/functions/repeating-linear-gradient.js +9 -0
  35. package/dist/lib/css/types/image.js +12 -2
  36. package/dist/lib/css/types/length-percentage.js +6 -2
  37. package/dist/lib/css/types/safe-eval.js +80 -0
  38. package/dist/lib/dom/document-cloner.js +23 -163
  39. package/dist/lib/dom/slot-cloner.js +176 -0
  40. package/dist/lib/index.js +1 -17
  41. package/dist/lib/render/canvas/background-renderer.js +169 -30
  42. package/dist/lib/render/canvas/border-image-renderer.js +153 -0
  43. package/dist/lib/render/canvas/canvas-renderer.js +39 -190
  44. package/dist/lib/render/canvas/content-renderer.js +202 -0
  45. package/dist/lib/render/canvas/effects-renderer.js +3 -0
  46. package/dist/lib/render/canvas/foreignobject-renderer.js +5 -1
  47. package/dist/lib/render/canvas/text/text-decoration-renderer.js +99 -0
  48. package/dist/lib/render/canvas/text-renderer.js +100 -224
  49. package/dist/lib/render/effects.js +38 -3
  50. package/dist/lib/render/object-fit.js +19 -15
  51. package/dist/lib/render/stacking-context.js +11 -0
  52. package/dist/types/config.d.ts +0 -10
  53. package/dist/types/core/cache-storage.d.ts +0 -24
  54. package/dist/types/core/constants.d.ts +22 -0
  55. package/dist/types/core/context.d.ts +3 -0
  56. package/dist/types/core/performance-monitor.d.ts +4 -4
  57. package/dist/types/core/validator.d.ts +6 -8
  58. package/dist/types/css/grouped/background-styles.d.ts +16 -0
  59. package/dist/types/css/grouped/border-styles.d.ts +31 -0
  60. package/dist/types/css/grouped/font-styles.d.ts +35 -0
  61. package/dist/types/css/grouped/layout-styles.d.ts +46 -0
  62. package/dist/types/css/index.d.ts +30 -0
  63. package/dist/types/css/property-descriptors/background-blend-mode.d.ts +23 -0
  64. package/dist/types/css/property-descriptors/border-image-repeat.d.ts +12 -0
  65. package/dist/types/css/property-descriptors/border-image-slice.d.ts +10 -0
  66. package/dist/types/css/property-descriptors/border-image-source.d.ts +4 -0
  67. package/dist/types/css/property-descriptors/box-decoration-break.d.ts +6 -0
  68. package/dist/types/css/property-descriptors/counter-increment.d.ts +3 -0
  69. package/dist/types/css/property-descriptors/filter.d.ts +3 -0
  70. package/dist/types/css/property-descriptors/font-variant-ligatures.d.ts +14 -0
  71. package/dist/types/css/property-descriptors/object-position.d.ts +4 -0
  72. package/dist/types/css/property-descriptors/zoom.d.ts +3 -0
  73. package/dist/types/css/types/functions/repeating-linear-gradient.d.ts +4 -0
  74. package/dist/types/css/types/image.d.ts +4 -2
  75. package/dist/types/css/types/safe-eval.d.ts +8 -0
  76. package/dist/types/dom/document-cloner.d.ts +3 -44
  77. package/dist/types/dom/slot-cloner.d.ts +66 -0
  78. package/dist/types/index.d.ts +3 -7
  79. package/dist/types/options.d.ts +11 -0
  80. package/dist/types/render/canvas/background-renderer.d.ts +23 -0
  81. package/dist/types/render/canvas/border-image-renderer.d.ts +18 -0
  82. package/dist/types/render/canvas/canvas-renderer.d.ts +1 -0
  83. package/dist/types/render/canvas/content-renderer.d.ts +44 -0
  84. package/dist/types/render/canvas/text/text-decoration-renderer.d.ts +18 -0
  85. package/dist/types/render/canvas/text-renderer.d.ts +12 -1
  86. package/dist/types/render/effects.d.ts +12 -2
  87. package/dist/types/render/object-fit.d.ts +2 -1
  88. package/dist/types/render/renderer-interface.d.ts +11 -9
  89. package/package.json +7 -20
  90. package/dist/lib/dom/replaced-elements/pseudo-elements.js +0 -0
  91. package/dist/lib/invariant.js +0 -9
  92. package/dist/types/dom/replaced-elements/pseudo-elements.d.ts +0 -0
  93. package/dist/types/invariant.d.ts +0 -1
  94. package/src/__tests__/index.ts +0 -99
  95. package/src/config.ts +0 -107
  96. package/src/core/__mocks__/cache-storage.ts +0 -1
  97. package/src/core/__mocks__/context.ts +0 -19
  98. package/src/core/__mocks__/features.ts +0 -8
  99. package/src/core/__mocks__/logger.ts +0 -17
  100. package/src/core/__tests__/cache-storage.test.ts +0 -205
  101. package/src/core/__tests__/cache-storage.ts +0 -278
  102. package/src/core/__tests__/logger.ts +0 -29
  103. package/src/core/__tests__/validator.ts +0 -359
  104. package/src/core/bitwise.ts +0 -1
  105. package/src/core/cache-storage.ts +0 -315
  106. package/src/core/context.ts +0 -31
  107. package/src/core/debugger.ts +0 -32
  108. package/src/core/features.ts +0 -222
  109. package/src/core/logger.ts +0 -64
  110. package/src/core/origin-checker.ts +0 -57
  111. package/src/core/performance-monitor.ts +0 -241
  112. package/src/core/render-element.ts +0 -272
  113. package/src/core/util.ts +0 -1
  114. package/src/core/validator.ts +0 -593
  115. package/src/css/index.ts +0 -427
  116. package/src/css/layout/__mocks__/bounds.ts +0 -6
  117. package/src/css/layout/bounds.ts +0 -79
  118. package/src/css/layout/text.ts +0 -161
  119. package/src/css/property-descriptor.ts +0 -49
  120. package/src/css/property-descriptors/__tests__/background-tests.ts +0 -65
  121. package/src/css/property-descriptors/__tests__/clip-path.test.ts +0 -280
  122. package/src/css/property-descriptors/__tests__/font-family.ts +0 -25
  123. package/src/css/property-descriptors/__tests__/image-rendering-integration.test.ts +0 -153
  124. package/src/css/property-descriptors/__tests__/image-rendering-performance.test.ts +0 -175
  125. package/src/css/property-descriptors/__tests__/image-rendering.test.ts +0 -72
  126. package/src/css/property-descriptors/__tests__/paint-order.ts +0 -87
  127. package/src/css/property-descriptors/__tests__/text-shadow.ts +0 -94
  128. package/src/css/property-descriptors/__tests__/transform-tests.ts +0 -18
  129. package/src/css/property-descriptors/background-clip.ts +0 -30
  130. package/src/css/property-descriptors/background-color.ts +0 -9
  131. package/src/css/property-descriptors/background-image.ts +0 -27
  132. package/src/css/property-descriptors/background-origin.ts +0 -31
  133. package/src/css/property-descriptors/background-position.ts +0 -38
  134. package/src/css/property-descriptors/background-repeat.ts +0 -44
  135. package/src/css/property-descriptors/background-size.ts +0 -27
  136. package/src/css/property-descriptors/border-color.ts +0 -13
  137. package/src/css/property-descriptors/border-radius.ts +0 -19
  138. package/src/css/property-descriptors/border-style.ts +0 -34
  139. package/src/css/property-descriptors/border-width.ts +0 -20
  140. package/src/css/property-descriptors/box-shadow.ts +0 -60
  141. package/src/css/property-descriptors/clip-path.ts +0 -271
  142. package/src/css/property-descriptors/color.ts +0 -9
  143. package/src/css/property-descriptors/content.ts +0 -26
  144. package/src/css/property-descriptors/counter-increment.ts +0 -43
  145. package/src/css/property-descriptors/counter-reset.ts +0 -36
  146. package/src/css/property-descriptors/direction.ts +0 -23
  147. package/src/css/property-descriptors/display.ts +0 -117
  148. package/src/css/property-descriptors/duration.ts +0 -14
  149. package/src/css/property-descriptors/float.ts +0 -29
  150. package/src/css/property-descriptors/font-family.ts +0 -38
  151. package/src/css/property-descriptors/font-size.ts +0 -9
  152. package/src/css/property-descriptors/font-style.ts +0 -25
  153. package/src/css/property-descriptors/font-variant.ts +0 -12
  154. package/src/css/property-descriptors/font-weight.ts +0 -26
  155. package/src/css/property-descriptors/image-rendering.ts +0 -33
  156. package/src/css/property-descriptors/letter-spacing.ts +0 -25
  157. package/src/css/property-descriptors/line-break.ts +0 -22
  158. package/src/css/property-descriptors/line-height.ts +0 -22
  159. package/src/css/property-descriptors/list-style-image.ts +0 -19
  160. package/src/css/property-descriptors/list-style-position.ts +0 -22
  161. package/src/css/property-descriptors/list-style-type.ts +0 -179
  162. package/src/css/property-descriptors/margin.ts +0 -13
  163. package/src/css/property-descriptors/mix-blend-mode.ts +0 -35
  164. package/src/css/property-descriptors/object-fit.ts +0 -39
  165. package/src/css/property-descriptors/opacity.ts +0 -15
  166. package/src/css/property-descriptors/overflow-wrap.ts +0 -22
  167. package/src/css/property-descriptors/overflow.ts +0 -34
  168. package/src/css/property-descriptors/padding.ts +0 -14
  169. package/src/css/property-descriptors/paint-order.ts +0 -42
  170. package/src/css/property-descriptors/position.ts +0 -30
  171. package/src/css/property-descriptors/quotes.ts +0 -57
  172. package/src/css/property-descriptors/rotate.ts +0 -34
  173. package/src/css/property-descriptors/text-align.ts +0 -26
  174. package/src/css/property-descriptors/text-decoration-color.ts +0 -9
  175. package/src/css/property-descriptors/text-decoration-line.ts +0 -38
  176. package/src/css/property-descriptors/text-decoration-style.ts +0 -32
  177. package/src/css/property-descriptors/text-decoration-thickness.ts +0 -30
  178. package/src/css/property-descriptors/text-overflow.ts +0 -23
  179. package/src/css/property-descriptors/text-shadow.ts +0 -52
  180. package/src/css/property-descriptors/text-transform.ts +0 -27
  181. package/src/css/property-descriptors/text-underline-offset.ts +0 -27
  182. package/src/css/property-descriptors/transform-origin.ts +0 -29
  183. package/src/css/property-descriptors/transform.ts +0 -74
  184. package/src/css/property-descriptors/visibility.ts +0 -25
  185. package/src/css/property-descriptors/webkit-line-clamp.ts +0 -30
  186. package/src/css/property-descriptors/webkit-text-stroke-color.ts +0 -8
  187. package/src/css/property-descriptors/webkit-text-stroke-width.ts +0 -15
  188. package/src/css/property-descriptors/word-break.ts +0 -25
  189. package/src/css/property-descriptors/writing-mode.ts +0 -37
  190. package/src/css/property-descriptors/z-index.ts +0 -27
  191. package/src/css/syntax/__tests__/tokernizer-tests.ts +0 -29
  192. package/src/css/syntax/parser.ts +0 -188
  193. package/src/css/syntax/tokenizer.ts +0 -822
  194. package/src/css/type-descriptor.ts +0 -7
  195. package/src/css/types/__tests__/color-tests.ts +0 -147
  196. package/src/css/types/__tests__/image-tests.ts +0 -239
  197. package/src/css/types/angle.ts +0 -86
  198. package/src/css/types/color-math.ts +0 -22
  199. package/src/css/types/color-spaces/a98.ts +0 -86
  200. package/src/css/types/color-spaces/p3.ts +0 -92
  201. package/src/css/types/color-spaces/pro-photo.ts +0 -87
  202. package/src/css/types/color-spaces/rec2020.ts +0 -90
  203. package/src/css/types/color-spaces/srgb.ts +0 -87
  204. package/src/css/types/color-utilities.ts +0 -452
  205. package/src/css/types/color.ts +0 -485
  206. package/src/css/types/functions/-prefix-linear-gradient.ts +0 -35
  207. package/src/css/types/functions/-prefix-radial-gradient.ts +0 -106
  208. package/src/css/types/functions/-webkit-gradient.ts +0 -69
  209. package/src/css/types/functions/__tests__/radial-gradient.ts +0 -69
  210. package/src/css/types/functions/counter.ts +0 -511
  211. package/src/css/types/functions/gradient.ts +0 -206
  212. package/src/css/types/functions/linear-gradient.ts +0 -28
  213. package/src/css/types/functions/radial-gradient.ts +0 -101
  214. package/src/css/types/image.ts +0 -120
  215. package/src/css/types/index.ts +0 -1
  216. package/src/css/types/length-percentage.ts +0 -137
  217. package/src/css/types/length.ts +0 -7
  218. package/src/css/types/time.ts +0 -20
  219. package/src/dom/__mocks__/document-cloner.ts +0 -22
  220. package/src/dom/__tests__/dom-normalizer.test.ts +0 -133
  221. package/src/dom/__tests__/element-container.test.ts +0 -129
  222. package/src/dom/document-cloner.ts +0 -929
  223. package/src/dom/dom-normalizer.ts +0 -133
  224. package/src/dom/element-container.ts +0 -75
  225. package/src/dom/elements/li-element-container.ts +0 -10
  226. package/src/dom/elements/ol-element-container.ts +0 -12
  227. package/src/dom/elements/select-element-container.ts +0 -10
  228. package/src/dom/elements/textarea-element-container.ts +0 -9
  229. package/src/dom/node-parser.ts +0 -177
  230. package/src/dom/node-type-guards.ts +0 -70
  231. package/src/dom/replaced-elements/canvas-element-container.ts +0 -15
  232. package/src/dom/replaced-elements/iframe-element-container.ts +0 -55
  233. package/src/dom/replaced-elements/image-element-container.ts +0 -16
  234. package/src/dom/replaced-elements/index.ts +0 -5
  235. package/src/dom/replaced-elements/input-element-container.ts +0 -105
  236. package/src/dom/replaced-elements/pseudo-elements.ts +0 -0
  237. package/src/dom/replaced-elements/svg-element-container.ts +0 -23
  238. package/src/dom/text-container.ts +0 -42
  239. package/src/global.d.ts +0 -19
  240. package/src/index.ts +0 -82
  241. package/src/invariant.ts +0 -5
  242. package/src/options.ts +0 -55
  243. package/src/render/__tests__/object-fit.test.ts +0 -85
  244. package/src/render/background.ts +0 -298
  245. package/src/render/bezier-curve.ts +0 -47
  246. package/src/render/border.ts +0 -165
  247. package/src/render/bound-curves.ts +0 -388
  248. package/src/render/box-sizing.ts +0 -31
  249. package/src/render/canvas/__tests__/background-renderer.test.ts +0 -72
  250. package/src/render/canvas/__tests__/border-renderer.test.ts +0 -24
  251. package/src/render/canvas/__tests__/effects-renderer.test.ts +0 -32
  252. package/src/render/canvas/__tests__/text-renderer.test.ts +0 -471
  253. package/src/render/canvas/background-renderer.ts +0 -271
  254. package/src/render/canvas/border-renderer.ts +0 -224
  255. package/src/render/canvas/canvas-path.ts +0 -31
  256. package/src/render/canvas/canvas-renderer.ts +0 -641
  257. package/src/render/canvas/effects-renderer.ts +0 -130
  258. package/src/render/canvas/foreignobject-renderer.ts +0 -53
  259. package/src/render/canvas/text-renderer.ts +0 -700
  260. package/src/render/effects.ts +0 -75
  261. package/src/render/font-metrics.ts +0 -72
  262. package/src/render/object-fit.ts +0 -100
  263. package/src/render/path.ts +0 -37
  264. package/src/render/renderer-interface.ts +0 -28
  265. package/src/render/stacking-context.ts +0 -386
  266. package/src/render/vector.ts +0 -19
@@ -1,31 +0,0 @@
1
- import { Logger } from './logger';
2
- import { Cache, ResourceOptions } from './cache-storage';
3
- import { Bounds } from '../css/layout/bounds';
4
- import { OriginChecker } from './origin-checker';
5
- import { Html2CanvasConfig } from '../config';
6
-
7
- export type ContextOptions = {
8
- logging: boolean;
9
- cache?: Cache;
10
- } & ResourceOptions;
11
-
12
- export class Context {
13
- private readonly instanceName = `#${Context.instanceCount++}`;
14
- readonly logger: Logger;
15
- readonly cache: Cache;
16
- readonly originChecker: OriginChecker;
17
- readonly config: Html2CanvasConfig;
18
-
19
- private static instanceCount = 1;
20
-
21
- constructor(
22
- options: ContextOptions,
23
- public windowBounds: Bounds,
24
- config: Html2CanvasConfig
25
- ) {
26
- this.config = config;
27
- this.logger = new Logger({ id: this.instanceName, enabled: options.logging });
28
- this.originChecker = new OriginChecker(config.window);
29
- this.cache = options.cache ?? config.cache ?? new Cache(this, options);
30
- }
31
- }
@@ -1,32 +0,0 @@
1
- const elementDebuggerAttribute = 'data-html2canvas-debug';
2
- export const enum DebuggerType {
3
- NONE,
4
- ALL,
5
- CLONE,
6
- PARSE,
7
- RENDER
8
- }
9
-
10
- const getElementDebugType = (element: Element): DebuggerType => {
11
- if (typeof element.getAttribute !== 'function') {
12
- return DebuggerType.NONE;
13
- }
14
- const attribute = element.getAttribute(elementDebuggerAttribute);
15
- switch (attribute) {
16
- case 'all':
17
- return DebuggerType.ALL;
18
- case 'clone':
19
- return DebuggerType.CLONE;
20
- case 'parse':
21
- return DebuggerType.PARSE;
22
- case 'render':
23
- return DebuggerType.RENDER;
24
- default:
25
- return DebuggerType.NONE;
26
- }
27
- };
28
-
29
- export const isDebugging = (element: Element, type: Omit<DebuggerType, DebuggerType.NONE>): boolean => {
30
- const elementType = getElementDebugType(element);
31
- return elementType === DebuggerType.ALL || type === elementType;
32
- };
@@ -1,222 +0,0 @@
1
- import { fromCodePoint, toCodePoints } from 'css-line-break';
2
-
3
- const testRangeBounds = (document: Document) => {
4
- const TEST_HEIGHT = 123;
5
-
6
- if (document.createRange) {
7
- const range = document.createRange();
8
- if (range.getBoundingClientRect) {
9
- const testElement = document.createElement('boundtest');
10
- testElement.style.height = `${TEST_HEIGHT}px`;
11
- testElement.style.display = 'block';
12
- document.body.appendChild(testElement);
13
-
14
- range.selectNode(testElement);
15
- const rangeBounds = range.getBoundingClientRect();
16
- const rangeHeight = Math.round(rangeBounds.height);
17
- document.body.removeChild(testElement);
18
- if (rangeHeight === TEST_HEIGHT) {
19
- return true;
20
- }
21
- }
22
- }
23
-
24
- return false;
25
- };
26
-
27
- const testIOSLineBreak = (document: Document) => {
28
- const testElement = document.createElement('boundtest');
29
- testElement.style.width = '50px';
30
- testElement.style.display = 'block';
31
- testElement.style.fontSize = '12px';
32
- testElement.style.letterSpacing = '0px';
33
- testElement.style.wordSpacing = '0px';
34
- document.body.appendChild(testElement);
35
- const range = document.createRange();
36
-
37
- testElement.innerHTML = typeof ''.repeat === 'function' ? '&#128104;'.repeat(10) : '';
38
-
39
- const node = testElement.firstChild as Text;
40
-
41
- const textList = toCodePoints(node.data).map((i) => fromCodePoint(i));
42
- let offset = 0;
43
- let prev: DOMRect = {} as DOMRect;
44
-
45
- // ios 13 does not handle range getBoundingClientRect line changes correctly #2177
46
- const supports = textList.every((text, i) => {
47
- range.setStart(node, offset);
48
- range.setEnd(node, offset + text.length);
49
- const rect = range.getBoundingClientRect();
50
-
51
- offset += text.length;
52
- const boundAhead = rect.x > prev.x || rect.y > prev.y;
53
-
54
- prev = rect;
55
- if (i === 0) {
56
- return true;
57
- }
58
-
59
- return boundAhead;
60
- });
61
-
62
- document.body.removeChild(testElement);
63
- return supports;
64
- };
65
-
66
- const testCORS = (): boolean => typeof new Image().crossOrigin !== 'undefined';
67
-
68
- const testResponseType = (): boolean => typeof new XMLHttpRequest().responseType === 'string';
69
-
70
- const testSVG = (document: Document): boolean => {
71
- const img = new Image();
72
- const canvas = document.createElement('canvas');
73
- const ctx = canvas.getContext('2d');
74
- if (!ctx) {
75
- return false;
76
- }
77
-
78
- img.src = `data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>`;
79
-
80
- try {
81
- ctx.drawImage(img, 0, 0);
82
- canvas.toDataURL();
83
- } catch (e) {
84
- return false;
85
- }
86
- return true;
87
- };
88
-
89
- const isGreenPixel = (data: Uint8ClampedArray): boolean =>
90
- data[0] === 0 && data[1] === 255 && data[2] === 0 && data[3] === 255;
91
-
92
- const testForeignObject = (document: Document): Promise<boolean> => {
93
- const canvas = document.createElement('canvas');
94
- const size = 100;
95
- canvas.width = size;
96
- canvas.height = size;
97
- const ctx = canvas.getContext('2d');
98
- if (!ctx) {
99
- return Promise.reject(false);
100
- }
101
- ctx.fillStyle = 'rgb(0, 255, 0)';
102
- ctx.fillRect(0, 0, size, size);
103
-
104
- const img = new Image();
105
- const greenImageSrc = canvas.toDataURL();
106
- img.src = greenImageSrc;
107
- const svg = createForeignObjectSVG(size, size, 0, 0, img);
108
- ctx.fillStyle = 'red';
109
- ctx.fillRect(0, 0, size, size);
110
-
111
- return loadSerializedSVG(svg)
112
- .then((img: HTMLImageElement) => {
113
- ctx.drawImage(img, 0, 0);
114
- const data = ctx.getImageData(0, 0, size, size).data;
115
- ctx.fillStyle = 'red';
116
- ctx.fillRect(0, 0, size, size);
117
-
118
- const node = document.createElement('div');
119
- node.style.backgroundImage = `url(${greenImageSrc})`;
120
- node.style.height = `${size}px`;
121
- // Firefox 55 does not render inline <img /> tags
122
- return isGreenPixel(data)
123
- ? loadSerializedSVG(createForeignObjectSVG(size, size, 0, 0, node))
124
- : Promise.reject(false);
125
- })
126
- .then((img: HTMLImageElement) => {
127
- ctx.drawImage(img, 0, 0);
128
- // Edge does not render background-images
129
- return isGreenPixel(ctx.getImageData(0, 0, size, size).data);
130
- })
131
- .catch(() => false);
132
- };
133
-
134
- export const createForeignObjectSVG = (
135
- width: number,
136
- height: number,
137
- x: number,
138
- y: number,
139
- node: Node
140
- ): SVGForeignObjectElement => {
141
- const xmlns = 'http://www.w3.org/2000/svg';
142
- const svg = document.createElementNS(xmlns, 'svg');
143
- const foreignObject = document.createElementNS(xmlns, 'foreignObject');
144
- svg.setAttributeNS(null, 'width', width.toString());
145
- svg.setAttributeNS(null, 'height', height.toString());
146
-
147
- foreignObject.setAttributeNS(null, 'width', '100%');
148
- foreignObject.setAttributeNS(null, 'height', '100%');
149
- foreignObject.setAttributeNS(null, 'x', x.toString());
150
- foreignObject.setAttributeNS(null, 'y', y.toString());
151
- foreignObject.setAttributeNS(null, 'externalResourcesRequired', 'true');
152
- svg.appendChild(foreignObject);
153
-
154
- foreignObject.appendChild(node);
155
-
156
- return svg;
157
- };
158
-
159
- export const loadSerializedSVG = (svg: Node): Promise<HTMLImageElement> => {
160
- return new Promise((resolve, reject) => {
161
- const img = new Image();
162
- img.onload = () => resolve(img);
163
- img.onerror = reject;
164
-
165
- img.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(new XMLSerializer().serializeToString(svg))}`;
166
- });
167
- };
168
-
169
- export const FEATURES = {
170
- get SUPPORT_RANGE_BOUNDS(): boolean {
171
- 'use strict';
172
- const value = testRangeBounds(document);
173
- Object.defineProperty(FEATURES, 'SUPPORT_RANGE_BOUNDS', { value });
174
- return value;
175
- },
176
- get SUPPORT_WORD_BREAKING(): boolean {
177
- 'use strict';
178
- const value = FEATURES.SUPPORT_RANGE_BOUNDS && testIOSLineBreak(document);
179
- Object.defineProperty(FEATURES, 'SUPPORT_WORD_BREAKING', { value });
180
- return value;
181
- },
182
- get SUPPORT_SVG_DRAWING(): boolean {
183
- 'use strict';
184
- const value = testSVG(document);
185
- Object.defineProperty(FEATURES, 'SUPPORT_SVG_DRAWING', { value });
186
- return value;
187
- },
188
- get SUPPORT_FOREIGNOBJECT_DRAWING(): Promise<boolean> {
189
- 'use strict';
190
- const value =
191
- typeof Array.from === 'function' && typeof window.fetch === 'function'
192
- ? testForeignObject(document)
193
- : Promise.resolve(false);
194
- Object.defineProperty(FEATURES, 'SUPPORT_FOREIGNOBJECT_DRAWING', { value });
195
- return value;
196
- },
197
- get SUPPORT_CORS_IMAGES(): boolean {
198
- 'use strict';
199
- const value = testCORS();
200
- Object.defineProperty(FEATURES, 'SUPPORT_CORS_IMAGES', { value });
201
- return value;
202
- },
203
- get SUPPORT_RESPONSE_TYPE(): boolean {
204
- 'use strict';
205
- const value = testResponseType();
206
- Object.defineProperty(FEATURES, 'SUPPORT_RESPONSE_TYPE', { value });
207
- return value;
208
- },
209
- get SUPPORT_CORS_XHR(): boolean {
210
- 'use strict';
211
- const value = 'withCredentials' in new XMLHttpRequest();
212
- Object.defineProperty(FEATURES, 'SUPPORT_CORS_XHR', { value });
213
- return value;
214
- },
215
- get SUPPORT_NATIVE_TEXT_SEGMENTATION(): boolean {
216
- 'use strict';
217
-
218
- const value = !!(typeof Intl !== 'undefined' && (Intl as any).Segmenter);
219
- Object.defineProperty(FEATURES, 'SUPPORT_NATIVE_TEXT_SEGMENTATION', { value });
220
- return value;
221
- }
222
- };
@@ -1,64 +0,0 @@
1
- export interface LoggerOptions {
2
- id: string;
3
- enabled: boolean;
4
- }
5
-
6
- export class Logger {
7
- static instances: { [key: string]: Logger } = {};
8
-
9
- private readonly id: string;
10
- private readonly enabled: boolean;
11
- private readonly start: number;
12
-
13
- constructor({ id, enabled }: LoggerOptions) {
14
- this.id = id;
15
- this.enabled = enabled;
16
- this.start = Date.now();
17
- }
18
-
19
- debug(...args: unknown[]): void {
20
- if (this.enabled) {
21
- // eslint-disable-next-line no-console
22
- if (typeof window !== 'undefined' && window.console && typeof console.debug === 'function') {
23
- // eslint-disable-next-line no-console
24
- console.debug(this.id, `${this.getTime()}ms`, ...args);
25
- } else {
26
- this.info(...args);
27
- }
28
- }
29
- }
30
-
31
- getTime(): number {
32
- return Date.now() - this.start;
33
- }
34
-
35
- info(...args: unknown[]): void {
36
- if (this.enabled) {
37
- // eslint-disable-next-line no-console
38
- if (typeof window !== 'undefined' && window.console && typeof console.info === 'function') {
39
- // eslint-disable-next-line no-console
40
- console.info(this.id, `${this.getTime()}ms`, ...args);
41
- }
42
- }
43
- }
44
-
45
- warn(...args: unknown[]): void {
46
- if (this.enabled) {
47
- if (typeof window !== 'undefined' && window.console && typeof console.warn === 'function') {
48
- console.warn(this.id, `${this.getTime()}ms`, ...args);
49
- } else {
50
- this.info(...args);
51
- }
52
- }
53
- }
54
-
55
- error(...args: unknown[]): void {
56
- if (this.enabled) {
57
- if (typeof window !== 'undefined' && window.console && typeof console.error === 'function') {
58
- console.error(this.id, `${this.getTime()}ms`, ...args);
59
- } else {
60
- this.info(...args);
61
- }
62
- }
63
- }
64
- }
@@ -1,57 +0,0 @@
1
- /**
2
- * Origin Checker
3
- *
4
- * Provides origin checking functionality without global static state.
5
- * Each instance maintains its own anchor element and origin reference.
6
- *
7
- * Replaces the static methods in CacheStorage with instance-based approach.
8
- */
9
- export class OriginChecker {
10
- private readonly link: HTMLAnchorElement;
11
- private readonly origin: string;
12
-
13
- constructor(window: Window) {
14
- if (!window || !window.document) {
15
- throw new Error('Valid window object required for OriginChecker');
16
- }
17
-
18
- if (!window.location || !window.location.href) {
19
- throw new Error('Window object must have valid location');
20
- }
21
-
22
- this.link = window.document.createElement('a');
23
- this.origin = this.getOrigin(window.location.href);
24
- }
25
-
26
- /**
27
- * Get the origin (protocol + hostname + port) of a URL
28
- *
29
- * @param url - URL to parse
30
- * @returns Origin string (e.g., "https://example.com:8080")
31
- */
32
- getOrigin(url: string): string {
33
- this.link.href = url;
34
- // IE9 hack: accessing href twice to ensure it's properly parsed
35
- this.link.href = this.link.href;
36
- return this.link.protocol + this.link.hostname + this.link.port;
37
- }
38
-
39
- /**
40
- * Check if a URL is from the same origin as the context
41
- *
42
- * @param src - URL to check
43
- * @returns true if same origin, false otherwise
44
- */
45
- isSameOrigin(src: string): boolean {
46
- return this.getOrigin(src) === this.origin;
47
- }
48
-
49
- /**
50
- * Get the current context origin
51
- *
52
- * @returns The origin of the context window
53
- */
54
- getContextOrigin(): string {
55
- return this.origin;
56
- }
57
- }
@@ -1,241 +0,0 @@
1
- import { Context } from './context';
2
-
3
- /**
4
- * Performance Metric
5
- *
6
- * Represents a single performance measurement
7
- */
8
- export interface PerformanceMetric {
9
- name: string;
10
- startTime: number;
11
- endTime?: number;
12
- duration?: number;
13
- metadata?: Record<string, any>;
14
- }
15
-
16
- /**
17
- * Performance Summary
18
- *
19
- * Aggregated performance data
20
- */
21
- export interface PerformanceSummary {
22
- totalDuration: number;
23
- metrics: PerformanceMetric[];
24
- breakdown: Array<{
25
- name: string;
26
- duration: number;
27
- percentage: string;
28
- }>;
29
- }
30
-
31
- /**
32
- * Performance Monitor
33
- *
34
- * Tracks performance metrics throughout the rendering pipeline.
35
- * Provides insights into where time is spent during rendering.
36
- *
37
- * Usage:
38
- * ```typescript
39
- * const monitor = new PerformanceMonitor(context);
40
- *
41
- * monitor.start('clone');
42
- * await cloneDocument();
43
- * monitor.end('clone');
44
- *
45
- * const summary = monitor.getSummary();
46
- * ```
47
- */
48
- export class PerformanceMonitor {
49
- private readonly activeMetrics: Map<string, PerformanceMetric> = new Map();
50
- private readonly completedMetrics: PerformanceMetric[] = [];
51
- private readonly enabled: boolean;
52
- private readonly getTime: () => number;
53
-
54
- constructor(
55
- private readonly context: Context | null,
56
- enabled: boolean = true
57
- ) {
58
- this.enabled = enabled;
59
-
60
- // Fallback for environments without performance.now()
61
- this.getTime =
62
- typeof performance !== 'undefined' && typeof performance.now === 'function'
63
- ? () => performance.now()
64
- : () => Date.now();
65
- }
66
-
67
- /**
68
- * Start measuring a performance metric
69
- *
70
- * @param name - Unique name for this metric
71
- * @param metadata - Optional metadata to attach
72
- */
73
- start(name: string, metadata?: Record<string, any>): void {
74
- if (!this.enabled) {
75
- return;
76
- }
77
-
78
- if (this.activeMetrics.has(name)) {
79
- this.context?.logger.warn(`Performance metric '${name}' already started. Overwriting.`);
80
- }
81
-
82
- this.activeMetrics.set(name, {
83
- name,
84
- startTime: this.getTime(),
85
- metadata
86
- });
87
- }
88
-
89
- /**
90
- * End measuring a performance metric
91
- *
92
- * @param name - Name of the metric to end
93
- * @returns The completed metric, or undefined if not found
94
- */
95
- end(name: string): PerformanceMetric | undefined {
96
- if (!this.enabled) {
97
- return undefined;
98
- }
99
-
100
- const metric = this.activeMetrics.get(name);
101
-
102
- if (!metric) {
103
- this.context?.logger.warn(`Performance metric '${name}' not found. Was start() called?`);
104
- return undefined;
105
- }
106
-
107
- metric.endTime = this.getTime();
108
- metric.duration = metric.endTime - metric.startTime;
109
-
110
- this.completedMetrics.push(metric);
111
- this.activeMetrics.delete(name);
112
-
113
- this.context?.logger.debug(`⏱️ ${name}: ${metric.duration.toFixed(2)}ms`, metric.metadata);
114
-
115
- return metric;
116
- }
117
-
118
- /**
119
- * Measure a synchronous function
120
- *
121
- * @param name - Name for this measurement
122
- * @param fn - Function to measure
123
- * @param metadata - Optional metadata
124
- * @returns The function's return value
125
- */
126
- measure<T>(name: string, fn: () => T, metadata?: Record<string, any>): T {
127
- this.start(name, metadata);
128
- try {
129
- const result = fn();
130
- this.end(name);
131
- return result;
132
- } catch (error) {
133
- this.end(name);
134
- throw error;
135
- }
136
- }
137
-
138
- /**
139
- * Measure an asynchronous function
140
- *
141
- * @param name - Name for this measurement
142
- * @param fn - Async function to measure
143
- * @param metadata - Optional metadata
144
- * @returns Promise resolving to the function's return value
145
- */
146
- async measureAsync<T>(name: string, fn: () => Promise<T>, metadata?: Record<string, any>): Promise<T> {
147
- this.start(name, metadata);
148
- try {
149
- const result = await fn();
150
- this.end(name);
151
- return result;
152
- } catch (error) {
153
- this.end(name);
154
- throw error;
155
- }
156
- }
157
-
158
- /**
159
- * Get all completed metrics
160
- *
161
- * @returns Array of completed performance metrics
162
- */
163
- getMetrics(): PerformanceMetric[] {
164
- return [...this.completedMetrics];
165
- }
166
-
167
- /**
168
- * Get a specific metric by name
169
- *
170
- * @param name - Metric name
171
- * @returns The metric, or undefined if not found
172
- */
173
- getMetric(name: string): PerformanceMetric | undefined {
174
- return this.completedMetrics.find((m) => m.name === name);
175
- }
176
-
177
- /**
178
- * Get performance summary
179
- *
180
- * @returns Aggregated performance data
181
- */
182
- getSummary(): PerformanceSummary {
183
- const totalDuration = this.completedMetrics.reduce((sum, metric) => sum + (metric.duration || 0), 0);
184
-
185
- const breakdown = this.completedMetrics.map((metric) => ({
186
- name: metric.name,
187
- duration: metric.duration || 0,
188
- percentage: totalDuration > 0 ? (((metric.duration || 0) / totalDuration) * 100).toFixed(1) + '%' : '0%'
189
- }));
190
-
191
- return {
192
- totalDuration,
193
- metrics: this.getMetrics(),
194
- breakdown
195
- };
196
- }
197
-
198
- /**
199
- * Log performance summary to console
200
- */
201
- logSummary(): void {
202
- if (!this.enabled || this.completedMetrics.length === 0 || !this.context) {
203
- return;
204
- }
205
-
206
- const summary = this.getSummary();
207
-
208
- this.context.logger.info(`\n📊 Performance Summary (Total: ${summary.totalDuration.toFixed(2)}ms):`);
209
-
210
- summary.breakdown
211
- .sort((a, b) => b.duration - a.duration)
212
- .forEach((item) => {
213
- this.context!.logger.info(
214
- ` ${item.name.padEnd(20)} ${item.duration.toFixed(2).padStart(8)}ms ${item.percentage.padStart(6)}`
215
- );
216
- });
217
- }
218
-
219
- /**
220
- * Clear all metrics
221
- */
222
- clear(): void {
223
- this.activeMetrics.clear();
224
- this.completedMetrics.splice(0);
225
- }
226
-
227
- /**
228
- * Check if monitoring is enabled
229
- */
230
- isEnabled(): boolean {
231
- return this.enabled;
232
- }
233
-
234
- /**
235
- * Get active (uncompleted) metrics
236
- * Useful for debugging leaked measurements
237
- */
238
- getActiveMetrics(): string[] {
239
- return Array.from(this.activeMetrics.keys());
240
- }
241
- }