-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
114 lines (92 loc) · 2.66 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
const path = require('path');
const got = require('got');
const jsdom = require('jsdom');
const { JSDOM } = jsdom;
const njk = require('nunjucks');
const isDebug = process.env.IS_DEBUG === 'true';
const port = Number(process.env.PORT || '3000');
const app = require('fastify')({ logger: true });
app.register(require('fastify-static'), {
root: path.join(__dirname, 'public'),
prefix: '/public/',
})
app.get('/', async (req, rep) => {
try {
const src = req.query.s ?? req.query.src;
if (!src) {
if (req.headers['user-agent'].match(/curl\/(\d+\.?)+/)) {
return rep.send((() => {
const title = 'redeqo';
const p = 'Web-based template mapper for terminals';
const github = 'https://github.com/0xTadash1/redeqo';
return title + ' -- ' + p + '\n' + github + '\n';
})());
} else {
return rep.sendFile('index.html');
}
}
const dom = new JSDOM(await gotBody(src));
// Priority: query > HTML meta tag
const dst = req.query.d ?? req.query.dst ?? dom.window.document
.querySelector('meta[name="redeqo-dst"]')
.getAttribute('content');
const [env, ctx] = await Promise.all([
defineNjkEnv(dom),
parseCtx(dom)
]);
// Download template as needed, and Render
if (dst.startsWith('http')) {
const template = njk.compile(await gotBody(dst), env);
return rep.send(template.render(ctx));
} else {
return rep.send(env.render(dst, ctx));
}
} catch (err) {
return err;
}
});
async function gotBody(s) {
if (s.match(/(redeqo|0z7xvl)\.deta\.dev/)) {
throw new Error('avoid recursive access');
}
return (await got(s)).body;
}
async function defineNjkEnv(dom, query = null) {
return new njk.Environment(new njk.FileSystemLoader('templates/'), {
autoescape: false,
trimBlocks: true,
watch: true
});
}
async function parseCtx(dom) {
const ctx = {};
const elms = Array.from(dom.window.document.querySelectorAll('[redeqo-key]'));
await Promise.all(elms.map(async elm => {
ctx[elm.getAttribute('redeqo-key')] = (() => {
if (elm.hasAttribute('redeqo-childKeys')) {
const childDict = {};
const childKeys = elm.getAttribute('redeqo-childKeys').split(' ');
childKeys.forEach(k => {
childDict[k] = k === 'textContent' ? elm.textContent : elm.getAttribute(k);
});
return childDict;
} else {
return elm.textContent;
}
})()
}))
return ctx;
}
const start = async () => {
try {
await app.listen(port);
} catch (err) {
app.log.error(err);
process.exit(1);
}
}
if (isDebug) {
start();
} else {
module.exports = app;
}