forked from gjb2048/moodle-format_vsf
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Gruntfile.js
192 lines (173 loc) · 6.44 KB
/
Gruntfile.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/**
* Gruntfile for the Progress Section Format.
*
* This file configures tasks to be run by Grunt
* http://gruntjs.com/ for the current format.
*
*
* Requirements:
* -------------
* nodejs, npm, grunt-cli.
*
* Installation:
* -------------
* node and npm: instructions at http://nodejs.org/
*
* grunt-cli: `[sudo] npm install -g grunt-cli`
*
* node dependencies: run `npm install` in the root directory.
*
*
* Usage:
* ------
* Call tasks from the format root directory. Default behaviour
* (calling only `grunt`) is to run the watch task detailed below.
*
*
* Porcelain tasks:
* ----------------
* The nice user interface intended for everyday use. Provide a
* high level of automation and convenience for specific use-cases.
*
* grunt css Create the default CSS and lint the SCSS.
*
* grunt amd Use core, e.g. grunt amd --root=course/format/vsf
* If on Windows, then set 'linebreak-style' to 'off' in root '.eslintrc'
* as Git will handle this for us.
*
* @package format_vsf.
* @author G J Barnard - {@link http://moodle.org/user/profile.php?id=442195}
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
module.exports = function(grunt) { // jshint ignore:line
var path = require('path'),
tasks = {},
cwd = process.env.PWD || process.cwd(), // jshint ignore:line
DOMParser = require('@xmldom/xmldom').DOMParser,
xpath = require('xpath'),
semver = require('semver');
// Verify the node version is new enough.
var expected = semver.validRange(grunt.file.readJSON('package.json').engines.node);
var actual = semver.valid(process.version); // jshint ignore:line
if (!semver.satisfies(actual, expected)) {
grunt.fail.fatal('Node version too old. Require ' + expected + ', version installed: ' + actual);
}
/* Windows users can't run grunt in a subdirectory, so allow them to set
the root by passing --root=path/to/dir. */
if (grunt.option('root')) {
var root = grunt.option('root');
if (grunt.file.exists(__dirname, root)) { // jshint ignore:line
cwd = path.join(__dirname, root); // jshint ignore:line
grunt.log.ok('Setting root to ' + cwd);
} else {
grunt.fail.fatal('Setting root to ' + root + ' failed - path does not exist');
}
}
/**
* Find thirdpartylibs.xml and generate an array of paths contained within
* them (used to generate ignore files and so on).
*
* @return {array} The list of thirdparty paths.
*/
var getThirdPartyPathsFromXML = function() {
var thirdpartyfiles = grunt.file.expand('**/thirdpartylibs.xml'); // Does not currently exist but add if needed.
var libs = ['node_modules/', 'vendor/'];
thirdpartyfiles.forEach(function(file) {
var dirname = path.dirname(file);
var doc = new DOMParser().parseFromString(grunt.file.read(file));
var nodes = xpath.select("/libraries/library/location/text()", doc);
nodes.forEach(function(node) {
var lib = path.join(dirname, node.toString());
if (grunt.file.isDir(lib)) {
// Ensure trailing slash on dirs.
lib = lib.replace(/\/?$/, '/');
}
// Look for duplicate paths before adding to array.
if (libs.indexOf(lib) === -1) {
libs.push(lib);
}
});
});
return libs;
};
// PHP strings for exec task.
var moodleroot = path.dirname(path.dirname(__dirname)), // jshint ignore:line
dirrootopt = grunt.option('dirroot') || process.env.MOODLE_DIR || ''; // jshint ignore:line
// Allow user to explicitly define Moodle root dir.
if ('' !== dirrootopt) {
moodleroot = path.resolve(dirrootopt);
}
var configfile = path.join(moodleroot, 'config.php');
var decachephp = 'define(\'CLI_SCRIPT\', true);';
decachephp += 'require(\'' + configfile + '\');';
decachephp += 'purge_all_caches();';
const sass = require('node-sass');
// Project configuration.
grunt.initConfig({
sass: {
dist: {
files: {
"styles.css": "scss/styles.scss"
}
},
options: { // https://github.com/sass/node-sass#options
implementation: sass,
includePaths: ["scss/"],
indentWidth: 4,
outputStyle: 'expanded'
}
},
stylelint: {
scss: {
options: {syntax: 'scss'},
src: ['*/**/*.scss']
},
css: {
src: ['*.css'],
options: {
configOverrides: {
rules: {
// These rules have to be disabled in .stylelintrc for scss compat.
"at-rule-no-unknown": true,
}
}
}
}
},
exec: {
decache: {
cmd: 'php -r "' + decachephp + '"',
callback: function(error) {
// The 'exec' process will output error messages, just add one to confirm success.
if (!error) {
grunt.log.writeln("Moodle cache reset.");
}
}
}
}
});
/**
* Generate ignore files (utilising thirdpartylibs.xml data)
*/
tasks.ignorefiles = function() {
// An array of paths to third party directories.
var thirdPartyPaths = getThirdPartyPathsFromXML();
// Generate .stylelintignore.
var stylelintIgnores = [
'# Generated by "grunt ignorefiles"',
'style/fallback.css'
].concat(thirdPartyPaths);
grunt.file.write('.stylelintignore', stylelintIgnores.join('\n'));
};
// Register tasks.
grunt.loadNpmTasks("grunt-exec");
grunt.loadNpmTasks('grunt-sass');
grunt.loadNpmTasks('grunt-stylelint');
grunt.registerTask("decache", ["exec:decache"]);
// Register JS tasks.
grunt.registerTask('ignorefiles', 'Generate ignore files for linters', tasks.ignorefiles);
// Register CSS taks.
grunt.registerTask('css', ['ignorefiles', 'stylelint:scss', 'sass', 'stylelint:css']);
// Register the default task.
grunt.registerTask('default', ['css']);
};