f8789e642a6761e965a53958352be7008e6681ea
[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 // Project configuration.
17 grunt.initConfig({
18 pkg: grunt.file.readJSON('package.json'),
19 banner: '/*!\n' +
20 ' * This file is part of the TYPO3 CMS project.\n' +
21 ' *\n' +
22 ' * It is free software; you can redistribute it and/or modify it under\n' +
23 ' * the terms of the GNU General Public License, either version 2\n' +
24 ' * of the License, or any later version.\n' +
25 ' *\n' +
26 ' * For the full copyright and license information, please read the\n' +
27 ' * LICENSE.txt file that was distributed with this source code.\n' +
28 ' *\n' +
29 ' * The TYPO3 project - inspiring people to share!\n' +
30 ' */\n',
31 paths: {
32 resources : 'Resources/',
33 less : '<%= paths.resources %>Public/Less/',
34 root : '../',
35 sysext : '<%= paths.root %>typo3/sysext/',
36 form : '<%= paths.sysext %>form/Resources/',
37 frontend : '<%= paths.sysext %>frontend/Resources/',
38 install : '<%= paths.sysext %>install/Resources/',
39 linkvalidator : '<%= paths.sysext %>linkvalidator/Resources/',
40 backend : '<%= paths.sysext %>backend/Resources/',
41 t3editor : '<%= paths.sysext %>t3editor/Resources/',
42 workspaces: '<%= paths.sysext %>workspaces/Resources/',
43 ckeditor : '<%= paths.sysext %>rte_ckeditor/Resources/',
44 core : '<%= paths.sysext %>core/Resources/',
45 bower : 'bower_components/',
46 flags : '<%= paths.bower %>region-flags/svg/',
47 t3icons : '<%= paths.bower %>typo3-icons/dist/',
48 npm : 'node_modules/'
49 },
50 less: {
51 options: {
52 banner: '<%= banner %>',
53 outputSourceFiles: true
54 },
55 backend: {
56 files: {
57 "<%= paths.backend %>Public/Css/backend.css": "<%= paths.less %>backend.less"
58 }
59 },
60 core: {
61 files: {
62 "<%= paths.core %>Public/Css/errorpage.css": "<%= paths.less %>errorpage.less"
63 }
64 },
65 form: {
66 files: {
67 "<%= paths.form %>Public/Css/form.css": "<%= paths.less %>form.less"
68 }
69 },
70 frontend: {
71 files: {
72 "<%= paths.frontend %>Public/Css/adminpanel.css": "<%= paths.less %>adminpanel.less"
73 }
74 },
75 install: {
76 files: {
77 "<%= paths.install %>Public/Css/install.css": "<%= paths.less %>install.less"
78 }
79 },
80 linkvalidator: {
81 files: {
82 "<%= paths.linkvalidator %>Public/Css/linkvalidator.css": "<%= paths.less %>linkvalidator.less"
83 }
84 },
85 workspaces: {
86 files: {
87 "<%= paths.workspaces %>Public/Css/preview.css": "<%= paths.workspaces %>Private/Less/preview.less"
88 }
89 },
90 t3editor: {
91 files: {
92 '<%= paths.t3editor %>Public/Css/t3editor.css': '<%= paths.t3editor %>Private/Less/t3editor.less',
93 '<%= paths.t3editor %>Public/Css/t3editor_inner.css': '<%= paths.t3editor %>Private/Less/t3editor_inner.less',
94 '<%= paths.t3editor %>Public/Css/t3editor_typoscript_colors.css': '<%= paths.t3editor %>Private/Less/t3editor_typoscript_colors.less'
95 }
96 }
97 },
98 postcss: {
99 options: {
100 map: false,
101 processors: [
102 require('autoprefixer')({ // add vendor prefixes
103 browsers: [
104 'Last 2 versions',
105 'Firefox ESR',
106 'IE 11'
107 ]
108 })
109 ]
110 },
111 backend: {
112 src: '<%= paths.backend %>Public/Css/*.css'
113 },
114 core: {
115 src: '<%= paths.core %>Public/Css/*.css'
116 },
117 form: {
118 src: '<%= paths.form %>Public/Css/*.css'
119 },
120 frontend: {
121 src: '<%= paths.frontend %>Public/Css/*.css'
122 },
123 install: {
124 src: '<%= paths.install %>Public/Css/*.css'
125 },
126 linkvalidator: {
127 src: '<%= paths.linkvalidator %>Public/Css/*.css'
128 },
129 t3editor: {
130 src: '<%= paths.t3editor %>Public/Css/*.css'
131 },
132 workspaces: {
133 src: '<%= paths.workspaces %>Public/Css/*.css'
134 }
135 },
136 ts: {
137 default : {
138 tsconfig: true,
139 options: {
140 verbose: false
141 }
142 }
143 },
144 tslint: {
145 options: {
146 configuration: 'tslint.json',
147 force: false
148 },
149 files: {
150 src: [
151 '<%= paths.sysext %>*/Resources/Private/TypeScript/**/*.ts'
152 ]
153 }
154 },
155 watch: {
156 options: {
157 livereload: true
158 },
159 less: {
160 files: '<%= paths.less %>**/*.less',
161 tasks: 'css'
162 },
163 ts: {
164 files: '<%= paths.sysext %>*/Resources/Private/TypeScript/**/*.ts',
165 tasks: 'scripts'
166 }
167 },
168 copy: {
169 options: {
170 punctuation: ''
171 },
172 ts_files: {
173 files: [{
174 expand: true,
175 cwd: '<%= paths.root %>Build/JavaScript/typo3/sysext/',
176 src: ['**/*.js', '**/*.js.map'],
177 dest: '<%= paths.sysext %>',
178 rename: function(dest, src) {
179 return dest + src.replace('Resources/Private/TypeScript', 'Resources/Public/JavaScript');
180 }
181 }]
182 },
183 core_icons: {
184 files: [{
185 expand: true,
186 cwd: '<%= paths.t3icons %>',
187 src: ['**/*.svg', '!module/*'],
188 dest: '<%= paths.sysext %>core/Resources/Public/Icons/T3Icons/',
189 ext: '.svg'
190 }]
191 },
192 module_icons: {
193 files: [
194 { dest: '<%= paths.sysext %>about/Resources/Public/Icons/module-about.svg', src: '<%= paths.t3icons %>module/module-about.svg' },
195 { dest: '<%= paths.sysext %>belog/Resources/Public/Icons/module-belog.svg', src: '<%= paths.t3icons %>module/module-belog.svg' },
196 { dest: '<%= paths.sysext %>beuser/Resources/Public/Icons/module-beuser.svg', src: '<%= paths.t3icons %>module/module-beuser.svg' },
197 { dest: '<%= paths.sysext %>lowlevel/Resources/Public/Icons/module-config.svg', src: '<%= paths.t3icons %>module/module-config.svg' },
198 { dest: '<%= paths.sysext %>cshmanual/Resources/Public/Icons/module-cshmanual.svg', src: '<%= paths.t3icons %>module/module-cshmanual.svg' },
199 { dest: '<%= paths.sysext %>lowlevel/Resources/Public/Icons/module-dbint.svg', src: '<%= paths.t3icons %>module/module-dbint.svg' },
200 { dest: '<%= paths.sysext %>documentation/Resources/Public/Icons/module-documentation.svg', src: '<%= paths.t3icons %>module/module-documentation.svg' },
201 { dest: '<%= paths.sysext %>extensionmanager/Resources/Public/Icons/module-extensionmanager.svg', src: '<%= paths.t3icons %>module/module-extensionmanager.svg' },
202 { dest: '<%= paths.sysext %>filelist/Resources/Public/Icons/module-filelist.svg', src: '<%= paths.t3icons %>module/module-filelist.svg' },
203 { dest: '<%= paths.sysext %>func/Resources/Public/Icons/module-func.svg', src: '<%= paths.t3icons %>module/module-func.svg' },
204 { dest: '<%= paths.sysext %>indexed_search/Resources/Public/Icons/module-indexed_search.svg', src: '<%= paths.t3icons %>module/module-indexed_search.svg' },
205 { dest: '<%= paths.sysext %>info/Resources/Public/Icons/module-info.svg', src: '<%= paths.t3icons %>module/module-info.svg' },
206 { dest: '<%= paths.sysext %>install/Resources/Public/Icons/module-install.svg', src: '<%= paths.t3icons %>module/module-install.svg' },
207 { dest: '<%= paths.sysext %>lang/Resources/Public/Icons/module-lang.svg', src: '<%= paths.t3icons %>module/module-lang.svg' },
208 { dest: '<%= paths.sysext %>recordlist/Resources/Public/Icons/module-list.svg', src: '<%= paths.t3icons %>module/module-list.svg' },
209 { dest: '<%= paths.sysext %>backend/Resources/Public/Icons/module-page.svg', src: '<%= paths.t3icons %>module/module-page.svg' },
210 { dest: '<%= paths.sysext %>beuser/Resources/Public/Icons/module-permission.svg', src: '<%= paths.t3icons %>module/module-permission.svg' },
211 { dest: '<%= paths.sysext %>recycler/Resources/Public/Icons/module-recycler.svg', src: '<%= paths.t3icons %>module/module-recycler.svg' },
212 { dest: '<%= paths.sysext %>reports/Resources/Public/Icons/module-reports.svg', src: '<%= paths.t3icons %>module/module-reports.svg' },
213 { dest: '<%= paths.sysext %>scheduler/Resources/Public/Icons/module-scheduler.svg', src: '<%= paths.t3icons %>module/module-scheduler.svg' },
214 { dest: '<%= paths.sysext %>setup/Resources/Public/Icons/module-setup.svg', src: '<%= paths.t3icons %>module/module-setup.svg' },
215 { dest: '<%= paths.sysext %>taskcenter/Resources/Public/Icons/module-taskcenter.svg', src: '<%= paths.t3icons %>module/module-taskcenter.svg' },
216 { dest: '<%= paths.sysext %>tstemplate/Resources/Public/Icons/module-tstemplate.svg', src: '<%= paths.t3icons %>module/module-tstemplate.svg' },
217 { dest: '<%= paths.sysext %>version/Resources/Public/Icons/module-version.svg', src: '<%= paths.t3icons %>module/module-version.svg' },
218 { dest: '<%= paths.sysext %>viewpage/Resources/Public/Icons/module-viewpage.svg', src: '<%= paths.t3icons %>module/module-viewpage.svg' },
219 { dest: '<%= paths.sysext %>workspaces/Resources/Public/Icons/module-workspaces.svg', src: '<%= paths.t3icons %>module/module-workspaces.svg' }
220 ]
221 },
222 fonts: {
223 files: [
224 { dest: '<%= paths.sysext %>backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.eot', src: '<%= paths.bower %>fontawesome/fonts/fontawesome-webfont.eot' },
225 { dest: '<%= paths.sysext %>backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.svg', src: '<%= paths.bower %>fontawesome/fonts/fontawesome-webfont.svg' },
226 { dest: '<%= paths.sysext %>backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.ttf', src: '<%= paths.bower %>fontawesome/fonts/fontawesome-webfont.ttf' },
227 { dest: '<%= paths.sysext %>backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.woff', src: '<%= paths.bower %>fontawesome/fonts/fontawesome-webfont.woff' },
228 { dest: '<%= paths.sysext %>backend/Resources/Public/Fonts/FontAwesome/fontawesome-webfont.woff2', src: '<%= paths.bower %>fontawesome/fonts/fontawesome-webfont.woff2' }
229 ]
230 },
231 npm: {
232 files: [
233 {dest: '<%= paths.install %>Public/JavaScript/tagsort.min.js', src: '<%= paths.npm %>tagsort/tagsort.js'}
234 ]
235 }
236 },
237 bowercopy: {
238 options: {
239 clean: false,
240 report: false,
241 runBower: false,
242 srcPrefix: "bower_components/"
243 },
244 glob: {
245 files: {
246 // When using glob patterns, destinations are *always* folder names
247 // into which matching files will be copied
248 // Also note that subdirectories are **not** maintained
249 // if a destination is specified
250 // For example, one of the files copied here is
251 // 'lodash/dist/lodash.js' -> 'public/js/libs/lodash/lodash.js'
252 '<%= paths.sysext %>core/Resources/Public/Images/colorpicker': 'jquery-minicolors/*.png'
253 }
254 },
255 ckeditor: {
256 options: {
257 destPrefix: "<%= paths.ckeditor %>Public/JavaScript/Contrib"
258 },
259 files: {
260 'ckeditor.js': 'ckeditor/ckeditor.js',
261 'plugins/': 'ckeditor/plugins/',
262 'skins/': 'ckeditor/skins/',
263 'lang/': 'ckeditor/lang/'
264 }
265 },
266 all: {
267 options: {
268 destPrefix: "<%= paths.core %>Public/JavaScript/Contrib"
269 },
270 files: {
271 'nprogress.js': 'nprogress/nprogress.js',
272 'jquery.matchHeight-min.js': 'matchHeight/dist/jquery.matchHeight-min.js',
273 'jquery.dataTables.js': 'datatables/media/js/jquery.dataTables.min.js',
274 'require.js': 'requirejs/require.js',
275 'moment.js': 'moment/min/moment-with-locales.min.js',
276 'moment-timezone.js': 'moment-timezone/builds/moment-timezone-with-data.min.js',
277 'cropper.min.js': 'cropper/dist/cropper.min.js',
278 'imagesloaded.pkgd.min.js': 'imagesloaded/imagesloaded.pkgd.min.js',
279 'bootstrap-datetimepicker.js': 'eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js',
280 'autosize.js': 'autosize/dist/autosize.min.js',
281 'taboverride.min.js': 'taboverride/build/output/taboverride.min.js',
282 'bootstrap-slider.min.js': 'seiyria-bootstrap-slider/dist/bootstrap-slider.min.js',
283 /* disabled until events are not bound to document only
284 see https://github.com/claviska/jquery-minicolors/issues/192
285 see https://github.com/claviska/jquery-minicolors/issues/206
286 'jquery.minicolors.js': 'jquery-minicolors/jquery.minicolors.min.js',
287 */
288 /* disabled until autocomplete formatGroup is fixed to pass on the index too
289 'jquery.autocomplete.js': 'devbridge-autocomplete/src/jquery.autocomplete.js',
290 */
291 'd3/d3.js': 'd3/d3.min.js',
292 /**
293 * copy needed parts of jquery
294 */
295 'jquery/jquery-3.1.1.js': 'jquery/dist/jquery.js',
296 'jquery/jquery-3.1.1.min.js': 'jquery/dist/jquery.min.js',
297 /**
298 * copy needed parts of jquery-ui
299 */
300 'jquery-ui/core.js': 'jquery-ui/ui/core.js',
301 'jquery-ui/draggable.js': 'jquery-ui/ui/draggable.js',
302 'jquery-ui/droppable.js': 'jquery-ui/ui/droppable.js',
303 'jquery-ui/mouse.js': 'jquery-ui/ui/mouse.js',
304 'jquery-ui/position.js': 'jquery-ui/ui/position.js',
305 'jquery-ui/resizable.js': 'jquery-ui/ui/resizable.js',
306 'jquery-ui/selectable.js': 'jquery-ui/ui/selectable.js',
307 'jquery-ui/sortable.js': 'jquery-ui/ui/sortable.js',
308 'jquery-ui/widget.js': 'jquery-ui/ui/widget.js'
309 }
310 }
311 },
312 uglify: {
313 thirdparty: {
314 files: {
315 "<%= paths.core %>Public/JavaScript/Contrib/require.js": ["<%= paths.core %>Public/JavaScript/Contrib/require.js"],
316 "<%= paths.core %>Public/JavaScript/Contrib/nprogress.js": ["<%= paths.core %>Public/JavaScript/Contrib/nprogress.js"],
317 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/core.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/core.js"],
318 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/draggable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/draggable.js"],
319 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/droppable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/droppable.js"],
320 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/mouse.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/mouse.js"],
321 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/position.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/position.js"],
322 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/resizable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/resizable.js"],
323 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/selectable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/selectable.js"],
324 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/sortable.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/sortable.js"],
325 "<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/widget.js": ["<%= paths.core %>Public/JavaScript/Contrib/jquery-ui/widget.js"],
326 "<%= paths.install %>Public/JavaScript/tagsort.min.js": ["<%= paths.install %>Public/JavaScript/tagsort.min.js"],
327 "<%= paths.core %>Public/JavaScript/Contrib/bootstrap-datetimepicker.js": ["<%= paths.core %>Public/JavaScript/Contrib/bootstrap-datetimepicker.js"]
328 }
329 }
330 },
331 svgmin: {
332 options: {
333 plugins: [
334 { removeViewBox: false }
335 ]
336 },
337 // Flags
338 flags: {
339 files: [{
340 expand: true,
341 cwd: '<%= paths.flags %>',
342 src: '*.svg',
343 dest: '<%= paths.sysext %>core/Resources/Public/Icons/Flags/SVG/',
344 ext: '.svg',
345 extDot: 'first'
346 }]
347 }
348 }
349 });
350
351 // Register tasks
352 grunt.loadNpmTasks('grunt-contrib-less');
353 grunt.loadNpmTasks('grunt-contrib-watch');
354 grunt.loadNpmTasks('grunt-bowercopy');
355 grunt.loadNpmTasks('grunt-npm-install');
356 grunt.loadNpmTasks('grunt-bower-just-install');
357 grunt.loadNpmTasks('grunt-contrib-uglify');
358 grunt.loadNpmTasks('grunt-svgmin');
359 grunt.loadNpmTasks('grunt-postcss');
360 grunt.loadNpmTasks('grunt-contrib-copy');
361 grunt.loadNpmTasks("grunt-ts");
362 grunt.loadNpmTasks('grunt-tslint');
363
364 /**
365 * grunt default task
366 *
367 * call "$ grunt"
368 *
369 * this will trigger the CSS build
370 */
371 grunt.registerTask('default', ['css']);
372
373 /**
374 * grunt css task
375 *
376 * call "$ grunt css"
377 *
378 * this task does the following things:
379 * - less
380 * - postcss
381 */
382 grunt.registerTask('css', ['less', 'postcss']);
383
384 /**
385 * grunt update task
386 *
387 * call "$ grunt update"
388 *
389 * this task does the following things:
390 * - npm install
391 * - bower install
392 * - copy some bower components to a specific destinations because they need to be included via PHP
393 */
394 grunt.registerTask('update', ['npm-install', 'bower_install', 'bowercopy']);
395
396 /**
397 * grunt scripts task
398 *
399 * call "$ grunt scripts"
400 *
401 * this task does the following things:
402 * - 1) Check all TypeScript files (*.ts) with TSLint which are located in sysext/<EXTKEY>/Resources/Private/TypeScript/*.ts
403 * - 2) Compiles all TypeScript files (*.ts) which are located in sysext/<EXTKEY>/Resources/Private/TypeScript/*.ts
404 * - 3) Copy all generated JavaScript and Map files to public folders
405 */
406 grunt.registerTask('scripts', ['tslint', 'tsclean', 'ts', 'copy:ts_files']);
407
408 grunt.task.registerTask('tsclean', function() {
409 grunt.file.delete("JavaScript");
410 });
411
412 /**
413 * grunt build task
414 *
415 * call "$ grunt build"
416 *
417 * this task does the following things:
418 * - execute update task
419 * - execute copy task
420 * - compile less files
421 * - uglify js files
422 * - minifies svg files
423 * - compiles TypeScript files
424 */
425 grunt.registerTask('build', ['update', 'scripts', 'copy', 'css', 'uglify', 'svgmin']);
426 };