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'
}
],
options: {
replacements: [
{ // Replace ; in include with ,
pattern: /(\s+)@include ([^\(]+)\(([^\)]+)\);/gi,
replacement: function mixinCommas(match, space, $1, $2) {
return space + '@include ' + $1 + '(' + $2.replace(/;/g, ',') + ');';
},
order: 3
},
{ // Remove unquote
pattern: /(\s+)unquote\("([^"]+)"\)/gi,
replacement: function mixinCommas(match, space, $1) {
return space + $1;
},
order: 3
},
{ // Inline &:extends converted
pattern: /&:extend\(([^\)]+)\)/gi,
replacement: '@extend $1',
order: 3
},
{ // Inline variables not default
pattern: / !default; }/gi,
replacement: '; }',
order: 3
},
{ // VuFind: Correct paths
pattern: 'vendor/bootstrap/bootstrap',
replacement: 'vendor/bootstrap',
order: 4
},
{
pattern: '$fa-font-path: "../../../fonts" !default;\n',
replacement: '',
order: 4
},
{
pattern: '@import "vendor/font-awesome/font-awesome";',
replacement: '$fa-font-path: ' + fontAwesomePath + ';\n@import "vendor/font-awesome/font-awesome";',
order: 4
},
{ // VuFind: Bootprint fixes
pattern: '@import "bootstrap";\n@import "variables";',
replacement: '@import "variables", "bootstrap";',
order: 4
},
{
pattern: '$brand-primary: #619144 !default;',
replacement: '$brand-primary: #619144;',
order: 4
},
// Wrap calcs in {}
{
pattern: /calc\((\$[^ ]+)/g,
replacement: 'calc(#{$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');
});