Skip to content

Commit e3a5e19

Browse files
committed
Refactor code
* move most code outside of lib/htmllint.js * rename a few variables and methods to be more descriptive * return early in parseErrorMessages
1 parent a4f56c3 commit e3a5e19

8 files changed

Lines changed: 133 additions & 108 deletions

File tree

Gruntfile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict';
22

3-
module.exports = function(grunt) {
3+
module.exports = grunt => {
44
require('time-grunt')(grunt);
55

66
grunt.initConfig({

lib/htmllint.js

Lines changed: 10 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -4,125 +4,32 @@ const os = require('os');
44
const path = require('path');
55
const { execFile } = require('child_process');
66
const async = require('async');
7-
const jar = require('vnu-jar');
87
const chunkify = require('./chunkify.js');
9-
const javadetect = require('./javadetect.js');
8+
const javaDetect = require('./javaDetect.js');
9+
const javaArgs = require('./javaArgs.js');
10+
const parseErrorMessages = require('./parseErrorMessages.js');
11+
const processErrorMessages = require('./processErrorMessages.js');
1012

1113
// chunkify's max characters
1214
const MAX_CHARS = 5000;
1315

14-
// Increase child process buffer to accommodate large amounts of
15-
// validation output. (the default is a paltry 200k)
16-
// https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
16+
/**
17+
* Increase child process buffer to accommodate large amounts of validation output.
18+
* The default is a paltry 200k:
19+
* https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
20+
*/
1721
const MAX_BUFFER = 20_000 * 1024;
1822

1923
// eslint-disable-next-line unicorn/explicit-length-check
2024
const CPUS = os.cpus() && os.cpus().length;
2125
const THREADS = CPUS > 2 ? CPUS - 1 : 1;
2226

23-
// Replace left/right quotation marks with normal quotation marks
24-
function normalizeQuotationMarks(string) {
25-
if (string) {
26-
string = string.replace(/[\u201C\u201D]/g, '"');
27-
}
28-
29-
return string;
30-
}
31-
32-
// Parse and, if needed, normalize error messages from HttpClient to java -jar format
33-
// java -jar: one object containing messages for all files
34-
// { messages: [{ message, type, url, ... }, ...] }
35-
// HttpClient: one object per file, separated by a newline,
36-
// each object containing messages for only that file
37-
// { messages: [{ message, type, ...}, ...], url }\n{ ... }
38-
function parseErrorMessages(errors, config) {
39-
const parsed = JSON.parse(config.server ? `[${errors.trim().replace(/\n/g, ',')}]` : errors);
40-
let { messages } = parsed;
41-
42-
if (config.server) {
43-
// Extract "messages" property from each object and set the url of each message.
44-
// This results in an array of arrays instead of array of objects, which is then
45-
// flattened
46-
messages = parsed.flatMap(file => {
47-
return file.messages.map(message => {
48-
message.url = file.url;
49-
return message;
50-
});
51-
});
52-
}
53-
54-
return messages;
55-
}
56-
57-
function processErrorMessages(errors, config) {
58-
const result = errors.map(message => {
59-
if (message.url) {
60-
message.file = path.relative('.', message.url.replace(path.sep === '\\' ? 'file:/' : 'file:', ''));
61-
}
62-
63-
if (config.absoluteFilePathsForReporter) {
64-
message.file = path.resolve(message.file);
65-
}
66-
67-
return message;
68-
});
69-
70-
if (!config.ignore) {
71-
return result;
72-
}
73-
74-
const ignore = Array.isArray(config.ignore) ? config.ignore : [config.ignore];
75-
76-
return result.filter(({ message }) => {
77-
// Iterate over the ignore rules and test the message against each rule.
78-
// A match should return false, which causes every() to return false and
79-
// the message to be filtered out.
80-
return ignore.every(
81-
currentValue => currentValue instanceof RegExp ?
82-
!currentValue.test(message) :
83-
normalizeQuotationMarks(currentValue) !== normalizeQuotationMarks(message)
84-
);
85-
});
86-
}
87-
88-
// Determine proper jarfile arguments
89-
function javaArgs(java, chunk, config) {
90-
const args = [];
91-
92-
// Increase the default stack size for ia32 versions
93-
if (java.arch === 'ia32') {
94-
args.push('-Xss512k');
95-
}
96-
97-
args.push(config.server ? '-cp' : '-jar', `"${jar}"`);
98-
99-
if (config.server) {
100-
if (config.server.host) {
101-
args.push(`-Dnu.validator.client.host=${config.server.host}`);
102-
}
103-
104-
if (config.server.port) {
105-
args.push(`-Dnu.validator.client.port=${config.server.port}`);
106-
}
107-
108-
args.push('-Dnu.validator.client.out=json nu.validator.client.HttpClient');
109-
} else {
110-
args.push('--format', 'json');
111-
}
112-
113-
if (config.noLangDetect) {
114-
args.push('--no-langdetect');
115-
}
116-
117-
return [...args, chunk];
118-
}
119-
12027
function htmllint(config, done) {
12128
if (config.files.length === 0) {
12229
return done(null, []);
12330
}
12431

125-
javadetect((err, java) => {
32+
javaDetect((err, java) => {
12633
if (err) {
12734
throw err;
12835
}

lib/javaArgs.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
'use strict';
2+
3+
const jar = require('vnu-jar');
4+
5+
// Determine proper jarfile arguments
6+
function javaArgs(java, chunk, config) {
7+
const args = [];
8+
9+
// Increase the default stack size for ia32 versions
10+
if (java.arch === 'ia32') {
11+
args.push('-Xss512k');
12+
}
13+
14+
args.push(config.server ? '-cp' : '-jar', `"${jar}"`);
15+
16+
if (config.server) {
17+
if (config.server.host) {
18+
args.push(`-Dnu.validator.client.host=${config.server.host}`);
19+
}
20+
21+
if (config.server.port) {
22+
args.push(`-Dnu.validator.client.port=${config.server.port}`);
23+
}
24+
25+
args.push('-Dnu.validator.client.out=json nu.validator.client.HttpClient');
26+
} else {
27+
args.push('--format', 'json');
28+
}
29+
30+
if (config.noLangDetect) {
31+
args.push('--no-langdetect');
32+
}
33+
34+
return [...args, chunk];
35+
}
36+
37+
module.exports = javaArgs;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const { execFile } = require('child_process');
44

5-
function javadetect(callback) {
5+
function javaDetect(callback) {
66
execFile('java', ['-version'], (error, stdout, stderr) => {
77
if (error) {
88
return callback(error);
@@ -15,4 +15,4 @@ function javadetect(callback) {
1515
});
1616
}
1717

18-
module.exports = javadetect;
18+
module.exports = javaDetect;

lib/parseErrorMessages.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
'use strict';
2+
3+
/**
4+
* Parse and, if needed, normalize error messages from HttpClient to java -jar format
5+
* java -jar: one object containing messages for all files
6+
* { messages: [{ message, type, url, ... }, ...] }
7+
* HttpClient: one object per file, separated by a newline,
8+
* each object containing messages for only that file
9+
* { messages: [{ message, type, ...}, ...], url }\n{ ... }
10+
*/
11+
function parseErrorMessages(errors, config) {
12+
const normalizedErrors = config.server ? `[${errors.trim().replace(/\n/g, ',')}]` : errors;
13+
const parsedErrors = JSON.parse(normalizedErrors);
14+
15+
// If server is not used, return the messages as is
16+
if (!config.server) {
17+
return parsedErrors.messages;
18+
}
19+
20+
// Extract the "messages" property from each object and set the url of each message.
21+
// This results in an array of arrays instead of array of objects, which is then flattened.
22+
return parsedErrors.flatMap(file => {
23+
return file.messages.map(message => {
24+
message.url = file.url;
25+
return message;
26+
});
27+
});
28+
}
29+
30+
module.exports = parseErrorMessages;

lib/processErrorMessages.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use strict';
2+
3+
const path = require('path');
4+
const { normalizeQuotationMarks } = require('./util.js');
5+
6+
const processedMessages = (errors, config) => {
7+
return errors.map(message => {
8+
if (message.url) {
9+
message.file = path.relative('.', message.url.replace(path.sep === '\\' ? 'file:/' : 'file:', ''));
10+
}
11+
12+
if (config.absoluteFilePathsForReporter) {
13+
message.file = path.resolve(message.file);
14+
}
15+
16+
return message;
17+
});
18+
};
19+
20+
function processErrorMessages(errors, config) {
21+
const messages = processedMessages(errors, config);
22+
23+
if (!config.ignore) {
24+
return messages;
25+
}
26+
27+
const ignore = Array.isArray(config.ignore) ? config.ignore : [config.ignore];
28+
29+
// Iterate over the ignore rules and test the message against each rule.
30+
// A match should return false, which causes every() to return false and
31+
// the message to be filtered out.
32+
return messages.filter(({ message }) => {
33+
return ignore.every(
34+
currentValue => currentValue instanceof RegExp ?
35+
!currentValue.test(message) :
36+
normalizeQuotationMarks(currentValue) !== normalizeQuotationMarks(message)
37+
);
38+
});
39+
}
40+
41+
module.exports = processErrorMessages;

lib/util.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ function encode(string) {
1818
return string || '';
1919
}
2020

21+
// Replace left/right quotation marks with normal quotation marks
22+
function normalizeQuotationMarks(string) {
23+
if (string) {
24+
string = string.replace(/[\u201C\u201D]/g, '"');
25+
}
26+
27+
return string;
28+
}
29+
2130
module.exports = {
22-
encode
31+
encode,
32+
normalizeQuotationMarks
2333
};

tasks/html.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const path = require('path');
1212
const htmllint = require('../lib/htmllint.js');
1313
const reporters = require('../lib/reporters.js');
1414

15-
module.exports = function(grunt) {
15+
module.exports = grunt => {
1616
grunt.registerMultiTask('htmllint', 'Validate html files', function() {
1717
const done = this.async();
1818
const files = grunt.file.expand(this.filesSrc);

0 commit comments

Comments
 (0)