@caweb/cli 1.4.2 → 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +2 -180
  2. package/bin/css-audit/.editorconfig +12 -0
  3. package/bin/css-audit/.github/workflows/build-report.yml +46 -0
  4. package/bin/css-audit/.github/workflows/merge-trunk-to-report.yml +17 -0
  5. package/bin/css-audit/.github/workflows/node.yaml +32 -0
  6. package/bin/css-audit/.nvmrc +1 -0
  7. package/bin/css-audit/README.md +131 -0
  8. package/bin/css-audit/css-audit.config.js +13 -0
  9. package/bin/css-audit/index.js +38 -0
  10. package/bin/css-audit/package-lock.json +6689 -0
  11. package/bin/css-audit/package.json +56 -0
  12. package/bin/css-audit/public/.gitkeep +1 -0
  13. package/bin/css-audit/src/__tests__/alphas.js +128 -0
  14. package/bin/css-audit/src/__tests__/colors.js +115 -0
  15. package/bin/css-audit/src/__tests__/display-none.js +52 -0
  16. package/bin/css-audit/src/__tests__/important.js +88 -0
  17. package/bin/css-audit/src/__tests__/media-queries.js +84 -0
  18. package/bin/css-audit/src/__tests__/property-values.js +55 -0
  19. package/bin/css-audit/src/__tests__/run.js +25 -0
  20. package/bin/css-audit/src/__tests__/selectors.js +66 -0
  21. package/bin/css-audit/src/audits/alphas.js +70 -0
  22. package/bin/css-audit/src/audits/colors.js +83 -0
  23. package/bin/css-audit/src/audits/display-none.js +39 -0
  24. package/bin/css-audit/src/audits/important.js +60 -0
  25. package/bin/css-audit/src/audits/media-queries.js +96 -0
  26. package/bin/css-audit/src/audits/property-values.js +65 -0
  27. package/bin/css-audit/src/audits/selectors.js +67 -0
  28. package/bin/css-audit/src/audits/typography.js +41 -0
  29. package/bin/css-audit/src/formats/cli-table.js +81 -0
  30. package/bin/css-audit/src/formats/html/_audit-alpha.twig +23 -0
  31. package/bin/css-audit/src/formats/html/_audit-colors.twig +23 -0
  32. package/bin/css-audit/src/formats/html/_audit-default.twig +24 -0
  33. package/bin/css-audit/src/formats/html/index.twig +88 -0
  34. package/bin/css-audit/src/formats/html/style.css +341 -0
  35. package/bin/css-audit/src/formats/html.js +52 -0
  36. package/bin/css-audit/src/formats/json.js +9 -0
  37. package/bin/css-audit/src/run.js +76 -0
  38. package/bin/css-audit/src/utils/__tests__/cli.js +70 -0
  39. package/bin/css-audit/src/utils/__tests__/example-config.config.js +12 -0
  40. package/bin/css-audit/src/utils/__tests__/get-specificity.js +39 -0
  41. package/bin/css-audit/src/utils/cli.js +133 -0
  42. package/bin/css-audit/src/utils/format-report.js +37 -0
  43. package/bin/css-audit/src/utils/get-specificity.js +97 -0
  44. package/bin/css-audit/src/utils/get-values-count.js +17 -0
  45. package/commands/index.js +15 -5
  46. package/commands/test.js +0 -3
  47. package/commands/webpack/webpack.js +166 -0
  48. package/configs/webpack.config.js +151 -81
  49. package/lib/cli.js +71 -35
  50. package/lib/helpers.js +3 -1
  51. package/lib/webpack/plugins/a11y/aceconfig.js +44 -0
  52. package/lib/webpack/plugins/a11y/index.js +272 -0
  53. package/lib/webpack/plugins/a11y/package.json +12 -0
  54. package/lib/webpack/plugins/css-audit/css-audit.config.cjs +5 -0
  55. package/lib/webpack/plugins/css-audit/default.config.js +19 -0
  56. package/lib/webpack/plugins/css-audit/index.js +297 -0
  57. package/lib/webpack/plugins/css-audit/package.json +12 -0
  58. package/lib/webpack/plugins/jshint/.jshintrc +31 -0
  59. package/lib/webpack/plugins/jshint/index.js +286 -0
  60. package/lib/webpack/plugins/jshint/package-lock.json +22 -0
  61. package/lib/webpack/plugins/jshint/package.json +15 -0
  62. package/lib/webpack/plugins/jshint/reporter.cjs +663 -0
  63. package/package.json +18 -12
  64. package/assets/logo.ico +0 -0
  65. package/commands/a11y.js +0 -95
  66. package/commands/build.js +0 -80
  67. package/commands/serve.js +0 -95
  68. package/configs/aceconfig.js +0 -28
  69. package/docs/CREDITS.MD +0 -27
  70. package/docs/ISSUES.MD +0 -7
  71. package/docs/OVERRIDES.md +0 -53
  72. package/docs/ROADMAP.MD +0 -19
  73. package/docs/SYNC.MD +0 -29
  74. package/docs/tool/index.js +0 -45
  75. package/gen/parser.js +0 -166
  76. package/gen/site-generator.js +0 -144
@@ -0,0 +1,272 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * External dependencies
5
+ */
6
+ import { sync as resolveBin } from 'resolve-bin';
7
+ import spawn from 'cross-spawn';
8
+ import { getAllFilesSync } from 'get-all-files'
9
+ import EntryDependency from "webpack/lib/dependencies/EntryDependency.js";
10
+ import path from 'path';
11
+ import { isUrl, isValidUrl } from 'check-valid-url';
12
+ import fs from 'fs';
13
+ import deepmerge from 'deepmerge';
14
+ import chalk from 'chalk';
15
+ import { fileURLToPath, URL } from 'url';
16
+
17
+ // default configuration
18
+ import {default as DefaultConfig} from './aceconfig.js';
19
+
20
+ const boldWhite = chalk.bold.white;
21
+ const boldGreen = chalk.bold.green;
22
+ const boldBlue = chalk.bold.hex('#03a7fc');
23
+ const currentPath = path.dirname(fileURLToPath(import.meta.url));
24
+
25
+ // IBM Accessibility Checker Plugin
26
+ class A11yPlugin {
27
+ config = {}
28
+
29
+ constructor(opts = {}) {
30
+ // outputFolder must be resolved
31
+ if( opts.outputFolder ){
32
+ opts.outputFolder = path.join(process.cwd(), opts.outputFolder);
33
+ }
34
+ this.config = deepmerge(
35
+ DefaultConfig,
36
+ {
37
+ outputFolder: path.join(currentPath, DefaultConfig.outputFolder)
38
+ },
39
+ opts
40
+ );
41
+ }
42
+
43
+ apply(compiler) {
44
+ const staticDir = {
45
+ directory: this.config.outputFolder,
46
+ watch: true
47
+ }
48
+ let { devServer, output } = compiler.options;
49
+ let hostUrl = 'localhost' === devServer.host ? `http://${devServer.host}`: devServer.host;
50
+ let hostPort = devServer.port;
51
+
52
+ if( hostPort && 80 !== hostPort )
53
+ {
54
+ hostUrl = `${hostUrl}:${hostPort}`;
55
+ }
56
+
57
+ // if dev server allows for multiple pages to be opened
58
+ // add outputFilename.html to open property.
59
+ if( Array.isArray(devServer.open) ){
60
+ devServer.open.push(`${hostUrl}/${this.config.outputFilename}.html`)
61
+ }else if( 'object' === typeof devServer.open && Array.isArray(devServer.open.target) ){
62
+ devServer.open.target.push(`${hostUrl}/${this.config.outputFilename}.html`)
63
+ }
64
+
65
+ // add our static directory
66
+ if( Array.isArray(devServer.static) ){
67
+ devServer.static.push(staticDir)
68
+ }else{
69
+ devServer.static = [].concat(devServer.static, staticDir );
70
+ }
71
+
72
+ // Wait for configuration preset plugins to apply all configure webpack defaults
73
+ compiler.hooks.initialize.tap('IBM Accessibility Plugin', () => {
74
+ compiler.hooks.compilation.tap(
75
+ "IBM Accessibility Plugin",
76
+ (compilation, { normalModuleFactory }) => {
77
+ compilation.dependencyFactories.set(
78
+ EntryDependency,
79
+ normalModuleFactory
80
+ );
81
+ }
82
+ );
83
+
84
+ const { entry, options, context } = {
85
+ entry: path.join( this.config.outputFolder, 'a11y.update.js'),
86
+ options: {
87
+ name: 'a11y'
88
+ },
89
+ context: 'a11y'
90
+ };
91
+
92
+ const dep = new EntryDependency(entry);
93
+ dep.loc = {
94
+ name: options.name
95
+ };
96
+ if( ! fs.existsSync(path.resolve(this.config.outputFolder))){
97
+ fs.mkdirSync( path.resolve(this.config.outputFolder), {recursive: true} );
98
+ }
99
+
100
+ fs.writeFileSync(
101
+ path.join(this.config.outputFolder, `a11y.update.js`),
102
+ `` // required for hot-update to compile on our page, blank script for now
103
+ );
104
+
105
+
106
+ compiler.hooks.thisCompilation.tap('IBM Accessibility Plugin',
107
+ /**
108
+ * Hook into the webpack compilation
109
+ * @param {Compilation} compilation
110
+ */
111
+ (compilation) => {
112
+
113
+ compiler.hooks.make.tapAsync("IBM Accessibility Plugin", (compilation, callback) => {
114
+
115
+ compilation.addEntry(
116
+ context,
117
+ dep,
118
+ options,
119
+ err => {
120
+ callback(err);
121
+ });
122
+ });
123
+
124
+ compiler.hooks.done.tapAsync(
125
+ 'IBM Accessibility Plugin',
126
+ /**
127
+ * Hook into the process assets hook
128
+ * @param {any} _
129
+ * @param {(err?: Error) => void} callback
130
+ */
131
+ ({compilation}, callback) => {
132
+
133
+ console.log(`<i> ${boldGreen('[webpack-dev-middleware] Running IBM Accessibility scan...')}`);
134
+
135
+ this.a11yCheck(path.join(process.cwd(), output.publicPath ?? '/' ), this.config );
136
+
137
+ console.log(`<i> ${boldGreen('[webpack-dev-middleware] IBM Accessibilty Report can be viewed at')} ${ boldBlue(new URL(`${hostUrl}/${this.config.outputFilename}.html`).toString()) }`);
138
+
139
+ callback();
140
+ });
141
+
142
+ compiler.hooks.watchClose.tap( 'IBM Accessibility Plugin', () => {
143
+ getAllFilesSync(compiler.options.output.path).toArray().forEach(f => {
144
+ if(
145
+ f.includes('a11y') || // delete any a11y files
146
+ f.includes('.hot-update.js') // delete any HMR files
147
+ ){
148
+ fs.rmSync(f)
149
+ }
150
+ })
151
+ });
152
+
153
+ });
154
+
155
+ });
156
+
157
+ }
158
+
159
+ /**
160
+ * Run accessibility checks
161
+ *
162
+ * @param {Object} options
163
+ * @param {boolean} options.debug True if debug mode is enabled.
164
+ * @param {boolean} options.ruleArchive Specify the rule archive.
165
+ * @param {boolean} options.policies Specify one or many policies to scan.
166
+ * @param {boolean} options.failLevels Specify one or many violation levels on which to fail the test.
167
+ * @param {boolean} options.reportLevels Specify one or many violation levels that should be reported.
168
+ * @param {boolean} options.labels Specify labels that you would like associated to your scan.
169
+ * @param {boolean} options.outputFormat In which formats should the results be output.
170
+ * @param {boolean} options.outputFilename Filename for the scan results.
171
+ * @param {boolean} options.outputFolder Where the scan results should be saved.
172
+ * @param {boolean} options.outputFilenameTimestamp Should the timestamp be included in the filename of the reports?
173
+ */
174
+ a11yCheck(url, {
175
+ debug,
176
+ ruleArchive,
177
+ policies,
178
+ failLevels,
179
+ reportLevels,
180
+ labels,
181
+ outputFormat,
182
+ outputFilename,
183
+ outputFolder,
184
+ outputFilenameTimestamp
185
+ }){
186
+
187
+ let acheckerArgs = [
188
+ '--ruleArchive',
189
+ ruleArchive,
190
+ '--policies',
191
+ Array.isArray(policies) ? policies.filter(e => e).join(',') : policies,
192
+ '--failLevels',
193
+ Array.isArray(failLevels) ? failLevels.filter(e => e).join(',') : failLevels,
194
+ '--reportLevels',
195
+ Array.isArray(reportLevels) ? reportLevels.filter(e => e).join(',') : reportLevels,
196
+ '--outputFolder',
197
+ outputFolder,
198
+ '--outputFormat',
199
+ outputFormat,
200
+ '---outputFilenameTimestamp',
201
+ outputFilenameTimestamp,
202
+ url
203
+ ];
204
+
205
+ let isValid = false;
206
+
207
+ if( fs.existsSync( url ) ){
208
+ if( fs.statSync(url).isDirectory() && path.join( url, 'index.html') ){
209
+ url = path.join( url, 'index.html')
210
+ }
211
+ isValid = true;
212
+ }else{
213
+ isValid = 'localhost' === new URL(url).hostname || isUrl( url )
214
+ }
215
+
216
+ if( isValid ){
217
+ let originalFileName = `${fs.existsSync( url ) ?
218
+ path.resolve(url).replace(':', '_') :
219
+ url.replace(/http[s]+:\/\//, '')}.html`;
220
+ let originalJsonFileName = `${fs.existsSync( url ) ?
221
+ path.resolve(url).replace(':', '_') :
222
+ url.replace(/http[s]+:\/\//, '')}.json`;
223
+
224
+ let outputDir = path.resolve('.', outputFolder );
225
+
226
+ let {stderr, stdout} = spawn.sync(
227
+ resolveBin('accessibility-checker', {executable: 'achecker'}),
228
+ acheckerArgs,
229
+ {
230
+ stdio: 'pipe',
231
+ timeout: 30000 // stop after 30 seconds
232
+ }
233
+ )
234
+
235
+ if( stderr && stderr.toString() ){
236
+ console.log( stderr.toString() );
237
+ }
238
+
239
+ if( stdout && stdout.toString()){
240
+ let reportedFile = path.join(outputDir, originalFileName );
241
+ let reportedJSon = path.join(outputDir, originalJsonFileName );
242
+
243
+ // if output file name option was passed
244
+ if( outputFilename ){
245
+
246
+ reportedFile = path.join( outputDir, `${outputFilename}.html` );
247
+ reportedJSon = path.join( outputDir, `${outputFilename}.json` );
248
+
249
+ // rename the output files
250
+ fs.renameSync(path.join(outputDir, originalFileName), reportedFile );
251
+ fs.renameSync(path.join(outputDir, originalJsonFileName), reportedJSon );
252
+
253
+ // delete any empty directories.
254
+ fs.rmSync( path.join(outputDir, originalFileName.split(path.sep).shift()), {recursive: true} )
255
+ }
256
+
257
+ if( 'a11y' === process.argv[2] ){
258
+ console.log( reportedFile )
259
+ }else{
260
+ return reportedFile;
261
+ }
262
+ }
263
+ }else{
264
+ console.log( `${url} is not a valid url.` )
265
+ }
266
+
267
+ } // end of a11yCheck
268
+
269
+ } // end of class
270
+
271
+
272
+ export default A11yPlugin;
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "@caweb/a11y-webpack-plugin",
3
+ "version": "1.0.0",
4
+ "description": "Webpack Plugin to run Accessibility Scans",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 0"
9
+ },
10
+ "author": "Danny Guzman",
11
+ "license": "ISC"
12
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+
5
+ module.exports = {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+
5
+ export default {
6
+ format: 'html',
7
+ filename: 'css-audit',
8
+ colors: true,
9
+ important: true,
10
+ displayNone: true,
11
+ selectors: true,
12
+ mediaQueries: true,
13
+ typography: true,
14
+ propertyValues: [
15
+ 'font-size',
16
+ 'padding,padding-top,padding-bottom,padding-right,padding-left' ,
17
+ 'property-values', 'margin,margin-top,marin-bottom,marin-right,marin-left',
18
+ ]
19
+ };
@@ -0,0 +1,297 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * External dependencies
5
+ */
6
+ import { sync as resolveBin } from 'resolve-bin';
7
+ import spawn from 'cross-spawn';
8
+ import { getAllFilesSync } from 'get-all-files'
9
+ import EntryDependency from "webpack/lib/dependencies/EntryDependency.js";
10
+
11
+ import path from 'path';
12
+ import fs, { stat } from 'fs';
13
+ import deepmerge from 'deepmerge';
14
+ import chalk from 'chalk';
15
+ import { fileURLToPath, URL } from 'url';
16
+
17
+ // default configuration
18
+ import {default as DefaultConfig} from './default.config.js';
19
+
20
+ const boldWhite = chalk.bold.white;
21
+ const boldGreen = chalk.bold.green;
22
+ const boldBlue = chalk.bold.hex('#03a7fc');
23
+ const currentPath = path.dirname(fileURLToPath(import.meta.url));
24
+
25
+ // CSS Audit Plugin
26
+ class CSSAuditPlugin {
27
+ config = {}
28
+
29
+ constructor(opts = {}) {
30
+ this.config = deepmerge(DefaultConfig, opts);
31
+ }
32
+
33
+ apply(compiler) {
34
+ const staticDir = {
35
+ directory: path.join(path.resolve(currentPath, '../../../../'), 'bin', 'css-audit', 'public'),
36
+ watch: true
37
+ }
38
+ let { devServer, output } = compiler.options;
39
+ let hostUrl = 'localhost' === devServer.host ? `http://${devServer.host}`: devServer.host;
40
+ let hostPort = devServer.port;
41
+
42
+ if( hostPort && 80 !== hostPort )
43
+ {
44
+ hostUrl = `${hostUrl}:${hostPort}`;
45
+ }
46
+
47
+ // if dev server allows for multiple pages to be opened
48
+ // add css-audit.html to open property.
49
+ if( Array.isArray(devServer.open) ){
50
+ devServer.open.push(`${hostUrl}/${this.config.rewrite ? this.config.rewrite : this.config.filename}.html`)
51
+ }else if( 'object' === typeof devServer.open && Array.isArray(devServer.open.target) ){
52
+ devServer.open.target.push(`${hostUrl}/${this.config.filename}.html`)
53
+ }
54
+
55
+ // add our static directory
56
+ if( Array.isArray(devServer.static) ){
57
+ devServer.static.push(staticDir)
58
+ }else{
59
+ devServer.static = [].concat(devServer.static, staticDir );
60
+ }
61
+
62
+
63
+ // Wait for configuration preset plugins to apply all configure webpack defaults
64
+ compiler.hooks.initialize.tap('CSS Audit Plugin', () => {
65
+ compiler.hooks.compilation.tap(
66
+ "CSS Audit Plugin",
67
+ (compilation, { normalModuleFactory }) => {
68
+ compilation.dependencyFactories.set(
69
+ EntryDependency,
70
+ normalModuleFactory
71
+ );
72
+ }
73
+ );
74
+
75
+ const { entry, options, context } = {
76
+ entry: path.join(staticDir.directory, 'css-audit.update.js'),
77
+ options: {
78
+ name: 'css-audit.update'
79
+ },
80
+ context: staticDir.directory
81
+ };
82
+
83
+ const dep = new EntryDependency(entry);
84
+ dep.loc = {
85
+ name: options.name
86
+ };
87
+
88
+ fs.writeFileSync(
89
+ path.join(staticDir.directory, `css-audit.update.js`),
90
+ `` // required for hot-update to compile on our page, blank script for now
91
+ );
92
+
93
+ compiler.hooks.thisCompilation.tap('CSS Audit Plugin',
94
+ /**
95
+ * Hook into the webpack compilation
96
+ * @param {Compilation} compilation
97
+ */
98
+ (compilation) => {
99
+
100
+ compiler.hooks.make.tapAsync("CSS Audit Plugin", (compilation, callback) => {
101
+
102
+ compilation.addEntry(
103
+ context,
104
+ dep,
105
+ options,
106
+ err => {
107
+ callback(err);
108
+ });
109
+ });
110
+
111
+ // process assets and run the css-audit on appropriate assets.
112
+ compilation.hooks.processAssets.tapAsync(
113
+ {
114
+ name: 'CSS Audit Plugin',
115
+ stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL
116
+ },
117
+ /**
118
+ * Hook into the process assets hook
119
+ * @param {any} _
120
+ * @param {(err?: Error) => void} callback
121
+ */
122
+ (assets, callback) => {
123
+ let files = [];
124
+
125
+ Object.entries(assets).forEach(([pathname, source]) => {
126
+ if( pathname.endsWith('.js') ){
127
+ if( source['_source'] && source['_source']['_children'] ){
128
+ source['_source']['_children'].forEach((s, i) => {
129
+ if(
130
+ 'string' === typeof s && // is a string and
131
+ 0 < s.indexOf('.css') && // has a .css reference and
132
+ 0 > s.indexOf('node_modules') // not referencing node_modules directory
133
+ ){
134
+ files.push( path.resolve(s.replace(/[\n\s\S\w]*"(.*)"[\n\s\S\w]*/, '$1')) )
135
+ }
136
+ })
137
+ }
138
+ }
139
+ })
140
+ console.log(`<i> ${boldGreen('[webpack-dev-middleware] Running CSS Audit...')}`);
141
+
142
+ this.audit(files, this.config );
143
+
144
+ // we have to inject the css-audit.update.js file into the head in order for the webpack-dev-server scripts to load.
145
+ let pageContent = fs.readFileSync(path.join(staticDir.directory, `${this.config.filename}.html`))
146
+
147
+ fs.writeFileSync(
148
+ path.join(staticDir.directory, `${this.config.filename}.html`),
149
+ pageContent.toString().replace('</head>', '<script src="/css-audit.update.js"></script>\n</head>')
150
+ )
151
+
152
+ console.log(`<i> ${boldGreen('[webpack-dev-middleware] CSS Audit can be viewed at')} ${ boldBlue(new URL(`${hostUrl}/${this.config.filename}.html`).toString()) }`);
153
+
154
+ callback();
155
+ });
156
+
157
+
158
+ compiler.hooks.watchClose.tap( 'CSS Audit Plugin', () => {
159
+ getAllFilesSync(compiler.options.output.path).toArray().forEach(f => {
160
+ if(
161
+ f.includes('css-audit') || // delete any css-audit files
162
+ f.includes('.hot-update.js') // delete any HMR files
163
+ ){
164
+ fs.rmSync(f)
165
+ }
166
+ })
167
+ })
168
+ });
169
+
170
+ });
171
+
172
+ }
173
+
174
+ /**
175
+ * Run CSS Auditor
176
+ *
177
+ * @param {Array} files
178
+ * @param {Object} options
179
+ * @param {boolean} options.debug
180
+ * @param {boolean} options.format
181
+ * @param {boolean} options.filename
182
+ * @param {boolean} options.colors
183
+ * @param {boolean} options.important
184
+ * @param {boolean} options.displayNone
185
+ * @param {boolean} options.selectors
186
+ * @param {boolean} options.mediaQueries
187
+ * @param {boolean} options.typography
188
+ * @param {Array} options.propertyValues
189
+ */
190
+ audit(files, {
191
+ debug,
192
+ format,
193
+ filename,
194
+ colors,
195
+ important,
196
+ displayNone,
197
+ selectors,
198
+ mediaQueries,
199
+ typography,
200
+ propertyValues
201
+ }){
202
+
203
+
204
+ let filesToBeAuditted = [];
205
+ let filesWithIssues = [];
206
+
207
+ files.forEach( (paths, i) => {
208
+ let resolvePath = path.resolve(paths);
209
+
210
+ try {
211
+ // if given path is a directory
212
+ if( fs.statSync(resolvePath).isDirectory() ){
213
+
214
+ // get all .css files
215
+ getAllFilesSync(resolvePath).toArray().forEach(f => {
216
+ if( f.endsWith('.css') ){
217
+ filesToBeAuditted.push(f)
218
+ }
219
+ })
220
+ // if given path is a file and a .css file
221
+ }else if( fs.statSync(paths).isFile() && paths.endsWith('.css') ){
222
+ filesToBeAuditted.push(paths)
223
+ }
224
+ // invalid path/file
225
+ } catch (error) {
226
+ filesWithIssues.push(paths)
227
+ }
228
+
229
+ });
230
+
231
+ if( ! filesToBeAuditted.length ){
232
+ console.log('No file(s) or directory path(s) were given or default directory was not found.')
233
+ console.log('Auditor did not execute.');
234
+ return
235
+ }
236
+
237
+ /**
238
+ * the css audit uses the filename for the title, rather than the project name
239
+ * we fix that by passing the project name for the file name
240
+ * then renaming the file to the intended file name.
241
+ */
242
+ let auditArgs = [
243
+ colors ? '--colors' : '',
244
+ important ? '--important' : '',
245
+ displayNone ? '--display-none' : '',
246
+ selectors ? '--selectors' : '',
247
+ mediaQueries ? '--media-queries' : '',
248
+ typography ? '--typography' : '',
249
+ format ? `--format=${format}` : '',
250
+ filename ? `--filename=${path.basename(process.cwd())}` : ''
251
+ ].filter( e => e)
252
+
253
+ if( propertyValues ){
254
+ propertyValues.forEach((p) => {
255
+ auditArgs.push(`--property-values=${p.replace(' ',',')}`)
256
+ })
257
+ }
258
+
259
+
260
+ let { stdout, stderr } = spawn.sync(
261
+ 'node ' + resolveBin('@caweb/cli', {executable: 'auditor'}),
262
+ [
263
+ ...filesToBeAuditted,
264
+ ...auditArgs
265
+ ],
266
+ {
267
+ stdio: 'pipe',
268
+ cwd: fs.existsSync(path.join(process.cwd(), 'css-audit.config.cjs')) ? process.cwd() : currentPath
269
+ }
270
+ )
271
+
272
+ if( stderr && stderr.toString() ){
273
+ console.log( stderr.toString())
274
+ }
275
+ if( stdout ){
276
+ // rename the file back to the intended file name instead of the project name
277
+ fs.renameSync(
278
+ path.join(path.resolve(currentPath, '../../../../'), 'bin', 'css-audit', 'public', `${path.basename(process.cwd())}.html`),
279
+ path.join(path.resolve(currentPath, '../../../../'), 'bin', 'css-audit', 'public', `${filename}.html`)
280
+ )
281
+
282
+ let msg = stdout.toString().replace('undefined', '');
283
+
284
+ if( 'audit' === process.argv[2] ){
285
+ console.log( msg )
286
+ }else{
287
+ return msg;
288
+ }
289
+
290
+ }
291
+
292
+ } // end of audit
293
+
294
+ } // end of class
295
+
296
+
297
+ export default CSSAuditPlugin;
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "@caweb/css-audit-webpack-plugin",
3
+ "version": "1.0.0",
4
+ "description": "Webpack Plugin to run WordPress CSS Audit",
5
+ "type": "module",
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "test": "echo \"Error: no test specified\" && exit 0"
9
+ },
10
+ "author": "Danny Guzman",
11
+ "license": "ISC"
12
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "boss": true,
3
+ "curly": true,
4
+ "eqeqeq": true,
5
+ "eqnull": true,
6
+ "esversion": 6,
7
+ "expr": true,
8
+ "immed": true,
9
+ "noarg": true,
10
+ "nonbsp": true,
11
+ "quotmark": "single",
12
+ "undef": true,
13
+ "unused": true,
14
+
15
+ "browser": true,
16
+
17
+ "globals": {
18
+ "_": false,
19
+ "Backbone": false,
20
+ "jQuery": false,
21
+ "JSON": false,
22
+ "wp": false,
23
+ "export": false,
24
+ "module": false,
25
+ "require": false,
26
+ "WorkerGlobalScope": false,
27
+ "self": false,
28
+ "OffscreenCanvas": false,
29
+ "Promise": false
30
+ }
31
+ }