-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.js
118 lines (96 loc) · 3.24 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
/**
* class RubySassEngine
*
* Engine for the SASS/SCSS compiler. You will need `sass` Ruby gem installed
* in order to use [[Mincer]] with `*.sass` or `*.scss` files:
*
* gem install sass
*
*
* ##### SUBCLASS OF
*
* [[Template]]
**/
'use strict';
var Mincer = require('mincer');
var Template = Mincer.Template;
var prop = require('mincer/lib/mincer/common').prop;
var path = require('path');
var fs = require('fs');
var execSync = require('sync-exec');
var temp = require('temp');
var includeDirs = [];
var showRawOutput = function (path) {
return false;
};
////////////////////////////////////////////////////////////////////////////////
// Class constructor
var RubySassEngine = module.exports = function RubySassEngine() {
Template.apply(this, arguments);
};
function shellEscape (text) {
var shellescape = /[\$\\"`]/g;
return '"' + text.replace(shellescape, '\\$&') + '"';
}
require('util').inherits(RubySassEngine, Template);
RubySassEngine.addIncludeDir = function (dir) {
includeDirs.push(dir);
};
RubySassEngine.setShowRawOutput = function (fn) {
if (typeof fn === 'function') {
showRawOutput = fn;
}
};
// Render data
RubySassEngine.prototype.evaluate = function (context, locals) {
if (showRawOutput(this.file)) {
return this.data;
}
var scssInputPath = temp.path({ suffix: '.scss' }),
dirs = includeDirs.concat(path.dirname(this.file)).map(shellEscape),
dependencyPath = temp.path({ suffix: '.json' }),
cssOutputPath = temp.path({ suffix: '.css' }),
cssSourcemapOutputPath = cssOutputPath + '.map',
withSourcemap = context.environment.isEnabled('source_maps'),
cmd = [
'./sass',
'-q',
withSourcemap ? '--sourcemap' : '',
'--dependencies-out',
dependencyPath,
'-I ' + dirs.join(' -I '),
scssInputPath,
cssOutputPath
];
fs.writeFileSync(scssInputPath, this.data);
var exec = execSync(cmd.join(' '), { cwd: __dirname + '/bin' });
if (exec.status || !fs.existsSync(cssOutputPath)) {
throw new Error('Error compiling Sass: ' + exec.stderr + "\n" + exec.stdout);
}
if (!fs.existsSync(dependencyPath)) {
throw new Error('Could not load dependent files from Sass: file does not exist.\n' + exec.stdout);
}
var dependentFileContent = fs.readFileSync(dependencyPath, { encoding: 'utf8' });
if (dependentFileContent) {
var dependentFiles = JSON.parse(dependentFileContent);
dependentFiles.forEach(function (file) {
context.dependOn(path.resolve(file));
});
}
if (withSourcemap && cssSourcemapOutputPath && fs.existsSync(cssSourcemapOutputPath)) {
var sourcemap = fs.readFileSync(cssSourcemapOutputPath, { encoding: 'utf8' });
if (sourcemap) {
var map = JSON.parse(sourcemap);
var dir = path.dirname(context.pathname);
map.sources.forEach(function (file, idx) {
var rel = path.relative(dir, file);
if (path.sep === '\\') { rel = rel.replace('\\', '/'); }
map.sources[idx] = rel;
});
this.map = JSON.stringify(map);
}
}
return this.data = fs.readFileSync(cssOutputPath, { encoding: 'utf8' });
};
// Expose default MimeType of an engine
prop(RubySassEngine, 'defaultMimeType', 'text/css');