Repository navigation
Expand file tree
/
Copy pathengine.js
More file actions
55 lines (48 loc) · 1.66 KB
/
Copy pathengine.js
File metadata and controls
55 lines (48 loc) · 1.66 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
// engine.js
const cheerio = require("cheerio");
const rules = require("./rules");
const { extractStyleBlocks, parseCssRules } = require("./utils");
function parseInlineStylesFromCheerio($) {
const out = [];
$("[style]").each((i, el) => {
const styleAttr = $(el).attr("style") || "";
const decls = styleAttr.split(";").filter(Boolean);
const selectorLabel = `<${el.tagName}${el.attribs.class ? "." + el.attribs.class.split(" ")[0] : ""}>`;
for (const decl of decls) {
const [prop, ...rest] = decl.split(":");
if (!prop || rest.length === 0) continue;
out.push({
selector: selectorLabel,
property: prop.trim().toLowerCase(),
value: rest.join(":").trim().toLowerCase(),
});
}
});
return out;
}
function runDetector(html) {
const $ = cheerio.load(html);
const cssText = extractStyleBlocks($);
const cssRules = parseCssRules(cssText);
const inlineRules = parseInlineStylesFromCheerio($);
const allText = $("body").text();
const ctx = { $, cssRules, inlineRules, allText };
const results = [];
for (const rule of rules) {
let findings;
try {
findings = rule.check(ctx);
} catch (e) {
findings = [];
}
if (findings === null) {
results.push({ id: rule.id, category: rule.category, type: rule.type, status: "skipped", findings: [] });
} else if (findings.length > 0) {
results.push({ id: rule.id, category: rule.category, type: rule.type, status: "flagged", findings });
} else {
results.push({ id: rule.id, category: rule.category, type: rule.type, status: "clean", findings: [] });
}
}
return results;
}
module.exports = { runDetector };