Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 1 | const pkg = require('./package.json') |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 2 | const glob = require('glob') |
| 3 | const yargs = require('yargs') |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 4 | const through = require('through2'); |
| 5 | const qunit = require('node-qunit-puppeteer') |
| 6 | |
| 7 | const {rollup} = require('rollup') |
Marc Kupietz | 9c036a4 | 2024-05-14 13:17:25 +0200 | [diff] [blame^] | 8 | const terser = require('@rollup/plugin-terser') |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 9 | const babel = require('@rollup/plugin-babel').default |
| 10 | const commonjs = require('@rollup/plugin-commonjs') |
| 11 | const resolve = require('@rollup/plugin-node-resolve').default |
| 12 | const sass = require('sass') |
| 13 | |
| 14 | const gulp = require('gulp') |
| 15 | const tap = require('gulp-tap') |
| 16 | const zip = require('gulp-zip') |
| 17 | const header = require('gulp-header') |
| 18 | const eslint = require('gulp-eslint') |
| 19 | const minify = require('gulp-clean-css') |
| 20 | const connect = require('gulp-connect') |
| 21 | const autoprefixer = require('gulp-autoprefixer') |
| 22 | |
| 23 | const root = yargs.argv.root || '.' |
| 24 | const port = yargs.argv.port || 8000 |
Christophe Dervieux | 8afae13 | 2021-12-06 15:16:42 +0100 | [diff] [blame] | 25 | const host = yargs.argv.host || 'localhost' |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 26 | |
| 27 | const banner = `/*! |
| 28 | * reveal.js ${pkg.version} |
| 29 | * ${pkg.homepage} |
| 30 | * MIT licensed |
| 31 | * |
Marc Kupietz | 9c036a4 | 2024-05-14 13:17:25 +0200 | [diff] [blame^] | 32 | * Copyright (C) 2011-2024 Hakim El Hattab, https://hakim.se |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 33 | */\n` |
| 34 | |
| 35 | // Prevents warnings from opening too many test pages |
| 36 | process.setMaxListeners(20); |
| 37 | |
| 38 | const babelConfig = { |
| 39 | babelHelpers: 'bundled', |
| 40 | ignore: ['node_modules'], |
| 41 | compact: false, |
| 42 | extensions: ['.js', '.html'], |
| 43 | plugins: [ |
| 44 | 'transform-html-import-to-string' |
| 45 | ], |
| 46 | presets: [[ |
| 47 | '@babel/preset-env', |
| 48 | { |
| 49 | corejs: 3, |
| 50 | useBuiltIns: 'usage', |
| 51 | modules: false |
| 52 | } |
| 53 | ]] |
| 54 | }; |
| 55 | |
| 56 | // Our ES module bundle only targets newer browsers with |
| 57 | // module support. Browsers are targeted explicitly instead |
| 58 | // of using the "esmodule: true" target since that leads to |
| 59 | // polyfilling older browsers and a larger bundle. |
| 60 | const babelConfigESM = JSON.parse( JSON.stringify( babelConfig ) ); |
| 61 | babelConfigESM.presets[0][1].targets = { browsers: [ |
Christophe Dervieux | 8afae13 | 2021-12-06 15:16:42 +0100 | [diff] [blame] | 62 | 'last 2 Chrome versions', |
| 63 | 'last 2 Safari versions', |
| 64 | 'last 2 iOS versions', |
| 65 | 'last 2 Firefox versions', |
| 66 | 'last 2 Edge versions', |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 67 | ] }; |
| 68 | |
| 69 | let cache = {}; |
| 70 | |
| 71 | // Creates a bundle with broad browser support, exposed |
| 72 | // as UMD |
| 73 | gulp.task('js-es5', () => { |
| 74 | return rollup({ |
| 75 | cache: cache.umd, |
| 76 | input: 'js/index.js', |
| 77 | plugins: [ |
| 78 | resolve(), |
| 79 | commonjs(), |
| 80 | babel( babelConfig ), |
| 81 | terser() |
| 82 | ] |
| 83 | }).then( bundle => { |
| 84 | cache.umd = bundle.cache; |
| 85 | return bundle.write({ |
| 86 | name: 'Reveal', |
| 87 | file: './dist/reveal.js', |
| 88 | format: 'umd', |
| 89 | banner: banner, |
| 90 | sourcemap: true |
| 91 | }); |
| 92 | }); |
| 93 | }) |
| 94 | |
| 95 | // Creates an ES module bundle |
| 96 | gulp.task('js-es6', () => { |
| 97 | return rollup({ |
| 98 | cache: cache.esm, |
| 99 | input: 'js/index.js', |
| 100 | plugins: [ |
| 101 | resolve(), |
| 102 | commonjs(), |
| 103 | babel( babelConfigESM ), |
| 104 | terser() |
| 105 | ] |
| 106 | }).then( bundle => { |
| 107 | cache.esm = bundle.cache; |
| 108 | return bundle.write({ |
| 109 | file: './dist/reveal.esm.js', |
| 110 | format: 'es', |
| 111 | banner: banner, |
| 112 | sourcemap: true |
| 113 | }); |
| 114 | }); |
| 115 | }) |
| 116 | gulp.task('js', gulp.parallel('js-es5', 'js-es6')); |
| 117 | |
| 118 | // Creates a UMD and ES module bundle for each of our |
| 119 | // built-in plugins |
| 120 | gulp.task('plugins', () => { |
| 121 | return Promise.all([ |
| 122 | { name: 'RevealHighlight', input: './plugin/highlight/plugin.js', output: './plugin/highlight/highlight' }, |
| 123 | { name: 'RevealMarkdown', input: './plugin/markdown/plugin.js', output: './plugin/markdown/markdown' }, |
| 124 | { name: 'RevealSearch', input: './plugin/search/plugin.js', output: './plugin/search/search' }, |
| 125 | { name: 'RevealNotes', input: './plugin/notes/plugin.js', output: './plugin/notes/notes' }, |
| 126 | { name: 'RevealZoom', input: './plugin/zoom/plugin.js', output: './plugin/zoom/zoom' }, |
| 127 | { name: 'RevealMath', input: './plugin/math/plugin.js', output: './plugin/math/math' }, |
| 128 | ].map( plugin => { |
| 129 | return rollup({ |
| 130 | cache: cache[plugin.input], |
| 131 | input: plugin.input, |
| 132 | plugins: [ |
| 133 | resolve(), |
| 134 | commonjs(), |
| 135 | babel({ |
| 136 | ...babelConfig, |
| 137 | ignore: [/node_modules\/(?!(highlight\.js|marked)\/).*/], |
| 138 | }), |
| 139 | terser() |
| 140 | ] |
| 141 | }).then( bundle => { |
| 142 | cache[plugin.input] = bundle.cache; |
| 143 | bundle.write({ |
| 144 | file: plugin.output + '.esm.js', |
| 145 | name: plugin.name, |
| 146 | format: 'es' |
| 147 | }) |
| 148 | |
| 149 | bundle.write({ |
| 150 | file: plugin.output + '.js', |
| 151 | name: plugin.name, |
| 152 | format: 'umd' |
| 153 | }) |
| 154 | }); |
| 155 | } )); |
| 156 | }) |
| 157 | |
| 158 | // a custom pipeable step to transform Sass to CSS |
| 159 | function compileSass() { |
| 160 | return through.obj( ( vinylFile, encoding, callback ) => { |
| 161 | const transformedFile = vinylFile.clone(); |
| 162 | |
| 163 | sass.render({ |
| 164 | data: transformedFile.contents.toString(), |
Marc Kupietz | 09b7575 | 2023-10-07 09:32:19 +0200 | [diff] [blame] | 165 | file: transformedFile.path, |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 166 | }, ( err, result ) => { |
| 167 | if( err ) { |
Marc Kupietz | 09b7575 | 2023-10-07 09:32:19 +0200 | [diff] [blame] | 168 | callback(err); |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 169 | } |
| 170 | else { |
| 171 | transformedFile.extname = '.css'; |
| 172 | transformedFile.contents = result.css; |
| 173 | callback( null, transformedFile ); |
| 174 | } |
| 175 | }); |
| 176 | }); |
| 177 | } |
| 178 | |
| 179 | gulp.task('css-themes', () => gulp.src(['./css/theme/source/*.{sass,scss}']) |
| 180 | .pipe(compileSass()) |
| 181 | .pipe(gulp.dest('./dist/theme'))) |
| 182 | |
| 183 | gulp.task('css-core', () => gulp.src(['css/reveal.scss']) |
| 184 | .pipe(compileSass()) |
| 185 | .pipe(autoprefixer()) |
| 186 | .pipe(minify({compatibility: 'ie9'})) |
| 187 | .pipe(header(banner)) |
| 188 | .pipe(gulp.dest('./dist'))) |
| 189 | |
| 190 | gulp.task('css', gulp.parallel('css-themes', 'css-core')) |
| 191 | |
| 192 | gulp.task('qunit', () => { |
| 193 | |
| 194 | let serverConfig = { |
| 195 | root, |
| 196 | port: 8009, |
Christophe Dervieux | 8afae13 | 2021-12-06 15:16:42 +0100 | [diff] [blame] | 197 | host: 'localhost', |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 198 | name: 'test-server' |
| 199 | } |
| 200 | |
| 201 | let server = connect.server( serverConfig ) |
| 202 | |
| 203 | let testFiles = glob.sync('test/*.html' ) |
| 204 | |
| 205 | let totalTests = 0; |
| 206 | let failingTests = 0; |
| 207 | |
| 208 | let tests = Promise.all( testFiles.map( filename => { |
| 209 | return new Promise( ( resolve, reject ) => { |
| 210 | qunit.runQunitPuppeteer({ |
| 211 | targetUrl: `http://${serverConfig.host}:${serverConfig.port}/${filename}`, |
| 212 | timeout: 20000, |
| 213 | redirectConsole: false, |
| 214 | puppeteerArgs: ['--allow-file-access-from-files'] |
| 215 | }) |
| 216 | .then(result => { |
| 217 | if( result.stats.failed > 0 ) { |
| 218 | console.log(`${'!'} ${filename} [${result.stats.passed}/${result.stats.total}] in ${result.stats.runtime}ms`.red); |
| 219 | // qunit.printResultSummary(result, console); |
| 220 | qunit.printFailedTests(result, console); |
| 221 | } |
| 222 | else { |
| 223 | console.log(`${'✔'} ${filename} [${result.stats.passed}/${result.stats.total}] in ${result.stats.runtime}ms`.green); |
| 224 | } |
| 225 | |
| 226 | totalTests += result.stats.total; |
| 227 | failingTests += result.stats.failed; |
| 228 | |
| 229 | resolve(); |
| 230 | }) |
| 231 | .catch(error => { |
| 232 | console.error(error); |
| 233 | reject(); |
| 234 | }); |
| 235 | } ) |
| 236 | } ) ); |
| 237 | |
| 238 | return new Promise( ( resolve, reject ) => { |
| 239 | |
| 240 | tests.then( () => { |
| 241 | if( failingTests > 0 ) { |
| 242 | reject( new Error(`${failingTests}/${totalTests} tests failed`.red) ); |
| 243 | } |
| 244 | else { |
| 245 | console.log(`${'✔'} Passed ${totalTests} tests`.green.bold); |
| 246 | resolve(); |
| 247 | } |
| 248 | } ) |
| 249 | .catch( () => { |
| 250 | reject(); |
| 251 | } ) |
| 252 | .finally( () => { |
| 253 | server.close(); |
| 254 | } ); |
| 255 | |
| 256 | } ); |
| 257 | } ) |
| 258 | |
| 259 | gulp.task('eslint', () => gulp.src(['./js/**', 'gulpfile.js']) |
| 260 | .pipe(eslint()) |
| 261 | .pipe(eslint.format())) |
| 262 | |
| 263 | gulp.task('test', gulp.series( 'eslint', 'qunit' )) |
| 264 | |
| 265 | gulp.task('default', gulp.series(gulp.parallel('js', 'css', 'plugins'), 'test')) |
| 266 | |
| 267 | gulp.task('build', gulp.parallel('js', 'css', 'plugins')) |
| 268 | |
Marc Kupietz | 09b7575 | 2023-10-07 09:32:19 +0200 | [diff] [blame] | 269 | gulp.task('package', gulp.series(() => |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 270 | |
Marc Kupietz | 09b7575 | 2023-10-07 09:32:19 +0200 | [diff] [blame] | 271 | gulp.src( |
| 272 | [ |
| 273 | './index.html', |
| 274 | './dist/**', |
| 275 | './lib/**', |
| 276 | './images/**', |
| 277 | './plugin/**', |
| 278 | './**/*.md' |
| 279 | ], |
| 280 | { base: './' } |
| 281 | ) |
| 282 | .pipe(zip('reveal-js-presentation.zip')).pipe(gulp.dest('./')) |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 283 | |
| 284 | )) |
| 285 | |
Marc Kupietz | 09b7575 | 2023-10-07 09:32:19 +0200 | [diff] [blame] | 286 | gulp.task('reload', () => gulp.src(['index.html']) |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 287 | .pipe(connect.reload())); |
| 288 | |
| 289 | gulp.task('serve', () => { |
| 290 | |
| 291 | connect.server({ |
| 292 | root: root, |
| 293 | port: port, |
Christophe Dervieux | 8afae13 | 2021-12-06 15:16:42 +0100 | [diff] [blame] | 294 | host: host, |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 295 | livereload: true |
| 296 | }) |
| 297 | |
Marc Kupietz | 09b7575 | 2023-10-07 09:32:19 +0200 | [diff] [blame] | 298 | const slidesRoot = root.endsWith('/') ? root : root + '/' |
| 299 | gulp.watch([ |
| 300 | slidesRoot + '**/*.html', |
| 301 | slidesRoot + '**/*.md', |
| 302 | `!${slidesRoot}**/node_modules/**`, // ignore node_modules |
| 303 | ], gulp.series('reload')) |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 304 | |
Christophe Dervieux | 8afae13 | 2021-12-06 15:16:42 +0100 | [diff] [blame] | 305 | gulp.watch(['js/**'], gulp.series('js', 'reload', 'eslint')) |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 306 | |
Marc Kupietz | 09b7575 | 2023-10-07 09:32:19 +0200 | [diff] [blame] | 307 | gulp.watch(['plugin/**/plugin.js', 'plugin/**/*.html'], gulp.series('plugins', 'reload')) |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 308 | |
| 309 | gulp.watch([ |
Marc Kupietz | 09b7575 | 2023-10-07 09:32:19 +0200 | [diff] [blame] | 310 | 'css/theme/source/**/*.{sass,scss}', |
Christophe Dervieux | e1893ae | 2021-10-07 17:09:02 +0200 | [diff] [blame] | 311 | 'css/theme/template/*.{sass,scss}', |
| 312 | ], gulp.series('css-themes', 'reload')) |
| 313 | |
| 314 | gulp.watch([ |
| 315 | 'css/*.scss', |
| 316 | 'css/print/*.{sass,scss,css}' |
| 317 | ], gulp.series('css-core', 'reload')) |
| 318 | |
| 319 | gulp.watch(['test/*.html'], gulp.series('test')) |
| 320 | |
Marc Kupietz | 09b7575 | 2023-10-07 09:32:19 +0200 | [diff] [blame] | 321 | }) |