aboutsummaryrefslogtreecommitdiffstats
path: root/gulpfile.js
blob: a9a63fd8d9f7db5774af7ed9ef81aebf2e2f41b2 (plain) (blame)
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
const gulp = require('gulp')
const postcss = require('gulp-postcss')
const autoprefixer = require('autoprefixer')
const cssnano = require('cssnano')
const sourcemaps = require('gulp-sourcemaps')
const bytediff = require('gulp-bytediff')
const browserSync = require('browser-sync').create()
const chalk = require('chalk')
const rename = require('gulp-rename')
const filter = require('gulp-filter')
const flatten = require('gulp-flatten')
const sizereport = require('gulp-sizereport')
const postcssCssVariables = require('postcss-css-variables')
const postcssImport = require('postcss-import')
const postcssInlineSvg = require('postcss-inline-svg')
const postcssColorModFunction = require('postcss-color-mod-function').bind(null, {
  /* Use `.toRGBLegacy()` as other methods can result in lots of decimals */
  stringifier: (color) => color.toRGBLegacy()
})

const paths = {
  docs: { src: 'docs/**', dest: 'out/docs' },
  styles: { src: 'src/builds/*.css', dest: 'out', watch: 'src/**/*.css' }
}

// https://stackoverflow.com/a/20732091
const humanFileSize = (size) => {
  const i = Math.floor(Math.log(size) / Math.log(1024))
  return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]
}

const formatByteMessage = (source, data) => {
  const prettyStartSize = humanFileSize(data.startSize)
  let message = ''

  if (data.startSize !== data.endSize) {
    const change = data.savings > 0 ? 'saved' : 'gained'
    const prettySavings = humanFileSize(Math.abs(data.savings))
    let prettyEndSize = humanFileSize(data.endSize)

    if (data.endSize > data.startSize) prettyEndSize = chalk.yellow(prettyEndSize)
    if (data.endSize < data.startSize) prettyEndSize = chalk.green(prettyEndSize)

    message = chalk`${change} ${prettySavings} (${prettyStartSize} -> {bold ${prettyEndSize}})`
  } else message = chalk`kept original filesize. ({bold ${prettyStartSize}})`

  return chalk`{cyan ${source.padStart(12, ' ')}}: {bold ${data.fileName}} ${message}`
}

const style = () => {
  const startDiff = () => bytediff.start()
  const endDiff = (source) => bytediff.stop((data) => formatByteMessage(source, data))

  return (
    gulp
      .src(paths.styles.src)
      .pipe(postcss([postcssImport(), postcssColorModFunction(), postcssInlineSvg()]))

      .pipe(startDiff())
      .pipe(postcss([postcssCssVariables({ preserve: true })]))
      .pipe(endDiff('css variables'))

      .pipe(startDiff())
      .pipe(postcss([autoprefixer()]))
      .pipe(endDiff('autoprefixer'))

      .pipe(flatten()) // Put files in out/*, not out/builds/*
      .pipe(gulp.dest(paths.styles.dest))

      // <minifying>
      .pipe(startDiff())
      .pipe(postcss([cssnano({ preset: ['default', { svgo: { floatPrecision: 0 } }] })]))
      .pipe(endDiff('minification'))
      .pipe(rename({ suffix: '.min' }))
      // </minifying>

      .pipe(gulp.dest(paths.styles.dest))
      .pipe(gulp.dest(paths.docs.dest + '/noir.css'))

      .pipe(sizereport({ gzip: true, total: false, title: 'SIZE REPORT' }))
      .pipe(browserSync.stream())
  )
}

const docs = () => {
  const cssOnly = filter('**/*.css', { restore: true })

  return (
    gulp
      .src(paths.docs.src)

      // * Process CSS *
      .pipe(cssOnly)
      .pipe(sourcemaps.init())
      .pipe(postcss([autoprefixer(), cssnano()]))
      .pipe(sourcemaps.write('.'))
      .pipe(cssOnly.restore)

      .pipe(gulp.dest(paths.docs.dest))
  )
}

const browserReload = (done) => {
  browserSync.reload()
  return done()
}

const startDevServer = () => {
  browserSync.init({ server: { baseDir: './out/docs' } })

  gulp.watch(paths.styles.watch, gulp.series(style, browserReload))
  gulp.watch(paths.docs.src, gulp.series(docs, browserReload))
}

const build = gulp.parallel(style, docs)
const watch = gulp.series(build, startDevServer)

module.exports.build = build
module.exports.watch = watch