Socket
Socket
Sign inDemoInstall

grunt-banana-checker

Package Overview
Dependencies
Maintainers
26
Versions
18
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

grunt-banana-checker - npm Package Compare versions

Comparing version 0.11.1 to 0.12.0

10

package.json
{
"name": "grunt-banana-checker",
"version": "0.11.1",
"version": "0.12.0",
"description": "Checker for the 'Banana' JSON-file format for interface messages, as used by MediaWiki and jQuery.i18n.",

@@ -28,8 +28,8 @@ "repository": {

"engines": {
"node": ">=8"
"node": ">=16"
},
"devDependencies": {
"eslint-config-wikimedia": "0.25.0",
"nyc": "15.1.0",
"grunt": "1.6.1"
"eslint-config-wikimedia": "0.27.0",
"grunt": "1.6.1",
"nyc": "15.1.0"
},

@@ -36,0 +36,0 @@ "scripts": {

@@ -118,2 +118,11 @@ # banana-checker

#### autofix
Type: `boolean`
Default value: `false`
If enabled, try to automatically fix issues detected by some checks.
Note that autofixing will not affect the check result - the checker will fail
even if all errors were automatically fixed.
#### sourceFile

@@ -120,0 +129,0 @@ Type: `string`

@@ -42,8 +42,10 @@ 'use strict';

skipIncompleteMessageDocumentation: []
skipIncompleteMessageDocumentation: [],
autofix: false
}, options );
const jsonFilenameRegex = /(.*)\.json$/;
const leadingWhitespaceRegex = /^\s/;
const trailingWhitespaceRegex = /\s$/;
const leadingWhitespaceRegex = /^\s+/;
const trailingWhitespaceRegex = /\s+$/;

@@ -59,3 +61,3 @@ const translatedData = {};

} catch ( e ) {
logErr( `Loading ${type} messages failed: "${e}".` );
logErr( `Loading ${ type } messages failed: "${ e }".` );
ok = false;

@@ -75,3 +77,3 @@ throw e;

if ( options.requireMetadata ) {
logErr( `No metadata block in the ${type} messages file.` );
logErr( `No metadata block in the ${ type } messages file.` );
ok = false;

@@ -86,5 +88,14 @@ }

function writeFile( filename, messageData ) {
// eslint-disable-next-line security/detect-non-literal-fs-filename
fs.writeFileSync(
path.resolve( dir, filename ),
JSON.stringify( messageData, null, '\t' ) + '\n'
);
}
// Source message data
const sourceMessages = messages( options.sourceFile, 'source' );
const sourceMessageKeys = keysNoMetadata( sourceMessages, 'source' );
let sourceMessagesModified = false;

@@ -94,2 +105,3 @@ // Documentation message data

const documentationMessageKeys = keysNoMetadata( documentationMessages, 'documentation' );
let documentationMessagesModified = false;

@@ -120,2 +132,3 @@ // Translated message data

let stack, originalParameters;
let modified = false;

@@ -162,4 +175,11 @@ for ( const index in keys ) {

leadingWhitespace = keys.filter( ( message ) =>
leadingWhitespaceRegex.test( sourceMessages[ message ] )
leadingWhitespaceRegex.test( languageMessages[ message ] )
);
if ( leadingWhitespace.length > 0 && options.autofix ) {
modified = true;
leadingWhitespace.forEach( ( message ) => {
languageMessages[ message ] = languageMessages[ message ].replace( leadingWhitespaceRegex, '' );
} );
}
}

@@ -169,4 +189,11 @@

trailingWhitespace = keys.filter( ( message ) =>
trailingWhitespaceRegex.test( sourceMessages[ message ] )
trailingWhitespaceRegex.test( languageMessages[ message ] )
);
if ( trailingWhitespace.length > 0 && options.autofix ) {
modified = true;
trailingWhitespace.forEach( ( message ) => {
languageMessages[ message ] = languageMessages[ message ].replace( trailingWhitespaceRegex, '' );
} );
}
}

@@ -176,6 +203,10 @@

missing = missing.filter( ( messageName ) =>
sourceMessages[ messageName ] !== ''
languageMessages[ messageName ] !== ''
);
}
if ( modified ) {
writeFile( languageFile, languageMessages );
}
translatedData[ language ] = {

@@ -223,2 +254,12 @@ messages: languageMessages,

);
if ( sourceMessageLeadingWhitespace.length > 0 && options.autofix ) {
sourceMessagesModified = true;
// This is modifying the sourceMessages object - from this point onward
// it's not always the exact same thing that was loaded from the source.
// This should be fine - we do want to run the lints on the messages we're
// writing to the file anyway.
sourceMessageLeadingWhitespace.forEach( ( message ) => {
sourceMessages[ message ] = sourceMessages[ message ].replace( leadingWhitespaceRegex, '' );
} );
}

@@ -228,2 +269,9 @@ documentationMessageLeadingWhitespace = documentationMessageKeys.filter(

);
if ( documentationMessageLeadingWhitespace.length > 0 && options.autofix ) {
documentationMessagesModified = true;
// We modify things here too - see the comment above.
documentationMessageLeadingWhitespace.forEach( ( message ) => {
documentationMessages[ message ] = documentationMessages[ message ].replace( leadingWhitespaceRegex, '' );
} );
}
}

@@ -237,2 +285,8 @@

);
if ( sourceMessageTrailingWhitespace.length > 0 && options.autofix ) {
sourceMessagesModified = true;
sourceMessageTrailingWhitespace.forEach( ( message ) => {
sourceMessages[ message ] = sourceMessages[ message ].replace( trailingWhitespaceRegex, '' );
} );
}

@@ -242,2 +296,8 @@ documentationMessageTrailingWhitespace = documentationMessageKeys.filter(

);
if ( documentationMessageTrailingWhitespace.length > 0 && options.autofix ) {
documentationMessagesModified = true;
documentationMessageTrailingWhitespace.forEach( ( message ) => {
documentationMessages[ message ] = documentationMessages[ message ].replace( trailingWhitespaceRegex, '' );
} );
}
}

@@ -265,2 +325,9 @@

if ( sourceMessagesModified ) {
writeFile( options.sourceFile, sourceMessages );
}
if ( documentationMessagesModified ) {
writeFile( options.documentationFile, documentationMessages );
}
// Step 3: Go through failures and report them, based on config.

@@ -278,6 +345,6 @@

logErr( `${count} message${( count > 1 ? 's lack' : ' lacks' )} documentation in qqq.json.` );
logErr( `${ count } message${ ( count > 1 ? 's lack' : ' lacks' ) } documentation in qqq.json.` );
sourceMessageMissing.forEach( ( messageName ) => {
logErr( `Message "${messageName}" lacks documentation in qqq.json.` );
logErr( `Message "${ messageName }" lacks documentation in qqq.json.` );
} );

@@ -292,6 +359,6 @@ }

logErr( `${count} documented message${( count > 1 ? 's are' : ' is' )} blank.` );
logErr( `${ count } documented message${ ( count > 1 ? 's are' : ' is' ) } blank.` );
documentationMessageBlanks.forEach( ( messageName ) => {
logErr( `Message "${messageName}" is documented with a blank string.` );
logErr( `Message "${ messageName }" is documented with a blank string.` );
} );

@@ -307,12 +374,12 @@ }

if ( options.requireLowerCase === 'initial' ) {
logErr( `${count} message${( count > 1 ? 's do' : ' does' )} not start with a lowercase character.` );
logErr( `${ count } message${ ( count > 1 ? 's do' : ' does' ) } not start with a lowercase character.` );
sourceMessageWrongCase.forEach( ( messageName ) => {
logErr( `Message "${messageName}" should start with a lowercase character.` );
logErr( `Message "${ messageName }" should start with a lowercase character.` );
} );
} else {
logErr( `${count} message${( count > 1 ? 's are' : ' is' )} not wholly lowercase.` );
logErr( `${ count } message${ ( count > 1 ? 's are' : ' is' ) } not wholly lowercase.` );
sourceMessageWrongCase.forEach( ( messageName ) => {
logErr( `Message "${messageName}" should be in lowercase.` );
logErr( `Message "${ messageName }" should be in lowercase.` );
} );

@@ -329,12 +396,12 @@ }

if ( options.requireKeyPrefix.length === 1 ) {
logErr( `${count} message${( count > 1 ? 's do' : ' does' )} not start with the required prefix "${options.requireKeyPrefix[ 0 ]}".` );
logErr( `${ count } message${ ( count > 1 ? 's do' : ' does' ) } not start with the required prefix "${ options.requireKeyPrefix[ 0 ] }".` );
sourceMessageWrongPrefix.forEach( ( messageName ) => {
logErr( `Message "${messageName}" should start with the required prefix "${options.requireKeyPrefix[ 0 ]}".` );
logErr( `Message "${ messageName }" should start with the required prefix "${ options.requireKeyPrefix[ 0 ] }".` );
} );
} else {
logErr( `${count} message${( count > 1 ? 's do' : ' does' )} not start with any of the required prefices.'` );
logErr( `${ count } message${ ( count > 1 ? 's do' : ' does' ) } not start with any of the required prefices.'` );
sourceMessageWrongPrefix.forEach( ( messageName ) => {
logErr( `Message "${messageName}" should start with one of the required prefices.` );
logErr( `Message "${ messageName }" should start with one of the required prefices.` );
} );

@@ -350,6 +417,6 @@ }

logErr( `${count} documented message${( count > 1 ? 's are' : ' is' )} undefined.` );
logErr( `${ count } documented message${ ( count > 1 ? 's are' : ' is' ) } undefined.` );
documentationMessageKeys.forEach( ( messageName ) => {
logErr( `Message "${messageName}" is documented but undefined.` );
logErr( `Message "${ messageName }" is documented but undefined.` );
} );

@@ -363,5 +430,5 @@ }

ok = false;
logErr( `${count} message${( count > 1 ? 's have' : ' has' )} leading whitespace:` );
logErr( `${ count } message${ ( count > 1 ? 's have' : ' has' ) } leading whitespace:` );
sourceMessageLeadingWhitespace.forEach( ( message ) => {
logErr( `Message "${message}" has leading whitespace` );
logErr( `Message "${ message }" has leading whitespace` );
} );

@@ -373,5 +440,5 @@ }

ok = false;
logErr( `${count} message documentation${( count > 1 ? 's have' : ' has' )} leading whitespace:` );
logErr( `${ count } message documentation${ ( count > 1 ? 's have' : ' has' ) } leading whitespace:` );
documentationMessageLeadingWhitespace.forEach( ( message ) => {
logErr( `Message documentation "${message}" has leading whitespace` );
logErr( `Message documentation "${ message }" has leading whitespace` );
} );

@@ -385,5 +452,5 @@ }

ok = false;
logErr( `${count} message${( count > 1 ? 's have' : ' has' )} trailing whitespace:` );
logErr( `${ count } message${ ( count > 1 ? 's have' : ' has' ) } trailing whitespace:` );
sourceMessageTrailingWhitespace.forEach( ( message ) => {
logErr( `Message "${message}" has trailing whitespace` );
logErr( `Message "${ message }" has trailing whitespace` );
} );

@@ -395,5 +462,5 @@ }

ok = false;
logErr( `${count} message documentation${( count > 1 ? 's have' : ' has' )} trailing whitespace:` );
logErr( `${ count } message documentation${ ( count > 1 ? 's have' : ' has' ) } trailing whitespace:` );
documentationMessageTrailingWhitespace.forEach( ( message ) => {
logErr( `Message documentation "${message}" has trailing whitespace` );
logErr( `Message documentation "${ message }" has trailing whitespace` );
} );

@@ -413,5 +480,5 @@ }

ok = false;
logErr( `The "${index}" translation has ${count} blank translation${( count > 1 ? 's' : '' )}:` );
logErr( `The "${ index }" translation has ${ count } blank translation${ ( count > 1 ? 's' : '' ) }:` );
translatedData[ index ].blank.forEach( ( messageName ) => {
logErr( `The translation of "${messageName}" is blank.` );
logErr( `The translation of "${ messageName }" is blank.` );
} );

@@ -425,5 +492,5 @@ }

ok = false;
logErr( `The "${index}" translation has ${count} duplicate translation${( count > 1 ? 's' : '' )}:` );
logErr( `The "${ index }" translation has ${ count } duplicate translation${ ( count > 1 ? 's' : '' ) }:` );
translatedData[ index ].duplicate.forEach( ( messageName ) => {
logErr( `The translation of "${messageName}" duplicates the primary message.` );
logErr( `The translation of "${ messageName }" duplicates the primary message.` );
} );

@@ -437,5 +504,5 @@ }

ok = false;
logErr( `The "${index}" translation has ${count} unused translation${( count > 1 ? 's' : '' )}:` );
logErr( `The "${ index }" translation has ${ count } unused translation${ ( count > 1 ? 's' : '' ) }:` );
translatedData[ index ].unused.forEach( ( messageName ) => {
logErr( `The translation of "${messageName}" is unused.` );
logErr( `The translation of "${ messageName }" is unused.` );
} );

@@ -449,3 +516,3 @@ }

ok = false;
logErr( `The "${index}" translation has ${count} message${( count > 1 ? 's' : '' )} which fail${( count > 1 ? 's' : '' )} to use all parameters:` );
logErr( `The "${ index }" translation has ${ count } message${ ( count > 1 ? 's' : '' ) } which fail${ ( count > 1 ? 's' : '' ) } to use all parameters:` );

@@ -455,9 +522,9 @@ translatedData[ index ].unusedParameters.forEach( ( report ) => {

case 1:
logErr( `The translation of "${report.message}" fails to use the parameter "${report.stack[ 0 ]}".` );
logErr( `The translation of "${ report.message }" fails to use the parameter "${ report.stack[ 0 ] }".` );
break;
case 2:
logErr( `The translation of "${report.message}" fails to use the parameters "${report.stack[ 0 ]}" and "${report.stack[ 1 ]}" .` );
logErr( `The translation of "${ report.message }" fails to use the parameters "${ report.stack[ 0 ] }" and "${ report.stack[ 1 ] }" .` );
break;
default:
logErr( `The translation of "${report.message}" fails to use the parameters "${report.stack.join( '", "' )}".` );
logErr( `The translation of "${ report.message }" fails to use the parameters "${ report.stack.join( '", "' ) }".` );
}

@@ -472,5 +539,5 @@ } );

ok = false;
logErr( `The "${index}" translation has ${count} translation${( count > 1 ? 's' : '' )} with leading whitespace:` );
logErr( `The "${ index }" translation has ${ count } translation${ ( count > 1 ? 's' : '' ) } with leading whitespace:` );
translatedData[ index ].leadingWhitespace.forEach( ( message ) => {
logErr( `The translation of "${message}" has leading whitespace.` );
logErr( `The translation of "${ message }" has leading whitespace.` );
} );

@@ -484,5 +551,5 @@ }

ok = false;
logErr( `The "${index}" translation has ${count} translation${( count > 1 ? 's' : '' )} with trailing whitespace:` );
logErr( `The "${ index }" translation has ${ count } translation${ ( count > 1 ? 's' : '' ) } with trailing whitespace:` );
translatedData[ index ].trailingWhitespace.forEach( ( message ) => {
logErr( `The translation of "${message}" has trailing whitespace.` );
logErr( `The translation of "${ message }" has trailing whitespace.` );
} );

@@ -506,6 +573,6 @@ }

ok = false;
logErr( `The "${index}" translation has ${count} missing translation${( count > 1 ? 's' : '' )}:` );
logErr( `The "${ index }" translation has ${ count } missing translation${ ( count > 1 ? 's' : '' ) }:` );
translatedData[ index ].missing.forEach( ( messageName ) => {
logErr( `The translation of "${messageName}" is missing.` );
logErr( `The translation of "${ messageName }" is missing.` );
} );

@@ -543,6 +610,6 @@ }

ok = false;
logErr( `The "${index}" translation is missing ${count} required message{( count > 1 ? 's' : '' )}:` );
logErr( `The "${ index }" translation is missing ${ count } required message{( count > 1 ? 's' : '' )}:` );
translatedData[ index ].missing.forEach( ( messageName ) => {
logErr( `The required message "${messageName}" is missing.` );
logErr( `The required message "${ messageName }" is missing.` );
} );

@@ -549,0 +616,0 @@ }

@@ -23,2 +23,3 @@ #!/usr/bin/env node

// Boolean options
case 'autofix':
case 'disallowBlankTranslations':

@@ -41,3 +42,3 @@ case 'disallowUnusedDocumentation':

} else {
console.error( `banana-check: Invalid option ignored, --${key}=${value}` );
console.error( `banana-check: Invalid option ignored, --${ key }=${ value }` );
}

@@ -54,3 +55,3 @@ break;

default:
console.error( `banana-check: Invalid option ignored, --${key}` );
console.error( `banana-check: Invalid option ignored, --${ key }` );
}

@@ -61,3 +62,3 @@ }

console.error( 'banana-check: Specify one or more directories.' );
// eslint-disable-next-line no-process-exit
// eslint-disable-next-line n/no-process-exit
process.exit( 1 );

@@ -67,14 +68,15 @@ }

const bananaChecker = require( '../src/banana.js' );
const result = dirs.every( ( dir ) => {
return bananaChecker(
let result = true;
dirs.forEach( ( dir ) => {
result = bananaChecker(
dir,
options,
console.error
);
) && result;
} );
if ( !result ) {
// eslint-disable-next-line no-process-exit
// eslint-disable-next-line n/no-process-exit
process.exit( 1 );
}
console.log( `Checked ${dirs.length} message director${( dirs.length > 1 ? 'ies' : 'y' )}.` );
console.log( `Checked ${ dirs.length } message director${ ( dirs.length > 1 ? 'ies' : 'y' ) }.` );

@@ -27,4 +27,4 @@ 'use strict';

grunt.log.ok( `${messageDirs} message director${( messageDirs > 1 ? 'ies' : 'y' )} checked.` );
grunt.log.ok( `${ messageDirs } message director${ ( messageDirs > 1 ? 'ies' : 'y' ) } checked.` );
} );
};
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc