1 | "use strict";
|
2 |
|
3 | var clone = require('clone');
|
4 | var compile = require('es6-templates').compile;
|
5 | var extend = require('extend');
|
6 | var fs = require('fs');
|
7 | var isarray = require('isarray');
|
8 | var join = require('path').join;
|
9 | var dirname = require('path').dirname;
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | var defaults = {
|
15 | base: '/',
|
16 | target: 'es6',
|
17 | indent: 2,
|
18 | useRelativePaths: false,
|
19 | removeLineBreaks: false,
|
20 | templateExtension: '.html',
|
21 | templateFunction: false,
|
22 | templateProcessor: defaultProcessor,
|
23 | styleProcessor: defaultProcessor
|
24 | };
|
25 |
|
26 | function defaultProcessor(path, file) {
|
27 | return file;
|
28 | }
|
29 |
|
30 | var htmlOptions = function (opts) {
|
31 | return {
|
32 | type: 'html',
|
33 | prop_url: 'templateUrl',
|
34 | prop: 'template',
|
35 | start_pattern: /templateUrl:.*/,
|
36 | end_pattern: new RegExp('.*\\' + opts.templateExtension + '\s*(\'\\)|\')|.*\\' + opts.templateExtension + '\s*("\\)|")'),
|
37 | oneliner_pattern: new RegExp('templateUrl.*(\\' + opts.templateExtension + '\s*(\'\\)|\')|\\' + opts.templateExtension + 's*("\\)|"))')
|
38 | };
|
39 | };
|
40 |
|
41 | var cssOptions = function () {
|
42 | return {
|
43 | type: 'css',
|
44 | prop_url: 'styleUrls',
|
45 | prop: 'styles',
|
46 | start_pattern: /styleUrls:.*/,
|
47 | end_pattern: /.*]/,
|
48 | oneliner_pattern: /styleUrls(.*?)]/
|
49 | };
|
50 | };
|
51 |
|
52 |
|
53 | module.exports = function parser(file, options) {
|
54 | var opts = extend({}, defaults, (options || {}));
|
55 | var lines = file.contents.toString().replace(/\r/g, '').split('\n');
|
56 | var start_line_idx, end_line_idx, frag;
|
57 | var HTML = false;
|
58 | var CSS = false;
|
59 |
|
60 | if (opts.templateProcessor) {
|
61 | HTML = true;
|
62 | extend(opts, htmlOptions(opts));
|
63 | execute();
|
64 | reset();
|
65 | }
|
66 | if (opts.styleProcessor) {
|
67 | CSS = true;
|
68 | extend(opts, cssOptions());
|
69 | execute();
|
70 | reset();
|
71 | }
|
72 |
|
73 | return lines.join('\n');
|
74 |
|
75 |
|
76 | function execute() {
|
77 | for(var i = 0; i < lines.length; i++) {
|
78 | var line = lines[i];
|
79 | getIndexes(line, i);
|
80 | if (i === end_line_idx && start_line_idx) {
|
81 | getFragment();
|
82 | replaceFrag();
|
83 | }
|
84 | }
|
85 | }
|
86 |
|
87 | function getIndexes(line, i) {
|
88 | if (opts.start_pattern.test(line)) {
|
89 | start_line_idx = i;
|
90 | }
|
91 | if (opts.end_pattern.test(line)) {
|
92 |
|
93 |
|
94 | if (start_line_idx <= end_line_idx) return;
|
95 | end_line_idx = i;
|
96 | }
|
97 | }
|
98 |
|
99 | function getFragment() {
|
100 | var fragStart, fragEnd;
|
101 | if (start_line_idx < 0 || end_line_idx < 0) return;
|
102 |
|
103 | if (start_line_idx === end_line_idx) {
|
104 | frag = opts.oneliner_pattern.exec(lines[start_line_idx])[0];
|
105 | }
|
106 |
|
107 | if (start_line_idx < end_line_idx) {
|
108 | fragStart = opts.start_pattern.exec(lines[start_line_idx])[0];
|
109 | fragEnd = opts.end_pattern.exec(lines[end_line_idx])[0];
|
110 | frag = concatLines();
|
111 | }
|
112 |
|
113 | function concatLines() {
|
114 | var _lines = clone(lines);
|
115 | _lines[start_line_idx] = fragStart;
|
116 | _lines[end_line_idx] = fragEnd;
|
117 | return _lines.splice(start_line_idx, end_line_idx - start_line_idx + 1).join('');
|
118 | }
|
119 | }
|
120 |
|
121 | function replaceFrag() {
|
122 | var _urls;
|
123 | var fnIndex = frag.indexOf('(');
|
124 | if (fnIndex > -1 && opts.templateFunction) {
|
125 |
|
126 | _urls = opts.templateFunction(/'(.*)'/.exec(frag)[1]);
|
127 | } else {
|
128 | _urls = eval('({' + frag + '})')[opts.prop_url];
|
129 | }
|
130 |
|
131 | var urls = isarray(_urls) ? _urls : [_urls];
|
132 | var line = lines[start_line_idx];
|
133 | var indentation = /^\s*/.exec(line)[0];
|
134 | var assetFiles = '';
|
135 | var startOfInsertionBlock = '\n';
|
136 | var endOfInsertionBlock = '\n';
|
137 |
|
138 | urls.forEach(function (url) {
|
139 | var file = getFile(url);
|
140 | var ext = /\.[0-9a-z]+$/i.exec(url);
|
141 | if (HTML && opts.templateProcessor) {
|
142 | file = opts.templateProcessor(ext, file);
|
143 | }
|
144 | if (CSS && opts.styleProcessor) {
|
145 | file = opts.styleProcessor(ext, file);
|
146 | }
|
147 | assetFiles += file;
|
148 | });
|
149 |
|
150 |
|
151 | assetFiles = assetFiles.replace(/(\n*)$/, '');
|
152 |
|
153 |
|
154 | if(!opts.removeLineBreaks) {
|
155 |
|
156 | assetFiles = indent(assetFiles);
|
157 | }
|
158 |
|
159 | if(opts.removeLineBreaks) {
|
160 | assetFiles = removeLineBreaks(assetFiles);
|
161 |
|
162 | indentation = '';
|
163 | startOfInsertionBlock = '';
|
164 | endOfInsertionBlock = '';
|
165 | }
|
166 |
|
167 |
|
168 | if ('html' === opts.type)
|
169 | assetFiles = opts.prop + ': `' + startOfInsertionBlock + assetFiles + endOfInsertionBlock + indentation + '`';
|
170 | if ('css' === opts.type)
|
171 | assetFiles = opts.prop + ': [`' + startOfInsertionBlock + assetFiles + endOfInsertionBlock + indentation + '`]';
|
172 | if ('es5' === opts.target) assetFiles = compile(assetFiles).code;
|
173 |
|
174 |
|
175 | if (start_line_idx === end_line_idx) {
|
176 | lines[start_line_idx] = line.replace(opts.oneliner_pattern, assetFiles);
|
177 | }
|
178 |
|
179 | if (start_line_idx < end_line_idx) {
|
180 | if (/(,)$/.test(lines[end_line_idx])) assetFiles += ',';
|
181 | lines[start_line_idx] = line.replace(opts.start_pattern, assetFiles);
|
182 | lines.splice(start_line_idx + 1, end_line_idx - start_line_idx);
|
183 | }
|
184 |
|
185 | function getFile(filepath) {
|
186 | var absPath = opts.useRelativePaths ? join(dirname(file.path), filepath)
|
187 | : join(process.cwd(), opts.base, filepath);
|
188 |
|
189 | return fs.readFileSync(absPath)
|
190 | .toString()
|
191 | .replace(/\r/g, '')
|
192 | .replace(/[\u200B-\u200D\uFEFF]/g, '');
|
193 | }
|
194 |
|
195 | function indent(str) {
|
196 | var lines = [];
|
197 | var spaces = '';
|
198 | for (var i = 0; i < indentation.length + opts.indent; i++) { spaces += ' '; }
|
199 | str.split('\n').forEach(function (line) {
|
200 |
|
201 | lines.push((/^(\s*)$/.test(line) ? '' : spaces) + line);
|
202 | });
|
203 | return lines.join('\n');
|
204 | }
|
205 |
|
206 | function removeLineBreaks(str) {
|
207 | return str.replace(/(\r\n|\n|\r)/gm," ");
|
208 | }
|
209 | }
|
210 |
|
211 | function reset() {
|
212 | start_line_idx = undefined;
|
213 | end_line_idx = undefined;
|
214 | frag = undefined;
|
215 | HTML = false;
|
216 | CSS = false;
|
217 | }
|
218 | };
|