1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | var Crixalis = require('../controller'),
|
12 | crypto = require('crypto'),
|
13 | fs = require('fs'),
|
14 | cache = {};
|
15 |
|
16 | function serveCache (filename) {
|
17 | var result = this.results.pop(),
|
18 | mtime = +result.mtime,
|
19 | context = this.context,
|
20 | error = this.error,
|
21 | options = this.options,
|
22 | cache = crypto.createHash('md5').update(filename + mtime).digest('hex'),
|
23 | path = context.cachePath + '/' + cache + '.' + options.extension;
|
24 |
|
25 |
|
26 | context.serve(path, function (error) {
|
27 | var chain = context.chain();
|
28 |
|
29 | chain.context = context;
|
30 | chain.error = error;
|
31 | chain.options = options;
|
32 | chain.path = path;
|
33 |
|
34 | |
35 |
|
36 |
|
37 |
|
38 | chain.append(fs.readFile, null, [filename]);
|
39 | chain.append(before, chain);
|
40 | chain.append(compile, chain, [filename]);
|
41 | chain.append(after, chain);
|
42 |
|
43 | chain.forward();
|
44 | });
|
45 |
|
46 | this.forward();
|
47 | }
|
48 |
|
49 | function before () {
|
50 | this.data = this.results.pop().toString();
|
51 |
|
52 |
|
53 | this.error = onError;
|
54 |
|
55 | this.forward();
|
56 | }
|
57 |
|
58 | function compile (filename) {
|
59 | var result;
|
60 |
|
61 | try {
|
62 | result = this.options.compile.call(this, filename, this.data, this.options);
|
63 | } catch (error) {
|
64 | this.forward(error);
|
65 | return;
|
66 | }
|
67 |
|
68 | if (!this.options.async) {
|
69 | this.forward(undefined, result);
|
70 | }
|
71 | }
|
72 |
|
73 | function after () {
|
74 | var data = this.results.pop();
|
75 |
|
76 |
|
77 | this.append(fs.writeFile, undefined, [this.path, data]);
|
78 |
|
79 |
|
80 | this.append(this.context.serve, this.context, [this.path]);
|
81 |
|
82 | this.forward();
|
83 | }
|
84 |
|
85 | function notFound () {
|
86 | this.context.emit('default');
|
87 | this.context.render();
|
88 | }
|
89 |
|
90 | function onError (error) {
|
91 | this.context.emit('error', error, true);
|
92 | }
|
93 |
|
94 | module.exports = function (options) {
|
95 | if (!options || typeof options !== 'object') {
|
96 | throw new Error('Options required');
|
97 | }
|
98 |
|
99 | if (typeof options.method !== 'string') {
|
100 | throw new Error('options.method expected to be string');
|
101 | }
|
102 |
|
103 | if (typeof options.compile !== 'function') {
|
104 | throw new Error('options.compile expected to be function');
|
105 | }
|
106 |
|
107 | options.extension = options.extension || method;
|
108 |
|
109 | Crixalis.define('method', options.method, function (filename) {
|
110 | var chain = this.chain();
|
111 |
|
112 | if (typeof filename !== 'string') {
|
113 | throw new Error('Filename expected to be string');
|
114 | }
|
115 |
|
116 | chain.context = this;
|
117 | chain.error = notFound;
|
118 | chain.options = options;
|
119 |
|
120 | chain.append(fs.lstat, null, [filename]);
|
121 | chain.append(serveCache, chain, [filename]);
|
122 |
|
123 | chain.forward();
|
124 |
|
125 | return this;
|
126 | });
|
127 | };
|