2015-02-23 23:39:20 -08:00
"use strict" ;
2018-04-27 22:05:34 -07:00
const fs = require ( "fs" ) ;
const path = require ( "path" ) ;
const md = require ( "markdown-it" ) ( ) ;
const tv4 = require ( "tv4" ) ;
const markdownlint = require ( "../lib/markdownlint" ) ;
const shared = require ( "../lib/shared" ) ;
const rules = require ( "../lib/rules" ) ;
2018-07-20 22:31:41 -07:00
const customRules = require ( "./rules/rules.js" ) ;
2018-04-27 22:05:34 -07:00
const defaultConfig = require ( "./markdownlint-test-default-config.json" ) ;
const configSchema = require ( "../schema/markdownlint-config-schema.json" ) ;
2015-02-27 22:06:54 -08:00
2018-04-27 22:29:52 -07:00
function promisify ( func , ... args ) {
return new Promise ( ( resolve , reject ) => {
func ( ... args , ( error , result ) => {
if ( error ) {
return reject ( error ) ;
}
resolve ( result ) ;
} ) ;
} ) ;
}
2015-02-23 23:39:20 -08:00
function createTestForFile ( file ) {
2015-02-24 18:40:37 -08:00
return function testForFile ( test ) {
2015-03-01 22:15:02 -08:00
test . expect ( 1 ) ;
2018-04-27 22:05:34 -07:00
const detailedResults = /[/\\]detailed-results-/ . test ( file ) ;
const resultsFile = file . replace ( /\.md$/ , ".results.json" ) ;
const configFile = file . replace ( /\.md$/ , ".json" ) ;
2018-04-27 22:29:52 -07:00
const actualPromise = promisify ( fs . stat , configFile )
2015-03-01 22:15:02 -08:00
. then (
function configFileExists ( ) {
2018-04-27 22:29:52 -07:00
return promisify ( fs . readFile , configFile , shared . utf8Encoding )
2016-10-16 21:46:02 -07:00
. then ( JSON . parse ) ;
2015-03-01 22:15:02 -08:00
} ,
function noConfigFile ( ) {
2015-09-26 16:55:33 -07:00
return { } ;
2015-03-01 22:15:02 -08:00
} )
. then (
function lintWithConfig ( config ) {
2018-04-27 22:05:34 -07:00
const mergedConfig =
shared . assign ( shared . clone ( defaultConfig ) , config ) ;
2018-04-27 22:29:52 -07:00
return promisify ( markdownlint , {
2015-03-01 22:15:02 -08:00
"files" : [ file ] ,
2016-10-16 21:46:02 -07:00
"config" : mergedConfig ,
2018-01-12 23:21:06 -08:00
"resultVersion" : detailedResults ? 2 : 0
2015-03-01 22:15:02 -08:00
} ) ;
} ) ;
2018-04-27 22:05:34 -07:00
const expectedPromise = detailedResults ?
2018-04-27 22:29:52 -07:00
promisify ( fs . readFile , resultsFile , shared . utf8Encoding )
2016-10-16 21:46:02 -07:00
. then ( JSON . parse ) :
2018-04-27 22:29:52 -07:00
promisify ( fs . readFile , file , shared . utf8Encoding )
2016-10-16 21:46:02 -07:00
. then (
function fileContents ( contents ) {
2018-04-27 22:05:34 -07:00
const lines = contents . split ( shared . newLineRe ) ;
const results = { } ;
2016-10-16 21:46:02 -07:00
lines . forEach ( function forLine ( line , lineNum ) {
2018-04-27 22:05:34 -07:00
const regex = /\{(MD\d+)(?::(\d+))?\}/g ;
let match = null ;
2016-10-16 21:46:02 -07:00
while ( ( match = regex . exec ( line ) ) ) {
2018-04-27 22:05:34 -07:00
const rule = match [ 1 ] ;
const errors = results [ rule ] || [ ] ;
2016-10-16 21:46:02 -07:00
errors . push ( match [ 2 ] ? parseInt ( match [ 2 ] , 10 ) : lineNum + 1 ) ;
results [ rule ] = errors ;
}
} ) ;
2018-04-27 22:05:34 -07:00
const sortedResults = { } ;
2016-10-16 21:46:02 -07:00
Object . keys ( results ) . sort ( ) . forEach ( function forKey ( key ) {
sortedResults [ key ] = results [ key ] ;
} ) ;
return sortedResults ;
2015-03-17 18:02:05 -07:00
} ) ;
2018-04-27 22:29:52 -07:00
Promise . all ( [ actualPromise , expectedPromise ] )
2015-03-01 22:15:02 -08:00
. then (
function compareResults ( fulfillments ) {
2018-04-27 22:05:34 -07:00
const actual = fulfillments [ 0 ] ;
const results = fulfillments [ 1 ] ;
const expected = { } ;
2015-03-01 22:15:02 -08:00
expected [ file ] = results ;
test . deepEqual ( actual , expected , "Line numbers are not correct." ) ;
} )
2018-04-27 22:29:52 -07:00
. catch ( )
. then ( test . done ) ;
2015-02-23 23:39:20 -08:00
} ;
}
2015-03-20 00:09:55 -07:00
fs . readdirSync ( "./test" ) . forEach ( function forFile ( file ) {
2015-02-23 23:39:20 -08:00
if ( file . match ( /\.md$/ ) ) {
2015-03-17 22:34:47 -07:00
module . exports [ file ] = createTestForFile ( path . join ( "./test" , file ) ) ;
2015-02-23 23:39:20 -08:00
}
} ) ;
2015-03-11 21:13:21 -07:00
2015-03-12 23:42:06 -07:00
module . exports . projectFiles = function projectFiles ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2018-06-24 20:01:44 -07:00
"files" : [
"README.md" ,
"CONTRIBUTING.md"
] ,
2017-05-21 22:58:10 -07:00
"noInlineConfig" : true ,
"config" : {
"MD013" : { "line_length" : 150 } ,
"MD024" : false
}
2015-03-12 23:42:06 -07:00
} ;
markdownlint ( options , function callback ( err , actual ) {
test . ifError ( err ) ;
2018-06-24 20:01:44 -07:00
const expected = {
"README.md" : [ ] ,
"CONTRIBUTING.md" : [ ]
} ;
2015-03-12 23:42:06 -07:00
test . deepEqual ( actual , expected , "Issue(s) with project files." ) ;
test . done ( ) ;
} ) ;
} ;
2016-10-16 21:46:02 -07:00
module . exports . resultFormattingV0 = function resultFormattingV0 ( test ) {
2016-01-12 21:29:17 -08:00
test . expect ( 4 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-13 09:13:07 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-07-20 22:06:48 -07:00
] ,
2017-07-05 21:53:21 -07:00
"config" : defaultConfig ,
"resultVersion" : 0
2015-03-13 09:13:07 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : {
2015-03-13 09:13:07 -07:00
"MD002" : [ 3 ] ,
"MD018" : [ 1 ] ,
"MD019" : [ 3 , 5 ]
} ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : {
2015-03-13 09:13:07 -07:00
"MD002" : [ 1 ]
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
2018-04-27 22:05:34 -07:00
let actualMessage = actualResult . toString ( ) ;
let expectedMessage =
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md: 3: MD002" +
" First heading should be a top level heading\n" +
"./test/atx_heading_spacing.md: 1: MD018" +
" No space after hash on atx style heading\n" +
"./test/atx_heading_spacing.md: 3: MD019" +
" Multiple spaces after hash on atx style heading\n" +
"./test/atx_heading_spacing.md: 5: MD019" +
" Multiple spaces after hash on atx style heading\n" +
"./test/first_heading_bad_atx.md: 1: MD002" +
" First heading should be a top level heading" ;
2016-01-12 21:29:17 -08:00
test . equal ( actualMessage , expectedMessage , "Incorrect message (name)." ) ;
actualMessage = actualResult . toString ( true ) ;
expectedMessage =
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md: 3: first-heading-h1" +
" First heading should be a top level heading\n" +
"./test/atx_heading_spacing.md: 1: no-missing-space-atx" +
" No space after hash on atx style heading\n" +
"./test/atx_heading_spacing.md: 3: no-multiple-space-atx" +
" Multiple spaces after hash on atx style heading\n" +
"./test/atx_heading_spacing.md: 5: no-multiple-space-atx" +
" Multiple spaces after hash on atx style heading\n" +
"./test/first_heading_bad_atx.md: 1: first-heading-h1" +
" First heading should be a top level heading" ;
2016-01-12 21:29:17 -08:00
test . equal ( actualMessage , expectedMessage , "Incorrect message (alias)." ) ;
2015-03-13 09:13:07 -07:00
test . done ( ) ;
} ) ;
} ;
2016-10-16 21:46:02 -07:00
module . exports . resultFormattingSyncV0 = function resultFormattingSyncV0 ( test ) {
2016-01-12 21:29:17 -08:00
test . expect ( 3 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-20 00:09:55 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-07-20 22:06:48 -07:00
] ,
2016-10-16 21:46:02 -07:00
"config" : defaultConfig ,
"resultVersion" : 0
2015-03-20 00:09:55 -07:00
} ;
2018-04-27 22:05:34 -07:00
const actualResult = markdownlint . sync ( options ) ;
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : {
2015-03-20 00:09:55 -07:00
"MD002" : [ 3 ] ,
"MD018" : [ 1 ] ,
"MD019" : [ 3 , 5 ]
} ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : {
2015-03-20 00:09:55 -07:00
"MD002" : [ 1 ]
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
2018-04-27 22:05:34 -07:00
let actualMessage = actualResult . toString ( ) ;
let expectedMessage =
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md: 3: MD002" +
" First heading should be a top level heading\n" +
"./test/atx_heading_spacing.md: 1: MD018" +
" No space after hash on atx style heading\n" +
"./test/atx_heading_spacing.md: 3: MD019" +
" Multiple spaces after hash on atx style heading\n" +
"./test/atx_heading_spacing.md: 5: MD019" +
" Multiple spaces after hash on atx style heading\n" +
"./test/first_heading_bad_atx.md: 1: MD002" +
" First heading should be a top level heading" ;
2016-01-12 21:29:17 -08:00
test . equal ( actualMessage , expectedMessage , "Incorrect message (name)." ) ;
actualMessage = actualResult . toString ( true ) ;
expectedMessage =
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md: 3: first-heading-h1" +
" First heading should be a top level heading\n" +
"./test/atx_heading_spacing.md: 1: no-missing-space-atx" +
" No space after hash on atx style heading\n" +
"./test/atx_heading_spacing.md: 3: no-multiple-space-atx" +
" Multiple spaces after hash on atx style heading\n" +
"./test/atx_heading_spacing.md: 5: no-multiple-space-atx" +
" Multiple spaces after hash on atx style heading\n" +
"./test/first_heading_bad_atx.md: 1: first-heading-h1" +
" First heading should be a top level heading" ;
2016-01-12 21:29:17 -08:00
test . equal ( actualMessage , expectedMessage , "Incorrect message (alias)." ) ;
2015-03-20 00:09:55 -07:00
test . done ( ) ;
} ;
2016-10-16 21:46:02 -07:00
module . exports . resultFormattingV1 = function resultFormattingV1 ( test ) {
test . expect ( 3 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2016-10-16 21:46:02 -07:00
"strings" : {
"truncate" :
2018-03-19 23:39:42 +01:00
"# Multiple spaces inside hashes on closed atx style heading #"
2016-10-16 21:46:02 -07:00
} ,
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2016-10-16 21:46:02 -07:00
] ,
2018-01-12 23:21:06 -08:00
"config" : defaultConfig ,
"resultVersion" : 1
2016-10-16 21:46:02 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2016-10-16 21:46:02 -07:00
"truncate" : [
{ "lineNumber" : 1 ,
"ruleName" : "MD021" ,
"ruleAlias" : "no-multiple-space-closed-atx" ,
"ruleDescription" :
2018-03-19 23:39:42 +01:00
"Multiple spaces inside hashes on closed atx style heading" ,
2016-10-16 21:46:02 -07:00
"errorDetail" : null ,
2018-03-19 23:39:42 +01:00
"errorContext" : "# Multiple spa...tyle heading #" ,
2016-10-31 22:53:46 -07:00
"errorRange" : [ 1 , 4 ] }
2016-10-16 21:46:02 -07:00
] ,
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : [
2016-10-16 21:46:02 -07:00
{ "lineNumber" : 3 ,
"ruleName" : "MD002" ,
2018-03-19 23:39:42 +01:00
"ruleAlias" : "first-heading-h1" ,
"ruleDescription" : "First heading should be a top level heading" ,
2016-10-16 21:46:02 -07:00
"errorDetail" : "Expected: h1; Actual: h2" ,
2016-10-31 22:53:46 -07:00
"errorContext" : null ,
"errorRange" : null } ,
2016-10-16 21:46:02 -07:00
{ "lineNumber" : 1 ,
"ruleName" : "MD018" ,
"ruleAlias" : "no-missing-space-atx" ,
2018-03-19 23:39:42 +01:00
"ruleDescription" : "No space after hash on atx style heading" ,
2016-10-16 21:46:02 -07:00
"errorDetail" : null ,
2018-03-19 23:39:42 +01:00
"errorContext" : "#Heading 1 {MD018}" ,
2016-10-31 22:53:46 -07:00
"errorRange" : [ 1 , 2 ] } ,
2016-10-16 21:46:02 -07:00
{ "lineNumber" : 3 ,
"ruleName" : "MD019" ,
"ruleAlias" : "no-multiple-space-atx" ,
2018-03-19 23:39:42 +01:00
"ruleDescription" : "Multiple spaces after hash on atx style heading" ,
2016-10-16 21:46:02 -07:00
"errorDetail" : null ,
2018-03-19 23:39:42 +01:00
"errorContext" : "## Heading 2 {MD019}" ,
2016-10-31 22:53:46 -07:00
"errorRange" : [ 1 , 5 ] } ,
2016-10-16 21:46:02 -07:00
{ "lineNumber" : 5 ,
"ruleName" : "MD019" ,
"ruleAlias" : "no-multiple-space-atx" ,
2018-03-19 23:39:42 +01:00
"ruleDescription" : "Multiple spaces after hash on atx style heading" ,
2016-10-16 21:46:02 -07:00
"errorDetail" : null ,
2018-03-19 23:39:42 +01:00
"errorContext" : "## Heading 3 {MD019}" ,
2016-10-31 22:53:46 -07:00
"errorRange" : [ 1 , 6 ] }
2016-10-16 21:46:02 -07:00
] ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : [
2016-10-16 21:46:02 -07:00
{ "lineNumber" : 1 ,
"ruleName" : "MD002" ,
2018-03-19 23:39:42 +01:00
"ruleAlias" : "first-heading-h1" ,
"ruleDescription" : "First heading should be a top level heading" ,
2016-10-16 21:46:02 -07:00
"errorDetail" : "Expected: h1; Actual: h2" ,
2016-10-31 22:53:46 -07:00
"errorContext" : null ,
"errorRange" : null }
2016-10-16 21:46:02 -07:00
]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
2018-04-27 22:05:34 -07:00
const actualMessage = actualResult . toString ( ) ;
const expectedMessage =
2016-10-16 21:46:02 -07:00
"truncate: 1: MD021/no-multiple-space-closed-atx" +
2018-03-19 23:39:42 +01:00
" Multiple spaces inside hashes on closed atx style heading" +
" [Context: \"# Multiple spa...tyle heading #\"]\n" +
"./test/atx_heading_spacing.md: 3: MD002/first-heading-h1" +
" First heading should be a top level heading" +
2016-10-16 21:46:02 -07:00
" [Expected: h1; Actual: h2]\n" +
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md: 1: MD018/no-missing-space-atx" +
" No space after hash on atx style heading" +
" [Context: \"#Heading 1 {MD018}\"]\n" +
"./test/atx_heading_spacing.md: 3: MD019/no-multiple-space-atx" +
" Multiple spaces after hash on atx style heading" +
" [Context: \"## Heading 2 {MD019}\"]\n" +
"./test/atx_heading_spacing.md: 5: MD019/no-multiple-space-atx" +
" Multiple spaces after hash on atx style heading" +
" [Context: \"## Heading 3 {MD019}\"]\n" +
"./test/first_heading_bad_atx.md: 1: MD002/first-heading-h1" +
" First heading should be a top level heading" +
2016-10-16 21:46:02 -07:00
" [Expected: h1; Actual: h2]" ;
test . equal ( actualMessage , expectedMessage , "Incorrect message." ) ;
test . done ( ) ;
} ) ;
} ;
2018-01-12 23:21:06 -08:00
module . exports . resultFormattingV2 = function resultFormattingV2 ( test ) {
test . expect ( 3 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2018-01-12 23:21:06 -08:00
"strings" : {
"truncate" :
2018-03-19 23:39:42 +01:00
"# Multiple spaces inside hashes on closed atx style heading #"
2018-01-12 23:21:06 -08:00
} ,
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2018-01-12 23:21:06 -08:00
] ,
"config" : defaultConfig
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-01-12 23:21:06 -08:00
"truncate" : [
{ "lineNumber" : 1 ,
"ruleNames" : [ "MD021" , "no-multiple-space-closed-atx" ] ,
"ruleDescription" :
2018-03-19 23:39:42 +01:00
"Multiple spaces inside hashes on closed atx style heading" ,
2018-01-12 23:21:06 -08:00
"errorDetail" : null ,
2018-03-19 23:39:42 +01:00
"errorContext" : "# Multiple spa...tyle heading #" ,
2018-01-12 23:21:06 -08:00
"errorRange" : [ 1 , 4 ] }
] ,
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : [
2018-01-12 23:21:06 -08:00
{ "lineNumber" : 3 ,
2018-03-19 23:39:42 +01:00
"ruleNames" : [ "MD002" , "first-heading-h1" , "first-header-h1" ] ,
"ruleDescription" : "First heading should be a top level heading" ,
2018-01-12 23:21:06 -08:00
"errorDetail" : "Expected: h1; Actual: h2" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 1 ,
"ruleNames" : [ "MD018" , "no-missing-space-atx" ] ,
2018-03-19 23:39:42 +01:00
"ruleDescription" : "No space after hash on atx style heading" ,
2018-01-12 23:21:06 -08:00
"errorDetail" : null ,
2018-03-19 23:39:42 +01:00
"errorContext" : "#Heading 1 {MD018}" ,
2018-01-12 23:21:06 -08:00
"errorRange" : [ 1 , 2 ] } ,
{ "lineNumber" : 3 ,
"ruleNames" : [ "MD019" , "no-multiple-space-atx" ] ,
2018-03-19 23:39:42 +01:00
"ruleDescription" : "Multiple spaces after hash on atx style heading" ,
2018-01-12 23:21:06 -08:00
"errorDetail" : null ,
2018-03-19 23:39:42 +01:00
"errorContext" : "## Heading 2 {MD019}" ,
2018-01-12 23:21:06 -08:00
"errorRange" : [ 1 , 5 ] } ,
{ "lineNumber" : 5 ,
"ruleNames" : [ "MD019" , "no-multiple-space-atx" ] ,
2018-03-19 23:39:42 +01:00
"ruleDescription" : "Multiple spaces after hash on atx style heading" ,
2018-01-12 23:21:06 -08:00
"errorDetail" : null ,
2018-03-19 23:39:42 +01:00
"errorContext" : "## Heading 3 {MD019}" ,
2018-01-12 23:21:06 -08:00
"errorRange" : [ 1 , 6 ] }
] ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : [
2018-01-12 23:21:06 -08:00
{ "lineNumber" : 1 ,
2018-03-19 23:39:42 +01:00
"ruleNames" : [ "MD002" , "first-heading-h1" , "first-header-h1" ] ,
"ruleDescription" : "First heading should be a top level heading" ,
2018-01-12 23:21:06 -08:00
"errorDetail" : "Expected: h1; Actual: h2" ,
"errorContext" : null ,
"errorRange" : null }
]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
2018-04-27 22:05:34 -07:00
const actualMessage = actualResult . toString ( ) ;
const expectedMessage =
2018-01-12 23:21:06 -08:00
"truncate: 1: MD021/no-multiple-space-closed-atx" +
2018-03-19 23:39:42 +01:00
" Multiple spaces inside hashes on closed atx style heading" +
" [Context: \"# Multiple spa...tyle heading #\"]\n" +
"./test/atx_heading_spacing.md: 3:" +
" MD002/first-heading-h1/first-header-h1" +
" First heading should be a top level heading" +
2018-01-12 23:21:06 -08:00
" [Expected: h1; Actual: h2]\n" +
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md: 1: MD018/no-missing-space-atx" +
" No space after hash on atx style heading" +
" [Context: \"#Heading 1 {MD018}\"]\n" +
"./test/atx_heading_spacing.md: 3: MD019/no-multiple-space-atx" +
" Multiple spaces after hash on atx style heading" +
" [Context: \"## Heading 2 {MD019}\"]\n" +
"./test/atx_heading_spacing.md: 5: MD019/no-multiple-space-atx" +
" Multiple spaces after hash on atx style heading" +
" [Context: \"## Heading 3 {MD019}\"]\n" +
"./test/first_heading_bad_atx.md: 1:" +
" MD002/first-heading-h1/first-header-h1" +
" First heading should be a top level heading" +
2018-01-12 23:21:06 -08:00
" [Expected: h1; Actual: h2]" ;
test . equal ( actualMessage , expectedMessage , "Incorrect message." ) ;
test . done ( ) ;
} ) ;
} ;
2015-04-29 18:46:52 -07:00
module . exports . stringInputLineEndings = function stringInputLineEndings ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-04-29 18:46:52 -07:00
"strings" : {
2015-05-02 17:41:41 -07:00
"cr" : "One\rTwo\r#Three" ,
2015-04-29 18:46:52 -07:00
"lf" : "One\nTwo\n#Three" ,
"crlf" : "One\r\nTwo\r\n#Three" ,
2018-04-30 21:43:34 -07:00
"mixed" : "One\rTwo\n#Three" ,
"crnel" : "One\r\u0085Two\r\u0085#Three" ,
"snl" : "One\u2424Two\u2424#Three" ,
"lsep" : "One\u2028Two\u2028#Three" ,
"nel" : "One\u0085Two\u0085#Three"
2015-07-20 22:06:48 -07:00
} ,
2017-07-05 21:53:21 -07:00
"config" : defaultConfig ,
"resultVersion" : 0
2015-04-29 18:46:52 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2015-05-02 17:41:41 -07:00
"cr" : { "MD018" : [ 3 ] } ,
2015-04-29 18:46:52 -07:00
"lf" : { "MD018" : [ 3 ] } ,
"crlf" : { "MD018" : [ 3 ] } ,
2018-04-30 21:43:34 -07:00
"mixed" : { "MD018" : [ 3 ] } ,
"crnel" : { "MD018" : [ 3 ] } ,
"snl" : { "MD018" : [ 3 ] } ,
"lsep" : { "MD018" : [ 3 ] } ,
"nel" : { "MD018" : [ 3 ] }
2015-04-29 18:46:52 -07:00
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-07-22 23:17:08 -07:00
module . exports . inputOnlyNewline = function inputOnlyNewline ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-07-22 23:17:08 -07:00
"strings" : {
"cr" : "\r" ,
"lf" : "\n" ,
"crlf" : "\r\n"
} ,
"config" : {
"default" : false
}
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2017-07-05 21:53:21 -07:00
"cr" : [ ] ,
"lf" : [ ] ,
"crlf" : [ ]
2015-07-22 23:17:08 -07:00
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-03-16 23:25:06 -07:00
module . exports . defaultTrue = function defaultTrue ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-16 23:25:06 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-03-16 23:25:06 -07:00
] ,
"config" : {
"default" : true
2017-07-05 21:53:21 -07:00
} ,
"resultVersion" : 0
2015-03-16 23:25:06 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : {
2015-03-16 23:25:06 -07:00
"MD002" : [ 3 ] ,
"MD018" : [ 1 ] ,
2015-07-20 22:06:48 -07:00
"MD019" : [ 3 , 5 ] ,
"MD041" : [ 1 ]
2015-03-16 23:25:06 -07:00
} ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : {
2015-07-20 22:06:48 -07:00
"MD002" : [ 1 ] ,
"MD041" : [ 1 ]
2015-03-16 23:25:06 -07:00
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . defaultFalse = function defaultFalse ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-16 23:25:06 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-03-16 23:25:06 -07:00
] ,
"config" : {
"default" : false
2017-07-05 21:53:21 -07:00
} ,
"resultVersion" : 0
2015-03-16 23:25:06 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : { } ,
"./test/first_heading_bad_atx.md" : { }
2015-03-16 23:25:06 -07:00
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-03-18 22:45:51 -07:00
module . exports . defaultUndefined = function defaultUndefined ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-18 22:45:51 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-03-18 22:45:51 -07:00
] ,
2017-07-05 21:53:21 -07:00
"config" : { } ,
"resultVersion" : 0
2015-03-18 22:45:51 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : {
2015-03-18 22:45:51 -07:00
"MD002" : [ 3 ] ,
"MD018" : [ 1 ] ,
2015-07-20 22:06:48 -07:00
"MD019" : [ 3 , 5 ] ,
"MD041" : [ 1 ]
2015-03-18 22:45:51 -07:00
} ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : {
2015-07-20 22:06:48 -07:00
"MD002" : [ 1 ] ,
"MD041" : [ 1 ]
2015-03-18 22:45:51 -07:00
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-03-16 23:25:06 -07:00
module . exports . disableRules = function disableRules ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-16 23:25:06 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-03-16 23:25:06 -07:00
] ,
"config" : {
"MD002" : false ,
"default" : true ,
2015-07-20 22:06:48 -07:00
"MD019" : false ,
2016-01-12 21:29:17 -08:00
"first-line-h1" : false
2017-07-05 21:53:21 -07:00
} ,
"resultVersion" : 0
2015-03-16 23:25:06 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : {
2015-03-16 23:25:06 -07:00
"MD018" : [ 1 ]
} ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : { }
2015-03-16 23:25:06 -07:00
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . enableRules = function enableRules ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-16 23:25:06 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-03-16 23:25:06 -07:00
] ,
"config" : {
"MD002" : true ,
"default" : false ,
2016-01-12 21:29:17 -08:00
"no-multiple-space-atx" : true
2017-07-05 21:53:21 -07:00
} ,
"resultVersion" : 0
2015-03-16 23:25:06 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : {
2015-03-16 23:25:06 -07:00
"MD002" : [ 3 ] ,
"MD019" : [ 3 , 5 ]
} ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : {
2015-03-16 23:25:06 -07:00
"MD002" : [ 1 ]
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-09-21 23:21:17 -07:00
module . exports . enableRulesMixedCase = function enableRulesMixedCase ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-09-21 23:21:17 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-09-21 23:21:17 -07:00
] ,
"config" : {
"Md002" : true ,
"DeFaUlT" : false ,
2016-01-12 21:29:17 -08:00
"nO-mUlTiPlE-sPaCe-AtX" : true
2017-07-05 21:53:21 -07:00
} ,
"resultVersion" : 0
2015-09-21 23:21:17 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : {
2015-09-21 23:21:17 -07:00
"MD002" : [ 3 ] ,
"MD019" : [ 3 , 5 ]
} ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : {
2015-09-21 23:21:17 -07:00
"MD002" : [ 1 ]
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-03-16 23:25:06 -07:00
module . exports . disableTag = function disableTag ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-16 23:25:06 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-03-16 23:25:06 -07:00
] ,
"config" : {
"default" : true ,
"spaces" : false
2017-07-05 21:53:21 -07:00
} ,
"resultVersion" : 0
2015-03-16 23:25:06 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : {
2015-07-20 22:06:48 -07:00
"MD002" : [ 3 ] ,
"MD041" : [ 1 ]
2015-03-16 23:25:06 -07:00
} ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : {
2015-07-20 22:06:48 -07:00
"MD002" : [ 1 ] ,
"MD041" : [ 1 ]
2015-03-16 23:25:06 -07:00
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . enableTag = function enableTag ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-16 23:25:06 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-03-16 23:25:06 -07:00
] ,
"config" : {
"default" : false ,
2015-09-26 16:55:33 -07:00
"spaces" : true ,
"notatag" : true
2017-07-05 21:53:21 -07:00
} ,
"resultVersion" : 0
2015-03-16 23:25:06 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : {
2015-03-16 23:25:06 -07:00
"MD018" : [ 1 ] ,
"MD019" : [ 3 , 5 ]
} ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : { }
2015-03-16 23:25:06 -07:00
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-09-21 23:21:17 -07:00
module . exports . enableTagMixedCase = function enableTagMixedCase ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-09-21 23:21:17 -07:00
"files" : [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-09-21 23:21:17 -07:00
] ,
"config" : {
"DeFaUlT" : false ,
2015-09-26 16:55:33 -07:00
"SpAcEs" : true ,
"NoTaTaG" : true
2017-07-05 21:53:21 -07:00
} ,
"resultVersion" : 0
2015-09-21 23:21:17 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" : {
2015-09-21 23:21:17 -07:00
"MD018" : [ 1 ] ,
"MD019" : [ 3 , 5 ]
} ,
2018-03-19 23:39:42 +01:00
"./test/first_heading_bad_atx.md" : { }
2015-09-21 23:21:17 -07:00
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-03-17 22:34:47 -07:00
module . exports . styleFiles = function styleFiles ( test ) {
test . expect ( 4 ) ;
fs . readdir ( "./style" , function readdir ( err , files ) {
test . ifError ( err ) ;
files . forEach ( function forFile ( file ) {
test . ok ( require ( path . join ( "../style" , file ) ) , "Unable to load/parse." ) ;
} ) ;
test . done ( ) ;
} ) ;
} ;
2015-03-17 18:02:05 -07:00
module . exports . styleAll = function styleAll ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-17 18:02:05 -07:00
"files" : [ "./test/break-all-the-rules.md" ] ,
2017-07-05 21:53:21 -07:00
"config" : require ( "../style/all.json" ) ,
"resultVersion" : 0
2015-03-17 18:02:05 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2015-03-17 18:02:05 -07:00
"./test/break-all-the-rules.md" : {
"MD001" : [ 3 ] ,
"MD002" : [ 1 ] ,
"MD003" : [ 5 , 30 ] ,
"MD004" : [ 8 ] ,
"MD005" : [ 12 ] ,
"MD006" : [ 8 ] ,
"MD007" : [ 8 , 11 ] ,
"MD009" : [ 14 ] ,
"MD010" : [ 14 ] ,
"MD011" : [ 16 ] ,
"MD012" : [ 18 ] ,
"MD013" : [ 21 ] ,
"MD014" : [ 23 ] ,
"MD018" : [ 25 ] ,
"MD019" : [ 27 ] ,
"MD020" : [ 29 ] ,
"MD021" : [ 30 ] ,
"MD022" : [ 30 ] ,
"MD023" : [ 30 ] ,
"MD024" : [ 34 ] ,
"MD026" : [ 40 ] ,
"MD027" : [ 42 ] ,
"MD028" : [ 43 ] ,
"MD029" : [ 47 ] ,
"MD030" : [ 8 ] ,
"MD031" : [ 50 ] ,
2015-04-16 09:39:04 -07:00
"MD032" : [ 51 ] ,
"MD033" : [ 55 ] ,
"MD034" : [ 57 ] ,
"MD035" : [ 61 ] ,
"MD036" : [ 65 ] ,
"MD037" : [ 67 ] ,
"MD038" : [ 69 ] ,
"MD039" : [ 71 ] ,
2015-07-20 22:06:48 -07:00
"MD040" : [ 73 ] ,
2016-06-27 22:19:02 -07:00
"MD041" : [ 1 ] ,
2018-01-08 21:29:13 -08:00
"MD042" : [ 77 ] ,
"MD045" : [ 81 ]
2015-03-17 18:02:05 -07:00
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . styleRelaxed = function styleRelaxed ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2015-03-17 18:02:05 -07:00
"files" : [ "./test/break-all-the-rules.md" ] ,
2017-07-05 21:53:21 -07:00
"config" : require ( "../style/relaxed.json" ) ,
"resultVersion" : 0
2015-03-17 18:02:05 -07:00
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2015-03-17 18:02:05 -07:00
"./test/break-all-the-rules.md" : {
"MD001" : [ 3 ] ,
"MD002" : [ 1 ] ,
"MD003" : [ 5 , 30 ] ,
"MD004" : [ 8 ] ,
"MD005" : [ 12 ] ,
"MD011" : [ 16 ] ,
"MD014" : [ 23 ] ,
"MD018" : [ 25 ] ,
"MD019" : [ 27 ] ,
"MD020" : [ 29 ] ,
"MD021" : [ 30 ] ,
"MD022" : [ 30 ] ,
"MD023" : [ 30 ] ,
"MD024" : [ 34 ] ,
"MD026" : [ 40 ] ,
"MD029" : [ 47 ] ,
"MD031" : [ 50 ] ,
2015-04-16 09:39:04 -07:00
"MD032" : [ 51 ] ,
"MD035" : [ 61 ] ,
2016-06-27 22:19:02 -07:00
"MD036" : [ 65 ] ,
2018-01-08 21:29:13 -08:00
"MD042" : [ 77 ] ,
"MD045" : [ 81 ]
2015-03-17 18:02:05 -07:00
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-07-25 22:18:30 -07:00
module . exports . nullFrontMatter = function nullFrontMatter ( test ) {
test . expect ( 2 ) ;
markdownlint ( {
"strings" : {
2018-03-19 23:39:42 +01:00
"content" : "---\n\t\n---\n# Heading\n"
2015-07-25 22:18:30 -07:00
} ,
"frontMatter" : null ,
"config" : {
"default" : false ,
"MD010" : true
2017-07-05 21:53:21 -07:00
} ,
"resultVersion" : 0
2015-07-25 22:18:30 -07:00
} , function callback ( err , result ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2015-07-25 22:18:30 -07:00
"content" : { "MD010" : [ 2 ] }
} ;
test . deepEqual ( result , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . customFrontMatter = function customFrontMatter ( test ) {
test . expect ( 2 ) ;
markdownlint ( {
"strings" : {
2018-03-19 23:39:42 +01:00
"content" : "<head>\n\t\n</head>\n# Heading\n"
2015-07-25 22:18:30 -07:00
} ,
"frontMatter" : /<head>[^]*<\/head>/ ,
"config" : {
"default" : false ,
"MD010" : true
}
} , function callback ( err , result ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2017-07-05 21:53:21 -07:00
"content" : [ ]
2015-07-25 22:18:30 -07:00
} ;
test . deepEqual ( result , expectedResult , "Did not get empty results." ) ;
test . done ( ) ;
} ) ;
} ;
2017-05-21 22:58:10 -07:00
module . exports . noInlineConfig = function noInlineConfig ( test ) {
test . expect ( 2 ) ;
markdownlint ( {
"strings" : {
"content" : [
"# Heading" ,
"" ,
"\tTab" ,
"" ,
"<!-- markdownlint-disable-->" ,
"" ,
"\tTab" ,
"" ,
"<!-- markdownlint-enable-->" ,
"" ,
"\tTab"
] . join ( "\n" )
} ,
2017-07-05 21:53:21 -07:00
"noInlineConfig" : true ,
"resultVersion" : 0
2017-05-21 22:58:10 -07:00
} , function callback ( err , result ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2017-05-21 22:58:10 -07:00
"content" : {
"MD010" : [ 3 , 7 , 11 ]
}
} ;
test . deepEqual ( result , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2018-03-19 23:39:42 +01:00
module . exports . readmeHeadings = function readmeHeadings ( test ) {
2016-07-02 22:37:52 -07:00
test . expect ( 2 ) ;
markdownlint ( {
"files" : "README.md" ,
2017-05-21 22:58:10 -07:00
"noInlineConfig" : true ,
2016-07-02 22:37:52 -07:00
"config" : {
"default" : false ,
2016-10-16 21:46:02 -07:00
"MD013" : {
"line_length" : 150
} ,
2016-07-02 22:37:52 -07:00
"MD043" : {
2018-03-19 23:39:42 +01:00
"headings" : [
2016-07-02 22:37:52 -07:00
"# markdownlint" ,
"## Install" ,
"## Overview" ,
"### Related" ,
"## Demonstration" ,
"## Rules / Aliases" ,
"## Tags" ,
"## Configuration" ,
"## API" ,
2017-05-19 22:36:46 -07:00
"### Linting" ,
"#### options" ,
2018-02-15 21:35:58 -08:00
"##### options.customRules" ,
2017-05-19 22:36:46 -07:00
"##### options.files" ,
"##### options.strings" ,
"##### options.config" ,
2017-05-21 22:58:10 -07:00
"##### options.frontMatter" ,
"##### options.noInlineConfig" ,
2017-05-19 22:36:46 -07:00
"##### options.resultVersion" ,
"#### callback" ,
"#### result" ,
"### Config" ,
"#### file" ,
2018-05-23 22:24:40 -07:00
"#### parsers" ,
2017-05-19 22:36:46 -07:00
"#### callback" ,
"#### result" ,
2016-07-02 22:37:52 -07:00
"## Usage" ,
"## Browser" ,
2017-11-21 21:58:42 -08:00
"## Examples" ,
2018-06-24 20:01:44 -07:00
"## Contributing" ,
2016-07-02 22:37:52 -07:00
"## History"
]
}
}
} , function callback ( err , result ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expected = { "README.md" : [ ] } ;
2016-07-02 22:37:52 -07:00
test . deepEqual ( result , expected , "Unexpected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-04-29 18:46:52 -07:00
module . exports . filesArrayNotModified = function filesArrayNotModified ( test ) {
2015-03-13 18:20:56 -07:00
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const files = [
2018-03-19 23:39:42 +01:00
"./test/atx_heading_spacing.md" ,
"./test/first_heading_bad_atx.md"
2015-03-13 18:20:56 -07:00
] ;
2018-04-27 22:05:34 -07:00
const expectedFiles = files . slice ( ) ;
2015-03-13 18:20:56 -07:00
markdownlint ( { "files" : files } , function callback ( err ) {
test . ifError ( err ) ;
test . deepEqual ( files , expectedFiles , "Files modified." ) ;
test . done ( ) ;
} ) ;
} ;
2016-01-15 22:00:34 -08:00
module . exports . filesArrayAsString = function filesArrayAsString ( test ) {
test . expect ( 2 ) ;
markdownlint ( {
"files" : "README.md" ,
2017-05-21 22:58:10 -07:00
"noInlineConfig" : true ,
"config" : {
"MD013" : { "line_length" : 150 } ,
"MD024" : false
}
2016-01-15 22:00:34 -08:00
} , function callback ( err , actual ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expected = { "README.md" : [ ] } ;
2016-01-15 22:00:34 -08:00
test . deepEqual ( actual , expected , "Unexpected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2015-03-11 21:13:21 -07:00
module . exports . missingOptions = function missingOptions ( test ) {
test . expect ( 2 ) ;
markdownlint ( null , function callback ( err , result ) {
test . ifError ( err ) ;
2015-04-29 18:46:52 -07:00
test . deepEqual ( result , { } , "Did not get empty result for missing options." ) ;
2015-03-11 21:13:21 -07:00
test . done ( ) ;
} ) ;
} ;
2015-04-29 18:46:52 -07:00
module . exports . missingFilesAndStrings = function missingFilesAndStrings ( test ) {
2015-03-11 21:13:21 -07:00
test . expect ( 2 ) ;
markdownlint ( { } , function callback ( err , result ) {
test . ifError ( err ) ;
2015-04-29 18:46:52 -07:00
test . ok ( result , "Did not get result for missing files/strings." ) ;
2015-03-11 21:13:21 -07:00
test . done ( ) ;
} ) ;
} ;
module . exports . missingCallback = function missingCallback ( test ) {
test . expect ( 0 ) ;
markdownlint ( ) ;
test . done ( ) ;
} ;
module . exports . badFile = function badFile ( test ) {
2015-03-20 00:09:55 -07:00
test . expect ( 4 ) ;
2015-03-11 21:13:21 -07:00
markdownlint ( {
"files" : [ "./badFile" ]
} , function callback ( err , result ) {
test . ok ( err , "Did not get an error for bad file." ) ;
2015-03-20 00:09:55 -07:00
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
2015-03-11 21:13:21 -07:00
test . equal ( err . code , "ENOENT" , "Error code for bad file not ENOENT." ) ;
test . ok ( ! result , "Got result for bad file." ) ;
test . done ( ) ;
} ) ;
} ;
2015-03-17 22:34:47 -07:00
2015-03-20 00:09:55 -07:00
module . exports . badFileSync = function badFileSync ( test ) {
2015-04-29 18:46:52 -07:00
test . expect ( 4 ) ;
2015-03-20 00:09:55 -07:00
test . throws ( function badFileCall ( ) {
markdownlint . sync ( {
"files" : [ "./badFile" ]
} ) ;
} , function testError ( err ) {
2015-04-29 18:46:52 -07:00
test . ok ( err , "Did not get an error for bad file." ) ;
2015-03-20 00:09:55 -07:00
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . code , "ENOENT" , "Error code for bad file not ENOENT." ) ;
return true ;
} , "Did not get exception for bad file." ) ;
test . done ( ) ;
} ;
2015-04-29 18:46:52 -07:00
module . exports . missingStringValue = function missingStringValue ( test ) {
test . expect ( 2 ) ;
markdownlint ( {
"strings" : {
"undefined" : undefined ,
"null" : null ,
"empty" : ""
2015-07-20 22:06:48 -07:00
} ,
"config" : defaultConfig
2015-04-29 18:46:52 -07:00
} , function callback ( err , result ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2017-07-05 21:53:21 -07:00
"undefined" : [ ] ,
"null" : [ ] ,
"empty" : [ ]
2015-04-29 18:46:52 -07:00
} ;
test . deepEqual ( result , expectedResult , "Did not get empty results." ) ;
test . done ( ) ;
} ) ;
} ;
2015-03-17 22:34:47 -07:00
module . exports . readme = function readme ( test ) {
2018-03-19 23:39:42 +01:00
test . expect ( 109 ) ;
2018-04-27 22:05:34 -07:00
const tagToRules = { } ;
2015-04-14 00:01:57 -07:00
rules . forEach ( function forRule ( rule ) {
rule . tags . forEach ( function forTag ( tag ) {
2018-04-27 22:05:34 -07:00
const tagRules = tagToRules [ tag ] || [ ] ;
2018-01-12 23:21:06 -08:00
tagRules . push ( rule . names [ 0 ] ) ;
2015-04-14 00:01:57 -07:00
tagToRules [ tag ] = tagRules ;
} ) ;
} ) ;
2015-03-17 22:34:47 -07:00
fs . readFile ( "README.md" , shared . utf8Encoding ,
function readFile ( err , contents ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const rulesLeft = rules . slice ( ) ;
let seenRelated = false ;
let seenRules = false ;
let inRules = false ;
let seenTags = false ;
let inTags = false ;
2015-03-17 22:34:47 -07:00
md . parse ( contents , { } ) . forEach ( function forToken ( token ) {
if ( token . type === "bullet_list_open" ) {
2016-01-14 22:15:44 -08:00
if ( ! seenRelated ) {
seenRelated = true ;
} else if ( seenRelated && ! seenRules ) {
2018-02-05 21:26:07 -08:00
seenRules = inRules = true ;
2016-01-14 22:15:44 -08:00
} else if ( seenRelated && seenRules && ! seenTags ) {
2018-02-05 21:26:07 -08:00
seenTags = inTags = true ;
2015-03-17 22:34:47 -07:00
}
} else if ( token . type === "bullet_list_close" ) {
2018-02-05 21:26:07 -08:00
inRules = inTags = false ;
2015-03-17 22:34:47 -07:00
} else if ( token . type === "inline" ) {
if ( inRules ) {
2018-04-27 22:05:34 -07:00
const rule = rulesLeft . shift ( ) ;
2015-04-14 00:01:57 -07:00
test . ok ( rule ,
"Missing rule implementation for " + token . content + "." ) ;
if ( rule ) {
2018-04-27 22:05:34 -07:00
const ruleName = rule . names [ 0 ] ;
const ruleAliases = rule . names . slice ( 1 ) ;
const expected = "**[" + ruleName + "](doc/Rules.md#" +
2018-01-12 23:21:06 -08:00
ruleName . toLowerCase ( ) + ")** *" +
2018-04-18 22:25:45 -07:00
ruleAliases . join ( "/" ) + "* - " + rule . description ;
2015-04-14 00:01:57 -07:00
test . equal ( token . content , expected , "Rule mismatch." ) ;
}
2015-03-17 22:34:47 -07:00
} else if ( inTags ) {
2018-04-27 22:05:34 -07:00
const parts =
token . content . replace ( /\*\*/g , "" ) . split ( / - |, |,\n/ ) ;
const tag = parts . shift ( ) ;
2015-04-14 00:01:57 -07:00
test . deepEqual ( parts , tagToRules [ tag ] || [ ] ,
"Rule mismatch for tag " + tag + "." ) ;
delete tagToRules [ tag ] ;
2015-03-17 22:34:47 -07:00
}
}
} ) ;
2018-04-27 22:05:34 -07:00
const ruleLeft = rulesLeft . shift ( ) ;
2015-04-14 00:01:57 -07:00
test . ok ( ! ruleLeft ,
2018-01-12 23:21:06 -08:00
"Missing rule documentation for " +
( ruleLeft || "[NO RULE]" ) . toString ( ) + "." ) ;
2018-04-27 22:05:34 -07:00
const tagLeft = Object . keys ( tagToRules ) . shift ( ) ;
2015-04-14 00:01:57 -07:00
test . ok ( ! tagLeft , "Undocumented tag " + tagLeft + "." ) ;
2015-03-17 22:34:47 -07:00
test . done ( ) ;
} ) ;
} ;
module . exports . doc = function doc ( test ) {
2018-07-19 21:49:30 -07:00
test . expect ( 311 ) ;
2015-03-17 22:34:47 -07:00
fs . readFile ( "doc/Rules.md" , shared . utf8Encoding ,
function readFile ( err , contents ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const rulesLeft = rules . slice ( ) ;
let inHeading = false ;
let rule = null ;
let ruleHasTags = true ;
let ruleHasAliases = true ;
let ruleUsesParams = null ;
const tagAliasParameterRe = /, |: | / ;
2018-01-12 23:21:06 -08:00
function testTagsAliasesParams ( r ) {
r = r || "[NO RULE]" ;
2015-12-13 21:42:51 -08:00
test . ok ( ruleHasTags ,
2018-07-19 21:49:30 -07:00
"Missing tags for rule " + r . names + "." ) ;
2016-01-12 21:29:17 -08:00
test . ok ( ruleHasAliases ,
2018-07-19 21:49:30 -07:00
"Missing aliases for rule " + r . names + "." ) ;
2015-12-13 21:42:51 -08:00
test . ok ( ! ruleUsesParams ,
2018-07-19 21:49:30 -07:00
"Missing parameters for rule " + r . names + "." ) ;
2015-12-13 21:42:51 -08:00
}
2015-03-17 22:34:47 -07:00
md . parse ( contents , { } ) . forEach ( function forToken ( token ) {
2015-03-18 23:14:44 -07:00
if ( ( token . type === "heading_open" ) && ( token . tag === "h2" ) ) {
2015-03-17 22:34:47 -07:00
inHeading = true ;
} else if ( token . type === "heading_close" ) {
inHeading = false ;
} else if ( token . type === "inline" ) {
if ( inHeading ) {
2018-01-12 23:21:06 -08:00
testTagsAliasesParams ( rule ) ;
2015-03-17 22:34:47 -07:00
rule = rulesLeft . shift ( ) ;
2016-01-12 21:29:17 -08:00
ruleHasTags = ruleHasAliases = false ;
2015-04-14 00:01:57 -07:00
test . ok ( rule ,
"Missing rule implementation for " + token . content + "." ) ;
2018-02-05 21:26:07 -08:00
test . equal ( token . content ,
rule . names [ 0 ] + " - " + rule . description ,
"Rule mismatch." ) ;
ruleUsesParams = rule . function . toString ( )
. match ( /params\.config\.[_a-z]*/gi ) ;
if ( ruleUsesParams ) {
ruleUsesParams = ruleUsesParams . map ( function forUse ( use ) {
return use . split ( "." ) . pop ( ) ;
} ) ;
2015-04-14 00:01:57 -07:00
}
} else if ( /^Tags: / . test ( token . content ) && rule ) {
2016-01-12 21:29:17 -08:00
test . deepEqual ( token . content . split ( tagAliasParameterRe ) . slice ( 1 ) ,
2018-07-19 21:49:30 -07:00
rule . tags , "Tag mismatch for rule " + rule . names + "." ) ;
2015-12-13 21:42:51 -08:00
ruleHasTags = true ;
2016-01-12 21:29:17 -08:00
} else if ( /^Aliases: / . test ( token . content ) && rule ) {
test . deepEqual ( token . content . split ( tagAliasParameterRe ) . slice ( 1 ) ,
2018-01-12 23:21:06 -08:00
rule . names . slice ( 1 ) ,
2018-07-19 21:49:30 -07:00
"Alias mismatch for rule " + rule . names + "." ) ;
2016-01-12 21:29:17 -08:00
ruleHasAliases = true ;
2015-12-13 21:42:51 -08:00
} else if ( /^Parameters: / . test ( token . content ) && rule ) {
2018-04-27 22:05:34 -07:00
let inDetails = false ;
const parameters = token . content . split ( tagAliasParameterRe )
2015-12-13 21:42:51 -08:00
. slice ( 1 )
. filter ( function forPart ( part ) {
inDetails = inDetails || ( part [ 0 ] === "(" ) ;
return ! inDetails ;
} ) ;
test . deepEqual ( parameters , ruleUsesParams ,
2018-07-19 21:49:30 -07:00
"Missing parameter for rule " + rule . names ) ;
2015-12-13 21:42:51 -08:00
ruleUsesParams = null ;
2015-03-17 22:34:47 -07:00
}
}
} ) ;
2018-04-27 22:05:34 -07:00
const ruleLeft = rulesLeft . shift ( ) ;
2015-04-14 00:01:57 -07:00
test . ok ( ! ruleLeft ,
2018-01-12 23:21:06 -08:00
"Missing rule documentation for " +
2018-07-19 21:49:30 -07:00
( ruleLeft || { "names" : "[NO RULE]" } ) . names + "." ) ;
2016-06-27 22:19:02 -07:00
if ( rule ) {
2018-01-12 23:21:06 -08:00
testTagsAliasesParams ( rule ) ;
2016-06-27 22:19:02 -07:00
}
2015-03-17 22:34:47 -07:00
test . done ( ) ;
} ) ;
} ;
2015-05-07 17:42:13 -07:00
2016-10-05 22:21:54 -07:00
module . exports . validateConfigSchema = function validateConfigSchema ( test ) {
2018-04-27 22:05:34 -07:00
const jsonFileRe = /\.json$/i ;
const resultsFileRe = /\.results\.json$/i ;
const testDirectory = _ _dirname ;
const testFiles = fs . readdirSync ( testDirectory ) ;
2016-10-05 22:21:54 -07:00
testFiles . filter ( function filterFile ( file ) {
2016-10-16 21:46:02 -07:00
return jsonFileRe . test ( file ) && ! resultsFileRe . test ( file ) ;
2016-10-05 22:21:54 -07:00
} ) . forEach ( function forFile ( file ) {
2018-04-27 22:05:34 -07:00
const data = fs . readFileSync ( path . join ( testDirectory , file ) ) ;
2016-10-05 22:21:54 -07:00
test . ok (
tv4 . validate ( JSON . parse ( data ) , configSchema ) ,
file + "\n" + JSON . stringify ( tv4 . error , null , 2 ) ) ;
} ) ;
test . done ( ) ;
} ;
2017-07-16 23:08:47 -07:00
module . exports . clearHtmlCommentTextValid =
function clearHtmlCommentTextValid ( test ) {
test . expect ( 1 ) ;
2018-04-27 22:05:34 -07:00
const validComments = [
2017-07-16 23:08:47 -07:00
"<!-- text -->" ,
"<!--text-->" ,
"<!-- -->" ,
"<!---->" ,
"<!---text-->" ,
"<!--text-text-->" ,
"<!--- -->" ,
"<!--" ,
"-->" ,
"<!--" ,
"" ,
"-->" ,
"<!--" ,
"" ,
"" ,
"-->" ,
"<!--" ,
"" ,
" text " ,
"" ,
"-->" ,
"<!--text" ,
"" ,
"text-->" ,
"text<!--text-->text" ,
"text<!--" ,
"-->text" ,
"text<!--" ,
"text" ,
"-->text" ,
"<!--text--><!--text-->" ,
"text<!--text-->text<!--text-->text" ,
"<!--" ,
"text"
] ;
2018-04-27 22:05:34 -07:00
const validResult = [
2017-07-16 23:08:47 -07:00
"<!-- -->" ,
"<!-- -->" ,
"<!-- -->" ,
"<!---->" ,
"<!-- -->" ,
"<!-- -->" ,
"<!-- -->" ,
"<!--" ,
"-->" ,
"<!--" ,
"" ,
"-->" ,
"<!--" ,
"" ,
"" ,
"-->" ,
"<!--" ,
"" ,
" \\" ,
"" ,
"-->" ,
"<!-- \\" ,
"" ,
" -->" ,
"text<!-- -->text" ,
"text<!--" ,
"-->text" ,
"text<!--" ,
" \\" ,
"-->text" ,
"<!-- --><!-- -->" ,
"text<!-- -->text<!-- -->text" ,
"<!--" ,
" \\"
] ;
2018-04-27 22:05:34 -07:00
const actual = shared . clearHtmlCommentText ( validComments . join ( "\n" ) ) ;
const expected = validResult . join ( "\n" ) ;
2017-07-16 23:08:47 -07:00
test . equal ( actual , expected ) ;
test . done ( ) ;
} ;
module . exports . clearHtmlCommentTextInvalid =
function clearHtmlCommentTextInvalid ( test ) {
test . expect ( 1 ) ;
2018-04-27 22:05:34 -07:00
const invalidComments = [
2017-07-16 23:08:47 -07:00
"<!>" ,
"<!->" ,
"<!-->" ,
"<!--->" ,
"<!-->-->" ,
"<!--->-->" ,
"<!----->" ,
"<!------>" ,
"<!-- -- -->" ,
"<!-->-->" ,
"<!--> -->" ,
"<!--->-->" ,
"<!-->text-->" ,
"<!--->text-->" ,
"<!--text--->" ,
"<!--te--xt-->"
] ;
2018-04-27 22:05:34 -07:00
const actual = shared . clearHtmlCommentText ( invalidComments . join ( "\n" ) ) ;
const expected = invalidComments . join ( "\n" ) ;
2017-07-16 23:08:47 -07:00
test . equal ( actual , expected ) ;
test . done ( ) ;
} ;
module . exports . clearHtmlCommentTextNonGreedy =
function clearHtmlCommentTextNonGreedy ( test ) {
test . expect ( 1 ) ;
2018-04-27 22:05:34 -07:00
const nonGreedyComments = [
2017-07-16 23:08:47 -07:00
"<!-- text --> -->" ,
"<!---text --> -->" ,
"<!--t--> -->" ,
"<!----> -->"
] ;
2018-04-27 22:05:34 -07:00
const nonGreedyResult = [
2017-07-16 23:08:47 -07:00
"<!-- --> -->" ,
"<!-- --> -->" ,
"<!-- --> -->" ,
"<!----> -->"
] ;
2018-04-27 22:05:34 -07:00
const actual = shared . clearHtmlCommentText ( nonGreedyComments . join ( "\n" ) ) ;
const expected = nonGreedyResult . join ( "\n" ) ;
2017-07-16 23:08:47 -07:00
test . equal ( actual , expected ) ;
test . done ( ) ;
} ;
module . exports . clearHtmlCommentTextEmbedded =
function clearHtmlCommentTextEmbedded ( test ) {
test . expect ( 1 ) ;
2018-04-27 22:05:34 -07:00
const embeddedComments = [
2017-07-16 23:08:47 -07:00
"text<!--text-->text" ,
"<!-- markdownlint-disable MD010 -->" ,
"text<!--text-->text" ,
"text<!-- markdownlint-disable MD010 -->text" ,
"text<!--text-->text"
] ;
2018-04-27 22:05:34 -07:00
const embeddedResult = [
2017-07-16 23:08:47 -07:00
"text<!-- -->text" ,
"<!-- markdownlint-disable MD010 -->" ,
"text<!-- -->text" ,
"text<!-- markdownlint-disable MD010 -->text" ,
"text<!-- -->text"
] ;
2018-04-27 22:05:34 -07:00
const actual = shared . clearHtmlCommentText ( embeddedComments . join ( "\n" ) ) ;
const expected = embeddedResult . join ( "\n" ) ;
2017-07-16 23:08:47 -07:00
test . equal ( actual , expected ) ;
test . done ( ) ;
} ;
2017-12-13 21:41:28 -08:00
module . exports . trimLeftRight = function trimLeftRight ( test ) {
2018-04-27 22:05:34 -07:00
const inputs = [
2015-05-03 22:40:34 -07:00
"text text" ,
" text text " ,
" text text " ,
// ECMAScript Whitespace
"\u0009 text text \u0009" ,
"\u000b text text \u000b" ,
"\u000c text text \u000c" ,
"\u0020 text text \u0020" ,
"\u00a0 text text \u00a0" ,
"\ufeff text text \ufeff" ,
// ECMAScript LineTerminator
"\u000a text text \u000a" ,
"\u000d text text \u000d" ,
"\u2028 text text \u2028" ,
"\u2029 text text \u2029"
] ;
test . expect ( inputs . length * 2 ) ;
inputs . forEach ( function forInput ( input ) {
2017-12-13 21:41:28 -08:00
test . equal ( shared . trimLeft ( input ) , input . trimLeft ( ) ,
2015-05-03 22:40:34 -07:00
"trimLeft incorrect for '" + input + "'" ) ;
2017-12-13 21:41:28 -08:00
test . equal ( shared . trimRight ( input ) , input . trimRight ( ) ,
2015-05-03 22:40:34 -07:00
"trimRight incorrect for '" + input + "'" ) ;
} ) ;
test . done ( ) ;
} ;
2017-05-19 22:36:46 -07:00
module . exports . configSingle = function configSingle ( test ) {
test . expect ( 2 ) ;
2018-05-20 21:37:05 -07:00
markdownlint . readConfig ( "./test/config/config-child.json" ,
2017-05-19 22:36:46 -07:00
function callback ( err , actual ) {
test . ifError ( err ) ;
2018-05-20 21:37:05 -07:00
const expected = require ( "./config/config-child.json" ) ;
2017-05-19 22:36:46 -07:00
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . configAbsolute = function configAbsolute ( test ) {
test . expect ( 2 ) ;
2018-05-20 21:37:05 -07:00
markdownlint . readConfig ( path . join ( _ _dirname , "config" , "config-child.json" ) ,
2017-05-19 22:36:46 -07:00
function callback ( err , actual ) {
test . ifError ( err ) ;
2018-05-20 21:37:05 -07:00
const expected = require ( "./config/config-child.json" ) ;
2017-05-19 22:36:46 -07:00
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . configMultiple = function configMultiple ( test ) {
test . expect ( 2 ) ;
2018-05-20 21:37:05 -07:00
markdownlint . readConfig ( "./test/config/config-grandparent.json" ,
2017-05-19 22:36:46 -07:00
function callback ( err , actual ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expected = shared . assign (
2017-07-17 22:23:00 -07:00
shared . assign (
2018-05-20 21:37:05 -07:00
shared . assign ( { } , require ( "./config/config-child.json" ) ) ,
require ( "./config/config-parent.json" ) ) ,
require ( "./config/config-grandparent.json" ) ) ;
2017-05-19 22:36:46 -07:00
delete expected . extends ;
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . configBadFile = function configBadFile ( test ) {
test . expect ( 4 ) ;
markdownlint . readConfig ( "./test/config/config-badfile.json" ,
function callback ( err , result ) {
test . ok ( err , "Did not get an error for bad file." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . code , "ENOENT" , "Error code for bad file not ENOENT." ) ;
test . ok ( ! result , "Got result for bad file." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . configBadChildFile = function configBadChildFile ( test ) {
test . expect ( 4 ) ;
markdownlint . readConfig ( "./test/config/config-badchildfile.json" ,
function callback ( err , result ) {
test . ok ( err , "Did not get an error for bad child file." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . code , "ENOENT" ,
"Error code for bad child file not ENOENT." ) ;
test . ok ( ! result , "Got result for bad child file." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . configBadJson = function configBadJson ( test ) {
test . expect ( 3 ) ;
markdownlint . readConfig ( "./test/config/config-badjson.json" ,
function callback ( err , result ) {
test . ok ( err , "Did not get an error for bad JSON." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . ok ( ! result , "Got result for bad JSON." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . configBadChildJson = function configBadChildJson ( test ) {
test . expect ( 3 ) ;
markdownlint . readConfig ( "./test/config/config-badchildjson.json" ,
function callback ( err , result ) {
test . ok ( err , "Did not get an error for bad child JSON." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . ok ( ! result , "Got result for bad child JSON." ) ;
test . done ( ) ;
} ) ;
} ;
2018-05-23 22:24:40 -07:00
module . exports . configSingleYaml = function configSingleYaml ( test ) {
test . expect ( 2 ) ;
markdownlint . readConfig (
"./test/config/config-child.yaml" ,
[ require ( "js-yaml" ) . safeLoad ] ,
function callback ( err , actual ) {
test . ifError ( err ) ;
const expected = require ( "./config/config-child.json" ) ;
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . configMultipleYaml = function configMultipleYaml ( test ) {
test . expect ( 2 ) ;
markdownlint . readConfig (
"./test/config/config-grandparent.yaml" ,
[ require ( "js-yaml" ) . safeLoad ] ,
function callback ( err , actual ) {
test . ifError ( err ) ;
const expected = shared . assign (
shared . assign (
shared . assign ( { } , require ( "./config/config-child.json" ) ) ,
require ( "./config/config-parent.json" ) ) ,
require ( "./config/config-grandparent.json" ) ) ;
delete expected . extends ;
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . configMultipleHybrid = function configMultipleHybrid ( test ) {
test . expect ( 2 ) ;
markdownlint . readConfig (
"./test/config/config-grandparent-hybrid.yaml" ,
[ JSON . parse , require ( "toml" ) . parse , require ( "js-yaml" ) . safeLoad ] ,
function callback ( err , actual ) {
test . ifError ( err ) ;
const expected = shared . assign (
shared . assign (
shared . assign ( { } , require ( "./config/config-child.json" ) ) ,
require ( "./config/config-parent.json" ) ) ,
require ( "./config/config-grandparent.json" ) ) ;
delete expected . extends ;
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . configBadHybrid = function configBadHybrid ( test ) {
test . expect ( 4 ) ;
markdownlint . readConfig (
"./test/config/config-badcontent.txt" ,
[ JSON . parse , require ( "toml" ) . parse , require ( "js-yaml" ) . safeLoad ] ,
function callback ( err , result ) {
test . ok ( err , "Did not get an error for bad child JSON." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . ok ( err . message . match (
// eslint-disable-next-line max-len
/^Unable to parse '[^']*'; Unexpected token \S+ in JSON at position \d+; Expected [^;]+ or end of input but "\S+" found.; end of the stream or a document separator is expected at line \d+, column \d+:[^;]*$/
) , "Error message unexpected." ) ;
test . ok ( ! result , "Got result for bad child JSON." ) ;
test . done ( ) ;
} ) ;
} ;
2017-05-19 22:36:46 -07:00
module . exports . configSingleSync = function configSingleSync ( test ) {
test . expect ( 1 ) ;
2018-05-20 21:37:05 -07:00
const actual = markdownlint . readConfigSync ( "./test/config/config-child.json" ) ;
const expected = require ( "./config/config-child.json" ) ;
2017-05-19 22:36:46 -07:00
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ;
module . exports . configAbsoluteSync = function configAbsoluteSync ( test ) {
test . expect ( 1 ) ;
2018-04-27 22:05:34 -07:00
const actual = markdownlint . readConfigSync (
2018-05-20 21:37:05 -07:00
path . join ( _ _dirname , "config" , "config-child.json" ) ) ;
const expected = require ( "./config/config-child.json" ) ;
2017-05-19 22:36:46 -07:00
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ;
module . exports . configMultipleSync = function configMultipleSync ( test ) {
test . expect ( 1 ) ;
2018-05-20 21:37:05 -07:00
const actual =
markdownlint . readConfigSync ( "./test/config/config-grandparent.json" ) ;
2018-04-27 22:05:34 -07:00
const expected = shared . assign (
2017-07-17 22:23:00 -07:00
shared . assign (
2018-05-20 21:37:05 -07:00
shared . assign ( { } , require ( "./config/config-child.json" ) ) ,
require ( "./config/config-parent.json" ) ) ,
require ( "./config/config-grandparent.json" ) ) ;
2017-05-19 22:36:46 -07:00
delete expected . extends ;
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ;
module . exports . configBadFileSync = function configBadFileSync ( test ) {
test . expect ( 4 ) ;
test . throws ( function badFileCall ( ) {
2018-05-20 21:37:05 -07:00
markdownlint . readConfigSync ( "./test/config/config-badfile.json" ) ;
2017-05-19 22:36:46 -07:00
} , function testError ( err ) {
test . ok ( err , "Did not get an error for bad file." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . code , "ENOENT" , "Error code for bad file not ENOENT." ) ;
return true ;
} , "Did not get exception for bad file." ) ;
test . done ( ) ;
} ;
module . exports . configBadChildFileSync = function configBadChildFileSync ( test ) {
test . expect ( 4 ) ;
test . throws ( function badChildFileCall ( ) {
2018-05-20 21:37:05 -07:00
markdownlint . readConfigSync ( "./test/config/config-badchildfile.json" ) ;
2017-05-19 22:36:46 -07:00
} , function testError ( err ) {
test . ok ( err , "Did not get an error for bad child file." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . code , "ENOENT" , "Error code for bad child file not ENOENT." ) ;
return true ;
} , "Did not get exception for bad child file." ) ;
test . done ( ) ;
} ;
module . exports . configBadJsonSync = function configBadJsonSync ( test ) {
2018-05-20 21:37:05 -07:00
test . expect ( 4 ) ;
2017-05-19 22:36:46 -07:00
test . throws ( function badJsonCall ( ) {
2018-05-20 21:37:05 -07:00
markdownlint . readConfigSync ( "./test/config/config-badjson.json" ) ;
2017-05-19 22:36:46 -07:00
} , function testError ( err ) {
test . ok ( err , "Did not get an error for bad JSON." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
2018-05-23 22:24:40 -07:00
test . ok ( err . message . match (
// eslint-disable-next-line max-len
/^Unable to parse '[^']*'; Unexpected token \S+ in JSON at position \d+$/
) , "Error message unexpected." ) ;
2017-05-19 22:36:46 -07:00
return true ;
} , "Did not get exception for bad JSON." ) ;
test . done ( ) ;
} ;
module . exports . configBadChildJsonSync = function configBadChildJsonSync ( test ) {
2018-05-20 21:37:05 -07:00
test . expect ( 4 ) ;
2017-05-19 22:36:46 -07:00
test . throws ( function badChildJsonCall ( ) {
2018-05-20 21:37:05 -07:00
markdownlint . readConfigSync ( "./test/config/config-badchildjson.json" ) ;
2017-05-19 22:36:46 -07:00
} , function testError ( err ) {
test . ok ( err , "Did not get an error for bad child JSON." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
2018-05-23 22:24:40 -07:00
test . ok ( err . message . match (
// eslint-disable-next-line max-len
/^Unable to parse '[^']*'; Unexpected token \S+ in JSON at position \d+$/
) , "Error message unexpected." ) ;
2017-05-19 22:36:46 -07:00
return true ;
} , "Did not get exception for bad child JSON." ) ;
test . done ( ) ;
} ;
2018-02-15 21:35:58 -08:00
2018-05-23 22:24:40 -07:00
module . exports . configSingleYamlSync = function configSingleYamlSync ( test ) {
test . expect ( 1 ) ;
const actual = markdownlint . readConfigSync (
"./test/config/config-child.yaml" , [ require ( "js-yaml" ) . safeLoad ] ) ;
const expected = require ( "./config/config-child.json" ) ;
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ;
module . exports . configMultipleYamlSync = function configMultipleYamlSync ( test ) {
test . expect ( 1 ) ;
const actual = markdownlint . readConfigSync (
"./test/config/config-grandparent.yaml" , [ require ( "js-yaml" ) . safeLoad ] ) ;
const expected = shared . assign (
shared . assign (
shared . assign ( { } , require ( "./config/config-child.json" ) ) ,
require ( "./config/config-parent.json" ) ) ,
require ( "./config/config-grandparent.json" ) ) ;
delete expected . extends ;
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ;
module . exports . configMultipleHybridSync =
function configMultipleHybridSync ( test ) {
test . expect ( 1 ) ;
const actual = markdownlint . readConfigSync (
"./test/config/config-grandparent-hybrid.yaml" ,
[ JSON . parse , require ( "toml" ) . parse , require ( "js-yaml" ) . safeLoad ] ) ;
const expected = shared . assign (
shared . assign (
shared . assign ( { } , require ( "./config/config-child.json" ) ) ,
require ( "./config/config-parent.json" ) ) ,
require ( "./config/config-grandparent.json" ) ) ;
delete expected . extends ;
test . deepEqual ( actual , expected , "Config object not correct." ) ;
test . done ( ) ;
} ;
module . exports . configBadHybridSync = function configBadHybridSync ( test ) {
test . expect ( 4 ) ;
test . throws ( function badHybridCall ( ) {
markdownlint . readConfigSync (
"./test/config/config-badcontent.txt" ,
[ JSON . parse , require ( "toml" ) . parse , require ( "js-yaml" ) . safeLoad ] ) ;
} , function testError ( err ) {
test . ok ( err , "Did not get an error for bad content." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . ok ( err . message . match (
// eslint-disable-next-line max-len
/^Unable to parse '[^']*'; Unexpected token \S+ in JSON at position \d+; Expected [^;]+ or end of input but "\S+" found.; end of the stream or a document separator is expected at line \d+, column \d+:[^;]*$/
) , "Error message unexpected." ) ;
return true ;
} , "Did not get exception for bad content." ) ;
test . done ( ) ;
} ;
2018-02-15 21:35:58 -08:00
module . exports . customRulesV0 = function customRulesV0 ( test ) {
test . expect ( 4 ) ;
2018-04-27 22:05:34 -07:00
const customRulesMd = "./test/custom-rules.md" ;
const options = {
2018-02-15 21:35:58 -08:00
"customRules" : customRules . all ,
"files" : [ customRulesMd ] ,
"resultVersion" : 0
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = { } ;
2018-02-15 21:35:58 -08:00
expectedResult [ customRulesMd ] = {
2018-02-25 16:04:13 -08:00
"any-blockquote" : [ 12 ] ,
2018-02-15 21:35:58 -08:00
"every-n-lines" : [ 2 , 4 , 6 , 10 , 12 ] ,
2018-02-25 16:04:13 -08:00
"first-line" : [ 1 ] ,
2018-02-15 21:35:58 -08:00
"letters-E-X" : [ 3 , 7 ]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
2018-04-27 22:05:34 -07:00
let actualMessage = actualResult . toString ( ) ;
let expectedMessage =
2018-02-25 16:04:13 -08:00
"./test/custom-rules.md: 12: any-blockquote" +
" Rule that reports an error for any blockquote\n" +
2018-02-15 21:35:58 -08:00
"./test/custom-rules.md: 2: every-n-lines" +
" Rule that reports an error every N lines\n" +
"./test/custom-rules.md: 4: every-n-lines" +
" Rule that reports an error every N lines\n" +
"./test/custom-rules.md: 6: every-n-lines" +
" Rule that reports an error every N lines\n" +
"./test/custom-rules.md: 10: every-n-lines" +
" Rule that reports an error every N lines\n" +
"./test/custom-rules.md: 12: every-n-lines" +
" Rule that reports an error every N lines\n" +
2018-02-25 16:04:13 -08:00
"./test/custom-rules.md: 1: first-line" +
" Rule that reports an error for the first line\n" +
2018-02-15 21:35:58 -08:00
"./test/custom-rules.md: 3: letters-E-X" +
" Rule that reports an error for lines with the letters 'EX'\n" +
"./test/custom-rules.md: 7: letters-E-X" +
" Rule that reports an error for lines with the letters 'EX'" ;
test . equal ( actualMessage , expectedMessage , "Incorrect message (name)." ) ;
actualMessage = actualResult . toString ( true ) ;
expectedMessage =
2018-02-25 16:04:13 -08:00
"./test/custom-rules.md: 12: any-blockquote" +
" Rule that reports an error for any blockquote\n" +
2018-02-15 21:35:58 -08:00
"./test/custom-rules.md: 2: every-n-lines" +
" Rule that reports an error every N lines\n" +
"./test/custom-rules.md: 4: every-n-lines" +
" Rule that reports an error every N lines\n" +
"./test/custom-rules.md: 6: every-n-lines" +
" Rule that reports an error every N lines\n" +
"./test/custom-rules.md: 10: every-n-lines" +
" Rule that reports an error every N lines\n" +
"./test/custom-rules.md: 12: every-n-lines" +
" Rule that reports an error every N lines\n" +
2018-02-25 16:04:13 -08:00
"./test/custom-rules.md: 1: first-line" +
" Rule that reports an error for the first line\n" +
2018-02-15 21:35:58 -08:00
"./test/custom-rules.md: 3: letter-E-letter-X" +
" Rule that reports an error for lines with the letters 'EX'\n" +
"./test/custom-rules.md: 7: letter-E-letter-X" +
" Rule that reports an error for lines with the letters 'EX'" ;
test . equal ( actualMessage , expectedMessage , "Incorrect message (alias)." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . customRulesV1 = function customRulesV1 ( test ) {
test . expect ( 3 ) ;
2018-04-27 22:05:34 -07:00
const customRulesMd = "./test/custom-rules.md" ;
const options = {
2018-02-15 21:35:58 -08:00
"customRules" : customRules . all ,
"files" : [ customRulesMd ] ,
"resultVersion" : 1
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = { } ;
2018-02-15 21:35:58 -08:00
expectedResult [ customRulesMd ] = [
{ "lineNumber" : 12 ,
2018-02-25 16:04:13 -08:00
"ruleName" : "any-blockquote" ,
"ruleAlias" : "any-blockquote" ,
"ruleDescription" : "Rule that reports an error for any blockquote" ,
2018-02-15 21:35:58 -08:00
"errorDetail" : "Blockquote spans 1 line(s)." ,
"errorContext" : "> Block" ,
"errorRange" : null } ,
{ "lineNumber" : 2 ,
"ruleName" : "every-n-lines" ,
"ruleAlias" : "every-n-lines" ,
"ruleDescription" : "Rule that reports an error every N lines" ,
"errorDetail" : "Line number 2" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 4 ,
"ruleName" : "every-n-lines" ,
"ruleAlias" : "every-n-lines" ,
"ruleDescription" : "Rule that reports an error every N lines" ,
"errorDetail" : "Line number 4" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 6 ,
"ruleName" : "every-n-lines" ,
"ruleAlias" : "every-n-lines" ,
"ruleDescription" : "Rule that reports an error every N lines" ,
"errorDetail" : "Line number 6" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 10 ,
"ruleName" : "every-n-lines" ,
"ruleAlias" : "every-n-lines" ,
"ruleDescription" : "Rule that reports an error every N lines" ,
"errorDetail" : "Line number 10" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 12 ,
"ruleName" : "every-n-lines" ,
"ruleAlias" : "every-n-lines" ,
"ruleDescription" : "Rule that reports an error every N lines" ,
"errorDetail" : "Line number 12" ,
"errorContext" : null ,
"errorRange" : null } ,
2018-02-25 16:04:13 -08:00
{ "lineNumber" : 1 ,
"ruleName" : "first-line" ,
"ruleAlias" : "first-line" ,
"ruleDescription" : "Rule that reports an error for the first line" ,
"errorDetail" : null ,
"errorContext" : null ,
"errorRange" : null } ,
2018-02-15 21:35:58 -08:00
{ "lineNumber" : 3 ,
"ruleName" : "letters-E-X" ,
"ruleAlias" : "letter-E-letter-X" ,
"ruleDescription" :
"Rule that reports an error for lines with the letters 'EX'" ,
"errorDetail" : null ,
"errorContext" : "text" ,
"errorRange" : null } ,
{ "lineNumber" : 7 ,
"ruleName" : "letters-E-X" ,
"ruleAlias" : "letter-E-letter-X" ,
"ruleDescription" :
"Rule that reports an error for lines with the letters 'EX'" ,
"errorDetail" : null ,
"errorContext" : "text" ,
"errorRange" : null }
] ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
2018-04-27 22:05:34 -07:00
const actualMessage = actualResult . toString ( ) ;
const expectedMessage =
2018-02-25 16:04:13 -08:00
"./test/custom-rules.md: 12: any-blockquote/any-blockquote" +
" Rule that reports an error for any blockquote" +
2018-02-15 21:35:58 -08:00
" [Blockquote spans 1 line(s).] [Context: \"> Block\"]\n" +
"./test/custom-rules.md: 2: every-n-lines/every-n-lines" +
" Rule that reports an error every N lines [Line number 2]\n" +
"./test/custom-rules.md: 4: every-n-lines/every-n-lines" +
" Rule that reports an error every N lines [Line number 4]\n" +
"./test/custom-rules.md: 6: every-n-lines/every-n-lines" +
" Rule that reports an error every N lines [Line number 6]\n" +
"./test/custom-rules.md: 10: every-n-lines/every-n-lines" +
" Rule that reports an error every N lines [Line number 10]\n" +
"./test/custom-rules.md: 12: every-n-lines/every-n-lines" +
" Rule that reports an error every N lines [Line number 12]\n" +
2018-02-25 16:04:13 -08:00
"./test/custom-rules.md: 1: first-line/first-line" +
" Rule that reports an error for the first line\n" +
2018-02-15 21:35:58 -08:00
"./test/custom-rules.md: 3: letters-E-X/letter-E-letter-X" +
" Rule that reports an error for lines with the letters 'EX'" +
" [Context: \"text\"]\n" +
"./test/custom-rules.md: 7: letters-E-X/letter-E-letter-X" +
" Rule that reports an error for lines with the letters 'EX'" +
" [Context: \"text\"]" ;
test . equal ( actualMessage , expectedMessage , "Incorrect message." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . customRulesV2 = function customRulesV2 ( test ) {
test . expect ( 3 ) ;
2018-04-27 22:05:34 -07:00
const customRulesMd = "./test/custom-rules.md" ;
const options = {
2018-02-15 21:35:58 -08:00
"customRules" : customRules . all ,
"files" : [ customRulesMd ] ,
"resultVersion" : 2
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = { } ;
2018-02-15 21:35:58 -08:00
expectedResult [ customRulesMd ] = [
{ "lineNumber" : 12 ,
2018-02-25 16:04:13 -08:00
"ruleNames" : [ "any-blockquote" ] ,
"ruleDescription" : "Rule that reports an error for any blockquote" ,
2018-02-15 21:35:58 -08:00
"errorDetail" : "Blockquote spans 1 line(s)." ,
"errorContext" : "> Block" ,
"errorRange" : null } ,
{ "lineNumber" : 2 ,
"ruleNames" : [ "every-n-lines" ] ,
"ruleDescription" : "Rule that reports an error every N lines" ,
"errorDetail" : "Line number 2" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 4 ,
"ruleNames" : [ "every-n-lines" ] ,
"ruleDescription" : "Rule that reports an error every N lines" ,
"errorDetail" : "Line number 4" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 6 ,
"ruleNames" : [ "every-n-lines" ] ,
"ruleDescription" : "Rule that reports an error every N lines" ,
"errorDetail" : "Line number 6" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 10 ,
"ruleNames" : [ "every-n-lines" ] ,
"ruleDescription" : "Rule that reports an error every N lines" ,
"errorDetail" : "Line number 10" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 12 ,
"ruleNames" : [ "every-n-lines" ] ,
"ruleDescription" : "Rule that reports an error every N lines" ,
"errorDetail" : "Line number 12" ,
"errorContext" : null ,
"errorRange" : null } ,
2018-02-25 16:04:13 -08:00
{ "lineNumber" : 1 ,
"ruleNames" : [ "first-line" ] ,
"ruleDescription" : "Rule that reports an error for the first line" ,
"errorDetail" : null ,
"errorContext" : null ,
"errorRange" : null } ,
2018-02-15 21:35:58 -08:00
{ "lineNumber" : 3 ,
"ruleNames" : [ "letters-E-X" , "letter-E-letter-X" , "contains-ex" ] ,
"ruleDescription" :
"Rule that reports an error for lines with the letters 'EX'" ,
"errorDetail" : null ,
"errorContext" : "text" ,
"errorRange" : null } ,
{ "lineNumber" : 7 ,
"ruleNames" : [ "letters-E-X" , "letter-E-letter-X" , "contains-ex" ] ,
"ruleDescription" :
"Rule that reports an error for lines with the letters 'EX'" ,
"errorDetail" : null ,
"errorContext" : "text" ,
"errorRange" : null }
] ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
2018-04-27 22:05:34 -07:00
const actualMessage = actualResult . toString ( ) ;
const expectedMessage =
2018-02-25 16:04:13 -08:00
"./test/custom-rules.md: 12: any-blockquote" +
" Rule that reports an error for any blockquote" +
2018-02-15 21:35:58 -08:00
" [Blockquote spans 1 line(s).] [Context: \"> Block\"]\n" +
"./test/custom-rules.md: 2: every-n-lines" +
" Rule that reports an error every N lines [Line number 2]\n" +
"./test/custom-rules.md: 4: every-n-lines" +
" Rule that reports an error every N lines [Line number 4]\n" +
"./test/custom-rules.md: 6: every-n-lines" +
" Rule that reports an error every N lines [Line number 6]\n" +
"./test/custom-rules.md: 10: every-n-lines" +
" Rule that reports an error every N lines [Line number 10]\n" +
"./test/custom-rules.md: 12: every-n-lines" +
" Rule that reports an error every N lines [Line number 12]\n" +
2018-02-25 16:04:13 -08:00
"./test/custom-rules.md: 1: first-line" +
" Rule that reports an error for the first line\n" +
2018-02-15 21:35:58 -08:00
"./test/custom-rules.md: 3: letters-E-X/letter-E-letter-X/contains-ex" +
" Rule that reports an error for lines with the letters 'EX'" +
" [Context: \"text\"]\n" +
"./test/custom-rules.md: 7: letters-E-X/letter-E-letter-X/contains-ex" +
" Rule that reports an error for lines with the letters 'EX'" +
" [Context: \"text\"]" ;
test . equal ( actualMessage , expectedMessage , "Incorrect message." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . customRulesConfig = function customRulesConfig ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const customRulesMd = "./test/custom-rules.md" ;
const options = {
2018-02-15 21:35:58 -08:00
"customRules" : customRules . all ,
"files" : [ customRulesMd ] ,
"config" : {
"blockquote" : true ,
"every-n-lines" : {
"n" : 3
} ,
"letters-e-x" : false
} ,
"resultVersion" : 0
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = { } ;
2018-02-15 21:35:58 -08:00
expectedResult [ customRulesMd ] = {
2018-02-25 16:04:13 -08:00
"any-blockquote" : [ 12 ] ,
2018-02-15 21:35:58 -08:00
"every-n-lines" : [ 3 , 6 , 12 ] ,
2018-02-25 16:04:13 -08:00
"first-line" : [ 1 ] ,
2018-02-15 21:35:58 -08:00
"letters-E-X" : [ 7 ]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2018-02-25 16:04:13 -08:00
2018-07-20 22:31:41 -07:00
module . exports . customRulesNpmPackage = function customRulesNpmPackage ( test ) {
test . expect ( 2 ) ;
const options = {
"customRules" : [ require ( "./rules/npm" ) ] ,
"strings" : {
"string" : "# Text\n\n---\n\nText"
} ,
"resultVersion" : 0
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
const expectedResult = { } ;
expectedResult . string = {
"sample-rule" : [ 3 ]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2018-02-25 16:04:13 -08:00
module . exports . customRulesBadProperty = function customRulesBadProperty ( test ) {
test . expect ( 76 ) ;
[
[ "names" , [ null , "string" , [ ] , [ null ] , [ "" ] , [ "string" , 10 ] ] ] ,
[ "description" , [ null , 10 , "" , [ ] ] ] ,
[ "tags" , [ null , "string" , [ ] , [ null ] , [ "" ] , [ "string" , 10 ] ] ] ,
[ "function" , [ null , "string" , [ ] ] ]
] . forEach ( function forProperty ( property ) {
2018-04-27 22:05:34 -07:00
const propertyName = property [ 0 ] ;
2018-02-25 16:04:13 -08:00
property [ 1 ] . forEach ( function forPropertyValue ( propertyValue ) {
2018-04-27 22:05:34 -07:00
const badRule = shared . clone ( customRules . anyBlockquote ) ;
2018-02-25 16:04:13 -08:00
badRule [ propertyName ] = propertyValue ;
2018-04-27 22:05:34 -07:00
const options = {
2018-02-25 16:04:13 -08:00
"customRules" : [ badRule ]
} ;
test . throws ( function badRuleCall ( ) {
markdownlint . sync ( options ) ;
} , function testError ( err ) {
test . ok ( err , "Did not get an error for missing property." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . message ,
"Property '" + propertyName +
"' of custom rule at index 0 is incorrect." ,
"Incorrect message for missing property." ) ;
return true ;
} , "Did not get exception for missing property." ) ;
} ) ;
} ) ;
test . done ( ) ;
} ;
module . exports . customRulesUsedNameName =
function customRulesUsedNameName ( test ) {
test . expect ( 4 ) ;
markdownlint ( {
"customRules" : [
{
"names" : [ "name" , "NO-missing-SPACE-atx" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function noop ( ) { }
}
]
} , function callback ( err , result ) {
test . ok ( err , "Did not get an error for duplicate name." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . message ,
"Name 'NO-missing-SPACE-atx' of custom rule at index 0 is " +
"already used as a name or tag." ,
"Incorrect message for duplicate name." ) ;
test . ok ( ! result , "Got result for duplicate name." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . customRulesUsedNameTag =
function customRulesUsedNameTag ( test ) {
test . expect ( 4 ) ;
markdownlint ( {
"customRules" : [
{
"names" : [ "name" , "HtMl" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function noop ( ) { }
}
]
} , function callback ( err , result ) {
test . ok ( err , "Did not get an error for duplicate name." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . message ,
"Name 'HtMl' of custom rule at index 0 is already used as a name or tag." ,
"Incorrect message for duplicate name." ) ;
test . ok ( ! result , "Got result for duplicate name." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . customRulesUsedTagName =
function customRulesUsedTagName ( test ) {
test . expect ( 4 ) ;
markdownlint ( {
"customRules" : [
{
"names" : [ "filler" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function noop ( ) { }
} ,
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" , "NO-missing-SPACE-atx" ] ,
"function" : function noop ( ) { }
}
]
} , function callback ( err , result ) {
test . ok ( err , "Did not get an error for duplicate tag." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . message ,
"Tag 'NO-missing-SPACE-atx' of custom rule at index 1 is " +
"already used as a name." ,
"Incorrect message for duplicate name." ) ;
test . ok ( ! result , "Got result for duplicate tag." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . customRulesThrowForFile =
function customRulesThrowForFile ( test ) {
test . expect ( 4 ) ;
2018-04-27 22:05:34 -07:00
const exceptionMessage = "Test exception message" ;
2018-02-25 16:04:13 -08:00
markdownlint ( {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function throws ( ) {
throw new Error ( exceptionMessage ) ;
}
}
] ,
"files" : [ "./test/custom-rules.md" ]
} , function callback ( err , result ) {
test . ok ( err , "Did not get an error for function thrown." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . message , exceptionMessage ,
"Incorrect message for function thrown." ) ;
test . ok ( ! result , "Got result for function thrown." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . customRulesThrowForFileSync =
function customRulesThrowForFileSync ( test ) {
test . expect ( 4 ) ;
2018-04-27 22:05:34 -07:00
const exceptionMessage = "Test exception message" ;
2018-02-25 16:04:13 -08:00
test . throws ( function customRuleThrowsCall ( ) {
markdownlint . sync ( {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function throws ( ) {
throw new Error ( exceptionMessage ) ;
}
}
] ,
"files" : [ "./test/custom-rules.md" ]
} ) ;
} , function testError ( err ) {
test . ok ( err , "Did not get an error for function thrown." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . message , exceptionMessage ,
"Incorrect message for function thrown." ) ;
return true ;
} , "Did not get exception for function thrown." ) ;
test . done ( ) ;
} ;
module . exports . customRulesThrowForString =
function customRulesThrowForString ( test ) {
test . expect ( 4 ) ;
2018-04-27 22:05:34 -07:00
const exceptionMessage = "Test exception message" ;
2018-02-25 16:04:13 -08:00
markdownlint ( {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function throws ( ) {
throw new Error ( exceptionMessage ) ;
}
}
] ,
2018-03-17 22:11:01 -07:00
"strings" : {
"string" : "String"
}
2018-02-25 16:04:13 -08:00
} , function callback ( err , result ) {
test . ok ( err , "Did not get an error for function thrown." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . message , exceptionMessage ,
"Incorrect message for function thrown." ) ;
test . ok ( ! result , "Got result for function thrown." ) ;
test . done ( ) ;
} ) ;
} ;
2018-02-27 21:14:02 -08:00
module . exports . customRulesOnErrorNull = function customRulesOnErrorNull ( test ) {
test . expect ( 4 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2018-02-27 21:14:02 -08:00
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function onErrorNull ( params , onError ) {
onError ( null ) ;
}
}
] ,
2018-03-17 22:11:01 -07:00
"strings" : {
"string" : "String"
}
2018-02-27 21:14:02 -08:00
} ;
test . throws ( function badErrorCall ( ) {
markdownlint . sync ( options ) ;
} , function testError ( err ) {
test . ok ( err , "Did not get an error for null object." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . message ,
"Property 'lineNumber' of onError parameter is incorrect." ,
"Incorrect message for bad object." ) ;
return true ;
} , "Did not get exception for null object." ) ;
test . done ( ) ;
} ;
module . exports . customRulesOnErrorBad = function customRulesOnErrorBad ( test ) {
2018-03-17 22:11:01 -07:00
test . expect ( 44 ) ;
2018-02-27 21:14:02 -08:00
[
[ "lineNumber" , [ null , "string" ] ] ,
2018-03-17 22:11:01 -07:00
[ "detail" , [ 10 , [ ] ] ] ,
[ "context" , [ 10 , [ ] ] ] ,
2018-02-27 21:14:02 -08:00
[ "range" , [ 10 , [ ] , [ 10 ] , [ 10 , null ] , [ 10 , 11 , 12 ] ] ]
] . forEach ( function forProperty ( property ) {
2018-04-27 22:05:34 -07:00
const propertyName = property [ 0 ] ;
2018-02-27 21:14:02 -08:00
property [ 1 ] . forEach ( function forPropertyValue ( propertyValue ) {
2018-04-27 22:05:34 -07:00
const badObject = {
2018-02-27 21:14:02 -08:00
"lineNumber" : 1
} ;
badObject [ propertyName ] = propertyValue ;
2018-04-27 22:05:34 -07:00
const options = {
2018-02-27 21:14:02 -08:00
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function onErrorBad ( params , onError ) {
onError ( badObject ) ;
}
}
] ,
2018-03-17 22:11:01 -07:00
"strings" : {
"string" : "String"
}
2018-02-27 21:14:02 -08:00
} ;
test . throws ( function badErrorCall ( ) {
markdownlint . sync ( options ) ;
} , function testError ( err ) {
test . ok ( err , "Did not get an error for bad object." ) ;
test . ok ( err instanceof Error , "Error not instance of Error." ) ;
test . equal ( err . message ,
"Property '" + propertyName + "' of onError parameter is incorrect." ,
"Incorrect message for bad object." ) ;
return true ;
} , "Did not get exception for bad object." ) ;
} ) ;
} ) ;
test . done ( ) ;
} ;
2018-03-03 22:15:49 -08:00
2018-03-17 22:11:01 -07:00
module . exports . customRulesOnErrorLazy = function customRulesOnErrorLazy ( test ) {
test . expect ( 2 ) ;
2018-04-27 22:05:34 -07:00
const options = {
2018-03-17 22:11:01 -07:00
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function onErrorNull ( params , onError ) {
onError ( {
"lineNumber" : 1 ,
"detail" : "" ,
"context" : "" ,
"range" : [ 0 , 0 ]
} ) ;
}
}
] ,
"strings" : {
"string" : "# Heading"
}
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expectedResult = {
2018-03-17 22:11:01 -07:00
"string" : [
{
"lineNumber" : 1 ,
"ruleNames" : [ "name" ] ,
"ruleDescription" : "description" ,
"errorDetail" : null ,
"errorContext" : null ,
"errorRange" : [ 0 , 0 ]
}
]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2018-05-25 17:28:56 -07:00
module . exports . customRulesFileName = function customRulesFileName ( test ) {
test . expect ( 2 ) ;
const options = {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function stringName ( params ) {
test . equal ( params . name , "doc/CustomRules.md" , "Incorrect file name" ) ;
}
}
] ,
"files" : "doc/CustomRules.md"
} ;
markdownlint ( options , function callback ( err ) {
test . ifError ( err ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . customRulesStringName = function customRulesStringName ( test ) {
test . expect ( 2 ) ;
const options = {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function stringName ( params ) {
test . equal ( params . name , "string" , "Incorrect string name" ) ;
}
}
] ,
"strings" : {
"string" : "# Heading"
}
} ;
markdownlint ( options , function callback ( err ) {
test . ifError ( err ) ;
test . done ( ) ;
} ) ;
} ;
2018-03-03 22:15:49 -08:00
module . exports . customRulesDoc = function customRulesDoc ( test ) {
test . expect ( 2 ) ;
markdownlint ( {
"files" : "doc/CustomRules.md" ,
"config" : {
"MD013" : { "line_length" : 200 }
}
} , function callback ( err , actual ) {
test . ifError ( err ) ;
2018-04-27 22:05:34 -07:00
const expected = { "doc/CustomRules.md" : [ ] } ;
2018-03-03 22:15:49 -08:00
test . deepEqual ( actual , expected , "Unexpected issues." ) ;
test . done ( ) ;
} ) ;
} ;