Skip to content
Snippets Groups Projects
gulpfile.js 5.58 KiB
'use strict';

const { dest, lastRun, parallel, series, src, watch, task } = require('gulp');
const patternLabConfig = require('./pattern-lab-config.json');
const patternLab = require('@pattern-lab/core')(patternLabConfig);
const postcss = require('gulp-postcss');
const sass = require('gulp-sass');
const sassGlob = require('gulp-sass-glob');
const sourcemaps = require('gulp-sourcemaps');
const stylelint = require('gulp-stylelint');
const yaml = require('yaml');
const rename = require('gulp-rename');

const fs = require('fs');
const path = require('path');
const util = require('util');

const webpack = require('webpack');
const asyncWebpack = util.promisify(webpack);

const readSource = require('./lib/readSource');
const transform = require('./lib/transform');
const renderSass = require('./lib/renderSass');

const writeFile = util.promisify(fs.writeFile);
const os = require('os');

const concat = require('gulp-concat');
const uglify = require('gulp-uglify');

const jsSrc = [
  path.join(__dirname, '/source/_patterns/**/*.js'),
  '!' + path.join(__dirname, '/source/_patterns/00-config/**')
];
const jsDest = path.join(__dirname, '..', 'js');

const compileComponentScripts = () => {
  return src(jsSrc)
    .pipe(concat('component_scripts.min.js'))
    .pipe(dest(jsDest));
}

const cssSrc = path.join(__dirname, '..', 'css');

const buildConfig = async() => {
  const scssDir = path.join(__dirname, '/source/_patterns/00-config');
  const ymlDir = path.join(__dirname, './source/_data');

  const parsed = await readSource(
    path.join(
      __dirname,
      './source/_patterns/00-config/config.design-tokens.yml'
    )
  );
  const dataComment =
    '# DO NOT EDIT THIS FILE.  This is a gitignored artifact created by Gulp.' +
    os.EOL +
    '# Design tokens should be edited in _patterns/00-config/config.design-tokens.yml';

  const transformed = transform(parsed);
  const sassComment =
    '// DO NOT EDIT THIS FILE.  This is a gitignored artifact created by Gulp.' +
    os.EOL +
    '// Design tokens should be edited in config.design-tokens.yml';

  await Promise.all([
    writeFile(
      path.join(ymlDir, 'design-tokens.artifact.yml'),
      dataComment + os.EOL + yaml.stringify(transformed.data)
    ),
    writeFile(
      path.join(scssDir, '_design-tokens.artifact.scss'),
      sassComment + os.EOL + renderSass(transformed.data)
    ),
  ]);
};

const lintStyles = () => {
  return src('**/*.scss', { cwd: './source', since: lastRun(lintStyles) }).pipe(
    stylelint({
      configFile: '.stylelintrc.yml',
      failAfterError: true,
      reporters: [{ formatter: 'string', console: true }],
    })
  );
};

const compileStyles = () => {
  return src('*.scss', { cwd: './source' })
    .pipe(sassGlob())
    .pipe(sourcemaps.init())
    .pipe(
      sass({
        includePaths: ['./node_modules/breakpoint-sass/stylesheets'],
        precision: 10,
      })
    )
    .pipe(
      postcss([
        require('postcss-assets')(),
        require('autoprefixer')({
          remove: false,
        }),
      ])
    )
    .pipe(dest(cssSrc));
};

const layoutsSrc = [
  path.join(__dirname, '/source/uw-dashboards.scss')
];

const compileLayoutStyles = () => {
  return src(layoutsSrc)
    .pipe(sassGlob())
    .pipe(sourcemaps.init())
    .pipe(
      sass({
        includePaths: ['./node_modules/breakpoint-sass/stylesheets'],
        precision: 10,
      })
    )
    .pipe(
      postcss([
        require('postcss-assets')(),
        require('autoprefixer')({
          remove: false,
        }),
      ])
    )
    .pipe(dest(cssSrc));
};

const buildPatternLab = () => {
  return patternLab.build({ cleanPublic: true, watch: false });
};

async function webpackBundleScripts(mode) {
  const webpackConfig = require('./webpack.config')(mode);
  const stats = await asyncWebpack(webpackConfig);
  if (stats.hasErrors()) {
    throw new Error(stats.compilation.errors.join('\n'));
  }
}

const bundleScripts = (exports.gessoBundleScripts = () =>
  webpackBundleScripts('production'));

const bundleScriptsDev = () => webpackBundleScripts('development');

const watchFiles = () => {
  watch(
    [
      'source/**/*.scss',
      'images/*.svg',
      '!source/_patterns/00-config/_config.artifact.design-tokens.scss',
    ],
    { usePolling: true, interval: 1500 },
    series(lintStyles, buildStyles)
  );
  watch(
    ['source/_patterns/00-config/config.design-tokens.yml'],
    { usePolling: true, interval: 1500 },
    series(
      buildConfig,
      parallel(series(lintStyles, buildStyles), buildPatternLab),
      parallel(series(lintStyles, buildStyles), buildPatternLab)
    )
  );
  watch(
    [
      'source/**/*.{twig,json,yaml,yml}',
      '!source/_patterns/00-config/config.design-tokens.yml',
    ],
    { usePolling: true, interval: 1500 },
    buildPatternLab
  );
  watch(
    ['js/src/**/*.es6.js'],
    { usePolling: true, interval: 1500 },
    bundleScriptsDev
  );
  watch(
    [
      'source/_patterns/**/*.js',
      '!source/_patterns/00-config/**',
      '!source/_patterns/01-global/**',
    ],
    { usePolling: true, interval: 1500 },
    series(compileComponentScripts)
  );
};

const buildComponentScripts = (exports.buildScripts = series(compileComponentScripts));

const buildStyles = (exports.buildStyles = series(lintStyles, compileStyles, compileLayoutStyles));

const build = (isProduction = true ) => {
  const scriptTask = isProduction ? bundleScripts : bundleScriptsDev;
  task('bundleScripts', scriptTask)
  return series(
    buildConfig,
    parallel(task('bundleScripts'), buildStyles, buildComponentScripts, buildPatternLab));
}

exports.build = build(true);

exports.default = series(build(false), watchFiles);