-
Notifications
You must be signed in to change notification settings - Fork 13
/
build-template.js
150 lines (115 loc) · 4.54 KB
/
build-template.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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
const fs = require('fs');
let natives = JSON.parse(fs.readFileSync('natives_test.json'));
const Twing = require('twing');
const { TokenType } = require('twig-lexer');
const loader = new Twing.TwingLoaderFilesystem(__dirname + '/views/');
const env = new Twing.TwingEnvironment(loader, {
autoescape: false
});
const objectify = (obj, [k, v]) => ({ ...obj, [k]: v });
env.addFilter(new Twing.TwingFilter('json_stringify', async input => JSON.stringify(input || {})));
env.addFilter(new Twing.TwingFilter('cast_to_array', async input => input));
env.addFilter(new Twing.TwingFilter('normalize_type', async input => input.replace(/\*/g, 'Ptr')));
env.addFilter(new Twing.TwingFilter('strip_author', async input => input));
env.addFilter(new Twing.TwingFilter('indent', async input => input));
env.addFilter(new Twing.TwingFilter('sort_array', async input => {
return Object.entries(input).sort(([a], [b]) => {
const aKey = (a === 'CFX') ? 'AAAAAAACFX' : a;
const bKey = (b === 'CFX') ? 'AAAAAAACFX' : b;
return aKey.localeCompare(bKey);
}).reduce(objectify, {});
}));
env.addFilter(new Twing.TwingFilter('sort_name', async input => {
return Object.entries(input).sort(([_, a], [_b, b]) => {
// JS compare makes _ first, so sort order:
// - a-z
// - _a-z
// - _hash
let aName = (a.name) ? a.name : 'zz_zz' + a.hash;
let bName = (b.name) ? b.name : 'zz_zz' + b.hash;
if (aName.startsWith('_')) {
aName = `zz${aName}`;
}
if (bName.startsWith('_')) {
bName = `zz${bName}`;
}
return aName.localeCompare(bName)
}).reduce(objectify, {});
}));
env.addFilter(new Twing.TwingFilter('makenative', async input => {
return input.toLowerCase().replace('0x', 'n_0x')
.replace(/_([a-z])/g, (sub, bit) => bit.toUpperCase())
.replace(/^([a-z])/, (sub, bit) => bit.toUpperCase());
}));
env.addFilter(new Twing.TwingFilter('pascalcase', async input => input.replace(/(?:\s|^)([a-z])/g, (sub, reg) => reg.toUpperCase())));
const remark = require('remark');
const html = require('remark-html');
const highlight = require('remark-highlight.js');
env.addFilter(new Twing.TwingFilter('mdify', async input => {
return remark()
.use(highlight)
.use(html)
.processSync(input)
.toString();
}));
env.addFilter(new Twing.TwingFilter('nop', async input => {
return input.replace(/<\/?p>/g, '');
}));
// exports.TwingToken = require('./twing/token').TwingToken;
class CodeBlockNode extends Twing.TwingNode {
constructor(body, line, tag) {
super(new Map([[ 'body', body ]]), {}, line, tag);
}
compile(compiler) {
compiler.write('let highlighter = this.environment.extensionSet.getExtension("CodeBlockHighlighter");\n');
compiler.write('outputBuffer.start();\n');
compiler.subcompile(this.getNode('body'));
compiler.write('let body = outputBuffer.getAndClean();\n');
compiler.write('let code = highlighter.highlight(body);\n');
compiler.write('outputBuffer.echo(`<figure class="code"><pre><code>${code}</code></pre></figure>`);');
}
}
class CodeBlockTokenParser extends Twing.TwingTokenParser {
parse(token) {
const parser = this.parser;
const stream = parser.getStream();
while (!stream.getCurrent().test(TokenType.TAG_END)) {
this.parseEncounteredToken(stream.getCurrent(), stream);
}
stream.expect(TokenType.TAG_END);
// seriously, PHP-like callables?!
const body = parser.subparse([this, this.decideBlockEnd], true);
stream.expect(TokenType.TAG_END);
return new CodeBlockNode(body, token.line, this.getTag());
}
parseEncounteredToken(token, stream) {
// TODO
}
decideBlockEnd(token) {
return token.test(TokenType.NAME, 'endcodeblock');
}
getTag() {
return 'codeblock';
}
}
const hljs = require('highlight.js');
class CodeBlockHighlighter extends Twing.TwingExtension {
highlight(str) {
return hljs.highlight('c', str).value;
}
}
env.addTokenParser(new CodeBlockTokenParser());
env.addExtension(new CodeBlockHighlighter(), 'CodeBlockHighlighter');
const templateName = process.argv.length >= 3 ? process.argv[2] : 'lua';
if (process.argv.length >= 4 && process.argv[3] == 'CFX') {
natives = { CFX: natives.CFX };
}
(async() => {
try {
const out = await env.render(templateName + '.twig', { natives });
process.stdout.write(out);
} catch (e) {
console.error(e);
process.exit(1);
}
})();