-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
115 lines (100 loc) · 3.11 KB
/
index.js
File metadata and controls
115 lines (100 loc) · 3.11 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
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
const loaderUtils = require('loader-utils');
const nodeEval = require('node-eval');
const path = require('path');
const beautifyHtml = require('js-beautify').html;
/**
* BemBH loader
*
* @param {String} source
*/
function bemBHLoader(source) {
const stack = [];
const options = {
beautify: true,
name: '[name].html',
client: false, // or true or 'static'
bhFilename: require.resolve('bh'),
bhOptions: {
jsAttrName: 'data-bem',
jsAttrScheme: 'json',
xhtml: false,
},
};
Object.assign(options, loaderUtils.getOptions(this));
const self = this;
let bemFS = nodeEval(source);
// Extract templates
const bhTemplates = bemFS.filter((fileName) => {
return /\.bh\.js$/i.test(fileName);
}).map((fileName) => {
return path.resolve(fileName);
});
// Prepare BH engine
const engine = new (require(options.bhFilename)).BH;
engine.setOptions(options.bhOptions);
// Apply templates to engine
bhTemplates.forEach((fileName) => {
try {
delete require.cache[fileName];
} catch (e) {
throw new Error('Template file not found ' + fileName);
}
try {
require(fileName)(engine);
self.addDependency(fileName);
} catch (e) {
throw new Error('Error processing BH template ' + fileName);
}
});
// Load BemJson and transform with BH engine
const callback = this.async();
const request = '!@intervolga/eval-loader!' + this.resourcePath;
this.loadModule(request, (err, source) => {
if (err) {
callback(err);
return;
}
const bemJson = nodeEval(source);
// TODO: replace images,
// maybe https://github.com/webpack-contrib/html-loader
let html;
try {
html = engine.apply(bemJson);
} catch (e) {
callback(e);
return;
}
if (options.beautify) {
html = beautifyHtml(html, {});
// .replace(/\s*\/\* beautify preserve:start \*\//g, '')
// .replace(/\/\* beautify preserve:end \*\/\s*/g, '');
}
const newName = loaderUtils.interpolateName(this, options.name, {
content: html,
});
self.emitFile(newName, html);
// Remove BH templates from pipe
bemFS = bemFS.filter((fileName) => {
return !(/\.bh\.js$/i.test(fileName));
}).map((fileName) => {
return {'require': fileName};
});
if (options.client) {
const templates = bhTemplates.filter(item => !~stack.indexOf(item));
const bhClientTemplates = templates.map((fileName) => {
let safeTemplate = loaderUtils.stringifyRequest(self, fileName);
return `window.matches[${safeTemplate}] = window.matches[${safeTemplate}] || require(${safeTemplate})(bh) || true;`;
}).join('\n');
const bhClientSource = `
window.initMatches = window.initMatches ? window.initMatches : [];
window.initMatches.push(function (bh) {
window.matches = window.matches ? window.matches : [];
${bhClientTemplates}
});`;
stack.push(...bhTemplates);
bemFS.splice(0, 0, {'raw': bhClientSource});
}
callback(null, 'module.exports = ' + JSON.stringify(bemFS) + ';');
});
}
module.exports = bemBHLoader;