Newer
Older
module.exports = function(grunt) {
require('jit-grunt')(grunt); // Just in time library loading
var fs = require('fs');
function getLoadPaths(file) {
var config;
var parts = file.split('/');
parts.pop(); // eliminate filename
// initialize search path with directory containing LESS file
var retVal = [];
retVal.push(parts.join('/'));
// Iterate through theme.config.php files collecting parent themes in search path:
while (config = fs.readFileSync("themes/" + parts[1] + "/theme.config.php", "UTF-8")) {
// First identify mixins:
var mixinMatches = config.match(/["']mixins["']\s*=>\s*\[([^\]]+)\]/);
if (mixinMatches !== null) {
var mixinParts = mixinMatches[1].split(',');
for (var i = 0; i < mixinParts.length; i++) {
parts[1] = mixinParts[i].trim().replace(/['"]/g, '');
retVal.push(parts.join('/') + '/');
}
}
// Now move up to parent theme:
var matches = config.match(/["']extends["']\s*=>\s*['"](\w+)['"]/);
// "extends" set to "false" or missing entirely? We've hit the end of the line:
if (matches === null || matches[1] === 'false') {
break;
}
parts[1] = matches[1];
retVal.push(parts.join('/') + '/');
}
return retVal;
}
var fontAwesomePath = '"../../bootstrap3/css/fonts"';
var lessFileSettings = [{
expand: true,
src: "themes/*/less/compiled.less",
rename: function (dest, src) {
return src.replace('/less/', '/css/').replace('.less', '.css');
}
}];
grunt.initConfig({
// LESS compilation
less: {
compile: {
options: {
paths: getLoadPaths,
compress: true,
modifyVars: {
'fa-font-path': fontAwesomePath
}
}
},
// Less with maps
lessdev: {
less: {
}
},
// SASS compilation
scss: {
sass: {
options: {
style: 'compress'
}
}
},
// Convert LESS to SASS, mostly for development team use
lessToSass: {
convert: {
files: [
{
expand: true,
cwd: 'themes/bootstrap3/less',
src: ['*.less', 'components/*.less'],
ext: '.scss',
dest: 'themes/bootstrap3/scss'
},
{
expand: true,
cwd: 'themes/bootprint3/less',
src: ['*.less'],
ext: '.scss',
dest: 'themes/bootprint3/scss'
},
{
expand: true,
cwd: 'themes/sandal/less',
src: ['*.less'],
ext: '.scss',
dest: 'themes/sandal/scss'
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
// Activate SCSS
{
pattern: /\/\* #SCSS>/gi,
replacement: "/* #SCSS> */",
order: -1 // Do before anything else
},
{
pattern: /<#SCSS \*\//gi,
replacement: "/* <#SCSS */",
order: -1
},
// Deactivate LESS
{
pattern: /\/\* #LESS> \*\//gi,
replacement: "/* #LESS>",
order: -1
},
{
pattern: /\/\* <#LESS \*\//gi,
replacement: "<#LESS */",
order: -1
},
{ // Change separator in @include statements
pattern: /@include ([^\(]+)\(([^\)]+)\);/gi,
replacement: function mixinCommas(match, $1, $2) {
return '@include ' + $1 + '(' + $2.replace(/;/g, ',') + ');';
order: 4 // after defaults included in less-to-sass
pattern: /unquote\("([^"]+)"\)/gi,
replacement: function ununquote(match, $1) {
return $1;
},
{ // Inline &:extends converted
pattern: /&:extend\(([^\)]+)\)/gi,
replacement: '@extend $1',
order: 4
},
{ // Wrap variables in calcs with #{}
pattern: /calc\([^;]+/gi,
replacement: function calcVariables(match) {
return match.replace(/(\$[^ ]+)/gi, '#{$1}');
},
{ // Remove !default from extends (icons.scss)
pattern: /@extend ([^;}]+) !default;/gi,
replacement: '@extend $1;',
order: 5
watch: {
options: {
atBegin: true
},
less: {
files: 'themes/*/less/**/*.less',
tasks: ['less']
},
lessdev: {
files: 'themes/*/less/**/*.less',
tasks: ['lessdev']
},
scss: {
files: 'themes/*/scss/**/*.scss',
tasks: ['scss']
}
}
});
grunt.registerMultiTask('lessdev', function lessWithMaps() {
grunt.config.set('less', {
dev: {
files: lessFileSettings,
options: {
paths: getLoadPaths,
sourceMap: true,
sourceMapFileInline: true,
modifyVars: {
'fa-font-path': fontAwesomePath
}
}
}
});
grunt.task.run('less');
});
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
grunt.registerMultiTask('scss', function sassScan() {
var sassConfig = {},
path = require('path'),
themeList = fs.readdirSync(path.resolve('themes')).filter(function (theme) {
return fs.existsSync(path.resolve('themes/' + theme + '/scss/compiled.scss'));
});
for (var i in themeList) {
var config = {
options: {
outputStyle: 'compressed'
},
files: [{
expand: true,
cwd: path.join('themes', themeList[i], 'scss'),
src: ['compiled.scss'],
dest: path.join('themes', themeList[i], 'css'),
ext: '.css'
}]
};
for (var key in this.data.options) {
config.options[key] = this.data.options[key] + '';
}
config.options.includePaths = getLoadPaths('themes/' + themeList[i] + '/scss/compiled.scss');
sassConfig[themeList[i]] = config;
}
grunt.config.set('sass', sassConfig);
grunt.task.run('sass');
});