forked from piuccio/html-to-json-data
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
52 lines (46 loc) · 1.96 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
const cheerio = require('cheerio');
const { group, text, number, attr } = require('./definitions');
const identity = (x) => x;
module.exports = (html, template) => {
const $ = cheerio.load(html);
const usesRootGroup = typeof template === 'function';
const processed = processTemplate($, undefined, usesRootGroup ? { root: template } : template);
return usesRootGroup ? processed.root : processed;
};
/**
* Process a template on a single node
*/
function processTemplate($, context, template) {
const extracted = {};
// Allow to iterate on a list of element changing context
function iterate(nestedTemplate) {
const usesRootGroup = typeof nestedTemplate === 'function';
return (nestedContext, filter) => {
const nestedProcessDefinition = createDefinitionProcessor($, nestedContext, iterate);
return nestedContext
.filter((i, node) => filter(nestedProcessDefinition))
.map((i, node) => processTemplate($, node, usesRootGroup ? { root: nestedTemplate } : nestedTemplate))
.get()
.map(usesRootGroup ? (value) => value.root : identity);
};
}
const processDefinition = createDefinitionProcessor($, context, iterate);
Object.keys(template).forEach((key) => {
if (typeof template[key] === 'function') {
extracted[key] = processDefinition(template[key]);
} else if (typeof template[key] === 'object') {
extracted[key] = processTemplate($, context, template[key]);
} else {
extracted[key] = template[key];
}
});
return extracted;
}
function createDefinitionProcessor($, context, iterate) {
return (definition) => {
const selectorFn = (selectorString) => selectorString === ':self' ? $(context) : $(selectorString, context);
const [node, getValue, transform = identity, filter = identity] = definition(selectorFn, iterate);
const result = node.length > 1 ? node.map((i, el) => getValue($(el), filter)).get() : getValue($(node), filter);
return transform(result, $, iterate);
};
}