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" ) ;
2019-01-15 21:56:38 -08:00
const { URL } = require ( "url" ) ;
2018-04-27 22:05:34 -07:00
const md = require ( "markdown-it" ) ( ) ;
2019-01-19 12:52:13 -08:00
const pluginInline = require ( "markdown-it-for-inline" ) ;
2019-01-21 18:21:36 -08:00
const pluginKatex = require ( "markdown-it-katex" ) ;
2019-01-19 12:52:13 -08:00
const pluginSub = require ( "markdown-it-sub" ) ;
const pluginSup = require ( "markdown-it-sup" ) ;
2018-04-27 22:05:34 -07:00
const tv4 = require ( "tv4" ) ;
2019-01-15 21:56:38 -08:00
const packageJson = require ( "../package.json" ) ;
2018-04-27 22:05:34 -07:00
const markdownlint = require ( "../lib/markdownlint" ) ;
2019-04-13 11:18:57 -07:00
const helpers = require ( "../helpers" ) ;
2018-04-27 22:05:34 -07:00
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" ) ;
2019-01-15 21:56:38 -08:00
const homepage = packageJson . homepage ;
const version = packageJson . version ;
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 ) ;
}
2019-03-30 14:36:04 -07:00
return resolve ( result ) ;
2018-04-27 22:29:52 -07:00
} ) ;
} ) ;
}
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 ( ) {
2019-04-13 11:18:57 -07:00
return promisify ( fs . readFile , configFile , helpers . 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 ) {
2019-05-05 22:27:01 -07:00
const mergedConfig = {
... 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 ?
2019-04-13 11:18:57 -07:00
promisify ( fs . readFile , resultsFile , helpers . utf8Encoding )
2019-01-15 21:56:38 -08:00
. then (
function fileContents ( contents ) {
const errorObjects = JSON . parse ( contents ) ;
errorObjects . forEach ( function forObject ( errorObject ) {
if ( errorObject . ruleInformation ) {
errorObject . ruleInformation =
errorObject . ruleInformation . replace ( "v0.0.0" , ` v ${ version } ` ) ;
}
} ) ;
return errorObjects ;
} ) :
2019-04-13 11:18:57 -07:00
promisify ( fs . readFile , file , helpers . utf8Encoding )
2016-10-16 21:46:02 -07:00
. then (
function fileContents ( contents ) {
2019-04-13 11:18:57 -07:00
const lines = contents . split ( helpers . newLineRe ) ;
2018-04-27 22:05:34 -07:00
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" ,
2019-04-13 11:18:57 -07:00
"CONTRIBUTING.md" ,
"helpers/README.md"
2018-06-24 20:01:44 -07:00
] ,
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" : [ ] ,
2019-04-13 11:18:57 -07:00
"CONTRIBUTING.md" : [ ] ,
"helpers/README.md" : [ ]
2018-06-24 20:01:44 -07:00
} ;
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
] ,
2019-03-12 22:23:12 -07:00
"config" : {
"MD002" : true ,
"MD041" : false
} ,
2017-07-05 21:53:21 -07:00
"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
] ,
2019-03-12 22:23:12 -07:00
"config" : {
"MD002" : true ,
"MD041" : false
} ,
2016-10-16 21:46:02 -07:00
"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" :
2019-04-05 12:36:12 +02:00
"# Multiple spaces inside hashes on closed atx style heading #\n"
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
] ,
2019-03-12 22:23:12 -07:00
"config" : {
"MD002" : true ,
"MD041" : false
} ,
2018-01-12 23:21:06 -08:00
"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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md021 ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md002 ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md018 ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md019 ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md019 ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md002 ` ,
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" :
2019-04-05 12:36:12 +02:00
"# Multiple spaces inside hashes on closed atx style heading #\n"
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
] ,
2019-03-12 22:23:12 -07:00
"config" : {
"MD002" : true ,
"MD041" : false
}
2018-01-12 23:21:06 -08:00
} ;
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md021 ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md002 ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md018 ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md019 ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md019 ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md002 ` ,
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" : {
2019-04-05 12:36:12 +02:00
"cr" : "One\rTwo\r#Three\n" ,
"lf" : "One\nTwo\n#Three\n" ,
"crlf" : "One\r\nTwo\r\n#Three\n" ,
"mixed" : "One\rTwo\n#Three\n" ,
"crnel" : "One\r\u0085Two\r\u0085#Three\n" ,
"snl" : "One\u2424Two\u2424#Three\n" ,
"lsep" : "One\u2028Two\u2028#Three\n" ,
"nel" : "One\u0085Two\u0085#Three\n"
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
"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
"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
"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
"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
"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
"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 ] ,
"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 ] ,
2019-01-21 18:21:36 -08:00
"MD032" : [ 7 , 8 , 51 ] ,
2015-04-16 09:39:04 -07:00
"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 ] ,
2019-04-17 14:42:17 -07:00
"MD045" : [ 81 ] ,
2019-04-05 12:36:12 +02:00
"MD046" : [ 49 , 73 ] ,
"MD047" : [ 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 ] ,
"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 ] ,
2019-01-21 18:21:36 -08:00
"MD032" : [ 7 , 8 , 51 ] ,
2015-04-16 09:39:04 -07:00
"MD035" : [ 61 ] ,
2016-06-27 22:19:02 -07:00
"MD036" : [ 65 ] ,
2018-01-08 21:29:13 -08:00
"MD042" : [ 77 ] ,
2019-04-17 14:42:17 -07:00
"MD045" : [ 81 ] ,
2019-04-05 12:36:12 +02:00
"MD046" : [ 49 , 73 ] ,
"MD047" : [ 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-->" ,
"" ,
2019-04-05 12:36:12 +02:00
"\tTab\n"
2017-05-21 22:58:10 -07:00
] . 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" ,
2019-01-19 12:52:13 -08:00
"##### options.markdownItPlugins" ,
2017-05-19 22:36:46 -07:00
"#### 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 ) {
2019-04-05 12:36:12 +02:00
test . expect ( 113 ) ;
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 ;
} ) ;
} ) ;
2019-04-13 11:18:57 -07:00
fs . readFile ( "README.md" , helpers . utf8Encoding ,
2015-03-17 22:34:47 -07:00
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 ) {
2019-03-30 14:36:04 -07:00
seenRules = true ;
inRules = true ;
2016-01-14 22:15:44 -08:00
} else if ( seenRelated && seenRules && ! seenTags ) {
2019-03-30 14:36:04 -07:00
seenTags = true ;
inTags = true ;
2015-03-17 22:34:47 -07:00
}
} else if ( token . type === "bullet_list_close" ) {
2019-03-30 14:36:04 -07:00
inRules = false ;
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 ) {
2019-04-05 12:36:12 +02:00
test . expect ( 327 ) ;
2019-04-13 11:18:57 -07:00
fs . readFile ( "doc/Rules.md" , helpers . utf8Encoding ,
2015-03-17 22:34:47 -07:00
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 ( ) ;
2019-03-30 14:36:04 -07:00
ruleHasTags = false ;
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" ,
"<!--" ,
" \\"
] ;
2019-04-13 11:18:57 -07:00
const actual = helpers . clearHtmlCommentText ( validComments . join ( "\n" ) ) ;
2018-04-27 22:05:34 -07:00
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-->"
] ;
2019-04-13 11:18:57 -07:00
const actual = helpers . clearHtmlCommentText ( invalidComments . join ( "\n" ) ) ;
2018-04-27 22:05:34 -07:00
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
"<!-- --> -->" ,
"<!-- --> -->" ,
"<!-- --> -->" ,
"<!----> -->"
] ;
2019-04-13 11:18:57 -07:00
const actual = helpers . clearHtmlCommentText ( nonGreedyComments . join ( "\n" ) ) ;
2018-04-27 22:05:34 -07:00
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"
] ;
2019-04-13 11:18:57 -07:00
const actual = helpers . clearHtmlCommentText ( embeddedComments . join ( "\n" ) ) ;
2018-04-27 22:05:34 -07:00
const expected = embeddedResult . join ( "\n" ) ;
2017-07-16 23:08:47 -07:00
test . equal ( actual , expected ) ;
test . done ( ) ;
} ;
2019-04-29 22:09:03 -07:00
module . exports . unescapeMarkdown = function unescapeMarkdown ( test ) {
test . expect ( 7 ) ;
// Test cases from https://spec.commonmark.org/0.29/#backslash-escapes
const testCases = [
[
"\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\-\\.\\/\\:\\;" +
"\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\`\\{\\|\\}\\~" ,
"!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
] ,
[
"\\→\\A\\a\\ \\3\\φ\\«" ,
"\\→\\A\\a\\ \\3\\φ\\«"
] ,
[
` \\ *not emphasized*
\ \ < br / > not a tag
\ \ [ not a link ] ( / f o o )
\ \ \ ` not code \`
1 \ \ . not a list
\ \ * not a list
\ \ # not a heading
\ \ [ foo ] : / u r l " n o t a r e f e r e n c e "
\ \ & ouml ; not a character entity ` ,
` *not emphasized*
< br / > not a tag
[ not a link ] ( / f o o )
\ ` not code \`
1. not a list
* not a list
# not a heading
[ foo ] : / u r l " n o t a r e f e r e n c e "
& ouml ; not a character entity `
] ,
[
"\\\\*emphasis*" ,
"\\*emphasis*"
] ,
[
` foo \\
bar ` ,
` foo \\
bar `
] ,
[
"Text \\<" ,
"Text _" ,
"_"
] ,
[
"Text \\\\<" ,
"Text _<" ,
"_"
]
] ;
testCases . forEach ( function forTestCase ( testCase ) {
const [ markdown , expected , replacement ] = testCase ;
const actual = helpers . unescapeMarkdown ( markdown , replacement ) ;
test . equal ( actual , expected ) ;
} ) ;
test . done ( ) ;
} ;
2019-03-20 21:48:18 -07:00
module . exports . isBlankLine = function isBlankLine ( test ) {
test . expect ( 25 ) ;
const blankLines = [
null ,
"" ,
" " ,
" " ,
"\t\t\t" ,
"\r" ,
"\n" ,
"\t\r\n" ,
" <!-- text --> " ,
"<!--text-->" ,
"<!---->" ,
"<!-- text -->\t<!-- text -->" ,
">" ,
"> " ,
"> > > \t" ,
"> <!--text-->" ,
">><!--text-->"
] ;
2019-04-13 11:18:57 -07:00
blankLines . forEach ( ( line ) => test . ok ( helpers . isBlankLine ( line ) , line ) ) ;
2019-03-20 21:48:18 -07:00
const nonBlankLines = [
"text" ,
" text " ,
"." ,
"> ." ,
"<!--text--> text" ,
"<!--->" ,
"<!--" ,
"-->"
] ;
2019-04-13 11:18:57 -07:00
nonBlankLines . forEach ( ( line ) => test . ok ( ! helpers . isBlankLine ( line ) , line ) ) ;
2019-03-20 21:48:18 -07:00
test . done ( ) ;
} ;
2019-03-28 22:06:42 -07:00
module . exports . includesSorted = function includesSorted ( test ) {
test . expect ( 154 ) ;
const inputs = [
[ ] ,
[ 8 ] ,
[ 7 , 11 ] ,
[ 0 , 1 , 2 , 3 , 5 , 8 , 13 ] ,
[ 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 ] ,
[ 1 , 3 , 5 , 7 , 9 , 11 , 13 , 15 , 17 , 19 ] ,
[ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 ]
] ;
inputs . forEach ( ( input ) => {
for ( let i = 0 ; i <= 21 ; i ++ ) {
2019-04-13 11:18:57 -07:00
test . equal ( helpers . includesSorted ( input , i ) , input . includes ( i ) ) ;
2019-03-28 22:06:42 -07:00
}
} ) ;
test . done ( ) ;
} ;
2019-01-30 22:09:20 -08:00
module . exports . forEachInlineCodeSpan = function forEachInlineCodeSpan ( test ) {
test . expect ( 94 ) ;
const testCases =
[
[
"`code`" ,
[ [ "code" , 0 , 1 , 1 ] ]
] ,
[
"text `code` text" ,
[ [ "code" , 0 , 6 , 1 ] ]
] ,
[
"text `code` text `edoc`" ,
[
[ "code" , 0 , 6 , 1 ] ,
[ "edoc" , 0 , 18 , 1 ]
]
] ,
[
"text `code` text `edoc` text" ,
[
[ "code" , 0 , 6 , 1 ] ,
[ "edoc" , 0 , 18 , 1 ]
]
] ,
[
"text ``code`code`` text" ,
[ [ "code`code" , 0 , 7 , 2 ] ]
] ,
[
"`code `` code`" ,
[ [ "code `` code" , 0 , 1 , 1 ] ]
] ,
[
"`code\\`text`" ,
[ [ "code\\" , 0 , 1 , 1 ] ]
] ,
[
"``\ncode\n``" ,
[ [ "\ncode\n" , 0 , 2 , 2 ] ]
] ,
[
"text\n`code`\ntext" ,
[ [ "code" , 1 , 1 , 1 ] ]
] ,
[
"text\ntext\n`code`\ntext\n`edoc`\ntext" ,
[
[ "code" , 2 , 1 , 1 ] ,
[ "edoc" , 4 , 1 , 1 ]
]
] ,
[
"text `code\nedoc` text" ,
[ [ "code\nedoc" , 0 , 6 , 1 ] ]
] ,
[
"> text `code` text" ,
[ [ "code" , 0 , 8 , 1 ] ]
] ,
[
"> text\n> `code`\n> text" ,
[ [ "code" , 1 , 3 , 1 ] ]
] ,
[
"> text\n> `code\n> edoc`\n> text" ,
[ [ "code\n> edoc" , 1 , 3 , 1 ] ]
] ,
[
"```text``" ,
[ ]
] ,
[
"text `text text" ,
[ ]
] ,
[
"`text``code``" ,
[ [ "code" , 0 , 7 , 2 ] ]
] ,
[
"text \\` text `code`" ,
[ [ "code" , 0 , 14 , 1 ] ]
]
] ;
testCases . forEach ( ( testCase ) => {
const [ input , expecteds ] = testCase ;
2019-04-13 11:18:57 -07:00
helpers . forEachInlineCodeSpan ( input , ( code , line , column , ticks ) => {
2019-01-30 22:09:20 -08:00
const [ expectedCode , expectedLine , expectedColumn , expectedTicks ] =
expecteds . shift ( ) ;
test . equal ( code , expectedCode , input ) ;
test . equal ( line , expectedLine , input ) ;
test . equal ( column , expectedColumn , input ) ;
test . equal ( ticks , expectedTicks , input ) ;
} ) ;
test . equal ( expecteds . length , 0 , "length" ) ;
} ) ;
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 ) ;
2019-05-05 22:27:01 -07:00
const expected = {
... 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 ) ;
2019-05-05 22:27:01 -07:00
const expected = {
... require ( "./config/config-child.json" ) ,
... require ( "./config/config-parent.json" ) ,
... require ( "./config/config-grandparent.json" )
} ;
2018-05-23 22:24:40 -07:00
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 ) ;
2019-05-05 22:27:01 -07:00
const expected = {
... require ( "./config/config-child.json" ) ,
... require ( "./config/config-parent.json" ) ,
... require ( "./config/config-grandparent.json" )
} ;
2018-05-23 22:24:40 -07:00
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" ) ;
2019-05-05 22:27:01 -07:00
const expected = {
... 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 ] ) ;
2019-05-05 22:27:01 -07:00
const expected = {
... require ( "./config/config-child.json" ) ,
... require ( "./config/config-parent.json" ) ,
... require ( "./config/config-grandparent.json" )
} ;
2018-05-23 22:24:40 -07:00
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 ] ) ;
2019-05-05 22:27:01 -07:00
const expected = {
... require ( "./config/config-child.json" ) ,
... require ( "./config/config-parent.json" ) ,
... require ( "./config/config-grandparent.json" )
} ;
2018-05-23 22:24:40 -07:00
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 ( ) ;
} ;
2019-01-15 21:56:38 -08:00
module . exports . allBuiltInRulesHaveValidUrl =
function allBuiltInRulesHaveValidUrl ( test ) {
2019-04-05 12:36:12 +02:00
test . expect ( 129 ) ;
2019-01-15 21:56:38 -08:00
rules . forEach ( function forRule ( rule ) {
test . ok ( rule . information ) ;
test . ok ( Object . getPrototypeOf ( rule . information ) === URL . prototype ) ;
const name = rule . names [ 0 ] . toLowerCase ( ) ;
test . equal (
rule . information . href ,
` ${ homepage } /blob/v ${ version } /doc/Rules.md# ${ name } `
) ;
} ) ;
test . done ( ) ;
} ;
module . exports . someCustomRulesHaveValidUrl =
function someCustomRulesHaveValidUrl ( test ) {
test . expect ( 6 ) ;
customRules . all . forEach ( function forRule ( rule ) {
test . ok ( ! rule . information ||
( Object . getPrototypeOf ( rule . information ) === URL . prototype ) ) ;
if ( rule === customRules . anyBlockquote ) {
test . equal (
rule . information ,
` ${ homepage } /blob/master/test/rules/any-blockquote.js `
) ;
} else if ( rule === customRules . lettersEX ) {
test . equal (
rule . information ,
` ${ homepage } /blob/master/test/rules/letters-E-X.js `
) ;
}
} ) ;
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" :
` ${ homepage } /blob/master/test/rules/any-blockquote.js ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-15 21:35:58 -08:00
"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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-15 21:35:58 -08:00
"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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-15 21:35:58 -08:00
"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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-15 21:35:58 -08:00
"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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-15 21:35:58 -08:00
"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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-25 16:04:13 -08:00
"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'" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/master/test/rules/letters-E-X.js ` ,
2018-02-15 21:35:58 -08:00
"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'" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/master/test/rules/letters-E-X.js ` ,
2018-02-15 21:35:58 -08:00
"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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" :
` ${ homepage } /blob/master/test/rules/any-blockquote.js ` ,
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-15 21:35:58 -08:00
"errorDetail" : "Line number 2" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 4 ,
"ruleNames" : [ "every-n-lines" ] ,
"ruleDescription" : "Rule that reports an error every N lines" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-15 21:35:58 -08:00
"errorDetail" : "Line number 4" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 6 ,
"ruleNames" : [ "every-n-lines" ] ,
"ruleDescription" : "Rule that reports an error every N lines" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-15 21:35:58 -08:00
"errorDetail" : "Line number 6" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 10 ,
"ruleNames" : [ "every-n-lines" ] ,
"ruleDescription" : "Rule that reports an error every N lines" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-15 21:35:58 -08:00
"errorDetail" : "Line number 10" ,
"errorContext" : null ,
"errorRange" : null } ,
{ "lineNumber" : 12 ,
"ruleNames" : [ "every-n-lines" ] ,
"ruleDescription" : "Rule that reports an error every N lines" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-15 21:35:58 -08:00
"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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-02-25 16:04:13 -08:00
"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'" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/master/test/rules/letters-E-X.js ` ,
2018-02-15 21:35:58 -08:00
"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'" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : ` ${ homepage } /blob/master/test/rules/letters-E-X.js ` ,
2018-02-15 21:35:58 -08:00
"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" : {
2019-04-05 12:36:12 +02:00
"string" : "# Text\n\n---\n\nText\n"
2018-07-20 22:31:41 -07:00
} ,
"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 ) {
2019-01-15 21:56:38 -08:00
test . expect ( 92 ) ;
2018-02-25 16:04:13 -08:00
[
[ "names" , [ null , "string" , [ ] , [ null ] , [ "" ] , [ "string" , 10 ] ] ] ,
[ "description" , [ null , 10 , "" , [ ] ] ] ,
2019-01-15 21:56:38 -08:00
[ "information" , [ 10 , [ ] , "string" , "https://example.com" ] ] ,
2018-02-25 16:04:13 -08:00
[ "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 ) {
2019-05-05 22:27:01 -07:00
const badRule = { ... 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
} ;
2019-04-23 22:30:33 -07:00
test . throws ( function nullErrorCall ( ) {
2018-02-27 21:14:02 -08:00
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." ,
2019-04-23 22:30:33 -07:00
"Incorrect message for null object." ) ;
2018-02-27 21:14:02 -08:00
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
2019-04-23 22:30:33 -07:00
module . exports . customRulesOnErrorInvalid =
function customRulesOnErrorInvalid ( test ) {
test . expect ( 36 ) ;
[
[ "lineNumber" , [ - 1 , 0 , 3 , 4 ] ] ,
[ "range" , [ [ 0 , 1 ] , [ 1 , 0 ] , [ 5 , 1 ] , [ 1 , 5 ] , [ 4 , 2 ] ] ]
] . forEach ( function forProperty ( property ) {
const propertyName = property [ 0 ] ;
property [ 1 ] . forEach ( function forPropertyValue ( propertyValue ) {
const badObject = {
"lineNumber" : 1
} ;
badObject [ propertyName ] = propertyValue ;
const options = {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function onErrorInvalid ( params , onError ) {
onError ( badObject ) ;
}
}
] ,
"strings" : {
"string" : "Text\ntext"
}
} ;
test . throws ( function invalidErrorCall ( ) {
markdownlint . sync ( options ) ;
} , function testError ( err ) {
test . ok ( err , "Did not get an error for invalid 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 invalid object." ) ;
return true ;
} , "Did not get exception for invalid object." ) ;
} ) ;
} ) ;
test . done ( ) ;
} ;
module . exports . customRulesOnErrorValid =
function customRulesOnErrorValid ( test ) {
test . expect ( 7 ) ;
[
[ "lineNumber" , [ 1 , 2 ] ] ,
[ "range" , [ [ 1 , 1 ] , [ 1 , 4 ] , [ 2 , 2 ] , [ 3 , 2 ] , [ 4 , 1 ] ] ]
] . forEach ( function forProperty ( property ) {
const propertyName = property [ 0 ] ;
property [ 1 ] . forEach ( function forPropertyValue ( propertyValue ) {
const goodObject = {
"lineNumber" : 1
} ;
goodObject [ propertyName ] = propertyValue ;
const options = {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function onErrorValid ( params , onError ) {
onError ( goodObject ) ;
}
}
] ,
"strings" : {
"string" : "Text\ntext"
}
} ;
markdownlint . sync ( options ) ;
test . ok ( true ) ;
} ) ;
} ) ;
test . done ( ) ;
} ;
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" : "" ,
2019-04-23 22:30:33 -07:00
"range" : [ 1 , 1 ]
2018-03-17 22:11:01 -07:00
} ) ;
}
}
] ,
"strings" : {
2019-04-05 12:36:12 +02:00
"string" : "# Heading\n"
2018-03-17 22:11:01 -07:00
}
} ;
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" ,
2019-01-15 21:56:38 -08:00
"ruleInformation" : null ,
2018-03-17 22:11:01 -07:00
"errorDetail" : null ,
"errorContext" : null ,
2019-04-23 22:30:33 -07:00
"errorRange" : [ 1 , 1 ]
2018-03-17 22:11:01 -07:00
}
]
} ;
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 ( ) ;
} ) ;
} ;
2019-01-19 12:52:13 -08:00
module . exports . markdownItPluginsSingle =
function markdownItPluginsSingle ( test ) {
test . expect ( 2 ) ;
markdownlint ( {
"strings" : {
2019-04-05 12:36:12 +02:00
"string" : "# Heading\n\nText [ link ](https://example.com)\n"
2019-01-19 12:52:13 -08:00
} ,
"markdownItPlugins" : [
[
pluginInline ,
"trim_text_plugin" ,
"text" ,
function iterator ( tokens , index ) {
tokens [ index ] . content = tokens [ index ] . content . trim ( ) ;
}
]
]
} , function callback ( err , actual ) {
test . ifError ( err ) ;
const expected = { "string" : [ ] } ;
test . deepEqual ( actual , expected , "Unexpected issues." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . markdownItPluginsMultiple =
function markdownItPluginsMultiple ( test ) {
test . expect ( 4 ) ;
markdownlint ( {
"strings" : {
2019-04-05 12:36:12 +02:00
"string" : "# Heading\n\nText H~2~0 text 29^th^ text\n"
2019-01-19 12:52:13 -08:00
} ,
"markdownItPlugins" : [
[ pluginSub ] ,
[ pluginSup ] ,
[ pluginInline , "check_sub_plugin" , "sub_open" , test . ok ] ,
[ pluginInline , "check_sup_plugin" , "sup_open" , test . ok ]
]
} , function callback ( err , actual ) {
test . ifError ( err ) ;
const expected = { "string" : [ ] } ;
test . deepEqual ( actual , expected , "Unexpected issues." ) ;
test . done ( ) ;
} ) ;
} ;
module . exports . markdownItPluginsMathjax =
function markdownItPluginsMathjax ( test ) {
test . expect ( 2 ) ;
markdownlint ( {
"strings" : {
"string" :
"# Heading\n" +
"\n" +
"$1 *2* 3$\n" +
"\n" +
"$$1 *2* 3$$\n" +
"\n" +
"$$1\n" +
"+ 2\n" +
"+ 3$$\n"
} ,
2019-01-21 18:21:36 -08:00
"markdownItPlugins" : [ [ pluginKatex ] ]
2019-01-19 12:52:13 -08:00
} , function callback ( err , actual ) {
test . ifError ( err ) ;
2019-01-21 18:21:36 -08:00
const expected = { "string" : [ ] } ;
2019-01-19 12:52:13 -08:00
test . deepEqual ( actual , expected , "Unexpected issues." ) ;
test . done ( ) ;
} ) ;
} ;
2019-02-13 19:52:34 -08:00
module . exports . markdownItPluginsMathjaxIssue166 =
function markdownItPluginsMathjaxIssue166 ( test ) {
test . expect ( 2 ) ;
markdownlint ( {
"strings" : {
"string" :
` ## Heading
$$
1
$$$$
2
2019-04-05 12:36:12 +02:00
$$ \ n `
2019-02-13 19:52:34 -08:00
} ,
"markdownItPlugins" : [ [ pluginKatex ] ] ,
"resultVersion" : 0
} , function callback ( err , actual ) {
test . ifError ( err ) ;
const expected = {
"string" : {
"MD041" : [ 1 ]
}
} ;
test . deepEqual ( actual , expected , "Unexpected issues." ) ;
test . done ( ) ;
} ) ;
} ;