-
Notifications
You must be signed in to change notification settings - Fork 82
Expand file tree
/
Copy pathinline-css.js
More file actions
111 lines (90 loc) · 2.83 KB
/
inline-css.js
File metadata and controls
111 lines (90 loc) · 2.83 KB
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
const parseCSS = require('css-rules');
const cheerio = require('cheerio');
const pseudoCheck = require('./pseudoCheck');
const handleRule = require('./handleRule');
const flatten = require('flat-util');
const setStyleAttrs = require('./setStyleAttrs');
const setWidthAttrs = require('./setWidthAttrs');
const removeClassId = require('./removeClassId');
const setTableAttrs = require('./setTableAttrs');
const pick = require('pick-util');
function replaceCodeBlock(html, re, block) {
return html.replace(re, () => block);
}
module.exports = (html, css, options) => {
const opts = options || {};
let rules;
let editedElements = [];
const codeBlockLookup = [];
const encodeCodeBlocks = _html => {
let __html = _html;
const blocks = opts.codeBlocks;
Object.keys(blocks).forEach(key => {
const re = new RegExp(`${blocks[key].start}([\\S\\s]*?)${blocks[key].end}`, 'g');
__html = __html.replace(re, match => {
codeBlockLookup.push(match);
return `EXCS_CODE_BLOCK_${codeBlockLookup.length - 1}_`;
});
});
return __html;
};
const decodeCodeBlocks = _html => {
let index;
let re;
let __html = _html;
for (index = 0; index < codeBlockLookup.length; index++) {
re = new RegExp(`EXCS_CODE_BLOCK_${index}_(="")?`, 'gi');
__html = replaceCodeBlock(__html, re, codeBlockLookup[index]);
}
return __html;
};
const encodeEntities = _html => encodeCodeBlocks(_html);
const decodeEntities = _html => decodeCodeBlocks(_html);
let $;
$ = cheerio.load(encodeEntities(html), pick(opts, [
'xmlMode',
'decodeEntities',
'lowerCaseTags',
'lowerCaseAttributeNames',
'recognizeCDATA',
'recognizeSelfClosing'
]), opts.isDocument);
try {
rules = parseCSS(css);
} catch (err) {
throw new Error(err);
}
rules.forEach(rule => {
let el;
let ignoredPseudos;
ignoredPseudos = pseudoCheck(rule);
if (ignoredPseudos) {
return false;
}
try {
el = handleRule(rule, $);
editedElements.push(el);
} catch (err) {
// skip invalid selector
return false;
}
return undefined;
});
// flatten array if nested
editedElements = flatten(editedElements);
editedElements.forEach(el => {
setStyleAttrs(el, $);
if (opts.applyWidthAttributes) {
setWidthAttrs(el, $);
}
if (opts.removeHtmlSelectors) {
removeClassId(el, $);
}
});
if (opts.applyTableAttributes) {
$('table').each((index, el) => {
setTableAttrs(el, $);
});
}
return decodeEntities($.html());
};