forked from radiocity/twig-html-loader
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.js
More file actions
126 lines (105 loc) · 3.48 KB
/
Copy pathindex.js
File metadata and controls
126 lines (105 loc) · 3.48 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
116
117
118
119
120
121
122
123
124
125
126
/* eslint prefer-arrow-callback: 0 */
/* eslint no-shadow: 0 */
const Twig = require('twig');
const utils = require('loader-utils');
const path = require('path');
// https://github.com/twigjs/twig.js/issues/608
const normalizeNamespaces = function normalizeNamespacesPathnames(namespaces) {
if (namespaces && typeof namespaces !== 'object') {
throw new Error('namespaces option should be an object');
}
const result = namespaces || {};
Object.keys(result).forEach((key) => {
if (typeof result[key] === 'string') {
const value = result[key] + path.sep;
result[key] = value.replace(/([\/\\]+)$/, path.sep);
}
});
return result;
};
const relativePathsToAbsolutePathsForSourceFn = (str, resourcePath) => {
const resourceDir = path.dirname(resourcePath);
let result = str;
let matches;
let prevSourceFnArg;
let newSourceFnArg;
let pattern;
// eslint-disable-next-line no-constant-condition
while (true) {
matches = /source\s*\(\s*['"]\s*(\.[^'"]+)['"]\s*\)/g.exec(result);
if (matches === null) {
break;
}
[, prevSourceFnArg] = matches;
newSourceFnArg = `source('${path.resolve(resourceDir, prevSourceFnArg)}')`;
pattern = `source\\s*\\(\\s*['"]\\s*${prevSourceFnArg}\\s*['"]\\s*\\)`;
result = result.replace(new RegExp(pattern, 'g'), newSourceFnArg);
}
return result;
};
module.exports = function loader(source) {
// eslint-disable-next-line no-param-reassign
source = relativePathsToAbsolutePathsForSourceFn(source, this.resourcePath);
try {
const params = this.resourceQuery && utils.parseQuery(this.resourceQuery)
const query = utils.getOptions(this) || {};
let data = query.data || {};
const templateFile = require.resolve(this.resourcePath);
const options = {
path: templateFile,
data: source,
async: false,
debug: Boolean(query.debug || false),
trace: Boolean(query.trace || false),
allowInlineIncludes: true,
rethrow: true,
namespaces: normalizeNamespaces(query.namespaces),
};
if (query.cache !== true) {
Twig.cache(false);
}
if (query.functions) {
Object.entries(query.functions).forEach(([name, fn]) => Twig.extendFunction(name, fn));
}
if (query.filters) {
Object.entries(query.filters).forEach(([name, fn]) => Twig.extendFilter(name, fn));
}
if (query.tests) {
Object.entries(query.tests).forEach(([name, fn]) => Twig.extendTest(name, fn));
}
if (query.extend) {
Twig.extend(query.extend);
}
if (typeof data === 'function') {
data = data(this);
if (typeof data !== 'object') {
this.emitError('data parameter should return an object');
}
}
if (params && typeof params.data === 'object') {
data = Object.assign({}, data, params.data)
}
const registry = [];
Twig.extend((Twig) => {
const defaultSave = Object.assign(Twig.Templates.save);
// eslint-disable-next-line no-param-reassign
Twig.Templates.save = function customSave(template) {
if (template.path) {
registry.push(path.normalize(template.path));
}
return defaultSave.call(this, template);
};
});
const template = Twig.twig(options);
const output = template.render(data);
registry.forEach(this.addDependency);
Twig.extend((Twig) => {
// eslint-disable-next-line no-param-reassign
Twig.Templates.registry = {};
});
return output;
} catch (e) {
this.callback(e);
return '';
}
};