-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
122 lines (94 loc) · 2.35 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* eslint-disable unicorn/prefer-add-event-listener */
'use strict';
const slice = Array.prototype.slice;
const reurl = /url\(\s*(['"]?)(.*?)\1\s*\)/g;
const camelCase = name => {
return name.replace(/([a-z])-([a-z])/g, (str, m1, m2) => {
return `${m1}${m2.toUpperCase()}`;
});
};
const check = obj => {
return new Promise(resolve => {
const {element, img, src} = obj;
if (img.complete && img.naturalWidth !== undefined) {
resolve(element);
}
const proxyImage = img;
proxyImage.onload = () => resolve(element);
proxyImage.onerror = () => resolve(element);
if (src !== undefined && element.src === undefined) {
proxyImage.src = src;
}
});
};
export default function (element, options) {
if (typeof element === 'string') {
element = document.querySelectorAll(element);
}
const elements = element instanceof NodeList ? slice.call(element) : [...element];
options = Object.assign({
props: [],
attrs: []
}, options);
const hasProps = Array.isArray(options.props) && options.props.length;
const hasAttrs = Array.isArray(options.attrs) && options.attrs.length;
const images = [];
elements.forEach(elem => {
const nodeType = elem.nodeType;
if (!nodeType || [1, 9, 11].indexOf(nodeType) === -1) {
return;
}
let children;
if (hasProps || hasAttrs) {
children = elem.getElementsByTagName('*');
} else {
children = elem.getElementsByTagName('img');
}
const tags = slice.call(children);
// Add self to array
tags.unshift(elem);
tags.forEach(tag => {
if (tag instanceof HTMLImageElement) {
images.push({
element: tag,
img: tag
});
}
if (hasProps) {
const style = getComputedStyle(tag);
if (!style) {
return;
}
options.props.forEach(prop => {
prop = camelCase(prop);
let match = reurl.exec(style[prop]);
while (match !== null) {
const obj = {
element: tag,
img: new Image(),
src: match[2]
};
images.push(obj);
match = reurl.exec(style[prop]);
}
});
}
if (hasAttrs) {
options.attrs.forEach(attr => {
if (typeof attr !== 'string') {
return;
}
const url = tag.getAttribute(attr);
if (url !== null) {
images.push({
element: tag,
img: new Image(),
src: url
});
}
});
}
});
});
return Promise.all(images.map(check));
}