Skip to content
Snippets Groups Projects
gulpfile.js 4.84 KiB
Newer Older
const { src, dest, parallel, series, watch } = require('gulp')
var ts = require('gulp-typescript')
var concat = require('gulp-concat')
var merge = require('merge2')
var fs = require('file-system')
var del = require('del')
var wp = require('webpack')
var webpacks = require('webpack-stream')
var browserSync = require('browser-sync').create()
var argv = require('yargs').argv

var paths = {
  src: './src/',
  tsbuild: './src/ts/build/',
  build: './build/'
}

var files = {
  css: 'style.css',
  mainjs: 'js/ts/page.js',
  js: 'page.js'
}


function cleantsc() {
  return del([paths.tsbuild])
}
function clean() {
  return del([paths.tsbuild , paths.build])
}
exports.clean = clean
exports.clean.description = 'Cleans the project'

function transpile() {
  var tsResult = src(paths.src + '**/*.ts')
    .pipe(ts.createProject(require('./tsconfig').compilerOptions)())

  return merge([
    tsResult.dts.pipe(dest(paths.tsbuild + 'd/')),
    tsResult.js.pipe(dest(paths.tsbuild + 'js/'))
  ])
}
exports.transpile = series(clean, transpile)
exports.transpile.description = 'Transpiles .ts files using tsconfig.json'

function webpack() {
  return src(paths.tsbuild + files.mainjs)
    .pipe(webpacks({
      output: { filename: files.js },
      plugins: [
        new wp.NoEmitOnErrorsPlugin()
      ],
      devtool: 'source-map',
      mode: 'none'
    }))
    .pipe(dest(paths.build))
    .pipe(browserSync.stream())
}
exports.webpack = series(clean, transpile, webpack)
exports.webpack.description = 'Bundles the main JavaScript file'


function css() {
  return src(paths.src + 'css/*.css')
    .pipe(concat(files.css))
    .pipe(dest(paths.build))
}
exports.css = css
exports.css.description = 'Bundles CSS source files into style.css'


// Generate icon-definitions.ts from optimized icons
// This removes stoke and fill colors since we set them with css to save space
function icon_definitions() {
  var data = ''
  fs.recurseSync(paths.src+'icons', function(filepath, relative, filename) {
    if (!filename) return
    const fileContent = fs.fs.readFileSync(filepath).toString().replace(/\n/g, '');
    data += 'export const ' + filename.slice(0, -4).replace('-', '_') + '_icon = '
    data += '`' + fileContent + '`;';
    data += '\n\n'
  })
  data = data.replace(/ ?(?:stroke|fill)="(none|#?[0-9A-Za-z]+)"/g, (match, value) => {    //remove stroke and fill attributes: fill="black" or stroke="#aaa"
    return value.toLowerCase() === 'none' ? `${match}` : '';    // preserve 'none' values for fill and stroke
  });
  data = data.replace(/style="([^"]*)"/g, (match, styleAttr) => {    //remove stroke and fill elements in style attribute: style="stroke:black"
    const cleanedStyle = styleAttr.replace(/\b(?:fill|stroke):\s*([^;]*);?/gi, (match, value) => {
      return value.toLowerCase() === 'none' ? `${match};` : '';    // Preserve 'none' values for fill and stroke
    });
    return `style="${cleanedStyle}"`;
  });
  data = data.replace(/ ?style=" *" ?/g,'').replace(/;;+/g,';')    //remove redundant semicolons and empty style attributes
  fs.writeFile(paths.src + "ts/icon-definitions.ts", data)
  return Promise.resolve('')
}
exports.icons = series(icon_definitions)
exports.icons.description = 'Optimises SVG files and writes icon-definitions.ts'

function html() {
  src(paths.src + 'html/**/*.*')
    .pipe(dest(paths.build))
  return src(paths.src + 'tests/**/*.*')
    .pipe(dest(paths.build + 'tests/'))
}
exports.assemble = parallel(exports.webpack, html, css, exports.icons)
exports.assemble.description = 'Assembles HTML, CSS, and JS output files'

function copy() {
  fs.recurseSync(paths.build + 'html', function(filepath, relative, filename) {
    //if filename is undefined, it's a directory
    if(filename == undefined && (filepath.match(/\\/g) || []).length == 2) {
      src(paths.build)
        .pipe(dest(filepath))
    }
  })
  src(paths.build)
    .pipe(dest(paths.build))
  return Promise.resolve('')
}

exports.build = series(clean, exports.assemble)
exports.build.description = 'Cleans and builds the project'

function stream() {
  return browserSync.stream()
}
const buildnc = series(parallel(series(cleantsc, transpile, webpack), html, css), copy, stream)

function loop() {
  var arg = (argv.slide || argv.s);
  var dir = 'tests/';
  var file = 'notes.html';
  if(arg) {
    if(arg.lastIndexOf('/'))
      dir = arg.substring(0, arg.lastIndexOf('/')+1);
    file = arg.substring(arg.lastIndexOf('/')+1);
  }

  browserSync.init({
    server: {
      index: dir + file,
      baseDir: [paths.build, paths.build + dir],
    }
  })
  watch(paths.src + '**/*.*', buildnc)
}
const gwatch = series(exports.build, loop)
exports.watch = gwatch
exports.watch.description = 'Automatically triggers build whenever a source file is changed and updates the browser'
exports.watch.flags = { '--slide | -s': 'Pass a custom slide deck to display (e.g. examples/rslidy-intro/index.html)' };

exports.default = exports.build