-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
141 lines (110 loc) · 3.68 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
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
const path = require('path');
const fs = require('fs');
const util = require('util');
class IncludeReplaceWebpackPlugin {
constructor(config) {
this.src = config.src || './src';
this.dist = config.dist || '.';
this.data = config.data || {};
}
apply(compiler) {
if (compiler.hooks) { // webpack 4
compiler.hooks.run.tap('IncludeReplaceWebpackPlugin', compilation => this.compileHook(compilation));
} else {
compiler.plugin('compilation', compilation => this.compileHook(compilation));
}
}
_readDir(dir) {
return util.promisify(fs.readdir)(dir);
}
_stat(file) {
return util.promisify(fs.lstat)(file);
}
_readFile(file) {
return util.promisify(fs.readFile)(file).then(file => file.toString());
}
_exists(file) {
return util.promisify(fs.exists)(file);
}
_unlink(file) {
return util.promisify(fs.unlink)(file);
}
async _mkdir(dir) {
let exists = await this._exists(dir);
if (!exists) return util.promisify(fs.mkdir)(dir);
}
async _writeFile(file, content) {
await this._mkdir(path.dirname(file));
return util.promisify(fs.writeFile)(file, content);
}
async compileHook(compilation) {
!compilation ? compilation = this.compilation : this.compilation = compilation;
const out = path.resolve(compilation.options.output.path, this.dist);
let files = await this._compile(this.src, out);
let includedFiles = files.reduce((includes, file) => {
includes.push(...file.includes);
return includes;
}, []);
let srcFolder = this.src;
if ((await this._stat(srcFolder)).isFile()) srcFolder = path.dirname(srcFolder);
for (let file of files.filter(file => !includedFiles.includes(file.input))) {
await this._writeFile(file.input.replace(srcFolder, out), file.content);
}
}
async _compile(file, out) {
let stat = await this._stat(file);
if (stat.isDirectory()) return await this._compileDir(file, out);
else if (stat.isFile()) return [await this._compileFile(file, this.data)];
else return [];
}
async _compileDir(dir, out) {
let files = [];
for (let file of await this._readDir(dir))
files.push(... await this._compile(path.resolve(dir, file), out));
return files;
}
_parseArguments(args, max = 128) {
let splittedArgs = args.split(',', max);
splittedArgs[splittedArgs.length - 1] += args.substr(splittedArgs.join(',').length);
return splittedArgs.map(item => {
item = item.trim();
let firstChar = item[0];
let lastChar = item[item.length - 1];
if (firstChar === `'` && lastChar === `'`) return item.substr(1, item.length - 2);
if (firstChar === `"` && lastChar === `"`) return item.substr(1, item.length - 2);
if (firstChar === '{' && lastChar === '}') return JSON.parse(item);
return item;
});
}
async _compileFile(file, context) {
let content = await this._readFile(file);
let includes = [];
let regex = /@@(.*?)\s*\((.*?)\)/g;
let match;
while ((match = regex.exec(content)) != null) {
if (match.index === regex.lastIndex) regex.lastIndex++;
let [full, method, args] = match;
let result = full;
if (method === 'include') {
let [include, data] = this._parseArguments(args, 2);
var location = path.resolve(path.dirname(file), include);
includes.push(location);
result = (await this._compileFile(location, { ...context, ...data })).content;
} else if (method === 'show') {
let [variable] = this._parseArguments(args, 1);
if (variable in context) {
var value = context[variable];
if (typeof value === 'Function') result = await context[variable]();
else result = context[variable];
}
}
content = content.replace(full, result);
}
return {
input: file,
includes,
content
};
}
}
module.exports = IncludeReplaceWebpackPlugin;