1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | var fs = require('fs');
|
8 | var path = require('path');
|
9 | var util = require('racer/lib/util');
|
10 | var htmlUtil = require('html-util');
|
11 | var resolve = require('resolve');
|
12 |
|
13 | exports.loadViewsSync = loadViewsSync;
|
14 | exports.loadStylesSync = loadStylesSync;
|
15 | exports.cssCompiler = cssCompiler;
|
16 | exports.htmlCompiler = htmlCompiler;
|
17 |
|
18 | function loadViewsSync(app, sourceFilename, namespace) {
|
19 | var views = [];
|
20 | var files = [];
|
21 | var resolved = resolve.sync(sourceFilename, {extensions: app.viewExtensions, packageFilter: deleteMain});
|
22 | if (!resolved) {
|
23 | throw new Error('View template file not found: ' + sourceFilename);
|
24 | }
|
25 |
|
26 | var file = fs.readFileSync(resolved, 'utf8');
|
27 |
|
28 | var extension = path.extname(resolved);
|
29 | var compiler = app.compilers[extension];
|
30 | if (!compiler) {
|
31 | throw new Error('Unable to find compiler for: ' + extension);
|
32 | }
|
33 |
|
34 | var htmlFile = compiler(file, resolved);
|
35 |
|
36 | var parsed = parseViews(namespace, htmlFile, resolved, app.viewExtensions);
|
37 | for (var i = 0, len = parsed.imports.length; i < len; i++) {
|
38 | var item = parsed.imports[i];
|
39 | var imported = loadViewsSync(app, item.filename, item.namespace);
|
40 | views = views.concat(imported.views);
|
41 | files = files.concat(imported.files);
|
42 | }
|
43 | return {
|
44 | views: views.concat(parsed.views)
|
45 | , files: files.concat(resolved)
|
46 | };
|
47 | }
|
48 |
|
49 | function htmlCompiler(file, filename) {
|
50 | return file;
|
51 | }
|
52 |
|
53 | function parseViews(namespace, file, filename, extensions) {
|
54 | var imports = [];
|
55 | var views = [];
|
56 | var prefix = (namespace) ? namespace + ':' : '';
|
57 |
|
58 | htmlUtil.parse(file + '\n', {
|
59 |
|
60 |
|
61 | rawTags: /^(?:[^\s=\/!>]+:|style|script)$/i
|
62 | , matchEnd: matchEnd
|
63 | , start: onStart
|
64 | , text: onText
|
65 | });
|
66 |
|
67 | function matchEnd(tagName) {
|
68 | if (tagName.slice(-1) === ':') {
|
69 | return /<\/?[^\s=\/!>]+:[\s>]/i;
|
70 | }
|
71 | return new RegExp('</' + tagName, 'i');
|
72 | }
|
73 |
|
74 |
|
75 |
|
76 | var name, attrs;
|
77 |
|
78 | function onStart(tag, tagName, tagAttrs) {
|
79 | var lastChar = tagName.charAt(tagName.length - 1);
|
80 | if (lastChar !== ':') {
|
81 | throw new Error('Expected tag ending in colon (:) instead of ' + tag);
|
82 | }
|
83 | name = tagName.slice(0, -1);
|
84 | attrs = tagAttrs;
|
85 | if (name === 'import') {
|
86 | var dir = path.dirname(filename);
|
87 | var resolved = resolve.sync(attrs.src, {basedir: dir, extensions: extensions, packageFilter: deleteMain});
|
88 | var extension = path.extname(resolved);
|
89 | var importNamespace = (attrs.ns == null) ?
|
90 | path.basename(attrs.src, extension) : attrs.ns;
|
91 | imports.push({
|
92 | filename: resolved
|
93 | , namespace: (!importNamespace) ? namespace : prefix + importNamespace
|
94 | });
|
95 | }
|
96 | }
|
97 |
|
98 | function onText(text, isRawText) {
|
99 | if (!name || name === 'import') return;
|
100 | views.push({
|
101 | name: prefix + name
|
102 | , source: text
|
103 | , options: attrs
|
104 | , filename: filename
|
105 | });
|
106 | }
|
107 |
|
108 | return {
|
109 | imports: imports
|
110 | , views: views
|
111 | };
|
112 | }
|
113 |
|
114 | function loadStylesSync(app, sourceFilename, options) {
|
115 | options || (options = {compress: util.isProduction});
|
116 | var resolved = resolve.sync(sourceFilename, {extensions: app.styleExtensions, packageFilter: deleteMain});
|
117 | if (!resolved) {
|
118 | throw new Error('Style file not found: ' + sourceFilename);
|
119 | }
|
120 | var extension = path.extname(resolved);
|
121 | var compiler = app.compilers[extension];
|
122 | if (!compiler) {
|
123 | throw new Error('Unable to find compiler for: ' + extension);
|
124 | }
|
125 | var file = fs.readFileSync(resolved, 'utf8');
|
126 | return compiler(file, resolved, options);
|
127 | }
|
128 |
|
129 | function cssCompiler(file, filename, options) {
|
130 | return {css: file, files: [filename]};
|
131 | }
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 | function deleteMain(package) {
|
138 | delete package.main;
|
139 | }
|