a557f509cdfcfe1f296c005323d446e4430096e9
[Packages/TYPO3.CMS.git] / Build / Gruntfile.js
1 /*
2 * This file is part of the TYPO3 CMS project.
3 *
4 * It is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, either version 2
6 * of the License, or any later version.
7 *
8 * For the full copyright and license information, please read the
9 * LICENSE.txt file that was distributed with this source code.
10 *
11 * The TYPO3 project - inspiring people to share!
12 */
13
14 module.exports = function (grunt) {
15
16 /**
17 * Grunt stylefmt task
18 */
19 grunt.registerMultiTask('formatsass', 'Grunt task for stylefmt', function () {
20 var options = this.options(),
21 done = this.async(),
22 stylefmt = require('stylefmt'),
23 scss = require('postcss-scss'),
24 files = this.filesSrc.filter(function (file) {
25 return grunt.file.isFile(file);
26 }),
27 counter = 0;
28 this.files.forEach(function (file) {
29 file.src.filter(function (filepath) {
30 var content = grunt.file.read(filepath);
31 var settings = {
32 from: filepath,
33 syntax: scss
34 };
35 stylefmt.process(content, settings).then(function (result) {
36 grunt.file.write(file.dest, result.css);
37 grunt.log.success('Source file "' + filepath + '" was processed.');
38 counter++;
39 if (counter >= files.length) done(true);
40 });
41 });
42 });
43 });
44
45 // Project configuration.
46 grunt.initConfig({
47 pkg: grunt.file.readJSON('package.json'),
48 paths: {
49 resources: 'Resources/',
50 sass: '<%= paths.resources %>Public/Sass/',
51 root: '../',
52 sysext: '<%= paths.root %>typo3/sysext/',
53 form: '<%= paths.sysext %>form/Resources/',
54 frontend: '<%= paths.sysext %>frontend/Resources/',
55 install: '<%= paths.sysext %>install/Resources/',
56 linkvalidator: '<%= paths.sysext %>linkvalidator/Resources/',
57 backend: '<%= paths.sysext %>backend/Resources/',
58 t3editor: '<%= paths.sysext %>t3editor/Resources/',
59 workspaces: '<%= paths.sysext %>workspaces/Resources/',
60 ckeditor: '<%= paths.sysext %>rte_ckeditor/Resources/',
61 core: '<%= paths.sysext %>core/Resources/',
62 bower: 'bower_components/',
63 npm: 'node_modules/',
64 t3icons: '<%= paths.npm %>@typo3/icons/dist/'
65 },
66 stylelint: {
67 options: {
68 configFile: '<%= paths.root %>.stylelintrc',
69 },
70 sass: ['<%= paths.sass %>**/*.scss']
71 },
72 formatsass: {
73 sass: {
74 files: [{
75 expand: true,
76 cwd: '<%= paths.sass %>',
77 src: ['**/*.scss'],
78 dest: '<%= paths.sass %>'
79 }]
80 }
81 },
82 sass: {
83 options: {
84 outputStyle: 'expanded',
85 precision: 8,
86 includePaths: [
87 'node_modules/bootstrap-sass/assets/stylesheets',
88 'node_modules/font-awesome/scss',
89 'node_modules/eonasdan-bootstrap-datetimepicker/src/sass',
90 'node_modules/tagsort'
91 ]
92 },
93 backend: {
94 files: {
95 "<%= paths.backend %>Public/Css/backend.css": "<%= paths.sass %>backend.scss"
96 }
97 },
98 core: {
99 files: {
100 "<%= paths.core %>Public/Css/errorpage.css": "<%= paths.sass %>errorpage.scss"
101 }
102 },
103 form: {
104 files: {
105 "<%= paths.form %>Public/Css/form.css": "<%= paths.sass %>form.scss"
106 }
107 },
108 frontend: {
109 files: {
110 "<%= paths.frontend %>Public/Css/adminpanel.css": "<%= paths.sass %>adminpanel.scss"
111 }
112 },
113 install: {
114 files: {
115 "<%= paths.install %>Public/Css/install.css": "<%= paths.sass %>install.scss"
116 }
117 },
118 linkvalidator: {
119 files: {
120 "<%= paths.linkvalidator %>Public/Css/linkvalidator.css": "<%= paths.sass %>linkvalidator.scss"
121 }
122 },
123 workspaces: {
124 files: {
125 "<%= paths.workspaces %>Public/Css/preview.css": "<%= paths.sass %>workspace.scss"
126 }
127 },
128 t3editor: {
129 files: {
130 '<%= paths.t3editor %>Public/Css/t3editor.css': '<%= paths.sass %>editor.scss',
131 '<%= paths.t3editor %>Public/Css/t3editor_inner.css': '<%= paths.sass %>editor_inner.scss',
132 '<%= paths.t3editor %>Public/Css/t3editor_typoscript_colors.css': '<%= paths.sass %>editor_typoscript_colors.scss'
133 }
134 }
135 },
136 postcss: {
137 options: {
138 map: false,
139 processors: [
140 require('autoprefixer')({
141 browsers: [
142 'Chrome >= 57',
143 'Firefox >= 52',
144 'Edge >= 14',
145 'Explorer >= 11',
146 'iOS >= 9',
147 'Safari >= 8',
148 'Android >= 4',
149 'Opera >= 43'
150 ]
151 }),
152 require('postcss-clean')({
153 keepSpecialComments: 0
154 }),
155 require('postcss-banner')({
156 banner: 'This file is part of the TYPO3 CMS project.\n' +
157 '\n' +
158 'It is free software; you can redistribute it and/or modify it under\n' +
159 'the terms of the GNU General Public License, either version 2\n' +
160 'of the License, or any later version.\n' +
161 '\n' +
162 'For the full copyright and license information, please read the\n' +
163 'LICENSE.txt file that was distributed with this source code.\n' +
164 '\n' +
165 'The TYPO3 project - inspiring people to share!',
166 important: true,
167 inline: false
168 })
169 ]
170 },
171 backend: {
172 src: '<%= paths.backend %>Public/Css/*.css'
173 },
174 core: {
175 src: '<%= paths.core %>Public/Css/*.css'
176 },
177 form: {
178 src: '<%= paths.form %>Public/Css/*.css'
179 },
180 frontend: {
181 src: '<%= paths.frontend %>Public/Css/*.css'
182 },
183 install: {
184 src: '<%= paths.install %>Public/Css/*.css'
185 },
186 linkvalidator: {
187 src: '<%= paths.linkvalidator %>Public/Css/*.css'
188 },
189 t3editor: {
190 src: '<%= paths.t3editor %>Public/Css/*.css'
191 },
192 workspaces: {
193 src: '<%= paths.workspaces %>Public/Css/*.css'
194 }
195 },
196 ts: {
197 default: {
198 tsconfig: true,
199 options: {
200 verbose: false,
201 additionalFlags: '--typeRoots "node_modules/@types,types"'
202 }
203 }
204 },
205 tslint: {
206 options: {
207 configuration: 'tslint.json',
208 force: false
209 },
210 files: {
211 src: [
212 '<%= paths.sysext %>*/Resources/Private/TypeScript/**/*.ts'
213 ]
214 }
215 },
216 watch: {
217 options: {
218 livereload: true
219 },
220 sass: {
221 files: '<%= paths.sass %>**/*.scss',
222 tasks: 'css'
223 },
224 ts: {
225 files: '<%= paths.sysext %>*/Resources/Private/TypeScript/**/*.ts',
226 tasks: 'scripts'
227 }
228 },
229 copy: {
230 options: {
231 punctuation: ''
232 },
233 ts_files: {
234 files: [{
235 expand: true,
236 cwd: '<%= paths.root %>Build/JavaScript/typo3/sysext/',
237 src: ['**/*.js', '**/*.js.map'],
238 dest: '<%= paths.sysext %>',
239 rename: function (dest, src) {
240 return dest + src.replace('Resources/Private/TypeScript', 'Resources/Public/JavaScript');
241 }
242 }]
243 },
244 core_icons: {
245 files: [{
246 expand: true,
247 cwd: '<%= paths.t3icons %>',
248 src: ['**/*.svg', '!module/*'],
249 dest: '<%= paths.sysext %>core/Resources/Public/Icons/T3Icons/',
250 ext: '.svg'
251 }]
252 },
253 module_icons: {
254 files: [
255 {
256 dest: '<%= paths.sysext %>about/Resources/Public/Icons/module-about.svg',
257 src: '<%= paths.t3icons %>module/module-about.svg'
258 },
259 {
260 dest: '<%= paths.sysext %>belog/Resources/Public/Icons/module-belog.svg',
261 src: '<%= paths.t3icons %>module/module-belog.svg'
262 },
263 {
264 dest: '<%= paths.sysext %>beuser/Resources/Public/Icons/module-beuser.svg',
265 src: '<%= paths.t3icons %>module/module-beuser.svg'
266 },
267 {
268 dest: '<%= paths.sysext %>lowlevel/Resources/Public/Icons/module-config.svg',
269 src: '<%= paths.t3icons %>module/module-config.svg'
270 },
271 {
272 dest: '<%= paths.sysext %>cshmanual/Resources/Public/Icons/module-cshmanual.svg',
273 src: '<%= paths.t3icons %>module/module-cshmanual.svg'
274 },
275 {
276 dest: '<%= paths.sysext %>lowlevel/Resources/Public/Icons/module-dbint.svg',
277 src: '<%= paths.t3icons %>module/module-dbint.svg'
278 },
279 {
280 dest: '<%= paths.sysext %>documentation/Resources/Public/Icons/module-documentation.svg',
281 src: '<%= paths.t3icons %>module/module-documentation.svg'
282 },
283 {
284 dest: '<%= paths.sysext %>extensionmanager/Resources/Public/Icons/module-extensionmanager.svg',
285 src: '<%= paths.t3icons %>module/module-extensionmanager.svg'
286 },
287 {
288 dest: '<%= paths.sysext %>filelist/Resources/Public/Icons/module-filelist.svg',
289 src: '<%= paths.t3icons %>module/module-filelist.svg'
290 },
291 {
292 dest: '<%= paths.sysext %>form/Resources/Public/Icons/module-form.svg',
293 src: '<%= paths.t3icons %>module/module-form.svg'
294 },
295 {
296 dest: '<%= paths.sysext %>func/Resources/Public/Icons/module-func.svg',
297 src: '<%= paths.t3icons %>module/module-func.svg'
298 },
299 {
300 dest: '<%= paths.sysext %>indexed_search/Resources/Public/Icons/module-indexed_search.svg',
301 src: '<%= paths.t3icons %>module/module-indexed_search.svg'
302 },
303 {
304 dest: '<%= paths.sysext %>info/Resources/Public/Icons/module-info.svg',
305 src: '<%= paths.t3icons %>module/module-info.svg'
306 },
307 {
308 dest: '<%= paths.sysext %>install/Resources/Public/Icons/module-install.svg',
309 src: '<%= paths.t3icons %>module/module-install.svg'
310 },
311 {
312 dest: '<%= paths.sysext %>lang/Resources/Public/Icons/module-lang.svg',
313 src: '<%= paths.t3icons %>module/module-lang.svg'
314 },
315 {
316 dest: '<%= paths.sysext %>recordlist/Resources/Public/Icons/module-list.svg',
317 src: '<%= paths.t3icons %>module/module-list.svg'
318 },
319 {
320 dest: '<%= paths.sysext %>backend/Resources/Public/Icons/module-page.svg',
321 src: '<%= paths.t3icons %>module/module-page.svg'
322 },
323 {
324 dest: '<%= paths.sysext %>beuser/Resources/Public/Icons/module-permission.svg',
325 src: '<%= paths.t3icons %>module/module-permission.svg'
326 },
327 {
328 dest: '<%= paths.sysext %>recycler/Resources/Public/Icons/module-recycler.svg',
329 src: '<%= paths.t3icons %>module/module-recycler.svg'
330 },
331 {
332 dest: '<%= paths.sysext %>reports/Resources/Public/Icons/module-reports.svg',
333 src: '<%= paths.t3icons %>module/module-reports.svg'
334 },
335 {
336 dest: '<%= paths.sysext %>scheduler/Resources/Public/Icons/module-scheduler.svg',
337 src: '<%= paths.t3icons %>module/module-scheduler.svg'
338 },
339 {
340 dest: '<%= paths.sysext %>setup/Resources/Public/Icons/module-setup.svg',
341 src: '<%= paths.t3icons %>module/module-setup.svg'
342 },
343 {
344 dest: '<%= paths.sysext %>taskcenter/Resources/Public/Icons/module-taskcenter.svg',
345 src: '<%= paths.t3icons %>module/module-taskcenter.svg'
346 },
347 {
348 dest: '<%= paths.sysext %>tstemplate/Resources/Public/Icons/module-tstemplate.svg',
349 src: '<%= paths.t3icons %>module/module-tstemplate.svg'
350 },
351 {
352 dest: '<%= paths.sysext %>version/Resources/Public/Icons/module-version.svg',
353 src: '<%= paths.t3icons %>module/module-version.svg'
354 },
355 {
356 dest: '<%= paths.sysext %>viewpage/Resources/Public/Icons/module-viewpage.svg',
357 src: '<%= paths.t3icons %>module/module-viewpage.svg'
358 },
359 {
360 dest: '<%= paths.sysext %>workspaces/Resources/Public/Icons/module-workspaces.svg',
361 src: '<%= paths.t3icons %>module/module-workspaces.svg'
362 }
363 ]
364 },
365 extension_icons: {
366 files: [
367 {
368 dest: '<%= paths.sysext %>form/Resources/Public/Icons/Extension.svg',
369 src: '<%= paths.t3icons %>module/module-form.svg'
370 }
371 ]
372 },
373 fonts: {
374 files: [
375 {
376 dest: '<%= paths.sysext %>backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.eot',
377 src: '<%= paths.npm %>font-awesome/fonts/fontawesome-webfont.eot'
378 },
379 {
380 dest: '<%= paths.sysext %>backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.svg',
381 src: '<%= paths.npm %>font-awesome/fonts/fontawesome-webfont.svg'
382 },
383 {
384 dest: '<%= paths.sysext %>backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.ttf',
385 src: '<%= paths.npm %>font-awesome/fonts/fontawesome-webfont.ttf'
386 },
387 {
388 dest: '<%= paths.sysext %>backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.woff',
389 src: '<%= paths.npm %>font-awesome/fonts/fontawesome-webfont.woff'
390 },
391 {
392 dest: '<%= paths.sysext %>backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.woff2',
393 src: '<%= paths.npm %>font-awesome/fonts/fontawesome-webfont.woff2'
394 }
395 ]
396 }
397 },
398 bowercopy: {
399 options: {
400 clean: false,
401 report: false,
402 runBower: false,
403 srcPrefix: "bower_components/"
404 },
405 ckeditor: {
406 options: {
407 destPrefix: "<%= paths.ckeditor %>Public/JavaScript/Contrib"
408 },
409 files: {
410 'ckeditor.js': '../node_modules/ckeditor/ckeditor.js',
411 'plugins/': '../node_modules/ckeditor/plugins/',
412 'skins/': '../node_modules/ckeditor/skins/',
413 'lang/': '../node_modules/ckeditor/lang/'
414 }
415 },
416 all: {
417 options: {
418 destPrefix: "<%= paths.core %>Public/JavaScript/Contrib"
419 },
420 files: {
421 'nprogress.js': '../node_modules/nprogress/nprogress.js',
422 'jquery.matchHeight-min.js': '../node_modules/jquery-match-height/dist/jquery.matchHeight-min.js',
423 'jquery.dataTables.js': '../node_modules/datatables/media/js/jquery.dataTables.min.js',
424 'require.js': '../node_modules/requirejs/require.js',
425 'moment.js': '../node_modules/moment/min/moment-with-locales.min.js',
426 'moment-timezone.js': '../node_modules/moment-timezone/builds/moment-timezone-with-data.min.js',
427 'cropper.min.js': '../node_modules/cropper/dist/cropper.min.js',
428 'imagesloaded.pkgd.min.js': '../node_modules/imagesloaded/imagesloaded.pkgd.min.js',
429 'bootstrap-datetimepicker.js': '../node_modules/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js',
430 'autosize.js': '../node_modules/autosize/dist/autosize.min.js',
431 'taboverride.min.js': '../node_modules/taboverride/build/output/taboverride.min.js',
432 'bootstrap-slider.min.js': '../node_modules/bootstrap-slider/dist/bootstrap-slider.min.js',
433 /* disabled until events are not bound to document only
434 see https://github.com/claviska/jquery-minicolors/issues/192
435 see https://github.com/claviska/jquery-minicolors/issues/206
436 'jquery.minicolors.js': '../node_modules/@claviska/jquery-minicolors/jquery.minicolors.min.js',
437 '../../Images/colorpicker/jquery.minicolors.png': '../node_modules/@claviska/jquery-minicolors/jquery.minicolors.png'
438 */
439 /* disabled until autocomplete formatGroup is fixed to pass on the index too
440 'jquery.autocomplete.js': '../node_modules/devbridge-autocomplete/dist/jquery.autocomplete.min.js',
441 */
442 'd3/d3.js': '../node_modules/d3/build/d3.min.js',
443 /**
444 * copy needed parts of jquery
445 */
446 'jquery/jquery-3.2.1.js': '../node_modules/jquery/dist/jquery.js',
447 'jquery/jquery-3.2.1.min.js': '../node_modules/jquery/dist/jquery.min.js',
448 /**
449 * copy needed parts of jquery-ui
450 */
451 'jquery-ui/core.js': '../node_modules/jquery-ui/ui/core.js',
452 'jquery-ui/draggable.js': '../node_modules/jquery-ui/ui/draggable.js',
453 'jquery-ui/droppable.js': '../node_modules/jquery-ui/ui/droppable.js',
454 'jquery-ui/mouse.js': '../node_modules/jquery-ui/ui/mouse.js',
455 'jquery-ui/position.js': '../node_modules/jquery-ui/ui/position.js',
456 'jquery-ui/resizable.js': '../node_modules/jquery-ui/ui/resizable.js',
457 'jquery-ui/selectable.js': '../node_modules/jquery-ui/ui/selectable.js',
458 'jquery-ui/sortable.js': '../node_modules/jquery-ui/ui/sortable.js',
459 'jquery-ui/widget.js': '../node_modules/jquery-ui/ui/widget.js'
460 }
461 }
462 },
463 uglify: {
464 thirdparty: {
465 files: {
466 "<%= paths.core %>Public/JavaScript/Contrib/require.js": ["<%= paths.core %>Public/JavaScript/Contrib/require.js"],
467 "<%= paths.core %>Public/JavaScript/Contrib/nprogress.js": ["<%= paths.core %>Public/JavaScript/Contrib/nprogress.js"],
468 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/core.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/core.js"],
469 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/draggable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/draggable.js"],
470 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/droppable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/droppable.js"],
471 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/mouse.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/mouse.js"],
472 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/position.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/position.js"],
473 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/resizable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/resizable.js"],
474 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/selectable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/selectable.js"],
475 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/sortable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/sortable.js"],
476 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/widget.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/widget.js"],
477 "<%= paths.install %>Public/JavaScript/chosen.jquery.min.js": ["<%= paths.npm %>chosen-js/chosen.jquery.js"],
478 "<%= paths.core %>Public/JavaScript/Contrib/bootstrap-datetimepicker.js": ["<%= paths.core %>Public/JavaScript/Contrib/bootstrap-datetimepicker.js"]
479 }
480 }
481 },
482 svgmin: {
483 options: {
484 plugins: [
485 {removeViewBox: false}
486 ]
487 }
488 }
489 });
490
491 // Register tasks
492 grunt.loadNpmTasks('grunt-sass');
493 grunt.loadNpmTasks('grunt-contrib-watch');
494 grunt.loadNpmTasks('grunt-bowercopy');
495 grunt.loadNpmTasks('grunt-npm-install');
496 grunt.loadNpmTasks('grunt-bower-just-install');
497 grunt.loadNpmTasks('grunt-contrib-uglify');
498 grunt.loadNpmTasks('grunt-svgmin');
499 grunt.loadNpmTasks('grunt-postcss');
500 grunt.loadNpmTasks('grunt-contrib-copy');
501 grunt.loadNpmTasks("grunt-ts");
502 grunt.loadNpmTasks('grunt-tslint');
503 grunt.loadNpmTasks('grunt-stylelint');
504
505 /**
506 * grunt default task
507 *
508 * call "$ grunt"
509 *
510 * this will trigger the CSS build
511 */
512 grunt.registerTask('default', ['css']);
513
514 /**
515 * grunt lint
516 *
517 * call "$ grunt lint"
518 *
519 * this task does the following things:
520 * - tslint
521 * - stylelint
522 */
523 grunt.registerTask('lint', ['tslint', 'stylelint']);
524
525 /**
526 * grunt format
527 *
528 * call "$ grunt format"
529 *
530 * this task does the following things:
531 * - formatsass
532 * - lint
533 */
534 grunt.registerTask('format', ['formatsass', 'stylelint']);
535
536 /**
537 * grunt css task
538 *
539 * call "$ grunt css"
540 *
541 * this task does the following things:
542 * - sass
543 * - postcss
544 */
545 grunt.registerTask('css', ['sass', 'postcss']);
546
547 /**
548 * grunt update task
549 *
550 * call "$ grunt update"
551 *
552 * this task does the following things:
553 * - npm install
554 * - bower install
555 * - copy some bower components to a specific destinations because they need to be included via PHP
556 */
557 grunt.registerTask('update', ['npm-install', 'bower_install', 'bowercopy']);
558
559 /**
560 * grunt scripts task
561 *
562 * call "$ grunt scripts"
563 *
564 * this task does the following things:
565 * - 1) Check all TypeScript files (*.ts) with TSLint which are located in sysext/<EXTKEY>/Resources/Private/TypeScript/*.ts
566 * - 2) Compiles all TypeScript files (*.ts) which are located in sysext/<EXTKEY>/Resources/Private/TypeScript/*.ts
567 * - 3) Copy all generated JavaScript and Map files to public folders
568 */
569 grunt.registerTask('scripts', ['tslint', 'tsclean', 'ts', 'copy:ts_files']);
570
571 grunt.task.registerTask('tsclean', function () {
572 grunt.option('force');
573 grunt.file.delete("JavaScript");
574 });
575
576 /**
577 * grunt build task
578 *
579 * call "$ grunt build"
580 *
581 * this task does the following things:
582 * - execute update task
583 * - execute copy task
584 * - compile sass files
585 * - uglify js files
586 * - minifies svg files
587 * - compiles TypeScript files
588 */
589 grunt.registerTask('build', ['update', 'scripts', 'copy', 'format', 'css', 'uglify', 'svgmin']);
590 };