2019-10-02 20:10:42 -07:00
/* markdownlint - https://github.com/DavidAnson/markdownlint - @license MIT */
( function ( f ) { if ( typeof exports === "object" && typeof module !== "undefined" ) { module . exports = f ( ) } else if ( typeof define === "function" && define . amd ) { define ( [ ] , f ) } else { var g ; if ( typeof window !== "undefined" ) { g = window } else if ( typeof global !== "undefined" ) { g = global } else if ( typeof self !== "undefined" ) { g = self } else { g = this } g . markdownlint = f ( ) } } ) ( function ( ) { var define , module , exports ; return ( function ( ) { function r ( e , n , t ) { function o ( i , f ) { if ( ! n [ i ] ) { if ( ! e [ i ] ) { var c = "function" == typeof require && require ; if ( ! f && c ) return c ( i , ! 0 ) ; if ( u ) return u ( i , ! 0 ) ; var a = new Error ( "Cannot find module '" + i + "'" ) ; throw a . code = "MODULE_NOT_FOUND" , a } var p = n [ i ] = { exports : { } } ; e [ i ] [ 0 ] . call ( p . exports , function ( r ) { var n = e [ i ] [ 1 ] [ r ] ; return o ( n || r ) } , p , p . exports , r , e , n , t ) } return n [ i ] . exports } for ( var u = "function" == typeof require && require , i = 0 ; i < t . length ; i ++ ) o ( t [ i ] ) ; return o } return r } ) ( ) ( { 1 : [ function ( require , module , exports ) {
"use strict" ;
// Alias "markdown-it" (expected) to "markdownit" (exported)
module . exports = window . markdownit ;
if ( ! module . exports ) {
console . error ( "markdown-it must be loaded before markdownlint." ) ;
}
// Use browser's URL implementation if not available on url module
var url = require ( "url" ) ;
if ( ! url . URL ) {
url . URL = URL ;
}
2019-12-14 13:50:48 -08:00
} , { "url" : 59 } ] , 2 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
// @ts-check
"use strict" ;
var os = require ( "os" ) ;
// Regular expression for matching common newline characters
// See NEWLINES_RE in markdown-it/lib/rules_core/normalize.js
var newLineRe = /\r\n?|\n/g ;
module . exports . newLineRe = newLineRe ;
// Regular expression for matching common front matter (YAML and TOML)
module . exports . frontMatterRe =
// eslint-disable-next-line max-len
/((^---\s*$[^]*?^---\s*$)|(^\+\+\+\s*$[^]*?^(\+\+\+|\.\.\.)\s*$))(\r\n|\r|\n|$)/m ;
// Regular expression for matching inline disable/enable comments
var inlineCommentRe =
// eslint-disable-next-line max-len
2020-04-11 13:54:46 -07:00
/<!--\s*markdownlint-(?:(?:(disable|enable|capture|restore|disable-file|enable-file)((?:\s+[a-z0-9_-]+)*))|(?:(configure-file)\s+([\s\S]*?)))\s*-->/ig ;
2019-10-02 20:10:42 -07:00
module . exports . inlineCommentRe = inlineCommentRe ;
// Regular expressions for range matching
2020-06-23 20:14:58 -07:00
module . exports . bareUrlRe = /(?:http|ftp)s?:\/\/[^\s\]"']*(?:\/|[^\s\]"'\W])/ig ;
2019-12-14 13:50:48 -08:00
module . exports . listItemMarkerRe = /^([\s>]*)(?:[*+-]|\d+[.)])\s+/ ;
2019-10-02 20:10:42 -07:00
module . exports . orderedListItemMarkerRe = /^[\s>]*0*(\d+)[.)]/ ;
2020-05-14 21:49:05 -07:00
// Regular expression for all instances of emphasis markers
var emphasisMarkersRe = /[_*]/g ;
// Regular expression for inline links and shortcut reference links
var linkRe = /\[(?:[^[\]]|\[[^\]]*\])*\](?:\(\S*\))?/g ;
2019-10-02 20:10:42 -07:00
// readFile options for reading with the UTF-8 encoding
module . exports . utf8Encoding = { "encoding" : "utf8" } ;
// All punctuation characters (normal and full-width)
module . exports . allPunctuation = ".,;:!?。,;:!?" ;
// Returns true iff the input is a number
module . exports . isNumber = function isNumber ( obj ) {
return typeof obj === "number" ;
} ;
// Returns true iff the input is a string
module . exports . isString = function isString ( obj ) {
return typeof obj === "string" ;
} ;
// Returns true iff the input string is empty
module . exports . isEmptyString = function isEmptyString ( str ) {
return str . length === 0 ;
} ;
// Returns true iff the input is an object
module . exports . isObject = function isObject ( obj ) {
return ( obj !== null ) && ( typeof obj === "object" ) && ! Array . isArray ( obj ) ;
} ;
// Returns true iff the input line is blank (no content)
// Example: Contains nothing, whitespace, or comments
var blankLineRe = />|(?:<!--.*?-->)/g ;
module . exports . isBlankLine = function isBlankLine ( line ) {
return ! line || ! line . trim ( ) || ! line . replace ( blankLineRe , "" ) . trim ( ) ;
} ;
2020-01-27 19:19:34 -08:00
/ * *
* Compare function for Array . prototype . sort for ascending order of numbers .
*
* @ param { number } a First number .
* @ param { number } b Second number .
* @ returns { number } Positive value if a > b , negative value if b < a , 0 otherwise .
* /
module . exports . numericSortAscending = function numericSortAscending ( a , b ) {
return a - b ;
} ;
2019-10-02 20:10:42 -07:00
// Returns true iff the sorted array contains the specified element
module . exports . includesSorted = function includesSorted ( array , element ) {
var left = 0 ;
var right = array . length - 1 ;
while ( left <= right ) {
/* eslint-disable no-bitwise */
var mid = ( left + right ) >> 1 ;
if ( array [ mid ] < element ) {
left = mid + 1 ;
}
else if ( array [ mid ] > element ) {
right = mid - 1 ;
}
else {
return true ;
}
}
return false ;
} ;
// Replaces the text of all properly-formatted HTML comments with whitespace
// This preserves the line/column information for the rest of the document
// Trailing whitespace is avoided with a '\' character in the last column
// See https://www.w3.org/TR/html5/syntax.html#comments for details
var htmlCommentBegin = "<!--" ;
var htmlCommentEnd = "-->" ;
module . exports . clearHtmlCommentText = function clearHtmlCommentText ( text ) {
var i = 0 ;
while ( ( i = text . indexOf ( htmlCommentBegin , i ) ) !== - 1 ) {
var j = text . indexOf ( htmlCommentEnd , i ) ;
if ( j === - 1 ) {
2020-04-11 13:54:46 -07:00
// Un-terminated comments are treated as text
break ;
2019-10-02 20:10:42 -07:00
}
var comment = text . slice ( i + htmlCommentBegin . length , j ) ;
if ( ( comment . length > 0 ) &&
( comment [ 0 ] !== ">" ) &&
( comment [ comment . length - 1 ] !== "-" ) &&
! comment . includes ( "--" ) &&
( text . slice ( i , j + htmlCommentEnd . length )
. search ( inlineCommentRe ) === - 1 ) ) {
var blanks = comment
. replace ( /[^\r\n]/g , " " )
. replace ( / ([\r\n])/g , "\\$1" ) ;
text = text . slice ( 0 , i + htmlCommentBegin . length ) +
blanks + text . slice ( j ) ;
}
i = j + htmlCommentEnd . length ;
}
return text ;
} ;
// Escapes a string for use in a RegExp
module . exports . escapeForRegExp = function escapeForRegExp ( str ) {
return str . replace ( /[-/\\^$*+?.()|[\]{}]/g , "\\$&" ) ;
} ;
// Un-escapes Markdown content (simple algorithm; not a parser)
var escapedMarkdownRe = /\\./g ;
module . exports . unescapeMarkdown =
function unescapeMarkdown ( markdown , replacement ) {
return markdown . replace ( escapedMarkdownRe , function ( match ) {
var char = match [ 1 ] ;
if ( "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" . includes ( char ) ) {
return replacement || char ;
}
return match ;
} ) ;
} ;
2020-01-27 19:19:34 -08:00
/ * *
* Return the string representation of a fence markup character .
*
* @ param { string } markup Fence string .
* @ returns { string } String representation .
* /
module . exports . fencedCodeBlockStyleFor =
function fencedCodeBlockStyleFor ( markup ) {
switch ( markup [ 0 ] ) {
case "~" :
return "tilde" ;
default :
return "backtick" ;
}
} ;
/ * *
* Return the number of characters of indent for a token .
*
* @ param { Object } token MarkdownItToken instance .
* @ returns { number } Characters of indent .
* /
2019-10-02 20:10:42 -07:00
function indentFor ( token ) {
var line = token . line . replace ( /^[\s>]*(> |>)/ , "" ) ;
return line . length - line . trimLeft ( ) . length ;
}
module . exports . indentFor = indentFor ;
// Returns the heading style for a heading token
module . exports . headingStyleFor = function headingStyleFor ( token ) {
if ( ( token . map [ 1 ] - token . map [ 0 ] ) === 1 ) {
if ( /[^\\]#\s*$/ . test ( token . line ) ) {
return "atx_closed" ;
}
return "atx" ;
}
return "setext" ;
} ;
2020-01-27 19:19:34 -08:00
/ * *
* Return the string representation of an unordered list marker .
*
* @ param { Object } token MarkdownItToken instance .
* @ returns { string } String representation .
* /
module . exports . unorderedListStyleFor = function unorderedListStyleFor ( token ) {
switch ( token . markup ) {
case "-" :
return "dash" ;
case "+" :
return "plus" ;
// case "*":
default :
return "asterisk" ;
}
} ;
/ * *
* Calls the provided function for each matching token .
*
* @ param { Object } params RuleParams instance .
* @ param { string } type Token type identifier .
* @ param { Function } handler Callback function .
* @ returns { void }
* /
2019-10-02 20:10:42 -07:00
function filterTokens ( params , type , handler ) {
params . tokens . forEach ( function forToken ( token ) {
if ( token . type === type ) {
handler ( token ) ;
}
} ) ;
}
module . exports . filterTokens = filterTokens ;
// Get line metadata array
module . exports . getLineMetadata = function getLineMetadata ( params ) {
var lineMetadata = params . lines . map ( function mapLine ( line , index ) {
return [ line , index , false , 0 , false , false ] ;
} ) ;
filterTokens ( params , "fence" , function forToken ( token ) {
lineMetadata [ token . map [ 0 ] ] [ 3 ] = 1 ;
lineMetadata [ token . map [ 1 ] - 1 ] [ 3 ] = - 1 ;
for ( var i = token . map [ 0 ] + 1 ; i < token . map [ 1 ] - 1 ; i ++ ) {
lineMetadata [ i ] [ 2 ] = true ;
}
} ) ;
filterTokens ( params , "code_block" , function forToken ( token ) {
for ( var i = token . map [ 0 ] ; i < token . map [ 1 ] ; i ++ ) {
lineMetadata [ i ] [ 2 ] = true ;
}
} ) ;
filterTokens ( params , "table_open" , function forToken ( token ) {
for ( var i = token . map [ 0 ] ; i < token . map [ 1 ] ; i ++ ) {
lineMetadata [ i ] [ 4 ] = true ;
}
} ) ;
filterTokens ( params , "list_item_open" , function forToken ( token ) {
2020-04-11 13:54:46 -07:00
var count = 1 ;
2019-10-02 20:10:42 -07:00
for ( var i = token . map [ 0 ] ; i < token . map [ 1 ] ; i ++ ) {
2020-04-11 13:54:46 -07:00
lineMetadata [ i ] [ 5 ] = count ;
count ++ ;
2019-10-02 20:10:42 -07:00
}
} ) ;
2020-04-11 13:54:46 -07:00
filterTokens ( params , "hr" , function forToken ( token ) {
lineMetadata [ token . map [ 0 ] ] [ 6 ] = true ;
} ) ;
2019-10-02 20:10:42 -07:00
return lineMetadata ;
} ;
// Calls the provided function for each line (with context)
module . exports . forEachLine = function forEachLine ( lineMetadata , handler ) {
lineMetadata . forEach ( function forMetadata ( metadata ) {
2020-05-14 21:49:05 -07:00
// Parameters: line, lineIndex, inCode, onFence, inTable, inItem, inBreak
2019-10-02 20:10:42 -07:00
handler . apply ( void 0 , metadata ) ;
} ) ;
} ;
// Returns (nested) lists as a flat array (in order)
module . exports . flattenLists = function flattenLists ( params ) {
var flattenedLists = [ ] ;
var stack = [ ] ;
var current = null ;
2020-04-11 13:54:46 -07:00
var nesting = 0 ;
var nestingStack = [ ] ;
2019-10-02 20:10:42 -07:00
var lastWithMap = { "map" : [ 0 , 1 ] } ;
params . tokens . forEach ( function forToken ( token ) {
if ( ( token . type === "bullet_list_open" ) ||
( token . type === "ordered_list_open" ) ) {
// Save current context and start a new one
stack . push ( current ) ;
current = {
"unordered" : ( token . type === "bullet_list_open" ) ,
"parentsUnordered" : ! current ||
( current . unordered && current . parentsUnordered ) ,
"open" : token ,
"indent" : indentFor ( token ) ,
"parentIndent" : ( current && current . indent ) || 0 ,
"items" : [ ] ,
2020-04-11 13:54:46 -07:00
"nesting" : nesting ,
2019-10-02 20:10:42 -07:00
"lastLineIndex" : - 1 ,
"insert" : flattenedLists . length
} ;
2020-04-11 13:54:46 -07:00
nesting ++ ;
2019-10-02 20:10:42 -07:00
}
else if ( ( token . type === "bullet_list_close" ) ||
( token . type === "ordered_list_close" ) ) {
// Finalize current context and restore previous
current . lastLineIndex = lastWithMap . map [ 1 ] ;
flattenedLists . splice ( current . insert , 0 , current ) ;
delete current . insert ;
current = stack . pop ( ) ;
2020-04-11 13:54:46 -07:00
nesting -- ;
2019-10-02 20:10:42 -07:00
}
else if ( token . type === "list_item_open" ) {
// Add list item
current . items . push ( token ) ;
}
2020-04-11 13:54:46 -07:00
else if ( token . type === "blockquote_open" ) {
nestingStack . push ( nesting ) ;
nesting = 0 ;
}
else if ( token . type === "blockquote_close" ) {
nesting = nestingStack . pop ( ) ;
}
2019-10-02 20:10:42 -07:00
else if ( token . map ) {
// Track last token with map
lastWithMap = token ;
}
} ) ;
return flattenedLists ;
} ;
// Calls the provided function for each specified inline child token
module . exports . forEachInlineChild =
function forEachInlineChild ( params , type , handler ) {
filterTokens ( params , "inline" , function forToken ( token ) {
token . children . forEach ( function forChild ( child ) {
if ( child . type === type ) {
handler ( child , token ) ;
}
} ) ;
} ) ;
} ;
// Calls the provided function for each heading's content
module . exports . forEachHeading = function forEachHeading ( params , handler ) {
var heading = null ;
params . tokens . forEach ( function forToken ( token ) {
if ( token . type === "heading_open" ) {
heading = token ;
}
else if ( token . type === "heading_close" ) {
heading = null ;
}
else if ( ( token . type === "inline" ) && heading ) {
handler ( heading , token . content ) ;
}
} ) ;
} ;
2020-04-25 21:15:13 -07:00
/ * *
* Calls the provided function for each inline code span ' s content .
*
* @ param { string } input Markdown content .
* @ param { Function } handler Callback function .
* @ returns { void }
* /
function forEachInlineCodeSpan ( input , handler ) {
var currentLine = 0 ;
var currentColumn = 0 ;
var index = 0 ;
while ( index < input . length ) {
var startIndex = - 1 ;
var startLine = - 1 ;
var startColumn = - 1 ;
var tickCount = 0 ;
var currentTicks = 0 ;
var state = "normal" ;
// Deliberate <= so trailing 0 completes the last span (ex: "text `code`")
for ( ; index <= input . length ; index ++ ) {
var char = input [ index ] ;
// Ignore backticks in link destination
if ( ( char === "[" ) && ( state === "normal" ) ) {
state = "linkTextOpen" ;
}
else if ( ( char === "]" ) && ( state === "linkTextOpen" ) ) {
state = "linkTextClosed" ;
}
else if ( ( char === "(" ) && ( state === "linkTextClosed" ) ) {
state = "linkDestinationOpen" ;
}
else if ( ( ( char === "(" ) && ( state === "linkDestinationOpen" ) ) ||
( ( char === ")" ) && ( state === "linkDestinationOpen" ) ) ||
( state === "linkTextClosed" ) ) {
state = "normal" ;
}
// Parse backtick open/close
if ( ( char === "`" ) && ( state !== "linkDestinationOpen" ) ) {
// Count backticks at start or end of code span
currentTicks ++ ;
if ( ( startIndex === - 1 ) || ( startColumn === - 1 ) ) {
startIndex = index + 1 ;
2019-10-02 20:10:42 -07:00
}
}
2020-04-25 21:15:13 -07:00
else {
if ( ( startIndex >= 0 ) &&
( startColumn >= 0 ) &&
( tickCount === currentTicks ) ) {
// Found end backticks; invoke callback for code span
handler ( input . substring ( startIndex , index - currentTicks ) , startLine , startColumn , tickCount ) ;
startIndex = - 1 ;
startColumn = - 1 ;
}
else if ( ( startIndex >= 0 ) && ( startColumn === - 1 ) ) {
// Found start backticks
tickCount = currentTicks ;
startLine = currentLine ;
startColumn = currentColumn ;
}
// Not in backticks
currentTicks = 0 ;
}
if ( char === "\n" ) {
// On next line
currentLine ++ ;
currentColumn = 0 ;
}
else if ( ( char === "\\" ) &&
( ( startIndex === - 1 ) || ( startColumn === - 1 ) ) &&
( input [ index + 1 ] !== "\n" ) ) {
// Escape character outside code, skip next
index ++ ;
currentColumn += 2 ;
}
else {
// On next column
currentColumn ++ ;
2019-10-02 20:10:42 -07:00
}
}
2020-04-25 21:15:13 -07:00
if ( startIndex >= 0 ) {
// Restart loop after unmatched start backticks (ex: "`text``code``")
index = startIndex ;
currentLine = startLine ;
currentColumn = startColumn ;
}
}
}
module . exports . forEachInlineCodeSpan = forEachInlineCodeSpan ;
2020-01-27 19:19:34 -08:00
/ * *
* Adds a generic error object via the onError callback .
*
* @ param { Object } onError RuleOnError instance .
* @ param { number } lineNumber Line number .
* @ param { string } [ detail ] Error details .
* @ param { string } [ context ] Error context .
* @ param { number [ ] } [ range ] Column and length of error .
* @ param { Object } [ fixInfo ] RuleOnErrorFixInfo instance .
* @ returns { void }
* /
2019-10-02 20:10:42 -07:00
function addError ( onError , lineNumber , detail , context , range , fixInfo ) {
onError ( {
lineNumber : lineNumber ,
detail : detail ,
context : context ,
range : range ,
fixInfo : fixInfo
} ) ;
}
module . exports . addError = addError ;
// Adds an error object with details conditionally via the onError callback
module . exports . addErrorDetailIf = function addErrorDetailIf ( onError , lineNumber , expected , actual , detail , context , range , fixInfo ) {
if ( expected !== actual ) {
addError ( onError , lineNumber , "Expected: " + expected + "; Actual: " + actual +
( detail ? "; " + detail : "" ) , context , range , fixInfo ) ;
}
} ;
// Adds an error object with context via the onError callback
module . exports . addErrorContext = function addErrorContext ( onError , lineNumber , context , left , right , range , fixInfo ) {
if ( context . length <= 30 ) {
// Nothing to do
}
else if ( left && right ) {
context = context . substr ( 0 , 15 ) + "..." + context . substr ( - 15 ) ;
}
else if ( right ) {
context = "..." + context . substr ( - 30 ) ;
}
else {
context = context . substr ( 0 , 30 ) + "..." ;
}
addError ( onError , lineNumber , null , context , range , fixInfo ) ;
} ;
// Returns a range object for a line by applying a RegExp
module . exports . rangeFromRegExp = function rangeFromRegExp ( line , regexp ) {
var range = null ;
var match = line . match ( regexp ) ;
if ( match ) {
var column = match . index + 1 ;
var length _1 = match [ 0 ] . length ;
range = [ column , length _1 ] ;
}
return range ;
} ;
// Determines if the front matter includes a title
module . exports . frontMatterHasTitle =
function frontMatterHasTitle ( frontMatterLines , frontMatterTitlePattern ) {
var ignoreFrontMatter = ( frontMatterTitlePattern !== undefined ) && ! frontMatterTitlePattern ;
2020-01-27 19:19:34 -08:00
var frontMatterTitleRe = new RegExp ( String ( frontMatterTitlePattern || "^\\s*title\\s*[:=]" ) , "i" ) ;
2019-10-02 20:10:42 -07:00
return ! ignoreFrontMatter &&
frontMatterLines . some ( function ( line ) { return frontMatterTitleRe . test ( line ) ; } ) ;
} ;
2020-04-25 21:15:13 -07:00
/ * *
2020-05-14 21:49:05 -07:00
* Returns a list of emphasis markers in code spans and links .
2020-04-25 21:15:13 -07:00
*
* @ param { Object } params RuleParams instance .
* @ returns { number [ ] [ ] } List of markers .
* /
2020-05-14 21:49:05 -07:00
function emphasisMarkersInContent ( params ) {
2020-04-25 21:15:13 -07:00
var lines = params . lines ;
var byLine = new Array ( lines . length ) ;
2020-05-14 21:49:05 -07:00
// Search code spans
2020-04-25 21:15:13 -07:00
filterTokens ( params , "inline" , function ( token ) {
var children = token . children , lineNumber = token . lineNumber , map = token . map ;
if ( children . some ( function ( child ) { return child . type === "code_inline" ; } ) ) {
var tokenLines = lines . slice ( map [ 0 ] , map [ 1 ] ) ;
forEachInlineCodeSpan ( tokenLines . join ( "\n" ) , function ( code , lineIndex , column , tickCount ) {
var codeLines = code . split ( newLineRe ) ;
codeLines . forEach ( function ( codeLine , codeLineIndex ) {
var match = null ;
while ( ( match = emphasisMarkersRe . exec ( codeLine ) ) ) {
var byLineIndex = lineNumber - 1 + lineIndex + codeLineIndex ;
var inLine = byLine [ byLineIndex ] || [ ] ;
var codeLineOffset = codeLineIndex ? 0 : column - 1 + tickCount ;
inLine . push ( codeLineOffset + match . index ) ;
byLine [ byLineIndex ] = inLine ;
}
} ) ;
} ) ;
}
} ) ;
2020-05-14 21:49:05 -07:00
// Search links
lines . forEach ( function ( tokenLine , tokenLineIndex ) {
var linkMatch = null ;
while ( ( linkMatch = linkRe . exec ( tokenLine ) ) ) {
var markerMatch = null ;
while ( ( markerMatch = emphasisMarkersRe . exec ( linkMatch [ 0 ] ) ) ) {
var inLine = byLine [ tokenLineIndex ] || [ ] ;
inLine . push ( linkMatch . index + markerMatch . index ) ;
byLine [ tokenLineIndex ] = inLine ;
}
}
} ) ;
2020-04-25 21:15:13 -07:00
return byLine ;
}
2020-05-14 21:49:05 -07:00
module . exports . emphasisMarkersInContent = emphasisMarkersInContent ;
2020-01-27 19:19:34 -08:00
/ * *
* Gets the most common line ending , falling back to the platform default .
*
* @ param { string } input Markdown content to analyze .
* @ returns { string } Preferred line ending .
* /
2019-10-02 20:10:42 -07:00
function getPreferredLineEnding ( input ) {
var cr = 0 ;
var lf = 0 ;
var crlf = 0 ;
var endings = input . match ( newLineRe ) || [ ] ;
endings . forEach ( function ( ending ) {
// eslint-disable-next-line default-case
switch ( ending ) {
case "\r" :
cr ++ ;
break ;
case "\n" :
lf ++ ;
break ;
case "\r\n" :
crlf ++ ;
break ;
}
} ) ;
var preferredLineEnding = null ;
if ( ! cr && ! lf && ! crlf ) {
preferredLineEnding = os . EOL ;
}
else if ( ( lf >= crlf ) && ( lf >= cr ) ) {
preferredLineEnding = "\n" ;
}
else if ( crlf >= cr ) {
preferredLineEnding = "\r\n" ;
}
else {
preferredLineEnding = "\r" ;
}
return preferredLineEnding ;
}
module . exports . getPreferredLineEnding = getPreferredLineEnding ;
2020-01-27 19:19:34 -08:00
/ * *
* Normalizes the fields of a RuleOnErrorFixInfo instance .
*
* @ param { Object } fixInfo RuleOnErrorFixInfo instance .
* @ param { number } [ lineNumber ] Line number .
* @ returns { Object } Normalized RuleOnErrorFixInfo instance .
* /
2019-10-02 20:10:42 -07:00
function normalizeFixInfo ( fixInfo , lineNumber ) {
return {
"lineNumber" : fixInfo . lineNumber || lineNumber ,
"editColumn" : fixInfo . editColumn || 1 ,
"deleteCount" : fixInfo . deleteCount || 0 ,
"insertText" : fixInfo . insertText || ""
} ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Fixes the specified error on a line of Markdown content .
*
* @ param { string } line Line of Markdown content .
* @ param { Object } fixInfo RuleOnErrorFixInfo instance .
* @ param { string } lineEnding Line ending to use .
* @ returns { string } Fixed content .
* /
2019-10-02 20:10:42 -07:00
function applyFix ( line , fixInfo , lineEnding ) {
var _a = normalizeFixInfo ( fixInfo ) , editColumn = _a . editColumn , deleteCount = _a . deleteCount , insertText = _a . insertText ;
var editIndex = editColumn - 1 ;
return ( deleteCount === - 1 ) ?
null :
line . slice ( 0 , editIndex ) +
insertText . replace ( /\n/g , lineEnding || "\n" ) +
line . slice ( editIndex + deleteCount ) ;
}
module . exports . applyFix = applyFix ;
// Applies as many fixes as possible to the input lines
module . exports . applyFixes = function applyFixes ( input , errors ) {
var lineEnding = getPreferredLineEnding ( input ) ;
var lines = input . split ( newLineRe ) ;
// Normalize fixInfo objects
var fixInfos = errors
. filter ( function ( error ) { return error . fixInfo ; } )
. map ( function ( error ) { return normalizeFixInfo ( error . fixInfo , error . lineNumber ) ; } ) ;
// Sort bottom-to-top, line-deletes last, right-to-left, long-to-short
fixInfos . sort ( function ( a , b ) {
var aDeletingLine = ( a . deleteCount === - 1 ) ;
var bDeletingLine = ( b . deleteCount === - 1 ) ;
return ( ( b . lineNumber - a . lineNumber ) ||
( aDeletingLine ? 1 : ( bDeletingLine ? - 1 : 0 ) ) ||
( b . editColumn - a . editColumn ) ||
( b . insertText . length - a . insertText . length ) ) ;
} ) ;
// Remove duplicate entries (needed for following collapse step)
var lastFixInfo = { } ;
fixInfos = fixInfos . filter ( function ( fixInfo ) {
var unique = ( ( fixInfo . lineNumber !== lastFixInfo . lineNumber ) ||
( fixInfo . editColumn !== lastFixInfo . editColumn ) ||
( fixInfo . deleteCount !== lastFixInfo . deleteCount ) ||
( fixInfo . insertText !== lastFixInfo . insertText ) ) ;
lastFixInfo = fixInfo ;
return unique ;
} ) ;
// Collapse insert/no-delete and no-insert/delete for same line/column
lastFixInfo = { } ;
fixInfos . forEach ( function ( fixInfo ) {
if ( ( fixInfo . lineNumber === lastFixInfo . lineNumber ) &&
( fixInfo . editColumn === lastFixInfo . editColumn ) &&
! fixInfo . insertText &&
( fixInfo . deleteCount > 0 ) &&
lastFixInfo . insertText &&
! lastFixInfo . deleteCount ) {
fixInfo . insertText = lastFixInfo . insertText ;
lastFixInfo . lineNumber = 0 ;
}
lastFixInfo = fixInfo ;
} ) ;
fixInfos = fixInfos . filter ( function ( fixInfo ) { return fixInfo . lineNumber ; } ) ;
// Apply all (remaining/updated) fixes
var lastLineIndex = - 1 ;
var lastEditIndex = - 1 ;
fixInfos . forEach ( function ( fixInfo ) {
var lineNumber = fixInfo . lineNumber , editColumn = fixInfo . editColumn , deleteCount = fixInfo . deleteCount ;
var lineIndex = lineNumber - 1 ;
var editIndex = editColumn - 1 ;
if ( ( lineIndex !== lastLineIndex ) ||
( ( editIndex + deleteCount ) < lastEditIndex ) ||
( deleteCount === - 1 ) ) {
lines [ lineIndex ] = applyFix ( lines [ lineIndex ] , fixInfo , lineEnding ) ;
}
lastLineIndex = lineIndex ;
lastEditIndex = editIndex ;
} ) ;
// Return corrected input
return lines . filter ( function ( line ) { return line !== null ; } ) . join ( lineEnding ) ;
} ;
2019-12-14 13:50:48 -08:00
} , { "os" : 52 } ] , 3 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
// @ts-check
"use strict" ;
var lineMetadata = null ;
module . exports . lineMetadata = function ( value ) {
if ( value ) {
lineMetadata = value ;
}
return lineMetadata ;
} ;
var flattenedLists = null ;
module . exports . flattenedLists = function ( value ) {
if ( value ) {
flattenedLists = value ;
}
return flattenedLists ;
} ;
module . exports . clear = function ( ) {
lineMetadata = null ;
flattenedLists = null ;
} ;
} , { } ] , 4 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _ _assign = ( this && this . _ _assign ) || function ( ) {
_ _assign = Object . assign || function ( t ) {
for ( var s , i = 1 , n = arguments . length ; i < n ; i ++ ) {
s = arguments [ i ] ;
for ( var p in s ) if ( Object . prototype . hasOwnProperty . call ( s , p ) )
t [ p ] = s [ p ] ;
}
return t ;
} ;
return _ _assign . apply ( this , arguments ) ;
} ;
2020-01-27 19:19:34 -08:00
var _ _spreadArrays = ( this && this . _ _spreadArrays ) || function ( ) {
for ( var s = 0 , i = 0 , il = arguments . length ; i < il ; i ++ ) s += arguments [ i ] . length ;
for ( var r = Array ( s ) , k = 0 , i = 0 ; i < il ; i ++ )
for ( var a = arguments [ i ] , j = 0 , jl = a . length ; j < jl ; j ++ , k ++ )
r [ k ] = a [ j ] ;
return r ;
} ;
2019-10-02 20:10:42 -07:00
var fs = require ( "fs" ) ;
var path = require ( "path" ) ;
var URL = require ( "url" ) . URL ;
var markdownIt = require ( "markdown-it" ) ;
var rules = require ( "./rules" ) ;
var helpers = require ( "../helpers" ) ;
var cache = require ( "./cache" ) ;
2020-01-27 19:19:34 -08:00
var deprecatedRuleNames = [ "MD002" , "MD006" ] ;
/ * *
* Validate the list of rules for structure and reuse .
*
* @ param { Rule [ ] } ruleList List of rules .
* @ returns { string } Error message if validation fails .
* /
2019-10-02 20:10:42 -07:00
function validateRuleList ( ruleList ) {
var result = null ;
if ( ruleList . length === rules . length ) {
// No need to validate if only using built-in rules
return result ;
}
var allIds = { } ;
ruleList . forEach ( function forRule ( rule , index ) {
var customIndex = index - rules . length ;
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2019-10-02 20:10:42 -07:00
function newError ( property ) {
return new Error ( "Property '" + property + "' of custom rule at index " +
customIndex + " is incorrect." ) ;
}
[ "names" , "tags" ] . forEach ( function forProperty ( property ) {
var value = rule [ property ] ;
if ( ! result &&
( ! value || ! Array . isArray ( value ) || ( value . length === 0 ) ||
! value . every ( helpers . isString ) || value . some ( helpers . isEmptyString ) ) ) {
result = newError ( property ) ;
}
} ) ;
[
[ "description" , "string" ] ,
[ "function" , "function" ]
] . forEach ( function forProperty ( propertyInfo ) {
var property = propertyInfo [ 0 ] ;
var value = rule [ property ] ;
if ( ! result && ( ! value || ( typeof value !== propertyInfo [ 1 ] ) ) ) {
result = newError ( property ) ;
}
} ) ;
if ( ! result && rule . information ) {
if ( Object . getPrototypeOf ( rule . information ) !== URL . prototype ) {
result = newError ( "information" ) ;
}
}
if ( ! result ) {
rule . names . forEach ( function forName ( name ) {
var nameUpper = name . toUpperCase ( ) ;
if ( ! result && ( allIds [ nameUpper ] !== undefined ) ) {
result = new Error ( "Name '" + name + "' of custom rule at index " +
customIndex + " is already used as a name or tag." ) ;
}
allIds [ nameUpper ] = true ;
} ) ;
rule . tags . forEach ( function forTag ( tag ) {
var tagUpper = tag . toUpperCase ( ) ;
if ( ! result && allIds [ tagUpper ] ) {
result = new Error ( "Tag '" + tag + "' of custom rule at index " +
customIndex + " is already used as a name." ) ;
}
allIds [ tagUpper ] = false ;
} ) ;
}
} ) ;
return result ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Creates a LintResults instance with toString for pretty display .
*
* @ param { Rule [ ] } ruleList List of rules .
* @ returns { LintResults } New LintResults instance .
* /
2019-10-02 20:10:42 -07:00
function newResults ( ruleList ) {
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2019-10-02 20:10:42 -07:00
function Results ( ) { }
Results . prototype . toString = function toString ( useAlias ) {
var that = this ;
var ruleNameToRule = null ;
var results = [ ] ;
Object . keys ( that ) . forEach ( function forFile ( file ) {
var fileResults = that [ file ] ;
if ( Array . isArray ( fileResults ) ) {
fileResults . forEach ( function forResult ( result ) {
var ruleMoniker = result . ruleNames ?
result . ruleNames . join ( "/" ) :
( result . ruleName + "/" + result . ruleAlias ) ;
results . push ( file + ": " +
result . lineNumber + ": " +
ruleMoniker + " " +
result . ruleDescription +
( result . errorDetail ?
" [" + result . errorDetail + "]" :
"" ) +
( result . errorContext ?
" [Context: \"" + result . errorContext + "\"]" :
"" ) ) ;
} ) ;
}
else {
if ( ! ruleNameToRule ) {
ruleNameToRule = { } ;
ruleList . forEach ( function forRule ( rule ) {
var ruleName = rule . names [ 0 ] . toUpperCase ( ) ;
ruleNameToRule [ ruleName ] = rule ;
} ) ;
}
Object . keys ( fileResults ) . forEach ( function forRule ( ruleName ) {
var rule = ruleNameToRule [ ruleName . toUpperCase ( ) ] ;
var ruleResults = fileResults [ ruleName ] ;
ruleResults . forEach ( function forLine ( lineNumber ) {
var nameIndex = Math . min ( useAlias ? 1 : 0 , rule . names . length - 1 ) ;
var result = file + ": " +
lineNumber + ": " +
rule . names [ nameIndex ] + " " +
rule . description ;
results . push ( result ) ;
} ) ;
} ) ;
}
} ) ;
return results . join ( "\n" ) ;
} ;
2020-01-27 19:19:34 -08:00
// @ts-ignore
2019-10-02 20:10:42 -07:00
return new Results ( ) ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Remove front matter ( if present at beginning of content ) .
*
* @ param { string } content Markdown content .
* @ param { RegExp } frontMatter Regular expression to match front matter .
* @ returns { Object } Trimmed content and front matter lines .
* /
2019-10-02 20:10:42 -07:00
function removeFrontMatter ( content , frontMatter ) {
var frontMatterLines = [ ] ;
if ( frontMatter ) {
var frontMatterMatch = content . match ( frontMatter ) ;
if ( frontMatterMatch && ! frontMatterMatch . index ) {
var contentMatched = frontMatterMatch [ 0 ] ;
content = content . slice ( contentMatched . length ) ;
frontMatterLines = contentMatched . split ( helpers . newLineRe ) ;
if ( frontMatterLines . length &&
( frontMatterLines [ frontMatterLines . length - 1 ] === "" ) ) {
frontMatterLines . length -- ;
}
}
}
return {
"content" : content ,
"frontMatterLines" : frontMatterLines
} ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Annotate tokens with line / lineNumber .
*
* @ param { MarkdownItToken [ ] } tokens Array of markdown - it tokens .
* @ param { string [ ] } lines Lines of Markdown content .
* @ returns { void }
* /
2019-10-02 20:10:42 -07:00
function annotateTokens ( tokens , lines ) {
var tbodyMap = null ;
tokens . forEach ( function forToken ( token ) {
// Handle missing maps for table body
if ( token . type === "tbody_open" ) {
tbodyMap = token . map . slice ( ) ;
}
else if ( ( token . type === "tr_close" ) && tbodyMap ) {
tbodyMap [ 0 ] ++ ;
}
else if ( token . type === "tbody_close" ) {
tbodyMap = null ;
}
if ( tbodyMap && ! token . map ) {
token . map = tbodyMap . slice ( ) ;
}
// Update token metadata
if ( token . map ) {
token . line = lines [ token . map [ 0 ] ] ;
token . lineNumber = token . map [ 0 ] + 1 ;
// Trim bottom of token to exclude whitespace lines
while ( token . map [ 1 ] && ! ( ( lines [ token . map [ 1 ] - 1 ] || "" ) . trim ( ) ) ) {
token . map [ 1 ] -- ;
}
// Annotate children with lineNumber
var lineNumber _1 = token . lineNumber ;
var codeSpanExtraLines _1 = [ ] ;
helpers . forEachInlineCodeSpan ( token . content , function handleInlineCodeSpan ( code ) {
codeSpanExtraLines _1 . push ( code . split ( helpers . newLineRe ) . length - 1 ) ;
} ) ;
( token . children || [ ] ) . forEach ( function forChild ( child ) {
child . lineNumber = lineNumber _1 ;
child . line = lines [ lineNumber _1 - 1 ] ;
if ( ( child . type === "softbreak" ) || ( child . type === "hardbreak" ) ) {
lineNumber _1 ++ ;
}
else if ( child . type === "code_inline" ) {
lineNumber _1 += codeSpanExtraLines _1 . shift ( ) ;
}
} ) ;
}
} ) ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Map rule names / tags to canonical rule name .
*
* @ param { Rule [ ] } ruleList List of rules .
* @ returns { Object . < string , string [ ] > } Map of alias to rule name .
* /
2019-10-02 20:10:42 -07:00
function mapAliasToRuleNames ( ruleList ) {
var aliasToRuleNames = { } ;
// const tagToRuleNames = {};
ruleList . forEach ( function forRule ( rule ) {
var ruleName = rule . names [ 0 ] . toUpperCase ( ) ;
// The following is useful for updating README.md:
// console.log(
// "* **[" + ruleName + "](doc/Rules.md#" + ruleName.toLowerCase() +
// ")** *" + rule.names.slice(1).join("/") + "* - " + rule.description);
rule . names . forEach ( function forName ( name ) {
var nameUpper = name . toUpperCase ( ) ;
aliasToRuleNames [ nameUpper ] = [ ruleName ] ;
} ) ;
rule . tags . forEach ( function forTag ( tag ) {
var tagUpper = tag . toUpperCase ( ) ;
var ruleNames = aliasToRuleNames [ tagUpper ] || [ ] ;
ruleNames . push ( ruleName ) ;
aliasToRuleNames [ tagUpper ] = ruleNames ;
// tagToRuleNames[tag] = ruleName;
} ) ;
} ) ;
// The following is useful for updating README.md:
// Object.keys(tagToRuleNames).sort().forEach(function forTag(tag) {
// console.log("* **" + tag + "** - " +
// aliasToRuleNames[tag.toUpperCase()].join(", "));
// });
2020-01-27 19:19:34 -08:00
// @ts-ignore
2019-10-02 20:10:42 -07:00
return aliasToRuleNames ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Apply ( and normalize ) configuration object .
*
* @ param { Rule [ ] } ruleList List of rules .
* @ param { Configuration } config Configuration object .
* @ param { Object . < string , string [ ] > } aliasToRuleNames Map of alias to rule
* names .
* @ returns { Configuration } Effective configuration .
* /
2019-10-02 20:10:42 -07:00
function getEffectiveConfig ( ruleList , config , aliasToRuleNames ) {
var defaultKey = Object . keys ( config ) . filter ( function ( key ) { return key . toUpperCase ( ) === "DEFAULT" ; } ) ;
var ruleDefault = ( defaultKey . length === 0 ) || ! ! config [ defaultKey [ 0 ] ] ;
var effectiveConfig = { } ;
ruleList . forEach ( function ( rule ) {
var ruleName = rule . names [ 0 ] . toUpperCase ( ) ;
effectiveConfig [ ruleName ] = ruleDefault ;
} ) ;
deprecatedRuleNames . forEach ( function ( ruleName ) {
effectiveConfig [ ruleName ] = false ;
} ) ;
Object . keys ( config ) . forEach ( function ( key ) {
var value = config [ key ] ;
if ( value ) {
if ( ! ( value instanceof Object ) ) {
value = { } ;
}
}
else {
value = false ;
}
var keyUpper = key . toUpperCase ( ) ;
( aliasToRuleNames [ keyUpper ] || [ ] ) . forEach ( function ( ruleName ) {
effectiveConfig [ ruleName ] = value ;
} ) ;
} ) ;
return effectiveConfig ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Create a mapping of enabled rules per line .
*
* @ param { Rule [ ] } ruleList List of rules .
* @ param { string [ ] } lines List of content lines .
* @ param { string [ ] } frontMatterLines List of front matter lines .
* @ param { boolean } noInlineConfig Whether to allow inline configuration .
2020-04-11 13:54:46 -07:00
* @ param { Configuration } config Configuration object .
2020-01-27 19:19:34 -08:00
* @ param { Object . < string , string [ ] > } aliasToRuleNames Map of alias to rule
* names .
2020-04-11 13:54:46 -07:00
* @ returns { Object } Effective configuration and enabled rules per line number .
2020-01-27 19:19:34 -08:00
* /
2020-04-11 13:54:46 -07:00
function getEnabledRulesPerLineNumber ( ruleList , lines , frontMatterLines , noInlineConfig , config , aliasToRuleNames ) {
// Shared variables
2019-10-02 20:10:42 -07:00
var enabledRules = { } ;
2020-04-11 13:54:46 -07:00
var capturedRules = { } ;
2019-10-02 20:10:42 -07:00
var allRuleNames = [ ] ;
2020-04-11 13:54:46 -07:00
var enabledRulesPerLineNumber = new Array ( 1 + frontMatterLines . length ) ;
// Helper functions
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2020-04-11 13:54:46 -07:00
function handleInlineConfig ( perLine , forEachMatch , forEachLine ) {
var input = perLine ? lines : [ lines . join ( "\n" ) ] ;
input . forEach ( function ( line ) {
if ( ! noInlineConfig ) {
var match = null ;
while ( ( match = helpers . inlineCommentRe . exec ( line ) ) ) {
var action = ( match [ 1 ] || match [ 3 ] ) . toUpperCase ( ) ;
var parameter = match [ 2 ] || match [ 4 ] ;
forEachMatch ( action , parameter ) ;
}
2019-12-14 13:50:48 -08:00
}
2020-04-11 13:54:46 -07:00
if ( forEachLine ) {
forEachLine ( ) ;
2019-12-14 13:50:48 -08:00
}
2020-04-11 13:54:46 -07:00
} ) ;
2019-10-02 20:10:42 -07:00
}
2020-04-11 13:54:46 -07:00
// eslint-disable-next-line jsdoc/require-jsdoc
function configureFile ( action , parameter ) {
if ( action === "CONFIGURE-FILE" ) {
try {
var json = JSON . parse ( parameter ) ;
config = _ _assign ( _ _assign ( { } , config ) , json ) ;
2019-10-02 20:10:42 -07:00
}
2020-04-11 13:54:46 -07:00
catch ( ex ) {
// Ignore parse errors for inline configuration
2019-12-14 13:50:48 -08:00
}
2020-04-11 13:54:46 -07:00
}
}
// eslint-disable-next-line jsdoc/require-jsdoc
function applyEnableDisable ( action , parameter ) {
var enabled = ( action . startsWith ( "ENABLE" ) ) ;
var items = parameter ?
parameter . trim ( ) . toUpperCase ( ) . split ( /\s+/ ) :
allRuleNames ;
items . forEach ( function ( nameUpper ) {
( aliasToRuleNames [ nameUpper ] || [ ] ) . forEach ( function ( ruleName ) {
enabledRules [ ruleName ] = enabled ;
} ) ;
2019-12-14 13:50:48 -08:00
} ) ;
2020-04-11 13:54:46 -07:00
}
// eslint-disable-next-line jsdoc/require-jsdoc
function enableDisableFile ( action , parameter ) {
if ( ( action === "ENABLE-FILE" ) || ( action === "DISABLE-FILE" ) ) {
applyEnableDisable ( action , parameter ) ;
}
}
// eslint-disable-next-line jsdoc/require-jsdoc
function captureRestoreEnableDisable ( action , parameter ) {
if ( action === "CAPTURE" ) {
capturedRules = _ _assign ( { } , enabledRules ) ;
}
else if ( action === "RESTORE" ) {
enabledRules = _ _assign ( { } , capturedRules ) ;
}
else if ( ( action === "ENABLE" ) || ( action === "DISABLE" ) ) {
enabledRules = _ _assign ( { } , enabledRules ) ;
applyEnableDisable ( action , parameter ) ;
}
}
// eslint-disable-next-line jsdoc/require-jsdoc
function updateLineState ( ) {
enabledRulesPerLineNumber . push ( enabledRules ) ;
}
// Handle inline comments
handleInlineConfig ( false , configureFile ) ;
var effectiveConfig = getEffectiveConfig ( ruleList , config , aliasToRuleNames ) ;
ruleList . forEach ( function ( rule ) {
var ruleName = rule . names [ 0 ] . toUpperCase ( ) ;
allRuleNames . push ( ruleName ) ;
enabledRules [ ruleName ] = ! ! effectiveConfig [ ruleName ] ;
2019-10-02 20:10:42 -07:00
} ) ;
2020-04-11 13:54:46 -07:00
capturedRules = enabledRules ;
handleInlineConfig ( true , enableDisableFile ) ;
handleInlineConfig ( true , captureRestoreEnableDisable , updateLineState ) ;
// Return results
return {
effectiveConfig : effectiveConfig ,
enabledRulesPerLineNumber : enabledRulesPerLineNumber
} ;
2019-10-02 20:10:42 -07:00
}
2020-01-27 19:19:34 -08:00
/ * *
* Compare function for Array . prototype . sort for ascending order of errors .
*
* @ param { LintError } a First error .
* @ param { LintError } b Second error .
* @ returns { number } Positive value if a > b , negative value if b < a , 0 otherwise .
* /
2019-10-02 20:10:42 -07:00
function lineNumberComparison ( a , b ) {
return a . lineNumber - b . lineNumber ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Filter function to include everything .
*
* @ returns { boolean } True .
* /
2019-10-02 20:10:42 -07:00
function filterAllValues ( ) {
return true ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Function to return unique values from a sorted errors array .
*
* @ param { LintError } value Error instance .
* @ param { number } index Index in array .
* @ param { LintError [ ] } array Array of errors .
* @ returns { boolean } Filter value .
* /
2019-10-02 20:10:42 -07:00
function uniqueFilterForSortedErrors ( value , index , array ) {
return ( index === 0 ) || ( value . lineNumber > array [ index - 1 ] . lineNumber ) ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Lints a string containing Markdown content .
*
* @ param { Rule [ ] } ruleList List of rules .
* @ param { string } name Identifier for the content .
* @ param { string } content Markdown content
* @ param { Object } md markdown - it instance .
* @ param { Configuration } config Configuration object .
* @ param { RegExp } frontMatter Regular expression for front matter .
* @ param { boolean } handleRuleFailures Whether to handle exceptions in rules .
* @ param { boolean } noInlineConfig Whether to allow inline configuration .
* @ param { number } resultVersion Version of the LintResults object to return .
* @ param { Function } callback Callback ( err , result ) function .
* @ returns { void }
* /
2019-10-02 20:10:42 -07:00
function lintContent ( ruleList , name , content , md , config , frontMatter , handleRuleFailures , noInlineConfig , resultVersion , callback ) {
// Remove UTF-8 byte order marker (if present)
content = content . replace ( /^\ufeff/ , "" ) ;
// Remove front matter
var removeFrontMatterResult = removeFrontMatter ( content , frontMatter ) ;
var frontMatterLines = removeFrontMatterResult . frontMatterLines ;
// Ignore the content of HTML comments
content = helpers . clearHtmlCommentText ( removeFrontMatterResult . content ) ;
// Parse content into tokens and lines
var tokens = md . parse ( content , { } ) ;
var lines = content . split ( helpers . newLineRe ) ;
annotateTokens ( tokens , lines ) ;
var aliasToRuleNames = mapAliasToRuleNames ( ruleList ) ;
2020-04-11 13:54:46 -07:00
var _a = getEnabledRulesPerLineNumber ( ruleList , lines , frontMatterLines , noInlineConfig , config , aliasToRuleNames ) , effectiveConfig = _a . effectiveConfig , enabledRulesPerLineNumber = _a . enabledRulesPerLineNumber ;
2019-10-02 20:10:42 -07:00
// Create parameters for rules
var params = {
name : name ,
tokens : tokens ,
lines : lines ,
frontMatterLines : frontMatterLines
} ;
cache . lineMetadata ( helpers . getLineMetadata ( params ) ) ;
cache . flattenedLists ( helpers . flattenLists ( params ) ) ;
// Function to run for each rule
var result = ( resultVersion === 0 ) ? { } : [ ] ;
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2019-10-02 20:10:42 -07:00
function forRule ( rule ) {
// Configure rule
var ruleNameFriendly = rule . names [ 0 ] ;
var ruleName = ruleNameFriendly . toUpperCase ( ) ;
params . config = effectiveConfig [ ruleName ] ;
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2019-10-02 20:10:42 -07:00
function throwError ( property ) {
throw new Error ( "Property '" + property + "' of onError parameter is incorrect." ) ;
}
var errors = [ ] ;
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2019-10-02 20:10:42 -07:00
function onError ( errorInfo ) {
if ( ! errorInfo ||
! helpers . isNumber ( errorInfo . lineNumber ) ||
( errorInfo . lineNumber < 1 ) ||
( errorInfo . lineNumber > lines . length ) ) {
throwError ( "lineNumber" ) ;
}
if ( errorInfo . detail &&
! helpers . isString ( errorInfo . detail ) ) {
throwError ( "detail" ) ;
}
if ( errorInfo . context &&
! helpers . isString ( errorInfo . context ) ) {
throwError ( "context" ) ;
}
if ( errorInfo . range &&
( ! Array . isArray ( errorInfo . range ) ||
( errorInfo . range . length !== 2 ) ||
! helpers . isNumber ( errorInfo . range [ 0 ] ) ||
( errorInfo . range [ 0 ] < 1 ) ||
! helpers . isNumber ( errorInfo . range [ 1 ] ) ||
( errorInfo . range [ 1 ] < 1 ) ||
( ( errorInfo . range [ 0 ] + errorInfo . range [ 1 ] - 1 ) >
lines [ errorInfo . lineNumber - 1 ] . length ) ) ) {
throwError ( "range" ) ;
}
var fixInfo = errorInfo . fixInfo ;
2019-10-19 17:55:10 -07:00
var cleanFixInfo = { } ;
2019-10-02 20:10:42 -07:00
if ( fixInfo ) {
if ( ! helpers . isObject ( fixInfo ) ) {
throwError ( "fixInfo" ) ;
}
2019-10-19 17:55:10 -07:00
if ( fixInfo . lineNumber !== undefined ) {
if ( ( ! helpers . isNumber ( fixInfo . lineNumber ) ||
2019-10-02 20:10:42 -07:00
( fixInfo . lineNumber < 1 ) ||
( fixInfo . lineNumber > lines . length ) ) ) {
2019-10-19 17:55:10 -07:00
throwError ( "fixInfo.lineNumber" ) ;
}
cleanFixInfo . lineNumber =
fixInfo . lineNumber + frontMatterLines . length ;
2019-10-02 20:10:42 -07:00
}
var effectiveLineNumber = fixInfo . lineNumber || errorInfo . lineNumber ;
2019-10-19 17:55:10 -07:00
if ( fixInfo . editColumn !== undefined ) {
if ( ( ! helpers . isNumber ( fixInfo . editColumn ) ||
2019-10-02 20:10:42 -07:00
( fixInfo . editColumn < 1 ) ||
( fixInfo . editColumn >
lines [ effectiveLineNumber - 1 ] . length + 1 ) ) ) {
2019-10-19 17:55:10 -07:00
throwError ( "fixInfo.editColumn" ) ;
}
cleanFixInfo . editColumn = fixInfo . editColumn ;
2019-10-02 20:10:42 -07:00
}
2019-10-19 17:55:10 -07:00
if ( fixInfo . deleteCount !== undefined ) {
if ( ( ! helpers . isNumber ( fixInfo . deleteCount ) ||
2019-10-02 20:10:42 -07:00
( fixInfo . deleteCount < - 1 ) ||
( fixInfo . deleteCount >
lines [ effectiveLineNumber - 1 ] . length ) ) ) {
2019-10-19 17:55:10 -07:00
throwError ( "fixInfo.deleteCount" ) ;
}
cleanFixInfo . deleteCount = fixInfo . deleteCount ;
2019-10-02 20:10:42 -07:00
}
2019-10-19 17:55:10 -07:00
if ( fixInfo . insertText !== undefined ) {
if ( ! helpers . isString ( fixInfo . insertText ) ) {
throwError ( "fixInfo.insertText" ) ;
}
cleanFixInfo . insertText = fixInfo . insertText ;
2019-10-02 20:10:42 -07:00
}
}
errors . push ( {
"lineNumber" : errorInfo . lineNumber + frontMatterLines . length ,
"detail" : errorInfo . detail || null ,
"context" : errorInfo . context || null ,
2020-01-27 19:19:34 -08:00
"range" : errorInfo . range ? _ _spreadArrays ( errorInfo . range ) : null ,
2019-10-19 17:55:10 -07:00
"fixInfo" : fixInfo ? cleanFixInfo : null
2019-10-02 20:10:42 -07:00
} ) ;
}
// Call (possibly external) rule function
if ( handleRuleFailures ) {
try {
rule [ "function" ] ( params , onError ) ;
}
catch ( ex ) {
onError ( {
"lineNumber" : 1 ,
"detail" : "This rule threw an exception: " + ex . message
} ) ;
}
}
else {
rule [ "function" ] ( params , onError ) ;
}
// Record any errors (significant performance benefit from length check)
if ( errors . length ) {
errors . sort ( lineNumberComparison ) ;
var filteredErrors = errors
. filter ( ( resultVersion === 3 ) ?
filterAllValues :
uniqueFilterForSortedErrors )
. filter ( function removeDisabledRules ( error ) {
return enabledRulesPerLineNumber [ error . lineNumber ] [ ruleName ] ;
} )
. map ( function formatResults ( error ) {
if ( resultVersion === 0 ) {
return error . lineNumber ;
}
var errorObject = { } ;
errorObject . lineNumber = error . lineNumber ;
if ( resultVersion === 1 ) {
errorObject . ruleName = ruleNameFriendly ;
errorObject . ruleAlias = rule . names [ 1 ] || rule . names [ 0 ] ;
}
else {
errorObject . ruleNames = rule . names ;
}
errorObject . ruleDescription = rule . description ;
errorObject . ruleInformation =
rule . information ? rule . information . href : null ;
errorObject . errorDetail = error . detail ;
errorObject . errorContext = error . context ;
errorObject . errorRange = error . range ;
if ( resultVersion === 3 ) {
errorObject . fixInfo = error . fixInfo ;
}
return errorObject ;
} ) ;
if ( filteredErrors . length ) {
if ( resultVersion === 0 ) {
result [ ruleNameFriendly ] = filteredErrors ;
}
else {
Array . prototype . push . apply ( result , filteredErrors ) ;
}
}
}
}
// Run all rules
try {
ruleList . forEach ( forRule ) ;
}
catch ( ex ) {
cache . clear ( ) ;
return callback ( ex ) ;
}
cache . clear ( ) ;
return callback ( null , result ) ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Lints a file containing Markdown content .
*
* @ param { Rule [ ] } ruleList List of rules .
* @ param { string } file Path of file to lint .
* @ param { Object } md markdown - it instance .
* @ param { Configuration } config Configuration object .
* @ param { RegExp } frontMatter Regular expression for front matter .
* @ param { boolean } handleRuleFailures Whether to handle exceptions in rules .
* @ param { boolean } noInlineConfig Whether to allow inline configuration .
* @ param { number } resultVersion Version of the LintResults object to return .
* @ param { boolean } synchronous Whether to execute synchronously .
* @ param { Function } callback Callback ( err , result ) function .
* @ returns { void }
* /
2019-10-02 20:10:42 -07:00
function lintFile ( ruleList , file , md , config , frontMatter , handleRuleFailures , noInlineConfig , resultVersion , synchronous , callback ) {
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2019-10-02 20:10:42 -07:00
function lintContentWrapper ( err , content ) {
if ( err ) {
return callback ( err ) ;
}
return lintContent ( ruleList , file , content , md , config , frontMatter , handleRuleFailures , noInlineConfig , resultVersion , callback ) ;
}
// Make a/synchronous call to read file
if ( synchronous ) {
lintContentWrapper ( null , fs . readFileSync ( file , helpers . utf8Encoding ) ) ;
}
else {
fs . readFile ( file , helpers . utf8Encoding , lintContentWrapper ) ;
}
}
2020-01-27 19:19:34 -08:00
/ * *
* Lint files and strings specified in the Options object .
*
* @ param { Options } options Options object .
* @ param { boolean } synchronous Whether to execute synchronously .
* @ param { Function } callback Callback ( err , result ) function .
* @ returns { void }
* /
2019-10-02 20:10:42 -07:00
function lintInput ( options , synchronous , callback ) {
// Normalize inputs
options = options || { } ;
callback = callback || function noop ( ) { } ;
var ruleList = rules . concat ( options . customRules || [ ] ) ;
var ruleErr = validateRuleList ( ruleList ) ;
if ( ruleErr ) {
return callback ( ruleErr ) ;
}
var files = [ ] ;
if ( Array . isArray ( options . files ) ) {
files = options . files . slice ( ) ;
}
else if ( options . files ) {
files = [ String ( options . files ) ] ;
}
var strings = options . strings || { } ;
var stringsKeys = Object . keys ( strings ) ;
var config = options . config || { "default" : true } ;
var frontMatter = ( options . frontMatter === undefined ) ?
helpers . frontMatterRe : options . frontMatter ;
var handleRuleFailures = ! ! options . handleRuleFailures ;
var noInlineConfig = ! ! options . noInlineConfig ;
var resultVersion = ( options . resultVersion === undefined ) ?
2 : options . resultVersion ;
var md = markdownIt ( { "html" : true } ) ;
var markdownItPlugins = options . markdownItPlugins || [ ] ;
markdownItPlugins . forEach ( function forPlugin ( plugin ) {
// @ts-ignore
md . use . apply ( md , plugin ) ;
} ) ;
var results = newResults ( ruleList ) ;
// Helper to lint the next string or file
/* eslint-disable consistent-return */
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2019-10-02 20:10:42 -07:00
function lintNextItem ( ) {
var iterating = true ;
var item = null ;
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2019-10-02 20:10:42 -07:00
function lintNextItemCallback ( err , result ) {
if ( err ) {
iterating = false ;
return callback ( err ) ;
}
results [ item ] = result ;
return iterating || lintNextItem ( ) ;
}
while ( iterating ) {
if ( ( item = stringsKeys . shift ( ) ) ) {
lintContent ( ruleList , item , strings [ item ] || "" , md , config , frontMatter , handleRuleFailures , noInlineConfig , resultVersion , lintNextItemCallback ) ;
}
else if ( ( item = files . shift ( ) ) ) {
iterating = synchronous ;
lintFile ( ruleList , item , md , config , frontMatter , handleRuleFailures , noInlineConfig , resultVersion , synchronous , lintNextItemCallback ) ;
}
else {
return callback ( null , results ) ;
}
}
}
return lintNextItem ( ) ;
}
/ * *
* Lint specified Markdown files .
*
2019-12-14 13:50:48 -08:00
* @ param { Options } options Configuration options .
* @ param { LintCallback } callback Callback ( err , result ) function .
2019-10-02 20:10:42 -07:00
* @ returns { void }
* /
function markdownlint ( options , callback ) {
return lintInput ( options , false , callback ) ;
}
/ * *
* Lint specified Markdown files synchronously .
*
2019-12-14 13:50:48 -08:00
* @ param { Options } options Configuration options .
* @ returns { LintResults } Results object .
2019-10-02 20:10:42 -07:00
* /
function markdownlintSync ( options ) {
var results = null ;
lintInput ( options , true , function callback ( error , res ) {
if ( error ) {
throw error ;
}
results = res ;
} ) ;
return results ;
}
2020-01-27 19:19:34 -08:00
/ * *
* Parse the content of a configuration file .
*
* @ param { string } name Name of the configuration file .
* @ param { string } content Configuration content .
* @ param { ConfigurationParser [ ] } parsers Parsing function ( s ) .
* @ returns { Object } Configuration object and error message .
* /
2019-10-02 20:10:42 -07:00
function parseConfiguration ( name , content , parsers ) {
var config = null ;
var message = "" ;
var errors = [ ] ;
// Try each parser
( parsers || [ JSON . parse ] ) . every ( function ( parser ) {
try {
config = parser ( content ) ;
}
catch ( ex ) {
errors . push ( ex . message ) ;
}
return ! config ;
} ) ;
// Message if unable to parse
if ( ! config ) {
errors . unshift ( "Unable to parse '" + name + "'" ) ;
message = errors . join ( "; " ) ;
}
return {
config : config ,
message : message
} ;
}
/ * *
* Read specified configuration file .
*
2019-12-14 13:50:48 -08:00
* @ param { string } file Configuration file name .
2020-01-27 19:19:34 -08:00
* @ param { ConfigurationParser [ ] | ReadConfigCallback } parsers Parsing
* function ( s ) .
* @ param { ReadConfigCallback } [ callback ] Callback ( err , result ) function .
2019-10-02 20:10:42 -07:00
* @ returns { void }
* /
function readConfig ( file , parsers , callback ) {
if ( ! callback ) {
// @ts-ignore
callback = parsers ;
parsers = null ;
}
// Read file
fs . readFile ( file , helpers . utf8Encoding , function ( err , content ) {
if ( err ) {
return callback ( err ) ;
}
// Try to parse file
2020-01-27 19:19:34 -08:00
// @ts-ignore
2019-10-02 20:10:42 -07:00
var _a = parseConfiguration ( file , content , parsers ) , config = _a . config , message = _a . message ;
if ( ! config ) {
return callback ( new Error ( message ) ) ;
}
// Extend configuration
var configExtends = config [ "extends" ] ;
if ( configExtends ) {
delete config [ "extends" ] ;
var extendsFile = path . resolve ( path . dirname ( file ) , configExtends ) ;
return readConfig ( extendsFile , parsers , function ( errr , extendsConfig ) {
if ( errr ) {
return callback ( errr ) ;
}
2019-10-03 20:53:54 -07:00
return callback ( null , _ _assign ( _ _assign ( { } , extendsConfig ) , config ) ) ;
2019-10-02 20:10:42 -07:00
} ) ;
}
return callback ( null , config ) ;
} ) ;
}
/ * *
* Read specified configuration file synchronously .
*
2019-12-14 13:50:48 -08:00
* @ param { string } file Configuration file name .
* @ param { ConfigurationParser [ ] } [ parsers ] Parsing function ( s ) .
* @ returns { Configuration } Configuration object .
2019-10-02 20:10:42 -07:00
* /
function readConfigSync ( file , parsers ) {
// Read file
var content = fs . readFileSync ( file , helpers . utf8Encoding ) ;
// Try to parse file
var _a = parseConfiguration ( file , content , parsers ) , config = _a . config , message = _a . message ;
if ( ! config ) {
throw new Error ( message ) ;
}
// Extend configuration
var configExtends = config [ "extends" ] ;
if ( configExtends ) {
delete config [ "extends" ] ;
2019-10-03 20:53:54 -07:00
return _ _assign ( _ _assign ( { } , readConfigSync ( path . resolve ( path . dirname ( file ) , configExtends ) , parsers ) ) , config ) ;
2019-10-02 20:10:42 -07:00
}
return config ;
}
// Export a/synchronous APIs
markdownlint . sync = markdownlintSync ;
markdownlint . readConfig = readConfig ;
markdownlint . readConfigSync = readConfigSync ;
module . exports = markdownlint ;
2019-12-14 13:50:48 -08:00
} , { "../helpers" : 2 , "./cache" : 3 , "./rules" : 49 , "fs" : 51 , "markdown-it" : 1 , "path" : 53 , "url" : 59 } ] , 5 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , filterTokens = _a . filterTokens ;
module . exports = {
"names" : [ "MD001" , "heading-increment" , "header-increment" ] ,
"description" : "Heading levels should only increment by one level at a time" ,
"tags" : [ "headings" , "headers" ] ,
"function" : function MD001 ( params , onError ) {
var prevLevel = 0 ;
filterTokens ( params , "heading_open" , function forToken ( token ) {
var level = parseInt ( token . tag . slice ( 1 ) , 10 ) ;
if ( prevLevel && ( level > prevLevel ) ) {
addErrorDetailIf ( onError , token . lineNumber , "h" + ( prevLevel + 1 ) , "h" + level ) ;
}
prevLevel = level ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 6 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var addErrorDetailIf = require ( "../helpers" ) . addErrorDetailIf ;
module . exports = {
"names" : [ "MD002" , "first-heading-h1" , "first-header-h1" ] ,
"description" : "First heading should be a top level heading" ,
"tags" : [ "headings" , "headers" ] ,
"function" : function MD002 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var level = Number ( params . config . level || 1 ) ;
2019-10-02 20:10:42 -07:00
var tag = "h" + level ;
params . tokens . every ( function forToken ( token ) {
if ( token . type === "heading_open" ) {
addErrorDetailIf ( onError , token . lineNumber , tag , token . tag ) ;
return false ;
}
return true ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 7 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , filterTokens = _a . filterTokens , headingStyleFor = _a . headingStyleFor ;
module . exports = {
"names" : [ "MD003" , "heading-style" , "header-style" ] ,
"description" : "Heading style" ,
"tags" : [ "headings" , "headers" ] ,
"function" : function MD003 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var style = String ( params . config . style || "consistent" ) ;
2019-10-02 20:10:42 -07:00
filterTokens ( params , "heading_open" , function forToken ( token ) {
var styleForToken = headingStyleFor ( token ) ;
if ( style === "consistent" ) {
style = styleForToken ;
}
if ( styleForToken !== style ) {
var h12 = /h[12]/ . test ( token . tag ) ;
var setextWithAtx = ( style === "setext_with_atx" ) &&
( ( h12 && ( styleForToken === "setext" ) ) ||
( ! h12 && ( styleForToken === "atx" ) ) ) ;
var setextWithAtxClosed = ( style === "setext_with_atx_closed" ) &&
( ( h12 && ( styleForToken === "setext" ) ) ||
( ! h12 && ( styleForToken === "atx_closed" ) ) ) ;
if ( ! setextWithAtx && ! setextWithAtxClosed ) {
var expected = style ;
if ( style === "setext_with_atx" ) {
expected = h12 ? "setext" : "atx" ;
}
else if ( style === "setext_with_atx_closed" ) {
expected = h12 ? "setext" : "atx_closed" ;
}
addErrorDetailIf ( onError , token . lineNumber , expected , styleForToken ) ;
}
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 8 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
2020-01-27 19:19:34 -08:00
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , listItemMarkerRe = _a . listItemMarkerRe , rangeFromRegExp = _a . rangeFromRegExp , unorderedListStyleFor = _a . unorderedListStyleFor ;
2019-10-02 20:10:42 -07:00
var flattenedLists = require ( "./cache" ) . flattenedLists ;
module . exports = {
"names" : [ "MD004" , "ul-style" ] ,
"description" : "Unordered list style" ,
"tags" : [ "bullet" , "ul" ] ,
"function" : function MD004 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var style = String ( params . config . style || "consistent" ) ;
2019-10-02 20:10:42 -07:00
var expectedStyle = style ;
var nestingStyles = [ ] ;
flattenedLists ( ) . forEach ( function ( list ) {
if ( list . unordered ) {
if ( expectedStyle === "consistent" ) {
expectedStyle = unorderedListStyleFor ( list . items [ 0 ] ) ;
}
list . items . forEach ( function ( item ) {
var itemStyle = unorderedListStyleFor ( item ) ;
if ( style === "sublist" ) {
var nesting = list . nesting ;
if ( ! nestingStyles [ nesting ] &&
( itemStyle !== nestingStyles [ nesting - 1 ] ) ) {
nestingStyles [ nesting ] = itemStyle ;
}
else {
addErrorDetailIf ( onError , item . lineNumber , nestingStyles [ nesting ] , itemStyle , null , null , rangeFromRegExp ( item . line , listItemMarkerRe ) ) ;
}
}
else {
addErrorDetailIf ( onError , item . lineNumber , expectedStyle , itemStyle , null , null , rangeFromRegExp ( item . line , listItemMarkerRe ) ) ;
}
} ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 9 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addError = _a . addError , addErrorDetailIf = _a . addErrorDetailIf , indentFor = _a . indentFor , listItemMarkerRe = _a . listItemMarkerRe , orderedListItemMarkerRe = _a . orderedListItemMarkerRe , rangeFromRegExp = _a . rangeFromRegExp ;
var flattenedLists = require ( "./cache" ) . flattenedLists ;
module . exports = {
"names" : [ "MD005" , "list-indent" ] ,
"description" : "Inconsistent indentation for list items at the same level" ,
"tags" : [ "bullet" , "ul" , "indentation" ] ,
"function" : function MD005 ( params , onError ) {
flattenedLists ( ) . forEach ( function ( list ) {
var expectedIndent = list . indent ;
var expectedEnd = 0 ;
var actualEnd = - 1 ;
var endMatching = false ;
list . items . forEach ( function ( item ) {
2020-01-27 19:19:34 -08:00
var line = item . line , lineNumber = item . lineNumber ;
2019-10-02 20:10:42 -07:00
var actualIndent = indentFor ( item ) ;
2020-04-11 13:54:46 -07:00
var match = null ;
2019-10-02 20:10:42 -07:00
if ( list . unordered ) {
2020-01-27 19:19:34 -08:00
addErrorDetailIf ( onError , lineNumber , expectedIndent , actualIndent , null , null , rangeFromRegExp ( line , listItemMarkerRe )
// No fixInfo; MD007 handles this scenario better
) ;
2019-10-02 20:10:42 -07:00
}
2020-04-11 13:54:46 -07:00
else if ( ( match = orderedListItemMarkerRe . exec ( line ) ) ) {
2020-01-27 19:19:34 -08:00
actualEnd = match [ 0 ] . length ;
2019-10-02 20:10:42 -07:00
expectedEnd = expectedEnd || actualEnd ;
2020-01-27 19:19:34 -08:00
var markerLength = match [ 1 ] . length + 1 ;
2019-10-02 20:10:42 -07:00
if ( ( expectedIndent !== actualIndent ) || endMatching ) {
if ( expectedEnd === actualEnd ) {
endMatching = true ;
}
else {
var detail = endMatching ?
"Expected: (" + expectedEnd + "); Actual: (" + actualEnd + ")" :
"Expected: " + expectedIndent + "; Actual: " + actualIndent ;
2020-01-27 19:19:34 -08:00
var expected = endMatching ?
expectedEnd - markerLength :
expectedIndent ;
var actual = endMatching ?
actualEnd - markerLength :
actualIndent ;
addError ( onError , lineNumber , detail , null , rangeFromRegExp ( line , listItemMarkerRe ) , {
"editColumn" : Math . min ( actual , expected ) + 1 ,
"deleteCount" : Math . max ( actual - expected , 0 ) ,
"insertText" : "" . padEnd ( Math . max ( expected - actual , 0 ) )
} ) ;
2019-10-02 20:10:42 -07:00
}
}
}
} ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 10 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , listItemMarkerRe = _a . listItemMarkerRe , rangeFromRegExp = _a . rangeFromRegExp ;
var flattenedLists = require ( "./cache" ) . flattenedLists ;
module . exports = {
"names" : [ "MD006" , "ul-start-left" ] ,
"description" : "Consider starting bulleted lists at the beginning of the line" ,
"tags" : [ "bullet" , "ul" , "indentation" ] ,
"function" : function MD006 ( params , onError ) {
flattenedLists ( ) . forEach ( function ( list ) {
if ( list . unordered && ! list . nesting && ( list . indent !== 0 ) ) {
2019-12-14 13:50:48 -08:00
list . items . forEach ( function ( item ) {
var lineNumber = item . lineNumber , line = item . line ;
addErrorDetailIf ( onError , lineNumber , 0 , list . indent , null , null , rangeFromRegExp ( line , listItemMarkerRe ) , {
"deleteCount" : line . length - line . trimLeft ( ) . length
} ) ;
2019-10-02 20:10:42 -07:00
} ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 11 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
2019-12-14 13:50:48 -08:00
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , indentFor = _a . indentFor , listItemMarkerRe = _a . listItemMarkerRe ;
2019-10-02 20:10:42 -07:00
var flattenedLists = require ( "./cache" ) . flattenedLists ;
module . exports = {
"names" : [ "MD007" , "ul-indent" ] ,
"description" : "Unordered list indentation" ,
"tags" : [ "bullet" , "ul" , "indentation" ] ,
"function" : function MD007 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var indent = Number ( params . config . indent || 2 ) ;
var startIndented = ! ! params . config . start _indented ;
2019-10-02 20:10:42 -07:00
flattenedLists ( ) . forEach ( function ( list ) {
2019-12-14 13:50:48 -08:00
if ( list . unordered && list . parentsUnordered ) {
list . items . forEach ( function ( item ) {
var lineNumber = item . lineNumber , line = item . line ;
2020-01-27 19:19:34 -08:00
var expectedNesting = list . nesting + ( startIndented ? 1 : 0 ) ;
var expectedIndent = expectedNesting * indent ;
2019-12-14 13:50:48 -08:00
var actualIndent = indentFor ( item ) ;
var range = null ;
var editColumn = 1 ;
var match = line . match ( listItemMarkerRe ) ;
if ( match ) {
range = [ 1 , match [ 0 ] . length ] ;
editColumn += match [ 1 ] . length - actualIndent ;
}
addErrorDetailIf ( onError , lineNumber , expectedIndent , actualIndent , null , null , range , {
editColumn : editColumn ,
"deleteCount" : actualIndent ,
"insertText" : "" . padEnd ( expectedIndent )
} ) ;
} ) ;
2019-10-02 20:10:42 -07:00
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 12 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
2020-01-27 19:19:34 -08:00
var _a = require ( "../helpers" ) , addError = _a . addError , filterTokens = _a . filterTokens , forEachInlineCodeSpan = _a . forEachInlineCodeSpan , forEachLine = _a . forEachLine , includesSorted = _a . includesSorted , newLineRe = _a . newLineRe , numericSortAscending = _a . numericSortAscending ;
2019-10-02 20:10:42 -07:00
var lineMetadata = require ( "./cache" ) . lineMetadata ;
module . exports = {
"names" : [ "MD009" , "no-trailing-spaces" ] ,
"description" : "Trailing spaces" ,
"tags" : [ "whitespace" ] ,
"function" : function MD009 ( params , onError ) {
var brSpaces = params . config . br _spaces ;
2020-01-27 19:19:34 -08:00
brSpaces = Number ( ( brSpaces === undefined ) ? 2 : brSpaces ) ;
2019-12-14 13:50:48 -08:00
var listItemEmptyLines = ! ! params . config . list _item _empty _lines ;
var strict = ! ! params . config . strict ;
2019-10-02 20:10:42 -07:00
var listItemLineNumbers = [ ] ;
2019-12-14 13:50:48 -08:00
if ( listItemEmptyLines ) {
2019-10-02 20:10:42 -07:00
filterTokens ( params , "list_item_open" , function ( token ) {
for ( var i = token . map [ 0 ] ; i < token . map [ 1 ] ; i ++ ) {
listItemLineNumbers . push ( i + 1 ) ;
}
} ) ;
2019-12-14 13:50:48 -08:00
listItemLineNumbers . sort ( numericSortAscending ) ;
}
var paragraphLineNumbers = [ ] ;
var codeInlineLineNumbers = [ ] ;
if ( strict ) {
filterTokens ( params , "paragraph_open" , function ( token ) {
for ( var i = token . map [ 0 ] ; i < token . map [ 1 ] - 1 ; i ++ ) {
paragraphLineNumbers . push ( i + 1 ) ;
}
} ) ;
paragraphLineNumbers . sort ( numericSortAscending ) ;
filterTokens ( params , "inline" , function ( token ) {
if ( token . children . some ( function ( child ) { return child . type === "code_inline" ; } ) ) {
var tokenLines = params . lines . slice ( token . map [ 0 ] , token . map [ 1 ] ) ;
forEachInlineCodeSpan ( tokenLines . join ( "\n" ) , function ( code , lineIndex ) {
var codeLineCount = code . split ( newLineRe ) . length ;
for ( var i = 0 ; i < codeLineCount ; i ++ ) {
codeInlineLineNumbers . push ( token . lineNumber + lineIndex + i ) ;
}
} ) ;
}
} ) ;
codeInlineLineNumbers . sort ( numericSortAscending ) ;
2019-10-02 20:10:42 -07:00
}
var expected = ( brSpaces < 2 ) ? 0 : brSpaces ;
var inFencedCode = 0 ;
forEachLine ( lineMetadata ( ) , function ( line , lineIndex , inCode , onFence ) {
inFencedCode += onFence ;
var lineNumber = lineIndex + 1 ;
var trailingSpaces = line . length - line . trimRight ( ) . length ;
if ( ( ! inCode || inFencedCode ) && trailingSpaces &&
! includesSorted ( listItemLineNumbers , lineNumber ) ) {
2019-12-14 13:50:48 -08:00
if ( ( expected !== trailingSpaces ) ||
( strict &&
( ! includesSorted ( paragraphLineNumbers , lineNumber ) ||
includesSorted ( codeInlineLineNumbers , lineNumber ) ) ) ) {
2019-10-02 20:10:42 -07:00
var column = line . length - trailingSpaces + 1 ;
addError ( onError , lineNumber , "Expected: " + ( expected === 0 ? "" : "0 or " ) +
expected + "; Actual: " + trailingSpaces , null , [ column , trailingSpaces ] , {
"editColumn" : column ,
"deleteCount" : trailingSpaces
} ) ;
}
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 13 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addError = _a . addError , forEachLine = _a . forEachLine ;
var lineMetadata = require ( "./cache" ) . lineMetadata ;
var tabRe = /\t+/g ;
module . exports = {
"names" : [ "MD010" , "no-hard-tabs" ] ,
"description" : "Hard tabs" ,
"tags" : [ "whitespace" , "hard_tab" ] ,
"function" : function MD010 ( params , onError ) {
var codeBlocks = params . config . code _blocks ;
var includeCodeBlocks = ( codeBlocks === undefined ) ? true : ! ! codeBlocks ;
forEachLine ( lineMetadata ( ) , function ( line , lineIndex , inCode ) {
if ( ! inCode || includeCodeBlocks ) {
var match = null ;
while ( ( match = tabRe . exec ( line ) ) !== null ) {
var column = match . index + 1 ;
var length _1 = match [ 0 ] . length ;
addError ( onError , lineIndex + 1 , "Column: " + column , null , [ column , length _1 ] , {
"editColumn" : column ,
"deleteCount" : length _1 ,
"insertText" : "" . padEnd ( length _1 )
} ) ;
}
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 14 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addError = _a . addError , forEachInlineChild = _a . forEachInlineChild , unescapeMarkdown = _a . unescapeMarkdown ;
var reversedLinkRe = /\(([^)]+)\)\[([^\]^][^\]]*)]/g ;
module . exports = {
"names" : [ "MD011" , "no-reversed-links" ] ,
"description" : "Reversed link syntax" ,
"tags" : [ "links" ] ,
"function" : function MD011 ( params , onError ) {
forEachInlineChild ( params , "text" , function ( token ) {
var lineNumber = token . lineNumber , content = token . content ;
var match = null ;
while ( ( match = reversedLinkRe . exec ( content ) ) !== null ) {
var reversedLink = match [ 0 ] , linkText = match [ 1 ] , linkDestination = match [ 2 ] ;
var line = params . lines [ lineNumber - 1 ] ;
var column = unescapeMarkdown ( line ) . indexOf ( reversedLink ) + 1 ;
var length _1 = reversedLink . length ;
addError ( onError , lineNumber , reversedLink , null , [ column , length _1 ] , {
"editColumn" : column ,
"deleteCount" : length _1 ,
"insertText" : "[" + linkText + "](" + linkDestination + ")"
} ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 15 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , forEachLine = _a . forEachLine ;
var lineMetadata = require ( "./cache" ) . lineMetadata ;
module . exports = {
"names" : [ "MD012" , "no-multiple-blanks" ] ,
"description" : "Multiple consecutive blank lines" ,
"tags" : [ "whitespace" , "blank_lines" ] ,
"function" : function MD012 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var maximum = Number ( params . config . maximum || 1 ) ;
2019-10-02 20:10:42 -07:00
var count = 0 ;
forEachLine ( lineMetadata ( ) , function ( line , lineIndex , inCode ) {
count = ( inCode || line . trim ( ) . length ) ? 0 : count + 1 ;
if ( maximum < count ) {
addErrorDetailIf ( onError , lineIndex + 1 , maximum , count , null , null , null , {
"deleteCount" : - 1
} ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 16 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
2019-12-14 13:50:48 -08:00
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , filterTokens = _a . filterTokens , forEachHeading = _a . forEachHeading , forEachLine = _a . forEachLine , includesSorted = _a . includesSorted ;
2019-10-02 20:10:42 -07:00
var lineMetadata = require ( "./cache" ) . lineMetadata ;
2019-12-14 13:50:48 -08:00
var longLineRePrefix = "^.{" ;
var longLineRePostfixRelaxed = "}.*\\s.*$" ;
var longLineRePostfixStrict = "}.+$" ;
2019-10-02 20:10:42 -07:00
var labelRe = /^\s*\[.*[^\\]]:/ ;
2020-01-27 19:19:34 -08:00
var linkOrImageOnlyLineRe = /^[es]*(lT?L|I)[ES]*$/ ;
2020-04-11 13:54:46 -07:00
var sternModeRe = /^([#>\s]*\s)?\S*$/ ;
2019-10-02 20:10:42 -07:00
var tokenTypeMap = {
"em_open" : "e" ,
"em_close" : "E" ,
2020-01-27 19:19:34 -08:00
"image" : "I" ,
2019-10-02 20:10:42 -07:00
"link_open" : "l" ,
"link_close" : "L" ,
"strong_open" : "s" ,
"strong_close" : "S" ,
"text" : "T"
} ;
module . exports = {
"names" : [ "MD013" , "line-length" ] ,
"description" : "Line length" ,
"tags" : [ "line_length" ] ,
"function" : function MD013 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var lineLength = Number ( params . config . line _length || 80 ) ;
var headingLineLength = Number ( params . config . heading _line _length || lineLength ) ;
var codeLineLength = Number ( params . config . code _block _line _length || lineLength ) ;
2019-12-14 13:50:48 -08:00
var strict = ! ! params . config . strict ;
2020-04-11 13:54:46 -07:00
var stern = ! ! params . config . stern ;
var longLineRePostfix = ( strict || stern ) ? longLineRePostfixStrict : longLineRePostfixRelaxed ;
2019-10-02 20:10:42 -07:00
var longLineRe = new RegExp ( longLineRePrefix + lineLength + longLineRePostfix ) ;
var longHeadingLineRe = new RegExp ( longLineRePrefix + headingLineLength + longLineRePostfix ) ;
var longCodeLineRe = new RegExp ( longLineRePrefix + codeLineLength + longLineRePostfix ) ;
var codeBlocks = params . config . code _blocks ;
var includeCodeBlocks = ( codeBlocks === undefined ) ? true : ! ! codeBlocks ;
var tables = params . config . tables ;
var includeTables = ( tables === undefined ) ? true : ! ! tables ;
var headings = params . config . headings ;
if ( headings === undefined ) {
headings = params . config . headers ;
}
var includeHeadings = ( headings === undefined ) ? true : ! ! headings ;
var headingLineNumbers = [ ] ;
forEachHeading ( params , function ( heading ) {
headingLineNumbers . push ( heading . lineNumber ) ;
} ) ;
var linkOnlyLineNumbers = [ ] ;
filterTokens ( params , "inline" , function ( token ) {
var childTokenTypes = "" ;
token . children . forEach ( function ( child ) {
if ( child . type !== "text" || child . content !== "" ) {
childTokenTypes += tokenTypeMap [ child . type ] || "x" ;
}
} ) ;
2020-01-27 19:19:34 -08:00
if ( linkOrImageOnlyLineRe . test ( childTokenTypes ) ) {
2019-10-02 20:10:42 -07:00
linkOnlyLineNumbers . push ( token . lineNumber ) ;
}
} ) ;
forEachLine ( lineMetadata ( ) , function ( line , lineIndex , inCode , onFence , inTable ) {
var lineNumber = lineIndex + 1 ;
var isHeading = includesSorted ( headingLineNumbers , lineNumber ) ;
var length = inCode ?
codeLineLength :
( isHeading ? headingLineLength : lineLength ) ;
var lengthRe = inCode ?
longCodeLineRe :
( isHeading ? longHeadingLineRe : longLineRe ) ;
if ( ( includeCodeBlocks || ! inCode ) &&
( includeTables || ! inTable ) &&
( includeHeadings || ! isHeading ) &&
2019-12-14 13:50:48 -08:00
( strict ||
2020-04-11 13:54:46 -07:00
( ! ( stern && sternModeRe . test ( line ) ) &&
! includesSorted ( linkOnlyLineNumbers , lineNumber ) &&
2019-12-14 13:50:48 -08:00
! labelRe . test ( line ) ) ) &&
lengthRe . test ( line ) ) {
addErrorDetailIf ( onError , lineNumber , length , line . length , null , null , [ length + 1 , line . length - length ] ) ;
2019-10-02 20:10:42 -07:00
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 17 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , filterTokens = _a . filterTokens ;
var dollarCommandRe = /^(\s*)(\$\s+)/ ;
module . exports = {
"names" : [ "MD014" , "commands-show-output" ] ,
"description" : "Dollar signs used before commands without showing output" ,
"tags" : [ "code" ] ,
"function" : function MD014 ( params , onError ) {
[ "code_block" , "fence" ] . forEach ( function ( type ) {
filterTokens ( params , type , function ( token ) {
var margin = ( token . type === "fence" ) ? 1 : 0 ;
2020-01-27 19:19:34 -08:00
var dollarInstances = [ ] ;
var allDollars = true ;
2019-10-02 20:10:42 -07:00
for ( var i = token . map [ 0 ] + margin ; i < token . map [ 1 ] - margin ; i ++ ) {
var line = params . lines [ i ] ;
var lineTrim = line . trim ( ) ;
2020-01-27 19:19:34 -08:00
if ( lineTrim ) {
var match = dollarCommandRe . exec ( line ) ;
if ( match ) {
var column = match [ 1 ] . length + 1 ;
var length _1 = match [ 2 ] . length ;
dollarInstances . push ( [ i , lineTrim , column , length _1 ] ) ;
}
else {
allDollars = false ;
}
2019-10-02 20:10:42 -07:00
}
2020-01-27 19:19:34 -08:00
}
if ( allDollars ) {
dollarInstances . forEach ( function ( instance ) {
var i = instance [ 0 ] , lineTrim = instance [ 1 ] , column = instance [ 2 ] , length = instance [ 3 ] ;
addErrorContext ( onError , i + 1 , lineTrim , null , null , [ column , length ] , {
"editColumn" : column ,
"deleteCount" : length
} ) ;
} ) ;
}
2019-10-02 20:10:42 -07:00
} ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 18 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , forEachLine = _a . forEachLine ;
var lineMetadata = require ( "./cache" ) . lineMetadata ;
module . exports = {
"names" : [ "MD018" , "no-missing-space-atx" ] ,
"description" : "No space after hash on atx style heading" ,
"tags" : [ "headings" , "headers" , "atx" , "spaces" ] ,
"function" : function MD018 ( params , onError ) {
forEachLine ( lineMetadata ( ) , function ( line , lineIndex , inCode ) {
2020-04-11 13:54:46 -07:00
if ( ! inCode &&
/^#+[^#\s]/ . test ( line ) &&
! /#\s*$/ . test ( line ) &&
! line . startsWith ( "#️⃣" ) ) {
2019-10-02 20:10:42 -07:00
var hashCount = /^#+/ . exec ( line ) [ 0 ] . length ;
addErrorContext ( onError , lineIndex + 1 , line . trim ( ) , null , null , [ 1 , hashCount + 1 ] , {
"editColumn" : hashCount + 1 ,
"insertText" : " "
} ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 19 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , filterTokens = _a . filterTokens , headingStyleFor = _a . headingStyleFor ;
module . exports = {
"names" : [ "MD019" , "no-multiple-space-atx" ] ,
"description" : "Multiple spaces after hash on atx style heading" ,
"tags" : [ "headings" , "headers" , "atx" , "spaces" ] ,
"function" : function MD019 ( params , onError ) {
filterTokens ( params , "heading_open" , function ( token ) {
if ( headingStyleFor ( token ) === "atx" ) {
var line = token . line , lineNumber = token . lineNumber ;
var match = /^(#+)(\s{2,})(?:\S)/ . exec ( line ) ;
if ( match ) {
var hashLength = match [ 1 ] [ "length" ] , spacesLength = match [ 2 ] [ "length" ] ;
addErrorContext ( onError , lineNumber , line . trim ( ) , null , null , [ 1 , hashLength + spacesLength + 1 ] , {
"editColumn" : hashLength + 1 ,
"deleteCount" : spacesLength - 1
} ) ;
}
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 20 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , forEachLine = _a . forEachLine ;
var lineMetadata = require ( "./cache" ) . lineMetadata ;
module . exports = {
"names" : [ "MD020" , "no-missing-space-closed-atx" ] ,
"description" : "No space inside hashes on closed atx style heading" ,
"tags" : [ "headings" , "headers" , "atx_closed" , "spaces" ] ,
"function" : function MD020 ( params , onError ) {
forEachLine ( lineMetadata ( ) , function ( line , lineIndex , inCode ) {
if ( ! inCode ) {
2019-10-24 20:23:22 -07:00
var match = /^(#+)(\s*)([^#]*?[^#\\])(\s*)((?:\\#)?)(#+)(\s*)$/ . exec ( line ) ;
2019-10-02 20:10:42 -07:00
if ( match ) {
var leftHash = match [ 1 ] , leftSpaceLength = match [ 2 ] [ "length" ] , content = match [ 3 ] , rightSpaceLength = match [ 4 ] [ "length" ] , rightEscape = match [ 5 ] , rightHash = match [ 6 ] , trailSpaceLength = match [ 7 ] [ "length" ] ;
var leftHashLength = leftHash . length ;
var rightHashLength = rightHash . length ;
var left = ! leftSpaceLength ;
var right = ! rightSpaceLength || rightEscape ;
var rightEscapeReplacement = rightEscape ? rightEscape + " " : "" ;
if ( left || right ) {
var range = left ?
[
1 ,
leftHashLength + 1
] :
[
line . length - trailSpaceLength - rightHashLength ,
rightHashLength + 1
] ;
addErrorContext ( onError , lineIndex + 1 , line . trim ( ) , left , right , range , {
"editColumn" : 1 ,
"deleteCount" : line . length ,
"insertText" : leftHash + " " + content + " " + rightEscapeReplacement + rightHash
} ) ;
}
}
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 21 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , filterTokens = _a . filterTokens , headingStyleFor = _a . headingStyleFor ;
module . exports = {
"names" : [ "MD021" , "no-multiple-space-closed-atx" ] ,
"description" : "Multiple spaces inside hashes on closed atx style heading" ,
"tags" : [ "headings" , "headers" , "atx_closed" , "spaces" ] ,
"function" : function MD021 ( params , onError ) {
filterTokens ( params , "heading_open" , function ( token ) {
if ( headingStyleFor ( token ) === "atx_closed" ) {
var line = token . line , lineNumber = token . lineNumber ;
var match = /^(#+)(\s+)([^#]+?)(\s+)(#+)(\s*)$/ . exec ( line ) ;
if ( match ) {
var leftHash = match [ 1 ] , leftSpaceLength = match [ 2 ] [ "length" ] , content = match [ 3 ] , rightSpaceLength = match [ 4 ] [ "length" ] , rightHash = match [ 5 ] , trailSpaceLength = match [ 6 ] [ "length" ] ;
var left = leftSpaceLength > 1 ;
var right = rightSpaceLength > 1 ;
if ( left || right ) {
var length _1 = line . length ;
var leftHashLength = leftHash . length ;
var rightHashLength = rightHash . length ;
var range = left ?
[
1 ,
leftHashLength + leftSpaceLength + 1
] :
[
length _1 - trailSpaceLength - rightHashLength - rightSpaceLength ,
rightSpaceLength + rightHashLength + 1
] ;
addErrorContext ( onError , lineNumber , line . trim ( ) , left , right , range , {
"editColumn" : 1 ,
"deleteCount" : length _1 ,
"insertText" : leftHash + " " + content + " " + rightHash
} ) ;
}
}
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 22 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , filterTokens = _a . filterTokens , isBlankLine = _a . isBlankLine ;
module . exports = {
"names" : [ "MD022" , "blanks-around-headings" , "blanks-around-headers" ] ,
"description" : "Headings should be surrounded by blank lines" ,
"tags" : [ "headings" , "headers" , "blank_lines" ] ,
"function" : function MD022 ( params , onError ) {
var linesAbove = params . config . lines _above ;
2020-01-27 19:19:34 -08:00
linesAbove = Number ( ( linesAbove === undefined ) ? 1 : linesAbove ) ;
2019-10-02 20:10:42 -07:00
var linesBelow = params . config . lines _below ;
2020-01-27 19:19:34 -08:00
linesBelow = Number ( ( linesBelow === undefined ) ? 1 : linesBelow ) ;
2019-10-02 20:10:42 -07:00
var lines = params . lines ;
filterTokens ( params , "heading_open" , function ( token ) {
var _a = token . map , topIndex = _a [ 0 ] , nextIndex = _a [ 1 ] ;
var actualAbove = 0 ;
for ( var i = 0 ; i < linesAbove ; i ++ ) {
if ( isBlankLine ( lines [ topIndex - i - 1 ] ) ) {
actualAbove ++ ;
}
}
addErrorDetailIf ( onError , topIndex + 1 , linesAbove , actualAbove , "Above" , lines [ topIndex ] . trim ( ) , null , {
"insertText" : "" . padEnd ( linesAbove - actualAbove , "\n" )
} ) ;
var actualBelow = 0 ;
for ( var i = 0 ; i < linesBelow ; i ++ ) {
if ( isBlankLine ( lines [ nextIndex + i ] ) ) {
actualBelow ++ ;
}
}
addErrorDetailIf ( onError , topIndex + 1 , linesBelow , actualBelow , "Below" , lines [ topIndex ] . trim ( ) , null , {
"lineNumber" : nextIndex + 1 ,
"insertText" : "" . padEnd ( linesBelow - actualBelow , "\n" )
} ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 23 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , filterTokens = _a . filterTokens ;
var spaceBeforeHeadingRe = /^((?:\s+)|(?:[>\s]+\s\s))[^>\s]/ ;
module . exports = {
"names" : [ "MD023" , "heading-start-left" , "header-start-left" ] ,
"description" : "Headings must start at the beginning of the line" ,
"tags" : [ "headings" , "headers" , "spaces" ] ,
"function" : function MD023 ( params , onError ) {
filterTokens ( params , "heading_open" , function forToken ( token ) {
var lineNumber = token . lineNumber , line = token . line ;
var match = line . match ( spaceBeforeHeadingRe ) ;
if ( match ) {
var prefixAndFirstChar = match [ 0 ] , prefix = match [ 1 ] ;
var deleteCount = prefix . length ;
var prefixLengthNoSpace = prefix . trimRight ( ) . length ;
if ( prefixLengthNoSpace ) {
deleteCount -= prefixLengthNoSpace - 1 ;
}
addErrorContext ( onError , lineNumber , line , null , null , [ 1 , prefixAndFirstChar . length ] , {
"editColumn" : prefixLengthNoSpace + 1 ,
"deleteCount" : deleteCount
} ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 24 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , forEachHeading = _a . forEachHeading ;
module . exports = {
"names" : [ "MD024" , "no-duplicate-heading" , "no-duplicate-header" ] ,
"description" : "Multiple headings with the same content" ,
"tags" : [ "headings" , "headers" ] ,
"function" : function MD024 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var siblingsOnly = ! ! params . config . siblings _only ||
! ! params . config . allow _different _nesting || false ;
2019-10-02 20:10:42 -07:00
var knownContents = [ null , [ ] ] ;
var lastLevel = 1 ;
var knownContent = knownContents [ lastLevel ] ;
forEachHeading ( params , function ( heading , content ) {
if ( siblingsOnly ) {
var newLevel = heading . tag . slice ( 1 ) ;
while ( lastLevel < newLevel ) {
lastLevel ++ ;
knownContents [ lastLevel ] = [ ] ;
}
while ( lastLevel > newLevel ) {
knownContents [ lastLevel ] = [ ] ;
lastLevel -- ;
}
knownContent = knownContents [ newLevel ] ;
}
if ( knownContent . includes ( content ) ) {
addErrorContext ( onError , heading . lineNumber , heading . line . trim ( ) ) ;
}
else {
knownContent . push ( content ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 25 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , filterTokens = _a . filterTokens , frontMatterHasTitle = _a . frontMatterHasTitle ;
module . exports = {
"names" : [ "MD025" , "single-title" , "single-h1" ] ,
"description" : "Multiple top level headings in the same document" ,
"tags" : [ "headings" , "headers" ] ,
"function" : function MD025 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var level = Number ( params . config . level || 1 ) ;
2019-10-02 20:10:42 -07:00
var tag = "h" + level ;
var foundFrontMatterTitle = frontMatterHasTitle ( params . frontMatterLines , params . config . front _matter _title ) ;
var hasTopLevelHeading = false ;
filterTokens ( params , "heading_open" , function forToken ( token ) {
if ( token . tag === tag ) {
if ( hasTopLevelHeading || foundFrontMatterTitle ) {
addErrorContext ( onError , token . lineNumber , token . line . trim ( ) ) ;
}
else if ( token . lineNumber === 1 ) {
hasTopLevelHeading = true ;
}
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 26 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addError = _a . addError , allPunctuation = _a . allPunctuation , escapeForRegExp = _a . escapeForRegExp , forEachHeading = _a . forEachHeading ;
module . exports = {
"names" : [ "MD026" , "no-trailing-punctuation" ] ,
"description" : "Trailing punctuation in heading" ,
"tags" : [ "headings" , "headers" ] ,
"function" : function MD026 ( params , onError ) {
var punctuation = params . config . punctuation ;
2020-01-27 19:19:34 -08:00
punctuation =
String ( ( punctuation === undefined ) ? allPunctuation : punctuation ) ;
2019-10-02 20:10:42 -07:00
var trailingPunctuationRe = new RegExp ( "\\s*[" + escapeForRegExp ( punctuation ) + "]+$" ) ;
forEachHeading ( params , function ( heading ) {
var line = heading . line , lineNumber = heading . lineNumber ;
var trimmedLine = line . replace ( /[\s#]*$/ , "" ) ;
var match = trailingPunctuationRe . exec ( trimmedLine ) ;
if ( match ) {
var fullMatch = match [ 0 ] ;
var column = match . index + 1 ;
var length _1 = fullMatch . length ;
addError ( onError , lineNumber , "Punctuation: '" + fullMatch + "'" , null , [ column , length _1 ] , {
"editColumn" : column ,
"deleteCount" : length _1
} ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 27 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , newLineRe = _a . newLineRe ;
var spaceAfterBlockQuoteRe = /^((?:\s*>)+)(\s{2,})\S/ ;
module . exports = {
"names" : [ "MD027" , "no-multiple-space-blockquote" ] ,
"description" : "Multiple spaces after blockquote symbol" ,
"tags" : [ "blockquote" , "whitespace" , "indentation" ] ,
"function" : function MD027 ( params , onError ) {
var blockquoteNesting = 0 ;
var listItemNesting = 0 ;
params . tokens . forEach ( function ( token ) {
var content = token . content , lineNumber = token . lineNumber , type = token . type ;
if ( type === "blockquote_open" ) {
blockquoteNesting ++ ;
}
else if ( type === "blockquote_close" ) {
blockquoteNesting -- ;
}
else if ( type === "list_item_open" ) {
listItemNesting ++ ;
}
else if ( type === "list_item_close" ) {
listItemNesting -- ;
}
else if ( ( type === "inline" ) && blockquoteNesting ) {
var lineCount = content . split ( newLineRe ) . length ;
for ( var i = 0 ; i < lineCount ; i ++ ) {
var line = params . lines [ lineNumber + i - 1 ] ;
var match = line . match ( spaceAfterBlockQuoteRe ) ;
if ( match ) {
var fullMatch = match [ 0 ] , blockquoteLength = match [ 1 ] [ "length" ] , spaceLength = match [ 2 ] [ "length" ] ;
if ( ! listItemNesting || ( fullMatch [ fullMatch . length - 1 ] === ">" ) ) {
addErrorContext ( onError , lineNumber + i , line , null , null , [ 1 , fullMatch . length ] , {
"editColumn" : blockquoteLength + 1 ,
"deleteCount" : spaceLength - 1
} ) ;
}
}
}
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 28 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var addError = require ( "../helpers" ) . addError ;
module . exports = {
"names" : [ "MD028" , "no-blanks-blockquote" ] ,
"description" : "Blank line inside blockquote" ,
"tags" : [ "blockquote" , "whitespace" ] ,
"function" : function MD028 ( params , onError ) {
var prevToken = { } ;
var prevLineNumber = null ;
params . tokens . forEach ( function forToken ( token ) {
if ( ( token . type === "blockquote_open" ) &&
( prevToken . type === "blockquote_close" ) ) {
for ( var lineNumber = prevLineNumber ; lineNumber < token . lineNumber ; lineNumber ++ ) {
addError ( onError , lineNumber , null , null , null , {
"deleteCount" : - 1
} ) ;
}
}
prevToken = token ;
if ( token . type === "blockquote_open" ) {
prevLineNumber = token . map [ 1 ] + 1 ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 29 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , listItemMarkerRe = _a . listItemMarkerRe , orderedListItemMarkerRe = _a . orderedListItemMarkerRe , rangeFromRegExp = _a . rangeFromRegExp ;
var flattenedLists = require ( "./cache" ) . flattenedLists ;
var listStyleExamples = {
"one" : "1/1/1" ,
"ordered" : "1/2/3" ,
"zero" : "0/0/0"
} ;
module . exports = {
"names" : [ "MD029" , "ol-prefix" ] ,
"description" : "Ordered list item prefix" ,
"tags" : [ "ol" ] ,
"function" : function MD029 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var style = String ( params . config . style || "one_or_ordered" ) ;
2020-04-11 13:54:46 -07:00
flattenedLists ( ) . filter ( function ( list ) { return ! list . unordered ; } ) . forEach ( function ( list ) {
var items = list . items ;
var current = 1 ;
var incrementing = false ;
// Check for incrementing number pattern 1/2/3 or 0/1/2
if ( items . length >= 2 ) {
var first = orderedListItemMarkerRe . exec ( items [ 0 ] . line ) ;
var second = orderedListItemMarkerRe . exec ( items [ 1 ] . line ) ;
if ( first && second ) {
var firstNumber = first [ 1 ] ;
var secondNumber = second [ 1 ] ;
if ( ( secondNumber !== "1" ) || ( firstNumber === "0" ) ) {
incrementing = true ;
if ( firstNumber === "0" ) {
current = 0 ;
}
2019-10-02 20:10:42 -07:00
}
2020-04-11 13:54:46 -07:00
}
}
// Determine effective style
var listStyle = style ;
if ( listStyle === "one_or_ordered" ) {
listStyle = incrementing ? "ordered" : "one" ;
}
// Force expected value for 0/0/0 and 1/1/1 patterns
if ( listStyle === "zero" ) {
current = 0 ;
2019-10-02 20:10:42 -07:00
}
2020-04-11 13:54:46 -07:00
else if ( listStyle === "one" ) {
current = 1 ;
}
// Validate each list item marker
items . forEach ( function ( item ) {
var match = orderedListItemMarkerRe . exec ( item . line ) ;
if ( match ) {
addErrorDetailIf ( onError , item . lineNumber , String ( current ) , match [ 1 ] , "Style: " + listStyleExamples [ listStyle ] , null , rangeFromRegExp ( item . line , listItemMarkerRe ) ) ;
if ( listStyle === "ordered" ) {
current ++ ;
}
}
} ) ;
2019-10-02 20:10:42 -07:00
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 30 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var addErrorDetailIf = require ( "../helpers" ) . addErrorDetailIf ;
var flattenedLists = require ( "./cache" ) . flattenedLists ;
module . exports = {
"names" : [ "MD030" , "list-marker-space" ] ,
"description" : "Spaces after list markers" ,
"tags" : [ "ol" , "ul" , "whitespace" ] ,
"function" : function MD030 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var ulSingle = Number ( params . config . ul _single || 1 ) ;
var olSingle = Number ( params . config . ol _single || 1 ) ;
var ulMulti = Number ( params . config . ul _multi || 1 ) ;
var olMulti = Number ( params . config . ol _multi || 1 ) ;
2019-10-02 20:10:42 -07:00
flattenedLists ( ) . forEach ( function ( list ) {
var lineCount = list . lastLineIndex - list . open . map [ 0 ] ;
var allSingle = lineCount === list . items . length ;
var expectedSpaces = list . unordered ?
( allSingle ? ulSingle : ulMulti ) :
( allSingle ? olSingle : olMulti ) ;
list . items . forEach ( function ( item ) {
var line = item . line , lineNumber = item . lineNumber ;
var match = /^[\s>]*\S+(\s*)/ . exec ( line ) ;
var matchLength = match [ 0 ] [ "length" ] , actualSpaces = match [ 1 ] [ "length" ] ;
2019-12-14 13:50:48 -08:00
if ( matchLength < line . length ) {
var fixInfo = null ;
if ( expectedSpaces !== actualSpaces ) {
fixInfo = {
"editColumn" : matchLength - actualSpaces + 1 ,
"deleteCount" : actualSpaces ,
"insertText" : "" . padEnd ( expectedSpaces )
} ;
}
addErrorDetailIf ( onError , lineNumber , expectedSpaces , actualSpaces , null , null , [ 1 , matchLength ] , fixInfo ) ;
2019-10-02 20:10:42 -07:00
}
} ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 31 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , forEachLine = _a . forEachLine , isBlankLine = _a . isBlankLine ;
var lineMetadata = require ( "./cache" ) . lineMetadata ;
2020-04-11 13:54:46 -07:00
var codeFencePrefixRe = /^(.*?)\s*[`~]/ ;
2019-10-02 20:10:42 -07:00
module . exports = {
"names" : [ "MD031" , "blanks-around-fences" ] ,
"description" : "Fenced code blocks should be surrounded by blank lines" ,
"tags" : [ "code" , "blank_lines" ] ,
"function" : function MD031 ( params , onError ) {
var listItems = params . config . list _items ;
var includeListItems = ( listItems === undefined ) ? true : ! ! listItems ;
var lines = params . lines ;
forEachLine ( lineMetadata ( ) , function ( line , i , inCode , onFence , inTable , inItem ) {
var onTopFence = ( onFence > 0 ) ;
var onBottomFence = ( onFence < 0 ) ;
if ( ( includeListItems || ! inItem ) &&
( ( onTopFence && ! isBlankLine ( lines [ i - 1 ] ) ) ||
( onBottomFence && ! isBlankLine ( lines [ i + 1 ] ) ) ) ) {
2020-04-11 13:54:46 -07:00
var _a = line . match ( codeFencePrefixRe ) , prefix = _a [ 1 ] ;
2019-10-02 20:10:42 -07:00
addErrorContext ( onError , i + 1 , lines [ i ] . trim ( ) , null , null , null , {
"lineNumber" : i + ( onTopFence ? 1 : 2 ) ,
2020-04-11 13:54:46 -07:00
"insertText" : prefix + "\n"
2019-10-02 20:10:42 -07:00
} ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 32 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , isBlankLine = _a . isBlankLine ;
var flattenedLists = require ( "./cache" ) . flattenedLists ;
var quotePrefixRe = /^[>\s]*/ ;
module . exports = {
"names" : [ "MD032" , "blanks-around-lists" ] ,
"description" : "Lists should be surrounded by blank lines" ,
"tags" : [ "bullet" , "ul" , "ol" , "blank_lines" ] ,
"function" : function MD032 ( params , onError ) {
var lines = params . lines ;
flattenedLists ( ) . filter ( function ( list ) { return ! list . nesting ; } ) . forEach ( function ( list ) {
var firstIndex = list . open . map [ 0 ] ;
if ( ! isBlankLine ( lines [ firstIndex - 1 ] ) ) {
var line = lines [ firstIndex ] ;
var quotePrefix = line . match ( quotePrefixRe ) [ 0 ] . trimRight ( ) ;
addErrorContext ( onError , firstIndex + 1 , line . trim ( ) , null , null , null , {
"insertText" : quotePrefix + "\n"
} ) ;
}
var lastIndex = list . lastLineIndex - 1 ;
if ( ! isBlankLine ( lines [ lastIndex + 1 ] ) ) {
var line = lines [ lastIndex ] ;
var quotePrefix = line . match ( quotePrefixRe ) [ 0 ] . trimRight ( ) ;
addErrorContext ( onError , lastIndex + 1 , line . trim ( ) , null , null , null , {
"lineNumber" : lastIndex + 2 ,
"insertText" : quotePrefix + "\n"
} ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 33 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
2019-10-24 20:23:22 -07:00
var _a = require ( "../helpers" ) , addError = _a . addError , forEachLine = _a . forEachLine , unescapeMarkdown = _a . unescapeMarkdown ;
2019-10-02 20:10:42 -07:00
var lineMetadata = require ( "./cache" ) . lineMetadata ;
var htmlElementRe = /<(([A-Za-z][A-Za-z0-9-]*)(?:\s[^>]*)?)\/?>/g ;
var linkDestinationRe = /]\(\s*$/ ;
var inlineCodeRe = /^[^`]*(`+[^`]+`+[^`]+)*`+[^`]*$/ ;
// See https://spec.commonmark.org/0.29/#autolinks
var emailAddressRe =
// eslint-disable-next-line max-len
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ ;
module . exports = {
"names" : [ "MD033" , "no-inline-html" ] ,
"description" : "Inline HTML" ,
"tags" : [ "html" ] ,
"function" : function MD033 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var allowedElements = params . config . allowed _elements ;
allowedElements = Array . isArray ( allowedElements ) ? allowedElements : [ ] ;
allowedElements = allowedElements . map ( function ( element ) { return element . toLowerCase ( ) ; } ) ;
2019-10-02 20:10:42 -07:00
forEachLine ( lineMetadata ( ) , function ( line , lineIndex , inCode ) {
var match = null ;
// eslint-disable-next-line no-unmodified-loop-condition
2019-10-24 20:23:22 -07:00
while ( ! inCode && ( ( match = htmlElementRe . exec ( line ) ) !== null ) ) {
2019-10-02 20:10:42 -07:00
var tag = match [ 0 ] , content = match [ 1 ] , element = match [ 2 ] ;
if ( ! allowedElements . includes ( element . toLowerCase ( ) ) &&
2019-10-24 20:23:22 -07:00
! tag . endsWith ( "\\>" ) &&
2019-10-02 20:10:42 -07:00
! emailAddressRe . test ( content ) ) {
var prefix = line . substring ( 0 , match . index ) ;
if ( ! linkDestinationRe . test ( prefix ) && ! inlineCodeRe . test ( prefix ) ) {
var unescaped = unescapeMarkdown ( prefix + "<" , "_" ) ;
if ( ! unescaped . endsWith ( "_" ) &&
( ( unescaped + "`" ) . match ( /`/g ) . length % 2 ) ) {
addError ( onError , lineIndex + 1 , "Element: " + element , null , [ match . index + 1 , tag . length ] ) ;
}
}
}
}
} ) ;
}
} ;
} , { "../helpers" : 2 , "./cache" : 3 } ] , 34 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , bareUrlRe = _a . bareUrlRe , filterTokens = _a . filterTokens ;
module . exports = {
"names" : [ "MD034" , "no-bare-urls" ] ,
"description" : "Bare URL used" ,
"tags" : [ "links" , "url" ] ,
"function" : function MD034 ( params , onError ) {
filterTokens ( params , "inline" , function ( token ) {
var inLink = false ;
token . children . forEach ( function ( child ) {
var content = child . content , line = child . line , lineNumber = child . lineNumber , type = child . type ;
var match = null ;
if ( type === "link_open" ) {
inLink = true ;
}
else if ( type === "link_close" ) {
inLink = false ;
}
else if ( ( type === "text" ) && ! inLink ) {
while ( ( match = bareUrlRe . exec ( content ) ) !== null ) {
var bareUrl = match [ 0 ] ;
2020-04-11 13:54:46 -07:00
var matchIndex = match . index ;
var bareUrlLength = bareUrl . length ;
// Allow "[https://example.com]" to avoid conflicts with
// MD011/no-reversed-links; allow quoting as another way
// of deliberately including a bare URL
var leftChar = content [ matchIndex - 1 ] ;
var rightChar = content [ matchIndex + bareUrlLength ] ;
if ( ! ( ( leftChar === "[" ) && ( rightChar === "]" ) ) &&
! ( ( leftChar === "\"" ) && ( rightChar === "\"" ) ) &&
! ( ( leftChar === "'" ) && ( rightChar === "'" ) ) ) {
var index = line . indexOf ( content ) ;
var range = ( index === - 1 ) ? null : [
index + matchIndex + 1 ,
bareUrlLength
] ;
var fixInfo = range ? {
"editColumn" : range [ 0 ] ,
"deleteCount" : range [ 1 ] ,
"insertText" : "<" + bareUrl + ">"
} : null ;
addErrorContext ( onError , lineNumber , bareUrl , null , null , range , fixInfo ) ;
}
2019-10-02 20:10:42 -07:00
}
}
} ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 35 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , filterTokens = _a . filterTokens ;
module . exports = {
"names" : [ "MD035" , "hr-style" ] ,
"description" : "Horizontal rule style" ,
"tags" : [ "hr" ] ,
"function" : function MD035 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var style = String ( params . config . style || "consistent" ) ;
2019-10-02 20:10:42 -07:00
filterTokens ( params , "hr" , function forToken ( token ) {
var lineTrim = token . line . trim ( ) ;
if ( style === "consistent" ) {
style = lineTrim ;
}
addErrorDetailIf ( onError , token . lineNumber , style , lineTrim ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 36 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , allPunctuation = _a . allPunctuation ;
module . exports = {
"names" : [ "MD036" , "no-emphasis-as-heading" , "no-emphasis-as-header" ] ,
"description" : "Emphasis used instead of a heading" ,
"tags" : [ "headings" , "headers" , "emphasis" ] ,
"function" : function MD036 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var punctuation = params . config . punctuation ;
punctuation =
String ( ( punctuation === undefined ) ? allPunctuation : punctuation ) ;
2019-10-02 20:10:42 -07:00
var re = new RegExp ( "[" + punctuation + "]$" ) ;
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2019-10-02 20:10:42 -07:00
function base ( token ) {
if ( token . type === "paragraph_open" ) {
return function inParagraph ( t ) {
// Always paragraph_open/inline/paragraph_close,
var children = t . children . filter ( function notEmptyText ( child ) {
return ( child . type !== "text" ) || ( child . content !== "" ) ;
} ) ;
if ( ( children . length === 3 ) &&
( ( children [ 0 ] . type === "strong_open" ) ||
( children [ 0 ] . type === "em_open" ) ) &&
( children [ 1 ] . type === "text" ) &&
! re . test ( children [ 1 ] . content ) ) {
addErrorContext ( onError , t . lineNumber , children [ 1 ] . content ) ;
}
return base ;
} ;
}
else if ( token . type === "blockquote_open" ) {
return function inBlockquote ( t ) {
if ( t . type !== "blockquote_close" ) {
return inBlockquote ;
}
return base ;
} ;
}
else if ( token . type === "list_item_open" ) {
return function inListItem ( t ) {
if ( t . type !== "list_item_close" ) {
return inListItem ;
}
return base ;
} ;
}
return base ;
}
var state = base ;
params . tokens . forEach ( function forToken ( token ) {
state = state ( token ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 37 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
2020-05-14 21:49:05 -07:00
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , emphasisMarkersInContent = _a . emphasisMarkersInContent , forEachLine = _a . forEachLine , isBlankLine = _a . isBlankLine ;
2020-04-11 13:54:46 -07:00
var lineMetadata = require ( "./cache" ) . lineMetadata ;
2020-05-14 21:49:05 -07:00
var emphasisRe = /(^|[^\\]|\\\\)(?:(\*\*?\*?)|(__?_?))/g ;
var asteriskListItemMarkerRe = /^([\s>]*)\*(\s+)/ ;
2020-04-11 13:54:46 -07:00
var leftSpaceRe = /^\s+/ ;
var rightSpaceRe = /\s+$/ ;
2019-10-02 20:10:42 -07:00
module . exports = {
"names" : [ "MD037" , "no-space-in-emphasis" ] ,
"description" : "Spaces inside emphasis markers" ,
"tags" : [ "whitespace" , "emphasis" ] ,
"function" : function MD037 ( params , onError ) {
2020-04-12 20:48:04 -07:00
// eslint-disable-next-line init-declarations
2020-04-25 21:15:13 -07:00
var effectiveEmphasisLength , emphasisIndex , emphasisKind , emphasisLength , pendingError = null ;
2020-04-12 20:48:04 -07:00
// eslint-disable-next-line jsdoc/require-jsdoc
function resetRunTracking ( ) {
emphasisIndex = - 1 ;
emphasisLength = 0 ;
2020-04-25 21:15:13 -07:00
emphasisKind = "" ;
2020-04-12 20:48:04 -07:00
effectiveEmphasisLength = 0 ;
pendingError = null ;
}
// eslint-disable-next-line jsdoc/require-jsdoc
function handleRunEnd ( line , lineIndex , contextLength , match , matchIndex ) {
// Close current run
var content = line . substring ( emphasisIndex , matchIndex ) ;
if ( ! emphasisLength ) {
content = content . trimStart ( ) ;
}
if ( ! match ) {
content = content . trimEnd ( ) ;
}
var leftSpace = leftSpaceRe . test ( content ) ;
var rightSpace = rightSpaceRe . test ( content ) ;
if ( leftSpace || rightSpace ) {
// Report the violation
var contextStart = emphasisIndex - emphasisLength ;
var contextEnd = matchIndex + contextLength ;
var context = line . substring ( contextStart , contextEnd ) ;
var column = contextStart + 1 ;
var length _1 = contextEnd - contextStart ;
var leftMarker = line . substring ( contextStart , emphasisIndex ) ;
var rightMarker = match ? ( match [ 2 ] || match [ 3 ] ) : "" ;
var fixedText = "" + leftMarker + content . trim ( ) + rightMarker ;
return [
onError ,
lineIndex + 1 ,
context ,
leftSpace ,
rightSpace ,
[ column , length _1 ] ,
{
"editColumn" : column ,
"deleteCount" : length _1 ,
"insertText" : fixedText
}
] ;
}
return null ;
}
// Initialize
2020-05-14 21:49:05 -07:00
var ignoreMarkersByLine = emphasisMarkersInContent ( params ) ;
2020-04-12 20:48:04 -07:00
resetRunTracking ( ) ;
forEachLine ( lineMetadata ( ) , function ( line , lineIndex , inCode , onFence , inTable , inItem , onBreak ) {
var onItemStart = ( inItem === 1 ) ;
if ( inCode || inTable || onBreak || onItemStart || isBlankLine ( line ) ) {
// Emphasis resets when leaving a block
resetRunTracking ( ) ;
}
if ( inCode || onBreak ) {
2020-04-11 13:54:46 -07:00
// Emphasis has no meaning here
return ;
}
2020-04-12 20:48:04 -07:00
if ( onItemStart ) {
2020-04-11 13:54:46 -07:00
// Trim overlapping '*' list item marker
line = line . replace ( asteriskListItemMarkerRe , "$1 $2" ) ;
}
var match = null ;
// Match all emphasis-looking runs in the line...
while ( ( match = emphasisRe . exec ( line ) ) ) {
2020-04-25 21:15:13 -07:00
var ignoreMarkersForLine = ignoreMarkersByLine [ lineIndex ] || [ ] ;
2020-04-11 13:54:46 -07:00
var matchIndex = match . index + match [ 1 ] . length ;
2020-05-14 21:49:05 -07:00
if ( ignoreMarkersForLine . includes ( matchIndex ) ) {
// Ignore emphasis markers inside code spans and links
2020-04-25 21:15:13 -07:00
continue ;
}
2020-04-11 13:54:46 -07:00
var matchLength = match [ 0 ] . length - match [ 1 ] . length ;
2020-04-25 21:15:13 -07:00
var matchKind = ( match [ 2 ] || match [ 3 ] ) [ 0 ] ;
2020-04-11 13:54:46 -07:00
if ( emphasisIndex === - 1 ) {
// New run
emphasisIndex = matchIndex + matchLength ;
emphasisLength = matchLength ;
2020-04-25 21:15:13 -07:00
emphasisKind = matchKind ;
2020-04-11 13:54:46 -07:00
effectiveEmphasisLength = matchLength ;
}
2020-05-14 21:49:05 -07:00
else if ( matchKind === emphasisKind ) {
// Matching emphasis markers
if ( matchLength === effectiveEmphasisLength ) {
// Ending an existing run, report any pending error
if ( pendingError ) {
addErrorContext . apply ( void 0 , pendingError ) ;
pendingError = null ;
}
var error = handleRunEnd ( line , lineIndex , effectiveEmphasisLength , match , matchIndex ) ;
if ( error ) {
addErrorContext . apply ( void 0 , error ) ;
}
// Reset
resetRunTracking ( ) ;
2020-04-12 20:48:04 -07:00
}
2020-05-14 21:49:05 -07:00
else if ( matchLength === 3 ) {
// Swap internal run length (1->2 or 2->1)
effectiveEmphasisLength = matchLength - effectiveEmphasisLength ;
2019-10-02 20:10:42 -07:00
}
2020-05-14 21:49:05 -07:00
else if ( effectiveEmphasisLength === 3 ) {
// Downgrade internal run (3->1 or 3->2)
effectiveEmphasisLength -= matchLength ;
}
else {
// Upgrade to internal run (1->3 or 2->3)
effectiveEmphasisLength += matchLength ;
}
// Back up one character so RegExp has a chance to match the
// next marker (ex: "**star**_underscore_")
2020-06-23 20:14:58 -07:00
if ( emphasisRe . lastIndex > 1 ) {
emphasisRe . lastIndex -- ;
}
2020-04-11 13:54:46 -07:00
}
2020-05-14 21:49:05 -07:00
else if ( emphasisRe . lastIndex > 1 ) {
// Back up one character so RegExp has a chance to match the
// mis-matched marker (ex: "*text_*")
emphasisRe . lastIndex -- ;
2020-04-11 13:54:46 -07:00
}
}
2020-04-12 20:48:04 -07:00
if ( emphasisIndex !== - 1 ) {
pendingError = pendingError ||
handleRunEnd ( line , lineIndex , 0 , null , line . length ) ;
// Adjust for pending run on new line
emphasisIndex = 0 ;
emphasisLength = 0 ;
}
2019-10-02 20:10:42 -07:00
} ) ;
}
} ;
2020-04-11 13:54:46 -07:00
} , { "../helpers" : 2 , "./cache" : 3 } ] , 38 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , filterTokens = _a . filterTokens , forEachInlineCodeSpan = _a . forEachInlineCodeSpan , newLineRe = _a . newLineRe ;
var leftSpaceRe = /^\s([^`]|$)/ ;
var rightSpaceRe = /[^`]\s$/ ;
2020-04-25 21:15:13 -07:00
var singleLeftRightSpaceRe = /^\s(?:\S.*\S|\S)\s$/ ;
2019-10-02 20:10:42 -07:00
module . exports = {
"names" : [ "MD038" , "no-space-in-code" ] ,
"description" : "Spaces inside code span elements" ,
"tags" : [ "whitespace" , "code" ] ,
"function" : function MD038 ( params , onError ) {
filterTokens ( params , "inline" , function ( token ) {
if ( token . children . some ( function ( child ) { return child . type === "code_inline" ; } ) ) {
var tokenLines _1 = params . lines . slice ( token . map [ 0 ] , token . map [ 1 ] ) ;
forEachInlineCodeSpan ( tokenLines _1 . join ( "\n" ) , function ( code , lineIndex , columnIndex , tickCount ) {
var rangeIndex = columnIndex - tickCount ;
var rangeLength = code . length + ( 2 * tickCount ) ;
var rangeLineOffset = 0 ;
var fixIndex = columnIndex ;
var fixLength = code . length ;
var codeLines = code . split ( newLineRe ) ;
var left = leftSpaceRe . test ( code ) ;
var right = ! left && rightSpaceRe . test ( code ) ;
if ( right && ( codeLines . length > 1 ) ) {
rangeIndex = 0 ;
rangeLineOffset = codeLines . length - 1 ;
fixIndex = 0 ;
}
2020-04-11 13:54:46 -07:00
var allowed = singleLeftRightSpaceRe . test ( code ) ;
if ( ( left || right ) && ! allowed ) {
2019-10-02 20:10:42 -07:00
var codeLinesRange = codeLines [ rangeLineOffset ] ;
if ( codeLines . length > 1 ) {
rangeLength = codeLinesRange . length + tickCount ;
fixLength = codeLinesRange . length ;
}
var context = tokenLines _1 [ lineIndex + rangeLineOffset ]
. substring ( rangeIndex , rangeIndex + rangeLength ) ;
var codeLinesRangeTrim = codeLinesRange . trim ( ) ;
var fixText = ( codeLinesRangeTrim . startsWith ( "`" ) ? " " : "" ) +
codeLinesRangeTrim +
( codeLinesRangeTrim . endsWith ( "`" ) ? " " : "" ) ;
addErrorContext ( onError , token . lineNumber + lineIndex + rangeLineOffset , context , left , right , [ rangeIndex + 1 , rangeLength ] , {
"editColumn" : fixIndex + 1 ,
"deleteCount" : fixLength ,
"insertText" : fixText
} ) ;
}
} ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 39 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , filterTokens = _a . filterTokens ;
var spaceInLinkRe = /\[(?:\s+(?:[^\]]*?)\s*|(?:[^\]]*?)\s+)](?=\(\S*\))/ ;
module . exports = {
"names" : [ "MD039" , "no-space-in-links" ] ,
"description" : "Spaces inside link text" ,
"tags" : [ "whitespace" , "links" ] ,
"function" : function MD039 ( params , onError ) {
filterTokens ( params , "inline" , function ( token ) {
var children = token . children ;
var lineNumber = token . lineNumber ;
var inLink = false ;
var linkText = "" ;
var lineIndex = 0 ;
children . forEach ( function ( child ) {
var content = child . content , type = child . type ;
if ( type === "link_open" ) {
inLink = true ;
linkText = "" ;
}
else if ( type === "link_close" ) {
inLink = false ;
var left = linkText . trimLeft ( ) . length !== linkText . length ;
var right = linkText . trimRight ( ) . length !== linkText . length ;
if ( left || right ) {
var line = params . lines [ lineNumber - 1 ] ;
2020-04-11 13:54:46 -07:00
var range = null ;
var fixInfo = null ;
2019-10-02 20:10:42 -07:00
var match = line . slice ( lineIndex ) . match ( spaceInLinkRe ) ;
2020-04-11 13:54:46 -07:00
if ( match ) {
var column = match . index + lineIndex + 1 ;
var length _1 = match [ 0 ] . length ;
range = [ column , length _1 ] ;
fixInfo = {
"editColumn" : column + 1 ,
"deleteCount" : length _1 - 2 ,
"insertText" : linkText . trim ( )
} ;
lineIndex = column + length _1 - 1 ;
}
addErrorContext ( onError , lineNumber , "[" + linkText + "]" , left , right , range , fixInfo ) ;
2019-10-02 20:10:42 -07:00
}
}
else if ( ( type === "softbreak" ) || ( type === "hardbreak" ) ) {
lineNumber ++ ;
lineIndex = 0 ;
}
else if ( inLink ) {
linkText += content ;
}
} ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 40 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , filterTokens = _a . filterTokens ;
module . exports = {
"names" : [ "MD040" , "fenced-code-language" ] ,
"description" : "Fenced code blocks should have a language specified" ,
"tags" : [ "code" , "language" ] ,
"function" : function MD040 ( params , onError ) {
filterTokens ( params , "fence" , function forToken ( token ) {
if ( ! token . info . trim ( ) ) {
addErrorContext ( onError , token . lineNumber , token . line ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 41 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , frontMatterHasTitle = _a . frontMatterHasTitle ;
module . exports = {
"names" : [ "MD041" , "first-line-heading" , "first-line-h1" ] ,
"description" : "First line in file should be a top level heading" ,
"tags" : [ "headings" , "headers" ] ,
"function" : function MD041 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var level = Number ( params . config . level || 1 ) ;
2019-10-02 20:10:42 -07:00
var tag = "h" + level ;
var foundFrontMatterTitle = frontMatterHasTitle ( params . frontMatterLines , params . config . front _matter _title ) ;
if ( ! foundFrontMatterTitle ) {
params . tokens . every ( function ( token ) {
if ( token . type === "html_block" ) {
return true ;
}
if ( ( token . type !== "heading_open" ) || ( token . tag !== tag ) ) {
addErrorContext ( onError , token . lineNumber , token . line ) ;
}
return false ;
} ) ;
}
}
} ;
} , { "../helpers" : 2 } ] , 42 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , filterTokens = _a . filterTokens , rangeFromRegExp = _a . rangeFromRegExp ;
var emptyLinkRe = /\[[^\]]*](?:\((?:#?|(?:<>))\))/ ;
module . exports = {
"names" : [ "MD042" , "no-empty-links" ] ,
"description" : "No empty links" ,
"tags" : [ "links" ] ,
"function" : function MD042 ( params , onError ) {
filterTokens ( params , "inline" , function forToken ( token ) {
var inLink = false ;
var linkText = "" ;
var emptyLink = false ;
token . children . forEach ( function forChild ( child ) {
if ( child . type === "link_open" ) {
inLink = true ;
linkText = "" ;
child . attrs . forEach ( function forAttr ( attr ) {
if ( attr [ 0 ] === "href" && ( ! attr [ 1 ] || ( attr [ 1 ] === "#" ) ) ) {
emptyLink = true ;
}
} ) ;
}
else if ( child . type === "link_close" ) {
inLink = false ;
if ( emptyLink ) {
addErrorContext ( onError , child . lineNumber , "[" + linkText + "]()" , null , null , rangeFromRegExp ( child . line , emptyLinkRe ) ) ;
}
}
else if ( inLink ) {
linkText += child . content ;
}
} ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 43 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorContext = _a . addErrorContext , addErrorDetailIf = _a . addErrorDetailIf , forEachHeading = _a . forEachHeading ;
module . exports = {
"names" : [ "MD043" , "required-headings" , "required-headers" ] ,
"description" : "Required heading structure" ,
"tags" : [ "headings" , "headers" ] ,
"function" : function MD043 ( params , onError ) {
var requiredHeadings = params . config . headings || params . config . headers ;
2020-01-27 19:19:34 -08:00
if ( Array . isArray ( requiredHeadings ) ) {
2019-10-02 20:10:42 -07:00
var levels _1 = { } ;
[ 1 , 2 , 3 , 4 , 5 , 6 ] . forEach ( function forLevel ( level ) {
levels _1 [ "h" + level ] = "######" . substr ( - level ) ;
} ) ;
var i _1 = 0 ;
var optional _1 = false ;
var errorCount _1 = 0 ;
forEachHeading ( params , function forHeading ( heading , content ) {
if ( ! errorCount _1 ) {
var actual = levels _1 [ heading . tag ] + " " + content ;
var expected = requiredHeadings [ i _1 ++ ] || "[None]" ;
if ( expected === "*" ) {
optional _1 = true ;
}
else if ( expected . toLowerCase ( ) === actual . toLowerCase ( ) ) {
optional _1 = false ;
}
else if ( optional _1 ) {
i _1 -- ;
}
else {
addErrorDetailIf ( onError , heading . lineNumber , expected , actual ) ;
errorCount _1 ++ ;
}
}
} ) ;
if ( ( i _1 < requiredHeadings . length ) && ! errorCount _1 ) {
addErrorContext ( onError , params . lines . length , requiredHeadings [ i _1 ] ) ;
}
}
}
} ;
} , { "../helpers" : 2 } ] , 44 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , bareUrlRe = _a . bareUrlRe , escapeForRegExp = _a . escapeForRegExp , filterTokens = _a . filterTokens , forEachInlineChild = _a . forEachInlineChild , newLineRe = _a . newLineRe ;
2020-06-23 20:14:58 -07:00
var startNonWordRe = /^\W/ ;
var endNonWordRe = /\W$/ ;
2019-10-02 20:10:42 -07:00
module . exports = {
"names" : [ "MD044" , "proper-names" ] ,
"description" : "Proper names should have the correct capitalization" ,
"tags" : [ "spelling" ] ,
"function" : function MD044 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var names = params . config . names ;
names = Array . isArray ( names ) ? names : [ ] ;
2019-10-02 20:10:42 -07:00
var codeBlocks = params . config . code _blocks ;
var includeCodeBlocks = ( codeBlocks === undefined ) ? true : ! ! codeBlocks ;
names . forEach ( function ( name ) {
var escapedName = escapeForRegExp ( name ) ;
2020-06-23 20:14:58 -07:00
var startNamePattern = startNonWordRe . test ( name ) ? "" : "\\S*\\b" ;
var endNamePattern = endNonWordRe . test ( name ) ? "" : "\\b\\S*" ;
var namePattern = "(" + startNamePattern + ")(" + escapedName + ")(" + endNamePattern + ")" ;
2019-10-02 20:10:42 -07:00
var anyNameRe = new RegExp ( namePattern , "gi" ) ;
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2019-10-02 20:10:42 -07:00
function forToken ( token ) {
var fenceOffset = ( token . type === "fence" ) ? 1 : 0 ;
token . content . split ( newLineRe )
. forEach ( function ( line , index ) {
var match = null ;
while ( ( match = anyNameRe . exec ( line ) ) !== null ) {
2020-06-23 20:14:58 -07:00
var fullMatch = match [ 0 ] , leftMatch = match [ 1 ] , nameMatch = match [ 2 ] , rightMatch = match [ 3 ] ;
2019-10-24 20:23:22 -07:00
if ( fullMatch . search ( bareUrlRe ) === - 1 ) {
2019-10-02 20:10:42 -07:00
var wordMatch = fullMatch
2020-06-23 20:14:58 -07:00
. replace ( new RegExp ( "^\\W{0," + leftMatch . length + "}" ) , "" )
. replace ( new RegExp ( "\\W{0," + rightMatch . length + "}$" ) , "" ) ;
2019-10-02 20:10:42 -07:00
if ( ! names . includes ( wordMatch ) ) {
var lineNumber = token . lineNumber + index + fenceOffset ;
var fullLine = params . lines [ lineNumber - 1 ] ;
var matchLength = wordMatch . length ;
2020-06-23 20:14:58 -07:00
var matchIndex = fullLine . indexOf ( wordMatch ) ;
2020-05-14 21:49:05 -07:00
var range = ( matchIndex === - 1 ) ?
null :
[ matchIndex + 1 , matchLength ] ;
2020-06-23 20:14:58 -07:00
var fixInfo = ( matchIndex === - 1 ) ?
null :
{
"editColumn" : matchIndex + 1 ,
"deleteCount" : matchLength ,
"insertText" : name
} ;
addErrorDetailIf ( onError , lineNumber , name , nameMatch , null , null , range , fixInfo ) ;
2019-10-02 20:10:42 -07:00
}
}
}
} ) ;
}
forEachInlineChild ( params , "text" , forToken ) ;
if ( includeCodeBlocks ) {
forEachInlineChild ( params , "code_inline" , forToken ) ;
filterTokens ( params , "code_block" , forToken ) ;
filterTokens ( params , "fence" , forToken ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 45 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addError = _a . addError , forEachInlineChild = _a . forEachInlineChild ;
module . exports = {
"names" : [ "MD045" , "no-alt-text" ] ,
"description" : "Images should have alternate text (alt text)" ,
"tags" : [ "accessibility" , "images" ] ,
"function" : function MD045 ( params , onError ) {
forEachInlineChild ( params , "image" , function forToken ( token ) {
if ( token . content === "" ) {
addError ( onError , token . lineNumber ) ;
}
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 46 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var addErrorDetailIf = require ( "../helpers" ) . addErrorDetailIf ;
var tokenTypeToStyle = {
"fence" : "fenced" ,
"code_block" : "indented"
} ;
module . exports = {
"names" : [ "MD046" , "code-block-style" ] ,
"description" : "Code block style" ,
"tags" : [ "code" ] ,
"function" : function MD046 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var expectedStyle = String ( params . config . style || "consistent" ) ;
2019-10-02 20:10:42 -07:00
params . tokens
. filter ( function ( token ) { return token . type === "code_block" || token . type === "fence" ; } )
. forEach ( function ( token ) {
var lineNumber = token . lineNumber , type = token . type ;
if ( expectedStyle === "consistent" ) {
expectedStyle = tokenTypeToStyle [ type ] ;
}
addErrorDetailIf ( onError , lineNumber , expectedStyle , tokenTypeToStyle [ type ] ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 47 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
var _a = require ( "../helpers" ) , addError = _a . addError , isBlankLine = _a . isBlankLine ;
module . exports = {
"names" : [ "MD047" , "single-trailing-newline" ] ,
"description" : "Files should end with a single newline character" ,
"tags" : [ "blank_lines" ] ,
"function" : function MD047 ( params , onError ) {
var lastLineNumber = params . lines . length ;
var lastLine = params . lines [ lastLineNumber - 1 ] ;
if ( ! isBlankLine ( lastLine ) ) {
addError ( onError , lastLineNumber , null , null , [ lastLine . length , 1 ] , {
"insertText" : "\n" ,
"editColumn" : lastLine . length + 1
} ) ;
}
}
} ;
} , { "../helpers" : 2 } ] , 48 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
2020-01-27 19:19:34 -08:00
var _a = require ( "../helpers" ) , addErrorDetailIf = _a . addErrorDetailIf , fencedCodeBlockStyleFor = _a . fencedCodeBlockStyleFor ;
2019-12-14 13:50:48 -08:00
module . exports = {
"names" : [ "MD048" , "code-fence-style" ] ,
"description" : "Code fence style" ,
"tags" : [ "code" ] ,
"function" : function MD048 ( params , onError ) {
2020-01-27 19:19:34 -08:00
var style = String ( params . config . style || "consistent" ) ;
2019-12-14 13:50:48 -08:00
var expectedStyle = style ;
params . tokens
. filter ( function ( token ) { return token . type === "fence" ; } )
. forEach ( function ( fenceToken ) {
var lineNumber = fenceToken . lineNumber , markup = fenceToken . markup ;
if ( expectedStyle === "consistent" ) {
expectedStyle = fencedCodeBlockStyleFor ( markup ) ;
}
addErrorDetailIf ( onError , lineNumber , expectedStyle , fencedCodeBlockStyleFor ( markup ) ) ;
} ) ;
}
} ;
} , { "../helpers" : 2 } ] , 49 : [ function ( require , module , exports ) {
// @ts-check
"use strict" ;
2019-10-02 20:10:42 -07:00
var URL = require ( "url" ) . URL ;
var packageJson = require ( "../package.json" ) ;
var homepage = packageJson . homepage ;
var version = packageJson . version ;
var rules = [
require ( "./md001" ) ,
require ( "./md002" ) ,
require ( "./md003" ) ,
require ( "./md004" ) ,
require ( "./md005" ) ,
require ( "./md006" ) ,
require ( "./md007" ) ,
require ( "./md009" ) ,
require ( "./md010" ) ,
require ( "./md011" ) ,
require ( "./md012" ) ,
require ( "./md013" ) ,
require ( "./md014" ) ,
require ( "./md018" ) ,
require ( "./md019" ) ,
require ( "./md020" ) ,
require ( "./md021" ) ,
require ( "./md022" ) ,
require ( "./md023" ) ,
require ( "./md024" ) ,
require ( "./md025" ) ,
require ( "./md026" ) ,
require ( "./md027" ) ,
require ( "./md028" ) ,
require ( "./md029" ) ,
require ( "./md030" ) ,
require ( "./md031" ) ,
require ( "./md032" ) ,
require ( "./md033" ) ,
require ( "./md034" ) ,
require ( "./md035" ) ,
require ( "./md036" ) ,
require ( "./md037" ) ,
require ( "./md038" ) ,
require ( "./md039" ) ,
require ( "./md040" ) ,
require ( "./md041" ) ,
require ( "./md042" ) ,
require ( "./md043" ) ,
require ( "./md044" ) ,
require ( "./md045" ) ,
require ( "./md046" ) ,
2019-12-14 13:50:48 -08:00
require ( "./md047" ) ,
require ( "./md048" )
2019-10-02 20:10:42 -07:00
] ;
rules . forEach ( function ( rule ) {
var name = rule . names [ 0 ] . toLowerCase ( ) ;
rule . information =
new URL ( homepage + "/blob/v" + version + "/doc/Rules.md#" + name ) ;
} ) ;
module . exports = rules ;
2019-12-14 13:50:48 -08:00
} , { "../package.json" : 50 , "./md001" : 5 , "./md002" : 6 , "./md003" : 7 , "./md004" : 8 , "./md005" : 9 , "./md006" : 10 , "./md007" : 11 , "./md009" : 12 , "./md010" : 13 , "./md011" : 14 , "./md012" : 15 , "./md013" : 16 , "./md014" : 17 , "./md018" : 18 , "./md019" : 19 , "./md020" : 20 , "./md021" : 21 , "./md022" : 22 , "./md023" : 23 , "./md024" : 24 , "./md025" : 25 , "./md026" : 26 , "./md027" : 27 , "./md028" : 28 , "./md029" : 29 , "./md030" : 30 , "./md031" : 31 , "./md032" : 32 , "./md033" : 33 , "./md034" : 34 , "./md035" : 35 , "./md036" : 36 , "./md037" : 37 , "./md038" : 38 , "./md039" : 39 , "./md040" : 40 , "./md041" : 41 , "./md042" : 42 , "./md043" : 43 , "./md044" : 44 , "./md045" : 45 , "./md046" : 46 , "./md047" : 47 , "./md048" : 48 , "url" : 59 } ] , 50 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
module . exports = {
"name" : "markdownlint" ,
2020-06-23 20:14:58 -07:00
"version" : "0.20.4" ,
2019-10-02 20:10:42 -07:00
"description" : "A Node.js style checker and lint tool for Markdown/CommonMark files." ,
"main" : "lib/markdownlint.js" ,
2019-12-14 13:50:48 -08:00
"types" : "lib/markdownlint.d.ts" ,
2019-10-02 20:10:42 -07:00
"author" : "David Anson (https://dlaa.me/)" ,
"license" : "MIT" ,
"homepage" : "https://github.com/DavidAnson/markdownlint" ,
"repository" : {
"type" : "git" ,
"url" : "https://github.com/DavidAnson/markdownlint.git"
} ,
"bugs" : "https://github.com/DavidAnson/markdownlint/issues" ,
"scripts" : {
2020-01-27 19:19:34 -08:00
"test" : "node test/markdownlint-test.js" ,
"test-cover" : "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 node test/markdownlint-test.js" ,
2019-12-14 13:50:48 -08:00
"test-declaration" : "cd example/typescript && tsc && node type-check.js" ,
2020-01-27 19:19:34 -08:00
"test-extra" : "node test/markdownlint-test-extra.js" ,
2019-10-02 20:10:42 -07:00
"debug" : "node debug node_modules/nodeunit/bin/nodeunit" ,
2020-01-27 19:19:34 -08:00
"lint" : "eslint --max-warnings 0 lib helpers test schema && eslint --env browser --global markdownit --global markdownlint --rule \"no-unused-vars: 0, no-extend-native: 0, max-statements: 0, no-console: 0, no-var: 0\" demo && eslint --rule \"no-console: 0, no-invalid-this: 0, no-shadow: 0, object-property-newline: 0\" example" ,
"ci" : "npm run test-cover && npm run lint && npm run test-declaration" ,
2019-10-02 20:10:42 -07:00
"build-config-schema" : "node schema/build-config-schema.js" ,
2019-12-14 13:50:48 -08:00
"build-declaration" : "tsc --allowJs --declaration --outDir declaration --resolveJsonModule lib/markdownlint.js && cpy declaration/lib/markdownlint.d.ts lib && rimraf declaration" ,
2019-10-02 20:10:42 -07:00
"build-demo" : "cpy node_modules/markdown-it/dist/markdown-it.min.js demo && cd demo && rimraf markdownlint-browser.* && cpy file-header.js . --rename=markdownlint-browser.js && tsc --allowJs --resolveJsonModule --outDir ../lib-es3 ../lib/markdownlint.js && cpy ../helpers/package.json ../lib-es3/helpers && browserify ../lib-es3/lib/markdownlint.js --standalone markdownlint >> markdownlint-browser.js && uglifyjs markdownlint-browser.js --compress --mangle --comments --output markdownlint-browser.min.js" ,
"build-example" : "npm install --no-save --ignore-scripts grunt grunt-cli gulp through2" ,
2020-05-14 21:49:05 -07:00
"example" : "cd example && node standalone.js && grunt markdownlint --force && gulp markdownlint" ,
"clone-test-repos" : "make-dir test-repos && cd test-repos && git clone https://github.com/eslint/eslint eslint-eslint --depth 1 --no-tags --quiet && git clone https://github.com/mkdocs/mkdocs mkdocs-mkdocs --depth 1 --no-tags --quiet && git clone https://github.com/pi-hole/docs pi-hole-docs --depth 1 --no-tags --quiet" ,
"clone-test-repos-large" : "npm run clone-test-repos && cd test-repos && git clone https://github.com/dotnet/docs dotnet-docs --depth 1 --no-tags --quiet" ,
"lint-test-repos" : "node test/markdownlint-test-repos.js" ,
"clean-test-repos" : "rimraf test-repos"
2019-10-02 20:10:42 -07:00
} ,
"engines" : {
2020-01-27 19:19:34 -08:00
"node" : ">=10"
2019-10-02 20:10:42 -07:00
} ,
"dependencies" : {
2019-10-03 20:53:54 -07:00
"markdown-it" : "10.0.0"
2019-10-02 20:10:42 -07:00
} ,
"devDependencies" : {
2020-04-11 13:54:46 -07:00
"@types/node" : "~13.11.1" ,
"browserify" : "~16.5.1" ,
2020-05-14 21:49:05 -07:00
"c8" : "~7.1.2" ,
2020-04-11 13:54:46 -07:00
"cpy-cli" : "~3.1.0" ,
2020-01-27 19:19:34 -08:00
"eslint" : "~6.8.0" ,
2020-04-11 13:54:46 -07:00
"eslint-plugin-jsdoc" : "~22.1.0" ,
2020-05-14 21:49:05 -07:00
"globby" : "~11.0.0" ,
2019-10-02 20:10:42 -07:00
"js-yaml" : "~3.13.1" ,
2020-05-14 21:49:05 -07:00
"make-dir-cli" : "~2.0.0" ,
2019-10-02 20:10:42 -07:00
"markdown-it-for-inline" : "~0.1.1" ,
"markdown-it-katex" : "~2.0.3" ,
"markdown-it-sub" : "~1.0.0" ,
"markdown-it-sup" : "~1.0.0" ,
2020-04-11 13:54:46 -07:00
"markdownlint-rule-helpers" : "~0.7.0" ,
"rimraf" : "~3.0.2" ,
2020-05-14 21:49:05 -07:00
"strip-json-comments" : "~3.1.0" ,
2020-04-11 13:54:46 -07:00
"tape" : "~4.13.2" ,
"tape-player" : "~0.1.0" ,
2019-10-02 20:10:42 -07:00
"toml" : "~3.0.0" ,
"tv4" : "~1.3.0" ,
2020-04-11 13:54:46 -07:00
"typescript" : "~3.8.3" ,
"uglify-js" : "~3.8.1"
2019-10-02 20:10:42 -07:00
} ,
"keywords" : [
"markdown" ,
"lint" ,
"md" ,
"CommonMark" ,
"markdownlint"
] ,
"browser" : {
"markdown-it" : "../demo/markdown-it-stub.js"
}
}
} , { } ] , 51 : [ function ( require , module , exports ) {
2019-12-14 13:50:48 -08:00
} , { } ] , 52 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
exports . endianness = function ( ) { return 'LE' } ;
exports . hostname = function ( ) {
if ( typeof location !== 'undefined' ) {
return location . hostname
}
else return '' ;
} ;
exports . loadavg = function ( ) { return [ ] } ;
exports . uptime = function ( ) { return 0 } ;
exports . freemem = function ( ) {
return Number . MAX _VALUE ;
} ;
exports . totalmem = function ( ) {
return Number . MAX _VALUE ;
} ;
exports . cpus = function ( ) { return [ ] } ;
exports . type = function ( ) { return 'Browser' } ;
exports . release = function ( ) {
if ( typeof navigator !== 'undefined' ) {
return navigator . appVersion ;
}
return '' ;
} ;
exports . networkInterfaces
= exports . getNetworkInterfaces
= function ( ) { return { } } ;
exports . arch = function ( ) { return 'javascript' } ;
exports . platform = function ( ) { return 'browser' } ;
exports . tmpdir = exports . tmpDir = function ( ) {
return '/tmp' ;
} ;
exports . EOL = '\n' ;
exports . homedir = function ( ) {
return '/'
} ;
2019-12-14 13:50:48 -08:00
} , { } ] , 53 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
( function ( process ) {
// .dirname, .basename, and .extname methods are extracted from Node.js v8.11.1,
// backported and transplited with Babel, with backwards-compat fixes
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
// resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
function normalizeArray ( parts , allowAboveRoot ) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0 ;
for ( var i = parts . length - 1 ; i >= 0 ; i -- ) {
var last = parts [ i ] ;
if ( last === '.' ) {
parts . splice ( i , 1 ) ;
} else if ( last === '..' ) {
parts . splice ( i , 1 ) ;
up ++ ;
} else if ( up ) {
parts . splice ( i , 1 ) ;
up -- ;
}
}
// if the path is allowed to go above the root, restore leading ..s
if ( allowAboveRoot ) {
for ( ; up -- ; up ) {
parts . unshift ( '..' ) ;
}
}
return parts ;
}
// path.resolve([from ...], to)
// posix version
exports . resolve = function ( ) {
var resolvedPath = '' ,
resolvedAbsolute = false ;
for ( var i = arguments . length - 1 ; i >= - 1 && ! resolvedAbsolute ; i -- ) {
var path = ( i >= 0 ) ? arguments [ i ] : process . cwd ( ) ;
// Skip empty and invalid entries
if ( typeof path !== 'string' ) {
throw new TypeError ( 'Arguments to path.resolve must be strings' ) ;
} else if ( ! path ) {
continue ;
}
resolvedPath = path + '/' + resolvedPath ;
resolvedAbsolute = path . charAt ( 0 ) === '/' ;
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray ( filter ( resolvedPath . split ( '/' ) , function ( p ) {
return ! ! p ;
} ) , ! resolvedAbsolute ) . join ( '/' ) ;
return ( ( resolvedAbsolute ? '/' : '' ) + resolvedPath ) || '.' ;
} ;
// path.normalize(path)
// posix version
exports . normalize = function ( path ) {
var isAbsolute = exports . isAbsolute ( path ) ,
trailingSlash = substr ( path , - 1 ) === '/' ;
// Normalize the path
path = normalizeArray ( filter ( path . split ( '/' ) , function ( p ) {
return ! ! p ;
} ) , ! isAbsolute ) . join ( '/' ) ;
if ( ! path && ! isAbsolute ) {
path = '.' ;
}
if ( path && trailingSlash ) {
path += '/' ;
}
return ( isAbsolute ? '/' : '' ) + path ;
} ;
// posix version
exports . isAbsolute = function ( path ) {
return path . charAt ( 0 ) === '/' ;
} ;
// posix version
exports . join = function ( ) {
var paths = Array . prototype . slice . call ( arguments , 0 ) ;
return exports . normalize ( filter ( paths , function ( p , index ) {
if ( typeof p !== 'string' ) {
throw new TypeError ( 'Arguments to path.join must be strings' ) ;
}
return p ;
} ) . join ( '/' ) ) ;
} ;
// path.relative(from, to)
// posix version
exports . relative = function ( from , to ) {
from = exports . resolve ( from ) . substr ( 1 ) ;
to = exports . resolve ( to ) . substr ( 1 ) ;
function trim ( arr ) {
var start = 0 ;
for ( ; start < arr . length ; start ++ ) {
if ( arr [ start ] !== '' ) break ;
}
var end = arr . length - 1 ;
for ( ; end >= 0 ; end -- ) {
if ( arr [ end ] !== '' ) break ;
}
if ( start > end ) return [ ] ;
return arr . slice ( start , end - start + 1 ) ;
}
var fromParts = trim ( from . split ( '/' ) ) ;
var toParts = trim ( to . split ( '/' ) ) ;
var length = Math . min ( fromParts . length , toParts . length ) ;
var samePartsLength = length ;
for ( var i = 0 ; i < length ; i ++ ) {
if ( fromParts [ i ] !== toParts [ i ] ) {
samePartsLength = i ;
break ;
}
}
var outputParts = [ ] ;
for ( var i = samePartsLength ; i < fromParts . length ; i ++ ) {
outputParts . push ( '..' ) ;
}
outputParts = outputParts . concat ( toParts . slice ( samePartsLength ) ) ;
return outputParts . join ( '/' ) ;
} ;
exports . sep = '/' ;
exports . delimiter = ':' ;
exports . dirname = function ( path ) {
if ( typeof path !== 'string' ) path = path + '' ;
if ( path . length === 0 ) return '.' ;
var code = path . charCodeAt ( 0 ) ;
var hasRoot = code === 47 /*/*/ ;
var end = - 1 ;
var matchedSlash = true ;
for ( var i = path . length - 1 ; i >= 1 ; -- i ) {
code = path . charCodeAt ( i ) ;
if ( code === 47 /*/*/ ) {
if ( ! matchedSlash ) {
end = i ;
break ;
}
} else {
// We saw the first non-path separator
matchedSlash = false ;
}
}
if ( end === - 1 ) return hasRoot ? '/' : '.' ;
if ( hasRoot && end === 1 ) {
// return '//';
// Backwards-compat fix:
return '/' ;
}
return path . slice ( 0 , end ) ;
} ;
function basename ( path ) {
if ( typeof path !== 'string' ) path = path + '' ;
var start = 0 ;
var end = - 1 ;
var matchedSlash = true ;
var i ;
for ( i = path . length - 1 ; i >= 0 ; -- i ) {
if ( path . charCodeAt ( i ) === 47 /*/*/ ) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if ( ! matchedSlash ) {
start = i + 1 ;
break ;
}
} else if ( end === - 1 ) {
// We saw the first non-path separator, mark this as the end of our
// path component
matchedSlash = false ;
end = i + 1 ;
}
}
if ( end === - 1 ) return '' ;
return path . slice ( start , end ) ;
}
// Uses a mixed approach for backwards-compatibility, as ext behavior changed
// in new Node.js versions, so only basename() above is backported here
exports . basename = function ( path , ext ) {
var f = basename ( path ) ;
if ( ext && f . substr ( - 1 * ext . length ) === ext ) {
f = f . substr ( 0 , f . length - ext . length ) ;
}
return f ;
} ;
exports . extname = function ( path ) {
if ( typeof path !== 'string' ) path = path + '' ;
var startDot = - 1 ;
var startPart = 0 ;
var end = - 1 ;
var matchedSlash = true ;
// Track the state of characters (if any) we see before our first dot and
// after any path separator we find
var preDotState = 0 ;
for ( var i = path . length - 1 ; i >= 0 ; -- i ) {
var code = path . charCodeAt ( i ) ;
if ( code === 47 /*/*/ ) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if ( ! matchedSlash ) {
startPart = i + 1 ;
break ;
}
continue ;
}
if ( end === - 1 ) {
// We saw the first non-path separator, mark this as the end of our
// extension
matchedSlash = false ;
end = i + 1 ;
}
if ( code === 46 /*.*/ ) {
// If this is our first dot, mark it as the start of our extension
if ( startDot === - 1 )
startDot = i ;
else if ( preDotState !== 1 )
preDotState = 1 ;
} else if ( startDot !== - 1 ) {
// We saw a non-dot and non-path separator before our dot, so we should
// have a good chance at having a non-empty extension
preDotState = - 1 ;
}
}
if ( startDot === - 1 || end === - 1 ||
// We saw a non-dot character immediately before the dot
preDotState === 0 ||
// The (right-most) trimmed path component is exactly '..'
preDotState === 1 && startDot === end - 1 && startDot === startPart + 1 ) {
return '' ;
}
return path . slice ( startDot , end ) ;
} ;
function filter ( xs , f ) {
if ( xs . filter ) return xs . filter ( f ) ;
var res = [ ] ;
for ( var i = 0 ; i < xs . length ; i ++ ) {
if ( f ( xs [ i ] , i , xs ) ) res . push ( xs [ i ] ) ;
}
return res ;
}
// String.prototype.substr - negative index don't work in IE8
var substr = 'ab' . substr ( - 1 ) === 'b'
? function ( str , start , len ) { return str . substr ( start , len ) }
: function ( str , start , len ) {
if ( start < 0 ) start = str . length + start ;
return str . substr ( start , len ) ;
}
;
} ) . call ( this , require ( '_process' ) )
2019-12-14 13:50:48 -08:00
} , { "_process" : 54 } ] , 54 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
// shim for using process in browser
var process = module . exports = { } ;
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout ;
var cachedClearTimeout ;
function defaultSetTimout ( ) {
throw new Error ( 'setTimeout has not been defined' ) ;
}
function defaultClearTimeout ( ) {
throw new Error ( 'clearTimeout has not been defined' ) ;
}
( function ( ) {
try {
if ( typeof setTimeout === 'function' ) {
cachedSetTimeout = setTimeout ;
} else {
cachedSetTimeout = defaultSetTimout ;
}
} catch ( e ) {
cachedSetTimeout = defaultSetTimout ;
}
try {
if ( typeof clearTimeout === 'function' ) {
cachedClearTimeout = clearTimeout ;
} else {
cachedClearTimeout = defaultClearTimeout ;
}
} catch ( e ) {
cachedClearTimeout = defaultClearTimeout ;
}
} ( ) )
function runTimeout ( fun ) {
if ( cachedSetTimeout === setTimeout ) {
//normal enviroments in sane situations
return setTimeout ( fun , 0 ) ;
}
// if setTimeout wasn't available but was latter defined
if ( ( cachedSetTimeout === defaultSetTimout || ! cachedSetTimeout ) && setTimeout ) {
cachedSetTimeout = setTimeout ;
return setTimeout ( fun , 0 ) ;
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout ( fun , 0 ) ;
} catch ( e ) {
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout . call ( null , fun , 0 ) ;
} catch ( e ) {
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout . call ( this , fun , 0 ) ;
}
}
}
function runClearTimeout ( marker ) {
if ( cachedClearTimeout === clearTimeout ) {
//normal enviroments in sane situations
return clearTimeout ( marker ) ;
}
// if clearTimeout wasn't available but was latter defined
if ( ( cachedClearTimeout === defaultClearTimeout || ! cachedClearTimeout ) && clearTimeout ) {
cachedClearTimeout = clearTimeout ;
return clearTimeout ( marker ) ;
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout ( marker ) ;
} catch ( e ) {
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout . call ( null , marker ) ;
} catch ( e ) {
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout . call ( this , marker ) ;
}
}
}
var queue = [ ] ;
var draining = false ;
var currentQueue ;
var queueIndex = - 1 ;
function cleanUpNextTick ( ) {
if ( ! draining || ! currentQueue ) {
return ;
}
draining = false ;
if ( currentQueue . length ) {
queue = currentQueue . concat ( queue ) ;
} else {
queueIndex = - 1 ;
}
if ( queue . length ) {
drainQueue ( ) ;
}
}
function drainQueue ( ) {
if ( draining ) {
return ;
}
var timeout = runTimeout ( cleanUpNextTick ) ;
draining = true ;
var len = queue . length ;
while ( len ) {
currentQueue = queue ;
queue = [ ] ;
while ( ++ queueIndex < len ) {
if ( currentQueue ) {
currentQueue [ queueIndex ] . run ( ) ;
}
}
queueIndex = - 1 ;
len = queue . length ;
}
currentQueue = null ;
draining = false ;
runClearTimeout ( timeout ) ;
}
process . nextTick = function ( fun ) {
var args = new Array ( arguments . length - 1 ) ;
if ( arguments . length > 1 ) {
for ( var i = 1 ; i < arguments . length ; i ++ ) {
args [ i - 1 ] = arguments [ i ] ;
}
}
queue . push ( new Item ( fun , args ) ) ;
if ( queue . length === 1 && ! draining ) {
runTimeout ( drainQueue ) ;
}
} ;
// v8 likes predictible objects
function Item ( fun , array ) {
this . fun = fun ;
this . array = array ;
}
Item . prototype . run = function ( ) {
this . fun . apply ( null , this . array ) ;
} ;
process . title = 'browser' ;
process . browser = true ;
process . env = { } ;
process . argv = [ ] ;
process . version = '' ; // empty string to avoid regexp issues
process . versions = { } ;
function noop ( ) { }
process . on = noop ;
process . addListener = noop ;
process . once = noop ;
process . off = noop ;
process . removeListener = noop ;
process . removeAllListeners = noop ;
process . emit = noop ;
process . prependListener = noop ;
process . prependOnceListener = noop ;
process . listeners = function ( name ) { return [ ] }
process . binding = function ( name ) {
throw new Error ( 'process.binding is not supported' ) ;
} ;
process . cwd = function ( ) { return '/' } ;
process . chdir = function ( dir ) {
throw new Error ( 'process.chdir is not supported' ) ;
} ;
process . umask = function ( ) { return 0 ; } ;
2019-12-14 13:50:48 -08:00
} , { } ] , 55 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
( function ( global ) {
/*! https://mths.be/punycode v1.4.1 by @mathias */
; ( function ( root ) {
/** Detect free variables */
var freeExports = typeof exports == 'object' && exports &&
! exports . nodeType && exports ;
var freeModule = typeof module == 'object' && module &&
! module . nodeType && module ;
var freeGlobal = typeof global == 'object' && global ;
if (
freeGlobal . global === freeGlobal ||
freeGlobal . window === freeGlobal ||
freeGlobal . self === freeGlobal
) {
root = freeGlobal ;
}
/ * *
* The ` punycode ` object .
* @ name punycode
* @ type Object
* /
var punycode ,
/** Highest positive signed 32-bit float value */
maxInt = 2147483647 , // aka. 0x7FFFFFFF or 2^31-1
/** Bootstring parameters */
base = 36 ,
tMin = 1 ,
tMax = 26 ,
skew = 38 ,
damp = 700 ,
initialBias = 72 ,
initialN = 128 , // 0x80
delimiter = '-' , // '\x2D'
/** Regular expressions */
regexPunycode = /^xn--/ ,
regexNonASCII = /[^\x20-\x7E]/ , // unprintable ASCII chars + non-ASCII chars
regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g , // RFC 3490 separators
/** Error messages */
errors = {
'overflow' : 'Overflow: input needs wider integers to process' ,
'not-basic' : 'Illegal input >= 0x80 (not a basic code point)' ,
'invalid-input' : 'Invalid input'
} ,
/** Convenience shortcuts */
baseMinusTMin = base - tMin ,
floor = Math . floor ,
stringFromCharCode = String . fromCharCode ,
/** Temporary variable */
key ;
/*--------------------------------------------------------------------------*/
/ * *
* A generic error utility function .
* @ private
* @ param { String } type The error type .
* @ returns { Error } Throws a ` RangeError ` with the applicable error message .
* /
function error ( type ) {
throw new RangeError ( errors [ type ] ) ;
}
/ * *
* A generic ` Array#map ` utility function .
* @ private
* @ param { Array } array The array to iterate over .
* @ param { Function } callback The function that gets called for every array
* item .
* @ returns { Array } A new array of values returned by the callback function .
* /
function map ( array , fn ) {
var length = array . length ;
var result = [ ] ;
while ( length -- ) {
result [ length ] = fn ( array [ length ] ) ;
}
return result ;
}
/ * *
* A simple ` Array#map ` - like wrapper to work with domain name strings or email
* addresses .
* @ private
* @ param { String } domain The domain name or email address .
* @ param { Function } callback The function that gets called for every
* character .
* @ returns { Array } A new string of characters returned by the callback
* function .
* /
function mapDomain ( string , fn ) {
var parts = string . split ( '@' ) ;
var result = '' ;
if ( parts . length > 1 ) {
// In email addresses, only the domain name should be punycoded. Leave
// the local part (i.e. everything up to `@`) intact.
result = parts [ 0 ] + '@' ;
string = parts [ 1 ] ;
}
// Avoid `split(regex)` for IE8 compatibility. See #17.
string = string . replace ( regexSeparators , '\x2E' ) ;
var labels = string . split ( '.' ) ;
var encoded = map ( labels , fn ) . join ( '.' ) ;
return result + encoded ;
}
/ * *
* Creates an array containing the numeric code points of each Unicode
* character in the string . While JavaScript uses UCS - 2 internally ,
* this function will convert a pair of surrogate halves ( each of which
* UCS - 2 exposes as separate characters ) into a single code point ,
* matching UTF - 16.
* @ see ` punycode.ucs2.encode `
* @ see < https : //mathiasbynens.be/notes/javascript-encoding>
* @ memberOf punycode . ucs2
* @ name decode
* @ param { String } string The Unicode input string ( UCS - 2 ) .
* @ returns { Array } The new array of code points .
* /
function ucs2decode ( string ) {
var output = [ ] ,
counter = 0 ,
length = string . length ,
value ,
extra ;
while ( counter < length ) {
value = string . charCodeAt ( counter ++ ) ;
if ( value >= 0xD800 && value <= 0xDBFF && counter < length ) {
// high surrogate, and there is a next character
extra = string . charCodeAt ( counter ++ ) ;
if ( ( extra & 0xFC00 ) == 0xDC00 ) { // low surrogate
output . push ( ( ( value & 0x3FF ) << 10 ) + ( extra & 0x3FF ) + 0x10000 ) ;
} else {
// unmatched surrogate; only append this code unit, in case the next
// code unit is the high surrogate of a surrogate pair
output . push ( value ) ;
counter -- ;
}
} else {
output . push ( value ) ;
}
}
return output ;
}
/ * *
* Creates a string based on an array of numeric code points .
* @ see ` punycode.ucs2.decode `
* @ memberOf punycode . ucs2
* @ name encode
* @ param { Array } codePoints The array of numeric code points .
* @ returns { String } The new Unicode string ( UCS - 2 ) .
* /
function ucs2encode ( array ) {
return map ( array , function ( value ) {
var output = '' ;
if ( value > 0xFFFF ) {
value -= 0x10000 ;
output += stringFromCharCode ( value >>> 10 & 0x3FF | 0xD800 ) ;
value = 0xDC00 | value & 0x3FF ;
}
output += stringFromCharCode ( value ) ;
return output ;
} ) . join ( '' ) ;
}
/ * *
* Converts a basic code point into a digit / integer .
* @ see ` digitToBasic() `
* @ private
* @ param { Number } codePoint The basic numeric code point value .
* @ returns { Number } The numeric value of a basic code point ( for use in
* representing integers ) in the range ` 0 ` to ` base - 1 ` , or ` base ` if
* the code point does not represent a value .
* /
function basicToDigit ( codePoint ) {
if ( codePoint - 48 < 10 ) {
return codePoint - 22 ;
}
if ( codePoint - 65 < 26 ) {
return codePoint - 65 ;
}
if ( codePoint - 97 < 26 ) {
return codePoint - 97 ;
}
return base ;
}
/ * *
* Converts a digit / integer into a basic code point .
* @ see ` basicToDigit() `
* @ private
* @ param { Number } digit The numeric value of a basic code point .
* @ returns { Number } The basic code point whose value ( when used for
* representing integers ) is ` digit ` , which needs to be in the range
* ` 0 ` to ` base - 1 ` . If ` flag ` is non - zero , the uppercase form is
* used ; else , the lowercase form is used . The behavior is undefined
* if ` flag ` is non - zero and ` digit ` has no uppercase form .
* /
function digitToBasic ( digit , flag ) {
// 0..25 map to ASCII a..z or A..Z
// 26..35 map to ASCII 0..9
return digit + 22 + 75 * ( digit < 26 ) - ( ( flag != 0 ) << 5 ) ;
}
/ * *
* Bias adaptation function as per section 3.4 of RFC 3492.
* https : //tools.ietf.org/html/rfc3492#section-3.4
* @ private
* /
function adapt ( delta , numPoints , firstTime ) {
var k = 0 ;
delta = firstTime ? floor ( delta / damp ) : delta >> 1 ;
delta += floor ( delta / numPoints ) ;
for ( /* no initialization */ ; delta > baseMinusTMin * tMax >> 1 ; k += base ) {
delta = floor ( delta / baseMinusTMin ) ;
}
return floor ( k + ( baseMinusTMin + 1 ) * delta / ( delta + skew ) ) ;
}
/ * *
* Converts a Punycode string of ASCII - only symbols to a string of Unicode
* symbols .
* @ memberOf punycode
* @ param { String } input The Punycode string of ASCII - only symbols .
* @ returns { String } The resulting string of Unicode symbols .
* /
function decode ( input ) {
// Don't use UCS-2
var output = [ ] ,
inputLength = input . length ,
out ,
i = 0 ,
n = initialN ,
bias = initialBias ,
basic ,
j ,
index ,
oldi ,
w ,
k ,
digit ,
t ,
/** Cached calculation results */
baseMinusT ;
// Handle the basic code points: let `basic` be the number of input code
// points before the last delimiter, or `0` if there is none, then copy
// the first basic code points to the output.
basic = input . lastIndexOf ( delimiter ) ;
if ( basic < 0 ) {
basic = 0 ;
}
for ( j = 0 ; j < basic ; ++ j ) {
// if it's not a basic code point
if ( input . charCodeAt ( j ) >= 0x80 ) {
error ( 'not-basic' ) ;
}
output . push ( input . charCodeAt ( j ) ) ;
}
// Main decoding loop: start just after the last delimiter if any basic code
// points were copied; start at the beginning otherwise.
for ( index = basic > 0 ? basic + 1 : 0 ; index < inputLength ; /* no final expression */ ) {
// `index` is the index of the next character to be consumed.
// Decode a generalized variable-length integer into `delta`,
// which gets added to `i`. The overflow checking is easier
// if we increase `i` as we go, then subtract off its starting
// value at the end to obtain `delta`.
for ( oldi = i , w = 1 , k = base ; /* no condition */ ; k += base ) {
if ( index >= inputLength ) {
error ( 'invalid-input' ) ;
}
digit = basicToDigit ( input . charCodeAt ( index ++ ) ) ;
if ( digit >= base || digit > floor ( ( maxInt - i ) / w ) ) {
error ( 'overflow' ) ;
}
i += digit * w ;
t = k <= bias ? tMin : ( k >= bias + tMax ? tMax : k - bias ) ;
if ( digit < t ) {
break ;
}
baseMinusT = base - t ;
if ( w > floor ( maxInt / baseMinusT ) ) {
error ( 'overflow' ) ;
}
w *= baseMinusT ;
}
out = output . length + 1 ;
bias = adapt ( i - oldi , out , oldi == 0 ) ;
// `i` was supposed to wrap around from `out` to `0`,
// incrementing `n` each time, so we'll fix that now:
if ( floor ( i / out ) > maxInt - n ) {
error ( 'overflow' ) ;
}
n += floor ( i / out ) ;
i %= out ;
// Insert `n` at position `i` of the output
output . splice ( i ++ , 0 , n ) ;
}
return ucs2encode ( output ) ;
}
/ * *
* Converts a string of Unicode symbols ( e . g . a domain name label ) to a
* Punycode string of ASCII - only symbols .
* @ memberOf punycode
* @ param { String } input The string of Unicode symbols .
* @ returns { String } The resulting Punycode string of ASCII - only symbols .
* /
function encode ( input ) {
var n ,
delta ,
handledCPCount ,
basicLength ,
bias ,
j ,
m ,
q ,
k ,
t ,
currentValue ,
output = [ ] ,
/** `inputLength` will hold the number of code points in `input`. */
inputLength ,
/** Cached calculation results */
handledCPCountPlusOne ,
baseMinusT ,
qMinusT ;
// Convert the input in UCS-2 to Unicode
input = ucs2decode ( input ) ;
// Cache the length
inputLength = input . length ;
// Initialize the state
n = initialN ;
delta = 0 ;
bias = initialBias ;
// Handle the basic code points
for ( j = 0 ; j < inputLength ; ++ j ) {
currentValue = input [ j ] ;
if ( currentValue < 0x80 ) {
output . push ( stringFromCharCode ( currentValue ) ) ;
}
}
handledCPCount = basicLength = output . length ;
// `handledCPCount` is the number of code points that have been handled;
// `basicLength` is the number of basic code points.
// Finish the basic string - if it is not empty - with a delimiter
if ( basicLength ) {
output . push ( delimiter ) ;
}
// Main encoding loop:
while ( handledCPCount < inputLength ) {
// All non-basic code points < n have been handled already. Find the next
// larger one:
for ( m = maxInt , j = 0 ; j < inputLength ; ++ j ) {
currentValue = input [ j ] ;
if ( currentValue >= n && currentValue < m ) {
m = currentValue ;
}
}
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
// but guard against overflow
handledCPCountPlusOne = handledCPCount + 1 ;
if ( m - n > floor ( ( maxInt - delta ) / handledCPCountPlusOne ) ) {
error ( 'overflow' ) ;
}
delta += ( m - n ) * handledCPCountPlusOne ;
n = m ;
for ( j = 0 ; j < inputLength ; ++ j ) {
currentValue = input [ j ] ;
if ( currentValue < n && ++ delta > maxInt ) {
error ( 'overflow' ) ;
}
if ( currentValue == n ) {
// Represent delta as a generalized variable-length integer
for ( q = delta , k = base ; /* no condition */ ; k += base ) {
t = k <= bias ? tMin : ( k >= bias + tMax ? tMax : k - bias ) ;
if ( q < t ) {
break ;
}
qMinusT = q - t ;
baseMinusT = base - t ;
output . push (
stringFromCharCode ( digitToBasic ( t + qMinusT % baseMinusT , 0 ) )
) ;
q = floor ( qMinusT / baseMinusT ) ;
}
output . push ( stringFromCharCode ( digitToBasic ( q , 0 ) ) ) ;
bias = adapt ( delta , handledCPCountPlusOne , handledCPCount == basicLength ) ;
delta = 0 ;
++ handledCPCount ;
}
}
++ delta ;
++ n ;
}
return output . join ( '' ) ;
}
/ * *
* Converts a Punycode string representing a domain name or an email address
* to Unicode . Only the Punycoded parts of the input will be converted , i . e .
* it doesn ' t matter if you call it on a string that has already been
* converted to Unicode .
* @ memberOf punycode
* @ param { String } input The Punycoded domain name or email address to
* convert to Unicode .
* @ returns { String } The Unicode representation of the given Punycode
* string .
* /
function toUnicode ( input ) {
return mapDomain ( input , function ( string ) {
return regexPunycode . test ( string )
? decode ( string . slice ( 4 ) . toLowerCase ( ) )
: string ;
} ) ;
}
/ * *
* Converts a Unicode string representing a domain name or an email address to
* Punycode . Only the non - ASCII parts of the domain name will be converted ,
* i . e . it doesn 't matter if you call it with a domain that' s already in
* ASCII .
* @ memberOf punycode
* @ param { String } input The domain name or email address to convert , as a
* Unicode string .
* @ returns { String } The Punycode representation of the given domain name or
* email address .
* /
function toASCII ( input ) {
return mapDomain ( input , function ( string ) {
return regexNonASCII . test ( string )
? 'xn--' + encode ( string )
: string ;
} ) ;
}
/*--------------------------------------------------------------------------*/
/** Define the public API */
punycode = {
/ * *
* A string representing the current Punycode . js version number .
* @ memberOf punycode
* @ type String
* /
'version' : '1.4.1' ,
/ * *
* An object of methods to convert from JavaScript ' s internal character
* representation ( UCS - 2 ) to Unicode code points , and back .
* @ see < https : //mathiasbynens.be/notes/javascript-encoding>
* @ memberOf punycode
* @ type Object
* /
'ucs2' : {
'decode' : ucs2decode ,
'encode' : ucs2encode
} ,
'decode' : decode ,
'encode' : encode ,
'toASCII' : toASCII ,
'toUnicode' : toUnicode
} ;
/** Expose `punycode` */
// Some AMD build optimizers, like r.js, check for specific condition patterns
// like the following:
if (
typeof define == 'function' &&
typeof define . amd == 'object' &&
define . amd
) {
define ( 'punycode' , function ( ) {
return punycode ;
} ) ;
} else if ( freeExports && freeModule ) {
if ( module . exports == freeExports ) {
// in Node.js, io.js, or RingoJS v0.8.0+
freeModule . exports = punycode ;
} else {
// in Narwhal or RingoJS v0.7.0-
for ( key in punycode ) {
punycode . hasOwnProperty ( key ) && ( freeExports [ key ] = punycode [ key ] ) ;
}
}
} else {
// in Rhino or a web browser
root . punycode = punycode ;
}
} ( this ) ) ;
} ) . call ( this , typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : { } )
2019-12-14 13:50:48 -08:00
} , { } ] , 56 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict' ;
// If obj.hasOwnProperty has been overridden, then calling
// obj.hasOwnProperty(prop) will break.
// See: https://github.com/joyent/node/issues/1707
function hasOwnProperty ( obj , prop ) {
return Object . prototype . hasOwnProperty . call ( obj , prop ) ;
}
module . exports = function ( qs , sep , eq , options ) {
sep = sep || '&' ;
eq = eq || '=' ;
var obj = { } ;
if ( typeof qs !== 'string' || qs . length === 0 ) {
return obj ;
}
var regexp = /\+/g ;
qs = qs . split ( sep ) ;
var maxKeys = 1000 ;
if ( options && typeof options . maxKeys === 'number' ) {
maxKeys = options . maxKeys ;
}
var len = qs . length ;
// maxKeys <= 0 means that we should not limit keys count
if ( maxKeys > 0 && len > maxKeys ) {
len = maxKeys ;
}
for ( var i = 0 ; i < len ; ++ i ) {
var x = qs [ i ] . replace ( regexp , '%20' ) ,
idx = x . indexOf ( eq ) ,
kstr , vstr , k , v ;
if ( idx >= 0 ) {
kstr = x . substr ( 0 , idx ) ;
vstr = x . substr ( idx + 1 ) ;
} else {
kstr = x ;
vstr = '' ;
}
k = decodeURIComponent ( kstr ) ;
v = decodeURIComponent ( vstr ) ;
if ( ! hasOwnProperty ( obj , k ) ) {
obj [ k ] = v ;
} else if ( isArray ( obj [ k ] ) ) {
obj [ k ] . push ( v ) ;
} else {
obj [ k ] = [ obj [ k ] , v ] ;
}
}
return obj ;
} ;
var isArray = Array . isArray || function ( xs ) {
return Object . prototype . toString . call ( xs ) === '[object Array]' ;
} ;
2019-12-14 13:50:48 -08:00
} , { } ] , 57 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict' ;
var stringifyPrimitive = function ( v ) {
switch ( typeof v ) {
case 'string' :
return v ;
case 'boolean' :
return v ? 'true' : 'false' ;
case 'number' :
return isFinite ( v ) ? v : '' ;
default :
return '' ;
}
} ;
module . exports = function ( obj , sep , eq , name ) {
sep = sep || '&' ;
eq = eq || '=' ;
if ( obj === null ) {
obj = undefined ;
}
if ( typeof obj === 'object' ) {
return map ( objectKeys ( obj ) , function ( k ) {
var ks = encodeURIComponent ( stringifyPrimitive ( k ) ) + eq ;
if ( isArray ( obj [ k ] ) ) {
return map ( obj [ k ] , function ( v ) {
return ks + encodeURIComponent ( stringifyPrimitive ( v ) ) ;
} ) . join ( sep ) ;
} else {
return ks + encodeURIComponent ( stringifyPrimitive ( obj [ k ] ) ) ;
}
} ) . join ( sep ) ;
}
if ( ! name ) return '' ;
return encodeURIComponent ( stringifyPrimitive ( name ) ) + eq +
encodeURIComponent ( stringifyPrimitive ( obj ) ) ;
} ;
var isArray = Array . isArray || function ( xs ) {
return Object . prototype . toString . call ( xs ) === '[object Array]' ;
} ;
function map ( xs , f ) {
if ( xs . map ) return xs . map ( f ) ;
var res = [ ] ;
for ( var i = 0 ; i < xs . length ; i ++ ) {
res . push ( f ( xs [ i ] , i ) ) ;
}
return res ;
}
var objectKeys = Object . keys || function ( obj ) {
var res = [ ] ;
for ( var key in obj ) {
if ( Object . prototype . hasOwnProperty . call ( obj , key ) ) res . push ( key ) ;
}
return res ;
} ;
2019-12-14 13:50:48 -08:00
} , { } ] , 58 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
'use strict' ;
exports . decode = exports . parse = require ( './decode' ) ;
exports . encode = exports . stringify = require ( './encode' ) ;
2019-12-14 13:50:48 -08:00
} , { "./decode" : 56 , "./encode" : 57 } ] , 59 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict' ;
var punycode = require ( 'punycode' ) ;
var util = require ( './util' ) ;
exports . parse = urlParse ;
exports . resolve = urlResolve ;
exports . resolveObject = urlResolveObject ;
exports . format = urlFormat ;
exports . Url = Url ;
function Url ( ) {
this . protocol = null ;
this . slashes = null ;
this . auth = null ;
this . host = null ;
this . port = null ;
this . hostname = null ;
this . hash = null ;
this . search = null ;
this . query = null ;
this . pathname = null ;
this . path = null ;
this . href = null ;
}
// Reference: RFC 3986, RFC 1808, RFC 2396
// define these here so at least they only have to be
// compiled once on the first module load.
var protocolPattern = /^([a-z0-9.+-]+:)/i ,
portPattern = /:[0-9]*$/ ,
// Special case for a simple path URL
simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/ ,
// RFC 2396: characters reserved for delimiting URLs.
// We actually just auto-escape these.
delims = [ '<' , '>' , '"' , '`' , ' ' , '\r' , '\n' , '\t' ] ,
// RFC 2396: characters not allowed for various reasons.
unwise = [ '{' , '}' , '|' , '\\' , '^' , '`' ] . concat ( delims ) ,
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
autoEscape = [ '\'' ] . concat ( unwise ) ,
// Characters that are never ever allowed in a hostname.
// Note that any invalid chars are also handled, but these
// are the ones that are *expected* to be seen, so we fast-path
// them.
nonHostChars = [ '%' , '/' , '?' , ';' , '#' ] . concat ( autoEscape ) ,
hostEndingChars = [ '/' , '?' , '#' ] ,
hostnameMaxLen = 255 ,
hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/ ,
hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/ ,
// protocols that can allow "unsafe" and "unwise" chars.
unsafeProtocol = {
'javascript' : true ,
'javascript:' : true
} ,
// protocols that never have a hostname.
hostlessProtocol = {
'javascript' : true ,
'javascript:' : true
} ,
// protocols that always contain a // bit.
slashedProtocol = {
'http' : true ,
'https' : true ,
'ftp' : true ,
'gopher' : true ,
'file' : true ,
'http:' : true ,
'https:' : true ,
'ftp:' : true ,
'gopher:' : true ,
'file:' : true
} ,
querystring = require ( 'querystring' ) ;
function urlParse ( url , parseQueryString , slashesDenoteHost ) {
if ( url && util . isObject ( url ) && url instanceof Url ) return url ;
var u = new Url ;
u . parse ( url , parseQueryString , slashesDenoteHost ) ;
return u ;
}
Url . prototype . parse = function ( url , parseQueryString , slashesDenoteHost ) {
if ( ! util . isString ( url ) ) {
throw new TypeError ( "Parameter 'url' must be a string, not " + typeof url ) ;
}
// Copy chrome, IE, opera backslash-handling behavior.
// Back slashes before the query string get converted to forward slashes
// See: https://code.google.com/p/chromium/issues/detail?id=25916
var queryIndex = url . indexOf ( '?' ) ,
splitter =
( queryIndex !== - 1 && queryIndex < url . indexOf ( '#' ) ) ? '?' : '#' ,
uSplit = url . split ( splitter ) ,
slashRegex = /\\/g ;
uSplit [ 0 ] = uSplit [ 0 ] . replace ( slashRegex , '/' ) ;
url = uSplit . join ( splitter ) ;
var rest = url ;
// trim before proceeding.
// This is to support parse stuff like " http://foo.com \n"
rest = rest . trim ( ) ;
if ( ! slashesDenoteHost && url . split ( '#' ) . length === 1 ) {
// Try fast path regexp
var simplePath = simplePathPattern . exec ( rest ) ;
if ( simplePath ) {
this . path = rest ;
this . href = rest ;
this . pathname = simplePath [ 1 ] ;
if ( simplePath [ 2 ] ) {
this . search = simplePath [ 2 ] ;
if ( parseQueryString ) {
this . query = querystring . parse ( this . search . substr ( 1 ) ) ;
} else {
this . query = this . search . substr ( 1 ) ;
}
} else if ( parseQueryString ) {
this . search = '' ;
this . query = { } ;
}
return this ;
}
}
var proto = protocolPattern . exec ( rest ) ;
if ( proto ) {
proto = proto [ 0 ] ;
var lowerProto = proto . toLowerCase ( ) ;
this . protocol = lowerProto ;
rest = rest . substr ( proto . length ) ;
}
// figure out if it's got a host
// user@server is *always* interpreted as a hostname, and url
// resolution will treat //foo/bar as host=foo,path=bar because that's
// how the browser resolves relative URLs.
if ( slashesDenoteHost || proto || rest . match ( /^\/\/[^@\/]+@[^@\/]+/ ) ) {
var slashes = rest . substr ( 0 , 2 ) === '//' ;
if ( slashes && ! ( proto && hostlessProtocol [ proto ] ) ) {
rest = rest . substr ( 2 ) ;
this . slashes = true ;
}
}
if ( ! hostlessProtocol [ proto ] &&
( slashes || ( proto && ! slashedProtocol [ proto ] ) ) ) {
// there's a hostname.
// the first instance of /, ?, ;, or # ends the host.
//
// If there is an @ in the hostname, then non-host chars *are* allowed
// to the left of the last @ sign, unless some host-ending character
// comes *before* the @-sign.
// URLs are obnoxious.
//
// ex:
// http://a@b@c/ => user:a@b host:c
// http://a@b?@c => user:a host:c path:/?@c
// v0.12 TODO(isaacs): This is not quite how Chrome does things.
// Review our test case against browsers more comprehensively.
// find the first instance of any hostEndingChars
var hostEnd = - 1 ;
for ( var i = 0 ; i < hostEndingChars . length ; i ++ ) {
var hec = rest . indexOf ( hostEndingChars [ i ] ) ;
if ( hec !== - 1 && ( hostEnd === - 1 || hec < hostEnd ) )
hostEnd = hec ;
}
// at this point, either we have an explicit point where the
// auth portion cannot go past, or the last @ char is the decider.
var auth , atSign ;
if ( hostEnd === - 1 ) {
// atSign can be anywhere.
atSign = rest . lastIndexOf ( '@' ) ;
} else {
// atSign must be in auth portion.
// http://a@b/c@d => host:b auth:a path:/c@d
atSign = rest . lastIndexOf ( '@' , hostEnd ) ;
}
// Now we have a portion which is definitely the auth.
// Pull that off.
if ( atSign !== - 1 ) {
auth = rest . slice ( 0 , atSign ) ;
rest = rest . slice ( atSign + 1 ) ;
this . auth = decodeURIComponent ( auth ) ;
}
// the host is the remaining to the left of the first non-host char
hostEnd = - 1 ;
for ( var i = 0 ; i < nonHostChars . length ; i ++ ) {
var hec = rest . indexOf ( nonHostChars [ i ] ) ;
if ( hec !== - 1 && ( hostEnd === - 1 || hec < hostEnd ) )
hostEnd = hec ;
}
// if we still have not hit it, then the entire thing is a host.
if ( hostEnd === - 1 )
hostEnd = rest . length ;
this . host = rest . slice ( 0 , hostEnd ) ;
rest = rest . slice ( hostEnd ) ;
// pull out port.
this . parseHost ( ) ;
// we've indicated that there is a hostname,
// so even if it's empty, it has to be present.
this . hostname = this . hostname || '' ;
// if hostname begins with [ and ends with ]
// assume that it's an IPv6 address.
var ipv6Hostname = this . hostname [ 0 ] === '[' &&
this . hostname [ this . hostname . length - 1 ] === ']' ;
// validate a little.
if ( ! ipv6Hostname ) {
var hostparts = this . hostname . split ( /\./ ) ;
for ( var i = 0 , l = hostparts . length ; i < l ; i ++ ) {
var part = hostparts [ i ] ;
if ( ! part ) continue ;
if ( ! part . match ( hostnamePartPattern ) ) {
var newpart = '' ;
for ( var j = 0 , k = part . length ; j < k ; j ++ ) {
if ( part . charCodeAt ( j ) > 127 ) {
// we replace non-ASCII char with a temporary placeholder
// we need this to make sure size of hostname is not
// broken by replacing non-ASCII by nothing
newpart += 'x' ;
} else {
newpart += part [ j ] ;
}
}
// we test again with ASCII char only
if ( ! newpart . match ( hostnamePartPattern ) ) {
var validParts = hostparts . slice ( 0 , i ) ;
var notHost = hostparts . slice ( i + 1 ) ;
var bit = part . match ( hostnamePartStart ) ;
if ( bit ) {
validParts . push ( bit [ 1 ] ) ;
notHost . unshift ( bit [ 2 ] ) ;
}
if ( notHost . length ) {
rest = '/' + notHost . join ( '.' ) + rest ;
}
this . hostname = validParts . join ( '.' ) ;
break ;
}
}
}
}
if ( this . hostname . length > hostnameMaxLen ) {
this . hostname = '' ;
} else {
// hostnames are always lower case.
this . hostname = this . hostname . toLowerCase ( ) ;
}
if ( ! ipv6Hostname ) {
// IDNA Support: Returns a punycoded representation of "domain".
// It only converts parts of the domain name that
// have non-ASCII characters, i.e. it doesn't matter if
// you call it with a domain that already is ASCII-only.
this . hostname = punycode . toASCII ( this . hostname ) ;
}
var p = this . port ? ':' + this . port : '' ;
var h = this . hostname || '' ;
this . host = h + p ;
this . href += this . host ;
// strip [ and ] from the hostname
// the host field still retains them, though
if ( ipv6Hostname ) {
this . hostname = this . hostname . substr ( 1 , this . hostname . length - 2 ) ;
if ( rest [ 0 ] !== '/' ) {
rest = '/' + rest ;
}
}
}
// now rest is set to the post-host stuff.
// chop off any delim chars.
if ( ! unsafeProtocol [ lowerProto ] ) {
// First, make 100% sure that any "autoEscape" chars get
// escaped, even if encodeURIComponent doesn't think they
// need to be.
for ( var i = 0 , l = autoEscape . length ; i < l ; i ++ ) {
var ae = autoEscape [ i ] ;
if ( rest . indexOf ( ae ) === - 1 )
continue ;
var esc = encodeURIComponent ( ae ) ;
if ( esc === ae ) {
esc = escape ( ae ) ;
}
rest = rest . split ( ae ) . join ( esc ) ;
}
}
// chop off from the tail first.
var hash = rest . indexOf ( '#' ) ;
if ( hash !== - 1 ) {
// got a fragment string.
this . hash = rest . substr ( hash ) ;
rest = rest . slice ( 0 , hash ) ;
}
var qm = rest . indexOf ( '?' ) ;
if ( qm !== - 1 ) {
this . search = rest . substr ( qm ) ;
this . query = rest . substr ( qm + 1 ) ;
if ( parseQueryString ) {
this . query = querystring . parse ( this . query ) ;
}
rest = rest . slice ( 0 , qm ) ;
} else if ( parseQueryString ) {
// no query string, but parseQueryString still requested
this . search = '' ;
this . query = { } ;
}
if ( rest ) this . pathname = rest ;
if ( slashedProtocol [ lowerProto ] &&
this . hostname && ! this . pathname ) {
this . pathname = '/' ;
}
//to support http.request
if ( this . pathname || this . search ) {
var p = this . pathname || '' ;
var s = this . search || '' ;
this . path = p + s ;
}
// finally, reconstruct the href based on what has been validated.
this . href = this . format ( ) ;
return this ;
} ;
// format a parsed object into a url string
function urlFormat ( obj ) {
// ensure it's an object, and not a string url.
// If it's an obj, this is a no-op.
// this way, you can call url_format() on strings
// to clean up potentially wonky urls.
if ( util . isString ( obj ) ) obj = urlParse ( obj ) ;
if ( ! ( obj instanceof Url ) ) return Url . prototype . format . call ( obj ) ;
return obj . format ( ) ;
}
Url . prototype . format = function ( ) {
var auth = this . auth || '' ;
if ( auth ) {
auth = encodeURIComponent ( auth ) ;
auth = auth . replace ( /%3A/i , ':' ) ;
auth += '@' ;
}
var protocol = this . protocol || '' ,
pathname = this . pathname || '' ,
hash = this . hash || '' ,
host = false ,
query = '' ;
if ( this . host ) {
host = auth + this . host ;
} else if ( this . hostname ) {
host = auth + ( this . hostname . indexOf ( ':' ) === - 1 ?
this . hostname :
'[' + this . hostname + ']' ) ;
if ( this . port ) {
host += ':' + this . port ;
}
}
if ( this . query &&
util . isObject ( this . query ) &&
Object . keys ( this . query ) . length ) {
query = querystring . stringify ( this . query ) ;
}
var search = this . search || ( query && ( '?' + query ) ) || '' ;
if ( protocol && protocol . substr ( - 1 ) !== ':' ) protocol += ':' ;
// only the slashedProtocols get the //. Not mailto:, xmpp:, etc.
// unless they had them to begin with.
if ( this . slashes ||
( ! protocol || slashedProtocol [ protocol ] ) && host !== false ) {
host = '//' + ( host || '' ) ;
if ( pathname && pathname . charAt ( 0 ) !== '/' ) pathname = '/' + pathname ;
} else if ( ! host ) {
host = '' ;
}
if ( hash && hash . charAt ( 0 ) !== '#' ) hash = '#' + hash ;
if ( search && search . charAt ( 0 ) !== '?' ) search = '?' + search ;
pathname = pathname . replace ( /[?#]/g , function ( match ) {
return encodeURIComponent ( match ) ;
} ) ;
search = search . replace ( '#' , '%23' ) ;
return protocol + host + pathname + search + hash ;
} ;
function urlResolve ( source , relative ) {
return urlParse ( source , false , true ) . resolve ( relative ) ;
}
Url . prototype . resolve = function ( relative ) {
return this . resolveObject ( urlParse ( relative , false , true ) ) . format ( ) ;
} ;
function urlResolveObject ( source , relative ) {
if ( ! source ) return relative ;
return urlParse ( source , false , true ) . resolveObject ( relative ) ;
}
Url . prototype . resolveObject = function ( relative ) {
if ( util . isString ( relative ) ) {
var rel = new Url ( ) ;
rel . parse ( relative , false , true ) ;
relative = rel ;
}
var result = new Url ( ) ;
var tkeys = Object . keys ( this ) ;
for ( var tk = 0 ; tk < tkeys . length ; tk ++ ) {
var tkey = tkeys [ tk ] ;
result [ tkey ] = this [ tkey ] ;
}
// hash is always overridden, no matter what.
// even href="" will remove it.
result . hash = relative . hash ;
// if the relative url is empty, then there's nothing left to do here.
if ( relative . href === '' ) {
result . href = result . format ( ) ;
return result ;
}
// hrefs like //foo/bar always cut to the protocol.
if ( relative . slashes && ! relative . protocol ) {
// take everything except the protocol from relative
var rkeys = Object . keys ( relative ) ;
for ( var rk = 0 ; rk < rkeys . length ; rk ++ ) {
var rkey = rkeys [ rk ] ;
if ( rkey !== 'protocol' )
result [ rkey ] = relative [ rkey ] ;
}
//urlParse appends trailing / to urls like http://www.example.com
if ( slashedProtocol [ result . protocol ] &&
result . hostname && ! result . pathname ) {
result . path = result . pathname = '/' ;
}
result . href = result . format ( ) ;
return result ;
}
if ( relative . protocol && relative . protocol !== result . protocol ) {
// if it's a known url protocol, then changing
// the protocol does weird things
// first, if it's not file:, then we MUST have a host,
// and if there was a path
// to begin with, then we MUST have a path.
// if it is file:, then the host is dropped,
// because that's known to be hostless.
// anything else is assumed to be absolute.
if ( ! slashedProtocol [ relative . protocol ] ) {
var keys = Object . keys ( relative ) ;
for ( var v = 0 ; v < keys . length ; v ++ ) {
var k = keys [ v ] ;
result [ k ] = relative [ k ] ;
}
result . href = result . format ( ) ;
return result ;
}
result . protocol = relative . protocol ;
if ( ! relative . host && ! hostlessProtocol [ relative . protocol ] ) {
var relPath = ( relative . pathname || '' ) . split ( '/' ) ;
while ( relPath . length && ! ( relative . host = relPath . shift ( ) ) ) ;
if ( ! relative . host ) relative . host = '' ;
if ( ! relative . hostname ) relative . hostname = '' ;
if ( relPath [ 0 ] !== '' ) relPath . unshift ( '' ) ;
if ( relPath . length < 2 ) relPath . unshift ( '' ) ;
result . pathname = relPath . join ( '/' ) ;
} else {
result . pathname = relative . pathname ;
}
result . search = relative . search ;
result . query = relative . query ;
result . host = relative . host || '' ;
result . auth = relative . auth ;
result . hostname = relative . hostname || relative . host ;
result . port = relative . port ;
// to support http.request
if ( result . pathname || result . search ) {
var p = result . pathname || '' ;
var s = result . search || '' ;
result . path = p + s ;
}
result . slashes = result . slashes || relative . slashes ;
result . href = result . format ( ) ;
return result ;
}
var isSourceAbs = ( result . pathname && result . pathname . charAt ( 0 ) === '/' ) ,
isRelAbs = (
relative . host ||
relative . pathname && relative . pathname . charAt ( 0 ) === '/'
) ,
mustEndAbs = ( isRelAbs || isSourceAbs ||
( result . host && relative . pathname ) ) ,
removeAllDots = mustEndAbs ,
srcPath = result . pathname && result . pathname . split ( '/' ) || [ ] ,
relPath = relative . pathname && relative . pathname . split ( '/' ) || [ ] ,
psychotic = result . protocol && ! slashedProtocol [ result . protocol ] ;
// if the url is a non-slashed url, then relative
// links like ../.. should be able
// to crawl up to the hostname, as well. This is strange.
// result.protocol has already been set by now.
// Later on, put the first path part into the host field.
if ( psychotic ) {
result . hostname = '' ;
result . port = null ;
if ( result . host ) {
if ( srcPath [ 0 ] === '' ) srcPath [ 0 ] = result . host ;
else srcPath . unshift ( result . host ) ;
}
result . host = '' ;
if ( relative . protocol ) {
relative . hostname = null ;
relative . port = null ;
if ( relative . host ) {
if ( relPath [ 0 ] === '' ) relPath [ 0 ] = relative . host ;
else relPath . unshift ( relative . host ) ;
}
relative . host = null ;
}
mustEndAbs = mustEndAbs && ( relPath [ 0 ] === '' || srcPath [ 0 ] === '' ) ;
}
if ( isRelAbs ) {
// it's absolute.
result . host = ( relative . host || relative . host === '' ) ?
relative . host : result . host ;
result . hostname = ( relative . hostname || relative . hostname === '' ) ?
relative . hostname : result . hostname ;
result . search = relative . search ;
result . query = relative . query ;
srcPath = relPath ;
// fall through to the dot-handling below.
} else if ( relPath . length ) {
// it's relative
// throw away the existing file, and take the new path instead.
if ( ! srcPath ) srcPath = [ ] ;
srcPath . pop ( ) ;
srcPath = srcPath . concat ( relPath ) ;
result . search = relative . search ;
result . query = relative . query ;
} else if ( ! util . isNullOrUndefined ( relative . search ) ) {
// just pull out the search.
// like href='?foo'.
// Put this after the other two cases because it simplifies the booleans
if ( psychotic ) {
result . hostname = result . host = srcPath . shift ( ) ;
//occationaly the auth can get stuck only in host
//this especially happens in cases like
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
var authInHost = result . host && result . host . indexOf ( '@' ) > 0 ?
result . host . split ( '@' ) : false ;
if ( authInHost ) {
result . auth = authInHost . shift ( ) ;
result . host = result . hostname = authInHost . shift ( ) ;
}
}
result . search = relative . search ;
result . query = relative . query ;
//to support http.request
if ( ! util . isNull ( result . pathname ) || ! util . isNull ( result . search ) ) {
result . path = ( result . pathname ? result . pathname : '' ) +
( result . search ? result . search : '' ) ;
}
result . href = result . format ( ) ;
return result ;
}
if ( ! srcPath . length ) {
// no path at all. easy.
// we've already handled the other stuff above.
result . pathname = null ;
//to support http.request
if ( result . search ) {
result . path = '/' + result . search ;
} else {
result . path = null ;
}
result . href = result . format ( ) ;
return result ;
}
// if a url ENDs in . or .., then it must get a trailing slash.
// however, if it ends in anything else non-slashy,
// then it must NOT get a trailing slash.
var last = srcPath . slice ( - 1 ) [ 0 ] ;
var hasTrailingSlash = (
( result . host || relative . host || srcPath . length > 1 ) &&
( last === '.' || last === '..' ) || last === '' ) ;
// strip single dots, resolve double dots to parent dir
// if the path tries to go above the root, `up` ends up > 0
var up = 0 ;
for ( var i = srcPath . length ; i >= 0 ; i -- ) {
last = srcPath [ i ] ;
if ( last === '.' ) {
srcPath . splice ( i , 1 ) ;
} else if ( last === '..' ) {
srcPath . splice ( i , 1 ) ;
up ++ ;
} else if ( up ) {
srcPath . splice ( i , 1 ) ;
up -- ;
}
}
// if the path is allowed to go above the root, restore leading ..s
if ( ! mustEndAbs && ! removeAllDots ) {
for ( ; up -- ; up ) {
srcPath . unshift ( '..' ) ;
}
}
if ( mustEndAbs && srcPath [ 0 ] !== '' &&
( ! srcPath [ 0 ] || srcPath [ 0 ] . charAt ( 0 ) !== '/' ) ) {
srcPath . unshift ( '' ) ;
}
if ( hasTrailingSlash && ( srcPath . join ( '/' ) . substr ( - 1 ) !== '/' ) ) {
srcPath . push ( '' ) ;
}
var isAbsolute = srcPath [ 0 ] === '' ||
( srcPath [ 0 ] && srcPath [ 0 ] . charAt ( 0 ) === '/' ) ;
// put the host back
if ( psychotic ) {
result . hostname = result . host = isAbsolute ? '' :
srcPath . length ? srcPath . shift ( ) : '' ;
//occationaly the auth can get stuck only in host
//this especially happens in cases like
//url.resolveObject('mailto:local1@domain1', 'local2@domain2')
var authInHost = result . host && result . host . indexOf ( '@' ) > 0 ?
result . host . split ( '@' ) : false ;
if ( authInHost ) {
result . auth = authInHost . shift ( ) ;
result . host = result . hostname = authInHost . shift ( ) ;
}
}
mustEndAbs = mustEndAbs || ( result . host && srcPath . length ) ;
if ( mustEndAbs && ! isAbsolute ) {
srcPath . unshift ( '' ) ;
}
if ( ! srcPath . length ) {
result . pathname = null ;
result . path = null ;
} else {
result . pathname = srcPath . join ( '/' ) ;
}
//to support request.http
if ( ! util . isNull ( result . pathname ) || ! util . isNull ( result . search ) ) {
result . path = ( result . pathname ? result . pathname : '' ) +
( result . search ? result . search : '' ) ;
}
result . auth = relative . auth || result . auth ;
result . slashes = result . slashes || relative . slashes ;
result . href = result . format ( ) ;
return result ;
} ;
Url . prototype . parseHost = function ( ) {
var host = this . host ;
var port = portPattern . exec ( host ) ;
if ( port ) {
port = port [ 0 ] ;
if ( port !== ':' ) {
this . port = port . substr ( 1 ) ;
}
host = host . substr ( 0 , host . length - port . length ) ;
}
if ( host ) this . hostname = host ;
} ;
2019-12-14 13:50:48 -08:00
} , { "./util" : 60 , "punycode" : 55 , "querystring" : 58 } ] , 60 : [ function ( require , module , exports ) {
2019-10-02 20:10:42 -07:00
'use strict' ;
module . exports = {
isString : function ( arg ) {
return typeof ( arg ) === 'string' ;
} ,
isObject : function ( arg ) {
return typeof ( arg ) === 'object' && arg !== null ;
} ,
isNull : function ( arg ) {
return arg === null ;
} ,
isNullOrUndefined : function ( arg ) {
return arg == null ;
}
} ;
} , { } ] } , { } , [ 4 ] ) ( 4 )
} ) ;