UNPKG

6.27 kBJavaScriptView Raw
1"use strict";
2
3var clone = require('clone');
4var compile = require('es6-templates').compile;
5var extend = require('extend');
6var fs = require('fs');
7var isarray = require('isarray');
8var join = require('path').join;
9var dirname = require('path').dirname;
10
11
12// -----------------------------------------------------------------------------
13// Configuration.
14var 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
26function defaultProcessor(path, file) {
27 return file;
28}
29
30var 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
41var 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
53module.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 // Match end pattern without start.
93 // end_line_idx is till equal to previous loop turn value.
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 // One liner.
103 if (start_line_idx === end_line_idx) {
104 frag = opts.oneliner_pattern.exec(lines[start_line_idx])[0];
105 }
106 // One or more lines.
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 // Using template function.
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 // Trim trailing line breaks.
151 assetFiles = assetFiles.replace(/(\n*)$/, '');
152
153 // We don't need indentation if we are going to insert it as one line
154 if(!opts.removeLineBreaks) {
155 // Indent content.
156 assetFiles = indent(assetFiles);
157 }
158
159 if(opts.removeLineBreaks) {
160 assetFiles = removeLineBreaks(assetFiles);
161 // don't need the indentation
162 indentation = '';
163 startOfInsertionBlock = '';
164 endOfInsertionBlock = '';
165 }
166
167 // Build the final string.
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 // One liner.
175 if (start_line_idx === end_line_idx) {
176 lines[start_line_idx] = line.replace(opts.oneliner_pattern, assetFiles);
177 }
178 // One or more lines.
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 // Add indentation spaces only to non-empty lines.
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};