├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmrc ├── .nvmrc ├── LICENSE ├── README.md ├── appveyor.yml ├── bower.json ├── circle.yml ├── cli.js ├── nightwatch.json ├── package-scripts.js ├── package.json ├── src ├── ReactComponentTemplate.js ├── example │ ├── App │ │ ├── App.css │ │ └── index.js │ └── Example.js └── index.js ├── test-e2e └── Smoketest.js ├── test ├── ReactComponentTemplate-test.js ├── example │ └── App-test.js └── index.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "es2015", 4 | "react" 5 | ], 6 | "plugins": [ 7 | "transform-object-rest-spread", 8 | "transform-class-properties" 9 | ], 10 | "env": { 11 | "production": { 12 | "plugins": [ 13 | [ 14 | "transform-react-remove-prop-types", 15 | { 16 | "mode": "remove", 17 | "removeImport": true 18 | } 19 | ] 20 | ] 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /example/ 2 | /lib/ 3 | /node_modules/ 4 | /build/ 5 | /reports/ 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "es6": true 6 | }, 7 | 8 | "parser": "babel-eslint", 9 | 10 | "plugins": ["react"], 11 | 12 | "ecmaFeatures": { 13 | "arrowFunctions": true, 14 | "binaryLiterals": true, 15 | "blockBindings": true, 16 | "classes": true, 17 | "defaultParams": true, 18 | "destructuring": true, 19 | "forOf": true, 20 | "generators": true, 21 | "modules": true, 22 | "objectLiteralComputedProperties": true, 23 | "objectLiteralDuplicateProperties": true, 24 | "objectLiteralShorthandMethods": true, 25 | "objectLiteralShorthandProperties": true, 26 | "octalLiterals": true, 27 | "regexUFlag": true, 28 | "regexYFlag": true, 29 | "spread": true, 30 | "superInFunctions": true, 31 | "templateStrings": true, 32 | "unicodeCodePointEscapes": true, 33 | "globalReturn": true, 34 | "jsx": true 35 | }, 36 | 37 | "rules": { 38 | // 39 | //Possible Errors 40 | // 41 | // The following rules point out areas where you might have made mistakes. 42 | // 43 | "comma-dangle": 2, // disallow or enforce trailing commas (recommended) 44 | "no-cond-assign": 2, // disallow assignment in conditional expressions (recommended) 45 | "no-console": 2, // disallow use of console (recommended) 46 | "no-constant-condition": 2, // disallow use of constant expressions in conditions (recommended) 47 | "no-control-regex": 2, // disallow control characters in regular expressions (recommended) 48 | "no-debugger": 2, // disallow use of debugger (recommended) 49 | "no-dupe-args": 2, // disallow duplicate arguments in functions (recommended) 50 | "no-dupe-keys": 2, // disallow duplicate keys when creating object literals (recommended) 51 | "no-duplicate-case": 2, // disallow a duplicate case label. (recommended) 52 | "no-empty": 2, // disallow empty block statements (recommended) 53 | "no-empty-character-class": 2, // disallow the use of empty character classes in regular expressions (recommended) 54 | "no-ex-assign": 2, // disallow assigning to the exception in a catch block (recommended) 55 | "no-extra-boolean-cast": 2, // disallow double-negation boolean casts in a boolean context (recommended) 56 | "no-extra-parens": 2, // disallow unnecessary parentheses 57 | "no-extra-semi": 2, // disallow unnecessary semicolons (recommended) (fixable) 58 | "no-func-assign": 2, // disallow overwriting functions written as function declarations (recommended) 59 | "no-inner-declarations": 2, // disallow function or variable declarations in nested blocks (recommended) 60 | "no-invalid-regexp": 2, // disallow invalid regular expression strings in the RegExp constructor (recommended) 61 | "no-irregular-whitespace": 2, // disallow irregular whitespace outside of strings and comments (recommended) 62 | "no-negated-in-lhs": 2, // disallow negation of the left operand of an in expression (recommended) 63 | "no-obj-calls": 2, // disallow the use of object properties of the global object (Math and JSON) as functions (recommended) 64 | "no-regex-spaces": 2, // disallow multiple spaces in a regular expression literal (recommended) 65 | "no-sparse-arrays": 2, // disallow sparse arrays (recommended) 66 | "no-unexpected-multiline": 2, // Avoid code that looks like two expressions but is actually one (recommended) 67 | "no-unreachable": 2, // disallow unreachable statements after a return, throw, continue, or break statement (recommended) 68 | "use-isnan": 2, // disallow comparisons with the value NaN (recommended) 69 | "valid-jsdoc": 2, // Ensure JSDoc comments are valid 70 | "valid-typeof": 2, // Ensure that the results of typeof are compared against a valid string (recommended) 71 | 72 | 73 | // 74 | // Best Practices 75 | // 76 | // These are rules designed to prevent you from making mistakes. 77 | // They either prescribe a better way of doing something or help you avoid footguns. 78 | // 79 | "accessor-pairs": 2, // Enforces getter/setter pairs in objects 80 | "array-callback-return": 2, // Enforces return statements in callbacks of array's methods 81 | "block-scoped-var": 2, // treat var statements as if they were block scoped 82 | "complexity": 0, // specify the maximum cyclomatic complexity allowed in a program 83 | "consistent-return": 2, // require return statements to either always or never specify values 84 | "curly": 2, // specify curly brace conventions for all control statements 85 | "default-case": 2, // require default case in switch statements 86 | "dot-location": [2, "property"], // enforces consistent newlines before or after dots 87 | "dot-notation": 2, // encourages use of dot notation whenever possible 88 | "eqeqeq": 2, // require the use of === and !== 89 | "guard-for-in": 2, // make sure for-in loops have an if statement 90 | "no-alert": 2, // disallow the use of alert, confirm, and prompt 91 | "no-caller": 2, // disallow use of arguments.caller or arguments.callee 92 | "no-case-declarations": 2, // disallow lexical declarations in case clauses (recommended) 93 | "no-div-regex": 2, // disallow division operators explicitly at beginning of regular expression 94 | "no-else-return": 2, // disallow else after a return in an if 95 | "no-empty-function": 2, // disallow use of empty functions 96 | "no-empty-pattern": 2, // disallow use of empty destructuring patterns (recommended) 97 | "no-eq-null": 2, // disallow comparisons to null without a type-checking operator 98 | "no-eval": 2, // disallow use of eval() 99 | "no-extend-native": 2, // disallow adding to native types 100 | "no-extra-bind": 2, // disallow unnecessary function binding 101 | "no-extra-label": 2, // disallow unnecessary labels 102 | "no-fallthrough": 2, // disallow fallthrough of case statements (recommended) 103 | "no-floating-decimal": 2, // disallow the use of leading or trailing decimal points in numeric literals 104 | "no-implicit-coercion": 2, // disallow the type conversions with shorter notations 105 | "no-implicit-globals": 2, // disallow var and named functions in global scope 106 | "no-implied-eval": 2, // disallow use of eval()-like methods 107 | "no-invalid-this": 2, // disallow this keywords outside of classes or class-like objects 108 | "no-iterator": 2, // disallow usage of __iterator__ property 109 | "no-labels": 2, // disallow use of labeled statements 110 | "no-lone-blocks": 2, // disallow unnecessary nested blocks 111 | "no-loop-func": 2, // disallow creation of functions within loops 112 | "no-magic-numbers": 0, // disallow the use of magic numbers 113 | "no-multi-spaces": 2, // disallow use of multiple spaces (fixable) 114 | "no-multi-str": 2, // disallow use of multiline strings 115 | "no-native-reassign": 2, // disallow reassignments of native objects 116 | "no-new": 2, // disallow use of the new operator when not part of an assignment or comparison 117 | "no-new-func": 2, // disallow use of new operator for Function object 118 | "no-new-wrappers": 2, // disallows creating new instances of String,Number, and Boolean 119 | "no-octal": 2, // disallow use of octal literals (recommended) 120 | "no-octal-escape": 2, // disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251"; 121 | "no-param-reassign": 2, // disallow reassignment of function parameters 122 | "no-process-env": 0, // disallow use of process.env 123 | "no-proto": 2, // disallow usage of __proto__ property 124 | "no-redeclare": 2, // disallow declaring the same variable more than once (recommended) 125 | "no-return-assign": 2, // disallow use of assignment in return statement 126 | "no-script-url": 2, // disallow use of javascript: urls. 127 | "no-self-assign": 2, // disallow assignments where both sides are exactly the same (recommended) 128 | "no-self-compare": 2, // disallow comparisons where both sides are exactly the same 129 | "no-sequences": 2, // disallow use of the comma operator 130 | "no-throw-literal": 2, // restrict what can be thrown as an exception 131 | "no-unmodified-loop-condition": 2, // disallow unmodified conditions of loops 132 | "no-unused-expressions": 2, // disallow usage of expressions in statement position 133 | "no-unused-labels": 2, // disallow unused labels (recommended) 134 | "no-useless-call": 2, // disallow unnecessary .call() and .apply() 135 | "no-useless-concat": 2, // disallow unnecessary concatenation of literals or template literals 136 | "no-void": 2, // disallow use of the void operator 137 | "no-warning-comments": 0, // disallow usage of configurable warning terms in comments - e.g. TODO or FIXME 138 | "no-with": 2, // disallow use of the with statement 139 | "radix": 2, // require use of the second argument for parseInt() 140 | "vars-on-top": 2, // require declaration of all vars at the top of their containing scope 141 | "wrap-iife": 2, // require immediate function invocation to be wrapped in parentheses 142 | "yoda": 2, // require or disallow Yoda conditions 143 | 144 | 145 | // 146 | // Strict Mode 147 | // 148 | // These rules relate to using strict mode. 149 | // 150 | "strict": 0, // controls location of Use Strict Directives. 0: required by babel-eslint 151 | 152 | 153 | // 154 | // Variables 155 | // 156 | // These rules have to do with variable declarations. 157 | // 158 | "init-declarations": 0, // enforce or disallow variable initializations at definition 159 | "no-catch-shadow": 2, // disallow the catch clause parameter name being the same as a variable in the outer scope 160 | "no-delete-var": 2, // disallow deletion of variables (recommended) 161 | "no-label-var": 2, // disallow labels that share a name with a variable 162 | "no-restricted-globals": 0, // restrict usage of specified global variables 163 | "no-shadow": 2, // disallow declaration of variables already declared in the outer scope 164 | "no-shadow-restricted-names": 2, // disallow shadowing of names such as arguments 165 | "no-undef": 2, // disallow use of undeclared variables unless mentioned in a /*global */ block (recommended) 166 | "no-undef-init": 2, // disallow use of undefined when initializing variables 167 | "no-undefined": 2, // disallow use of undefined variable 168 | "no-unused-vars": [2, {"argsIgnorePattern": "^_", "varsIgnorePattern": "^_"}], // disallow declaration of variables that are not used in the code (recommended) 169 | "no-use-before-define": 2, // disallow use of variables before they are defined 170 | 171 | // 172 | // Node.js and CommonJS 173 | // 174 | // These rules are specific to JavaScript running on Node.js or using CommonJS in the browser. 175 | // 176 | "callback-return": 2, // enforce return after a callback 177 | "global-require": 0, // enforce require() on top-level module scope 178 | "handle-callback-err": 2, // enforce error handling in callbacks 179 | "no-mixed-requires": 2, // disallow mixing regular variable and require declarations 180 | "no-new-require": 2, // disallow use of new operator with the require function 181 | "no-path-concat": 2, // disallow string concatenation with __dirname and __filename 182 | "no-process-exit": 0, // disallow process.exit() 183 | "no-restricted-imports": 0, // restrict usage of specified node imports 184 | "no-restricted-modules": 0, // restrict usage of specified node modules 185 | "no-sync": 2, // disallow use of synchronous methods 186 | // 187 | // Stylistic Issues 188 | // 189 | // These rules are purely matters of style and are quite subjective. 190 | // 191 | "array-bracket-spacing": [2, "never"], // enforce spacing inside array brackets (fixable) 192 | "block-spacing": [2, "always"], // disallow or enforce spaces inside of single line blocks (fixable) 193 | "brace-style": 2, // enforce one true brace style 194 | "camelcase": 2, // require camel case names 195 | "comma-spacing": [2, {"before": false, "after": true}], // enforce spacing before and after comma (fixable) 196 | "comma-style": [2, "last"], // enforce one true comma style 197 | "computed-property-spacing": [2, "never"], // require or disallow padding inside computed properties (fixable) 198 | "consistent-this": [2, "_this"], // enforce consistent naming when capturing the current execution context 199 | "eol-last": 2, // enforce newline at the end of file, with no multiple empty lines (fixable) 200 | "func-names": 0, // require function expressions to have a name 201 | "func-style": 0, // enforce use of function declarations or expressions 202 | "id-blacklist": 0, // blacklist certain identifiers to prevent them being used 203 | "id-length": 0, // this option enforces minimum and maximum identifier lengths (variable names, property names etc.) 204 | "id-match": 0, // require identifiers to match the provided regular expression 205 | "indent": [2, 2, {"SwitchCase": 1}], // specify tab or space width for your code (fixable) 206 | "jsx-quotes": [2, "prefer-double"], // specify whether double or single quotes should be used in JSX attributes (fixable) 207 | "key-spacing": [2, {"beforeColon": false, "afterColon": true}], // enforce spacing between keys and values in object literal properties 208 | "keyword-spacing": [2, {"before": true, "after": true}], // enforce spacing before and after keywords (fixable) 209 | "linebreak-style": [2, "unix"], // disallow mixed 'LF' and 'CRLF' as linebreaks 210 | "lines-around-comment": [2, {"beforeBlockComment": true, "afterBlockComment": false, "afterLineComment": false}], // enforce empty lines around comments 211 | "max-depth": [2, 3], // specify the maximum depth that blocks can be nested 212 | "max-len": [2, 100, 2], // specify the maximum length of a line in your program 213 | "max-nested-callbacks": [2, 3], // specify the maximum depth callbacks can be nested 214 | "max-params": [2, 5], // limits the number of parameters that can be used in the function declaration 215 | "max-statements": 0, // specify the maximum number of statement allowed in a function 216 | "new-cap": [2, {"newIsCap": true, "capIsNew": false}], // require a capital letter for constructors 217 | "new-parens": 2, // disallow the omission of parentheses when invoking a constructor with no arguments 218 | "newline-after-var": [2, "always"], // require or disallow an empty newline after variable declarations 219 | "newline-per-chained-call": 0, // enforce newline after each call when chaining the calls 220 | "no-array-constructor": 2, // disallow use of the Array constructor 221 | "no-bitwise": 2, // disallow use of bitwise operators 222 | "no-continue": 2, // disallow use of the continue statement 223 | "no-inline-comments": 2, // disallow comments inline after code 224 | "no-lonely-if": 2, // disallow if as the only statement in an else block 225 | "no-mixed-spaces-and-tabs": 2, // disallow mixed spaces and tabs for indentation (recommended) 226 | "no-multiple-empty-lines": [2, {"max": 2}], // disallow multiple empty lines 227 | "no-negated-condition": 2, // disallow negated conditions 228 | "no-nested-ternary": 2, // disallow nested ternary expressions 229 | "no-new-object": 2, // disallow the use of the Object constructor 230 | "no-plusplus": 2, // disallow use of unary operators, ++ and -- 231 | "no-restricted-syntax": [2, "WithStatement"], // disallow use of certain syntax in code 232 | "no-spaced-func": 2, // disallow space between function identifier and application (fixable) 233 | "no-ternary": 0, // disallow the use of ternary operators 234 | "no-trailing-spaces": 2, // disallow trailing whitespace at the end of lines (fixable) 235 | "no-underscore-dangle": 2, // disallow dangling underscores in identifiers 236 | "no-unneeded-ternary": 2, // disallow the use of ternary operators when a simpler alternative exists 237 | "no-whitespace-before-property": 2, // disallow whitespace before properties 238 | "object-curly-spacing": [2, "never"], // require or disallow padding inside curly braces (fixable) 239 | "one-var": [2, "never"], // require or disallow one variable declaration per function 240 | "one-var-declaration-per-line": 2, // require or disallow an newline around variable declarations 241 | "operator-assignment": [2, "never"], // require assignment operator shorthand where possible or prohibit it entirely 242 | "operator-linebreak": [2, "after"], // enforce operators to be placed before or after line breaks 243 | "padded-blocks": [2, "never"], // enforce padding within blocks 244 | "quote-props": [2, "as-needed"], // require quotes around object literal property names 245 | "quotes": [2, "single"], // specify whether backticks, double or single quotes should be used (fixable) 246 | "require-jsdoc": 0, // Require JSDoc comment 247 | "semi": [2, "always"], // require or disallow use of semicolons instead of ASI (fixable) 248 | "semi-spacing": [2, {"before": false, "after": true}], // enforce spacing before and after semicolons (fixable) 249 | "sort-imports": 0, // sort import declarations within module 250 | "sort-vars": 0, // sort variables within the same declaration block 251 | "space-before-blocks": [2, "always"], // require or disallow a space before blocks (fixable) 252 | "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}], // require or disallow a space before function opening parenthesis (fixable) 253 | "space-in-parens": [2, "never"], // require or disallow spaces inside parentheses (fixable) 254 | "space-infix-ops": 2, // require spaces around operators (fixable) 255 | "space-unary-ops": [2, {"words": true, "nonwords": false}], // require or disallow spaces before/after unary operators (fixable) 256 | "spaced-comment": [2, "always"], // require or disallow a space immediately following the // or /* in a comment 257 | "wrap-regex": 0, // require regex literals to be wrapped in parentheses 258 | // 259 | // ECMAScript 6 260 | // 261 | // These rules are only relevant to ES6 environments and are off by default. 262 | // 263 | "arrow-body-style": [2, "as-needed"], // require braces in arrow function body 264 | "arrow-parens": [2, "as-needed"], // require parens in arrow function arguments 265 | "arrow-spacing": 2, // require space before/after arrow function's arrow (fixable) 266 | "constructor-super": 2, // verify calls of super() in constructors (recommended) 267 | "generator-star-spacing": [2, "before"], // enforce spacing around the * in generator functions (fixable) 268 | "no-class-assign": 2, // disallow modifying variables of class declarations (recommended) 269 | "no-confusing-arrow": 0, // disallow arrow functions where they could be confused with comparisons 270 | "no-const-assign": 2, // disallow modifying variables that are declared using const (recommended) 271 | "no-dupe-class-members": 2, // disallow duplicate name in class members (recommended) 272 | "no-new-symbol": 2, // disallow use of the new operator with the Symbol object (recommended) 273 | "no-this-before-super": 2, // disallow use of this/super before calling super() in constructors (recommended) 274 | "no-useless-constructor": 2, // disallow unnecessary constructor 275 | "no-var": 2, // require let or const instead of var 276 | "object-shorthand": 2, // require method and property shorthand syntax for object literals 277 | "prefer-arrow-callback": 2, // suggest using arrow functions as callbacks 278 | "prefer-const": 2, // suggest using const declaration for variables that are never modified after declared 279 | "prefer-reflect": 0, // suggest using Reflect methods where applicable 280 | "prefer-rest-params": 2, // suggest using the rest parameters instead of arguments 281 | "prefer-spread": 2, // suggest using the spread operator instead of .apply() 282 | "prefer-template": 2, // suggest using template literals instead of strings concatenation 283 | "require-yield": 2, // disallow generator functions that do not have yield 284 | "template-curly-spacing": 2, // enforce spacing around embedded expressions of template strings (fixable) 285 | "yield-star-spacing": 2, // enforce spacing around the * in yield* expressions (fixable) 286 | // 287 | // eslint-plugin-react 288 | // 289 | // List of supported rules 290 | // 291 | "react/display-name": 0, // Prevent missing displayName in a React component definition 292 | "react/forbid-prop-types": [2, {"forbid": ["any", "array"]}], // Forbid certain propTypes 293 | "react/no-danger": 2, // Prevent usage of dangerous JSX properties 294 | "react/no-deprecated": 2, // Prevent usage of deprecated methods 295 | "react/no-did-mount-set-state": 2, // Prevent usage of setState in componentDidMount 296 | "react/no-did-update-set-state": 2, // Prevent usage of setState in componentDidUpdate 297 | "react/no-direct-mutation-state": 2, // Prevent direct mutation of this.state 298 | "react/no-is-mounted": 2, // Prevent usage of isMounted 299 | "react/no-multi-comp": 0, // Prevent multiple component definition per file 300 | "react/no-set-state": 0, // Prevent usage of setState 301 | "react/no-string-refs": 2, // Prevent using string references in ref attribute. 302 | "react/no-unknown-property": 2, // Prevent usage of unknown DOM property (fixable) 303 | "react/prefer-es6-class": 0, // Enforce ES5 or ES6 class for React Components 304 | "react/prefer-stateless-function": 0, // Enforce stateless React Components to be written as a pure function 305 | "react/prop-types": 2, // Prevent missing props validation in a React component definition 306 | "react/react-in-jsx-scope": 2, // Prevent missing React when using JSX 307 | "react/self-closing-comp": 2, // Prevent extra closing tags for components without children 308 | "react/sort-comp": 2, // Enforce component methods order 309 | // 310 | // JSX-specific rules 311 | // 312 | "react/jsx-boolean-value": [2, "always"], // Enforce boolean attributes notation in JSX (fixable) 313 | "react/jsx-closing-bracket-location": [2, {"selfClosing": "after-props", "nonEmpty": "after-props"}], // Validate closing bracket location in JSX 314 | "react/jsx-curly-spacing": [2, "never"], // Enforce or disallow spaces inside of curly braces in JSX attributes (fixable) 315 | "react/jsx-equals-spacing": 2, // Enforce or disallow spaces around equal signs in JSX attributes 316 | "react/jsx-handler-names": [2, {"eventHandlerPrefix": "on", "eventHandlerPropPrefix": "on"}], // Enforce event handler naming conventions in JSX 317 | "react/jsx-indent-props": [2, 2], // Validate props indentation in JSX 318 | "react/jsx-indent": [2, 2], // Validate JSX indentation 319 | "react/jsx-key": 2, // Validate JSX has key prop when in array or iterator 320 | "react/jsx-max-props-per-line": [2, {"maximum": 4}], // Limit maximum of props on a single line in JSX 321 | "react/jsx-no-bind": [2, {"allowArrowFunctions": true}], // Prevent usage of .bind() and arrow functions in JSX props 322 | "react/jsx-no-duplicate-props": [2, {"ignoreCase": true}], // Prevent duplicate props in JSX 323 | "react/jsx-no-literals": 0, // Prevent usage of unwrapped JSX strings 324 | "react/jsx-no-undef": 2, // Disallow undeclared variables in JSX 325 | "react/jsx-pascal-case": 2, // Enforce PascalCase for user-defined JSX components 326 | "react/jsx-sort-prop-types": 0, // Enforce propTypes declarations alphabetical sorting 327 | "react/jsx-sort-props": 2, // Enforce props alphabetical sorting 328 | "react/jsx-space-before-closing": [2, "always"], // Validate spacing before closing bracket in JSX (fixable) 329 | "react/jsx-uses-react": 2, // Prevent React to be incorrectly marked as unused 330 | "react/jsx-uses-vars": 2, // Prevent variables used in JSX to be incorrectly marked as unused 331 | "react/jsx-wrap-multilines": 2 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | /build/ 11 | 12 | # Dependency directory 13 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 14 | /node_modules/ 15 | 16 | /lib/ 17 | /example/ 18 | /.coveralls.yml 19 | /reports/ 20 | 21 | /.eslintcache 22 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | save-exact = true 2 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Nik Butenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-component-template [![npm](https://img.shields.io/npm/v/react-component-template.svg?style=flat-square)](https://www.npmjs.com/package/react-component-template) 2 | 3 | [![Discord](https://img.shields.io/badge/chat-discord-blue.svg?style=flat-square)](https://discord.gg/013tGW1IMcW6Vd1o7) 4 | 5 | [![CircleCI](https://img.shields.io/circleci/project/nkbt/react-component-template.svg?style=flat-square&label=nix-build)](https://circleci.com/gh/nkbt/react-component-template) 6 | [![AppVeyor](https://img.shields.io/appveyor/ci/nkbt/react-component-template.svg?style=flat-square&label=win-build)](https://ci.appveyor.com/project/nkbt/react-component-template) 7 | [![Coverage](https://img.shields.io/codecov/c/github/nkbt/react-component-template.svg?style=flat-square)](https://codecov.io/github/nkbt/react-component-template?branch=master) 8 | [![Dependencies](https://img.shields.io/david/nkbt/react-component-template.svg?style=flat-square)](https://david-dm.org/nkbt/react-component-template) 9 | [![Dev Dependencies](https://img.shields.io/david/dev/nkbt/react-component-template.svg?style=flat-square)](https://david-dm.org/nkbt/react-component-template#info=devDependencies) 10 | 11 | Base for React Components 12 | 13 | ## Reason 14 | 15 | Developing and publishing multiple React components requires a lot of work to keep them all at the same code, ops, best-practices level. Most of configs are often copy-pasted. If one project updated, for example, .eslintrc, other projects should follow to keep codebase consistent. Having growing number of components leads to a more diverged codebase that is exponentially harder to manage. 16 | 17 | 18 | ## Contents 19 | 20 | - React module boilerplate dependencies and scripts 21 | - .gitignore and .npmignore 22 | - CircleCI config 23 | - ESLint config, strict version of Airbnb code style guide 24 | - Empty React component 25 | - Example 26 | - Tests and coverage (Tape, Isparta) 27 | - End-to-End tests (Nightwatch, Selenium) 28 | 29 | 30 | ## Usage 31 | 32 | 1. Install 33 | 34 | ```sh 35 | npm install --save-dev react-component-template 36 | ``` 37 | 38 | 2. Set npm scripts in `package.json` and set component name 39 | 40 | ```json 41 | { 42 | "config": { 43 | "component": "ReactComponentTemplate" 44 | }, 45 | "scripts": { 46 | "start": "react-component-template", 47 | "test": "npm start test", 48 | "precommit": "npm start precommit", 49 | "prepush": "npm start prepush", 50 | "postversion": "npm start postversion", 51 | "prepublish": "npm start prepublish" 52 | } 53 | } 54 | ``` 55 | 56 | 3. Create `webpack.config.js` 57 | 58 | ```js 59 | 'use strict'; 60 | 61 | module.exports = require('react-component-template/webpack.config'); 62 | ``` 63 | 64 | 4. Create `.eslintrc` 65 | 66 | ```json 67 | { 68 | "extends": "./node_modules/react-component-template/.eslintrc" 69 | } 70 | ``` 71 | 72 | 5. Other files 73 | 74 | There is a `react-component-template` scaffold generator, install it: 75 | ```sh 76 | npm install -g cf-react-component-template 77 | ``` 78 | and answer some questions, for example: 79 | ```sh 80 | cf-react-component-template 81 | 82 | Your name: Nik Butenko 83 | Your email (will be publicly available, optional): nik@butenko.me 84 | Your GitHub public username: nkbt 85 | Package name: my-awesome-react-lib 86 | Global package name (CamelCased): MyAwesomeReactLib 87 | Package description: My awesome React library 88 | ``` 89 | 90 | ## License 91 | 92 | MIT 93 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | install: 2 | - npm install 3 | 4 | cache: 5 | - "%LOCALAPPDATA%/Yarn" 6 | - node_modules -> package.json 7 | 8 | build: off 9 | shallow_clone: true 10 | clone_depth: 1 11 | skip_branch_with_pr: true 12 | 13 | test_script: 14 | - node --version 15 | - npm --version 16 | - npm test 17 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-component-template", 3 | "version": "0.0.0", 4 | "description": "React component", 5 | "main": [ 6 | "build/react-component-template.js", 7 | "build/react-component-template.js.map", 8 | "build/react-component-template.min.js", 9 | "build/react-component-template.min.js.map" 10 | ], 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/nkbt/react-component-template.git" 14 | }, 15 | "keywords": [ 16 | "component", 17 | "react-component", 18 | "react" 19 | ], 20 | "authors": [ 21 | "Nik Butenko (http://butenko.me/)" 22 | ], 23 | "license": "MIT", 24 | "homepage": "https://github.com/nkbt/react-component-template", 25 | "dependencies": { 26 | "react": "^0.14 || ^15" 27 | }, 28 | "ignore": [ 29 | "**/.*", 30 | "node_modules", 31 | "bower_components", 32 | "test", 33 | "tests" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /circle.yml: -------------------------------------------------------------------------------- 1 | machine: 2 | node: 3 | version: 7 4 | 5 | dependencies: 6 | override: 7 | - npm install 8 | - node ./node_modules/selenium-standalone/bin/selenium-standalone install 9 | 10 | test: 11 | override: 12 | - npm start ci.lint 13 | - npm start ci.test 14 | - npm start ci.cov 15 | - npm start ci.e2e 16 | 17 | post: 18 | - npm start ci.codecov 19 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 4 | const config = require.resolve('react-component-template/package-scripts'); 5 | const ps = require.resolve('p-s/dist/bin/nps'); 6 | 7 | 8 | require('child_process') 9 | .spawn('node', [ps, '--config', config].concat(process.argv.slice(2)), { 10 | cwd: process.cwd(), 11 | env: process.env, 12 | stdio: [process.stdin, process.stdout, process.stderr] 13 | }); 14 | -------------------------------------------------------------------------------- /nightwatch.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_folders" : ["test-e2e"], 3 | "output_folder" : "reports/test-e2e", 4 | 5 | "selenium" : { 6 | "start_process" : false 7 | }, 8 | 9 | "test_workers": { 10 | "enabled": true, 11 | "workers": 8 12 | }, 13 | 14 | "test_settings" : { 15 | "default" : { 16 | "launch_url" : "http://localhost:8080", 17 | "selenium_port" : 4444, 18 | "selenium_host" : "localhost", 19 | "silent": true, 20 | "screenshots" : { 21 | "enabled" : true, 22 | "on_failure" : true, 23 | "on_error" : false, 24 | "path" : "reports/test-e2e" 25 | }, 26 | "desiredCapabilities": { 27 | "browserName": "chrome", 28 | "javascriptEnabled": true, 29 | "acceptSslCerts": true 30 | } 31 | }, 32 | 33 | "chrome" : { 34 | "desiredCapabilities": { 35 | "browserName": "chrome", 36 | "javascriptEnabled": true, 37 | "acceptSslCerts": true 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /package-scripts.js: -------------------------------------------------------------------------------- 1 | const pathTo = require('path').join.bind(null, process.cwd()); 2 | 3 | exports.scripts = { 4 | dev: 'cross-env NODE_ENV=development webpack-dev-server', 5 | 6 | ghPages: [ 7 | 'npm start -- build.ghPages', 8 | 'gh-pages --dist example' 9 | ].join(' && '), 10 | 11 | build: { 12 | default: [ 13 | `rimraf ${pathTo('lib')} ${pathTo('example')} ${pathTo('build')}`, 14 | 'npm start -- --parallel build.lib,build.ghPages,build.dist,build.min' 15 | ].join(' && '), 16 | lib: 'cross-env NODE_ENV=production' + 17 | ` babel ${pathTo('src')} --out-dir ${pathTo('lib')}` + 18 | ` --ignore ${pathTo('src', 'example')}`, 19 | ghPages: 'cross-env NODE_ENV=production BUILD=ghPages webpack', 20 | dist: 'cross-env NODE_ENV=production BUILD=dist webpack', 21 | min: 'cross-env NODE_ENV=production BUILD=min webpack' 22 | }, 23 | 24 | lint: `eslint ${pathTo('.')}`, 25 | 26 | test: { 27 | default: `cross-env NODE_ENV=test babel-node ${pathTo('test')}`, 28 | dev: 'npm start -- test | tap-nyan', 29 | cov: 'cross-env NODE_ENV=test' + 30 | ' babel-node node_modules/.bin/babel-istanbul cover' + 31 | ` --report text --report html --report lcov --dir reports/coverage ${pathTo('test')}`, 32 | e2e: 'cross-env NODE_ENV=development nightwatch-autorun' 33 | }, 34 | 35 | // CircleCI scripts 36 | ci: { 37 | lint: `eslint ${pathTo('.')}`, 38 | test: `NODE_ENV=test babel-node ${pathTo('test')}`, 39 | cov: 'NODE_ENV=test' + 40 | ' babel-node node_modules/.bin/babel-istanbul cover' + 41 | ' --report text --report lcov --verbose --dir ${CIRCLE_ARTIFACTS}/coverage' + 42 | ` ${pathTo('test')}`, 43 | e2e: 'REPORT_DIR=${CIRCLE_TEST_REPORTS} LOG_DIR=${CIRCLE_ARTIFACTS}' + 44 | ' NODE_ENV=development nightwatch-autorun', 45 | codecov: 'cat ${CIRCLE_ARTIFACTS}/coverage/lcov.info | codecov' 46 | }, 47 | 48 | // GIT Hooks 49 | precommit: 'npm start -- lint', 50 | prepush: 'npm start -- test', 51 | 52 | // NPM Hooks 53 | postversion: 'git push --follow-tags', 54 | prepublish: 'npm start -- --parallel build.lib,build.dist,build.min' 55 | }; 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-component-template", 3 | "version": "0.1.10", 4 | "description": "React component", 5 | "main": "lib/index.js", 6 | "bin": { 7 | "react-component-template": "cli.js" 8 | }, 9 | "config": { 10 | "component": "ReactComponentTemplate" 11 | }, 12 | "scripts": { 13 | "start": "p-s", 14 | "test": "npm start test", 15 | "precommit": "npm start precommit", 16 | "prepush": "npm start prepush", 17 | "postversion": "npm start postversion" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/nkbt/react-component-template.git" 22 | }, 23 | "keywords": [ 24 | "component", 25 | "react-component", 26 | "react" 27 | ], 28 | "author": "Nik Butenko (http://butenko.me/)", 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/nkbt/react-component-template/issues" 32 | }, 33 | "homepage": "https://github.com/nkbt/react-component-template", 34 | "dependencies": { 35 | "babel-cli": "6.24.1", 36 | "babel-core": "6.24.1", 37 | "babel-eslint": "7.2.3", 38 | "babel-istanbul": "0.12.2", 39 | "babel-loader": "7.0.0", 40 | "babel-plugin-transform-class-properties": "6.24.1", 41 | "babel-plugin-transform-object-rest-spread": "6.23.0", 42 | "babel-plugin-transform-react-remove-prop-types": "0.4.1", 43 | "babel-preset-es2015": "6.24.1", 44 | "babel-preset-react": "6.24.1", 45 | "codecov": "2.1.0", 46 | "cross-env": "4.0.0", 47 | "css-loader": "0.28.0", 48 | "css-modules-require-hook": "4.0.6", 49 | "eslint": "3.19.0", 50 | "eslint-plugin-react": "6.10.3", 51 | "gh-pages": "0.12.0", 52 | "glob": "7.1.1", 53 | "html-webpack-plugin": "2.28.0", 54 | "husky": "0.13.3", 55 | "nightwatch-autorun": "3.1.0", 56 | "p-s": "3.1.0", 57 | "react": "15.5.4", 58 | "react-dom": "15.5.4", 59 | "rimraf": "2.6.1", 60 | "sinon": "2.1.0", 61 | "style-loader": "0.16.1", 62 | "tap-nyan": "1.1.0", 63 | "tap-xunit": "1.7.0", 64 | "tape": "4.6.3", 65 | "webpack": "2.4.1", 66 | "webpack-dev-server": "2.4.4" 67 | }, 68 | "files": [ 69 | "/test/index.js", 70 | "/test-e2e/Smoketest.js", 71 | "/.eslintrc", 72 | "/cli.js", 73 | "/nightwatch.json", 74 | "/package-scripts.js", 75 | "/README.md", 76 | "/webpack.config.js" 77 | ] 78 | } 79 | -------------------------------------------------------------------------------- /src/ReactComponentTemplate.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | 4 | const ReactComponentTemplate = () => 5 |
{process.env.npm_package_name}
; 6 | 7 | 8 | export default ReactComponentTemplate; 9 | -------------------------------------------------------------------------------- /src/example/App/App.css: -------------------------------------------------------------------------------- 1 | .app { 2 | padding: 2em; 3 | } 4 | -------------------------------------------------------------------------------- /src/example/App/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactComponentTemplate from '../../ReactComponentTemplate'; 3 | import css from './App.css'; 4 | 5 | 6 | const App = () => 7 |
8 | 9 |
; 10 | 11 | 12 | export default App; 13 | -------------------------------------------------------------------------------- /src/example/Example.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | const appRoot = document.createElement('div'); 6 | 7 | appRoot.id = 'app'; 8 | document.body.appendChild(appRoot); 9 | ReactDOM.render(, appRoot); 10 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Babel6 does not hack the default behaviour of ES Modules anymore, so we should export 4 | const ReactComponentTemplate = require('./ReactComponentTemplate').default; 5 | 6 | module.exports = ReactComponentTemplate; 7 | -------------------------------------------------------------------------------- /test-e2e/Smoketest.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const packageJson = require(path.join(process.cwd(), 'package.json')); 5 | 6 | 7 | module.exports = { 8 | 'Smoketest'(browser) { 9 | browser 10 | .url(`${browser.launchUrl}/`) 11 | .waitForElementVisible('body', 1000) 12 | .assert.containsText('body', packageJson.name) 13 | .end(); 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /test/ReactComponentTemplate-test.js: -------------------------------------------------------------------------------- 1 | import test from 'tape'; 2 | import ReactComponentTemplate from '../src/ReactComponentTemplate'; 3 | 4 | 5 | test('ReactComponentTemplate', t => { 6 | t.ok(ReactComponentTemplate instanceof Function, 'should be function'); 7 | t.end(); 8 | }); 9 | -------------------------------------------------------------------------------- /test/example/App-test.js: -------------------------------------------------------------------------------- 1 | import test from 'tape'; 2 | import App from '../../src/example/App'; 3 | 4 | 5 | test('App', t => { 6 | t.ok(App instanceof Function, 'should be function'); 7 | t.end(); 8 | }); 9 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | require('css-modules-require-hook')({ 2 | generateScopedName: '[name]__[local]' 3 | }); 4 | 5 | require('glob') 6 | .sync('**/*-test.js', { 7 | realpath: true, 8 | cwd: require('path').resolve(process.cwd(), 'test') 9 | }) 10 | .forEach(require); 11 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | const webpack = require('webpack'); 5 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | const path = require('path'); 7 | const COMPONENT_NAME = process.env.npm_package_config_component; 8 | const pathTo = path.join.bind(null, process.cwd()); 9 | 10 | 11 | if (!COMPONENT_NAME) { 12 | throw Error('.config.component name is required'); 13 | } 14 | 15 | 16 | const loaders = [ 17 | { 18 | test: /\.css$/, 19 | loader: 'style-loader!css-loader?sourceMap&modules&localIdentName=[path][name]---[local]', 20 | include: [pathTo('src', 'example')] 21 | }, 22 | { 23 | test: /\.js$/, 24 | loader: 'babel-loader', 25 | include: [pathTo('src')] 26 | } 27 | ]; 28 | 29 | 30 | const definePlugin = new webpack.DefinePlugin({ 31 | 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), 32 | 'process.env.npm_package_name': JSON.stringify(process.env.npm_package_name) 33 | }); 34 | 35 | 36 | const resolve = {}; 37 | const stats = {colors: true}; 38 | 39 | 40 | const development = { 41 | devtool: '#source-map', 42 | 43 | entry: [ 44 | pathTo('src', 'example', 'Example.js'), 45 | 'webpack-dev-server/client?http://localhost:8080' 46 | ], 47 | output: {filename: 'bundle.js', path: pathTo('example')}, 48 | plugins: [ 49 | new HtmlWebpackPlugin(), 50 | definePlugin 51 | ], 52 | module: { 53 | loaders 54 | }, 55 | resolve, 56 | stats, 57 | devServer: { 58 | historyApiFallback: true, 59 | stats: { 60 | // Do not show list of hundreds of files included in a bundle 61 | chunkModules: false, 62 | colors: true 63 | } 64 | } 65 | }; 66 | 67 | 68 | const ghPages = { 69 | devtool: '#source-map', 70 | entry: pathTo('src', 'example', 'Example.js'), 71 | output: {filename: 'bundle.js', path: pathTo('example')}, 72 | plugins: [new HtmlWebpackPlugin(), definePlugin], 73 | module: {loaders}, 74 | resolve, 75 | stats 76 | }; 77 | 78 | 79 | const dist = { 80 | devtool: '#source-map', 81 | entry: pathTo('src', 'index.js'), 82 | output: { 83 | filename: `${require(pathTo('package.json')).name}.js`, 84 | path: pathTo('build'), 85 | library: COMPONENT_NAME, 86 | libraryTarget: 'umd' 87 | }, 88 | plugins: [definePlugin], 89 | module: {loaders}, 90 | resolve, 91 | stats, 92 | externals: { 93 | react: {root: 'React', commonjs2: 'react', commonjs: 'react', amd: 'react'} 94 | } 95 | }; 96 | 97 | 98 | const min = { 99 | devtool: '#source-map', 100 | entry: pathTo('src', 'index.js'), 101 | output: { 102 | filename: `${require(pathTo('package.json')).name}.min.js`, 103 | path: pathTo('build'), 104 | library: COMPONENT_NAME, 105 | libraryTarget: 'umd' 106 | }, 107 | plugins: [ 108 | definePlugin, 109 | new webpack.optimize.UglifyJsPlugin() 110 | ], 111 | module: {loaders}, 112 | resolve, 113 | stats, 114 | externals: { 115 | react: {root: 'React', commonjs2: 'react', commonjs: 'react', amd: 'react'} 116 | } 117 | }; 118 | 119 | 120 | const test = { 121 | output: {libraryTarget: 'commonjs2'}, 122 | module: {loaders} 123 | }; 124 | 125 | 126 | const configs = {development, ghPages, dist, min, test}; 127 | const build = process.env.BUILD || process.env.NODE_ENV || 'development'; 128 | 129 | 130 | module.exports = configs[build]; 131 | --------------------------------------------------------------------------------