From 4b0200e0be51116e8c24f4065f5c5014041f975e Mon Sep 17 00:00:00 2001 From: Vaclovas Date: Mon, 29 May 2017 16:38:40 +0300 Subject: [PATCH] * Updated Scss structure. * Added check-deps for automated dependencies updating from package.json. * Automated image minification. --- .editorConfig | 14 +- .nvmrc | 2 +- CHANGELOG.md | 15 +- gulp-tasks/compile-scss.js | 2 +- gulp-tasks/create-hook.js | 9 + gulp-tasks/create-svg-sprite.js | 67 ++++---- gulp-tasks/develop.js | 15 ++ gulp-tasks/lint-commit.js | 55 +++++++ gulp-tasks/lint.js | 12 ++ gulp-tasks/prepare-assets.js | 13 ++ gulp-tasks/prepare-config.js | 9 + gulp-tasks/production.js | 13 ++ gulp-tasks/scss-linting.js | 9 +- gulp-tasks/{watchers => }/watch-all.js | 0 .../{watchers => }/watch-images-optimize.js | 2 +- gulp-tasks/{watchers => }/watch-scss.js | 2 +- gulp-tasks/{watchers => }/watch-svg.js | 2 +- gulp-tasks/watchers/watch-webpack.js | 31 ---- gulp-tasks/webpack.js | 18 -- gulp.config.js | 154 +++++++++++------- gulpfile.js | 18 +- package.json | 7 +- src/scss/base/_variables.scss | 2 +- src/scss/components/form-elements/_index.scss | 9 +- 24 files changed, 301 insertions(+), 179 deletions(-) create mode 100644 gulp-tasks/create-hook.js create mode 100644 gulp-tasks/develop.js create mode 100644 gulp-tasks/lint-commit.js create mode 100644 gulp-tasks/lint.js create mode 100644 gulp-tasks/prepare-assets.js create mode 100644 gulp-tasks/prepare-config.js create mode 100644 gulp-tasks/production.js rename gulp-tasks/{watchers => }/watch-all.js (100%) rename gulp-tasks/{watchers => }/watch-images-optimize.js (73%) rename gulp-tasks/{watchers => }/watch-scss.js (73%) rename gulp-tasks/{watchers => }/watch-svg.js (84%) delete mode 100644 gulp-tasks/watchers/watch-webpack.js delete mode 100644 gulp-tasks/webpack.js diff --git a/.editorConfig b/.editorConfig index 73edb80..e8b7a34 100644 --- a/.editorConfig +++ b/.editorConfig @@ -1,3 +1,13 @@ -[package.json] +# http://editorconfig.org +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 indent_style = space -indent_size = 2 \ No newline at end of file +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.nvmrc b/.nvmrc index 5b19a6b..f8c26c9 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -"5.11" +"6.4.0" diff --git a/CHANGELOG.md b/CHANGELOG.md index e3b77d4..51e717d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ -### 2.0.0 (July 13, 2016) +### 2.0.0 (July 1, 2017) + +* Updated normalize.scss to v4.1.1. +* Added .nvmrc file for use with node version manager. Node 6.4.0 version is required. +* Added .eslintrc file with eslint configuration + lodash, react plugins. +* Updated Scss structure. +* Added check-deps for automated dependencies updating from package.json. +* Automated image minification. +* Moved from scss-lint to sass-lint, fixed issues in code. +* Added language tag in HTML. +* Added gulp-accessibility task for automated accessibility testing. -* Updated normalize.scss to v4.1.1 -* Added .nvmrc file for use with node version manager. Node 5.11 version is required. -* Added .eslintrc file with eslint configuration + lodash, react plugins \ No newline at end of file diff --git a/gulp-tasks/compile-scss.js b/gulp-tasks/compile-scss.js index 71e53c0..4accebd 100644 --- a/gulp-tasks/compile-scss.js +++ b/gulp-tasks/compile-scss.js @@ -28,7 +28,7 @@ module.exports = function() { outputStyle: 'expanded', sourceMap: true, noCache: false, - includePaths: [].concat(neat, bourbon) + includePaths: [].concat(neat, bourbon, config.tmp) })) .on('error', swallowError) .pipe(csso()) diff --git a/gulp-tasks/create-hook.js b/gulp-tasks/create-hook.js new file mode 100644 index 0000000..aa52977 --- /dev/null +++ b/gulp-tasks/create-hook.js @@ -0,0 +1,9 @@ +const gulp = require("gulp"); +const rename = require("gulp-rename"); + +module.exports = function () { + + return gulp.src("./.pre-commit") + .pipe(rename("pre-commit")) + .pipe(gulp.dest("./.git/hooks")); +}; diff --git a/gulp-tasks/create-svg-sprite.js b/gulp-tasks/create-svg-sprite.js index 9797c2a..da26358 100644 --- a/gulp-tasks/create-svg-sprite.js +++ b/gulp-tasks/create-svg-sprite.js @@ -1,39 +1,40 @@ -module.exports = function () { - var gulp = require('gulp'), - plumber = require('gulp-plumber'), - svg2png = require('gulp-svg2png'), - config = require('../gulp.config.js')(), - svgSprite = require('gulp-svg-sprite'); +module.exports = function (done) { + var gulp = require("gulp"), + runSequence = require("run-sequence").use(gulp), + plumber = require("gulp-plumber"), + svg2png = require("gulp-svg2png"), + config = require("../gulp.config.js")(), + svgSprite = require("gulp-svg-sprite"); - gulp.task('svg-sprite', function () { - gulp.src(config.svg.sourceFolder + '*.svg') - .pipe(plumber({ - errorHandler: function (err) { - console.log(err); - this.emit('end'); - } - })) - .pipe(svgSprite(config.svgConfig)) - .pipe(gulp.dest('./')); - }); + gulp.task("svg-sprite", function () { + return gulp.src(config.svg.sourceFolder + "*.svg") + .pipe(plumber({ + errorHandler: function (err) { + console.log(err); + this.emit("end"); + } + })) + .pipe(svgSprite(config.svgConfig)) + .pipe(gulp.dest("./")); + }); - gulp.task('png-sprite', ['svg-sprite'], function () { - gulp.src(config.svg.spriteFolder + '*.svg') - .pipe(plumber({ - errorHandler: function () { - console.log(err); - this.emit('end'); - } - })) - .pipe(svg2png()) - .pipe(gulp.dest(config.svg.spriteFolder)); - }); + gulp.task("png-sprite", function () { + return gulp.src(config.svg.spriteFolder + "*.svg") + .pipe(plumber({ + errorHandler: function () { + console.log(err); + this.emit("end"); + } + })) + .pipe(svg2png()) + .pipe(gulp.dest(config.svg.spriteFolder)); + }); - if (config.svg.pngFallback) { - gulp.start('png-sprite') - } else { - gulp.start('svg-sprite') - } + if (config.svg.pngFallback) { + runSequence("svg-sprite", "png-sprite", done); + } else { + runSequence("svg-sprite", done); + } }; diff --git a/gulp-tasks/develop.js b/gulp-tasks/develop.js new file mode 100644 index 0000000..2ddf75a --- /dev/null +++ b/gulp-tasks/develop.js @@ -0,0 +1,15 @@ +module.exports = function (done) { + let gulp = require("gulp"), + runSequence = require("run-sequence").use(gulp); + + return runSequence( + "check-deps", + "prepare-assets", + "prepare-config", + "clear-image-cache", + "watch-scss", + "watch-svg", + "watch-images-optimize", + done + ); +}; diff --git a/gulp-tasks/lint-commit.js b/gulp-tasks/lint-commit.js new file mode 100644 index 0000000..3271d96 --- /dev/null +++ b/gulp-tasks/lint-commit.js @@ -0,0 +1,55 @@ +const gulp = require("gulp"); +const eslint = require("gulp-eslint"); +const config = require("../gulp.config.js")(); +const _ = require("lodash"); +const through = require("through2"); +const sassLint = require("gulp-sass-lint"); +const gulpif = require("gulp-if"); +const es = require("event-stream"); +const vinyl = require("vinyl-fs"); + +function replaceStreamWith() { + let pass = through.obj(); + return es.duplex(pass, vinyl.src.apply(vinyl.src, arguments)); +} + +function makeEmptyStream() { + return through.obj((a, b, cb) => cb(null)); +} + +function lintCode(srcJs, srcSass) { + return gulp.src(srcJs) + .pipe(eslint()) + .pipe(eslint.format()) + .pipe(eslint.failAfterError()) + .pipe(gulpif(!_.isEmpty(srcSass), replaceStreamWith(config.scss.lint), makeEmptyStream())) + .pipe(sassLint()) + .pipe(sassLint.format()) + .pipe(sassLint.failOnError()); +} + +function eslintCommit() { + const execSync = require("child_process").execSync; + const stdout = execSync("git diff --cached --name-only").toString() + + "\n" + + execSync("git diff --name-only").toString(); + + const resArray = stdout.split("\n"); + + const commitJsFiles = resArray + .filter((line) => line.endsWith(".js")) + .filter((line) => { + return _.reduce(config.custom.foldersToLint, (res, curr) => res || line.startsWith(curr), false); + }); + + const commitScssFiles = _(resArray).filter((line) => line.endsWith(".scss")).value(); + + + if (commitJsFiles.length > 0 || commitScssFiles.length > 0) { + return lintCode(commitJsFiles, commitScssFiles); + } +} + +module.exports = function () { + return eslintCommit(); +}; diff --git a/gulp-tasks/lint.js b/gulp-tasks/lint.js new file mode 100644 index 0000000..7098877 --- /dev/null +++ b/gulp-tasks/lint.js @@ -0,0 +1,12 @@ +const gulp = require("gulp"); +const eslint = require("gulp-eslint"); +const config = require("../gulp.config.js")(); +const _ = require("lodash"); + +module.exports = function () { + + return gulp.src(_.map(config.custom.foldersToLint, (folder) => `${folder}/**/*.js`)) + .pipe(eslint()) + .pipe(eslint.format()) + .pipe(eslint.failAfterError()); +}; diff --git a/gulp-tasks/prepare-assets.js b/gulp-tasks/prepare-assets.js new file mode 100644 index 0000000..7e1b7a2 --- /dev/null +++ b/gulp-tasks/prepare-assets.js @@ -0,0 +1,13 @@ +module.exports = function (done) { + var gulp = require('gulp'), + runSequence = require('run-sequence'), + config = require('../gulp.config.js')(); + + return runSequence('image-optimization', + 'create-svg-sprite', + 'scss-linting', + 'compile-scss', + done); +}; + + diff --git a/gulp-tasks/prepare-config.js b/gulp-tasks/prepare-config.js new file mode 100644 index 0000000..e9527a6 --- /dev/null +++ b/gulp-tasks/prepare-config.js @@ -0,0 +1,9 @@ +module.exports = function () { + const gulp = require("gulp"), + config = require("../gulp.config.js")(), + rename = require("gulp-rename"); + + return gulp.src(config.environmentConfig.source) + .pipe(rename("env.js")) + .pipe(gulp.dest(config.path.DEST)); +}; diff --git a/gulp-tasks/production.js b/gulp-tasks/production.js new file mode 100644 index 0000000..e164d94 --- /dev/null +++ b/gulp-tasks/production.js @@ -0,0 +1,13 @@ + +module.exports = function (done) { + let gulp = require("gulp"), + runSequence = require("run-sequence").use(gulp); + + return runSequence( + "check-deps", + "prepare-assets", + "prepare-config", + "clear-image-cache", + done + ); +}; diff --git a/gulp-tasks/scss-linting.js b/gulp-tasks/scss-linting.js index bbd8d9b..78e2a7e 100644 --- a/gulp-tasks/scss-linting.js +++ b/gulp-tasks/scss-linting.js @@ -1,12 +1,13 @@ module.exports = function () { - var scsslint = require('gulp-scss-lint'), + var sassLint = require('gulp-sass-lint'), gulp = require('gulp'), gulpif = require('gulp-if'), argv = require('yargs').argv, config = require('../gulp.config.js')(); - return gulp.src(['./scss/**/*.scss', '!./scss/**/*_scsslint_tmp*.scss', '!./scss/vendor/**/*.scss', '!./scss/base/_svg-sprite-map.scss', '!./scss/base/_svg-sprite-template.scss']) - .pipe(gulpif(!argv.nolint, scsslint())); + return gulp.src(config.scss.lint) + .pipe(gulpif(!argv.nolint, sassLint())) + .pipe(sassLint.format()) + .pipe(sassLint.failOnError()); }; - diff --git a/gulp-tasks/watchers/watch-all.js b/gulp-tasks/watch-all.js similarity index 100% rename from gulp-tasks/watchers/watch-all.js rename to gulp-tasks/watch-all.js diff --git a/gulp-tasks/watchers/watch-images-optimize.js b/gulp-tasks/watch-images-optimize.js similarity index 73% rename from gulp-tasks/watchers/watch-images-optimize.js rename to gulp-tasks/watch-images-optimize.js index e8a6142..f1cc9c9 100644 --- a/gulp-tasks/watchers/watch-images-optimize.js +++ b/gulp-tasks/watch-images-optimize.js @@ -1,6 +1,6 @@ module.exports = function () { var gulp = require('gulp'), - config = require('../../gulp.config.js')(); + config = require('../gulp.config.js')(); gulp.watch(config.optimize.images.src, ['image-optimization']); }; diff --git a/gulp-tasks/watchers/watch-scss.js b/gulp-tasks/watch-scss.js similarity index 73% rename from gulp-tasks/watchers/watch-scss.js rename to gulp-tasks/watch-scss.js index e5e5b8a..70fb051 100644 --- a/gulp-tasks/watchers/watch-scss.js +++ b/gulp-tasks/watch-scss.js @@ -1,6 +1,6 @@ module.exports = function () { var gulp = require('gulp'), - config = require('../../gulp.config.js')(); + config = require('../gulp.config.js')(); gulp.watch(config.scss.src, ['compile-scss', 'scss-linting']); }; diff --git a/gulp-tasks/watchers/watch-svg.js b/gulp-tasks/watch-svg.js similarity index 84% rename from gulp-tasks/watchers/watch-svg.js rename to gulp-tasks/watch-svg.js index 1ef1264..d25a92a 100644 --- a/gulp-tasks/watchers/watch-svg.js +++ b/gulp-tasks/watch-svg.js @@ -1,6 +1,6 @@ module.exports = function () { var gulp = require('gulp'), - config = require('../../gulp.config.js')(); + config = require('../gulp.config.js')(); return gulp.watch(config.svg.sourceFolder + '**/*.svg', function () { // Create SVG sprite diff --git a/gulp-tasks/watchers/watch-webpack.js b/gulp-tasks/watchers/watch-webpack.js deleted file mode 100644 index d03dd1f..0000000 --- a/gulp-tasks/watchers/watch-webpack.js +++ /dev/null @@ -1,31 +0,0 @@ -module.exports = function () { - var gulp = require('gulp'), - concat = require('gulp-concat'), - uglify = require('gulp-uglify'), - sourcemaps = require('gulp-sourcemaps'), - gutil = require("gulp-util"), - webpack = require("webpack"), - WebpackDevServer = require("webpack-dev-server"), - webpackConfig = require("../../webpack.config.js"), - config = require('../../gulp.config.js')(), - stream = require('webpack-stream'); - - // modify some webpack config options - var myConfig = Object.create(webpackConfig); - myConfig.devtool = "eval"; - myConfig.debug = true; - - // Start a webpack-dev-server - new WebpackDevServer(webpack(myConfig), { - publicPath: "/" + myConfig.output.publicPath, - hot: true, - stats: { - colors: true - } - }).listen(8080, "localhost", function(err) { - if (err) throw new gutil.PluginError("webpack-dev-server", err); - gutil.log("[webpack-dev-server]", "http://localhost:8080/webpack-dev-server/index.html"); - }); - gulp.watch(config.path.ALL, ['webpack']); -}; - diff --git a/gulp-tasks/webpack.js b/gulp-tasks/webpack.js deleted file mode 100644 index e4b0e4f..0000000 --- a/gulp-tasks/webpack.js +++ /dev/null @@ -1,18 +0,0 @@ -module.exports = function () { - var gulp = require('gulp'), - uglify = require('gulp-uglify'), - sourcemaps = require('gulp-sourcemaps'), - webpackConfig = require("../webpack.config.js"), - config = require('../gulp.config.js')(), - stream = require('webpack-stream'); - - return gulp.src(config.path.ALL) - .pipe(sourcemaps.init()) - .pipe(stream(webpackConfig)) - .pipe(uglify()) - .pipe(sourcemaps.write()) - .pipe(gulp.dest(config.path.DEST_BUILD)); -}; - - - diff --git a/gulp.config.js b/gulp.config.js index e2eb9c9..6b1ccfa 100644 --- a/gulp.config.js +++ b/gulp.config.js @@ -1,75 +1,105 @@ +const argv = require("yargs").argv; + +const ENV = process.env.npm_lifecycle_event; +const isProd = ENV && ENV.startsWith("build"); + module.exports = function () { - var svg = { - sourceFolder: 'scss/assets/icons/', - spriteFolder: 'content/styles/images/', - scssMapFolder: 'scss/base/', - pngFallback: false + const app = argv.app || "src"; + const environment = argv.environment || "dev"; + + const distFolder = "build"; + + + const tmp = "tmp/"; + const svg = { + sourceFolder: `${app}/scss/assets/icons/`, + spriteFolder: `${distFolder}/styles/images/`, + scssMapFolder: `${app}/scss/base/`, + scssTemplateFolder: `${app}/scss/base/`, + pngFallback: true }; - var config = { - path: { - HTML: '/index.html', - ALL: ['scripts/**/*.jsx', 'scripts/**/*.js'], - MINIFIED_OUT: 'build.min.js', - DEST_SRC: 'scripts', - DEST_BUILD: 'scripts', - DEST: 'dist' - }, - svg: { - sourceFolder: svg.sourceFolder, - spriteFolder: svg.spr, - scssMapFolder: svg.scssMapFolder, - pngFallback: svg.pngFallback - }, - scss: { - src: [ - './scss/**/*.scss', - '!scss/**/*_scsslint_tmp*.scss' //ignores temporary scss-lint files - ], - cssFolder: 'content/styles/' - } - , - optimize: { - css: {} - , - js: {} - , - images: { - src: 'content/images/originals/**/*.{png,gif,jpg,svg}', - dest: 'content/images/', - options: { // Target options - optimizationLevel: 7, - svgoPlugins: [{removeViewBox: false}], - progessive: true, - interlaced: true - } + const config = { + tmp, + root: "./", + packages: [ + "./package.json" + ], + custom: { + foldersToLint: ["src"] + }, + path: { + HTML: "/index.html", + ALL: [`${app}/src/main.js`], + MINIFIED_OUT: "build.min.js", + DEST_SRC: "scripts", + DEST_BUILD: "scripts", + DEST: distFolder + }, + environmentConfig: { + source: `config/${environment}.js` + }, + svg: { + sourceFolder: svg.sourceFolder, + spriteFolder: svg.spriteFolder, + scssMapFolder: svg.scssMapFolder, + pngFallback: svg.pngFallback + }, + scss: { + src: [ + `./${app}/scss/**/*.scss`, + `!./${app}/scss/**/*_scsslint_tmp*.scss` //ignores temporary scss-lint files + ], + lint: [ + `./${app}/scss/**/*.scss`, + `!./${app}/scss/base/_svg-sprite-map.scss`, + `!./${app}/scss/base/_svg-sprite.scss`, + `!./${app}/scss/**/*_scsslint_tmp*.scss`, + `!./${app}/scss/vendor/**/*.scss`, + `!./${app}/scss/base/_svg-sprite-map.scss`, + `!./${app}/scss/base/_svg-sprite-template.mustache` + ], + cssFolder: `${distFolder}/styles/` + } + , + optimize: { + css: {}, + js: {}, + images: { + src: `${app}/assets/images/**/*.{png,gif,jpg,svg}`, + dest: `${distFolder}/images/`, + options: { // Target options + optimizationLevel: 7, + svgoPlugins: [{removeViewBox: false}], + progessive: true, + interlaced: true } } - , - svgConfig: { - shape: { - spacing: { - padding: 0 - } + }, + svgConfig: { + shape: { + spacing: { + padding: 4 } - , - mode: { - css: { - bust: false, - dest: './', - // layout: 'vertical', 'horizontal', 'diagonal' - sprite: svg.spriteFolder + 'sprite.svg', - render: { - scss: { - dest: svg.scssMapFolder + '_svg-sprite-map.scss', - template: svg.scssMapFolder + '_svg-sprite-template.scss' - } + }, + variables: { + version: Math.round(+new Date() / 1000) + }, + mode: { + css: { + bust: false, + dest: "./", + // layout: "vertical", "horizontal", "diagonal" + sprite: svg.spriteFolder + "sprite.svg", + render: { + scss: { + dest: svg.scssMapFolder + "_svg-sprite-map.scss", + template: svg.scssTemplateFolder + "_svg-sprite-template.mustache" } } } } - , } - ; + }; return config; }; diff --git a/gulpfile.js b/gulpfile.js index 729130b..44f1b3d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,18 +1,12 @@ var gulp = require('gulp'), config = require('./gulp.config.js')(); -gulp.task('check-deps', function () { - require('check-dependencies')({ - install: true, - verbose: false - }); -}); - - -gulp.task('develop', ['check-deps', 'clear-image-cache', 'watch-scss', 'watch-svg', 'watch-webpack', 'watch-images-optimize']); - // Load all tasks from gulp-tasks folder require('gulp-task-loader')(); -// Load watcher tasks from gulp-tasks folder, watchers subdirectory -require('gulp-task-loader')('gulp-tasks/watchers'); \ No newline at end of file +gulp.task("check-deps", function () { + return require("check-dependencies")({ + install: true, + verbose: false + }); +}); \ No newline at end of file diff --git a/package.json b/package.json index c808ac0..c856a2e 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,10 @@ }, "description": "Starter project", "main": "gulpfile.js", - "dependencies": {}, + "dependencies": { + "gulp-eslint": "3.0.1", + "run-sequence": "1.2.2" + }, "scripts": { "start": "gulp develop" }, @@ -35,7 +38,7 @@ "gulp-sourcemaps": "2.6.0", "gulp-svg-sprite": "1.3.6", "gulp-svg2png": "2.0.2", - "gulp-task-loader": "1.4.4", + "gulp-task-loader": "1.2.1", "gulp-uglify": "3.0.0", "gulp-watch": "4.3.11", "node-bourbon": "4.2.8", diff --git a/src/scss/base/_variables.scss b/src/scss/base/_variables.scss index 0cd9280..bd8aa11 100644 --- a/src/scss/base/_variables.scss +++ b/src/scss/base/_variables.scss @@ -1,4 +1,4 @@ -//module TYPOGRAPHY + $base-line-height: 1.5; $base-font-size: 16px; diff --git a/src/scss/components/form-elements/_index.scss b/src/scss/components/form-elements/_index.scss index 4810291..24f82b1 100644 --- a/src/scss/components/form-elements/_index.scss +++ b/src/scss/components/form-elements/_index.scss @@ -2,9 +2,8 @@ // Form styles // // Styles for form elements (select, input, file upload, checkbox, radio and etc) - @import 'button', - 'checkbox', - 'input', - 'radio', - 'select'; \ No newline at end of file +'checkbox', +'input', +'radio', +'select'; \ No newline at end of file