-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathindex.js
154 lines (133 loc) · 3.59 KB
/
index.js
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
'use strict';
var destroy = require('demolish')
, dollars = require('dollars')
, Supply = require('supply')
, css = require('css');
/**
* Finn: Helps you explore the dangerous worlds of CSS using pre-processing.
*
* @constructor
* @api public
*/
var Finn = Supply.extend({
constructor: function constr(context, options) {
if (!this) return new Finn(context, options);
//
// Initialize supply.
//
Supply.prototype.constructor.apply(this, arguments);
},
/**
* Initialize the Supply instance and add extra before and after hooks which
* will:
*
* - pre: Before we pass the string in to the parser.
* - post: After we've received a new string.
*
* @api private
*/
initialize: function initialize() {
this.post = new Supply(this);
this.pre = new Supply(this);
},
/**
* Compile the CSS from a string.
*
* @param {String} sheet The CSS style sheet that we need to compile.
* @param {Object} options Optional configuration for the parse & stringify.
* @param {Function} fn Completion callback.
* @api public
*/
render: function render(css, options, fn) {
if ('function' === typeof options) {
fn = options;
options = {};
}
var data = { css: css }
, finn = this;
/**
* Run the `after` hooks when everything is done.
*
* @param {Error} err Optional error.
* @param {Object} data Data to process.
* @api private
*/
function after(err, data) {
if (err) return fn(err);
finn.post.each(data, finn, function afterall(err) {
fn(err, data);
});
}
/**
* Iterate over the middleware layers after pre-processing all the things.
*
* @param {Error} err Optional error.
* @param {Object} ast Result of the parsed CSS.
* @api private
*/
function each(err, ast) {
if (err) return fn(err);
finn.each(ast.stylesheet, finn, function transformed(err) {
if (err) return fn(err);
var result = finn.stringify(ast, options);
data = {};
if ('string' !== typeof result) {
data.css = result.code;
data.map = result.map;
} else {
data.css = result;
}
if (options.sourcemap) return finn.sourcemap(data, after);
else after(err, data);
});
}
/**
* Parse the pre-processed CSS.
*
* @param {Error} err Optional err.
* @api private
*/
function parse(err) {
if (err) return fn(err);
dollars.catch(function trys() {
return finn.parse(data.css);
}, each);
}
return finn.pre.each(data, finn, parse);
},
/**
* Generate a source map from the generated CSS.
*
* @param {Object} data The compiled source.
* @param {Function} fn Completion callback.
* @api public
*/
sourcemap: function sourcemap(data, fn) {
var content = this.transform.fromObject(data.map).toBase64();
data.css += '\n/*# sourceMappingURL=data:application/json;base64,'+ content +' */';
fn(undefined, data);
},
/**
* Completely destroy the Finn instance and release all references.
*
* @type {Function}
* @returns {Boolean}
* @api public
*/
destroy: destroy('layers, providers, pre, post'),
/**
* Expose the CSS parsers and source map utilities on the prototype so it can
* be extended with different parsers easily when needed or re-used when we're
* extended.
*
* @type {Function}
* @private
*/
transform: require('convert-source-map'),
stringify: css.stringify,
parse: css.parse
});
//
// Expose the compiler.
//
module.exports = Finn;