diff --git a/.editorconfig b/.editorconfig index 21f03ed..e271f67 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,6 @@ # WordPress Coding Standards # https://make.wordpress.org/core/handbook/coding-standards/ - + root = true [*] diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 0000000..58c6190 --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,3 @@ +{ + "extends": "stylelint-config-wordpress" +} diff --git a/check-diff.sh b/check-diff.sh index 2ed1935..dbd84c0 100755 --- a/check-diff.sh +++ b/check-diff.sh @@ -173,6 +173,15 @@ function set_environment_variables { ESLINT_IGNORE="$( upsearch .eslintignore )" fi + if [ -z "$STYLELINT_CONFIG" ]; then + for SEARCHED_STYLELINT_CONFIG in .stylelintrc{,.yaml,.yml,.js,.json} stylelint.config.js; do + STYLELINT_CONFIG="$( upsearch $SEARCHED_STYLELINT_CONFIG )" + if [ ! -z "$STYLELINT_CONFIG" ]; then + break + fi + done + fi + # Load any environment variable overrides from config files ENV_FILE=$( upsearch .ci-env.sh ) if [ ! -z "$ENV_FILE" ]; then @@ -252,7 +261,7 @@ function set_environment_variables { cat "$TEMP_DIRECTORY/paths-scope" | grep -E '\.php(:|$)' | cat - > "$TEMP_DIRECTORY/paths-scope-php" cat "$TEMP_DIRECTORY/paths-scope" | grep -E '\.jsx?(:|$)' | cat - > "$TEMP_DIRECTORY/paths-scope-js" - cat "$TEMP_DIRECTORY/paths-scope" | grep -E '\.(css|scss)(:|$)' | cat - > "$TEMP_DIRECTORY/paths-scope-scss" + cat "$TEMP_DIRECTORY/paths-scope" | grep -E '\.css(:|$)' | cat - > "$TEMP_DIRECTORY/paths-scope-css" cat "$TEMP_DIRECTORY/paths-scope" | grep -E '\.(xml|svg|xml.dist)(:|$)' | cat - > "$TEMP_DIRECTORY/paths-scope-xml" # Gather the proper states of files to run through linting (this won't apply to phpunit) @@ -290,7 +299,7 @@ function set_environment_variables { done # Make sure linter configs get copied linting directory since upsearch is relative. - for linter_file in .jshintrc .jshintignore .jscsrc .jscs.json .eslintignore .eslintrc phpcs.xml phpcs.xml.dist phpcs.ruleset.xml ruleset.xml; do + for linter_file in .jshintrc .jshintignore .jscsrc .jscs.json .eslintignore .eslintrc .stylelintrc{,.yaml,.yml,.js,.json} stylelint.config.js phpcs.xml phpcs.xml.dist phpcs.ruleset.xml ruleset.xml; do if git ls-files "$linter_file" --error-unmatch > /dev/null 2>&1; then if [ -L $linter_file ]; then ln -fs $(git show :"$linter_file") "$LINTING_DIRECTORY/$linter_file" @@ -470,6 +479,18 @@ function install_tools { fi fi + # Install stylelint + if [ -n "$STYLELINT_CONFIG" ] && [ -e "$STYLELINT_CONFIG" ] && [ ! -e "$(npm bin)/stylelint" ] && check_should_execute 'stylelint'; then + echo "Installing stylelint" + if ! npm install -g stylelint 2>/dev/null; then + echo "Failed to install stylelint (try manually doing: sudo npm install -g stylelint), so skipping stylelint" + DEV_LIB_SKIP="$DEV_LIB_SKIP,stylelint" + elif ! -e node_modules/stylelint-formatter-compact; then + echo "The stylelint-formatter-compact node module is not installed, skipping stylelint." + DEV_LIB_SKIP="$DEV_LIB_SKIP,stylelint" + fi + fi + # YUI Compressor if [ "$YUI_COMPRESSOR_CHECK" == 1 ] && command -v java >/dev/null 2>&1 && check_should_execute 'yuicompressor'; then if [ ! -e "$YUI_COMPRESSOR_PATH" ]; then @@ -783,6 +804,35 @@ function lint_js_files { fi } + +function lint_css_files { + if [ ! -s "$TEMP_DIRECTORY/paths-scope-css" ]; then + return + fi + + set -e + + # Run stylelint. + if [ -n "$STYLELINT_CONFIG" ] && [ -e "$STYLELINT_CONFIG" ] && [ -e "$(npm bin)/stylelint" ] && check_should_execute 'stylelint'; then + ( + echo "## stylelint" + cd "$LINTING_DIRECTORY" + if ! cat "$TEMP_DIRECTORY/paths-scope-css" | remove_diff_range | xargs "$(npm bin)/stylelint" --custom-formatter=node_modules/stylelint-formatter-compact --config="$STYLELINT_CONFIG" > "$TEMP_DIRECTORY/stylelint-report"; then + if [ "$CHECK_SCOPE" == 'patches' ]; then + cat "$TEMP_DIRECTORY/stylelint-report" | php "$DEV_LIB_PATH/diff-tools/filter-report-for-patch-ranges.php" "$TEMP_DIRECTORY/paths-scope-css" | cut -c$( expr ${#LINTING_DIRECTORY} + 2 )- + exit_code="${PIPESTATUS[1]}" + if [[ $exit_code != 0 ]]; then + return $exit_code + fi + elif [ -s "$TEMP_DIRECTORY/stylelint-report" ]; then + cat "$TEMP_DIRECTORY/stylelint-report" | cut -c$( expr ${#LINTING_DIRECTORY} + 2 )- + exit 1 + fi + fi + ) + fi +} + # @todo: This is wrong, as we should be doing `npm test` instead of calling `grunt qunit` directly. function run_qunit { if [ ! -s "$TEMP_DIRECTORY/paths-scope-js" ] || ! check_should_execute 'grunt'; then diff --git a/pre-commit b/pre-commit index ce24531..929878b 100755 --- a/pre-commit +++ b/pre-commit @@ -40,6 +40,7 @@ echo "## Checking files, scope $CHECK_SCOPE:" cat "$TEMP_DIRECTORY/paths-scope" check_execute_bit +lint_css_files lint_js_files lint_php_files lint_xml_files diff --git a/readme.md b/readme.md index a73823b..3c556b7 100644 --- a/readme.md +++ b/readme.md @@ -27,7 +27,7 @@ To install the pre-commit hook, symlink to [`pre-commit`](pre-commit) from your ./dev-lib/install-pre-commit-hook.sh ``` -Also symlink (or copy) the [`.jshintrc`](.jshint), [`.jshintignore`](.jshintignore), [`.jscsrc`](.jscsrc), [`phpcs.xml`](phpcs.xml), and [`phpunit-plugin.xml`](phpunit-plugin.xml) (note the PHPUnit config will need its paths modified if it is copied instead of symlinked): +Also symlink (or copy) the desired linting configs and [`phpunit-plugin.xml`](phpunit-plugin.xml) (note the PHPUnit config will need its paths modified if it is copied instead of symlinked): ```bash ln -s dev-lib/phpunit-plugin.xml phpunit.xml.dist && git add phpunit.xml.dist # (if working with a plugin) @@ -36,15 +36,17 @@ ln -s dev-lib/.jshintrc . && git add .jshintrc ln -s dev-lib/.jscsrc . && git add .jscsrc ln -s dev-lib/.eslintrc . && git add .eslintrc ln -s dev-lib/.eslintignore . && git add .eslintignore +ln -s dev-lib/.stylelintrc . && git add .stylelintrc ln -s dev-lib/.editorconfig . && git add .editorconfig cp dev-lib/.jshintignore . && git add .jshintignore # don't use symlink for this ``` -For ESLint, you'll also likely want to make `eslint` as a dev dependency for your NPM package: +For ESLint and stylelint, you'll also likely want to make them dev dependencies for your NPM package: ```bash npm init # if you don't have a package.json already npm install --save-dev eslint +npm install --save-dev stylelint stylelint-formatter-compact git add package.json echo 'node_modules' >> .gitignore git add .gitignore @@ -63,7 +65,7 @@ git clone https://github.com/xwp/wp-dev-lib.git ~/Projects/wp-dev-lib For the Travis CI checks, the `.travis.yml` copied and committed to the repo (see below) will clone the repo into the `dev-lib` directory if it doesn't exist (or whatever your `DEV_LIB_PATH` environment variable is set to). -To install the [`.jshintrc`](.jshint), [`.jshintignore`](.jshintignore), [`.jscsrc`](.jscsrc), and (especially optionally) [`phpcs.xml`](phpcs.xml), copy the files into the repo root (as opposed to creating symlinks, as when installing via submodule). +To install the [`.jshintrc`](.jshint), [`.jshintignore`](.jshintignore), [`.jscsrc`](.jscsrc), [`.eslintrc`](.eslintrc), [`.stylelintrc`](.stylelintrc), and (especially optionally) [`phpcs.xml`](phpcs.xml), copy the files into the repo root (as opposed to creating symlinks, as when installing via submodule). To install dev-lib for all themes and plugins that don't already have a `pre-commit` hook installed, and to upgrade the dev-lib for any submodule installations, you can run the bundled script [`install-upgrade-pre-commit-hook.sh`](install-upgrade-pre-commit-hook.sh) which will look for any repos in the current directory tree and attempt to auto-install. For example: diff --git a/travis.script.sh b/travis.script.sh index 2aa6e2d..b3a001c 100755 --- a/travis.script.sh +++ b/travis.script.sh @@ -9,6 +9,7 @@ fi echo check_execute_bit +lint_css_files lint_js_files lint_php_files lint_xml_files