From 45e769797d0b0de89b9f3c34c23d30c16713c74b Mon Sep 17 00:00:00 2001 From: Justin Gordon Date: Sat, 2 May 2015 13:18:47 -1000 Subject: [PATCH] Add configuration for full linting * Including eslint, jscs, rubocop, ruby-lint, brakeman, bundler-audit --- .rubocop.yml | 6 + .scss-lint.yml | 205 ++++++++++++++++++ Gemfile | 6 + Gemfile.lock | 30 +++ README.md | 27 +-- app/assets/stylesheets/_bootstrap-custom.scss | 82 +++---- app/assets/stylesheets/application.css.scss | 8 +- app/assets/stylesheets/scaffolds.css.scss | 47 ++-- client/.eslintrc | 7 +- client/README.md | 25 +++ client/assets/javascripts/FluxAlt.js | 2 - .../assets/javascripts/actions/FormActions.js | 4 +- .../javascripts/components/CommentBox.jsx | 2 - .../javascripts/components/CommentForm.jsx | 17 +- client/assets/javascripts/stores/FormStore.js | 2 +- .../javascripts/utils/CommentsManager.js | 2 +- .../_app-styling-post-bootstrap-loading.scss | 51 +---- .../_bootstrap-variables-customization.scss | 5 +- .../stylesheets/test-sass-stylesheet.scss | 4 +- client/assets/stylesheets/test-stylesheet.css | 2 +- client/bin/lint | 2 +- client/bootstrap-sass.config.js | 2 - client/gulpfile.js | 14 +- client/karma.conf.js | 6 +- client/npm-shrinkwrap.json | 146 +++++++------ client/package.json | 20 +- client/server.js | 2 +- client/tests.webpack.js | 3 +- client/webpack.common.config.js | 4 +- client/webpack.hot.config.js | 8 +- client/webpack.rails.config.js | 10 +- client/webpack.test-hot.config.js | 39 ---- config.ru | 2 +- lib/tasks/ci.rake | 35 +++ lib/tasks/linters.rake | 56 +++++ lib/tasks/rubocop.rake | 13 -- package.json | 2 +- ruby-lint.yml | 7 +- scripts/lint | 14 ++ 39 files changed, 606 insertions(+), 313 deletions(-) create mode 100644 .scss-lint.yml delete mode 100644 client/webpack.test-hot.config.js create mode 100644 lib/tasks/ci.rake create mode 100644 lib/tasks/linters.rake delete mode 100644 lib/tasks/rubocop.rake create mode 100755 scripts/lint diff --git a/.rubocop.yml b/.rubocop.yml index eaba5caa..ee3c1cca 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,14 +1,20 @@ # This is the configuration used to check the rubocop source code. +# Check out: https://github.com/bbatsov/rubocop AllCops: + Include: + - '**/Rakefile' + - '**/config.ru' Exclude: - 'vendor/**/*' - 'spec/fixtures/**/*' - 'node_modules/**/*' + - 'db/**/*' - 'db/schema.rb' - 'db/seeds.rb' - 'client/node_modules/**/*' - 'bin/**/*' + - !ruby/regexp /old_and_unused\.rb$/ Metrics/LineLength: Max: 120 diff --git a/.scss-lint.yml b/.scss-lint.yml new file mode 100644 index 00000000..52b2a854 --- /dev/null +++ b/.scss-lint.yml @@ -0,0 +1,205 @@ +# See http://sass-guidelin.es/#zeros + +scss_files: + - 'app/assets/stylesheets/**/*.scss' + - 'client/assets/stylesheets/**/*.scss' + +linters: +# BangFormat: +# enabled: true +# space_before_bang: true +# space_after_bang: false +# +# BorderZero: +# enabled: true +# convention: zero # or `none` +# + ColorKeyword: + enabled: false + ColorVariable: + enabled: false +# +# Comment: +# enabled: true +# +# DebugStatement: +# enabled: true +# +# DeclarationOrder: +# enabled: true +# +# DuplicateProperty: +# enabled: true +# +# ElsePlacement: +# enabled: true +# style: same_line # or 'new_line' +# +# EmptyLineBetweenBlocks: +# enabled: true +# ignore_single_line_blocks: true +# +# EmptyRule: +# enabled: true +# +# FinalNewline: +# enabled: true +# present: true +# + HexLength: + enabled: true + style: long + + HexNotation: + enabled: true + style: uppercase +# +# HexValidation: +# enabled: true +# + IdSelector: + enabled: true +# +# ImportantRule: +# enabled: true +# +# ImportPath: +# enabled: true +# leading_underscore: false +# filename_extension: false +# +# Indentation: +# enabled: true +# allow_non_nested_indentation: false +# character: space # or 'tab' +# width: 2 +# + LeadingZero: + enabled: true + style: include_zero +# +# MergeableSelector: +# enabled: true +# force_nesting: true +# +# NameFormat: +# enabled: true +# allow_leading_underscore: true +# convention: hyphenated_lowercase # or 'camel_case', or 'snake_case', or a regex pattern +# +# NestingDepth: +# enabled: true +# max_depth: 3 +# +# PlaceholderInExtend: +# enabled: true +# +# PropertyCount: +# enabled: false +# include_nested: false +# max_properties: 10 +# +# PropertyUnits: +# enabled: true +# global: [ +# 'ch', 'em', 'ex', 'rem', # Font-relative lengths +# 'cm', 'in', 'mm', 'pc', 'pt', 'px', 'q', # Absolute lengths +# 'vh', 'vw', 'vmin', 'vmax', # Viewport-percentage lengths +# 'deg', 'grad', 'rad', 'turn', # Angle +# 'ms', 's', # Duration +# 'Hz', 'kHz', # Frequency +# 'dpi', 'dpcm', 'dppx', # Resolution +# '%', # Other +# ] +# properties: {} +# +# PropertySortOrder: +# enabled: true +# ignore_unspecified: false +# separate_groups: false +# +# PropertySpelling: +# enabled: true +# extra_properties: [] +# +# QualifyingElement: +# enabled: true +# allow_element_with_attribute: false +# allow_element_with_class: false +# allow_element_with_id: false +# +# SelectorDepth: +# enabled: true +# max_depth: 3 +# +# SelectorFormat: +# enabled: true +# convention: hyphenated_lowercase # or 'strict_BEM', or 'hyphenated_BEM', or 'snake_case', or 'camel_case', or a regex pattern +# +# Shorthand: +# enabled: true +# allowed_shorthands: [1, 2, 3] +# +# SingleLinePerProperty: +# enabled: true +# allow_single_line_rule_sets: true +# +# SingleLinePerSelector: +# enabled: true +# +# SpaceAfterComma: +# enabled: true +# +# SpaceAfterPropertyColon: +# enabled: true +# style: one_space # or 'no_space', or 'at_least_one_space', or 'aligned' +# +# SpaceAfterPropertyName: +# enabled: true +# +# SpaceBeforeBrace: +# enabled: true +# style: space # or 'new_line' +# allow_single_line_padding: false +# +# SpaceBetweenParens: +# enabled: true +# spaces: 0 +# +# StringQuotes: +# enabled: true +# style: single_quotes # or double_quotes +# +# TrailingSemicolon: +# enabled: true +# +# TrailingZero: +# enabled: false +# +# UnnecessaryMantissa: +# enabled: true +# +# UnnecessaryParentReference: +# enabled: true +# +# UrlFormat: +# enabled: true +# +# UrlQuotes: +# enabled: true +# +# VariableForProperty: +# enabled: false +# properties: [] +# +# VendorPrefix: +# enabled: true +# identifier_list: base +# additional_identifiers: [] +# excluded_identifiers: [] +# +# ZeroUnit: +# enabled: true +# +# Compass::*: +# enabled: false diff --git a/Gemfile b/Gemfile index d8dcd067..49c799d7 100644 --- a/Gemfile +++ b/Gemfile @@ -62,6 +62,12 @@ group :development, :test do gem "rubocop", require: false gem "ruby-lint", require: false + + gem "scss-lint", require: false + + gem "brakeman", require: false + + gem "bundler-audit", require: false end gem "spring-commands-rspec", group: :development diff --git a/Gemfile.lock b/Gemfile.lock index eb46e969..eeb18b19 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -49,7 +49,20 @@ GEM bootstrap-sass (3.3.4.1) autoprefixer-rails (>= 5.0.0.1) sass (>= 3.2.19) + brakeman (3.0.3) + erubis (~> 2.6) + fastercsv (~> 1.5) + haml (>= 3.0, < 5.0) + highline (~> 1.6.20) + multi_json (~> 1.2) + ruby2ruby (~> 2.1.1) + ruby_parser (~> 3.6.2) + sass (~> 3.0) + terminal-table (~> 1.4) builder (3.2.2) + bundler-audit (0.3.1) + bundler (~> 1.2) + thor (~> 0.18) byebug (4.0.3) columnize (= 0.9.0) capybara (2.4.4) @@ -82,10 +95,14 @@ GEM factory_girl_rails (4.5.0) factory_girl (~> 4.5.0) railties (>= 3.0.0) + fastercsv (1.5.5) foreman (0.78.0) thor (~> 0.19.1) globalid (0.3.3) activesupport (>= 4.1.0) + haml (4.0.6) + tilt + highline (1.6.21) hike (1.2.3) i18n (0.7.0) jbuilder (2.2.12) @@ -177,6 +194,11 @@ GEM parser (~> 2.1, >= 2.1.1) slop (~> 3.4, >= 3.4.7) ruby-progressbar (1.7.5) + ruby2ruby (2.1.4) + ruby_parser (~> 3.1) + sexp_processor (~> 4.0) + ruby_parser (3.6.6) + sexp_processor (~> 4.1) sass (3.4.13) sass-rails (5.0.1) railties (>= 4.0.0, < 5.0) @@ -184,9 +206,13 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (~> 1.1) + scss-lint (0.37.0) + rainbow (~> 2.0) + sass (~> 3.4.1) sdoc (0.4.1) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) + sexp_processor (4.5.1) slop (3.6.0) spring (1.3.3) spring-commands-rspec (1.0.4) @@ -201,6 +227,7 @@ GEM activesupport (>= 3.0) sprockets (>= 2.8, < 4.0) sqlite3 (1.3.10) + terminal-table (1.4.5) thor (0.19.1) thread_safe (0.3.5) tilt (1.4.1) @@ -229,6 +256,8 @@ PLATFORMS DEPENDENCIES autoprefixer-rails bootstrap-sass (~> 3.3.1) + brakeman + bundler-audit byebug capybara capybara-screenshot @@ -248,6 +277,7 @@ DEPENDENCIES rubocop ruby-lint sass-rails + scss-lint sdoc spring spring-commands-rspec diff --git a/README.md b/README.md index 031c1970..9e5088d9 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ In no particular order: - Easily enable use of npm modules with a Rails application. - Easily enable retrofitting such a JS framework into an existing Rails app. - Enable the use of the JavaScript ES6 transpiler. +- Example setting up Ruby and ES6 linting in a real project. # Technologies involved @@ -216,18 +217,6 @@ To deploy the app on Heroku: git push heroku master ``` -# Update Node Modules -``` -rm npm-shrinkwrap.json -npm-check-updates -u -npm install -npm shrinkwrap -``` - -Then confirm that the hot reload server and the rails server both work fine. You -may have to delete `node_modules` and `npm-shrinkwrap.json` and then run `npm -shrinkwrap`. - # Running Tests *Default rake task runs tests and linting* @@ -258,14 +247,26 @@ QMAKE=/usr/local/Cellar/qt5/5.4.0/bin/qmake bundle install Then run `rspec` and you should see the tests have passed. # Linting and Code Inspection -* Default rake task runs tests and linting (yes, repeating this!) +## Running Lint and CI tasks +* Default rake task runs tests and linting (yes, repeating this!) (see `ci.rake`) * See file [README.md](client/README.md) for how to run ESLint and JSCS +* See scripts `scripts/lint` and `client/bin/lint`. * Create a custom scope like this for RubyMine, named "Inspection Scope" file[react-rails-tutorial]:*/&&!file[react-rails-tutorial]:tmp//*&&!file[react-rails-tutorial]:log//*&&!file[react-rails-tutorial]:client/node_modules//*&&!file[react-rails-tutorial]:client/assets/fonts//*&&!file[react-rails-tutorial]:app/assets/fonts//*&&!file[react-rails-tutorial]:bin//*&&!file[react-rails-tutorial]:app/assets/javascripts//* * Install the code style and inspection files in [client/jetbrains](client/jetbrains) * Use the installed inspection settings and new Inspection Scope for code inspection. +* RubyMine configuration is optional. All linters run from the command line. + +## Linters + 1. [Rubocop](https://github.com/bbatsov/rubocop) + 2. [Ruby-Lint](https://github.com/YorickPeterse/ruby-lint) + 3. [Eslint](http://eslint.org/) + 4. [JSCS](https://github.com/jscs-dev/node-jscs) + 5. [scss-lint](https://github.com/brigade/scss-lint) + 6. [brakeman](http://brakemanscanner.org/) + 7. [bundle-audit](https://github.com/rubysec/bundler-audit) # Contributors * [Martin Breining](https://github.com/mbreining) diff --git a/app/assets/stylesheets/_bootstrap-custom.scss b/app/assets/stylesheets/_bootstrap-custom.scss index b987dca1..f2708cb7 100644 --- a/app/assets/stylesheets/_bootstrap-custom.scss +++ b/app/assets/stylesheets/_bootstrap-custom.scss @@ -2,58 +2,58 @@ // The _bootstrap-variables-customization.scss file is located under // client/assets/stylesheets, which has been added to the Rails asset // pipeline search path. See config/application.rb. -@import "bootstrap-variables-customization"; +@import 'bootstrap-variables-customization'; // Core variables and mixins -@import "bootstrap/variables"; -@import "bootstrap/mixins"; +@import 'bootstrap/variables'; +@import 'bootstrap/mixins'; // Reset and dependencies -@import "bootstrap/normalize"; -@import "bootstrap/print"; -@import "bootstrap/glyphicons"; +@import 'bootstrap/normalize'; +@import 'bootstrap/print'; +@import 'bootstrap/glyphicons'; // Core CSS -@import "bootstrap/scaffolding"; -@import "bootstrap/type"; -@import "bootstrap/code"; -@import "bootstrap/grid"; -@import "bootstrap/tables"; -@import "bootstrap/forms"; -@import "bootstrap/buttons"; +@import 'bootstrap/scaffolding'; +@import 'bootstrap/type'; +@import 'bootstrap/code'; +@import 'bootstrap/grid'; +@import 'bootstrap/tables'; +@import 'bootstrap/forms'; +@import 'bootstrap/buttons'; // Components -@import "bootstrap/component-animations"; -@import "bootstrap/dropdowns"; -@import "bootstrap/button-groups"; -@import "bootstrap/input-groups"; -@import "bootstrap/navs"; -@import "bootstrap/navbar"; -@import "bootstrap/breadcrumbs"; -@import "bootstrap/pagination"; -@import "bootstrap/pager"; -@import "bootstrap/labels"; -@import "bootstrap/badges"; -//@import "bootstrap/jumbotron"; // excluding as an example -@import "bootstrap/thumbnails"; -@import "bootstrap/alerts"; -//@import "bootstrap/progress-bars"; // excluding as an example -@import "bootstrap/media"; -@import "bootstrap/list-group"; -@import "bootstrap/panels"; -@import "bootstrap/responsive-embed"; -@import "bootstrap/wells"; -@import "bootstrap/close"; +@import 'bootstrap/component-animations'; +@import 'bootstrap/dropdowns'; +@import 'bootstrap/button-groups'; +@import 'bootstrap/input-groups'; +@import 'bootstrap/navs'; +@import 'bootstrap/navbar'; +@import 'bootstrap/breadcrumbs'; +@import 'bootstrap/pagination'; +@import 'bootstrap/pager'; +@import 'bootstrap/labels'; +@import 'bootstrap/badges'; +//@import 'bootstrap/jumbotron'; // excluding as an example +@import 'bootstrap/thumbnails'; +@import 'bootstrap/alerts'; +//@import 'bootstrap/progress-bars'; // excluding as an example +@import 'bootstrap/media'; +@import 'bootstrap/list-group'; +@import 'bootstrap/panels'; +@import 'bootstrap/responsive-embed'; +@import 'bootstrap/wells'; +@import 'bootstrap/close'; // Components w/ JavaScript -@import "bootstrap/modals"; // excluding as an example -@import "bootstrap/tooltip"; -@import "bootstrap/popovers"; -@import "bootstrap/carousel"; // excluding as an example +@import 'bootstrap/modals'; // excluding as an example +@import 'bootstrap/tooltip'; +@import 'bootstrap/popovers'; +@import 'bootstrap/carousel'; // excluding as an example // Utility classes -@import "bootstrap/utilities"; -@import "bootstrap/responsive-utilities"; +@import 'bootstrap/utilities'; +@import 'bootstrap/responsive-utilities'; // This must come after all the boostrap styles are loaded so that these styles can override those. -@import "app-styling-post-bootstrap-loading"; +@import 'app-styling-post-bootstrap-loading'; diff --git a/app/assets/stylesheets/application.css.scss b/app/assets/stylesheets/application.css.scss index 05c05704..e2670123 100644 --- a/app/assets/stylesheets/application.css.scss +++ b/app/assets/stylesheets/application.css.scss @@ -5,8 +5,8 @@ $rails: true; // Those scss files are located under client/assets/stylesheets, // which has been added to the Rails asset pipeline search path. // See config/application.rb. -@import "bootstrap-custom"; -@import "test-stylesheet"; -@import "test-sass-stylesheet"; +@import 'bootstrap-custom'; +@import 'test-stylesheet'; +@import 'test-sass-stylesheet'; -@import "bootstrap-sprockets"; +@import 'bootstrap-sprockets'; diff --git a/app/assets/stylesheets/scaffolds.css.scss b/app/assets/stylesheets/scaffolds.css.scss index f0f9f3bd..5bb34c9a 100644 --- a/app/assets/stylesheets/scaffolds.css.scss +++ b/app/assets/stylesheets/scaffolds.css.scss @@ -1,36 +1,43 @@ +// scss-lint:disable SelectorFormat, IdSelector body { - background-color: #fff; - color: #333; + background-color: #FFFFFF; + color: #333333; font-family: verdana, arial, helvetica, sans-serif; font-size: 13px; line-height: 18px; } -p, ol, ul, td { +p, +ol, +ul, +td { font-family: verdana, arial, helvetica, sans-serif; font-size: 13px; line-height: 18px; } pre { - background-color: #eee; - padding: 10px; + background-color: #EEEEEE; font-size: 11px; + padding: 10px; } a { - color: #000; + color: #000000; + &:visited { - color: #666; + color: #666666; } + &:hover { - color: #fff; - background-color: #000; + background-color: #000000; + color: #FFFFFF; } } div { - &.field, &.actions { + &.field, + &.actions { margin-bottom: 10px; } } @@ -40,27 +47,29 @@ div { } .field_with_errors { - padding: 2px; background-color: red; display: table; + padding: 2px; } #error_explanation { - width: 450px; + background-color: #F0F0F0; border: 2px solid red; - padding: 7px 7px 0; margin-bottom: 20px; - background-color: #f0f0f0; + padding: 7px 7px 0; + width: 450px; + h2 { - text-align: left; - font-weight: bold; - padding: 5px 5px 5px 15px; + background-color: #CC0000; + color: #FFFFFF; font-size: 12px; + font-weight: bold; margin: -7px; margin-bottom: 0; - background-color: #c00; - color: #fff; + padding: 5px 5px 5px 15px; + text-align: left; } + ul li { font-size: 12px; list-style: square; diff --git a/client/.eslintrc b/client/.eslintrc index f2f6f252..4f2691a7 100644 --- a/client/.eslintrc +++ b/client/.eslintrc @@ -163,7 +163,12 @@ "no-wrap-func": 2, // http://eslint.org/docs/rules/no-wrap-func "no-underscore-dangle": 0, // http://eslint.org/docs/rules/no-underscore-dangle "one-var": [2, "never"], // http://eslint.org/docs/rules/one-var - "padded-blocks": [1, "never"], // http://eslint.org/docs/rules/padded-blocks + + # Change after this issue is fixed: + # https://github.com/babel/babel-eslint/issues/33 + "padded-blocks": 0, // http://eslint.org/docs/rules/padded-blocks +# "padded-blocks": [1, "never"], // http://eslint.org/docs/rules/padded-blocks + "semi": [2, "always"], // http://eslint.org/docs/rules/semi "semi-spacing": [2, { // http://eslint.org/docs/rules/semi-spacing "before": false, diff --git a/client/README.md b/client/README.md index 0c959a12..df88be48 100644 --- a/client/README.md +++ b/client/README.md @@ -20,3 +20,28 @@ So don't use `npm run gulp lint` yet. For now: bin/lint + + + +Updating Node Dependenencies +=========================== + +``` +npm install -g npm-check-updates +``` + + +``` +rm npm-shrinkwrap.json +npm-check-updates -u +npm install +npm shrinkwrap +``` + +Then confirm that the hot reload server and the rails server both work fine. You +may have to delete `node_modules` and `npm-shrinkwrap.json` and then run `npm +shrinkwrap`. + + + + diff --git a/client/assets/javascripts/FluxAlt.js b/client/assets/javascripts/FluxAlt.js index 396d6ca9..4575c21e 100644 --- a/client/assets/javascripts/FluxAlt.js +++ b/client/assets/javascripts/FluxAlt.js @@ -1,5 +1,3 @@ -'use strict'; - import Alt from 'alt'; const alt = new Alt(); diff --git a/client/assets/javascripts/actions/FormActions.js b/client/assets/javascripts/actions/FormActions.js index 966a90c7..507e3fcd 100644 --- a/client/assets/javascripts/actions/FormActions.js +++ b/client/assets/javascripts/actions/FormActions.js @@ -22,8 +22,8 @@ class FormActions { submitComment(url, comment) { this.dispatch(); CommentsManager.submitComment(url, comment) - .then((comment) => { - CommentActions.addComment(comment); + .then((returnedComment) => { + CommentActions.addComment(returnedComment); }, (errorMessage) => { diff --git a/client/assets/javascripts/components/CommentBox.jsx b/client/assets/javascripts/components/CommentBox.jsx index 46b2b46e..82af0fd6 100644 --- a/client/assets/javascripts/components/CommentBox.jsx +++ b/client/assets/javascripts/components/CommentBox.jsx @@ -1,11 +1,9 @@ -import $ from 'jquery'; import React from 'react'; import CommentForm from './CommentForm'; import CommentList from './CommentList'; import CommentStore from '../stores/CommentStore'; import FormStore from '../stores/FormStore'; import CommentActions from '../actions/CommentActions'; -import FormActions from '../actions/FormActions'; const CommentBox = React.createClass({ displayName: 'CommentBox', diff --git a/client/assets/javascripts/components/CommentForm.jsx b/client/assets/javascripts/components/CommentForm.jsx index 2bd0e4dd..7a8ffc9f 100644 --- a/client/assets/javascripts/components/CommentForm.jsx +++ b/client/assets/javascripts/components/CommentForm.jsx @@ -16,29 +16,30 @@ const CommentForm = React.createClass({ ajaxSending: React.PropTypes.bool.isRequired }, - getInitialState: function() { + getInitialState() { return { formMode: 0 }; }, - handleSelect: function(selectedKey) { + handleSelect(selectedKey) { this.setState({formMode: selectedKey}); }, handleChange() { + let obj; + // This could also be done using ReactLink: // http://facebook.github.io/react/docs/two-way-binding-helpers.html - let obj; if (this.state.formMode < 2) { obj = { author: this.refs.author.getValue(), text: this.refs.text.getValue() }; } else { - // This is different because the input is a native HTML element - // rather than a React element. obj = { + // This is different because the input is a native HTML element + // rather than a React element. author: this.refs.inlineAuthor.getDOMNode().value, text: this.refs.inlineText.getDOMNode().value }; @@ -52,7 +53,7 @@ const CommentForm = React.createClass({ FormActions.submitComment(this.props.url, FormStore.getState().comment); }, - formHorizontal: function() { + formHorizontal() { return (

@@ -79,7 +80,7 @@ const CommentForm = React.createClass({ ); }, - formStacked: function() { + formStacked() { return (

@@ -97,7 +98,7 @@ const CommentForm = React.createClass({ ); }, - formInline: function() { + formInline() { return (

diff --git a/client/assets/javascripts/stores/FormStore.js b/client/assets/javascripts/stores/FormStore.js index f7be41c6..c5df8aa6 100644 --- a/client/assets/javascripts/stores/FormStore.js +++ b/client/assets/javascripts/stores/FormStore.js @@ -2,7 +2,7 @@ import alt from '../FluxAlt'; import FormActions from '../actions/FormActions'; import CommentActions from '../actions/CommentActions'; -const emptyComment = { author: '', text: '' }; +const emptyComment = {author: '', text: ''}; class FormStore { constructor() { diff --git a/client/assets/javascripts/utils/CommentsManager.js b/client/assets/javascripts/utils/CommentsManager.js index b4cbb0e1..16e7e142 100644 --- a/client/assets/javascripts/utils/CommentsManager.js +++ b/client/assets/javascripts/utils/CommentsManager.js @@ -26,7 +26,7 @@ const CommentsManager = { url: url, dataType: 'json', type: 'POST', - data: { comment: comment } + data: {comment: comment} }); } }; diff --git a/client/assets/stylesheets/_app-styling-post-bootstrap-loading.scss b/client/assets/stylesheets/_app-styling-post-bootstrap-loading.scss index 4426caee..8e67e5fc 100644 --- a/client/assets/stylesheets/_app-styling-post-bootstrap-loading.scss +++ b/client/assets/stylesheets/_app-styling-post-bootstrap-loading.scss @@ -6,20 +6,16 @@ body { padding-top: 20px; } -#main-entry-point { - color: pink; -} - .doc-content { padding-top: 10px; } .logo { - background: img-url("railsonmaui.png") no-repeat left bottom; + background: img-url('railsonmaui.png') no-repeat left bottom; + display: inline-block; height: 40px; - width: 146px; margin-right: 10px; - display: inline-block; + width: 146px; } .twitter-image { @@ -34,6 +30,8 @@ body { // ## Nav // When nav is affixed, set it's position and size. + +// scss-lint:disable IdSelector #nav.affix { position: fixed; top: 3px; @@ -41,42 +39,3 @@ body { z-index: 10; } -// ## Code -// Set up table to render two column view -// of documentation on left and code, syntax -// highlighted on the right. -table.file-table { - width: 100%; - border-radius: $border-radius-base; - border: 0; - border-spacing: 0; - display: table; - table-layout: fixed; - - td.file-docs { - background-color: #fff; - width: 30%; - max-width: 30%; - text-overflow: ellipsis; - padding: 5px; - vertical-align: top; - } - - td.file-code { - border-left: 1px groove darken(#f5f5f5, 20%); - background-color: #f5f5f5; - color: #333; - width: 70%; - max-width: 70%; - text-overflow: ellipsis; - padding-left: 5px; - vertical-align: bottom; - } - // Remove extra separation between the code - // so it looks more like one continuous block. - pre.prettyprint { - padding: 0 !important; - border: 0 !important; - margin: 0 0 !important; - } -} diff --git a/client/assets/stylesheets/_bootstrap-variables-customization.scss b/client/assets/stylesheets/_bootstrap-variables-customization.scss index e46b1303..003f0b6d 100644 --- a/client/assets/stylesheets/_bootstrap-variables-customization.scss +++ b/client/assets/stylesheets/_bootstrap-variables-customization.scss @@ -23,11 +23,12 @@ $font-size-base: 15px; // Sass 3 removes image-url helper // https://github.com/sass/libsass/issues/489 -$image-url-path: "/assets/images/" !default; +$image-url-path: '/assets/images/' !default; + @function img-url($image) { @if $rails { @return image-url($image); } @else { - @return url("#{$image-url-path}#{$image}"); + @return url('#{$image-url-path}#{$image}'); } } diff --git a/client/assets/stylesheets/test-sass-stylesheet.scss b/client/assets/stylesheets/test-sass-stylesheet.scss index 71e4f0e9..10433e1f 100644 --- a/client/assets/stylesheets/test-sass-stylesheet.scss +++ b/client/assets/stylesheets/test-sass-stylesheet.scss @@ -1,6 +1,6 @@ -/* Proof of concept of loading css from webpack */ +// Proof of concept of loading css from webpack // partial defines the $comment-text-color -@import "test-sass-stylesheet-partial"; +@import 'test-sass-stylesheet-partial'; .comment { p { diff --git a/client/assets/stylesheets/test-stylesheet.css b/client/assets/stylesheets/test-stylesheet.css index e078392d..b5f69e62 100644 --- a/client/assets/stylesheets/test-stylesheet.css +++ b/client/assets/stylesheets/test-stylesheet.css @@ -1,4 +1,4 @@ -/* Proof of concept of loading css from webpack */ +// Proof of concept of loading css from webpack .comment-author { color: blue; diff --git a/client/bin/lint b/client/bin/lint index f66e8d9f..284b920e 100755 --- a/client/bin/lint +++ b/client/bin/lint @@ -3,7 +3,7 @@ echo =========================================================================== echo Warnings are OPTIONAL echo ================================================================================ -find . -path ./node_modules -prune -o -name "*.js" -o -name "*.jsx" -exec eslint {} \; +npm run eslint . -- --ext .jsx,.js npm run jscs . echo ================================================================================ diff --git a/client/bootstrap-sass.config.js b/client/bootstrap-sass.config.js index 9cb808ee..08dab813 100644 --- a/client/bootstrap-sass.config.js +++ b/client/bootstrap-sass.config.js @@ -1,8 +1,6 @@ // IMPORTANT: Make sure to keep the customizations defined in this file // in-sync with the ones defined in app/assets/stylesheets/_bootstrap-custom.scss. -'use strict'; - module.exports = { bootstrapCustomizations: './assets/stylesheets/_bootstrap-variables-customization.scss', mainSass: './assets/stylesheets/_app-styling-post-bootstrap-loading.scss', diff --git a/client/gulpfile.js b/client/gulpfile.js index 720077ce..eed37cf6 100644 --- a/client/gulpfile.js +++ b/client/gulpfile.js @@ -1,17 +1,15 @@ -'use strict'; +const gulp = require('gulp'); +const eslint = require('gulp-eslint'); -var gulp = require('gulp'); -var eslint = require('gulp-eslint'); - -gulp.task('lint', function() { - // Note: To have the process exit with an error code (1) on - // lint error, return the stream and pipe to failOnError last. +// Note: To have the process exit with an error code (1) on +// lint error, return the stream and pipe to failOnError last. +gulp.task('lint', function gulpLint() { return gulp.src(['assets/javascripts/**/*.jsx', 'scripts/**/*.jsx', '*.js']) .pipe(eslint()) .pipe(eslint.format()) .pipe(eslint.failOnError()); }); -gulp.task('default', ['lint'], function() { +gulp.task('default', ['lint'], function gulpDefault() { // This will only run if the lint task is successful... }); diff --git a/client/karma.conf.js b/client/karma.conf.js index 1b77a2f2..d6d592b6 100644 --- a/client/karma.conf.js +++ b/client/karma.conf.js @@ -1,8 +1,6 @@ -'use strict'; +const webpack = require('webpack'); -var webpack = require('webpack'); - -module.exports = function(config) { +module.exports = function karmaMain(config) { config.set({ browserNoActivityTimeout: 30000, diff --git a/client/npm-shrinkwrap.json b/client/npm-shrinkwrap.json index a01a8737..5b2b7468 100644 --- a/client/npm-shrinkwrap.json +++ b/client/npm-shrinkwrap.json @@ -3,9 +3,9 @@ "version": "1.1.0", "dependencies": { "alt": { - "version": "0.15.6", - "from": "alt@>=0.15.6 <0.16.0", - "resolved": "https://registry.npmjs.org/alt/-/alt-0.15.6.tgz", + "version": "0.16.1", + "from": "alt@0.16.1", + "resolved": "https://registry.npmjs.org/alt/-/alt-0.16.1.tgz", "dependencies": { "es-symbol": { "version": "1.1.1", @@ -18,9 +18,9 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-0.1.6.tgz" }, "flux": { - "version": "2.0.1", + "version": "2.0.3", "from": "flux@>=2.0.1 <3.0.0", - "resolved": "https://registry.npmjs.org/flux/-/flux-2.0.1.tgz" + "resolved": "https://registry.npmjs.org/flux/-/flux-2.0.3.tgz" }, "object-assign": { "version": "2.0.0", @@ -30,15 +30,20 @@ } }, "babel-core": { - "version": "5.1.13", - "from": "babel-core@>=5.1.13 <6.0.0", - "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-5.1.13.tgz", + "version": "5.2.6", + "from": "babel-core@5.2.6", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-5.2.6.tgz", "dependencies": { "ast-types": { "version": "0.7.6", "from": "ast-types@>=0.7.0 <0.8.0", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.7.6.tgz" }, + "bluebird": { + "version": "2.9.25", + "from": "bluebird@>=2.9.25 <3.0.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.9.25.tgz" + }, "chalk": { "version": "1.0.0", "from": "chalk@>=1.0.0 <2.0.0", @@ -61,7 +66,7 @@ "dependencies": { "ansi-regex": { "version": "1.1.1", - "from": "ansi-regex@>=1.1.0 <2.0.0", + "from": "ansi-regex@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" }, "get-stdin": { @@ -78,7 +83,7 @@ "dependencies": { "ansi-regex": { "version": "1.1.1", - "from": "ansi-regex@>=1.1.0 <2.0.0", + "from": "ansi-regex@>=1.0.0 <2.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-1.1.1.tgz" } } @@ -96,9 +101,9 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.0.tgz" }, "core-js": { - "version": "0.9.3", + "version": "0.9.6", "from": "core-js@>=0.9.0 <0.10.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-0.9.3.tgz" + "resolved": "https://registry.npmjs.org/core-js/-/core-js-0.9.6.tgz" }, "debug": { "version": "2.1.3", @@ -189,14 +194,14 @@ } }, "lodash": { - "version": "3.7.0", + "version": "3.8.0", "from": "lodash@>=3.6.0 <4.0.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz" + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.8.0.tgz" }, "minimatch": { - "version": "2.0.4", + "version": "2.0.7", "from": "minimatch@>=2.0.3 <3.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.4.tgz", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.7.tgz", "dependencies": { "brace-expansion": { "version": "1.1.0", @@ -537,9 +542,9 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.0.2.tgz" }, "map-obj": { - "version": "1.0.0", + "version": "1.0.1", "from": "map-obj@>=1.0.0 <2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.0.tgz" + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz" } } }, @@ -569,6 +574,11 @@ } } }, + "resolve": { + "version": "1.1.6", + "from": "resolve@>=1.1.6 <2.0.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.6.tgz" + }, "shebang-regex": { "version": "1.0.0", "from": "shebang-regex@>=1.0.0 <2.0.0", @@ -634,54 +644,54 @@ }, "babel-loader": { "version": "5.0.0", - "from": "babel-loader@>=5.0.0 <6.0.0", + "from": "https://registry.npmjs.org/babel-loader/-/babel-loader-5.0.0.tgz", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-5.0.0.tgz" }, "body-parser": { "version": "1.12.3", - "from": "body-parser@>=1.12.3 <2.0.0", + "from": "https://registry.npmjs.org/body-parser/-/body-parser-1.12.3.tgz", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.12.3.tgz", "dependencies": { "bytes": { "version": "1.0.0", - "from": "bytes@1.0.0", + "from": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz" }, "content-type": { "version": "1.0.1", - "from": "content-type@>=1.0.1 <1.1.0", + "from": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.1.tgz" }, "debug": { "version": "2.1.3", - "from": "debug@>=2.1.3 <2.2.0", + "from": "https://registry.npmjs.org/debug/-/debug-2.1.3.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.3.tgz", "dependencies": { "ms": { "version": "0.7.0", - "from": "ms@0.7.0", + "from": "https://registry.npmjs.org/ms/-/ms-0.7.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.0.tgz" } } }, "depd": { "version": "1.0.1", - "from": "depd@>=1.0.1 <1.1.0", + "from": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-1.0.1.tgz" }, "iconv-lite": { "version": "0.4.8", - "from": "iconv-lite@0.4.8", + "from": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.8.tgz", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.8.tgz" }, "on-finished": { "version": "2.2.1", - "from": "on-finished@>=2.2.0 <2.3.0", + "from": "https://registry.npmjs.org/on-finished/-/on-finished-2.2.1.tgz", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.2.1.tgz", "dependencies": { "ee-first": { "version": "1.1.0", - "from": "ee-first@1.1.0", + "from": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.0.tgz" } } @@ -693,27 +703,27 @@ }, "raw-body": { "version": "1.3.4", - "from": "raw-body@1.3.4", + "from": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.4.tgz", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.3.4.tgz" }, "type-is": { "version": "1.6.1", - "from": "type-is@>=1.6.1 <1.7.0", + "from": "https://registry.npmjs.org/type-is/-/type-is-1.6.1.tgz", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.1.tgz", "dependencies": { "media-typer": { "version": "0.3.0", - "from": "media-typer@0.3.0", + "from": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz" }, "mime-types": { "version": "2.0.10", - "from": "mime-types@>=2.0.10 <2.1.0", + "from": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.10.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.10.tgz", "dependencies": { "mime-db": { "version": "1.8.0", - "from": "mime-db@>=1.8.0 <1.9.0", + "from": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.8.0.tgz" } } @@ -724,22 +734,22 @@ }, "es5-shim": { "version": "4.1.1", - "from": "es5-shim@>=4.1.1 <5.0.0", + "from": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.1.1.tgz", "resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.1.1.tgz" }, "imports-loader": { "version": "0.6.3", - "from": "imports-loader@>=0.6.3 <0.7.0", + "from": "https://registry.npmjs.org/imports-loader/-/imports-loader-0.6.3.tgz", "resolved": "https://registry.npmjs.org/imports-loader/-/imports-loader-0.6.3.tgz", "dependencies": { "source-map": { "version": "0.1.43", - "from": "source-map@>=0.1.0 <0.2.0", + "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "amdefine@>=0.0.4", + "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } @@ -747,70 +757,70 @@ } }, "jquery": { - "version": "2.1.3", - "from": "jquery@>=2.1.3 <3.0.0", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.1.3.tgz" + "version": "2.1.4", + "from": "jquery@2.1.4", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.1.4.tgz" }, "loader-utils": { "version": "0.2.7", - "from": "loader-utils@>=0.2.7 <0.3.0", + "from": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.7.tgz", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.7.tgz", "dependencies": { "json5": { "version": "0.1.0", - "from": "json5@>=0.1.0 <0.2.0", + "from": "https://registry.npmjs.org/json5/-/json5-0.1.0.tgz", "resolved": "https://registry.npmjs.org/json5/-/json5-0.1.0.tgz" }, "big.js": { "version": "2.5.1", - "from": "big.js@>=2.5.1 <2.6.0", + "from": "https://registry.npmjs.org/big.js/-/big.js-2.5.1.tgz", "resolved": "https://registry.npmjs.org/big.js/-/big.js-2.5.1.tgz" } } }, "marked": { "version": "0.3.3", - "from": "marked@>=0.3.3 <0.4.0", + "from": "https://registry.npmjs.org/marked/-/marked-0.3.3.tgz", "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.3.tgz" }, "react": { "version": "0.13.2", - "from": "react@>=0.13.2 <0.14.0", + "from": "https://registry.npmjs.org/react/-/react-0.13.2.tgz", "resolved": "https://registry.npmjs.org/react/-/react-0.13.2.tgz", "dependencies": { "envify": { "version": "3.4.0", - "from": "envify@>=3.0.0 <4.0.0", + "from": "https://registry.npmjs.org/envify/-/envify-3.4.0.tgz", "resolved": "https://registry.npmjs.org/envify/-/envify-3.4.0.tgz", "dependencies": { "through": { "version": "2.3.7", - "from": "through@>=2.3.4 <2.4.0", + "from": "https://registry.npmjs.org/through/-/through-2.3.7.tgz", "resolved": "https://registry.npmjs.org/through/-/through-2.3.7.tgz" }, "jstransform": { "version": "10.1.0", - "from": "jstransform@>=10.0.1 <11.0.0", + "from": "https://registry.npmjs.org/jstransform/-/jstransform-10.1.0.tgz", "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-10.1.0.tgz", "dependencies": { "base62": { "version": "0.1.1", - "from": "base62@0.1.1", + "from": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz", "resolved": "https://registry.npmjs.org/base62/-/base62-0.1.1.tgz" }, "esprima-fb": { "version": "13001.1001.0-dev-harmony-fb", - "from": "esprima-fb@13001.1001.0-dev-harmony-fb", + "from": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-13001.1001.0-dev-harmony-fb.tgz", "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-13001.1001.0-dev-harmony-fb.tgz" }, "source-map": { "version": "0.1.31", - "from": "source-map@0.1.31", + "from": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.31.tgz", "dependencies": { "amdefine": { "version": "0.1.0", - "from": "amdefine@>=0.0.4", + "from": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-0.1.0.tgz" } } @@ -822,33 +832,33 @@ } }, "react-bootstrap": { - "version": "0.21.0", - "from": "react-bootstrap@>=0.21.0 <0.22.0", - "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.21.0.tgz", + "version": "0.21.2", + "from": "react-bootstrap@0.21.2", + "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.21.2.tgz", "dependencies": { "classnames": { - "version": "1.2.1", + "version": "1.2.2", "from": "classnames@>=1.1.4 <2.0.0", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-1.2.1.tgz" + "resolved": "https://registry.npmjs.org/classnames/-/classnames-1.2.2.tgz" } } }, "sleep": { "version": "2.0.0", - "from": "sleep@>=2.0.0 <3.0.0", + "from": "sleep@2.0.0", "resolved": "https://registry.npmjs.org/sleep/-/sleep-2.0.0.tgz", "dependencies": { "nan": { - "version": "1.7.0", + "version": "1.8.4", "from": "nan@*", - "resolved": "https://registry.npmjs.org/nan/-/nan-1.7.0.tgz" + "resolved": "https://registry.npmjs.org/nan/-/nan-1.8.4.tgz" } } }, "webpack": { - "version": "1.8.9", - "from": "webpack@>=1.8.9 <2.0.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.8.9.tgz", + "version": "1.8.11", + "from": "webpack@1.8.11", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-1.8.11.tgz", "dependencies": { "async": { "version": "0.9.0", @@ -1041,7 +1051,7 @@ }, "readable-stream": { "version": "1.1.13", - "from": "readable-stream@>=1.1.9 <1.2.0", + "from": "readable-stream@>=1.1.13 <2.0.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz", "dependencies": { "core-util-is": { @@ -1145,7 +1155,7 @@ }, "supports-color": { "version": "1.3.1", - "from": "supports-color@>=1.3.0 <2.0.0", + "from": "supports-color@>=1.2.0 <2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz" }, "tapable": { @@ -1210,9 +1220,9 @@ } }, "watchpack": { - "version": "0.2.4", + "version": "0.2.5", "from": "watchpack@>=0.2.1 <0.3.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.4.tgz", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-0.2.5.tgz", "dependencies": { "chokidar": { "version": "1.0.1", @@ -1294,7 +1304,7 @@ }, "debug": { "version": "2.1.3", - "from": "debug@>=2.1.3 <3.0.0", + "from": "debug@>=2.1.1 <3.0.0", "resolved": "https://registry.npmjs.org/debug/-/debug-2.1.3.tgz", "dependencies": { "ms": { diff --git a/client/package.json b/client/package.json index 72c38ec0..07fe67af 100644 --- a/client/package.json +++ b/client/package.json @@ -4,7 +4,7 @@ "description": "Code from the React Webpack tutorial.", "main": "server.js", "engines": { - "node": "0.10.32" + "node": "0.12.2" }, "repository": { "type": "git", @@ -23,19 +23,19 @@ }, "homepage": "https://github.com/justin808/react-webpack-rails-tutorial", "dependencies": { - "alt": "^0.15.6", - "babel-core": "^5.1.13", + "alt": "^0.16.1", + "babel-core": "^5.2.6", "babel-loader": "^5.0.0", "body-parser": "^1.12.3", "es5-shim": "^4.1.1", "imports-loader": "^0.6.3", - "jquery": "^2.1.3", + "jquery": "^2.1.4", "loader-utils": "^0.2.7", "marked": "^0.3.3", "react": "^0.13.2", - "react-bootstrap": "^0.21.0", + "react-bootstrap": "^0.21.2", "sleep": "^2.0.0", - "webpack": "^1.8.9" + "webpack": "^1.8.11" }, "devDependencies": { "babel-eslint": "^3.0.1", @@ -49,12 +49,12 @@ "express": "^4.12.3", "file-loader": "^0.8.1", "gulp": "^3.8.11", - "gulp-eslint": "^0.9.0", - "jscs": "^1.12.0", + "gulp-eslint": "^0.11.1", + "jscs": "^1.13.1", "node-sass": "^2.1.1", - "react-hot-loader": "^1.2.5", + "react-hot-loader": "^1.2.6", "sass-loader": "^0.6.0", - "style-loader": "^0.12.0", + "style-loader": "^0.12.1", "url-loader": "^0.5.5", "webpack-dev-server": "^1.8.2" }, diff --git a/client/server.js b/client/server.js index 2944b73d..d0b95802 100644 --- a/client/server.js +++ b/client/server.js @@ -1,4 +1,4 @@ -'use strict'; +/*eslint-disable no-console, func-names, no-var */ var bodyParser = require('body-parser'); var webpack = require('webpack'); var WebpackDevServer = require('webpack-dev-server'); diff --git a/client/tests.webpack.js b/client/tests.webpack.js index 132654fa..5e9765c0 100644 --- a/client/tests.webpack.js +++ b/client/tests.webpack.js @@ -1,3 +1,2 @@ -'use strict'; -var context = require.context('./modules', true, /-test\.js$/); +const context = require.context('./modules', true, /-test\.js$/); context.keys().forEach(context); diff --git a/client/webpack.common.config.js b/client/webpack.common.config.js index 5629e584..2b532144 100644 --- a/client/webpack.common.config.js +++ b/client/webpack.common.config.js @@ -1,8 +1,6 @@ // Common webpack configuration used by webpack.hot.config and webpack.rails.config. -'use strict'; - -var path = require('path'); +const path = require('path'); module.exports = { diff --git a/client/webpack.hot.config.js b/client/webpack.hot.config.js index 9e4a2c87..ef4f80b7 100644 --- a/client/webpack.hot.config.js +++ b/client/webpack.hot.config.js @@ -1,11 +1,9 @@ // Run like this: // cd client && node server.js -'use strict'; - -var path = require('path'); -var config = require('./webpack.common.config'); -var webpack = require('webpack'); +const path = require('path'); +const config = require('./webpack.common.config'); +const webpack = require('webpack'); // We're using the bootstrap-sass loader. // See: https://github.com/justin808/bootstrap-sass-loader diff --git a/client/webpack.rails.config.js b/client/webpack.rails.config.js index bbe175ce..de4c32e1 100644 --- a/client/webpack.rails.config.js +++ b/client/webpack.rails.config.js @@ -4,9 +4,7 @@ // NOTE: All style sheets handled by the asset pipeline in rails -'use strict'; - -var config = require('./webpack.common.config'); +const config = require('./webpack.common.config'); config.output = { filename: 'client-bundle.js', @@ -33,10 +31,10 @@ config.module.loaders.push( module.exports = config; // Next line is Heroku specific. You'll have BUILDPACK_URL defined for your Heroku install. -var devBuild = (typeof process.env.BUILDPACK_URL) === 'undefined'; +const devBuild = (typeof process.env.BUILDPACK_URL) === 'undefined'; if (devBuild) { - console.log('Webpack dev build for Rails'); + console.log('Webpack dev build for Rails'); // eslint-disable-line no-console module.exports.devtool = 'eval-source-map'; } else { - console.log('Webpack production build for Rails'); + console.log('Webpack production build for Rails'); // eslint-disable-line no-console } diff --git a/client/webpack.test-hot.config.js b/client/webpack.test-hot.config.js deleted file mode 100644 index 3b73e78b..00000000 --- a/client/webpack.test-hot.config.js +++ /dev/null @@ -1,39 +0,0 @@ -// File helpful for debugging issues with dependencies only used by the hot reload server -// node-debug webpack --config webpack.test-hot.config.js - -'use strict'; -var path = require('path'); -var config = require('./webpack.common.config'); - -// We're using the bootstrap-sass loader. -// See: https://github.com/justin808/bootstrap-sass-loader -config.entry.push('./scripts/webpack_only', - - // custom bootstrap - 'bootstrap-sass!./bootstrap-sass.config.js'); -config.output = { - - // this file is served directly by webpack - filename: 'express-bundle.js', - path: __dirname -}; -config.devtool = 'eval-source-map'; - -// All the styling loaders only apply to hot-reload, not rails -config.module.loaders.push( - {test: /\.jsx$/, loaders: ['react-hot', 'es6', 'jsx?harmony']}, - {test: /\.css$/, loader: 'style-loader!css-loader'}, - { - test: /\.scss$/, - loader: 'style!css!sass?outputStyle=expanded&imagePath=/assets/images&includePaths[]=' + - path.resolve(__dirname, './assets/stylesheets') - }, - - // The url-loader uses DataUrls. The file-loader emits files. - {test: /\.woff$/, loader: 'url-loader?limit=10000&minetype=application/font-woff'}, - {test: /\.woff2$/, loader: 'url-loader?limit=10000&minetype=application/font-woff'}, - {test: /\.ttf$/, loader: 'file-loader'}, - {test: /\.eot$/, loader: 'file-loader'}, - {test: /\.svg$/, loader: 'file-loader'}); - -module.exports = config; diff --git a/config.ru b/config.ru index 5bc2a619..93fb28fa 100644 --- a/config.ru +++ b/config.ru @@ -1,4 +1,4 @@ # This file is used by Rack-based servers to start the application. -require ::File.expand_path('../config/environment', __FILE__) +require ::File.expand_path("../config/environment", __FILE__) run Rails.application diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake new file mode 100644 index 00000000..fe4f84a8 --- /dev/null +++ b/lib/tasks/ci.rake @@ -0,0 +1,35 @@ +if Rails.env.development? + # See tasks/linters.rake + + task :bundle_audit do + puts "Running security audit on gems (bundle_audit)".green + Rake::Task["bundle_audit"].invoke + end + + task :security_audit do + puts "Running security audit on code (brakeman)".green + Rake::Task["brakeman:run"].invoke("tmp/brakeman-report.html") + end + + namespace :ci do + desc "Run all audits and tests" + task all: [:environment, :lint, :spec, :bundle_audit, :security_audit] do + begin + puts "PASSED".green + puts "" + rescue Exception => e + puts "#{e}" + puts "FAILED".red + puts "" + raise(e) + end + end + end + + task :ci do + Rake::Task["ci:all"].invoke + end + + task(:default).clear + task default: [:ci] +end diff --git a/lib/tasks/linters.rake b/lib/tasks/linters.rake new file mode 100644 index 00000000..8c92d808 --- /dev/null +++ b/lib/tasks/linters.rake @@ -0,0 +1,56 @@ +if %w(development test).include? Rails.env + require "rubocop/rake_task" + RuboCop::RakeTask.new + + task(:default).clear + + desc "JS Linting" + task :js_lint do + sh "cd client && bin/lint" + end + + task default: [:spec, :rubocop] +end + +if %w(development test).include? Rails.env + # require "rubocop/rake_task" + # require "slim_lint/rake_task" + require "scss_lint/rake_task" + + # This fails: https://github.com/bbatsov/rubocop/issues/1840 + # RuboCop::RakeTask.new + + desc "Run Rubocop lint as shell" + task :rubocop_lint do + puts "Running Rubocop Linters" + sh "rubocop ." + end + + # SlimLint::RakeTask.new + + SCSSLint::RakeTask.new do |t| + t.files = ["app/assets/stylesheets/", "client/assets/stylesheets/"] + end + + desc "eslint" + task :eslint_lint do + puts "Running eslint" + sh "cd client && npm run eslint . -- --ext .jsx,.js" + end + + desc "jscs" + task :jscs_lint do + puts "Running jscs" + sh "cd client && npm run jscs ." + end + + desc "JS Linting" + task js_lint: [:eslint_lint, :jscs_lint] do + puts "Running JavaScript Linters" + end + + # could add :slim_lint here + task lint: [:rubocop_lint, :js_lint, :scss_lint] do + puts "Completed All Linting" + end +end diff --git a/lib/tasks/rubocop.rake b/lib/tasks/rubocop.rake deleted file mode 100644 index ed77e520..00000000 --- a/lib/tasks/rubocop.rake +++ /dev/null @@ -1,13 +0,0 @@ -if %w(development test).include? Rails.env - require "rubocop/rake_task" - RuboCop::RakeTask.new - - task(:default).clear - - desc "JS Linting" - task :js_lint do - sh "cd client && bin/lint" - end - - task default: [:spec, :rubocop] -end diff --git a/package.json b/package.json index 52240777..b23d269b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Code from the React Webpack tutorial.", "main": "server.js", "engines": { - "node": "0.10.32" + "node": "0.12.2" }, "scripts": { "postinstall": "cd ./client && npm install", diff --git a/ruby-lint.yml b/ruby-lint.yml index 66ff7b5d..5d747b5c 100644 --- a/ruby-lint.yml +++ b/ruby-lint.yml @@ -7,10 +7,9 @@ directories: - config - spec -#ignore_paths: -# - client -# - node_modules -# - client/**/* +ignore_paths: + - client + - node_modules analysis_classes: # - argument_amount diff --git a/scripts/lint b/scripts/lint new file mode 100755 index 00000000..fc77595c --- /dev/null +++ b/scripts/lint @@ -0,0 +1,14 @@ +#!/bin/sh +echo Linting with Rubocop, ruby-lint, eslint, jsrc, and slim-lint +rubocop . + +# NOTE: Ruby-lint is experimental. Did not add value to rubocop +echo Linting with ruby-lint +ruby-lint app config spec + +echo Linting with eslint and jscs +(cd client && bin/lint) + +scss-lint client/assets/stylesheets/*.scss app/assets/stylesheets/*.scss + +echo Done linting with Rubocop, ruby-lint, eslint, jsrc, and slim-lint