html2canvas-pro 2.1.0 → 2.1.1
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/dist/html2canvas-pro.esm.js +21 -7
- package/dist/html2canvas-pro.esm.js.map +1 -1
- package/dist/html2canvas-pro.js +21 -7
- package/dist/html2canvas-pro.js.map +1 -1
- package/dist/html2canvas-pro.min.js +3 -3
- package/dist/lib/core/cache-storage.js +2 -2
- package/dist/lib/core/features.js +2 -2
- package/dist/lib/render/canvas/background-renderer.js +6 -0
- package/dist/lib/render/canvas/canvas-renderer.js +5 -1
- package/dist/lib/render/canvas/foreignobject-renderer.js +5 -1
- package/package.json +3 -11
- package/dist/lib/invariant.js +0 -9
- package/dist/types/invariant.d.ts +0 -1
- package/src/__tests__/index.ts +0 -99
- package/src/config.ts +0 -107
- package/src/core/__mocks__/cache-storage.ts +0 -1
- package/src/core/__mocks__/context.ts +0 -19
- package/src/core/__mocks__/features.ts +0 -8
- package/src/core/__mocks__/logger.ts +0 -17
- package/src/core/__tests__/cache-storage.test.ts +0 -205
- package/src/core/__tests__/cache-storage.ts +0 -278
- package/src/core/__tests__/logger.ts +0 -29
- package/src/core/__tests__/validator.ts +0 -359
- package/src/core/bitwise.ts +0 -1
- package/src/core/cache-storage.ts +0 -315
- package/src/core/context.ts +0 -31
- package/src/core/debugger.ts +0 -32
- package/src/core/features.ts +0 -222
- package/src/core/logger.ts +0 -64
- package/src/core/origin-checker.ts +0 -57
- package/src/core/performance-monitor.ts +0 -241
- package/src/core/render-element.ts +0 -272
- package/src/core/util.ts +0 -1
- package/src/core/validator.ts +0 -593
- package/src/css/index.ts +0 -427
- package/src/css/layout/__mocks__/bounds.ts +0 -6
- package/src/css/layout/bounds.ts +0 -79
- package/src/css/layout/text.ts +0 -161
- package/src/css/property-descriptor.ts +0 -49
- package/src/css/property-descriptors/__tests__/background-tests.ts +0 -65
- package/src/css/property-descriptors/__tests__/clip-path.test.ts +0 -280
- package/src/css/property-descriptors/__tests__/font-family.ts +0 -25
- package/src/css/property-descriptors/__tests__/image-rendering-integration.test.ts +0 -153
- package/src/css/property-descriptors/__tests__/image-rendering-performance.test.ts +0 -175
- package/src/css/property-descriptors/__tests__/image-rendering.test.ts +0 -72
- package/src/css/property-descriptors/__tests__/paint-order.ts +0 -87
- package/src/css/property-descriptors/__tests__/text-shadow.ts +0 -94
- package/src/css/property-descriptors/__tests__/transform-tests.ts +0 -18
- package/src/css/property-descriptors/background-clip.ts +0 -30
- package/src/css/property-descriptors/background-color.ts +0 -9
- package/src/css/property-descriptors/background-image.ts +0 -27
- package/src/css/property-descriptors/background-origin.ts +0 -31
- package/src/css/property-descriptors/background-position.ts +0 -38
- package/src/css/property-descriptors/background-repeat.ts +0 -44
- package/src/css/property-descriptors/background-size.ts +0 -27
- package/src/css/property-descriptors/border-color.ts +0 -13
- package/src/css/property-descriptors/border-radius.ts +0 -19
- package/src/css/property-descriptors/border-style.ts +0 -34
- package/src/css/property-descriptors/border-width.ts +0 -20
- package/src/css/property-descriptors/box-shadow.ts +0 -60
- package/src/css/property-descriptors/clip-path.ts +0 -271
- package/src/css/property-descriptors/color.ts +0 -9
- package/src/css/property-descriptors/content.ts +0 -26
- package/src/css/property-descriptors/counter-increment.ts +0 -43
- package/src/css/property-descriptors/counter-reset.ts +0 -36
- package/src/css/property-descriptors/direction.ts +0 -23
- package/src/css/property-descriptors/display.ts +0 -117
- package/src/css/property-descriptors/duration.ts +0 -14
- package/src/css/property-descriptors/float.ts +0 -29
- package/src/css/property-descriptors/font-family.ts +0 -38
- package/src/css/property-descriptors/font-size.ts +0 -9
- package/src/css/property-descriptors/font-style.ts +0 -25
- package/src/css/property-descriptors/font-variant.ts +0 -12
- package/src/css/property-descriptors/font-weight.ts +0 -26
- package/src/css/property-descriptors/image-rendering.ts +0 -33
- package/src/css/property-descriptors/letter-spacing.ts +0 -25
- package/src/css/property-descriptors/line-break.ts +0 -22
- package/src/css/property-descriptors/line-height.ts +0 -22
- package/src/css/property-descriptors/list-style-image.ts +0 -19
- package/src/css/property-descriptors/list-style-position.ts +0 -22
- package/src/css/property-descriptors/list-style-type.ts +0 -179
- package/src/css/property-descriptors/margin.ts +0 -13
- package/src/css/property-descriptors/mix-blend-mode.ts +0 -35
- package/src/css/property-descriptors/object-fit.ts +0 -39
- package/src/css/property-descriptors/opacity.ts +0 -15
- package/src/css/property-descriptors/overflow-wrap.ts +0 -22
- package/src/css/property-descriptors/overflow.ts +0 -34
- package/src/css/property-descriptors/padding.ts +0 -14
- package/src/css/property-descriptors/paint-order.ts +0 -42
- package/src/css/property-descriptors/position.ts +0 -30
- package/src/css/property-descriptors/quotes.ts +0 -57
- package/src/css/property-descriptors/rotate.ts +0 -34
- package/src/css/property-descriptors/text-align.ts +0 -26
- package/src/css/property-descriptors/text-decoration-color.ts +0 -9
- package/src/css/property-descriptors/text-decoration-line.ts +0 -38
- package/src/css/property-descriptors/text-decoration-style.ts +0 -32
- package/src/css/property-descriptors/text-decoration-thickness.ts +0 -30
- package/src/css/property-descriptors/text-overflow.ts +0 -23
- package/src/css/property-descriptors/text-shadow.ts +0 -52
- package/src/css/property-descriptors/text-transform.ts +0 -27
- package/src/css/property-descriptors/text-underline-offset.ts +0 -27
- package/src/css/property-descriptors/transform-origin.ts +0 -29
- package/src/css/property-descriptors/transform.ts +0 -74
- package/src/css/property-descriptors/visibility.ts +0 -25
- package/src/css/property-descriptors/webkit-line-clamp.ts +0 -30
- package/src/css/property-descriptors/webkit-text-stroke-color.ts +0 -8
- package/src/css/property-descriptors/webkit-text-stroke-width.ts +0 -15
- package/src/css/property-descriptors/word-break.ts +0 -25
- package/src/css/property-descriptors/writing-mode.ts +0 -37
- package/src/css/property-descriptors/z-index.ts +0 -27
- package/src/css/syntax/__tests__/tokernizer-tests.ts +0 -29
- package/src/css/syntax/parser.ts +0 -188
- package/src/css/syntax/tokenizer.ts +0 -822
- package/src/css/type-descriptor.ts +0 -7
- package/src/css/types/__tests__/color-tests.ts +0 -147
- package/src/css/types/__tests__/image-tests.ts +0 -239
- package/src/css/types/angle.ts +0 -86
- package/src/css/types/color-math.ts +0 -22
- package/src/css/types/color-spaces/a98.ts +0 -86
- package/src/css/types/color-spaces/p3.ts +0 -92
- package/src/css/types/color-spaces/pro-photo.ts +0 -87
- package/src/css/types/color-spaces/rec2020.ts +0 -90
- package/src/css/types/color-spaces/srgb.ts +0 -87
- package/src/css/types/color-utilities.ts +0 -452
- package/src/css/types/color.ts +0 -485
- package/src/css/types/functions/-prefix-linear-gradient.ts +0 -35
- package/src/css/types/functions/-prefix-radial-gradient.ts +0 -106
- package/src/css/types/functions/-webkit-gradient.ts +0 -69
- package/src/css/types/functions/__tests__/radial-gradient.ts +0 -69
- package/src/css/types/functions/counter.ts +0 -511
- package/src/css/types/functions/gradient.ts +0 -206
- package/src/css/types/functions/linear-gradient.ts +0 -28
- package/src/css/types/functions/radial-gradient.ts +0 -101
- package/src/css/types/image.ts +0 -120
- package/src/css/types/index.ts +0 -1
- package/src/css/types/length-percentage.ts +0 -137
- package/src/css/types/length.ts +0 -7
- package/src/css/types/time.ts +0 -20
- package/src/dom/__mocks__/document-cloner.ts +0 -22
- package/src/dom/__tests__/dom-normalizer.test.ts +0 -133
- package/src/dom/__tests__/element-container.test.ts +0 -129
- package/src/dom/document-cloner.ts +0 -929
- package/src/dom/dom-normalizer.ts +0 -133
- package/src/dom/element-container.ts +0 -75
- package/src/dom/elements/li-element-container.ts +0 -10
- package/src/dom/elements/ol-element-container.ts +0 -12
- package/src/dom/elements/select-element-container.ts +0 -10
- package/src/dom/elements/textarea-element-container.ts +0 -9
- package/src/dom/node-parser.ts +0 -177
- package/src/dom/node-type-guards.ts +0 -70
- package/src/dom/replaced-elements/canvas-element-container.ts +0 -15
- package/src/dom/replaced-elements/iframe-element-container.ts +0 -55
- package/src/dom/replaced-elements/image-element-container.ts +0 -16
- package/src/dom/replaced-elements/index.ts +0 -5
- package/src/dom/replaced-elements/input-element-container.ts +0 -105
- package/src/dom/replaced-elements/pseudo-elements.ts +0 -0
- package/src/dom/replaced-elements/svg-element-container.ts +0 -23
- package/src/dom/text-container.ts +0 -42
- package/src/global.d.ts +0 -19
- package/src/index.ts +0 -82
- package/src/invariant.ts +0 -5
- package/src/options.ts +0 -55
- package/src/render/__tests__/object-fit.test.ts +0 -85
- package/src/render/background.ts +0 -298
- package/src/render/bezier-curve.ts +0 -47
- package/src/render/border.ts +0 -165
- package/src/render/bound-curves.ts +0 -388
- package/src/render/box-sizing.ts +0 -31
- package/src/render/canvas/__tests__/background-renderer.test.ts +0 -72
- package/src/render/canvas/__tests__/border-renderer.test.ts +0 -24
- package/src/render/canvas/__tests__/effects-renderer.test.ts +0 -32
- package/src/render/canvas/__tests__/text-renderer.test.ts +0 -471
- package/src/render/canvas/background-renderer.ts +0 -271
- package/src/render/canvas/border-renderer.ts +0 -224
- package/src/render/canvas/canvas-path.ts +0 -31
- package/src/render/canvas/canvas-renderer.ts +0 -641
- package/src/render/canvas/effects-renderer.ts +0 -130
- package/src/render/canvas/foreignobject-renderer.ts +0 -53
- package/src/render/canvas/text-renderer.ts +0 -700
- package/src/render/effects.ts +0 -75
- package/src/render/font-metrics.ts +0 -72
- package/src/render/object-fit.ts +0 -100
- package/src/render/path.ts +0 -37
- package/src/render/renderer-interface.ts +0 -28
- package/src/render/stacking-context.ts +0 -386
- package/src/render/vector.ts +0 -19
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DOM Normalizer
|
|
3
|
-
* Handles DOM side effects that need to happen before rendering
|
|
4
|
-
* Extracted from ElementContainer to follow SRP
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { CSSParsedDeclaration } from '../css';
|
|
8
|
-
import { isHTMLElementNode } from './node-type-guards';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Stored original styles for restoration
|
|
12
|
-
*/
|
|
13
|
-
export interface OriginalStyles {
|
|
14
|
-
animationDuration?: string;
|
|
15
|
-
transform?: string;
|
|
16
|
-
rotate?: string;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Normalize element styles for accurate rendering
|
|
21
|
-
* This includes disabling animations and neutralizing transforms.
|
|
22
|
-
*/
|
|
23
|
-
export class DOMNormalizer {
|
|
24
|
-
/**
|
|
25
|
-
* Normalize a single element and return original styles.
|
|
26
|
-
*
|
|
27
|
-
* ## Why we replace transforms with an identity value instead of "none"
|
|
28
|
-
*
|
|
29
|
-
* `getBoundingClientRect()` returns visual (post-transform) coordinates, so we
|
|
30
|
-
* must neutralize any active transform before measuring element bounds.
|
|
31
|
-
*
|
|
32
|
-
* The naive approach of setting `transform: none` (or `rotate: none`) has a
|
|
33
|
-
* critical side-effect: per **CSS Transforms Level 2**, an element whose
|
|
34
|
-
* `transform` is non-none automatically becomes the **containing block** for
|
|
35
|
-
* all of its `position: absolute` *and* `position: fixed` descendants.
|
|
36
|
-
* Setting it to `none` destroys that role, causing children to resolve their
|
|
37
|
-
* percentage dimensions and offsets against an unintended ancestor — which
|
|
38
|
-
* produces completely wrong bounds.
|
|
39
|
-
*
|
|
40
|
-
* Solution: instead of removing the transform, we replace it with a visually
|
|
41
|
-
* inert identity value:
|
|
42
|
-
*
|
|
43
|
-
* - `transform: scale(0.5)` → `transform: translate(0, 0)`
|
|
44
|
-
* - `translate(0, 0)` is an identity transform (no visual change, no layout shift).
|
|
45
|
-
* - `getBoundingClientRect()` returns the same layout-space coordinates as
|
|
46
|
-
* if there were no transform at all.
|
|
47
|
-
* - Because the value is still non-none, the element **remains a containing
|
|
48
|
-
* block** for both `position: absolute` and `position: fixed` descendants.
|
|
49
|
-
*
|
|
50
|
-
* - `rotate: 45deg` → `rotate: 0deg`
|
|
51
|
-
* - `0deg` is the identity rotation; `0deg ≠ none`, so the same containing-
|
|
52
|
-
* block guarantee holds.
|
|
53
|
-
*
|
|
54
|
-
* @param element - Element to normalize
|
|
55
|
-
* @param styles - Parsed CSS styles
|
|
56
|
-
* @returns Original styles map for restoration
|
|
57
|
-
*/
|
|
58
|
-
static normalizeElement(element: Element, styles: CSSParsedDeclaration): OriginalStyles {
|
|
59
|
-
const originalStyles: OriginalStyles = {};
|
|
60
|
-
|
|
61
|
-
if (!isHTMLElementNode(element)) {
|
|
62
|
-
return originalStyles;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Disable animations to capture static state
|
|
66
|
-
if (styles.animationDuration.some((duration) => duration > 0)) {
|
|
67
|
-
originalStyles.animationDuration = element.style.animationDuration;
|
|
68
|
-
element.style.animationDuration = '0s';
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Replace the actual transform with an identity translate so that:
|
|
72
|
-
// 1. getBoundingClientRect() returns layout-space (unscaled/unrotated) coords.
|
|
73
|
-
// 2. The element still satisfies "transform != none" and therefore keeps
|
|
74
|
-
// its role as a containing block for position:absolute / position:fixed
|
|
75
|
-
// descendants (CSS Transforms Level 2 §2.3).
|
|
76
|
-
if (styles.transform !== null) {
|
|
77
|
-
originalStyles.transform = element.style.transform;
|
|
78
|
-
element.style.transform = 'translate(0, 0)';
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Same rationale for the standalone `rotate` property.
|
|
82
|
-
// `rotate: 0deg` is an identity rotation with no visual effect.
|
|
83
|
-
//
|
|
84
|
-
// However, individual transform properties (`rotate`, `translate`, `scale`)
|
|
85
|
-
// are part of CSS Transforms Level 2 and their containing-block guarantee
|
|
86
|
-
// is not uniformly implemented across all browsers. To be safe, if `rotate`
|
|
87
|
-
// is the only transform-like property active on this element, we also set
|
|
88
|
-
// `transform: translate(0, 0)` so that the containing-block role is reliably
|
|
89
|
-
// preserved via the well-supported `transform` property.
|
|
90
|
-
if (styles.rotate !== null) {
|
|
91
|
-
originalStyles.rotate = element.style.rotate;
|
|
92
|
-
element.style.rotate = '0deg';
|
|
93
|
-
|
|
94
|
-
// Individual transform properties (`rotate`, `translate`, `scale`) are
|
|
95
|
-
// CSS Transforms Level 2 and their containing-block guarantee is not
|
|
96
|
-
// uniformly implemented in all browsers. If `transform` was not already
|
|
97
|
-
// set to translate(0,0) in the block above (i.e. this element has
|
|
98
|
-
// `rotate` but no `transform`), we set it now so the containing-block
|
|
99
|
-
// role is reliably established via the widely-supported `transform`
|
|
100
|
-
// property – independently of browser support for individual props.
|
|
101
|
-
if (originalStyles.transform === undefined) {
|
|
102
|
-
originalStyles.transform = element.style.transform;
|
|
103
|
-
element.style.transform = 'translate(0, 0)';
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return originalStyles;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Restore element styles after rendering.
|
|
112
|
-
*
|
|
113
|
-
* @param element - Element to restore
|
|
114
|
-
* @param originalStyles - Original styles to restore
|
|
115
|
-
*/
|
|
116
|
-
static restoreElement(element: Element, originalStyles: OriginalStyles): void {
|
|
117
|
-
if (!isHTMLElementNode(element)) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (originalStyles.animationDuration !== undefined) {
|
|
122
|
-
element.style.animationDuration = originalStyles.animationDuration;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (originalStyles.transform !== undefined) {
|
|
126
|
-
element.style.transform = originalStyles.transform;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
if (originalStyles.rotate !== undefined) {
|
|
130
|
-
element.style.rotate = originalStyles.rotate;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { CSSParsedDeclaration } from '../css/index';
|
|
2
|
-
import { TextContainer } from './text-container';
|
|
3
|
-
import { Bounds, parseBounds } from '../css/layout/bounds';
|
|
4
|
-
import { isHTMLElementNode } from './node-type-guards';
|
|
5
|
-
import { Context } from '../core/context';
|
|
6
|
-
import { DebuggerType, isDebugging } from '../core/debugger';
|
|
7
|
-
import { DOMNormalizer, OriginalStyles } from './dom-normalizer';
|
|
8
|
-
|
|
9
|
-
export interface ElementContainerOptions {
|
|
10
|
-
normalizeDom?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class ElementContainer {
|
|
14
|
-
readonly styles: CSSParsedDeclaration;
|
|
15
|
-
readonly textNodes: TextContainer[] = [];
|
|
16
|
-
readonly elements: ElementContainer[] = [];
|
|
17
|
-
bounds: Bounds;
|
|
18
|
-
|
|
19
|
-
createsStackingContext = false;
|
|
20
|
-
createsRealStackingContext = false;
|
|
21
|
-
isListOwner = false;
|
|
22
|
-
debugRender = false;
|
|
23
|
-
|
|
24
|
-
private originalStyles?: OriginalStyles;
|
|
25
|
-
private originalElement?: Element;
|
|
26
|
-
|
|
27
|
-
constructor(
|
|
28
|
-
protected readonly context: Context,
|
|
29
|
-
element: Element,
|
|
30
|
-
options: ElementContainerOptions = {}
|
|
31
|
-
) {
|
|
32
|
-
if (isDebugging(element, DebuggerType.PARSE)) {
|
|
33
|
-
debugger;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
this.styles = new CSSParsedDeclaration(context, context.config.window.getComputedStyle(element, null));
|
|
37
|
-
|
|
38
|
-
const shouldNormalize = options.normalizeDom !== false;
|
|
39
|
-
if (shouldNormalize && isHTMLElementNode(element)) {
|
|
40
|
-
this.originalStyles = DOMNormalizer.normalizeElement(element, this.styles);
|
|
41
|
-
this.originalElement = element;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
this.bounds = parseBounds(this.context, element);
|
|
45
|
-
|
|
46
|
-
if (isDebugging(element, DebuggerType.RENDER)) {
|
|
47
|
-
this.debugRender = true;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Restore original element styles (if normalized)
|
|
53
|
-
* Call this after rendering is complete to clean up DOM state
|
|
54
|
-
*/
|
|
55
|
-
restore(): void {
|
|
56
|
-
if (this.originalStyles && this.originalElement) {
|
|
57
|
-
DOMNormalizer.restoreElement(this.originalElement, this.originalStyles);
|
|
58
|
-
// Clear references to prevent memory leaks
|
|
59
|
-
this.originalStyles = undefined;
|
|
60
|
-
this.originalElement = undefined;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Recursively restore all elements in the tree
|
|
66
|
-
* Call this on the root container after rendering is complete
|
|
67
|
-
*/
|
|
68
|
-
restoreTree(): void {
|
|
69
|
-
this.restore();
|
|
70
|
-
// Recursively restore all child elements
|
|
71
|
-
for (const child of this.elements) {
|
|
72
|
-
child.restoreTree();
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ElementContainer } from '../element-container';
|
|
2
|
-
import { Context } from '../../core/context';
|
|
3
|
-
export class LIElementContainer extends ElementContainer {
|
|
4
|
-
readonly value: number;
|
|
5
|
-
|
|
6
|
-
constructor(context: Context, element: HTMLLIElement) {
|
|
7
|
-
super(context, element);
|
|
8
|
-
this.value = element.value;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { ElementContainer } from '../element-container';
|
|
2
|
-
import { Context } from '../../core/context';
|
|
3
|
-
export class OLElementContainer extends ElementContainer {
|
|
4
|
-
readonly start: number;
|
|
5
|
-
readonly reversed: boolean;
|
|
6
|
-
|
|
7
|
-
constructor(context: Context, element: HTMLOListElement) {
|
|
8
|
-
super(context, element);
|
|
9
|
-
this.start = element.start;
|
|
10
|
-
this.reversed = typeof element.reversed === 'boolean' && element.reversed === true;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { ElementContainer } from '../element-container';
|
|
2
|
-
import { Context } from '../../core/context';
|
|
3
|
-
export class SelectElementContainer extends ElementContainer {
|
|
4
|
-
readonly value: string;
|
|
5
|
-
constructor(context: Context, element: HTMLSelectElement) {
|
|
6
|
-
super(context, element);
|
|
7
|
-
const option = element.options[element.selectedIndex || 0];
|
|
8
|
-
this.value = option ? option.text || '' : '';
|
|
9
|
-
}
|
|
10
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { ElementContainer } from '../element-container';
|
|
2
|
-
import { Context } from '../../core/context';
|
|
3
|
-
export class TextareaElementContainer extends ElementContainer {
|
|
4
|
-
readonly value: string;
|
|
5
|
-
constructor(context: Context, element: HTMLTextAreaElement) {
|
|
6
|
-
super(context, element);
|
|
7
|
-
this.value = element.value;
|
|
8
|
-
}
|
|
9
|
-
}
|
package/src/dom/node-parser.ts
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import { CSSParsedDeclaration } from '../css';
|
|
2
|
-
import { ElementContainer } from './element-container';
|
|
3
|
-
import { TextContainer } from './text-container';
|
|
4
|
-
import { ImageElementContainer } from './replaced-elements/image-element-container';
|
|
5
|
-
import { CanvasElementContainer } from './replaced-elements/canvas-element-container';
|
|
6
|
-
import { SVGElementContainer } from './replaced-elements/svg-element-container';
|
|
7
|
-
import { LIElementContainer } from './elements/li-element-container';
|
|
8
|
-
import { OLElementContainer } from './elements/ol-element-container';
|
|
9
|
-
import { InputElementContainer } from './replaced-elements/input-element-container';
|
|
10
|
-
import { SelectElementContainer } from './elements/select-element-container';
|
|
11
|
-
import { TextareaElementContainer } from './elements/textarea-element-container';
|
|
12
|
-
import { IFrameElementContainer } from './replaced-elements/iframe-element-container';
|
|
13
|
-
import { Context } from '../core/context';
|
|
14
|
-
import {
|
|
15
|
-
isBodyElement,
|
|
16
|
-
isCanvasElement,
|
|
17
|
-
isCustomElement,
|
|
18
|
-
isElementNode,
|
|
19
|
-
isHTMLElement,
|
|
20
|
-
isHTMLElementNode,
|
|
21
|
-
isIFrameElement,
|
|
22
|
-
isImageElement,
|
|
23
|
-
isInputElement,
|
|
24
|
-
isLIElement,
|
|
25
|
-
isOLElement,
|
|
26
|
-
isScriptElement,
|
|
27
|
-
isSelectElement,
|
|
28
|
-
isSlotElement,
|
|
29
|
-
isStyleElement,
|
|
30
|
-
isSVGElement,
|
|
31
|
-
isSVGElementNode,
|
|
32
|
-
isTextareaElement,
|
|
33
|
-
isTextNode,
|
|
34
|
-
isVideoElement
|
|
35
|
-
} from './node-type-guards';
|
|
36
|
-
|
|
37
|
-
// Re-export all type guards for backward compatibility
|
|
38
|
-
export {
|
|
39
|
-
isBodyElement,
|
|
40
|
-
isCanvasElement,
|
|
41
|
-
isCustomElement,
|
|
42
|
-
isElementNode,
|
|
43
|
-
isHTMLElement,
|
|
44
|
-
isHTMLElementNode,
|
|
45
|
-
isIFrameElement,
|
|
46
|
-
isImageElement,
|
|
47
|
-
isInputElement,
|
|
48
|
-
isLIElement,
|
|
49
|
-
isOLElement,
|
|
50
|
-
isScriptElement,
|
|
51
|
-
isSelectElement,
|
|
52
|
-
isSlotElement,
|
|
53
|
-
isStyleElement,
|
|
54
|
-
isSVGElement,
|
|
55
|
-
isSVGElementNode,
|
|
56
|
-
isTextareaElement,
|
|
57
|
-
isTextNode,
|
|
58
|
-
isVideoElement
|
|
59
|
-
};
|
|
60
|
-
import { contains } from '../core/bitwise';
|
|
61
|
-
import { DISPLAY } from '../css/property-descriptors/display';
|
|
62
|
-
|
|
63
|
-
const LIST_OWNERS = ['OL', 'UL', 'MENU'];
|
|
64
|
-
|
|
65
|
-
const parseNodeTree = (context: Context, node: Node, parent: ElementContainer, root: ElementContainer) => {
|
|
66
|
-
for (let childNode = node.firstChild, nextNode; childNode; childNode = nextNode) {
|
|
67
|
-
nextNode = childNode.nextSibling;
|
|
68
|
-
|
|
69
|
-
// Fixes #2238 #1624 - Fix the issue of TextNode content being overlooked in rendering due to being perceived as blank by trim().
|
|
70
|
-
if (isTextNode(childNode) && childNode.data.length > 0) {
|
|
71
|
-
parent.textNodes.push(new TextContainer(context, childNode, parent.styles));
|
|
72
|
-
} else if (isElementNode(childNode)) {
|
|
73
|
-
if (isSlotElement(childNode) && childNode.assignedNodes) {
|
|
74
|
-
childNode
|
|
75
|
-
.assignedNodes()
|
|
76
|
-
.forEach((assignedNode: Node) => parseNodeTree(context, assignedNode, parent, root));
|
|
77
|
-
} else {
|
|
78
|
-
const container = createContainer(context, childNode);
|
|
79
|
-
if (container.styles.isVisible()) {
|
|
80
|
-
if (createsRealStackingContext(childNode, container, root)) {
|
|
81
|
-
container.createsRealStackingContext = true;
|
|
82
|
-
} else if (createsStackingContext(container.styles)) {
|
|
83
|
-
container.createsStackingContext = true;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (LIST_OWNERS.indexOf(childNode.tagName) !== -1) {
|
|
87
|
-
container.isListOwner = true;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
parent.elements.push(container);
|
|
91
|
-
if (childNode.shadowRoot) {
|
|
92
|
-
parseNodeTree(context, childNode.shadowRoot, container, root);
|
|
93
|
-
} else if (
|
|
94
|
-
!isTextareaElement(childNode) &&
|
|
95
|
-
!isSVGElement(childNode) &&
|
|
96
|
-
!isSelectElement(childNode)
|
|
97
|
-
) {
|
|
98
|
-
parseNodeTree(context, childNode, container, root);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const createContainer = (context: Context, element: Element): ElementContainer => {
|
|
107
|
-
if (isImageElement(element)) {
|
|
108
|
-
return new ImageElementContainer(context, element);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (isCanvasElement(element)) {
|
|
112
|
-
return new CanvasElementContainer(context, element);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (isSVGElement(element)) {
|
|
116
|
-
return new SVGElementContainer(context, element);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (isLIElement(element)) {
|
|
120
|
-
return new LIElementContainer(context, element);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (isOLElement(element)) {
|
|
124
|
-
return new OLElementContainer(context, element);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (isInputElement(element)) {
|
|
128
|
-
return new InputElementContainer(context, element);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (isSelectElement(element)) {
|
|
132
|
-
return new SelectElementContainer(context, element);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (isTextareaElement(element)) {
|
|
136
|
-
return new TextareaElementContainer(context, element);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (isIFrameElement(element)) {
|
|
140
|
-
return new IFrameElementContainer(context, element, parseTree);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return new ElementContainer(context, element);
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
export const parseTree = (context: Context, element: HTMLElement): ElementContainer => {
|
|
147
|
-
const container = createContainer(context, element);
|
|
148
|
-
container.createsRealStackingContext = true;
|
|
149
|
-
parseNodeTree(context, element, container, container);
|
|
150
|
-
return container;
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
const createsRealStackingContext = (node: Element, container: ElementContainer, root: ElementContainer): boolean => {
|
|
154
|
-
return (
|
|
155
|
-
container.styles.isPositionedWithZIndex() ||
|
|
156
|
-
container.styles.opacity < 1 ||
|
|
157
|
-
container.styles.isTransformed() ||
|
|
158
|
-
(isBodyElement(node) && root.styles.isTransparent())
|
|
159
|
-
);
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
const createsStackingContext = (styles: CSSParsedDeclaration): boolean => {
|
|
163
|
-
// Positioned and floating elements create stacking contexts
|
|
164
|
-
if (styles.isPositioned() || styles.isFloating()) {
|
|
165
|
-
return true;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Fix for Issue #137: Inline-level containers (inline-flex, inline-block, etc.)
|
|
169
|
-
// should create stacking contexts to prevent their children from being added
|
|
170
|
-
// to the parent's stacking context, which causes rendering order issues
|
|
171
|
-
return (
|
|
172
|
-
contains(styles.display, DISPLAY.INLINE_FLEX) ||
|
|
173
|
-
contains(styles.display, DISPLAY.INLINE_BLOCK) ||
|
|
174
|
-
contains(styles.display, DISPLAY.INLINE_GRID) ||
|
|
175
|
-
contains(styles.display, DISPLAY.INLINE_TABLE)
|
|
176
|
-
);
|
|
177
|
-
};
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DOM Node Type Guards
|
|
3
|
-
*
|
|
4
|
-
* All DOM node type guards consolidated here to eliminate duplication
|
|
5
|
-
* and provide a single source of truth for node type checking.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
// --- Generic node type guards ---
|
|
9
|
-
|
|
10
|
-
export const isElementNode = (node: Node): node is Element => node.nodeType === Node.ELEMENT_NODE;
|
|
11
|
-
export const isTextNode = (node: Node): node is Text => node.nodeType === Node.TEXT_NODE;
|
|
12
|
-
|
|
13
|
-
export const isSVGElementNode = (element: Element): element is SVGElement =>
|
|
14
|
-
typeof (element as SVGElement).className === 'object';
|
|
15
|
-
|
|
16
|
-
export const isHTMLElementNode = (node: Node): node is HTMLElement =>
|
|
17
|
-
isElementNode(node) && typeof (node as HTMLElement).style !== 'undefined' && !isSVGElementNode(node);
|
|
18
|
-
|
|
19
|
-
// --- Tag name based type guards ---
|
|
20
|
-
|
|
21
|
-
export const isInputElement = (node: Element): node is HTMLInputElement => node.tagName === 'INPUT';
|
|
22
|
-
export const isHTMLElement = (node: Element): node is HTMLHtmlElement => node.tagName === 'HTML';
|
|
23
|
-
export const isSVGElement = (node: Element): node is SVGSVGElement => node.tagName === 'svg';
|
|
24
|
-
export const isBodyElement = (node: Element): node is HTMLBodyElement => node.tagName === 'BODY';
|
|
25
|
-
export const isCanvasElement = (node: Element): node is HTMLCanvasElement => node.tagName === 'CANVAS';
|
|
26
|
-
export const isVideoElement = (node: Element): node is HTMLVideoElement => node.tagName === 'VIDEO';
|
|
27
|
-
export const isImageElement = (node: Element): node is HTMLImageElement => node.tagName === 'IMG';
|
|
28
|
-
export const isIFrameElement = (node: Element): node is HTMLIFrameElement => node.tagName === 'IFRAME';
|
|
29
|
-
export const isStyleElement = (node: Element): node is HTMLStyleElement => node.tagName === 'STYLE';
|
|
30
|
-
export const isScriptElement = (node: Element): node is HTMLScriptElement => node.tagName === 'SCRIPT';
|
|
31
|
-
export const isTextareaElement = (node: Element): node is HTMLTextAreaElement => node.tagName === 'TEXTAREA';
|
|
32
|
-
export const isSelectElement = (node: Element): node is HTMLSelectElement => node.tagName === 'SELECT';
|
|
33
|
-
export const isSlotElement = (node: Element): node is HTMLSlotElement => node.tagName === 'SLOT';
|
|
34
|
-
export const isLIElement = (node: Element): node is HTMLLIElement => node.tagName === 'LI';
|
|
35
|
-
export const isOLElement = (node: Element): node is HTMLOListElement => node.tagName === 'OL';
|
|
36
|
-
|
|
37
|
-
export const isCustomElement = (element: Element): element is HTMLElement =>
|
|
38
|
-
!isSVGElementNode(element) && element.tagName.indexOf('-') > 0;
|
|
39
|
-
|
|
40
|
-
const VOID_OR_REPLACED_TAGS = new Set([
|
|
41
|
-
'IMG',
|
|
42
|
-
'VIDEO',
|
|
43
|
-
'AUDIO',
|
|
44
|
-
'CANVAS',
|
|
45
|
-
'IFRAME',
|
|
46
|
-
'INPUT',
|
|
47
|
-
'TEXTAREA',
|
|
48
|
-
'SELECT',
|
|
49
|
-
'BR',
|
|
50
|
-
'HR',
|
|
51
|
-
'META',
|
|
52
|
-
'LINK',
|
|
53
|
-
'BASE',
|
|
54
|
-
'COL',
|
|
55
|
-
'SOURCE',
|
|
56
|
-
'TRACK',
|
|
57
|
-
'WBR',
|
|
58
|
-
'AREA',
|
|
59
|
-
'PARAM',
|
|
60
|
-
'EMBED',
|
|
61
|
-
'OBJECT'
|
|
62
|
-
]);
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Check if an element can have ::before / ::after pseudo-elements.
|
|
66
|
-
* Per the CSS spec, replaced elements and void elements cannot have pseudo-elements.
|
|
67
|
-
* SVG elements also do not support pseudo-elements.
|
|
68
|
-
*/
|
|
69
|
-
export const canHavePseudoElements = (element: Element): boolean =>
|
|
70
|
-
!isSVGElementNode(element) && !VOID_OR_REPLACED_TAGS.has(element.tagName);
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { ElementContainer } from '../element-container';
|
|
2
|
-
import { Context } from '../../core/context';
|
|
3
|
-
|
|
4
|
-
export class CanvasElementContainer extends ElementContainer {
|
|
5
|
-
canvas: HTMLCanvasElement;
|
|
6
|
-
intrinsicWidth: number;
|
|
7
|
-
intrinsicHeight: number;
|
|
8
|
-
|
|
9
|
-
constructor(context: Context, canvas: HTMLCanvasElement) {
|
|
10
|
-
super(context, canvas);
|
|
11
|
-
this.canvas = canvas;
|
|
12
|
-
this.intrinsicWidth = canvas.width;
|
|
13
|
-
this.intrinsicHeight = canvas.height;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { ElementContainer } from '../element-container';
|
|
2
|
-
import { Color, parseColor, COLORS } from '../../css/types/color';
|
|
3
|
-
import { isTransparent } from '../../css/types/color-utilities';
|
|
4
|
-
import { Context } from '../../core/context';
|
|
5
|
-
|
|
6
|
-
// Parser function type to break circular dependency
|
|
7
|
-
type ParseTreeFunction = (context: Context, node: Node) => ElementContainer;
|
|
8
|
-
|
|
9
|
-
export class IFrameElementContainer extends ElementContainer {
|
|
10
|
-
src: string;
|
|
11
|
-
width: number;
|
|
12
|
-
height: number;
|
|
13
|
-
tree?: ElementContainer;
|
|
14
|
-
backgroundColor: Color;
|
|
15
|
-
private parseTreeFn?: ParseTreeFunction;
|
|
16
|
-
|
|
17
|
-
constructor(context: Context, iframe: HTMLIFrameElement, parseTreeFn?: ParseTreeFunction) {
|
|
18
|
-
super(context, iframe);
|
|
19
|
-
this.src = iframe.src;
|
|
20
|
-
this.width = parseInt(iframe.width, 10) || 0;
|
|
21
|
-
this.height = parseInt(iframe.height, 10) || 0;
|
|
22
|
-
this.backgroundColor = this.styles.backgroundColor;
|
|
23
|
-
this.parseTreeFn = parseTreeFn;
|
|
24
|
-
try {
|
|
25
|
-
if (
|
|
26
|
-
iframe.contentWindow &&
|
|
27
|
-
iframe.contentWindow.document &&
|
|
28
|
-
iframe.contentWindow.document.documentElement &&
|
|
29
|
-
this.parseTreeFn
|
|
30
|
-
) {
|
|
31
|
-
this.tree = this.parseTreeFn(context, iframe.contentWindow.document.documentElement);
|
|
32
|
-
|
|
33
|
-
// http://www.w3.org/TR/css3-background/#special-backgrounds
|
|
34
|
-
const documentBackgroundColor = iframe.contentWindow.document.documentElement
|
|
35
|
-
? parseColor(
|
|
36
|
-
context,
|
|
37
|
-
getComputedStyle(iframe.contentWindow.document.documentElement).backgroundColor as string
|
|
38
|
-
)
|
|
39
|
-
: COLORS.TRANSPARENT;
|
|
40
|
-
const bodyBackgroundColor = iframe.contentWindow.document.body
|
|
41
|
-
? parseColor(
|
|
42
|
-
context,
|
|
43
|
-
getComputedStyle(iframe.contentWindow.document.body).backgroundColor as string
|
|
44
|
-
)
|
|
45
|
-
: COLORS.TRANSPARENT;
|
|
46
|
-
|
|
47
|
-
this.backgroundColor = isTransparent(documentBackgroundColor)
|
|
48
|
-
? isTransparent(bodyBackgroundColor)
|
|
49
|
-
? this.styles.backgroundColor
|
|
50
|
-
: bodyBackgroundColor
|
|
51
|
-
: documentBackgroundColor;
|
|
52
|
-
}
|
|
53
|
-
} catch (e) {}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { ElementContainer } from '../element-container';
|
|
2
|
-
import { Context } from '../../core/context';
|
|
3
|
-
|
|
4
|
-
export class ImageElementContainer extends ElementContainer {
|
|
5
|
-
src: string;
|
|
6
|
-
intrinsicWidth: number;
|
|
7
|
-
intrinsicHeight: number;
|
|
8
|
-
|
|
9
|
-
constructor(context: Context, img: HTMLImageElement) {
|
|
10
|
-
super(context, img);
|
|
11
|
-
this.src = img.currentSrc || img.src;
|
|
12
|
-
this.intrinsicWidth = img.naturalWidth;
|
|
13
|
-
this.intrinsicHeight = img.naturalHeight;
|
|
14
|
-
this.context.cache.addImage(this.src);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { CanvasElementContainer } from './canvas-element-container';
|
|
2
|
-
import { ImageElementContainer } from './image-element-container';
|
|
3
|
-
import { SVGElementContainer } from './svg-element-container';
|
|
4
|
-
|
|
5
|
-
export type ReplacedElementContainer = CanvasElementContainer | ImageElementContainer | SVGElementContainer;
|