From 76295676a1c073f6d2cd15f5c54b0edcbbbc14c6 Mon Sep 17 00:00:00 2001 From: XhmikosR Date: Mon, 27 Nov 2017 19:41:48 +0200 Subject: [PATCH] Replace lint-vars.sh with a Node.js script. (#24860) Also, include it in the `css` npm script since it's instant. --- build/lint-vars.js | 83 ++++++++++++++++++++++++++++++++++++++++++++++ build/lint-vars.sh | 28 ---------------- package-lock.json | 18 +++++----- package.json | 2 ++ 4 files changed, 94 insertions(+), 37 deletions(-) create mode 100644 build/lint-vars.js delete mode 100755 build/lint-vars.sh diff --git a/build/lint-vars.js b/build/lint-vars.js new file mode 100644 index 000000000000..909f5293d788 --- /dev/null +++ b/build/lint-vars.js @@ -0,0 +1,83 @@ +#!/usr/bin/env node + +/*! + * Script to find unused Sass variables. + * + * Copyright 2017 The Bootstrap Authors + * Copyright 2017 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +'use strict' + +const fs = require('fs') +const path = require('path') +const glob = require('glob') + +// Blame TC39... https://github.com/benjamingr/RegExp.escape/issues/37 +function regExpQuote(str) { + return str.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&') +} + +let globalSuccess = true + +function findUnusedVars(dir) { + if (!(fs.existsSync(dir) && fs.statSync(dir).isDirectory())) { + console.log(`"${dir}": Not a valid directory!`) + process.exit(1) + } + + console.log(`Finding unused variables in "${dir}"...`) + + // A variable to handle success/failure message in this function + let unusedVarsFound = false + + // Array of all Sass files' content + const sassFiles = glob.sync(path.join(dir, '**/*.scss')) + // String of all Sass files' content + let sassFilesString = '' + + sassFiles.forEach((file) => { + sassFilesString += fs.readFileSync(file, 'utf8') + }) + + // Array of all Sass variables + const variables = sassFilesString.match(/(^\$[a-zA-Z0-9_-]+[^:])/gm) + + console.log(`There's a total of ${variables.length} variables.`) + + // Loop through each variable + variables.forEach((variable) => { + const re = new RegExp(regExpQuote(variable), 'g') + const count = (sassFilesString.match(re) || []).length + + if (count === 1) { + console.log(`Variable "${variable}" is only used once!`) + unusedVarsFound = true + globalSuccess = false + } + }) + + if (unusedVarsFound === false) { + console.log(`No unused variables found in "${dir}".`) + } +} + +function main(args) { + if (args.length < 1) { + console.log('Wrong arguments!') + console.log('Usage: lint-vars.js folder [, folder2...]') + process.exit(1) + } + + args.forEach((arg) => { + findUnusedVars(arg) + }) + + if (globalSuccess === false) { + process.exit(1) + } +} + +// The first and second args are: path/to/node script.js +main(process.argv.slice(2)) diff --git a/build/lint-vars.sh b/build/lint-vars.sh deleted file mode 100755 index ae7f716c1f3b..000000000000 --- a/build/lint-vars.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env bash -# -# Approach: -# 1. Find variable declaration in the form of "$my-var: anyvalue" -# 2. Loop through found variables and find occurrences of each variable in all sass files -# 3. Filter out vars that occurred only once -# -# Run from command line with `build/lint-vars.sh scss`. -# -# Source: https://gist.github.com/badsyntax/6193491 - -if [ -z "$1" ]; then - echo "Please specify a directory as the first argument." - exit 1 -fi -if [ ! -d "$1" ]; then - echo "Not a valid directory." - exit 1 -fi - -echo "Finding unused variables. This might take some time..." - -vars=$(find "$1" -type f -name "*.scss" -exec grep --color=never -h '^$[a-zA-Z0-9_-][^:]*' {} \; | sed 's/$\([a-zA-Z0-9_-][^:]*\).*/\1/') - -for var in $vars; do - echo -n "Occurrences of \"\$$var\":" - find "$1" -type f -name "*.scss" -exec grep --color=never -h "$var" "{}" \; | wc -l -done | grep ' 1$' diff --git a/package-lock.json b/package-lock.json index 1e36304d14f1..28dbe1de48b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6934,15 +6934,6 @@ "duplexer": "0.1.1" } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -6981,6 +6972,15 @@ "function-bind": "1.1.1" } }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", diff --git a/package.json b/package.json index 101fed0a277d..ae787dd86f6c 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "css-compile-docs": "node-sass --output-style expanded --source-map true --source-map-contents true --precision 6 assets/scss/docs.scss assets/css/docs.min.css", "css-lint": "stylelint --config build/.stylelintrc --syntax scss \"scss/**/*.scss\"", "css-lint-docs": "stylelint --config build/.stylelintrc --syntax scss \"assets/scss/*.scss\" && stylelint --config docs/4.0/examples/.stylelintrc \"docs/**/*.css\"", + "css-lint-vars": "node build/lint-vars.js scss/ assets/scss/", "css-prefix": "postcss --config build/postcss.config.js --replace \"dist/css/*.css\" \"!dist/css/*.min.css\"", "css-prefix-docs": "postcss --config build/postcss.config.js --replace \"assets/css/docs.min.css\" \"docs/**/*.css\"", "css-minify": "cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap.min.css dist/css/bootstrap.css && cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap-grid.min.css dist/css/bootstrap-grid.css && cleancss --level 1 --source-map --source-map-inline-sources --output dist/css/bootstrap-reboot.min.css dist/css/bootstrap-reboot.css", @@ -94,6 +95,7 @@ "cross-env": "^5.1.1", "eslint": "^4.11.0", "eslint-plugin-compat": "^2.1.0", + "glob": "^7.1.2", "htmllint-cli": "^0.0.6", "jsunitsaucelabs": "^1.3.0", "karma": "^1.7.1",