44// MIT License
55
66// Imports
7- import color from 'ansi-colors' ;
87import PluginError from 'plugin-error' ;
9- import log from 'fancy-log' ;
108import through2 from 'through2' ;
119import { w3cHtmlValidator } from 'w3c-html-validator' ;
1210
@@ -16,99 +14,35 @@ const pluginName = 'gulp-w3c-html-validator';
1614// Gulp plugin
1715const htmlValidator = {
1816
19- handleMessages ( file ) {
20- const text = {
21- error : color . red . bold ( 'HTML Error:' ) ,
22- info : color . yellow . bold ( 'HTML Warning:' ) ,
23- } ;
24- const lines = file . contents . toString ( ) . split ( / \r \n | \r | \n / g) ;
25- const processMessage = ( message ) => {
26- // Example message object:
27- // {
28- // type: 'error',
29- // message: 'Unclosed element “h1”.',
30- // extract: '<body>\n <h1>Specif',
31- // lastLine: 8,
32- // firstColumn: 4,
33- // lastColumn: 7,
34- // hiliteStart: 10,
35- // hiliteLength: 4,
36- // }
37- // See: https://github.com/validator/validator/wiki/Output-»-JSON#example
38- const type = text [ message . type ] || color . cyan . bold ( 'HTML Comment:' ) ;
39- const line = message . lastLine || 0 ;
40- const column = message . lastColumn || 0 ;
41- const location = 'Line ' + line + ', Column ' + column + ':' ;
42- let erroredLine = lines [ line - 1 ] ;
43- let errorColumn = message . lastColumn ;
44- const trimErrorLength = ( ) => {
45- erroredLine = erroredLine . slice ( errorColumn - 50 ) ;
46- errorColumn = 50 ;
47- } ;
48- const formatErroredLine = ( ) => {
49- if ( errorColumn > 60 )
50- trimErrorLength ( ) ;
51- erroredLine = erroredLine . slice ( 0 , 60 ) ; //trim after so the line is not too long
52- erroredLine = //highlight character with error
53- color . gray ( erroredLine . substring ( 0 , errorColumn - 1 ) ) +
54- color . red . bold ( erroredLine [ errorColumn - 1 ] ) +
55- color . gray ( erroredLine . substring ( errorColumn ) ) ;
56- } ;
57- if ( erroredLine ) //if false, stream was changed since validation
58- formatErroredLine ( ) ;
59- if ( typeof message . lastLine !== 'undefined' || typeof lastColumn !== 'undefined' )
60- log ( type , file . relative , location , message . message ) ;
61- else
62- log ( type , file . relative , message . message ) ;
63- if ( erroredLine )
64- log ( erroredLine ) ;
65- } ;
66- if ( ! file . validationResults || ! Array . isArray ( file . validationResults . messages ) )
67- log ( text . warning , 'Failed to run validation on' , file . relative ) ;
68- else
69- file . validationResults . messages . forEach ( processMessage ) ;
70- } ,
71-
7217 analyzer ( options ) {
73- const defaults = { proxy : null , skipWarnings : false , url : null , verifyMessage : null } ;
74- const settings = { ...defaults , ...options } ;
75- if ( settings . proxy )
76- throw Error ( 'The "proxy" option is not supported at this time.' ) ;
77- const transform = ( file , encoding , done ) => {
18+ const validate = ( file , encoding , done ) => {
7819 const handleValidation = ( results ) => {
79- const worthy = ( message ) => ! ( settings . skipWarnings && message . type === 'info' ) &&
80- ! ( settings . verifyMessage && ! settings . verifyMessage ( message . type , message . message ) ) ;
81- const filteredMessages = results . messages . filter ( worthy ) ;
82- file . validationResults = {
83- success : ! filteredMessages . length ,
84- messages : filteredMessages ,
85- unfiltered : results . messages ,
86- } ;
87- htmlValidator . handleMessages ( file ) ;
20+ file . w3cHtmlValidator = results ;
8821 done ( null , file ) ;
8922 } ;
90- const validatorOptions = { html : file . contents } ;
91- if ( typeof settings . url === 'string' )
92- validatorOptions . checkUrl = settings . url ;
23+ const validatorOptions = { ...options , ...{ html : file . contents . toString ( ) } } ;
9324 if ( file . isNull ( ) )
9425 done ( null , file ) ;
9526 else if ( file . isStream ( ) )
9627 done ( new PluginError ( pluginName , 'Streaming not supported' ) ) ;
9728 else
98- w3cHtmlValidator . validate ( { html : file . contents } ) . then ( handleValidation ) ;
29+ w3cHtmlValidator . validate ( validatorOptions ) . then ( handleValidation ) ;
9930 } ;
100- return through2 . obj ( transform ) ;
31+ return through2 . obj ( validate ) ;
10132 } ,
10233
10334 reporter ( options ) {
104- const defaults = { throwErrors : false } ;
35+ const defaults = { maxMessageLen : null , throwErrors : false } ;
10536 const settings = { ...defaults , ...options } ;
106- const transform = ( file , encoding , done ) => {
37+ const report = ( file , encoding , done ) => {
38+ const options = { title : file . path , maxMessageLen : settings . maxMessageLen } ;
39+ if ( file . w3cHtmlValidator )
40+ w3cHtmlValidator . reporter ( file . w3cHtmlValidator , options ) ;
10741 done ( null , file ) ;
108- if ( settings . throwErrors && file . validationResults && ! file . validationResults . success )
42+ if ( settings . throwErrors && file . w3cHtmlValidator && ! file . w3cHtmlValidator . validates )
10943 throw new PluginError ( pluginName , 'HTML validation failed' ) ;
11044 } ;
111- return through2 . obj ( transform ) ;
45+ return through2 . obj ( report ) ;
11246 } ,
11347
11448 } ;
0 commit comments