Check for unused initial (untested) implementation
This commit is contained in:
parent
e599bef72e
commit
d55786f744
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
SOURCE: 'templates',
|
SOURCE_DIR: 'templates',
|
||||||
DIST: 'dist',
|
DIST_DIR: 'dist',
|
||||||
WORKING_DIR: 'tmp',
|
WORKING_DIR: 'tmp',
|
||||||
CONFIGURATION_FILE: 'conf.json'
|
CONFIGURATION_FILE: 'conf.json'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
23
gulpfile.js
23
gulpfile.js
|
|
@ -1,11 +1,11 @@
|
||||||
const gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
const plumber = require('gulp-plumber');
|
const plumber = require('gulp-plumber');
|
||||||
|
|
||||||
const { SOURCE, DIST, WORKING_DIR, CONFIGURATION_FILE } = require('./constants');
|
const { SOURCE_DIR, DIST_DIR, WORKING_DIR, CONFIGURATION_FILE } = require('./constants');
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
source: SOURCE,
|
sourceDir: SOURCE_DIR,
|
||||||
dist: DIST,
|
distDir: DIST_DIR,
|
||||||
workingDir: WORKING_DIR,
|
workingDir: WORKING_DIR,
|
||||||
configurationFile: CONFIGURATION_FILE,
|
configurationFile: CONFIGURATION_FILE,
|
||||||
src: function plumbedSrc() {
|
src: function plumbedSrc() {
|
||||||
|
|
@ -22,11 +22,14 @@ require('./tasks/less')(options);
|
||||||
require('./tasks/lint')(options);
|
require('./tasks/lint')(options);
|
||||||
require('./tasks/postcss')(options);
|
require('./tasks/postcss')(options);
|
||||||
require('./tasks/sass')(options);
|
require('./tasks/sass')(options);
|
||||||
require('./tasks/check-for-missing')(options);
|
require('./tasks/check-for-unused').checkForUnusedTask(options);
|
||||||
require('./tasks/check-deps')(options);
|
require('./tasks/check-deps')(options);
|
||||||
|
|
||||||
/* Runs the entire pipeline once. */
|
/* Runs the entire pipeline once. */
|
||||||
gulp.task('run-pipeline', gulp.series('dupe', 'less', 'sass', 'postcss', 'lint', 'build', 'check-for-missing'));
|
gulp.task(
|
||||||
|
'run-pipeline',
|
||||||
|
gulp.series('dupe', 'less', 'sass', 'postcss', 'lint', 'build', gulp.parallel('check-for-unused'))
|
||||||
|
);
|
||||||
|
|
||||||
/* By default templates will be built into '/dist'. */
|
/* By default templates will be built into '/dist'. */
|
||||||
gulp.task(
|
gulp.task(
|
||||||
|
|
@ -35,11 +38,11 @@ gulp.task(
|
||||||
/* gulp will watch for changes in '/templates'. */
|
/* gulp will watch for changes in '/templates'. */
|
||||||
gulp.watch(
|
gulp.watch(
|
||||||
[
|
[
|
||||||
options.source + '/**/*.html',
|
options.sourceDir + '/**/*.html',
|
||||||
options.source + '/**/*.css',
|
options.sourceDir + '/**/*.css',
|
||||||
options.source + '/**/*.scss',
|
options.sourceDir + '/**/*.scss',
|
||||||
options.source + '/**/*.less',
|
options.sourceDir + '/**/*.less',
|
||||||
options.source + '/**/conf.json'
|
options.sourceDir + '/**/conf.json'
|
||||||
],
|
],
|
||||||
{ delay: 500 },
|
{ delay: 500 },
|
||||||
gulp.series('run-pipeline')
|
gulp.series('run-pipeline')
|
||||||
|
|
|
||||||
|
|
@ -1635,9 +1635,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chalk": {
|
"chalk": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||||
"integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
|
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-styles": "^3.2.1",
|
"ansi-styles": "^3.2.1",
|
||||||
"escape-string-regexp": "^1.0.5",
|
"escape-string-regexp": "^1.0.5",
|
||||||
|
|
|
||||||
10
package.json
10
package.json
|
|
@ -26,13 +26,13 @@
|
||||||
"start": "node ./node_modules/.bin/gulp",
|
"start": "node ./node_modules/.bin/gulp",
|
||||||
"once": "node ./node_modules/.bin/gulp run-pipeline",
|
"once": "node ./node_modules/.bin/gulp run-pipeline",
|
||||||
"deploy": "npm run test && cp -r dist demo && git push origin `git subtree split --prefix demo develop`:gh-pages --force",
|
"deploy": "npm run test && cp -r dist demo && git push origin `git subtree split --prefix demo develop`:gh-pages --force",
|
||||||
"test": "npm run once && node ./node_modules/.bin/ava",
|
"e2e-test": "npm run once && node ./node_modules/.bin/ava",
|
||||||
"test:watch": "npm run once && node ./node_modules/.bin/ava --watch",
|
"format": "prettier {tasks,tests}/**/*.js gulpfile.js .eslintrc.js --write",
|
||||||
"format": "node ./node_modules/.bin/prettier {tasks,tests}/**/*.js gulpfile.js .eslintrc.js --write",
|
"lint": "eslint ./**/*.js gulpfile.js"
|
||||||
"lint": "node ./node_modules/.bin/eslint ./**/*.js gulpfile.js"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"autoprefixer": "^9.7.4",
|
"autoprefixer": "^9.6.1",
|
||||||
|
"chalk": "^2.4.2",
|
||||||
"del": "^5.1.0",
|
"del": "^5.1.0",
|
||||||
"graceful-fs": "^4.2.3",
|
"graceful-fs": "^4.2.3",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ function buildTask(options) {
|
||||||
return path;
|
return path;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.pipe(gulp.dest(options.dist));
|
.pipe(gulp.dest(options.distDir));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ function buildTask(options) {
|
||||||
* Clean up & then read from workingDir to generate templates.
|
* Clean up & then read from workingDir to generate templates.
|
||||||
* For each found config, a template group will be generated through `makeTemplates`.
|
* For each found config, a template group will be generated through `makeTemplates`.
|
||||||
*/
|
*/
|
||||||
return del(options.dist)
|
return del(options.distDir)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
/**
|
/**
|
||||||
* Loop through dirs and load their conf files.
|
* Loop through dirs and load their conf files.
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,9 @@
|
||||||
const gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
const { getConfigsForDir, getFilePathsForDir } = require('./util/util');
|
|
||||||
|
|
||||||
function checkForMissingTask(options) {
|
function checkForUnusedTask(options) {
|
||||||
gulp.task('check-for-missing', done => {
|
gulp.task('check-for-unused', async done => {
|
||||||
const configs = getConfigsForDir(options.workingDir, options.configurationFile);
|
done();
|
||||||
|
|
||||||
configs.map(({ dir, confItems }) => {
|
|
||||||
confItems.forEach(async confItem => {
|
|
||||||
const definedStrings = Object.keys(confItem).map(key => {
|
|
||||||
return {
|
|
||||||
src: `@echo ${key}`,
|
|
||||||
used: false
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const cwd = `${options.workingDir}/${dir}`;
|
|
||||||
const files = await getFilePathsForDir(cwd);
|
|
||||||
const htmlTemplates = files.filter(file => !!file.match(/.*\.html/) && !file.match(/.*\.inc*\.html/)); // Read only CSS files.
|
|
||||||
console.log(definedStrings, htmlTemplates);
|
|
||||||
});
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = checkForMissingTask;
|
module.exports = checkForUnusedTask;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
const gulp = require('gulp');
|
||||||
|
const fs = require('fs');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
const { getConfigsForDir, getFilePathsForDir, log } = require('./util/util');
|
||||||
|
|
||||||
|
const OUTPUT_KEYWORD = '@echo';
|
||||||
|
|
||||||
|
// todo: needs a proper refactor.
|
||||||
|
function checkForUnusedTask(options) {
|
||||||
|
gulp.task('check-for-unused', async done => {
|
||||||
|
const configs = getConfigsForDir(options.workingDir, options.configurationFile);
|
||||||
|
const unusedItems = await checkForUnusedItemsInConfigs(options.workingDir, configs);
|
||||||
|
outputWarningsForUnusedItems(unusedItems, configs);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: find configs by id instead of using the index?
|
||||||
|
const outputWarningsForUnusedItems = (unusedItems, configs) => {
|
||||||
|
const find = OUTPUT_KEYWORD;
|
||||||
|
const regex = new RegExp(find, 'g');
|
||||||
|
unusedItems.forEach((unusedInConfigs, index) => {
|
||||||
|
const { dir } = configs[index];
|
||||||
|
|
||||||
|
unusedInConfigs.forEach((unusedInConfItems, index) => {
|
||||||
|
log.warn(
|
||||||
|
`${unusedInConfItems.length} unused properties in ${dir}: ${unusedInConfItems
|
||||||
|
.reduce((acc, cur) => (acc ? `${acc}, ${chalk.white(cur)}` : chalk.white(cur)), '')
|
||||||
|
.replace(regex, '')}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkForUnusedItemsInConfigs = (rootDir, configs) => {
|
||||||
|
return Promise.all(
|
||||||
|
configs.map(async ({ dir, confItems }) => {
|
||||||
|
return Promise.all(
|
||||||
|
confItems.map(async confItem => {
|
||||||
|
const definedStrings = Object.keys(confItem).map(key => `${OUTPUT_KEYWORD} ${key}`);
|
||||||
|
const cwd = `${rootDir}/${dir}`;
|
||||||
|
const files = await getFilePathsForDir(cwd);
|
||||||
|
const htmlTemplates = await self.getHtmlTemplatesFromFilelist(files);
|
||||||
|
const concatenatedTemplates = htmlTemplates.join('');
|
||||||
|
|
||||||
|
return definedStrings.filter(str => concatenatedTemplates.includes(str));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// todo: should be util, so should the one in build.js
|
||||||
|
const getHtmlTemplatesFromFilelist = filelist => {
|
||||||
|
return Promise.all(
|
||||||
|
filelist
|
||||||
|
.filter(file => !!file.match(/.*\.html/) && !file.match(/.*\.inc*\.html/))
|
||||||
|
.map(
|
||||||
|
htmlTemplate =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
fs.readFile(htmlTemplate, 'utf8', (error, data) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(data);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const self = {
|
||||||
|
checkForUnusedTask,
|
||||||
|
outputWarningsForUnusedItems,
|
||||||
|
checkForUnusedItemsInConfigs,
|
||||||
|
getHtmlTemplatesFromFilelist
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = self;
|
||||||
|
|
@ -5,7 +5,7 @@ function dupeTask(options) {
|
||||||
gulp.task('dupe', function() {
|
gulp.task('dupe', function() {
|
||||||
del.sync([options.workingDir]);
|
del.sync([options.workingDir]);
|
||||||
|
|
||||||
return options.src([options.source + '/**/*']).pipe(gulp.dest('./' + options.workingDir));
|
return options.src([options.sourceDir + '/**/*']).pipe(gulp.dest('./' + options.workingDir));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const klaw = require('klaw');
|
const klaw = require('klaw');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
|
||||||
|
// todo test
|
||||||
/**
|
/**
|
||||||
* Given a directory, scans all directories in it (not deep) and returns found config items.
|
* Given a directory, scans all directories in it (not deep) and returns found config items.
|
||||||
*
|
*
|
||||||
|
|
@ -16,7 +18,7 @@ const getConfigsForDir = (rootDir, configFileName) => {
|
||||||
|
|
||||||
/** Exit with warn if no configuration file found. */
|
/** Exit with warn if no configuration file found. */
|
||||||
if (!fs.existsSync(path.resolve(rootDir, confPath))) {
|
if (!fs.existsSync(path.resolve(rootDir, confPath))) {
|
||||||
console.warn(`Missing configuration in "${dir}". Did you remember to create "${dir}/${configFileName}"?`);
|
self.log.warn(`Missing configuration in "${dir}". Did you remember to create "${dir}/${configFileName}"?`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -41,8 +43,11 @@ const getConfigsForDir = (rootDir, configFileName) => {
|
||||||
.filter(config => config);
|
.filter(config => config);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// todo test
|
||||||
/**
|
/**
|
||||||
* Given a directory, gets all file paths in it.
|
* Given a directory, gets all file paths in it.
|
||||||
|
*
|
||||||
|
* @param { string } dir Dir to get files paths for.
|
||||||
*/
|
*/
|
||||||
const getFilePathsForDir = dir => {
|
const getFilePathsForDir = dir => {
|
||||||
const files = [];
|
const files = [];
|
||||||
|
|
@ -63,7 +68,24 @@ const getFilePathsForDir = dir => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
const log = {
|
||||||
|
warn: (...messages) => {
|
||||||
|
console.warn('🔵 ', chalk.yellow(messages));
|
||||||
|
},
|
||||||
|
|
||||||
|
log: (...messages) => {
|
||||||
|
console.log('🔘 ', chalk.gray(messages));
|
||||||
|
},
|
||||||
|
|
||||||
|
error: (...messages) => {
|
||||||
|
console.error('🔴 ', chalk.red(messages));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const self = {
|
||||||
|
log,
|
||||||
getConfigsForDir,
|
getConfigsForDir,
|
||||||
getFilePathsForDir
|
getFilePathsForDir
|
||||||
};
|
};
|
||||||
|
|
||||||
|
module.exports = self;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
const test = require('ava');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const readFileSync = path => fs.readFileSync(('../', path), 'utf8');
|
||||||
|
|
||||||
|
test('dark signature output', async t => {
|
||||||
|
const expected = readFileSync('tests/sample/dark/signature-dark.html');
|
||||||
|
const built = readFileSync('dist/dark/signature-dark.html');
|
||||||
|
|
||||||
|
t.deepEqual(expected, built);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('dark signature reply output', async t => {
|
||||||
|
const expected = readFileSync('tests/sample/dark/signature-reply-dark.html');
|
||||||
|
const built = readFileSync('dist/dark/signature-reply-dark.html');
|
||||||
|
|
||||||
|
t.deepEqual(expected, built);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('light signature output', async t => {
|
||||||
|
const expected = readFileSync('tests/sample/light/signature-light.html');
|
||||||
|
const built = readFileSync('dist/light/signature-light.html');
|
||||||
|
|
||||||
|
t.deepEqual(expected, built);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('light signature reply output', async t => {
|
||||||
|
const expected = readFileSync('tests/sample/light/signature-reply-light.html');
|
||||||
|
const built = readFileSync('dist/light/signature-reply-light.html');
|
||||||
|
|
||||||
|
t.deepEqual(expected, built);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('light full mail output', async t => {
|
||||||
|
const expected = readFileSync('tests/sample/light/full-mail-light.html');
|
||||||
|
const built = readFileSync('dist/light/full-mail-light.html');
|
||||||
|
|
||||||
|
t.deepEqual(expected, built);
|
||||||
|
});
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
const test = require('ava');
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
test('dark signature output', async t => {
|
|
||||||
const expected = fs.readFileSync(path.resolve('tests/sample/dark/signature-dark.html'), 'utf8');
|
|
||||||
const built = fs.readFileSync(path.resolve('dist/dark/signature-dark.html'), 'utf8');
|
|
||||||
|
|
||||||
t.deepEqual(expected, built);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('dark signature reply output', async t => {
|
|
||||||
const expected = fs.readFileSync(path.resolve('tests/sample/dark/signature-reply-dark.html'), 'utf8');
|
|
||||||
const built = fs.readFileSync(path.resolve('dist/dark/signature-reply-dark.html'), 'utf8');
|
|
||||||
|
|
||||||
t.deepEqual(expected, built);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('light signature output', async t => {
|
|
||||||
const expected = fs.readFileSync(path.resolve('tests/sample/light/signature-light.html'), 'utf8');
|
|
||||||
const built = fs.readFileSync(path.resolve('dist/light/signature-light.html'), 'utf8');
|
|
||||||
|
|
||||||
t.deepEqual(expected, built);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('light signature reply output', async t => {
|
|
||||||
const expected = fs.readFileSync(path.resolve('tests/sample/light/signature-reply-light.html'), 'utf8');
|
|
||||||
const built = fs.readFileSync(path.resolve('dist/light/signature-reply-light.html'), 'utf8');
|
|
||||||
|
|
||||||
t.deepEqual(expected, built);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('light full mail output', async t => {
|
|
||||||
const expected = fs.readFileSync(path.resolve('tests/sample/light/full-mail-light.html'), 'utf8');
|
|
||||||
const built = fs.readFileSync(path.resolve('dist/light/full-mail-light.html'), 'utf8');
|
|
||||||
|
|
||||||
t.deepEqual(expected, built);
|
|
||||||
});
|
|
||||||
Loading…
Reference in New Issue