2019-10-30 20:37:06 -07:00
// @ts-check
2015-02-23 23:39:20 -08:00
"use strict" ;
2018-04-27 22:05:34 -07:00
const fs = require ( "fs" ) ;
2019-09-14 22:31:08 -07:00
const os = require ( "os" ) ;
2018-04-27 22:05:34 -07:00
const path = require ( "path" ) ;
2019-01-15 21:56:38 -08:00
const { URL } = require ( "url" ) ;
2020-01-09 21:06:22 -08:00
const { promisify } = require ( "util" ) ;
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" ) ;
2020-01-08 22:13:51 -08:00
const tape = require ( "tape" ) ;
2020-01-09 20:57:14 -08:00
require ( "./tape-reporter" ) ;
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
2020-01-13 19:19:49 -08:00
const deprecatedRuleNames = [ "MD002" , "MD006" ] ;
2019-07-08 13:10:08 -05:00
2015-02-23 23:39:20 -08:00
function createTestForFile ( file ) {
2020-01-09 21:06:22 -08:00
const markdownlintPromise = promisify ( markdownlint ) ;
2015-02-24 18:40:37 -08:00
return function testForFile ( test ) {
2018-04-27 22:05:34 -07:00
const detailedResults = /[/\\]detailed-results-/ . test ( file ) ;
2020-01-08 22:13:51 -08:00
test . plan ( detailedResults ? 3 : 2 ) ;
2018-04-27 22:05:34 -07:00
const resultsFile = file . replace ( /\.md$/ , ".results.json" ) ;
2019-09-16 21:48:34 -07:00
const fixedFile = file . replace ( /\.md$/ , ".md.fixed" ) ;
2018-04-27 22:05:34 -07:00
const configFile = file . replace ( /\.md$/ , ".json" ) ;
2019-08-16 19:56:52 -07:00
let mergedConfig = null ;
2020-01-09 21:06:22 -08:00
const actualPromise = fs . promises . stat ( configFile )
2015-03-01 22:15:02 -08:00
. then (
function configFileExists ( ) {
2020-01-09 21:06:22 -08:00
return fs . promises . 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-08-16 19:56:52 -07:00
mergedConfig = {
2019-05-05 22:27:01 -07:00
... defaultConfig ,
... config
} ;
2020-01-09 21:06:22 -08:00
return markdownlintPromise ( {
2015-03-01 22:15:02 -08:00
"files" : [ file ] ,
2016-10-16 21:46:02 -07:00
"config" : mergedConfig ,
2019-08-16 19:56:52 -07:00
"resultVersion" : detailedResults ? 2 : 3
2015-03-01 22:15:02 -08:00
} ) ;
2019-08-16 19:56:52 -07:00
} )
. then (
2019-09-16 21:48:34 -07:00
function diffFixedFiles ( resultVersion2or3 ) {
return detailedResults ?
Promise . all ( [
2020-01-09 21:06:22 -08:00
markdownlintPromise ( {
2019-09-16 21:48:34 -07:00
"files" : [ file ] ,
"config" : mergedConfig ,
"resultVersion" : 3
} ) ,
2020-01-09 21:06:22 -08:00
fs . promises . readFile ( file , helpers . utf8Encoding ) ,
fs . promises . readFile ( fixedFile , helpers . utf8Encoding )
2019-09-16 21:48:34 -07:00
] )
. then ( function validateApplyFixes ( fulfillments ) {
const [ resultVersion3 , content , expected ] = fulfillments ;
const errors = resultVersion3 [ file ] ;
const actual = helpers . applyFixes ( content , errors ) ;
// Uncomment the following line to update *.md.fixed files
// fs.writeFileSync(fixedFile, actual, helpers.utf8Encoding);
test . equal ( actual , expected ,
"Unexpected output from applyFixes." ) ;
return resultVersion2or3 ;
} ) :
resultVersion2or3 ;
}
)
. then (
function convertResultVersion2To0 ( resultVersion2or3 ) {
2019-08-16 19:56:52 -07:00
const result0 = { } ;
2019-09-16 21:48:34 -07:00
const result2or3 = resultVersion2or3 [ file ] ;
2019-08-16 19:56:52 -07:00
result2or3 . forEach ( function forResult ( result ) {
const ruleName = result . ruleNames [ 0 ] ;
const lineNumbers = result0 [ ruleName ] || [ ] ;
2019-08-21 21:02:09 -07:00
if ( ! lineNumbers . includes ( result . lineNumber ) ) {
lineNumbers . push ( result . lineNumber ) ;
}
2019-08-16 19:56:52 -07:00
result0 [ ruleName ] = lineNumbers ;
} ) ;
return [ result0 , result2or3 ] ;
}
) ;
2018-04-27 22:05:34 -07:00
const expectedPromise = detailedResults ?
2020-01-09 21:06:22 -08:00
fs . promises . readFile ( resultsFile , helpers . utf8Encoding )
2019-01-15 21:56:38 -08:00
. then (
function fileContents ( contents ) {
2020-01-11 20:48:00 -08:00
// @ts-ignore
2019-01-15 21:56:38 -08:00
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 ;
} ) :
2020-01-09 21:06:22 -08:00
fs . promises . readFile ( file , helpers . utf8Encoding )
2016-10-16 21:46:02 -07:00
. then (
function fileContents ( contents ) {
2020-01-11 20:48:00 -08:00
// @ts-ignore
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 ) {
2019-08-16 19:56:52 -07:00
const [ [ actual0 , actual2or3 ] , expected ] = fulfillments ;
const actual = detailedResults ? actual2or3 : actual0 ;
2015-03-01 22:15:02 -08:00
test . deepEqual ( actual , expected , "Line numbers are not correct." ) ;
2019-08-16 19:56:52 -07:00
return actual2or3 ;
} )
. then (
2019-09-12 21:50:40 -07:00
function verifyFixes ( errors ) {
2019-08-16 19:56:52 -07:00
if ( detailedResults ) {
return test . ok ( true ) ;
}
2020-01-09 21:06:22 -08:00
return fs . promises . readFile ( file , helpers . utf8Encoding )
2019-08-16 19:56:52 -07:00
. then (
2019-09-12 21:50:40 -07:00
function applyFixes ( content ) {
const corrections = helpers . applyFixes ( content , errors ) ;
2020-01-09 21:06:22 -08:00
return markdownlintPromise ( {
2019-08-16 19:56:52 -07:00
"strings" : {
"input" : corrections
} ,
"config" : mergedConfig ,
"resultVersion" : 3
} ) ;
} )
. then (
2019-09-12 21:50:40 -07:00
function checkFixes ( newErrors ) {
2019-08-16 19:56:52 -07:00
const unfixed = newErrors . input
. filter ( ( error ) => ! ! error . fixInfo ) ;
test . deepEqual ( unfixed , [ ] , "Fixable error was not fixed." ) ;
}
) ;
2015-03-01 22:15:02 -08:00
} )
2018-04-27 22:29:52 -07:00
. catch ( )
. then ( test . done ) ;
2015-02-23 23:39:20 -08:00
} ;
}
2020-01-08 22:13:51 -08:00
fs . readdirSync ( "./test" )
. filter ( ( file ) => / \ . md$ / . test ( file ) )
. forEach ( ( file ) => tape ( file , createTestForFile ( path . join ( "./test" , file ) ) ) ) ;
2015-03-11 21:13:21 -07:00
2020-01-08 22:13:51 -08:00
tape ( "projectFiles" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-12 23:42:06 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-12 23:42:06 -07:00
2020-01-08 22:13:51 -08:00
tape ( "resultFormattingV0" , ( test ) => {
test . plan ( 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)." ) ;
2019-11-10 19:26:55 -08:00
// @ts-ignore
2016-01-12 21:29:17 -08:00
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)." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-13 09:13:07 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-13 09:13:07 -07:00
2020-01-08 22:13:51 -08:00
tape ( "resultFormattingSyncV0" , ( test ) => {
test . plan ( 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)." ) ;
2020-01-11 20:48:00 -08:00
// @ts-ignore
2016-01-12 21:29:17 -08:00
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)." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2015-03-20 00:09:55 -07:00
2020-01-08 22:13:51 -08:00
tape ( "resultFormattingV1" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2016-10-16 21:46:02 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2016-10-16 21:46:02 -07:00
2020-01-08 22:13:51 -08:00
tape ( "resultFormattingV2" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-01-12 23:21:06 -08:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-01-12 23:21:06 -08:00
2020-01-08 22:13:51 -08:00
tape ( "resultFormattingV3" , ( test ) => {
test . plan ( 3 ) ;
2019-08-16 19:56:52 -07:00
const options = {
"strings" : {
2019-08-24 22:55:51 -07:00
"input" :
"# Heading \n" +
"\n" +
2019-09-22 21:58:57 -07:00
"Text\ttext\t\ttext\n" +
"Text * emphasis * text"
2019-08-16 19:56:52 -07:00
} ,
"resultVersion" : 3
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
const expectedResult = {
"input" : [
{
"lineNumber" : 1 ,
2019-08-24 22:55:51 -07:00
"ruleNames" : [ "MD009" , "no-trailing-spaces" ] ,
"ruleDescription" : "Trailing spaces" ,
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md009 ` ,
"errorDetail" : "Expected: 0 or 2; Actual: 3" ,
"errorContext" : null ,
"errorRange" : [ 10 , 3 ] ,
"fixInfo" : {
"editColumn" : 10 ,
"deleteCount" : 3
}
} ,
{
"lineNumber" : 3 ,
"ruleNames" : [ "MD010" , "no-hard-tabs" ] ,
"ruleDescription" : "Hard tabs" ,
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md010 ` ,
"errorDetail" : "Column: 5" ,
"errorContext" : null ,
"errorRange" : [ 5 , 1 ] ,
"fixInfo" : {
"editColumn" : 5 ,
"deleteCount" : 1 ,
"insertText" : " "
}
} ,
{
"lineNumber" : 3 ,
"ruleNames" : [ "MD010" , "no-hard-tabs" ] ,
"ruleDescription" : "Hard tabs" ,
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md010 ` ,
"errorDetail" : "Column: 10" ,
"errorContext" : null ,
"errorRange" : [ 10 , 2 ] ,
"fixInfo" : {
"editColumn" : 10 ,
"deleteCount" : 2 ,
"insertText" : " "
}
} ,
{
2019-09-22 21:58:57 -07:00
"lineNumber" : 4 ,
"ruleNames" : [ "MD037" , "no-space-in-emphasis" ] ,
"ruleDescription" : "Spaces inside emphasis markers" ,
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md037 ` ,
"errorDetail" : null ,
"errorContext" : "* emphasis *" ,
"errorRange" : [ 6 , 12 ] ,
"fixInfo" : {
"editColumn" : 6 ,
"deleteCount" : 12 ,
"insertText" : "*emphasis*"
}
} ,
{
"lineNumber" : 4 ,
2019-08-16 19:56:52 -07:00
"ruleNames" : [ "MD047" , "single-trailing-newline" ] ,
"ruleDescription" : "Files should end with a single newline character" ,
"ruleInformation" : ` ${ homepage } /blob/v ${ version } /doc/Rules.md#md047 ` ,
"errorDetail" : null ,
"errorContext" : null ,
2019-09-22 21:58:57 -07:00
"errorRange" : [ 22 , 1 ] ,
2019-08-16 19:56:52 -07:00
"fixInfo" : {
"insertText" : "\n" ,
2019-09-22 21:58:57 -07:00
"editColumn" : 23
2019-08-16 19:56:52 -07:00
}
}
]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
const actualMessage = actualResult . toString ( ) ;
const expectedMessage =
2019-08-24 22:55:51 -07:00
"input: 1: MD009/no-trailing-spaces" +
" Trailing spaces [Expected: 0 or 2; Actual: 3]\n" +
"input: 3: MD010/no-hard-tabs" +
" Hard tabs [Column: 5]\n" +
"input: 3: MD010/no-hard-tabs" +
" Hard tabs [Column: 10]\n" +
2019-09-22 21:58:57 -07:00
"input: 4: MD037/no-space-in-emphasis" +
" Spaces inside emphasis markers [Context: \"* emphasis *\"]\n" +
"input: 4: MD047/single-trailing-newline" +
2019-08-16 19:56:52 -07:00
" Files should end with a single newline character" ;
test . equal ( actualMessage , expectedMessage , "Incorrect message." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2019-08-16 19:56:52 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2019-08-16 19:56:52 -07:00
2020-01-08 22:13:51 -08:00
tape ( "onePerLineResultVersion0" , ( test ) => {
test . plan ( 2 ) ;
const options = {
"strings" : {
"input" : "# Heading\theading\t\theading\n"
} ,
"resultVersion" : 0
2019-08-21 21:02:09 -07:00
} ;
2020-01-08 22:13:51 -08:00
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
const expectedResult = {
"input" : {
"MD010" : [ 1 ]
}
2019-08-21 21:02:09 -07:00
} ;
2020-01-08 22:13:51 -08:00
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
2019-08-21 21:02:09 -07:00
2020-01-08 22:13:51 -08:00
tape ( "onePerLineResultVersion1" , ( test ) => {
test . plan ( 2 ) ;
const options = {
"strings" : {
"input" : "# Heading\theading\t\theading\n"
} ,
"resultVersion" : 1
2019-08-21 21:02:09 -07:00
} ;
2020-01-08 22:13:51 -08:00
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
const expectedResult = {
"input" : [
{
"lineNumber" : 1 ,
"ruleName" : "MD010" ,
"ruleAlias" : "no-hard-tabs" ,
"ruleDescription" : "Hard tabs" ,
"ruleInformation" :
` ${ homepage } /blob/v ${ version } /doc/Rules.md#md010 ` ,
"errorDetail" : "Column: 10" ,
"errorContext" : null ,
"errorRange" : [ 10 , 1 ]
}
]
2019-08-21 21:02:09 -07:00
} ;
2020-01-08 22:13:51 -08:00
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
2019-08-21 21:02:09 -07:00
2020-01-08 22:13:51 -08:00
tape ( "onePerLineResultVersion2" , ( test ) => {
test . plan ( 2 ) ;
const options = {
"strings" : {
"input" : "# Heading\theading\t\theading\n"
} ,
"resultVersion" : 2
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
const expectedResult = {
"input" : [
{
"lineNumber" : 1 ,
"ruleNames" : [ "MD010" , "no-hard-tabs" ] ,
"ruleDescription" : "Hard tabs" ,
"ruleInformation" :
` ${ homepage } /blob/v ${ version } /doc/Rules.md#md010 ` ,
"errorDetail" : "Column: 10" ,
"errorContext" : null ,
"errorRange" : [ 10 , 1 ]
}
]
2019-10-19 17:34:02 -07:00
} ;
2020-01-08 22:13:51 -08:00
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
tape ( "manyPerLineResultVersion3" , ( test ) => {
test . plan ( 2 ) ;
const options = {
"strings" : {
"input" : "# Heading\theading\t\theading\n"
} ,
"resultVersion" : 3
} ;
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
const expectedResult = {
"input" : [
{
"lineNumber" : 1 ,
"ruleNames" : [ "MD010" , "no-hard-tabs" ] ,
"ruleDescription" : "Hard tabs" ,
"ruleInformation" :
` ${ homepage } /blob/v ${ version } /doc/Rules.md#md010 ` ,
"errorDetail" : "Column: 10" ,
"errorContext" : null ,
"errorRange" : [ 10 , 1 ] ,
"fixInfo" : {
"editColumn" : 10 ,
"deleteCount" : 1 ,
"insertText" : " "
2019-10-19 17:34:02 -07:00
}
2020-01-08 22:13:51 -08:00
} ,
{
"lineNumber" : 1 ,
"ruleNames" : [ "MD010" , "no-hard-tabs" ] ,
"ruleDescription" : "Hard tabs" ,
"ruleInformation" :
` ${ homepage } /blob/v ${ version } /doc/Rules.md#md010 ` ,
"errorDetail" : "Column: 18" ,
"errorContext" : null ,
"errorRange" : [ 18 , 2 ] ,
"fixInfo" : {
"editColumn" : 18 ,
"deleteCount" : 2 ,
"insertText" : " "
}
}
]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
tape ( "frontMatterResultVersion3" , ( test ) => {
test . plan ( 2 ) ;
const options = {
"strings" : {
"input" : "---\n---\n# Heading\nText\n"
} ,
"resultVersion" : 3
2019-10-19 17:34:02 -07:00
} ;
2020-01-08 22:13:51 -08:00
markdownlint ( options , function callback ( err , actualResult ) {
test . ifError ( err ) ;
const expectedResult = {
"input" : [
{
"lineNumber" : 3 ,
"ruleNames" :
[ "MD022" , "blanks-around-headings" , "blanks-around-headers" ] ,
"ruleDescription" : "Headings should be surrounded by blank lines" ,
"ruleInformation" :
` ${ homepage } /blob/v ${ version } /doc/Rules.md#md022 ` ,
"errorDetail" : "Expected: 1; Actual: 0; Below" ,
"errorContext" : "# Heading" ,
"errorRange" : null ,
"fixInfo" : {
"lineNumber" : 4 ,
"insertText" : "\n"
}
}
]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
2019-10-19 17:34:02 -07:00
2020-01-08 22:13:51 -08:00
tape ( "stringInputLineEndings" , ( test ) => {
test . plan ( 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" ,
2019-09-14 13:53:35 -07:00
"mixed" : "One\rTwo\n#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 ] } ,
2019-09-14 13:53:35 -07:00
"mixed" : { "MD018" : [ 3 ] }
2015-04-29 18:46:52 -07:00
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-04-29 18:46:52 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-04-29 18:46:52 -07:00
2020-01-08 22:13:51 -08:00
tape ( "inputOnlyNewline" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-07-22 23:17:08 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-07-22 23:17:08 -07:00
2020-01-08 22:13:51 -08:00
tape ( "defaultTrue" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-16 23:25:06 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-16 23:25:06 -07:00
2020-01-08 22:13:51 -08:00
tape ( "defaultFalse" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-16 23:25:06 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-16 23:25:06 -07:00
2020-01-08 22:13:51 -08:00
tape ( "defaultUndefined" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-18 22:45:51 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-18 22:45:51 -07:00
2020-01-08 22:13:51 -08:00
tape ( "disableRules" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-16 23:25:06 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-16 23:25:06 -07:00
2020-01-08 22:13:51 -08:00
tape ( "enableRules" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-16 23:25:06 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-16 23:25:06 -07:00
2020-01-08 22:13:51 -08:00
tape ( "enableRulesMixedCase" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-09-21 23:21:17 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-09-21 23:21:17 -07:00
2020-01-08 22:13:51 -08:00
tape ( "disableTag" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-16 23:25:06 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-16 23:25:06 -07:00
2020-01-08 22:13:51 -08:00
tape ( "enableTag" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-16 23:25:06 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-16 23:25:06 -07:00
2020-01-08 22:13:51 -08:00
tape ( "enableTagMixedCase" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-09-21 23:21:17 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-09-21 23:21:17 -07:00
2020-01-08 22:13:51 -08:00
tape ( "styleFiles" , ( test ) => {
test . plan ( 4 ) ;
2015-03-17 22:34:47 -07:00
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." ) ;
} ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-17 22:34:47 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-17 22:34:47 -07:00
2020-01-08 22:13:51 -08:00
tape ( "styleAll" , ( test ) => {
test . plan ( 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 ] ,
2019-09-08 16:51:00 -07:00
"MD003" : [ 5 , 31 ] ,
2015-03-17 18:02:05 -07:00
"MD004" : [ 8 ] ,
"MD005" : [ 12 ] ,
"MD007" : [ 8 , 11 ] ,
"MD009" : [ 14 ] ,
"MD010" : [ 14 ] ,
"MD011" : [ 16 ] ,
"MD012" : [ 18 ] ,
"MD013" : [ 21 ] ,
"MD014" : [ 23 ] ,
"MD018" : [ 25 ] ,
"MD019" : [ 27 ] ,
"MD020" : [ 29 ] ,
2019-09-08 16:51:00 -07:00
"MD021" : [ 31 ] ,
2019-10-08 21:10:02 -07:00
"MD022" : [ 86 ] ,
2019-09-08 16:51:00 -07:00
"MD023" : [ 40 ] ,
"MD024" : [ 35 ] ,
2015-03-17 18:02:05 -07:00
"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 ] ,
2019-10-08 21:10:02 -07:00
"MD042" : [ 81 ] ,
"MD045" : [ 85 ] ,
"MD046" : [ 49 , 73 , 77 ] ,
"MD047" : [ 88 ] ,
"MD048" : [ 77 ]
2015-03-17 18:02:05 -07:00
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-17 18:02:05 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-17 18:02:05 -07:00
2020-01-08 22:13:51 -08:00
tape ( "styleRelaxed" , ( test ) => {
test . plan ( 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 ] ,
2019-09-08 16:51:00 -07:00
"MD003" : [ 5 , 31 ] ,
2015-03-17 18:02:05 -07:00
"MD004" : [ 8 ] ,
"MD005" : [ 12 ] ,
"MD011" : [ 16 ] ,
"MD014" : [ 23 ] ,
"MD018" : [ 25 ] ,
"MD019" : [ 27 ] ,
"MD020" : [ 29 ] ,
2019-09-08 16:51:00 -07:00
"MD021" : [ 31 ] ,
2019-10-08 21:10:02 -07:00
"MD022" : [ 86 ] ,
2019-09-08 16:51:00 -07:00
"MD023" : [ 40 ] ,
"MD024" : [ 35 ] ,
2015-03-17 18:02:05 -07:00
"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 ] ,
2019-10-08 21:10:02 -07:00
"MD042" : [ 81 ] ,
"MD045" : [ 85 ] ,
"MD046" : [ 49 , 73 , 77 ] ,
"MD047" : [ 88 ] ,
"MD048" : [ 77 ]
2015-03-17 18:02:05 -07:00
}
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-17 18:02:05 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-17 18:02:05 -07:00
2020-01-08 22:13:51 -08:00
tape ( "nullFrontMatter" , ( test ) => {
test . plan ( 2 ) ;
2015-07-25 22:18:30 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-07-25 22:18:30 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-07-25 22:18:30 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customFrontMatter" , ( test ) => {
test . plan ( 2 ) ;
2015-07-25 22:18:30 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-07-25 22:18:30 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-07-25 22:18:30 -07:00
2020-01-08 22:13:51 -08:00
tape ( "noInlineConfig" , ( test ) => {
test . plan ( 2 ) ;
2017-05-21 22:58:10 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2017-05-21 22:58:10 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2017-05-21 22:58:10 -07:00
2020-01-08 22:13:51 -08:00
tape ( "readmeHeadings" , ( test ) => {
test . plan ( 2 ) ;
2016-07-02 22:37:52 -07:00
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" ,
2019-05-18 12:32:52 -07:00
"##### options.handleRuleFailures" ,
2017-05-21 22:58:10 -07:00
"##### 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2016-07-02 22:37:52 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2016-07-02 22:37:52 -07:00
2020-01-08 22:13:51 -08:00
tape ( "filesArrayNotModified" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-13 18:20:56 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-13 18:20:56 -07:00
2020-01-08 22:13:51 -08:00
tape ( "filesArrayAsString" , ( test ) => {
test . plan ( 2 ) ;
2016-01-15 22:00:34 -08:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2016-01-15 22:00:34 -08:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2016-01-15 22:00:34 -08:00
2020-01-08 22:13:51 -08:00
tape ( "missingOptions" , ( test ) => {
test . plan ( 2 ) ;
2015-03-11 21:13:21 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-11 21:13:21 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-11 21:13:21 -07:00
2020-01-08 22:13:51 -08:00
tape ( "missingFilesAndStrings" , ( test ) => {
test . plan ( 2 ) ;
2015-03-11 21:13:21 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-11 21:13:21 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-11 21:13:21 -07:00
2020-01-08 22:13:51 -08:00
tape ( "missingCallback" , ( test ) => {
test . plan ( 0 ) ;
2019-10-30 20:37:06 -07:00
// @ts-ignore
2015-03-11 21:13:21 -07:00
markdownlint ( ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2015-03-11 21:13:21 -07:00
2020-01-08 22:13:51 -08:00
tape ( "badFile" , ( test ) => {
test . plan ( 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." ) ;
2019-10-30 20:37:06 -07:00
// @ts-ignore
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-11 21:13:21 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-17 22:34:47 -07:00
2020-01-08 22:13:51 -08:00
tape ( "badFileSync" , ( test ) => {
test . plan ( 1 ) ;
test . throws (
function badFileCall ( ) {
markdownlint . sync ( {
"files" : [ "./badFile" ]
} ) ;
} ,
/ENOENT/ ,
"Did not get correct exception for bad file."
) ;
test . end ( ) ;
} ) ;
2015-03-20 00:09:55 -07:00
2020-01-08 22:13:51 -08:00
tape ( "missingStringValue" , ( test ) => {
test . plan ( 2 ) ;
2015-04-29 18:46:52 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-04-29 18:46:52 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-04-29 18:46:52 -07:00
2020-01-08 22:13:51 -08:00
tape ( "readme" , ( test ) => {
test . plan ( 115 ) ;
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 ) ;
2019-07-08 13:10:08 -05:00
let 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 ;
2019-07-08 13:10:08 -05:00
if ( deprecatedRuleNames . includes ( ruleName ) ) {
expected = "~~" + expected + "~~" ;
}
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 + "." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-17 22:34:47 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-03-17 22:34:47 -07:00
2020-01-08 22:13:51 -08:00
tape ( "doc" , ( test ) => {
test . plan ( 336 ) ;
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 + "." ) ;
2019-07-08 13:10:08 -05:00
const ruleName = rule . names [ 0 ] ;
let headingContent = ruleName + " - " + rule . description ;
if ( deprecatedRuleNames . includes ( ruleName ) ) {
headingContent = "~~" + headingContent + "~~" ;
}
2018-02-05 21:26:07 -08:00
test . equal ( token . content ,
2019-07-08 13:10:08 -05:00
headingContent ,
2018-02-05 21:26:07 -08:00
"Rule mismatch." ) ;
ruleUsesParams = rule . function . toString ( )
. match ( /params\.config\.[_a-z]*/gi ) ;
if ( ruleUsesParams ) {
ruleUsesParams = ruleUsesParams . map ( function forUse ( use ) {
return use . split ( "." ) . pop ( ) ;
} ) ;
2019-12-09 22:05:57 -08:00
ruleUsesParams . sort ( ) ;
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 ;
} ) ;
2019-12-09 22:05:57 -08:00
parameters . sort ( ) ;
2015-12-13 21:42:51 -08:00
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
}
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2015-03-17 22:34:47 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2015-05-07 17:42:13 -07:00
2020-01-08 22:13:51 -08:00
tape ( "validateConfigSchema" , ( test ) => {
2018-04-27 22:05:34 -07:00
const jsonFileRe = /\.json$/i ;
const resultsFileRe = /\.results\.json$/i ;
2019-10-30 20:37:06 -07:00
const jsConfigFileRe = /^jsconfig\.json$/i ;
2018-04-27 22:05:34 -07:00
const testDirectory = _ _dirname ;
const testFiles = fs . readdirSync ( testDirectory ) ;
2016-10-05 22:21:54 -07:00
testFiles . filter ( function filterFile ( file ) {
2019-10-30 20:37:06 -07:00
return jsonFileRe . test ( file ) &&
! resultsFileRe . test ( file ) &&
! jsConfigFileRe . test ( file ) ;
2016-10-05 22:21:54 -07:00
} ) . forEach ( function forFile ( file ) {
2019-10-30 20:37:06 -07:00
const data = fs . readFileSync (
path . join ( testDirectory , file ) ,
helpers . utf8Encoding
) ;
2016-10-05 22:21:54 -07:00
test . ok (
tv4 . validate ( JSON . parse ( data ) , configSchema ) ,
file + "\n" + JSON . stringify ( tv4 . error , null , 2 ) ) ;
} ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2016-10-05 22:21:54 -07:00
2020-01-08 22:13:51 -08:00
tape ( "clearHtmlCommentTextValid" , ( test ) => {
test . plan ( 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-05-16 22:14:07 -07:00
" \\" ,
""
2017-07-16 23:08:47 -07:00
] ;
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 ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2017-07-16 23:08:47 -07:00
2020-01-08 22:13:51 -08:00
tape ( "clearHtmlCommentTextInvalid" , ( test ) => {
test . plan ( 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 ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2017-07-16 23:08:47 -07:00
2020-01-08 22:13:51 -08:00
tape ( "clearHtmlCommentTextNonGreedy" , ( test ) => {
test . plan ( 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 ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2017-07-16 23:08:47 -07:00
2020-01-08 22:13:51 -08:00
tape ( "clearHtmlCommentTextEmbedded" , ( test ) => {
test . plan ( 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 ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2017-07-16 23:08:47 -07:00
2020-01-08 22:13:51 -08:00
tape ( "unescapeMarkdown" , ( test ) => {
test . plan ( 7 ) ;
2019-04-29 22:09:03 -07:00
// 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 ) ;
} ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2019-04-29 22:09:03 -07:00
2020-01-08 22:13:51 -08:00
tape ( "isBlankLine" , ( test ) => {
test . plan ( 25 ) ;
2019-03-20 21:48:18 -07:00
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 ) ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2019-03-20 21:48:18 -07:00
2020-01-08 22:13:51 -08:00
tape ( "includesSorted" , ( test ) => {
test . plan ( 154 ) ;
2019-03-28 22:06:42 -07:00
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
}
} ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2019-03-28 22:06:42 -07:00
2020-01-08 22:13:51 -08:00
tape ( "forEachInlineCodeSpan" , ( test ) => {
test . plan ( 99 ) ;
2019-01-30 22:09:20 -08:00
const testCases =
[
2019-10-30 20:37:06 -07:00
{
"input" : "`code`" ,
"expecteds" : [ [ "code" , 0 , 1 , 1 ] ]
} ,
{
"input" : "text `code` text" ,
"expecteds" : [ [ "code" , 0 , 6 , 1 ] ]
} ,
{
"input" : "text `code` text `edoc`" ,
"expecteds" : [
2019-01-30 22:09:20 -08:00
[ "code" , 0 , 6 , 1 ] ,
[ "edoc" , 0 , 18 , 1 ]
]
2019-10-30 20:37:06 -07:00
} ,
{
"input" : "text `code` text `edoc` text" ,
"expecteds" : [
2019-01-30 22:09:20 -08:00
[ "code" , 0 , 6 , 1 ] ,
[ "edoc" , 0 , 18 , 1 ]
]
2019-10-30 20:37:06 -07:00
} ,
{
"input" : "text ``code`code`` text" ,
"expecteds" : [ [ "code`code" , 0 , 7 , 2 ] ]
} ,
{
"input" : "`code `` code`" ,
"expecteds" : [ [ "code `` code" , 0 , 1 , 1 ] ]
} ,
{
"input" : "`code\\`text`" ,
"expecteds" : [ [ "code\\" , 0 , 1 , 1 ] ]
} ,
{
"input" : "``\ncode\n``" ,
"expecteds" : [ [ "\ncode\n" , 0 , 2 , 2 ] ]
} ,
{
"input" : "text\n`code`\ntext" ,
"expecteds" : [ [ "code" , 1 , 1 , 1 ] ]
} ,
{
"input" : "text\ntext\n`code`\ntext\n`edoc`\ntext" ,
"expecteds" : [
2019-01-30 22:09:20 -08:00
[ "code" , 2 , 1 , 1 ] ,
[ "edoc" , 4 , 1 , 1 ]
]
2019-10-30 20:37:06 -07:00
} ,
{
"input" : "text `code\nedoc` text" ,
"expecteds" : [ [ "code\nedoc" , 0 , 6 , 1 ] ]
} ,
{
"input" : "> text `code` text" ,
"expecteds" : [ [ "code" , 0 , 8 , 1 ] ]
} ,
{
"input" : "> text\n> `code`\n> text" ,
"expecteds" : [ [ "code" , 1 , 3 , 1 ] ]
} ,
{
"input" : "> text\n> `code\n> edoc`\n> text" ,
"expecteds" : [ [ "code\n> edoc" , 1 , 3 , 1 ] ]
} ,
{
"input" : "```text``" ,
"expecteds" : [ ]
} ,
{
"input" : "text `text text" ,
"expecteds" : [ ]
} ,
{
"input" : "`text``code``" ,
"expecteds" : [ [ "code" , 0 , 7 , 2 ] ]
} ,
{
"input" : "text \\` text `code`" ,
"expecteds" : [ [ "code" , 0 , 14 , 1 ] ]
} ,
{
"input" : "text\\\n`code`" ,
"expecteds" : [ [ "code" , 1 , 1 , 1 ] ]
}
2019-01-30 22:09:20 -08:00
] ;
testCases . forEach ( ( testCase ) => {
2019-10-30 20:37:06 -07:00
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" ) ;
} ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2019-01-30 22:09:20 -08:00
2020-01-08 22:13:51 -08:00
tape ( "getPreferredLineEnding" , ( test ) => {
test . plan ( 17 ) ;
2019-09-14 22:31:08 -07:00
const testCases = [
[ "" , os . EOL ] ,
[ "\r" , "\r" ] ,
[ "\n" , "\n" ] ,
[ "\r\n" , "\r\n" ] ,
[ "t\rt\nt" , "\n" ] ,
[ "t\nt\rt" , "\n" ] ,
[ "t\r\nt\nt" , "\n" ] ,
[ "t\nt\r\nt" , "\n" ] ,
[ "t\r\nt\rt" , "\r\n" ] ,
[ "t\rt\r\nt" , "\r\n" ] ,
[ "t\r\nt\rt\nt" , "\n" ] ,
[ "t\r\nt\r\nt\r\nt" , "\r\n" ] ,
[ "t\nt\nt\nt" , "\n" ] ,
[ "t\rt\rt\rt" , "\r" ] ,
[ "t\r\nt\nt\r\nt" , "\r\n" ] ,
[ "t\nt\r\nt\nt" , "\n" ] ,
[ "t\rt\t\rt" , "\r" ]
] ;
testCases . forEach ( ( testCase ) => {
const [ input , expected ] = testCase ;
const actual = helpers . getPreferredLineEnding ( input ) ;
test . equal ( actual , expected , "Incorrect line ending returned." ) ;
} ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2019-09-14 22:31:08 -07:00
2020-01-08 22:13:51 -08:00
tape ( "applyFix" , ( test ) => {
test . plan ( 4 ) ;
2019-09-20 21:50:44 -07:00
const testCases = [
[
"Hello world." ,
{
"editColumn" : 12 ,
"deleteCount" : 1
} ,
undefined ,
"Hello world"
] ,
[
"Hello world." ,
{
"editColumn" : 13 ,
"insertText" : "\n"
} ,
undefined ,
"Hello world.\n"
] ,
[
"Hello world." ,
{
"editColumn" : 13 ,
"insertText" : "\n"
} ,
"\n" ,
"Hello world.\n"
] ,
[
"Hello world." ,
{
"editColumn" : 13 ,
"insertText" : "\n"
} ,
"\r\n" ,
"Hello world.\r\n"
]
] ;
testCases . forEach ( ( testCase ) => {
const [ line , fixInfo , lineEnding , expected ] = testCase ;
const actual = helpers . applyFix ( line , fixInfo , lineEnding ) ;
test . equal ( actual , expected , "Incorrect fix applied." ) ;
} ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2019-09-20 21:50:44 -07:00
2020-01-08 22:13:51 -08:00
tape ( "applyFixes" , ( test ) => {
test . plan ( 28 ) ;
2019-08-16 19:56:52 -07:00
const testCases = [
[
"Hello world." ,
[ ] ,
"Hello world."
] ,
[
"Hello world." ,
[
{
"lineNumber" : 1 ,
"fixInfo" : { }
}
] ,
"Hello world."
] ,
[
"Hello world." ,
[
{
"lineNumber" : 1 ,
"fixInfo" : {
"insertText" : "Very "
}
}
] ,
"Very Hello world."
] ,
[
"Hello world." ,
[
{
"lineNumber" : 1 ,
"fixInfo" : {
"editColumn" : 7 ,
"insertText" : "big "
}
}
] ,
"Hello big world."
] ,
[
"Hello world." ,
[
{
"lineNumber" : 1 ,
"fixInfo" : {
"deleteCount" : 6
}
}
] ,
"world."
] ,
[
"Hello world." ,
[
{
"lineNumber" : 1 ,
"fixInfo" : {
"editColumn" : 7 ,
"deleteCount" : 5 ,
"insertText" : "there"
}
}
] ,
"Hello there."
] ,
[
"Hello world." ,
[
{
"lineNumber" : 1 ,
"fixInfo" : {
"editColumn" : 12 ,
"deleteCount" : 1
}
} ,
{
"lineNumber" : 1 ,
"fixInfo" : {
"editColumn" : 6 ,
"deleteCount" : 1
}
}
] ,
"Helloworld"
] ,
[
"Hello world." ,
[
{
"lineNumber" : 1 ,
"fixInfo" : {
"editColumn" : 13 ,
"insertText" : " Hi."
}
}
] ,
"Hello world. Hi."
2019-08-24 22:55:51 -07:00
] ,
[
"Hello\nworld" ,
[
{
"lineNumber" : 1 ,
"fixInfo" : {
"deleteCount" : - 1
}
}
] ,
"world"
] ,
[
"Hello\nworld" ,
[
{
"lineNumber" : 2 ,
"fixInfo" : {
"deleteCount" : - 1
}
}
] ,
"Hello"
2019-08-28 21:47:07 -07:00
] ,
[
"Hello\nworld" ,
[
{
"lineNumber" : 2 ,
"fixInfo" : {
"lineNumber" : 1 ,
"deleteCount" : - 1
}
}
] ,
"world"
] ,
[
"Hello\nworld" ,
[
{
"lineNumber" : 1 ,
"fixInfo" : {
"lineNumber" : 2 ,
"deleteCount" : - 1
}
}
] ,
"Hello"
] ,
[
"Hello world" ,
[
{
"lineNumber" : 1 ,
"fixInfo" : {
"editColumn" : 4 ,
"deleteCount" : 1
}
} ,
{
"lineNumber" : 1 ,
"fixInfo" : {
"editColumn" : 10 ,
"deleteCount" : 1
}
}
] ,
"Helo word"
] ,
[
"Hello world" ,
[
{
"lineNumber" : 1 ,
"fixInfo" : {
"editColumn" : 10 ,
"deleteCount" : 1
}
} ,
{
"lineNumber" : 1 ,
"fixInfo" : {
"editColumn" : 4 ,
"deleteCount" : 1
}
}
] ,
"Helo word"
] ,
[
"Hello\nworld" ,
[
{
"fixInfo" : {
"lineNumber" : 1 ,
"deleteCount" : - 1
}
} ,
{
"fixInfo" : {
"lineNumber" : 1 ,
"insertText" : "Big "
}
}
] ,
"world"
] ,
[
"Hello\nworld" ,
[
{
"fixInfo" : {
"lineNumber" : 1 ,
"deleteCount" : - 1
}
} ,
{
"fixInfo" : {
"lineNumber" : 2 ,
"deleteCount" : - 1
}
}
] ,
""
] ,
[
"Hello world" ,
[
{
"fixInfo" : {
"lineNumber" : 1 ,
"insertText" : "aa"
}
} ,
{
"fixInfo" : {
"lineNumber" : 1 ,
"insertText" : "b"
}
}
] ,
"aaHello world"
] ,
[
"Hello world" ,
[
{
"fixInfo" : {
"lineNumber" : 1 ,
"insertText" : "a"
}
} ,
{
"fixInfo" : {
"lineNumber" : 1 ,
"insertText" : "bb"
}
}
] ,
"bbHello world"
] ,
[
"Hello world" ,
[
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 6 ,
"insertText" : " big"
}
} ,
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 7 ,
"deleteCount" : 1
}
}
] ,
"Hello big orld"
] ,
[
"Hello world" ,
[
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 8 ,
"deleteCount" : 2
}
} ,
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 7 ,
"deleteCount" : 2
}
}
] ,
"Hello wld"
] ,
[
"Hello world" ,
[
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 7 ,
"deleteCount" : 2
}
} ,
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 8 ,
"deleteCount" : 2
}
}
] ,
"Hello wld"
] ,
2019-09-02 15:35:43 -07:00
[
"Hello world" ,
[
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 7 ,
"deleteCount" : 1 ,
"insertText" : "z"
}
}
] ,
"Hello zorld"
] ,
2019-08-28 21:47:07 -07:00
[
"Hello world" ,
[
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 7 ,
"deleteCount" : 1
}
} ,
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 7 ,
"insertText" : "z"
}
}
] ,
2019-09-02 15:35:43 -07:00
"Hello zorld"
2019-08-28 21:47:07 -07:00
] ,
[
"Hello world" ,
[
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 7 ,
"insertText" : "z"
}
} ,
{
"fixInfo" : {
"lineNumber" : 1 ,
"editColumn" : 7 ,
"deleteCount" : 1
}
}
] ,
2019-09-02 15:35:43 -07:00
"Hello zorld"
2019-09-14 22:31:08 -07:00
] ,
[
"Hello\nworld\nhello\rworld" ,
[
{
"fixInfo" : {
"lineNumber" : 4 ,
"editColumn" : 6 ,
"insertText" : "\n"
}
}
] ,
"Hello\nworld\nhello\nworld\n"
] ,
[
"Hello\r\nworld\r\nhello\nworld" ,
[
{
"fixInfo" : {
"lineNumber" : 4 ,
"editColumn" : 6 ,
"insertText" : "\n"
}
}
] ,
"Hello\r\nworld\r\nhello\r\nworld\r\n"
] ,
[
"Hello\rworld\rhello\nworld" ,
[
{
"fixInfo" : {
"lineNumber" : 4 ,
"editColumn" : 6 ,
"insertText" : "\n"
}
}
] ,
"Hello\rworld\rhello\rworld\r"
2019-09-16 22:34:49 -07:00
] ,
[
"Hello\r\nworld" ,
[
{
"lineNumber" : 2 ,
"fixInfo" : {
"editColumn" : 6 ,
"insertText" : "\n\n"
}
}
] ,
"Hello\r\nworld\r\n\r\n"
2019-08-16 19:56:52 -07:00
]
] ;
testCases . forEach ( ( testCase ) => {
const [ input , errors , expected ] = testCase ;
2019-09-12 21:50:40 -07:00
const actual = helpers . applyFixes ( input , errors ) ;
2019-08-16 19:56:52 -07:00
test . equal ( actual , expected , "Incorrect fix applied." ) ;
} ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2019-08-16 19:56:52 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configSingle" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2017-05-19 22:36:46 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2017-05-19 22:36:46 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configAbsolute" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2017-05-19 22:36:46 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2017-05-19 22:36:46 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configMultiple" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2017-05-19 22:36:46 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2017-05-19 22:36:46 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configBadFile" , ( test ) => {
test . plan ( 4 ) ;
2017-05-19 22:36:46 -07:00
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." ) ;
2020-01-11 20:48:00 -08:00
// @ts-ignore
2017-05-19 22:36:46 -07:00
test . equal ( err . code , "ENOENT" , "Error code for bad file not ENOENT." ) ;
test . ok ( ! result , "Got result for bad file." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2017-05-19 22:36:46 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2017-05-19 22:36:46 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configBadChildFile" , ( test ) => {
test . plan ( 4 ) ;
2017-05-19 22:36:46 -07:00
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." ) ;
2020-01-11 20:48:00 -08:00
// @ts-ignore
2017-05-19 22:36:46 -07:00
test . equal ( err . code , "ENOENT" ,
"Error code for bad child file not ENOENT." ) ;
test . ok ( ! result , "Got result for bad child file." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2017-05-19 22:36:46 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2017-05-19 22:36:46 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configBadJson" , ( test ) => {
test . plan ( 3 ) ;
2017-05-19 22:36:46 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2017-05-19 22:36:46 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2017-05-19 22:36:46 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configBadChildJson" , ( test ) => {
test . plan ( 3 ) ;
2017-05-19 22:36:46 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2017-05-19 22:36:46 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2017-05-19 22:36:46 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configSingleYaml" , ( test ) => {
test . plan ( 2 ) ;
2018-05-23 22:24:40 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-05-23 22:24:40 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-05-23 22:24:40 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configMultipleYaml" , ( test ) => {
test . plan ( 2 ) ;
2018-05-23 22:24:40 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-05-23 22:24:40 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-05-23 22:24:40 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configMultipleHybrid" , ( test ) => {
test . plan ( 2 ) ;
2018-05-23 22:24:40 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-05-23 22:24:40 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-05-23 22:24:40 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configBadHybrid" , ( test ) => {
test . plan ( 4 ) ;
2018-05-23 22:24:40 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-05-23 22:24:40 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-05-23 22:24:40 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configSingleSync" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2017-05-19 22:36:46 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configAbsoluteSync" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2017-05-19 22:36:46 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configMultipleSync" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
tape ( "configBadFileSync" , ( test ) => {
test . plan ( 1 ) ;
test . throws (
function badFileCall ( ) {
markdownlint . readConfigSync ( "./test/config/config-badfile.json" ) ;
} ,
/ENOENT/ ,
"Did not get correct exception for bad file."
) ;
test . end ( ) ;
} ) ;
tape ( "configBadChildFileSync" , ( test ) => {
test . plan ( 1 ) ;
test . throws (
function badChildFileCall ( ) {
markdownlint . readConfigSync ( "./test/config/config-badchildfile.json" ) ;
} ,
/ENOENT/ ,
"Did not get correct exception for bad child file."
) ;
test . end ( ) ;
} ) ;
tape ( "configBadJsonSync" , ( test ) => {
test . plan ( 1 ) ;
test . throws (
function badJsonCall ( ) {
markdownlint . readConfigSync ( "./test/config/config-badjson.json" ) ;
} ,
/Unable to parse '[^']*'; Unexpected token \S+ in JSON at position \d+/ ,
"Did not get correct exception for bad JSON."
) ;
test . end ( ) ;
} ) ;
tape ( "configBadChildJsonSync" , ( test ) => {
test . plan ( 1 ) ;
test . throws (
function badChildJsonCall ( ) {
markdownlint . readConfigSync ( "./test/config/config-badchildjson.json" ) ;
} ,
/Unable to parse '[^']*'; Unexpected token \S+ in JSON at position \d+/ ,
"Did not get correct exception for bad child JSON."
) ;
test . end ( ) ;
} ) ;
tape ( "configSingleYamlSync" , ( test ) => {
test . plan ( 1 ) ;
2018-05-23 22:24:40 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2018-05-23 22:24:40 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configMultipleYamlSync" , ( test ) => {
test . plan ( 1 ) ;
2018-05-23 22:24:40 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2018-05-23 22:24:40 -07:00
2020-01-08 22:13:51 -08:00
tape ( "configMultipleHybridSync" , ( test ) => {
test . plan ( 1 ) ;
2018-05-23 22:24:40 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
tape ( "configBadHybridSync" , ( test ) => {
test . plan ( 1 ) ;
test . throws (
function badHybridCall ( ) {
markdownlint . readConfigSync (
"./test/config/config-badcontent.txt" ,
[ JSON . parse , require ( "toml" ) . parse , require ( "js-yaml" ) . safeLoad ] ) ;
} ,
// 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+:[^;]*/ ,
"Did not get correct exception for bad content."
) ;
test . end ( ) ;
} ) ;
tape ( "allBuiltInRulesHaveValidUrl" , ( test ) => {
test . plan ( 132 ) ;
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 . end ( ) ;
} ) ;
tape ( "someCustomRulesHaveValidUrl" , ( test ) => {
test . plan ( 7 ) ;
customRules . all . forEach ( function forRule ( rule ) {
test . ok ( ! rule . information ||
( Object . getPrototypeOf ( rule . information ) === URL . prototype ) ) ;
if ( rule === customRules . anyBlockquote ) {
2019-01-15 21:56:38 -08:00
test . equal (
rule . information . href ,
2020-01-08 22:13:51 -08:00
` ${ homepage } /blob/master/test/rules/any-blockquote.js `
2019-01-15 21:56:38 -08:00
) ;
2020-01-08 22:13:51 -08:00
} else if ( rule === customRules . lettersEX ) {
test . equal (
rule . information . href ,
` ${ homepage } /blob/master/test/rules/letters-E-X.js `
) ;
}
} ) ;
test . end ( ) ;
} ) ;
2019-01-15 21:56:38 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesV0" , ( test ) => {
test . plan ( 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)." ) ;
2019-11-10 19:26:55 -08:00
// @ts-ignore
2018-02-15 21:35:58 -08:00
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)." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-02-15 21:35:58 -08:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-02-15 21:35:58 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesV1" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-02-15 21:35:58 -08:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-02-15 21:35:58 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesV2" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-02-15 21:35:58 -08:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-02-15 21:35:58 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesConfig" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-02-15 21:35:58 -08:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-02-25 16:04:13 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesNpmPackage" , ( test ) => {
test . plan ( 2 ) ;
2018-07-20 22:31:41 -07:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-07-20 22:31:41 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-07-20 22:31:41 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesBadProperty" , ( test ) => {
test . plan ( 23 ) ;
2018-02-25 16:04:13 -08:00
[
2019-10-30 20:37:06 -07:00
{
"propertyName" : "names" ,
"propertyValues" :
[ null , "string" , [ ] , [ null ] , [ "" ] , [ "string" , 10 ] ]
} ,
{
"propertyName" : "description" ,
"propertyValues" : [ null , 10 , "" , [ ] ]
} ,
{
"propertyName" : "information" ,
"propertyValues" : [ 10 , [ ] , "string" , "https://example.com" ]
} ,
{
"propertyName" : "tags" ,
"propertyValues" :
[ null , "string" , [ ] , [ null ] , [ "" ] , [ "string" , 10 ] ]
} ,
{
"propertyName" : "function" ,
"propertyValues" : [ null , "string" , [ ] ]
}
] . forEach ( function forTestCase ( testCase ) {
const { propertyName , propertyValues } = testCase ;
propertyValues . 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 ]
} ;
2020-01-08 22:13:51 -08:00
test . throws (
function badRuleCall ( ) {
markdownlint . sync ( options ) ;
} ,
new RegExp (
` Property ' ${ propertyName } ' of custom rule at index 0 is incorrect. `
) ,
"Did not get correct exception for missing property."
) ;
2018-02-25 16:04:13 -08:00
} ) ;
} ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2018-02-25 16:04:13 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesUsedNameName" , ( test ) => {
test . plan ( 4 ) ;
2018-02-25 16:04:13 -08:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-02-25 16:04:13 -08:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-02-25 16:04:13 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesUsedNameTag" , ( test ) => {
test . plan ( 4 ) ;
2018-02-25 16:04:13 -08:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-02-25 16:04:13 -08:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-02-25 16:04:13 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesUsedTagName" , ( test ) => {
test . plan ( 4 ) ;
2018-02-25 16:04:13 -08:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-02-25 16:04:13 -08:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-02-25 16:04:13 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesThrowForFile" , ( test ) => {
test . plan ( 4 ) ;
const exceptionMessage = "Test exception message" ;
markdownlint ( {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function throws ( ) {
throw new Error ( exceptionMessage ) ;
2018-02-25 16:04:13 -08:00
}
2020-01-08 22:13:51 -08:00
}
] ,
"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 . end ( ) ;
} ) ;
} ) ;
2019-05-18 12:32:52 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesThrowForFileSync" , ( test ) => {
test . plan ( 1 ) ;
const exceptionMessage = "Test exception message" ;
test . throws (
function customRuleThrowsCall ( ) {
2019-05-18 12:32:52 -07:00
markdownlint . sync ( {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function throws ( ) {
throw new Error ( exceptionMessage ) ;
}
}
] ,
"files" : [ "./test/custom-rules.md" ]
} ) ;
2020-01-08 22:13:51 -08:00
} ,
new RegExp ( exceptionMessage ) ,
"Did not get correct exception for function thrown."
) ;
test . end ( ) ;
} ) ;
2018-02-25 16:04:13 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesThrowForString" , ( test ) => {
test . plan ( 4 ) ;
const exceptionMessage = "Test exception message" ;
markdownlint ( {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function throws ( ) {
throw new Error ( exceptionMessage ) ;
2018-02-25 16:04:13 -08:00
}
}
2020-01-08 22:13:51 -08:00
] ,
"strings" : {
"string" : "String"
}
} , 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 . end ( ) ;
} ) ;
} ) ;
2018-02-27 21:14:02 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesOnErrorNull" , ( test ) => {
test . plan ( 1 ) ;
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
} ;
2020-01-08 22:13:51 -08:00
test . throws (
function nullErrorCall ( ) {
markdownlint . sync ( options ) ;
} ,
/Property 'lineNumber' of onError parameter is incorrect./ ,
"Did not get correct exception for null object."
) ;
test . end ( ) ;
} ) ;
tape ( "customRulesOnErrorBad" , ( test ) => {
test . plan ( 21 ) ;
2018-02-27 21:14:02 -08:00
[
2019-10-30 20:37:06 -07:00
{
"propertyName" : "lineNumber" ,
"subPropertyName" : null ,
"propertyValues" : [ null , "string" ]
} ,
{
"propertyName" : "detail" ,
"subPropertyName" : null ,
"propertyValues" : [ 10 , [ ] ]
} ,
{
"propertyName" : "context" ,
"subPropertyName" : null ,
"propertyValues" : [ 10 , [ ] ]
} ,
{
"propertyName" : "range" ,
"subPropertyName" : null ,
"propertyValues" : [ 10 , [ ] , [ 10 ] , [ 10 , null ] , [ 10 , 11 , 12 ] ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : null ,
"propertyValues" : [ 10 , "string" ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "lineNumber" ,
"propertyValues" : [ null , "string" ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "editColumn" ,
"propertyValues" : [ null , "string" ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "deleteCount" ,
"propertyValues" : [ null , "string" ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "insertText" ,
"propertyValues" : [ 10 , [ ] ]
}
] . forEach ( function forTestCase ( testCase ) {
const { propertyName , subPropertyName , propertyValues } = testCase ;
2019-09-14 13:39:27 -07:00
propertyValues . forEach ( function forPropertyValue ( propertyValue ) {
2018-04-27 22:05:34 -07:00
const badObject = {
2018-02-27 21:14:02 -08:00
"lineNumber" : 1
} ;
2019-09-14 13:39:27 -07:00
let propertyNames = null ;
if ( subPropertyName ) {
badObject [ propertyName ] = { } ;
badObject [ propertyName ] [ subPropertyName ] = propertyValue ;
propertyNames = ` ${ propertyName } . ${ subPropertyName } ` ;
} else {
badObject [ propertyName ] = propertyValue ;
propertyNames = propertyName ;
}
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
} ;
2020-01-08 22:13:51 -08:00
test . throws (
function badErrorCall ( ) {
markdownlint . sync ( options ) ;
} ,
new RegExp (
` Property ' ${ propertyNames } ' of onError parameter is incorrect. `
) ,
"Did not get correct exception for bad object."
) ;
2018-02-27 21:14:02 -08:00
} ) ;
} ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
} ) ;
2018-03-03 22:15:49 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesOnErrorInvalid" , ( test ) => {
test . plan ( 17 ) ;
[
{
"propertyName" : "lineNumber" ,
"subPropertyName" : null ,
"propertyValues" : [ - 1 , 0 , 3 , 4 ]
} ,
{
"propertyName" : "range" ,
"subPropertyName" : null ,
"propertyValues" : [ [ 0 , 1 ] , [ 1 , 0 ] , [ 5 , 1 ] , [ 1 , 5 ] , [ 4 , 2 ] ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "lineNumber" ,
"propertyValues" : [ - 1 , 0 , 3 , 4 ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "editColumn" ,
"propertyValues" : [ 0 , 6 ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "deleteCount" ,
"propertyValues" : [ - 2 , 5 ]
}
] . forEach ( function forTestCase ( testCase ) {
const { propertyName , subPropertyName , propertyValues } = testCase ;
propertyValues . forEach ( function forPropertyValue ( propertyValue ) {
const badObject = {
"lineNumber" : 1
} ;
let propertyNames = null ;
if ( subPropertyName ) {
badObject [ propertyName ] = { } ;
badObject [ propertyName ] [ subPropertyName ] = propertyValue ;
propertyNames = ` ${ propertyName } . ${ subPropertyName } ` ;
} else {
badObject [ propertyName ] = propertyValue ;
propertyNames = propertyName ;
2019-10-30 20:37:06 -07:00
}
2020-01-08 22:13:51 -08:00
const options = {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function onErrorInvalid ( params , onError ) {
onError ( badObject ) ;
2019-04-23 22:30:33 -07:00
}
}
2020-01-08 22:13:51 -08:00
] ,
"strings" : {
"string" : "Text\ntext"
}
} ;
test . throws (
function invalidErrorCall ( ) {
2019-04-23 22:30:33 -07:00
markdownlint . sync ( options ) ;
2020-01-08 22:13:51 -08:00
} ,
new RegExp (
` Property ' ${ propertyNames } ' of onError parameter is incorrect. `
) ,
"Did not get correct exception for invalid object."
) ;
2019-04-23 22:30:33 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
test . end ( ) ;
} ) ;
2019-04-23 22:30:33 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesOnErrorValid" , ( test ) => {
test . plan ( 24 ) ;
[
{
"propertyName" : "lineNumber" ,
"subPropertyName" : null ,
"propertyValues" : [ 1 , 2 ]
} ,
{
"propertyName" : "range" ,
"subPropertyName" : null ,
"propertyValues" : [ [ 1 , 1 ] , [ 1 , 4 ] , [ 2 , 2 ] , [ 3 , 2 ] , [ 4 , 1 ] ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "lineNumber" ,
"propertyValues" : [ 1 , 2 ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "editColumn" ,
"propertyValues" : [ 1 , 2 , 4 , 5 ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "deleteCount" ,
"propertyValues" : [ - 1 , 0 , 1 , 4 ]
} ,
{
"propertyName" : "fixInfo" ,
"subPropertyName" : "insertText" ,
"propertyValues" :
[ "" , "1" , "123456" , "\n" , "\nText" , "Text\n" , "\nText\n" ]
}
] . forEach ( function forTestCase ( testCase ) {
const { propertyName , subPropertyName , propertyValues } = testCase ;
propertyValues . forEach ( function forPropertyValue ( propertyValue ) {
const goodObject = {
"lineNumber" : 1
} ;
if ( subPropertyName ) {
goodObject [ propertyName ] = { } ;
goodObject [ propertyName ] [ subPropertyName ] = propertyValue ;
} else {
goodObject [ propertyName ] = propertyValue ;
2019-10-30 20:37:06 -07:00
}
2020-01-08 22:13:51 -08:00
const options = {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function onErrorValid ( params , onError ) {
onError ( goodObject ) ;
2019-04-23 22:30:33 -07:00
}
}
2020-01-08 22:13:51 -08:00
] ,
"strings" : {
"string" : "Text\ntext"
}
} ;
markdownlint . sync ( options ) ;
test . ok ( true ) ;
2019-04-23 22:30:33 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
test . end ( ) ;
} ) ;
2019-04-23 22:30:33 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesOnErrorLazy" , ( test ) => {
test . plan ( 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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-03-17 22:11:01 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-03-17 22:11:01 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesThrowForFileHandled" , ( test ) => {
test . plan ( 2 ) ;
const exceptionMessage = "Test exception message" ;
markdownlint ( {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function throws ( ) {
throw new Error ( exceptionMessage ) ;
}
}
] ,
"files" : [ "./test/custom-rules.md" ] ,
"handleRuleFailures" : true
} , function callback ( err , actualResult ) {
test . ifError ( err ) ;
const expectedResult = {
"./test/custom-rules.md" : [
2019-05-18 12:32:52 -07:00
{
2020-01-08 22:13:51 -08:00
"lineNumber" : 1 ,
"ruleNames" : [ "name" ] ,
"ruleDescription" : "description" ,
"ruleInformation" : null ,
"errorDetail" :
` This rule threw an exception: ${ exceptionMessage } ` ,
"errorContext" : null ,
"errorRange" : null
2019-05-18 12:32:52 -07:00
}
2020-01-08 22:13:51 -08:00
]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
2019-05-18 12:32:52 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesThrowForStringHandled" , ( test ) => {
test . plan ( 2 ) ;
const exceptionMessage = "Test exception message" ;
const informationUrl = "https://example.com/rule" ;
markdownlint ( {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"information" : new URL ( informationUrl ) ,
"tags" : [ "tag" ] ,
"function" : function throws ( ) {
throw new Error ( exceptionMessage ) ;
}
}
] ,
"strings" : {
"string" : "String\n"
} ,
"handleRuleFailures" : true
} , function callback ( err , actualResult ) {
test . ifError ( err ) ;
const expectedResult = {
"string" : [
2019-05-18 12:32:52 -07:00
{
2020-01-08 22:13:51 -08:00
"lineNumber" : 1 ,
"ruleNames" : [ "MD041" , "first-line-heading" , "first-line-h1" ] ,
"ruleDescription" :
"First line in file should be a top level heading" ,
"ruleInformation" :
` ${ homepage } /blob/v ${ version } /doc/Rules.md#md041 ` ,
"errorDetail" : null ,
"errorContext" : "String" ,
"errorRange" : null
} ,
{
"lineNumber" : 1 ,
"ruleNames" : [ "name" ] ,
"ruleDescription" : "description" ,
"ruleInformation" : informationUrl ,
"errorDetail" :
` This rule threw an exception: ${ exceptionMessage } ` ,
"errorContext" : null ,
"errorRange" : null
2019-05-18 12:32:52 -07:00
}
2020-01-08 22:13:51 -08:00
]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
2019-05-18 12:32:52 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesOnErrorInvalidHandled" , ( test ) => {
test . plan ( 2 ) ;
markdownlint ( {
"customRules" : [
{
"names" : [ "name" ] ,
"description" : "description" ,
"tags" : [ "tag" ] ,
"function" : function onErrorInvalid ( params , onError ) {
onError ( {
"lineNumber" : 13 ,
2020-01-11 20:48:00 -08:00
"details" : "N/A"
2020-01-08 22:13:51 -08:00
} ) ;
}
}
] ,
"strings" : {
"string" : "# Heading\n"
} ,
"handleRuleFailures" : true
} , function callback ( err , actualResult ) {
test . ifError ( err ) ;
const expectedResult = {
"string" : [
2019-05-18 12:32:52 -07:00
{
2020-01-08 22:13:51 -08:00
"lineNumber" : 1 ,
"ruleNames" : [ "name" ] ,
"ruleDescription" : "description" ,
"ruleInformation" : null ,
"errorDetail" : "This rule threw an exception: " +
"Property 'lineNumber' of onError parameter is incorrect." ,
"errorContext" : null ,
"errorRange" : null
2019-05-18 12:32:52 -07:00
}
2020-01-08 22:13:51 -08:00
]
} ;
test . deepEqual ( actualResult , expectedResult , "Undetected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
2019-05-18 12:32:52 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesFileName" , ( test ) => {
test . plan ( 2 ) ;
2018-05-25 17:28:56 -07:00
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 ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-05-25 17:28:56 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-05-25 17:28:56 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesStringName" , ( test ) => {
test . plan ( 2 ) ;
2018-05-25 17:28:56 -07:00
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 ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-05-25 17:28:56 -07:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2018-05-25 17:28:56 -07:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesDoc" , ( test ) => {
test . plan ( 2 ) ;
2018-03-03 22:15:49 -08:00
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." ) ;
2020-01-08 22:13:51 -08:00
test . end ( ) ;
2018-03-03 22:15:49 -08:00
} ) ;
2020-01-08 22:13:51 -08:00
} ) ;
2019-01-19 12:52:13 -08:00
2020-01-08 22:13:51 -08:00
tape ( "customRulesLintJavaScript" , ( test ) => {
test . plan ( 2 ) ;
const options = {
"customRules" : customRules . lintJavaScript ,
"files" : "test/lint-javascript.md"
2019-07-30 23:07:42 -07:00
} ;
2020-01-08 22:13:51 -08:00
markdownlint ( options , ( err , actual ) => {
test . ifError ( err ) ;
const expected = {
"test/lint-javascript.md" : [
{
"lineNumber" : 10 ,
"ruleNames" : [ "lint-javascript" ] ,
"ruleDescription" : "Rule that lints JavaScript code" ,
"ruleInformation" : null ,
"errorDetail" : "Unexpected var, use let or const instead." ,
"errorContext" : "var x = 0;" ,
"errorRange" : null
} ,
{
"lineNumber" : 12 ,
"ruleNames" : [ "lint-javascript" ] ,
"ruleDescription" : "Rule that lints JavaScript code" ,
"ruleInformation" : null ,
"errorDetail" : "Unexpected console statement." ,
"errorContext" : "console.log(x);" ,
"errorRange" : null
}
2019-01-19 12:52:13 -08:00
]
2020-01-08 22:13:51 -08:00
} ;
test . deepEqual ( actual , expected , "Unexpected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
2019-01-19 12:52:13 -08:00
2020-01-08 22:13:51 -08:00
tape ( "markdownItPluginsSingle" , ( test ) => {
test . plan ( 2 ) ;
markdownlint ( {
"strings" : {
"string" : "# Heading\n\nText [ link ](https://example.com)\n"
} ,
"markdownItPlugins" : [
[
pluginInline ,
"trim_text_plugin" ,
"text" ,
function iterator ( tokens , index ) {
tokens [ index ] . content = tokens [ index ] . content . trim ( ) ;
}
2019-01-19 12:52:13 -08:00
]
2020-01-08 22:13:51 -08:00
]
} , function callback ( err , actual ) {
test . ifError ( err ) ;
const expected = { "string" : [ ] } ;
test . deepEqual ( actual , expected , "Unexpected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
2019-01-19 12:52:13 -08:00
2020-01-08 22:13:51 -08:00
tape ( "markdownItPluginsMultiple" , ( test ) => {
test . plan ( 4 ) ;
markdownlint ( {
"strings" : {
"string" : "# Heading\n\nText H~2~0 text 29^th^ text\n"
} ,
"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 . end ( ) ;
} ) ;
} ) ;
tape ( "markdownItPluginsMathjax" , ( test ) => {
test . plan ( 2 ) ;
markdownlint ( {
"strings" : {
"string" :
"# Heading\n" +
"\n" +
"$1 *2* 3$\n" +
"\n" +
"$$1 *2* 3$$\n" +
"\n" +
"$$1\n" +
"+ 2\n" +
"+ 3$$\n"
} ,
"markdownItPlugins" : [ [ pluginKatex ] ]
} , function callback ( err , actual ) {
test . ifError ( err ) ;
const expected = { "string" : [ ] } ;
test . deepEqual ( actual , expected , "Unexpected issues." ) ;
test . end ( ) ;
} ) ;
} ) ;
2019-02-13 19:52:34 -08:00
2020-01-08 22:13:51 -08:00
tape ( "markdownItPluginsMathjaxIssue166" , ( test ) => {
test . plan ( 2 ) ;
markdownlint ( {
"strings" : {
"string" :
2019-02-13 19:52:34 -08:00
` ## Heading
$$
1
$$$$
2
2019-04-05 12:36:12 +02:00
$$ \ n `
2020-01-08 22:13:51 -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 . end ( ) ;
} ) ;
} ) ;