2024-01-07 17:22:52 -08:00
/*! markdownlint 0.33.0 https://github.com/DavidAnson/markdownlint @license MIT */
Update dependencies: c8 to 7.7.2, eslint to 7.28.0, eslint-plugin-jsdoc to 35.1.3, eslint-plugin-unicorn to 33.0.1, globby to 11.0.3, js-yaml to 4.1.0, markdown-it-texmath to 0.9.0, markdownlint-rule-helpers to 0.14.0, ts-loader to 9.2.3, typescript to 4.3.2, webpack to 5.38.1, webpack-cli to 4.7.2.
2021-06-08 22:20:13 -07:00
var markdownlint ;
2021-01-05 20:55:09 -08:00
/******/ ( ( ) => { // webpackBootstrap
/******/ var _ _webpack _modules _ _ = ( {
2019-10-02 20:10:42 -07:00
2021-01-06 19:45:15 -08:00
/***/ "../lib sync recursive" :
/ * ! * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / sync * * * !
\ * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module ) => {
function webpackEmptyContext ( req ) {
var e = new Error ( "Cannot find module '" + req + "'" ) ;
e . code = 'MODULE_NOT_FOUND' ;
throw e ;
}
2021-02-06 19:23:55 -08:00
webpackEmptyContext . keys = ( ) => ( [ ] ) ;
2021-01-06 19:45:15 -08:00
webpackEmptyContext . resolve = webpackEmptyContext ;
webpackEmptyContext . id = "../lib sync recursive" ;
module . exports = webpackEmptyContext ;
/***/ } ) ,
/***/ "../helpers/helpers.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / helpers / helpers . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2022-05-04 22:09:11 -07:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const micromark = _ _webpack _require _ _ ( /*! ./micromark.cjs */ "../helpers/micromark.cjs" ) ;
const {
newLineRe ,
nextLinesRe
} = _ _webpack _require _ _ ( /*! ./shared.js */ "../helpers/shared.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports . newLineRe = newLineRe ;
2023-10-18 23:20:19 -07:00
module . exports . nextLinesRe = nextLinesRe ;
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
// Regular expression for matching common front matter (YAML and TOML)
2023-11-05 20:13:12 -08:00
module . exports . frontMatterRe = /((^---\s*$[\s\S]+?^---\s*)|(^\+\+\+\s*$[\s\S]+?^(\+\+\+|\.\.\.)\s*)|(^\{\s*$[\s\S]+?^\}\s*))(\r\n|\r|\n|$)/m ;
2023-01-17 04:19:40 +00:00
2022-02-12 17:46:46 -08:00
// Regular expression for matching the start of inline disable/enable comments
2024-01-06 20:47:01 -08:00
const inlineCommentStartRe = /(<!--\s*markdownlint-(disable|enable|capture|restore|disable-file|enable-file|disable-line|disable-next-line|configure-file))(?:\s|-->)/gi ;
2022-02-12 17:46:46 -08:00
module . exports . inlineCommentStartRe = inlineCommentStartRe ;
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
// Regular expressions for range matching
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+)[.)]/ ;
2023-01-17 04:19:40 +00:00
2022-08-01 18:48:01 -07:00
// Regular expression for blockquote prefixes
2024-01-06 20:47:01 -08:00
const blockquotePrefixRe = /^[>\s]*/ ;
2022-08-01 18:48:01 -07:00
module . exports . blockquotePrefixRe = blockquotePrefixRe ;
2023-01-17 04:19:40 +00:00
2022-06-01 20:23:08 -07:00
// Regular expression for link reference definitions
2024-01-06 20:47:01 -08:00
const linkReferenceDefinitionRe = /^ {0,3}\[([^\]]*[^\\])\]:/ ;
2022-06-01 20:23:08 -07:00
module . exports . linkReferenceDefinitionRe = linkReferenceDefinitionRe ;
2023-01-17 04:19:40 +00:00
2023-06-24 15:45:51 -07:00
// Regular expression for identifying an HTML entity at the end of a line
2023-11-05 20:13:12 -08:00
module . exports . endOfLineHtmlEntityRe = /&(?:#\d+|#[xX][\da-fA-F]+|[a-zA-Z]{2,31}|blk\d{2}|emsp1[34]|frac\d{2}|sup\d|there4);$/ ;
2023-06-24 15:45:51 -07:00
// Regular expression for identifying a GitHub emoji code at the end of a line
2023-11-05 20:13:12 -08:00
module . exports . endOfLineGemojiCodeRe = /:(?:[abmovx]|[-+]1|100|1234|(?:1st|2nd|3rd)_place_medal|8ball|clock\d{1,4}|e-mail|non-potable_water|o2|t-rex|u5272|u5408|u55b6|u6307|u6708|u6709|u6e80|u7121|u7533|u7981|u7a7a|[a-z]{2,15}2?|[a-z]{1,14}(?:_[a-z\d]{1,16})+):$/ ;
2023-06-24 15:45:51 -07:00
2019-10-02 20:10:42 -07:00
// All punctuation characters (normal and full-width)
2024-01-06 20:47:01 -08:00
const allPunctuation = ".,;:!?。,;:!?" ;
2020-11-24 16:37:11 -08:00
module . exports . allPunctuation = allPunctuation ;
2023-01-17 04:19:40 +00:00
2020-11-24 16:37:11 -08:00
// All punctuation characters without question mark (normal and full-width)
2024-01-06 20:47:01 -08:00
module . exports . allPunctuationNoQuestion = allPunctuation . replace ( /[?? ]/gu , "" ) ;
2023-01-17 04:19:40 +00:00
2023-07-12 21:58:36 -07:00
/ * *
* Returns true iff the input is a Number .
*
* @ param { Object } obj Object of unknown type .
* @ returns { boolean } True iff obj is a Number .
* /
function isNumber ( obj ) {
2023-01-17 04:19:40 +00:00
return typeof obj === "number" ;
2023-07-12 21:58:36 -07:00
}
module . exports . isNumber = isNumber ;
2023-01-17 04:19:40 +00:00
2023-07-12 21:58:36 -07:00
/ * *
* Returns true iff the input is a String .
*
* @ param { Object } obj Object of unknown type .
* @ returns { boolean } True iff obj is a String .
* /
function isString ( obj ) {
2023-01-17 04:19:40 +00:00
return typeof obj === "string" ;
2023-07-12 21:58:36 -07:00
}
module . exports . isString = isString ;
2023-01-17 04:19:40 +00:00
2023-07-12 21:58:36 -07:00
/ * *
* Returns true iff the input String is empty .
*
* @ param { string } str String of unknown length .
* @ returns { boolean } True iff the input String is empty .
* /
function isEmptyString ( str ) {
2023-01-17 04:19:40 +00:00
return str . length === 0 ;
2023-07-12 21:58:36 -07:00
}
module . exports . isEmptyString = isEmptyString ;
2023-01-17 04:19:40 +00:00
2023-07-12 21:58:36 -07:00
/ * *
* Returns true iff the input is an Object .
*
* @ param { Object } obj Object of unknown type .
* @ returns { boolean } True iff obj is an Object .
* /
function isObject ( obj ) {
2024-01-06 20:47:01 -08:00
return ! ! obj && typeof obj === "object" && ! Array . isArray ( obj ) ;
2023-07-12 21:58:36 -07:00
}
module . exports . isObject = isObject ;
2023-07-11 21:44:45 -07:00
2023-07-12 21:58:36 -07:00
/ * *
* Returns true iff the input is a URL .
*
* @ param { Object } obj Object of unknown type .
* @ returns { boolean } True iff obj is a URL .
* /
function isUrl ( obj ) {
2023-07-11 21:44:45 -07:00
return ! ! obj && Object . getPrototypeOf ( obj ) === URL . prototype ;
2023-07-12 21:58:36 -07:00
}
module . exports . isUrl = isUrl ;
/ * *
* Clones the input if it is an Array .
*
* @ param { Object } arr Object of unknown type .
* @ returns { Object } Clone of obj iff obj is an Array .
* /
function cloneIfArray ( arr ) {
2024-01-06 20:47:01 -08:00
return Array . isArray ( arr ) ? [ ... arr ] : arr ;
2023-07-12 21:58:36 -07:00
}
module . exports . cloneIfArray = cloneIfArray ;
/ * *
* Clones the input if it is a URL .
*
* @ param { Object } url Object of unknown type .
* @ returns { Object } Clone of obj iff obj is a URL .
* /
function cloneIfUrl ( url ) {
return isUrl ( url ) ? new URL ( url ) : url ;
}
module . exports . cloneIfUrl = cloneIfUrl ;
2023-01-17 04:19:40 +00:00
2023-10-18 23:45:39 -07:00
/ * *
* Gets a Regular Expression for matching the specified HTML attribute .
*
* @ param { string } name HTML attribute name .
* @ returns { RegExp } Regular Expression for matching .
* /
module . exports . getHtmlAttributeRe = function getHtmlAttributeRe ( name ) {
2024-01-06 20:47:01 -08:00
return new RegExp ( ` \\ s ${ name } \\ s*= \\ s*['"]?([^'" \\ s>]*) ` , "iu" ) ;
2023-10-18 23:45:39 -07:00
} ;
2022-02-11 21:54:43 -08:00
/ * *
* Returns true iff the input line is blank ( contains nothing , whitespace , or
* comments ( unclosed start / end comments allowed ) ) .
*
* @ param { string } line Input line .
* @ returns { boolean } True iff line is blank .
* /
function isBlankLine ( line ) {
2024-01-06 20:47:01 -08:00
const startComment = "<!--" ;
const endComment = "-->" ;
const removeComments = s => {
2023-01-17 04:19:40 +00:00
// eslint-disable-next-line no-constant-condition
while ( true ) {
2024-01-06 20:47:01 -08:00
const start = s . indexOf ( startComment ) ;
const end = s . indexOf ( endComment ) ;
2023-01-17 04:19:40 +00:00
if ( end !== - 1 && ( start === - 1 || end < start ) ) {
// Unmatched end comment is first
s = s . slice ( end + endComment . length ) ;
} else if ( start !== - 1 && end !== - 1 ) {
// Start comment is before end comment
s = s . slice ( 0 , start ) + s . slice ( end + endComment . length ) ;
} else if ( start !== - 1 && end === - 1 ) {
// Unmatched start comment is last
s = s . slice ( 0 , start ) ;
} else {
// No more comments to remove
return s ;
}
}
} ;
return ! line || ! line . trim ( ) || ! removeComments ( line ) . replace ( />/g , "" ) . trim ( ) ;
2022-02-11 21:54:43 -08:00
}
module . exports . isBlankLine = isBlankLine ;
2023-01-17 04:19:40 +00:00
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 ) {
2023-01-17 04:19:40 +00:00
return a - b ;
2020-01-27 19:19:34 -08:00
} ;
2023-01-17 04:19:40 +00:00
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 ) {
2024-01-06 20:47:01 -08:00
let left = 0 ;
let right = array . length - 1 ;
2023-01-17 04:19:40 +00:00
while ( left <= right ) {
// eslint-disable-next-line no-bitwise
2024-01-06 20:47:01 -08:00
const mid = left + right >> 1 ;
2023-01-17 04:19:40 +00:00
if ( array [ mid ] < element ) {
left = mid + 1 ;
} else if ( array [ mid ] > element ) {
right = mid - 1 ;
} else {
return true ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
return false ;
2019-10-02 20:10:42 -07:00
} ;
2023-01-17 04:19:40 +00:00
2021-01-30 14:36:11 -08:00
// Replaces the content of properly-formatted CommonMark comments with "."
2019-10-02 20:10:42 -07:00
// This preserves the line/column information for the rest of the document
2021-01-30 13:08:57 -08:00
// https://spec.commonmark.org/0.29/#html-blocks
// https://spec.commonmark.org/0.29/#html-comment
2024-01-06 20:47:01 -08:00
const htmlCommentBegin = "<!--" ;
const htmlCommentEnd = "-->" ;
const safeCommentCharacter = "." ;
const startsWithPipeRe = /^ *\|/ ;
const notCrLfRe = /[^\r\n]/g ;
const notSpaceCrLfRe = /[^ \r\n]/g ;
const trailingSpaceRe = / +[\r\n]/g ;
const replaceTrailingSpace = s => s . replace ( notCrLfRe , safeCommentCharacter ) ;
2019-10-02 20:10:42 -07:00
module . exports . clearHtmlCommentText = function clearHtmlCommentText ( text ) {
2024-01-06 20:47:01 -08:00
let i = 0 ;
2023-01-17 04:19:40 +00:00
while ( ( i = text . indexOf ( htmlCommentBegin , i ) ) !== - 1 ) {
2024-01-06 20:47:01 -08:00
const j = text . indexOf ( htmlCommentEnd , i + 2 ) ;
2023-01-17 04:19:40 +00:00
if ( j === - 1 ) {
// Un-terminated comments are treated as text
break ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
// If the comment has content...
if ( j > i + htmlCommentBegin . length ) {
2024-01-06 20:47:01 -08:00
const content = text . slice ( i + htmlCommentBegin . length , j ) ;
const lastLf = text . lastIndexOf ( "\n" , i ) + 1 ;
const preText = text . slice ( lastLf , i ) ;
const isBlock = preText . trim ( ) . length === 0 ;
const couldBeTable = startsWithPipeRe . test ( preText ) ;
const spansTableCells = couldBeTable && content . includes ( "\n" ) ;
const isValid = isBlock || ! ( spansTableCells || content . startsWith ( ">" ) || content . startsWith ( "->" ) || content . endsWith ( "-" ) || content . includes ( "--" ) ) ;
2023-01-17 04:19:40 +00:00
// If a valid block/inline comment...
if ( isValid ) {
2024-01-06 20:47:01 -08:00
const clearedContent = content . replace ( notSpaceCrLfRe , safeCommentCharacter ) . replace ( trailingSpaceRe , replaceTrailingSpace ) ;
2023-01-17 04:19:40 +00:00
text = text . slice ( 0 , i + htmlCommentBegin . length ) + clearedContent + text . slice ( j ) ;
}
}
i = j + htmlCommentEnd . length ;
}
return text ;
2019-10-02 20:10:42 -07:00
} ;
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
// Escapes a string for use in a RegExp
module . exports . escapeForRegExp = function escapeForRegExp ( str ) {
2023-01-17 04:19:40 +00:00
return str . replace ( /[-/\\^$*+?.()|[\]{}]/g , "\\$&" ) ;
2019-10-02 20:10:42 -07:00
} ;
2023-01-17 04:19:40 +00:00
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 .
* /
2023-01-17 04:19:40 +00:00
module . exports . fencedCodeBlockStyleFor = function fencedCodeBlockStyleFor ( markup ) {
switch ( markup [ 0 ] ) {
case "~" :
return "tilde" ;
default :
return "backtick" ;
}
} ;
2021-10-21 06:42:48 +02:00
/ * *
* Return the string representation of a emphasis or strong markup character .
*
* @ param { string } markup Emphasis or strong string .
* @ returns { string } String representation .
* /
2023-01-17 04:19:40 +00:00
module . exports . emphasisOrStrongStyleFor = function emphasisOrStrongStyleFor ( markup ) {
switch ( markup [ 0 ] ) {
case "*" :
return "asterisk" ;
default :
return "underscore" ;
}
} ;
2020-01-27 19:19:34 -08:00
/ * *
* 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 ) {
2024-01-06 20:47:01 -08:00
const line = token . line . replace ( /^[\s>]*(> |>)/ , "" ) ;
2023-01-17 04:19:40 +00:00
return line . length - line . trimStart ( ) . length ;
2019-10-02 20:10:42 -07:00
}
module . exports . indentFor = indentFor ;
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
// Returns the heading style for a heading token
module . exports . headingStyleFor = function headingStyleFor ( token ) {
2023-01-17 04:19:40 +00:00
if ( token . map [ 1 ] - token . map [ 0 ] === 1 ) {
if ( /[^\\]#\s*$/ . test ( token . line ) ) {
return "atx_closed" ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
return "atx" ;
}
return "setext" ;
2019-10-02 20:10:42 -07:00
} ;
2023-01-17 04:19:40 +00:00
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 ) {
2023-01-17 04:19:40 +00:00
switch ( token . markup ) {
case "-" :
return "dash" ;
case "+" :
return "plus" ;
// case "*":
default :
return "asterisk" ;
}
2020-01-27 19:19:34 -08:00
} ;
2023-01-17 04:19:40 +00:00
2023-09-04 21:41:16 -07:00
/ * *
* @ callback TokenCallback
* @ param { MarkdownItToken } token Current token .
* @ returns { void }
* /
2020-01-27 19:19:34 -08:00
/ * *
* Calls the provided function for each matching token .
*
* @ param { Object } params RuleParams instance .
* @ param { string } type Token type identifier .
2023-09-04 21:41:16 -07:00
* @ param { TokenCallback } handler Callback function .
2020-01-27 19:19:34 -08:00
* @ returns { void }
* /
2019-10-02 20:10:42 -07:00
function filterTokens ( params , type , handler ) {
2024-01-06 20:47:01 -08:00
for ( const token of params . parsers . markdownit . tokens ) {
if ( token . type === type ) {
handler ( token ) ;
2022-06-07 22:59:48 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
}
module . exports . filterTokens = filterTokens ;
2023-01-17 04:19:40 +00:00
2023-09-04 21:41:16 -07:00
/ * *
* @ typedef { Array } LineMetadata
* /
/ * *
* Gets a line metadata array .
*
* @ param { Object } params RuleParams instance .
* @ returns { LineMetadata } Line metadata .
* /
function getLineMetadata ( params ) {
2024-01-06 20:47:01 -08:00
const lineMetadata = params . lines . map ( ( line , index ) => [ line , index , false , 0 , false , false , false ] ) ;
filterTokens ( params , "fence" , token => {
2023-01-17 04:19:40 +00:00
lineMetadata [ token . map [ 0 ] ] [ 3 ] = 1 ;
lineMetadata [ token . map [ 1 ] - 1 ] [ 3 ] = - 1 ;
2024-01-06 20:47:01 -08:00
for ( let i = token . map [ 0 ] + 1 ; i < token . map [ 1 ] - 1 ; i ++ ) {
2023-01-17 04:19:40 +00:00
lineMetadata [ i ] [ 2 ] = true ;
}
} ) ;
2024-01-06 20:47:01 -08:00
filterTokens ( params , "code_block" , token => {
for ( let i = token . map [ 0 ] ; i < token . map [ 1 ] ; i ++ ) {
2023-01-17 04:19:40 +00:00
lineMetadata [ i ] [ 2 ] = true ;
2022-06-08 22:10:27 -07:00
}
2023-01-17 04:19:40 +00:00
} ) ;
2024-01-06 20:47:01 -08:00
filterTokens ( params , "table_open" , token => {
for ( let i = token . map [ 0 ] ; i < token . map [ 1 ] ; i ++ ) {
2023-01-17 04:19:40 +00:00
lineMetadata [ i ] [ 4 ] = true ;
}
} ) ;
2024-01-06 20:47:01 -08:00
filterTokens ( params , "list_item_open" , token => {
let count = 1 ;
for ( let i = token . map [ 0 ] ; i < token . map [ 1 ] ; i ++ ) {
2023-01-17 04:19:40 +00:00
lineMetadata [ i ] [ 5 ] = count ;
count ++ ;
}
} ) ;
2024-01-06 20:47:01 -08:00
filterTokens ( params , "hr" , token => {
2023-01-17 04:19:40 +00:00
lineMetadata [ token . map [ 0 ] ] [ 6 ] = true ;
} ) ;
return lineMetadata ;
2023-09-04 21:41:16 -07:00
}
module . exports . getLineMetadata = getLineMetadata ;
/ * *
* @ callback EachLineCallback
* @ param { string } line Line content .
* @ param { number } lineIndex Line index ( 0 - based ) .
* @ param { boolean } inCode Iff in a code block .
* @ param { number } onFence + if open , - if closed , 0 otherwise .
* @ param { boolean } inTable Iff in a table .
* @ param { boolean } inItem Iff in a list item .
* @ param { boolean } inBreak Iff in semantic break .
* @ returns { void }
* /
2023-01-17 04:19:40 +00:00
2021-11-23 04:40:05 +00:00
/ * *
* Calls the provided function for each line .
*
2023-09-04 21:41:16 -07:00
* @ param { LineMetadata } lineMetadata Line metadata object .
* @ param { EachLineCallback } handler Function taking ( line , lineIndex , inCode ,
* onFence , inTable , inItem , inBreak ) .
2021-11-23 04:40:05 +00:00
* @ returns { void }
* /
function forEachLine ( lineMetadata , handler ) {
2024-01-06 20:47:01 -08:00
for ( const metadata of lineMetadata ) {
// @ts-ignore
handler ( ... metadata ) ;
2023-01-17 04:19:40 +00:00
}
2021-11-23 04:40:05 +00:00
}
module . exports . forEachLine = forEachLine ;
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
// Returns (nested) lists as a flat array (in order)
2021-06-17 22:01:27 -07:00
module . exports . flattenLists = function flattenLists ( tokens ) {
2024-01-06 20:47:01 -08:00
const flattenedLists = [ ] ;
const stack = [ ] ;
let current = null ;
let nesting = 0 ;
const nestingStack = [ ] ;
let lastWithMap = {
2023-01-17 04:19:40 +00:00
"map" : [ 0 , 1 ]
} ;
2024-01-06 20:47:01 -08:00
for ( const token of tokens ) {
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" : [ ] ,
"nesting" : nesting ,
"lastLineIndex" : - 1 ,
"insert" : flattenedLists . length
} ;
nesting ++ ;
} 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 ( ) ;
nesting -- ;
} else if ( token . type === "list_item_open" ) {
// Add list item
current . items . push ( token ) ;
} else if ( token . type === "blockquote_open" ) {
nestingStack . push ( nesting ) ;
nesting = 0 ;
} else if ( token . type === "blockquote_close" ) {
nesting = nestingStack . pop ( ) || 0 ;
}
if ( token . map ) {
// Track last token with map
lastWithMap = token ;
2022-06-08 22:10:27 -07:00
}
2023-01-17 04:19:40 +00:00
}
return flattenedLists ;
2019-10-02 20:10:42 -07:00
} ;
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
// Calls the provided function for each heading's content
module . exports . forEachHeading = function forEachHeading ( params , handler ) {
2024-01-06 20:47:01 -08:00
let heading = null ;
for ( const token of params . parsers . markdownit . tokens ) {
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 , token ) ;
2022-06-08 22:10:27 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2023-01-17 04:19:40 +00:00
2023-09-04 21:41:16 -07:00
/ * *
* @ callback InlineCodeSpanCallback
* @ param { string } code Code content .
* @ param { number } lineIndex Line index ( 0 - based ) .
* @ param { number } columnIndex Column index ( 0 - based ) .
* @ param { number } ticks Count of backticks .
* @ returns { void }
* /
2020-04-25 21:15:13 -07:00
/ * *
* Calls the provided function for each inline code span ' s content .
*
* @ param { string } input Markdown content .
2023-09-04 21:41:16 -07:00
* @ param { InlineCodeSpanCallback } handler Callback function taking ( code ,
* lineIndex , columnIndex , ticks ) .
2020-04-25 21:15:13 -07:00
* @ returns { void }
* /
function forEachInlineCodeSpan ( input , handler ) {
2024-01-06 20:47:01 -08:00
const backtickRe = /`+/g ;
let match = null ;
const backticksLengthAndIndex = [ ] ;
2023-01-17 04:19:40 +00:00
while ( ( match = backtickRe . exec ( input ) ) !== null ) {
backticksLengthAndIndex . push ( [ match [ 0 ] . length , match . index ] ) ;
}
2024-01-06 20:47:01 -08:00
const newLinesIndex = [ ] ;
2023-01-17 04:19:40 +00:00
while ( ( match = newLineRe . exec ( input ) ) !== null ) {
newLinesIndex . push ( match . index ) ;
}
2024-01-06 20:47:01 -08:00
let lineIndex = 0 ;
let lineStartIndex = 0 ;
let k = 0 ;
for ( let i = 0 ; i < backticksLengthAndIndex . length - 1 ; i ++ ) {
const [ startLength , startIndex ] = backticksLengthAndIndex [ i ] ;
2023-01-17 04:19:40 +00:00
if ( startIndex === 0 || input [ startIndex - 1 ] !== "\\" ) {
2024-01-06 20:47:01 -08:00
for ( let j = i + 1 ; j < backticksLengthAndIndex . length ; j ++ ) {
const [ endLength , endIndex ] = backticksLengthAndIndex [ j ] ;
2023-01-17 04:19:40 +00:00
if ( startLength === endLength ) {
for ( ; k < newLinesIndex . length ; k ++ ) {
2024-01-06 20:47:01 -08:00
const newLineIndex = newLinesIndex [ k ] ;
2023-01-17 04:19:40 +00:00
if ( startIndex < newLineIndex ) {
break ;
2020-04-25 21:15:13 -07:00
}
2023-01-17 04:19:40 +00:00
lineIndex ++ ;
lineStartIndex = newLineIndex + 1 ;
}
2024-01-06 20:47:01 -08:00
const columnIndex = startIndex - lineStartIndex + startLength ;
2023-01-17 04:19:40 +00:00
handler ( input . slice ( startIndex + startLength , endIndex ) , lineIndex , columnIndex , startLength ) ;
i = j ;
break ;
}
}
2020-04-25 21:15:13 -07:00
}
2023-01-17 04:19:40 +00:00
}
2020-04-25 21:15:13 -07:00
}
module . exports . forEachInlineCodeSpan = forEachInlineCodeSpan ;
2023-01-17 04:19:40 +00:00
2022-06-01 20:23:08 -07:00
/ * *
* Adds ellipsis to the left / right / middle of the specified text .
*
* @ param { string } text Text to ellipsify .
* @ param { boolean } [ start ] True iff the start of the text is important .
* @ param { boolean } [ end ] True iff the end of the text is important .
* @ returns { string } Ellipsified text .
* /
function ellipsify ( text , start , end ) {
2023-01-17 04:19:40 +00:00
if ( text . length <= 30 ) {
// Nothing to do
} else if ( start && end ) {
text = text . slice ( 0 , 15 ) + "..." + text . slice ( - 15 ) ;
} else if ( end ) {
text = "..." + text . slice ( - 30 ) ;
} else {
text = text . slice ( 0 , 30 ) + "..." ;
}
return text ;
2022-06-01 20:23:08 -07:00
}
module . exports . ellipsify = ellipsify ;
2023-01-17 04:19:40 +00:00
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 ) {
2023-01-17 04:19:40 +00:00
onError ( {
2024-01-06 20:47:01 -08:00
lineNumber ,
detail ,
context ,
range ,
fixInfo
2023-01-17 04:19:40 +00:00
} ) ;
2019-10-02 20:10:42 -07:00
}
module . exports . addError = addError ;
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
// Adds an error object with details conditionally via the onError callback
module . exports . addErrorDetailIf = function addErrorDetailIf ( onError , lineNumber , expected , actual , detail , context , range , fixInfo ) {
2023-01-17 04:19:40 +00:00
if ( expected !== actual ) {
addError ( onError , lineNumber , "Expected: " + expected + "; Actual: " + actual + ( detail ? "; " + detail : "" ) , context , range , fixInfo ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
// Adds an error object with context via the onError callback
module . exports . addErrorContext = function addErrorContext ( onError , lineNumber , context , left , right , range , fixInfo ) {
2023-01-17 04:19:40 +00:00
context = ellipsify ( context , left , right ) ;
addError ( onError , lineNumber , undefined , context , range , fixInfo ) ;
2019-10-02 20:10:42 -07:00
} ;
2023-01-17 04:19:40 +00:00
2021-06-17 21:50:03 -07:00
/ * *
2021-11-23 04:40:05 +00:00
* Returns an array of code block and span content ranges .
2021-06-17 21:50:03 -07:00
*
2021-11-23 04:40:05 +00:00
* @ param { Object } params RuleParams instance .
* @ param { Object } lineMetadata Line metadata object .
* @ returns { number [ ] [ ] } Array of ranges ( lineIndex , columnIndex , length ) .
2021-06-17 21:50:03 -07:00
* /
2024-01-06 20:47:01 -08:00
module . exports . codeBlockAndSpanRanges = ( params , lineMetadata ) => {
const exclusions = [ ] ;
2023-01-17 04:19:40 +00:00
// Add code block ranges (excludes fences)
2024-01-06 20:47:01 -08:00
forEachLine ( lineMetadata , ( line , lineIndex , inCode , onFence ) => {
2023-01-17 04:19:40 +00:00
if ( inCode && ! onFence ) {
exclusions . push ( [ lineIndex , 0 , line . length ] ) ;
}
} ) ;
// Add code span ranges (excludes ticks)
2024-01-06 20:47:01 -08:00
filterTokens ( params , "inline" , token => {
if ( token . children . some ( child => child . type === "code_inline" ) ) {
const tokenLines = params . lines . slice ( token . map [ 0 ] , token . map [ 1 ] ) ;
forEachInlineCodeSpan ( tokenLines . join ( "\n" ) , ( code , lineIndex , columnIndex ) => {
const codeLines = code . split ( newLineRe ) ;
for ( const [ i , line ] of codeLines . entries ( ) ) {
exclusions . push ( [ token . lineNumber - 1 + lineIndex + i , i ? 0 : columnIndex , line . length ] ) ;
2023-01-17 04:19:40 +00:00
}
} ) ;
}
} ) ;
return exclusions ;
2021-06-17 21:50:03 -07:00
} ;
2023-01-17 04:19:40 +00:00
2022-06-01 20:23:08 -07:00
/ * *
* Determines whether the specified range is within another range .
*
* @ param { number [ ] [ ] } ranges Array of ranges ( line , index , length ) .
* @ param { number } lineIndex Line index to check .
* @ param { number } index Index to check .
* @ param { number } length Length to check .
* @ returns { boolean } True iff the specified range is within .
* /
2024-01-06 20:47:01 -08:00
const withinAnyRange = ( ranges , lineIndex , index , length ) => ! ranges . every ( span => lineIndex !== span [ 0 ] || index < span [ 1 ] || index + length > span [ 1 ] + span [ 2 ] ) ;
2022-06-02 22:17:32 -07:00
module . exports . withinAnyRange = withinAnyRange ;
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
// Returns a range object for a line by applying a RegExp
module . exports . rangeFromRegExp = function rangeFromRegExp ( line , regexp ) {
2024-01-06 20:47:01 -08:00
let range = null ;
const match = line . match ( regexp ) ;
2023-01-17 04:19:40 +00:00
if ( match ) {
2024-01-06 20:47:01 -08:00
const column = match . index + 1 ;
const length = match [ 0 ] . length ;
2023-01-17 04:19:40 +00:00
range = [ column , length ] ;
}
return range ;
2019-10-02 20:10:42 -07:00
} ;
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
// Determines if the front matter includes a title
2023-01-17 04:19:40 +00:00
module . exports . frontMatterHasTitle = function frontMatterHasTitle ( frontMatterLines , frontMatterTitlePattern ) {
2024-01-06 20:47:01 -08:00
const ignoreFrontMatter = frontMatterTitlePattern !== undefined && ! frontMatterTitlePattern ;
const frontMatterTitleRe = new RegExp ( String ( frontMatterTitlePattern || "^\\s*\"?title\"?\\s*[:=]" ) , "i" ) ;
return ! ignoreFrontMatter && frontMatterLines . some ( line => frontMatterTitleRe . test ( line ) ) ;
2023-01-17 04:19:40 +00:00
} ;
2022-06-01 20:23:08 -07:00
/ * *
* Returns an object with information about reference links and images .
*
2023-01-29 20:36:53 -08:00
* @ param { Object } params RuleParams instance .
2022-06-01 20:23:08 -07:00
* @ returns { Object } Reference link / image data .
* /
2023-01-29 20:36:53 -08:00
function getReferenceLinkImageData ( params ) {
2024-01-06 20:47:01 -08:00
const normalizeReference = s => s . toLowerCase ( ) . trim ( ) . replace ( /\s+/g , " " ) ;
const definitions = new Map ( ) ;
const definitionLineIndices = [ ] ;
const duplicateDefinitions = [ ] ;
const references = new Map ( ) ;
const shortcuts = new Map ( ) ;
const filteredTokens = micromark . filterByTypes ( params . parsers . micromark . tokens , [
2023-01-29 20:36:53 -08:00
// definitionLineIndices
"definition" , "gfmFootnoteDefinition" ,
// definitions and definitionLineIndices
"definitionLabelString" , "gfmFootnoteDefinitionLabelString" ,
// references and shortcuts
2023-02-05 16:58:06 -08:00
"gfmFootnoteCall" , "image" , "link" ] ) ;
2024-01-06 20:47:01 -08:00
for ( const token of filteredTokens ) {
let labelPrefix = "" ;
// eslint-disable-next-line default-case
switch ( token . type ) {
case "definition" :
case "gfmFootnoteDefinition" :
// definitionLineIndices
for ( let i = token . startLine ; i <= token . endLine ; i ++ ) {
definitionLineIndices . push ( i - 1 ) ;
}
break ;
case "gfmFootnoteDefinitionLabelString" :
labelPrefix = "^" ;
case "definitionLabelString" :
// eslint-disable-line no-fallthrough
{
// definitions and definitionLineIndices
const reference = normalizeReference ( ` ${ labelPrefix } ${ token . text } ` ) ;
if ( definitions . has ( reference ) ) {
duplicateDefinitions . push ( [ reference , token . startLine - 1 ] ) ;
} else {
let destinationString = null ;
const parent = micromark . getTokenParentOfType ( token , [ "definition" ] ) ;
if ( parent ) {
destinationString = micromark . getTokenTextByType ( micromark . filterByPredicate ( parent . children ) , "definitionDestinationString" ) ;
2023-01-29 20:36:53 -08:00
}
2024-01-06 20:47:01 -08:00
definitions . set ( reference , [ token . startLine - 1 , destinationString ] ) ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
}
break ;
case "gfmFootnoteCall" :
case "image" :
case "link" :
{
let isShortcut = false ;
let isFullOrCollapsed = false ;
let labelText = null ;
let referenceStringText = null ;
const shortcutCandidate = micromark . matchAndGetTokensByType ( token . children , [ "label" ] ) ;
if ( shortcutCandidate ) {
labelText = micromark . getTokenTextByType ( shortcutCandidate [ 0 ] . children , "labelText" ) ;
isShortcut = labelText !== null ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
const fullAndCollapsedCandidate = micromark . matchAndGetTokensByType ( token . children , [ "label" , "reference" ] ) ;
if ( fullAndCollapsedCandidate ) {
labelText = micromark . getTokenTextByType ( fullAndCollapsedCandidate [ 0 ] . children , "labelText" ) ;
referenceStringText = micromark . getTokenTextByType ( fullAndCollapsedCandidate [ 1 ] . children , "referenceString" ) ;
isFullOrCollapsed = labelText !== null ;
}
const footnote = micromark . matchAndGetTokensByType ( token . children , [ "gfmFootnoteCallLabelMarker" , "gfmFootnoteCallMarker" , "gfmFootnoteCallString" , "gfmFootnoteCallLabelMarker" ] , [ "gfmFootnoteCallMarker" , "gfmFootnoteCallString" ] ) ;
if ( footnote ) {
const callMarkerText = footnote [ 0 ] . text ;
const callString = footnote [ 1 ] . text ;
labelText = ` ${ callMarkerText } ${ callString } ` ;
isShortcut = true ;
}
// Track shortcuts separately due to ambiguity in "text [text] text"
if ( isShortcut || isFullOrCollapsed ) {
const referenceDatum = [ token . startLine - 1 , token . startColumn - 1 , token . text . length ,
// @ts-ignore
labelText . length , ( referenceStringText || "" ) . length ] ;
const reference = normalizeReference ( referenceStringText || labelText ) ;
const dictionary = isShortcut ? shortcuts : references ;
const referenceData = dictionary . get ( reference ) || [ ] ;
referenceData . push ( referenceDatum ) ;
dictionary . set ( reference , referenceData ) ;
}
}
break ;
2022-06-01 20:23:08 -07:00
}
2023-01-17 04:19:40 +00:00
}
return {
2024-01-06 20:47:01 -08:00
references ,
shortcuts ,
definitions ,
duplicateDefinitions ,
definitionLineIndices
2023-01-17 04:19:40 +00:00
} ;
2022-06-01 20:23:08 -07:00
}
module . exports . getReferenceLinkImageData = getReferenceLinkImageData ;
2023-01-17 04:19:40 +00:00
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 .
2022-05-06 21:04:34 -07:00
* @ param { Object } [ os ] Node . js "os" module .
2020-01-27 19:19:34 -08:00
* @ returns { string } Preferred line ending .
* /
2022-05-06 21:04:34 -07:00
function getPreferredLineEnding ( input , os ) {
2024-01-06 20:47:01 -08:00
let cr = 0 ;
let lf = 0 ;
let crlf = 0 ;
const endings = input . match ( newLineRe ) || [ ] ;
for ( const ending of endings ) {
// eslint-disable-next-line default-case
switch ( ending ) {
case "\r" :
cr ++ ;
break ;
case "\n" :
lf ++ ;
break ;
case "\r\n" :
crlf ++ ;
break ;
2022-06-08 22:10:27 -07:00
}
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
let preferredLineEnding = null ;
2023-01-17 04:19:40 +00:00
if ( ! cr && ! lf && ! crlf ) {
preferredLineEnding = os && os . EOL || "\n" ;
} else if ( lf >= crlf && lf >= cr ) {
preferredLineEnding = "\n" ;
} else if ( crlf >= cr ) {
preferredLineEnding = "\r\n" ;
} else {
preferredLineEnding = "\r" ;
}
return preferredLineEnding ;
2019-10-02 20:10:42 -07:00
}
module . exports . getPreferredLineEnding = getPreferredLineEnding ;
2023-01-17 04:19:40 +00:00
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 ) {
2023-01-17 04:19:40 +00:00
return {
"lineNumber" : fixInfo . lineNumber || lineNumber ,
"editColumn" : fixInfo . editColumn || 1 ,
"deleteCount" : fixInfo . deleteCount || 0 ,
"insertText" : fixInfo . insertText || ""
} ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
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 .
2022-02-09 22:44:49 -08:00
* @ param { string } [ lineEnding ] Line ending to use .
2022-06-12 17:51:47 -07:00
* @ returns { string | null } Fixed content .
2020-01-27 19:19:34 -08:00
* /
2019-10-02 20:10:42 -07:00
function applyFix ( line , fixInfo , lineEnding ) {
2024-01-06 20:47:01 -08:00
const {
editColumn ,
deleteCount ,
insertText
} = normalizeFixInfo ( fixInfo ) ;
const editIndex = editColumn - 1 ;
2023-01-17 04:19:40 +00:00
return deleteCount === - 1 ? null : line . slice ( 0 , editIndex ) + insertText . replace ( /\n/g , lineEnding || "\n" ) + line . slice ( editIndex + deleteCount ) ;
2019-10-02 20:10:42 -07:00
}
module . exports . applyFix = applyFix ;
2023-01-17 04:19:40 +00:00
2022-02-09 22:44:49 -08:00
/ * *
* Applies as many fixes as possible to Markdown content .
*
* @ param { string } input Lines of Markdown content .
* @ param { Object [ ] } errors RuleOnErrorInfo instances .
* @ returns { string } Corrected content .
* /
2022-05-05 23:14:18 -07:00
function applyFixes ( input , errors ) {
2024-01-06 20:47:01 -08:00
const lineEnding = getPreferredLineEnding ( input , _ _webpack _require _ _ ( /*! node:os */ "?0176" ) ) ;
const lines = input . split ( newLineRe ) ;
2023-01-17 04:19:40 +00:00
// Normalize fixInfo objects
2024-01-06 20:47:01 -08:00
let fixInfos = errors . filter ( error => error . fixInfo ) . map ( error => normalizeFixInfo ( error . fixInfo , error . lineNumber ) ) ;
2023-01-17 04:19:40 +00:00
// Sort bottom-to-top, line-deletes last, right-to-left, long-to-short
2024-01-06 20:47:01 -08:00
fixInfos . sort ( ( a , b ) => {
const aDeletingLine = a . deleteCount === - 1 ;
const bDeletingLine = b . deleteCount === - 1 ;
2023-01-17 04:19:40 +00:00
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)
2024-01-06 20:47:01 -08:00
let lastFixInfo = { } ;
fixInfos = fixInfos . filter ( fixInfo => {
const unique = fixInfo . lineNumber !== lastFixInfo . lineNumber || fixInfo . editColumn !== lastFixInfo . editColumn || fixInfo . deleteCount !== lastFixInfo . deleteCount || fixInfo . insertText !== lastFixInfo . insertText ;
2023-01-17 04:19:40 +00:00
lastFixInfo = fixInfo ;
return unique ;
} ) ;
// Collapse insert/no-delete and no-insert/delete for same line/column
lastFixInfo = {
"lineNumber" : - 1
} ;
2024-01-06 20:47:01 -08:00
for ( const fixInfo of fixInfos ) {
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 ;
2022-06-08 22:10:27 -07:00
}
2024-01-06 20:47:01 -08:00
lastFixInfo = fixInfo ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
fixInfos = fixInfos . filter ( fixInfo => fixInfo . lineNumber ) ;
2023-01-17 04:19:40 +00:00
// Apply all (remaining/updated) fixes
2024-01-06 20:47:01 -08:00
let lastLineIndex = - 1 ;
let lastEditIndex = - 1 ;
for ( const fixInfo of fixInfos ) {
const {
lineNumber ,
editColumn ,
deleteCount
} = fixInfo ;
const lineIndex = lineNumber - 1 ;
const editIndex = editColumn - 1 ;
if ( lineIndex !== lastLineIndex || deleteCount === - 1 || editIndex + deleteCount <= lastEditIndex - ( deleteCount > 0 ? 0 : 1 ) ) {
// @ts-ignore
lines [ lineIndex ] = applyFix ( lines [ lineIndex ] , fixInfo , lineEnding ) ;
2022-06-08 22:10:27 -07:00
}
2024-01-06 20:47:01 -08:00
lastLineIndex = lineIndex ;
lastEditIndex = editIndex ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
// Return corrected input
return lines . filter ( line => line !== null ) . join ( lineEnding ) ;
2022-02-09 22:44:49 -08:00
}
module . exports . applyFixes = applyFixes ;
2023-01-17 04:19:40 +00:00
2022-05-16 22:57:11 -07:00
/ * *
* Expands a path with a tilde to an absolute path .
*
* @ param { string } file Path that may begin with a tilde .
* @ param { Object } os Node . js "os" module .
* @ returns { string } Absolute path ( or original path ) .
* /
function expandTildePath ( file , os ) {
2024-01-06 20:47:01 -08:00
const homedir = os && os . homedir && os . homedir ( ) ;
return homedir ? file . replace ( /^~($|\/|\\)/ , ` ${ homedir } $ 1 ` ) : file ;
2022-05-16 22:57:11 -07:00
}
module . exports . expandTildePath = expandTildePath ;
2023-01-17 04:19:40 +00:00
2023-09-04 21:41:16 -07:00
// Copied from markdownlint.js to avoid TypeScript compiler import() issue.
/ * *
* @ typedef { Object } MarkdownItToken
* @ property { string [ ] [ ] } attrs HTML attributes .
* @ property { boolean } block Block - level token .
* @ property { MarkdownItToken [ ] } children Child nodes .
* @ property { string } content Tag contents .
* @ property { boolean } hidden Ignore element .
* @ property { string } info Fence info .
* @ property { number } level Nesting level .
* @ property { number [ ] } map Beginning / ending line numbers .
* @ property { string } markup Markup text .
* @ property { Object } meta Arbitrary data .
* @ property { number } nesting Level change .
* @ property { string } tag HTML tag name .
* @ property { string } type Token type .
* @ property { number } lineNumber Line number ( 1 - based ) .
* @ property { string } line Line content .
* /
2022-04-21 21:09:07 -07:00
/***/ } ) ,
2023-07-21 22:49:08 -07:00
/***/ "../helpers/shared.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / helpers / shared . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module ) => {
"use strict" ;
// @ts-check
// Regular expression for matching common newline characters
// See NEWLINES_RE in markdown-it/lib/rules_core/normalize.js
module . exports . newLineRe = /\r\n?|\n/g ;
2023-10-18 23:20:19 -07:00
// Regular expression for matching next lines
module . exports . nextLinesRe = /[\r\n][\s\S]*$/ ;
2023-07-21 22:49:08 -07:00
/***/ } ) ,
2022-04-21 21:09:07 -07:00
/***/ "markdown-it" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * external "markdownit" * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module ) => {
"use strict" ;
module . exports = markdownit ;
/***/ } ) ,
2023-02-08 20:50:28 -08:00
/***/ "markdownlint-micromark" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * external "micromarkBrowser" * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module ) => {
"use strict" ;
module . exports = micromarkBrowser ;
/***/ } ) ,
2022-08-16 04:01:53 +00:00
/***/ "?0176" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * node : os ( ignored ) * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * /
2022-05-04 22:09:11 -07:00
/***/ ( ( ) => {
/* (ignored) */
/***/ } ) ,
2022-08-16 04:01:53 +00:00
/***/ "?d0ee" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * node : fs ( ignored ) * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * /
2022-04-21 21:09:07 -07:00
/***/ ( ( ) => {
/* (ignored) */
/***/ } ) ,
2022-08-16 04:01:53 +00:00
/***/ "?e6c4" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * node : os ( ignored ) * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * /
2022-05-16 22:57:11 -07:00
/***/ ( ( ) => {
/* (ignored) */
/***/ } ) ,
2022-08-16 04:01:53 +00:00
/***/ "?9a52" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * node : path ( ignored ) * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2022-04-21 21:09:07 -07:00
/***/ ( ( ) => {
/* (ignored) */
/***/ } ) ,
2022-08-16 04:01:53 +00:00
/***/ "?39e5" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * node : util ( ignored ) * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2022-04-21 21:09:07 -07:00
/***/ ( ( ) => {
/* (ignored) */
2022-12-29 00:43:53 +00:00
/***/ } ) ,
/***/ "./markdownlint-exports.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . / markdownlint - exports . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
"use strict" ;
// @ts-check
2023-01-17 04:19:40 +00:00
2022-12-29 00:43:53 +00:00
module . exports = {
2023-01-17 04:19:40 +00:00
"library" : _ _webpack _require _ _ ( /*! .. */ "../lib/markdownlint.js" ) ,
"helpers" : _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" )
2022-12-29 00:43:53 +00:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2023-01-20 04:10:18 +00:00
/***/ "../helpers/micromark.cjs" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / helpers / micromark . cjs * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
"use strict" ;
// @ts-check
// @ts-ignore
2024-01-06 20:47:01 -08:00
const {
directive ,
gfmAutolinkLiteral ,
gfmFootnote ,
gfmTable ,
math ,
parse ,
postprocess ,
preprocess
// @ts-ignore
} = _ _webpack _require _ _ ( /*! markdownlint-micromark */ "markdownlint-micromark" ) ;
const {
newLineRe
} = _ _webpack _require _ _ ( /*! ./shared.js */ "../helpers/shared.js" ) ;
const flatTokensSymbol = Symbol ( "flat-tokens" ) ;
2023-01-20 04:10:18 +00:00
/ * *
* Markdown token .
*
* @ typedef { Object } Token
* @ property { string } type Token type .
* @ property { number } startLine Start line ( 1 - based ) .
* @ property { number } startColumn Start column ( 1 - based ) .
* @ property { number } endLine End line ( 1 - based ) .
* @ property { number } endColumn End column ( 1 - based ) .
* @ property { string } text Token text .
2023-02-25 15:42:28 -08:00
* @ property { Token [ ] } children Child tokens .
2023-10-19 23:01:31 -07:00
* @ property { Token | null } parent Parent token .
2023-01-20 04:10:18 +00:00
* /
2023-09-02 12:07:14 -07:00
/ * *
* Returns whether a token is an htmlFlow type containing an HTML comment .
*
* @ param { Token } token Micromark token .
* @ returns { boolean } True iff token is htmlFlow containing a comment .
* /
function isHtmlFlowComment ( token ) {
2024-01-06 20:47:01 -08:00
const {
text ,
type
} = token ;
2023-09-02 12:07:14 -07:00
if ( type === "htmlFlow" && text . startsWith ( "<!--" ) && text . endsWith ( "-->" ) ) {
2024-01-06 20:47:01 -08:00
const comment = text . slice ( 4 , - 3 ) ;
2023-10-07 20:18:43 -07:00
return ! comment . startsWith ( ">" ) && ! comment . startsWith ( "->" ) && ! comment . endsWith ( "-" )
// The following condition from the CommonMark specification is commented
// to avoid parsing HTML comments that include "--" because that is NOT a
// condition of the HTML specification.
// https://spec.commonmark.org/0.30/#raw-html
// https://html.spec.whatwg.org/multipage/syntax.html#comments
// && !comment.includes("--")
;
2023-09-02 12:07:14 -07:00
}
return false ;
}
2023-01-20 04:10:18 +00:00
/ * *
2023-02-10 20:37:32 -08:00
* Parses a Markdown document and returns Micromark events .
2023-01-20 04:10:18 +00:00
*
* @ param { string } markdown Markdown document .
2023-07-21 22:49:08 -07:00
* @ param { Object } [ micromarkOptions ] Options for micromark .
* @ param { boolean } [ referencesDefined ] Treat references as defined .
2023-02-10 20:37:32 -08:00
* @ returns { Object [ ] } Micromark events .
2023-01-20 04:10:18 +00:00
* /
2023-02-10 20:37:32 -08:00
function getMicromarkEvents ( markdown ) {
2024-01-06 20:47:01 -08:00
let micromarkOptions = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : { } ;
let referencesDefined = arguments . length > 2 && arguments [ 2 ] !== undefined ? arguments [ 2 ] : true ;
2023-01-29 20:36:53 -08:00
// Customize options object to add useful extensions
2023-07-21 22:49:08 -07:00
micromarkOptions . extensions = micromarkOptions . extensions || [ ] ;
2024-01-01 22:12:42 -08:00
micromarkOptions . extensions . push ( directive ( ) , gfmAutolinkLiteral ( ) , gfmFootnote ( ) , gfmTable ( ) , math ( ) ) ;
2023-01-29 20:36:53 -08:00
2023-01-20 04:10:18 +00:00
// Use micromark to parse document into Events
2024-01-06 20:47:01 -08:00
const encoding = undefined ;
const eol = true ;
const parseContext = parse ( micromarkOptions ) ;
2023-07-21 22:49:08 -07:00
if ( referencesDefined ) {
2023-05-23 04:01:55 +00:00
// Customize ParseContext to treat all references as defined
2024-01-06 20:47:01 -08:00
parseContext . defined . includes = searchElement => searchElement . length > 0 ;
2023-05-23 04:01:55 +00:00
}
2024-01-06 20:47:01 -08:00
const chunks = preprocess ( ) ( markdown , encoding , eol ) ;
const events = postprocess ( parseContext . document ( ) . write ( chunks ) ) ;
2023-02-10 20:37:32 -08:00
return events ;
}
/ * *
* Parses a Markdown document and returns ( frozen ) tokens .
*
* @ param { string } markdown Markdown document .
2023-07-21 22:49:08 -07:00
* @ param { Object } micromarkOptions Options for micromark .
* @ param { boolean } referencesDefined Treat references as defined .
* @ param { number } lineDelta Offset to apply to start / end line .
2023-10-19 23:01:31 -07:00
* @ param { Token } [ ancestor ] Parent of top - most tokens .
2023-02-10 20:37:32 -08:00
* @ returns { Token [ ] } Micromark tokens ( frozen ) .
* /
2023-10-19 23:01:31 -07:00
function micromarkParseWithOffset ( markdown , micromarkOptions , referencesDefined , lineDelta , ancestor ) {
2023-02-10 20:37:32 -08:00
// Use micromark to parse document into Events
2024-01-06 20:47:01 -08:00
const events = getMicromarkEvents ( markdown , micromarkOptions , referencesDefined ) ;
2023-01-20 04:10:18 +00:00
// Create Token objects
2024-01-06 20:47:01 -08:00
const document = [ ] ;
let flatTokens = [ ] ;
2023-10-19 23:01:31 -07:00
/** @type {Token} */
2024-01-06 20:47:01 -08:00
const root = {
2023-10-19 23:01:31 -07:00
"type" : "ROOT" ,
"startLine" : - 1 ,
"startColumn" : - 1 ,
"endLine" : - 1 ,
"endColumn" : - 1 ,
"text" : "ROOT" ,
"children" : document ,
"parent" : null
2023-01-20 04:10:18 +00:00
} ;
2024-01-06 20:47:01 -08:00
const history = [ root ] ;
let current = root ;
let reparseOptions = null ;
let lines = null ;
let skipHtmlFlowChildren = false ;
for ( const event of events ) {
const [ kind , token , context ] = event ;
const {
type ,
start ,
end
} = token ;
const {
"column" : startColumn ,
"line" : startLine
} = start ;
const {
"column" : endColumn ,
"line" : endLine
} = end ;
const text = context . sliceSerialize ( token ) ;
if ( kind === "enter" && ! skipHtmlFlowChildren ) {
const previous = current ;
history . push ( previous ) ;
current = {
type ,
"startLine" : startLine + lineDelta ,
startColumn ,
"endLine" : endLine + lineDelta ,
endColumn ,
text ,
"children" : [ ] ,
"parent" : previous === root ? ancestor || null : previous
} ;
previous . children . push ( current ) ;
flatTokens . push ( current ) ;
if ( current . type === "htmlFlow" && ! isHtmlFlowComment ( current ) ) {
skipHtmlFlowChildren = true ;
if ( ! reparseOptions || ! lines ) {
reparseOptions = {
... micromarkOptions ,
"extensions" : [ {
"disable" : {
"null" : [ "codeIndented" , "htmlFlow" ]
}
} ]
} ;
lines = markdown . split ( newLineRe ) ;
2023-09-02 12:07:14 -07:00
}
2024-01-06 20:47:01 -08:00
const reparseMarkdown = lines . slice ( current . startLine - 1 , current . endLine ) . join ( "\n" ) ;
const tokens = micromarkParseWithOffset ( reparseMarkdown , reparseOptions , referencesDefined , current . startLine - 1 , current ) ;
current . children = tokens ;
// Avoid stack overflow of Array.push(...spread)
// eslint-disable-next-line unicorn/prefer-spread
flatTokens = flatTokens . concat ( tokens [ flatTokensSymbol ] ) ;
}
} else if ( kind === "exit" ) {
if ( type === "htmlFlow" ) {
skipHtmlFlowChildren = false ;
}
if ( ! skipHtmlFlowChildren ) {
Object . freeze ( current . children ) ;
Object . freeze ( current ) ;
// @ts-ignore
current = history . pop ( ) ;
2023-01-20 04:10:18 +00:00
}
}
}
2024-01-06 20:47:01 -08:00
// Return document
2023-08-28 22:00:43 -07:00
Object . defineProperty ( document , flatTokensSymbol , {
"value" : flatTokens
} ) ;
2023-01-20 04:10:18 +00:00
Object . freeze ( document ) ;
return document ;
}
2023-01-21 15:41:03 -08:00
2023-07-21 22:49:08 -07:00
/ * *
* Parses a Markdown document and returns ( frozen ) tokens .
*
* @ param { string } markdown Markdown document .
* @ param { Object } [ micromarkOptions ] Options for micromark .
* @ param { boolean } [ referencesDefined ] Treat references as defined .
* @ returns { Token [ ] } Micromark tokens ( frozen ) .
* /
function micromarkParse ( markdown ) {
2024-01-06 20:47:01 -08:00
let micromarkOptions = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : { } ;
let referencesDefined = arguments . length > 2 && arguments [ 2 ] !== undefined ? arguments [ 2 ] : true ;
2023-07-21 22:49:08 -07:00
return micromarkParseWithOffset ( markdown , micromarkOptions , referencesDefined , 0 ) ;
}
2023-09-04 21:41:16 -07:00
/ * *
* @ callback AllowedPredicate
* @ param { Token } token Micromark token .
* @ returns { boolean } True iff allowed .
* /
/ * *
* @ callback TransformPredicate
* @ param { Token } token Micromark token .
* @ returns { Token [ ] } Child tokens .
* /
2023-01-21 15:41:03 -08:00
/ * *
* Filter a list of Micromark tokens by predicate .
*
* @ param { Token [ ] } tokens Micromark tokens .
2023-10-25 20:05:19 -07:00
* @ param { AllowedPredicate } [ allowed ] Allowed token predicate .
2023-09-04 21:41:16 -07:00
* @ param { TransformPredicate } [ transformChildren ] Transform predicate .
2023-01-21 15:41:03 -08:00
* @ returns { Token [ ] } Filtered tokens .
* /
2023-03-14 21:03:07 -07:00
function filterByPredicate ( tokens , allowed , transformChildren ) {
2024-01-06 20:47:01 -08:00
allowed = allowed || ( ( ) => true ) ;
const result = [ ] ;
const queue = [ {
2023-09-02 21:30:43 -07:00
"array" : tokens ,
"index" : 0
} ] ;
while ( queue . length > 0 ) {
2024-01-06 20:47:01 -08:00
const current = queue [ queue . length - 1 ] ;
const {
array ,
index
} = current ;
2023-09-02 21:30:43 -07:00
if ( index < array . length ) {
2024-01-06 20:47:01 -08:00
const token = array [ current . index ++ ] ;
2023-09-02 21:30:43 -07:00
if ( allowed ( token ) ) {
result . push ( token ) ;
}
2024-01-06 20:47:01 -08:00
const {
children
} = token ;
2023-09-02 21:30:43 -07:00
if ( children . length > 0 ) {
2024-01-06 20:47:01 -08:00
const transformed = transformChildren ? transformChildren ( token ) : children ;
2023-09-02 21:30:43 -07:00
queue . push ( {
"array" : transformed ,
"index" : 0
} ) ;
}
} else {
queue . pop ( ) ;
2023-03-10 22:22:54 -08:00
}
2023-01-21 15:41:03 -08:00
}
return result ;
}
/ * *
* Filter a list of Micromark tokens by type .
*
* @ param { Token [ ] } tokens Micromark tokens .
2023-10-21 22:03:11 -07:00
* @ param { string [ ] } types Types to allow .
2023-01-21 15:41:03 -08:00
* @ returns { Token [ ] } Filtered tokens .
* /
2023-10-21 22:03:11 -07:00
function filterByTypes ( tokens , types ) {
2024-01-06 20:47:01 -08:00
const predicate = token => types . includes ( token . type ) ;
const flatTokens = tokens [ flatTokensSymbol ] ;
2023-08-28 22:00:43 -07:00
if ( flatTokens ) {
return flatTokens . filter ( predicate ) ;
}
return filterByPredicate ( tokens , predicate ) ;
2023-01-21 15:41:03 -08:00
}
2023-01-29 20:36:53 -08:00
2023-08-08 22:56:47 -07:00
/ * *
* Gets the heading level of a Micromark heading tokan .
*
* @ param { Token } heading Micromark heading token .
* @ returns { number } Heading level .
* /
function getHeadingLevel ( heading ) {
2024-01-06 20:47:01 -08:00
const headingSequence = filterByTypes ( heading . children , [ "atxHeadingSequence" , "setextHeadingLineSequence" ] ) ;
let level = 1 ;
const {
text
} = headingSequence [ 0 ] ;
2023-08-08 22:56:47 -07:00
if ( text [ 0 ] === "#" ) {
level = Math . min ( text . length , 6 ) ;
} else if ( text [ 0 ] === "-" ) {
level = 2 ;
}
return level ;
}
2023-02-05 16:58:06 -08:00
/ * *
* Gets information about the tag in an HTML token .
*
* @ param { Token } token Micromark token .
* @ returns { Object | null } HTML tag information .
* /
function getHtmlTagInfo ( token ) {
2024-01-06 20:47:01 -08:00
const htmlTagNameRe = /^<([^!>][^/\s>]*)/ ;
2023-02-05 16:58:06 -08:00
if ( token . type === "htmlText" ) {
2024-01-06 20:47:01 -08:00
const match = htmlTagNameRe . exec ( token . text ) ;
2023-02-05 16:58:06 -08:00
if ( match ) {
2024-01-06 20:47:01 -08:00
const name = match [ 1 ] ;
const close = name . startsWith ( "/" ) ;
2023-02-05 16:58:06 -08:00
return {
2024-01-06 20:47:01 -08:00
close ,
2023-02-05 16:58:06 -08:00
"name" : close ? name . slice ( 1 ) : name
} ;
}
}
return null ;
}
2023-10-21 22:03:11 -07:00
/ * *
* Gets the nearest parent of the specified type for a Micromark token .
*
* @ param { Token } token Micromark token .
* @ param { string [ ] } types Types to allow .
* @ returns { Token | null } Parent token .
* /
function getTokenParentOfType ( token , types ) {
/** @type {Token | null} */
2024-01-06 20:47:01 -08:00
let current = token ;
2023-10-21 22:03:11 -07:00
while ( ( current = current . parent ) && ! types . includes ( current . type ) ) {
// Empty
}
return current ;
}
2023-01-29 20:36:53 -08:00
/ * *
2023-10-25 20:05:19 -07:00
* Get the text of the first match from a list of Micromark tokens by type .
2023-01-29 20:36:53 -08:00
*
* @ param { Token [ ] } tokens Micromark tokens .
* @ param { string } type Types to match .
* @ returns { string | null } Text of token .
* /
function getTokenTextByType ( tokens , type ) {
2024-01-06 20:47:01 -08:00
const filtered = tokens . filter ( token => token . type === type ) ;
2023-10-25 20:05:19 -07:00
return filtered . length > 0 ? filtered [ 0 ] . text : null ;
2023-01-29 20:36:53 -08:00
}
2023-10-21 22:03:11 -07:00
/ * *
* Determines if a Micromark token has an htmlFlow - type parent .
*
* @ param { Token } token Micromark token .
* @ returns { boolean } True iff the token has an htmlFlow - type parent .
* /
function inHtmlFlow ( token ) {
return getTokenParentOfType ( token , [ "htmlFlow" ] ) !== null ;
}
2023-01-29 20:36:53 -08:00
/ * *
* Determines a list of Micromark tokens matches and returns a subset .
*
* @ param { Token [ ] } tokens Micromark tokens .
* @ param { string [ ] } matchTypes Types to match .
* @ param { string [ ] } [ resultTypes ] Types to return .
2023-02-23 22:14:44 -08:00
* @ returns { Token [ ] | null } Matching tokens .
2023-01-29 20:36:53 -08:00
* /
function matchAndGetTokensByType ( tokens , matchTypes , resultTypes ) {
if ( tokens . length !== matchTypes . length ) {
return null ;
}
2023-02-25 16:24:24 -08:00
resultTypes = resultTypes || matchTypes ;
2024-01-06 20:47:01 -08:00
const result = [ ] ;
2023-02-23 22:14:44 -08:00
// eslint-disable-next-line unicorn/no-for-loop
2024-01-06 20:47:01 -08:00
for ( let i = 0 ; i < matchTypes . length ; i ++ ) {
2023-01-29 20:36:53 -08:00
if ( tokens [ i ] . type !== matchTypes [ i ] ) {
return null ;
} else if ( resultTypes . includes ( matchTypes [ i ] ) ) {
2023-02-23 22:14:44 -08:00
result . push ( tokens [ i ] ) ;
2023-01-29 20:36:53 -08:00
}
}
return result ;
}
2023-05-25 03:47:34 +00:00
/ * *
* Returns the specified token iff it is of the desired type .
*
* @ param { Token } token Micromark token candidate .
* @ param { string } type Desired type .
* @ returns { Token | null } Token instance .
* /
function tokenIfType ( token , type ) {
return token && token . type === type ? token : null ;
}
2023-01-20 04:10:18 +00:00
module . exports = {
2023-02-05 16:58:06 -08:00
"parse" : micromarkParse ,
2024-01-06 20:47:01 -08:00
filterByPredicate ,
filterByTypes ,
getHeadingLevel ,
getHtmlTagInfo ,
getMicromarkEvents ,
getTokenParentOfType ,
getTokenTextByType ,
inHtmlFlow ,
matchAndGetTokensByType ,
tokenIfType
2023-01-20 04:10:18 +00:00
} ;
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/cache.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / cache . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2019-10-02 20:10:42 -07:00
2021-01-05 20:55:09 -08:00
2024-01-06 20:47:01 -08:00
const map = new Map ( ) ;
module . exports . set = keyValuePairs => {
for ( const [ key , value ] of Object . entries ( keyValuePairs ) ) {
2023-01-17 04:19:40 +00:00
map . set ( key , value ) ;
}
} ;
2024-01-06 20:47:01 -08:00
module . exports . clear = ( ) => map . clear ( ) ;
module . exports . codeBlockAndSpanRanges = ( ) => map . get ( "codeBlockAndSpanRanges" ) ;
module . exports . flattenedLists = ( ) => map . get ( "flattenedLists" ) ;
module . exports . lineMetadata = ( ) => map . get ( "lineMetadata" ) ;
module . exports . referenceLinkImageData = ( ) => map . get ( "referenceLinkImageData" ) ;
2023-01-17 04:19:40 +00:00
2021-11-10 21:48:15 -08:00
/***/ } ) ,
/***/ "../lib/constants.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / constants . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module ) => {
"use strict" ;
// @ts-check
2023-01-17 04:19:40 +00:00
2023-11-09 19:47:15 -08:00
module . exports . deprecatedRuleNames = [ ] ;
module . exports . fixableRuleNames = [ "MD004" , "MD005" , "MD007" , "MD009" , "MD010" , "MD011" , "MD012" , "MD014" , "MD018" , "MD019" , "MD020" , "MD021" , "MD022" , "MD023" , "MD026" , "MD027" , "MD030" , "MD031" , "MD032" , "MD034" , "MD037" , "MD038" , "MD039" , "MD044" , "MD047" , "MD049" , "MD050" , "MD051" , "MD053" , "MD054" ] ;
2021-11-10 21:48:15 -08:00
module . exports . homepage = "https://github.com/DavidAnson/markdownlint" ;
2024-01-07 17:22:52 -08:00
module . exports . version = "0.33.0" ;
2021-11-10 21:48:15 -08:00
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/markdownlint.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / markdownlint . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2022-06-02 21:42:48 -07:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2021-01-05 20:55:09 -08:00
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const path = _ _webpack _require _ _ ( /*! node:path */ "?9a52" ) ;
const {
promisify
} = _ _webpack _require _ _ ( /*! node:util */ "?39e5" ) ;
const markdownit = _ _webpack _require _ _ ( /*! markdown-it */ "markdown-it" ) ;
const micromark = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
2023-11-09 19:47:15 -08:00
// const { deprecatedRuleNames } = require("./constants");
2024-01-06 20:47:01 -08:00
const rules = _ _webpack _require _ _ ( /*! ./rules */ "../lib/rules.js" ) ;
const helpers = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const cache = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
2023-01-17 04:19:40 +00:00
2021-02-11 22:16:07 -08:00
// @ts-ignore
2023-11-05 20:13:12 -08:00
// eslint-disable-next-line camelcase, no-inline-comments, no-undef
2024-01-06 20:47:01 -08:00
const dynamicRequire = typeof require === "undefined" ? _ _webpack _require _ _ ( "../lib sync recursive" ) : /* c8 ignore next */ require ;
2021-02-11 22:16:07 -08:00
// Capture native require implementation for dynamic loading of modules
2023-01-17 04:19:40 +00:00
2020-01-27 19:19:34 -08:00
/ * *
* Validate the list of rules for structure and reuse .
*
* @ param { Rule [ ] } ruleList List of rules .
2021-12-11 21:44:25 -08:00
* @ param { boolean } synchronous Whether to execute synchronously .
2022-06-11 22:40:45 -07:00
* @ returns { Error | null } Error message if validation fails .
2020-01-27 19:19:34 -08:00
* /
2021-12-11 21:44:25 -08:00
function validateRuleList ( ruleList , synchronous ) {
2024-01-06 20:47:01 -08:00
let result = null ;
2023-01-17 04:19:40 +00:00
if ( ruleList . length === rules . length ) {
// No need to validate if only using built-in rules
return result ;
}
2024-01-06 20:47:01 -08:00
const allIds = { } ;
for ( const [ index , rule ] of ruleList . entries ( ) ) {
const customIndex = index - rules . length ;
// eslint-disable-next-line no-inner-declarations, jsdoc/require-jsdoc
function newError ( property ) {
return new Error ( "Property '" + property + "' of custom rule at index " + customIndex + " is incorrect." ) ;
}
for ( const property of [ "names" , "tags" ] ) {
const value = rule [ property ] ;
if ( ! result && ( ! value || ! Array . isArray ( value ) || value . length === 0 || ! value . every ( helpers . isString ) || value . some ( helpers . isEmptyString ) ) ) {
result = newError ( property ) ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
}
for ( const propertyInfo of [ [ "description" , "string" ] , [ "function" , "function" ] ] ) {
const property = propertyInfo [ 0 ] ;
const value = rule [ property ] ;
if ( ! result && ( ! value || typeof value !== propertyInfo [ 1 ] ) ) {
result = newError ( property ) ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
}
if ( ! result && rule . information && ! helpers . isUrl ( rule . information ) ) {
result = newError ( "information" ) ;
}
if ( ! result && rule . asynchronous !== undefined && typeof rule . asynchronous !== "boolean" ) {
result = newError ( "asynchronous" ) ;
}
if ( ! result && rule . asynchronous && synchronous ) {
result = new Error ( "Custom rule " + rule . names . join ( "/" ) + " at index " + customIndex + " is asynchronous and can not be used in a synchronous context." ) ;
}
if ( ! result ) {
for ( const name of rule . names ) {
const 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." ) ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
allIds [ nameUpper ] = true ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
for ( const tag of rule . tags ) {
const tagUpper = tag . toUpperCase ( ) ;
if ( ! result && allIds [ tagUpper ] ) {
result = new Error ( "Tag '" + tag + "' of custom rule at index " + customIndex + " is already used as a name." ) ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
allIds [ tagUpper ] = false ;
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
return result ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
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 ) {
2024-01-06 20:47:01 -08:00
const lintResults = { } ;
2023-01-17 04:19:40 +00:00
// eslint-disable-next-line jsdoc/require-jsdoc
function toString ( useAlias ) {
2024-01-06 20:47:01 -08:00
let ruleNameToRule = null ;
const results = [ ] ;
const keys = Object . keys ( lintResults ) ;
2023-01-17 04:19:40 +00:00
keys . sort ( ) ;
2024-01-06 20:47:01 -08:00
for ( const file of keys ) {
const fileResults = lintResults [ file ] ;
2023-01-17 04:19:40 +00:00
if ( Array . isArray ( fileResults ) ) {
2024-01-06 20:47:01 -08:00
for ( const result of fileResults ) {
const 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 + "\"]" : "" ) ) ;
2023-01-17 04:19:40 +00:00
}
} else {
if ( ! ruleNameToRule ) {
ruleNameToRule = { } ;
2024-01-06 20:47:01 -08:00
for ( const rule of ruleList ) {
const ruleName = rule . names [ 0 ] . toUpperCase ( ) ;
ruleNameToRule [ ruleName ] = rule ;
2023-01-17 04:19:40 +00:00
}
}
2024-01-06 20:47:01 -08:00
for ( const [ ruleName , ruleResults ] of Object . entries ( fileResults ) ) {
const rule = ruleNameToRule [ ruleName . toUpperCase ( ) ] ;
for ( const lineNumber of ruleResults ) {
// @ts-ignore
const nameIndex = Math . min ( useAlias ? 1 : 0 , rule . names . length - 1 ) ;
const result = file + ": " + lineNumber + ": " +
// @ts-ignore
rule . names [ nameIndex ] + " " +
// @ts-ignore
rule . description ;
results . push ( result ) ;
2023-01-17 04:19:40 +00:00
}
}
}
2020-09-13 21:15:11 -07:00
}
2023-01-17 04:19:40 +00:00
return results . join ( "\n" ) ;
}
Object . defineProperty ( lintResults , "toString" , {
"value" : toString
} ) ;
// @ts-ignore
return lintResults ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
2020-01-27 19:19:34 -08:00
/ * *
* Remove front matter ( if present at beginning of content ) .
*
* @ param { string } content Markdown content .
2023-01-29 21:13:17 -08:00
* @ param { RegExp | null } frontMatter Regular expression to match front matter .
2020-01-27 19:19:34 -08:00
* @ returns { Object } Trimmed content and front matter lines .
* /
2019-10-02 20:10:42 -07:00
function removeFrontMatter ( content , frontMatter ) {
2024-01-06 20:47:01 -08:00
let frontMatterLines = [ ] ;
2023-01-17 04:19:40 +00:00
if ( frontMatter ) {
2024-01-06 20:47:01 -08:00
const frontMatterMatch = content . match ( frontMatter ) ;
2023-01-17 04:19:40 +00:00
if ( frontMatterMatch && ! frontMatterMatch . index ) {
2024-01-06 20:47:01 -08:00
const contentMatched = frontMatterMatch [ 0 ] ;
2023-01-17 04:19:40 +00:00
content = content . slice ( contentMatched . length ) ;
frontMatterLines = contentMatched . split ( helpers . newLineRe ) ;
if ( frontMatterLines . length > 0 && frontMatterLines [ frontMatterLines . length - 1 ] === "" ) {
frontMatterLines . length -- ;
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
return {
"content" : content ,
"frontMatterLines" : frontMatterLines
} ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
2020-01-27 19:19:34 -08:00
/ * *
2022-06-09 23:56:44 -07:00
* Freeze all freeze - able members of a token and its children .
*
* @ param { MarkdownItToken } token A markdown - it token .
* @ returns { void }
* /
function freezeToken ( token ) {
2023-01-17 04:19:40 +00:00
if ( token . attrs ) {
2024-01-06 20:47:01 -08:00
for ( const attr of token . attrs ) {
Object . freeze ( attr ) ;
2022-06-09 23:56:44 -07:00
}
2023-01-17 04:19:40 +00:00
Object . freeze ( token . attrs ) ;
}
if ( token . children ) {
2024-01-06 20:47:01 -08:00
for ( const child of token . children ) {
freezeToken ( child ) ;
2022-06-09 23:56:44 -07:00
}
2023-01-17 04:19:40 +00:00
Object . freeze ( token . children ) ;
}
if ( token . map ) {
Object . freeze ( token . map ) ;
}
Object . freeze ( token ) ;
2022-06-09 23:56:44 -07:00
}
2023-01-17 04:19:40 +00:00
2022-06-09 23:56:44 -07:00
/ * *
* Annotate tokens with line / lineNumber and freeze them .
2020-01-27 19:19:34 -08:00
*
* @ param { MarkdownItToken [ ] } tokens Array of markdown - it tokens .
* @ param { string [ ] } lines Lines of Markdown content .
* @ returns { void }
* /
2022-06-09 23:56:44 -07:00
function annotateAndFreezeTokens ( tokens , lines ) {
2024-01-06 20:47:01 -08:00
let trMap = null ;
for ( const token of tokens ) {
// Provide missing maps for table content
if ( token . type === "tr_open" ) {
trMap = token . map ;
} else if ( token . type === "tr_close" ) {
trMap = null ;
}
if ( ! token . map && trMap ) {
token . map = [ ... trMap ] ;
}
// 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 ] -- ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
}
// Annotate children with lineNumber
if ( token . children ) {
const codeSpanExtraLines = [ ] ;
if ( token . children . some ( child => child . type === "code_inline" ) ) {
helpers . forEachInlineCodeSpan ( token . content , code => {
codeSpanExtraLines . push ( code . split ( helpers . newLineRe ) . length - 1 ) ;
} ) ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
let lineNumber = token . lineNumber ;
for ( const child of token . children ) {
child . lineNumber = lineNumber ;
child . line = lines [ lineNumber - 1 ] ;
if ( child . type === "softbreak" || child . type === "hardbreak" ) {
lineNumber ++ ;
} else if ( child . type === "code_inline" ) {
lineNumber += codeSpanExtraLines . shift ( ) ;
2023-01-17 04:19:40 +00:00
}
}
2022-06-08 22:10:27 -07:00
}
2024-01-06 20:47:01 -08:00
freezeToken ( token ) ;
2023-01-17 04:19:40 +00:00
}
Object . freeze ( tokens ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
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 ) {
2024-01-06 20:47:01 -08:00
const aliasToRuleNames = { } ;
2023-01-17 04:19:40 +00:00
// const tagToRuleNames = {};
2024-01-06 20:47:01 -08:00
for ( const rule of ruleList ) {
const ruleName = rule . names [ 0 ] . toUpperCase ( ) ;
2019-10-02 20:10:42 -07:00
// The following is useful for updating README.md:
2024-01-06 20:47:01 -08:00
// console.log(
// "* **[" + ruleName + "](doc/Rules.md#" + ruleName.toLowerCase() +
// ")** *" + rule.names.slice(1).join("/") + "* - " + rule.description);
for ( const name of rule . names ) {
const nameUpper = name . toUpperCase ( ) ;
aliasToRuleNames [ nameUpper ] = [ ruleName ] ;
}
for ( const tag of rule . tags ) {
const tagUpper = tag . toUpperCase ( ) ;
const ruleNames = aliasToRuleNames [ tagUpper ] || [ ] ;
ruleNames . push ( ruleName ) ;
aliasToRuleNames [ tagUpper ] = ruleNames ;
// tagToRuleNames[tag] = ruleName;
}
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
// The following is useful for updating README.md:
// Object.keys(tagToRuleNames).sort().forEach(function forTag(tag) {
// console.log("* **" + tag + "** - " +
// aliasToRuleNames[tag.toUpperCase()].join(", "));
// });
// @ts-ignore
2023-01-17 04:19:40 +00:00
return aliasToRuleNames ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
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 ) {
2024-01-06 20:47:01 -08:00
const defaultKey = Object . keys ( config ) . filter ( key => key . toUpperCase ( ) === "DEFAULT" ) ;
const ruleDefault = defaultKey . length === 0 || ! ! config [ defaultKey [ 0 ] ] ;
2023-11-08 19:49:02 -08:00
/** @type {Configuration} */
2024-01-06 20:47:01 -08:00
const effectiveConfig = { } ;
for ( const rule of ruleList ) {
const ruleName = rule . names [ 0 ] . toUpperCase ( ) ;
effectiveConfig [ ruleName ] = ruleDefault ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
// for (const ruleName of deprecatedRuleNames) {
// effectiveConfig[ruleName] = false;
// }
for ( const key of Object . keys ( config ) ) {
let value = config [ key ] ;
2023-01-17 04:19:40 +00:00
if ( value ) {
if ( ! ( value instanceof Object ) ) {
value = { } ;
}
} else {
value = false ;
2022-06-08 22:10:27 -07:00
}
2024-01-06 20:47:01 -08:00
const keyUpper = key . toUpperCase ( ) ;
for ( const ruleName of aliasToRuleNames [ keyUpper ] || [ ] ) {
effectiveConfig [ ruleName ] = value ;
2023-01-17 04:19:40 +00:00
}
}
return effectiveConfig ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
2022-06-05 22:32:22 -07:00
/ * *
* Parse the content of a configuration file .
*
* @ param { string } name Name of the configuration file .
* @ param { string } content Configuration content .
2022-06-11 22:40:45 -07:00
* @ param { ConfigurationParser [ ] | null } [ parsers ] Parsing function ( s ) .
2022-06-05 22:32:22 -07:00
* @ returns { Object } Configuration object and error message .
* /
function parseConfiguration ( name , content , parsers ) {
2024-01-06 20:47:01 -08:00
let config = null ;
let message = "" ;
const errors = [ ] ;
let index = 0 ;
2023-01-17 04:19:40 +00:00
// Try each parser
2024-01-06 20:47:01 -08:00
( parsers || [ JSON . parse ] ) . every ( parser => {
2023-01-17 04:19:40 +00:00
try {
config = parser ( content ) ;
} catch ( error ) {
2024-01-06 20:47:01 -08:00
errors . push ( ` Parser ${ index ++ } : ${ error . message } ` ) ;
2022-06-05 22:32:22 -07:00
}
2023-01-17 04:19:40 +00:00
return ! config ;
} ) ;
// Message if unable to parse
if ( ! config ) {
2024-01-06 20:47:01 -08:00
errors . unshift ( ` Unable to parse ' ${ name } ' ` ) ;
2023-01-17 04:19:40 +00:00
message = errors . join ( "; " ) ;
}
return {
2024-01-06 20:47:01 -08:00
config ,
message
2023-01-17 04:19:40 +00:00
} ;
2022-06-05 22:32:22 -07:00
}
2023-01-17 04:19:40 +00:00
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 .
2022-06-11 22:40:45 -07:00
* @ param { ConfigurationParser [ ] | null } configParsers Configuration parsers .
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
* /
2022-06-05 22:32:22 -07:00
function getEnabledRulesPerLineNumber ( ruleList , lines , frontMatterLines , noInlineConfig , config , configParsers , aliasToRuleNames ) {
2023-01-17 04:19:40 +00:00
// Shared variables
2024-01-06 20:47:01 -08:00
let enabledRules = { } ;
let capturedRules = { } ;
const allRuleNames = [ ] ;
const enabledRulesPerLineNumber = new Array ( 1 + frontMatterLines . length ) ;
2023-01-17 04:19:40 +00:00
// Helper functions
// eslint-disable-next-line jsdoc/require-jsdoc
function handleInlineConfig ( input , forEachMatch , forEachLine ) {
2024-01-06 20:47:01 -08:00
for ( const [ lineIndex , line ] of input . entries ( ) ) {
if ( ! noInlineConfig ) {
let match = null ;
while ( match = helpers . inlineCommentStartRe . exec ( line ) ) {
const action = match [ 2 ] . toUpperCase ( ) ;
const startIndex = match . index + match [ 1 ] . length ;
const endIndex = line . indexOf ( "-->" , startIndex ) ;
if ( endIndex === - 1 ) {
break ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
const parameter = line . slice ( startIndex , endIndex ) ;
forEachMatch ( action , parameter , lineIndex + 1 ) ;
2023-01-17 04:19:40 +00:00
}
}
2024-01-06 20:47:01 -08:00
if ( forEachLine ) {
forEachLine ( ) ;
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
// eslint-disable-next-line jsdoc/require-jsdoc
function configureFile ( action , parameter ) {
if ( action === "CONFIGURE-FILE" ) {
2024-01-06 20:47:01 -08:00
const {
"config" : parsed
} = parseConfiguration ( "CONFIGURE-FILE" , parameter , configParsers ) ;
2023-01-17 04:19:40 +00:00
if ( parsed ) {
2024-01-06 20:47:01 -08:00
config = {
... config ,
... parsed
} ;
2023-01-17 04:19:40 +00:00
}
2020-04-11 13:54:46 -07:00
}
2023-01-17 04:19:40 +00:00
}
// eslint-disable-next-line jsdoc/require-jsdoc
function applyEnableDisable ( action , parameter , state ) {
2024-01-06 20:47:01 -08:00
state = {
... state
} ;
const enabled = action . startsWith ( "ENABLE" ) ;
const trimmed = parameter && parameter . trim ( ) ;
const items = trimmed ? trimmed . toUpperCase ( ) . split ( /\s+/ ) : allRuleNames ;
for ( const nameUpper of items ) {
for ( const ruleName of aliasToRuleNames [ nameUpper ] || [ ] ) {
state [ ruleName ] = enabled ;
2023-01-17 04:19:40 +00:00
}
2020-04-11 13:54:46 -07:00
}
2023-01-17 04:19:40 +00:00
return state ;
}
// eslint-disable-next-line jsdoc/require-jsdoc
function enableDisableFile ( action , parameter ) {
if ( action === "ENABLE-FILE" || action === "DISABLE-FILE" ) {
enabledRules = applyEnableDisable ( action , parameter , enabledRules ) ;
2020-04-11 13:54:46 -07:00
}
2023-01-17 04:19:40 +00:00
}
// eslint-disable-next-line jsdoc/require-jsdoc
function captureRestoreEnableDisable ( action , parameter ) {
if ( action === "CAPTURE" ) {
capturedRules = enabledRules ;
} else if ( action === "RESTORE" ) {
enabledRules = capturedRules ;
} else if ( action === "ENABLE" || action === "DISABLE" ) {
enabledRules = applyEnableDisable ( action , parameter , enabledRules ) ;
2020-04-11 13:54:46 -07:00
}
2023-01-17 04:19:40 +00:00
}
// eslint-disable-next-line jsdoc/require-jsdoc
function updateLineState ( ) {
enabledRulesPerLineNumber . push ( enabledRules ) ;
}
// eslint-disable-next-line jsdoc/require-jsdoc
function disableLineNextLine ( action , parameter , lineNumber ) {
2024-01-06 20:47:01 -08:00
const disableLine = action === "DISABLE-LINE" ;
const disableNextLine = action === "DISABLE-NEXT-LINE" ;
2023-01-17 04:19:40 +00:00
if ( disableLine || disableNextLine ) {
2024-01-06 20:47:01 -08:00
const nextLineNumber = frontMatterLines . length + lineNumber + ( disableNextLine ? 1 : 0 ) ;
2023-07-28 14:33:03 +10:00
enabledRulesPerLineNumber [ nextLineNumber ] = applyEnableDisable ( action , parameter , enabledRulesPerLineNumber [ nextLineNumber ] ) ;
2020-11-24 16:37:11 -08:00
}
2023-01-17 04:19:40 +00:00
}
// Handle inline comments
handleInlineConfig ( [ lines . join ( "\n" ) ] , configureFile ) ;
2024-01-06 20:47:01 -08:00
const effectiveConfig = getEffectiveConfig ( ruleList , config , aliasToRuleNames ) ;
for ( const rule of ruleList ) {
const ruleName = rule . names [ 0 ] . toUpperCase ( ) ;
allRuleNames . push ( ruleName ) ;
enabledRules [ ruleName ] = ! ! effectiveConfig [ ruleName ] ;
2023-01-17 04:19:40 +00:00
}
capturedRules = enabledRules ;
handleInlineConfig ( lines , enableDisableFile ) ;
handleInlineConfig ( lines , captureRestoreEnableDisable , updateLineState ) ;
handleInlineConfig ( lines , disableLineNextLine ) ;
// Return results
return {
2024-01-06 20:47:01 -08:00
effectiveConfig ,
enabledRulesPerLineNumber
2023-01-17 04:19:40 +00:00
} ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
2020-01-27 19:19:34 -08:00
/ * *
* Lints a string containing Markdown content .
*
* @ param { Rule [ ] } ruleList List of rules .
2023-03-12 20:49:41 -07:00
* @ param { Object . < string , string [ ] > } aliasToRuleNames Map of alias to rule
* names .
2020-01-27 19:19:34 -08:00
* @ param { string } name Identifier for the content .
2020-11-24 16:37:11 -08:00
* @ param { string } content Markdown content .
* @ param { Object } md Instance of markdown - it .
2020-01-27 19:19:34 -08:00
* @ param { Configuration } config Configuration object .
2022-06-11 22:40:45 -07:00
* @ param { ConfigurationParser [ ] | null } configParsers Configuration parsers .
2023-01-29 21:13:17 -08:00
* @ param { RegExp | null } frontMatter Regular expression for front matter .
2020-01-27 19:19:34 -08:00
* @ 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 .
2023-09-04 21:41:16 -07:00
* @ param { LintContentCallback } callback Callback ( err , result ) function .
2020-01-27 19:19:34 -08:00
* @ returns { void }
* /
2023-03-12 20:49:41 -07:00
function lintContent ( ruleList , aliasToRuleNames , name , content , md , config , configParsers , frontMatter , handleRuleFailures , noInlineConfig , resultVersion , callback ) {
2023-01-17 04:19:40 +00:00
// Remove UTF-8 byte order marker (if present)
content = content . replace ( /^\uFEFF/ , "" ) ;
// Remove front matter
2024-01-06 20:47:01 -08:00
const removeFrontMatterResult = removeFrontMatter ( content , frontMatter ) ;
const {
frontMatterLines
} = removeFrontMatterResult ;
2023-01-17 04:19:40 +00:00
content = removeFrontMatterResult . content ;
// Get enabled rules per line (with HTML comments present)
2024-01-06 20:47:01 -08:00
const {
effectiveConfig ,
enabledRulesPerLineNumber
} = getEnabledRulesPerLineNumber ( ruleList , content . split ( helpers . newLineRe ) , frontMatterLines , noInlineConfig , config , configParsers , aliasToRuleNames ) ;
2023-01-15 21:41:22 -08:00
// Parse content into parser tokens
2024-01-06 20:47:01 -08:00
const markdownitTokens = md . parse ( content , { } ) ;
const micromarkTokens = micromark . parse ( content ) ;
2023-01-15 21:41:22 -08:00
// Hide the content of HTML comments from rules
2023-01-17 04:19:40 +00:00
content = helpers . clearHtmlCommentText ( content ) ;
2023-01-15 21:41:22 -08:00
// Parse content into lines and update markdown-it tokens
2024-01-06 20:47:01 -08:00
const lines = content . split ( helpers . newLineRe ) ;
2023-01-15 21:41:22 -08:00
annotateAndFreezeTokens ( markdownitTokens , lines ) ;
2023-01-17 04:19:40 +00:00
// Create (frozen) parameters for rules
2024-01-06 20:47:01 -08:00
const parsers = Object . freeze ( {
2023-01-21 19:16:07 -08:00
"markdownit" : Object . freeze ( {
"tokens" : markdownitTokens
} ) ,
"micromark" : Object . freeze ( {
"tokens" : micromarkTokens
} )
2023-01-15 21:41:22 -08:00
} ) ;
2024-01-06 20:47:01 -08:00
const paramsBase = {
name ,
parsers ,
2023-01-15 21:41:22 -08:00
"tokens" : markdownitTokens ,
2023-01-17 04:19:40 +00:00
"lines" : Object . freeze ( lines ) ,
"frontMatterLines" : Object . freeze ( frontMatterLines )
} ;
2024-01-06 20:47:01 -08:00
const lineMetadata = helpers . getLineMetadata ( paramsBase ) ;
const codeBlockAndSpanRanges = helpers . codeBlockAndSpanRanges ( paramsBase , lineMetadata ) ;
const flattenedLists = helpers . flattenLists ( paramsBase . parsers . markdownit . tokens ) ;
const referenceLinkImageData = helpers . getReferenceLinkImageData ( paramsBase ) ;
2023-01-17 04:19:40 +00:00
cache . set ( {
2024-01-06 20:47:01 -08:00
codeBlockAndSpanRanges ,
flattenedLists ,
lineMetadata ,
referenceLinkImageData
2023-01-17 04:19:40 +00:00
} ) ;
// Function to run for each rule
2024-01-06 20:47:01 -08:00
let results = [ ] ;
2023-01-17 04:19:40 +00:00
// eslint-disable-next-line jsdoc/require-jsdoc
function forRule ( rule ) {
// Configure rule
2024-01-06 20:47:01 -08:00
const ruleName = rule . names [ 0 ] . toUpperCase ( ) ;
const params = {
... paramsBase ,
2023-01-17 04:19:40 +00:00
"config" : effectiveConfig [ ruleName ]
2024-01-06 20:47:01 -08:00
} ;
2020-01-27 19:19:34 -08:00
// eslint-disable-next-line jsdoc/require-jsdoc
2023-01-17 04:19:40 +00:00
function throwError ( property ) {
2024-01-06 20:47:01 -08:00
throw new Error ( ` Value of ' ${ property } ' passed to onError by ' ${ ruleName } ' is incorrect for ' ${ name } '. ` ) ;
2021-12-11 21:44:25 -08:00
}
// eslint-disable-next-line jsdoc/require-jsdoc
2023-01-17 04:19:40 +00:00
function onError ( errorInfo ) {
if ( ! errorInfo || ! helpers . isNumber ( errorInfo . lineNumber ) || errorInfo . lineNumber < 1 || errorInfo . lineNumber > lines . length ) {
throwError ( "lineNumber" ) ;
}
2024-01-06 20:47:01 -08:00
const lineNumber = errorInfo . lineNumber + frontMatterLines . length ;
2023-01-17 04:19:40 +00:00
if ( ! enabledRulesPerLineNumber [ lineNumber ] [ ruleName ] ) {
return ;
}
if ( errorInfo . detail && ! helpers . isString ( errorInfo . detail ) ) {
throwError ( "detail" ) ;
}
if ( errorInfo . context && ! helpers . isString ( errorInfo . context ) ) {
throwError ( "context" ) ;
}
2023-07-11 21:44:45 -07:00
if ( errorInfo . information && ! helpers . isUrl ( errorInfo . information ) ) {
throwError ( "information" ) ;
}
2023-01-17 04:19:40 +00:00
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" ) ;
}
2024-01-06 20:47:01 -08:00
const fixInfo = errorInfo . fixInfo ;
const cleanFixInfo = { } ;
2023-01-17 04:19:40 +00:00
if ( fixInfo ) {
if ( ! helpers . isObject ( fixInfo ) ) {
throwError ( "fixInfo" ) ;
}
if ( fixInfo . lineNumber !== undefined ) {
if ( ! helpers . isNumber ( fixInfo . lineNumber ) || fixInfo . lineNumber < 1 || fixInfo . lineNumber > lines . length ) {
throwError ( "fixInfo.lineNumber" ) ;
}
cleanFixInfo . lineNumber = fixInfo . lineNumber + frontMatterLines . length ;
}
2024-01-06 20:47:01 -08:00
const effectiveLineNumber = fixInfo . lineNumber || errorInfo . lineNumber ;
2023-01-17 04:19:40 +00:00
if ( fixInfo . editColumn !== undefined ) {
if ( ! helpers . isNumber ( fixInfo . editColumn ) || fixInfo . editColumn < 1 || fixInfo . editColumn > lines [ effectiveLineNumber - 1 ] . length + 1 ) {
throwError ( "fixInfo.editColumn" ) ;
}
cleanFixInfo . editColumn = fixInfo . editColumn ;
}
if ( fixInfo . deleteCount !== undefined ) {
if ( ! helpers . isNumber ( fixInfo . deleteCount ) || fixInfo . deleteCount < - 1 || fixInfo . deleteCount > lines [ effectiveLineNumber - 1 ] . length ) {
throwError ( "fixInfo.deleteCount" ) ;
}
cleanFixInfo . deleteCount = fixInfo . deleteCount ;
}
if ( fixInfo . insertText !== undefined ) {
if ( ! helpers . isString ( fixInfo . insertText ) ) {
throwError ( "fixInfo.insertText" ) ;
}
cleanFixInfo . insertText = fixInfo . insertText ;
}
}
2024-01-06 20:47:01 -08:00
const information = errorInfo . information || rule . information ;
2023-01-17 04:19:40 +00:00
results . push ( {
2024-01-06 20:47:01 -08:00
lineNumber ,
2023-01-17 04:19:40 +00:00
"ruleName" : rule . names [ 0 ] ,
"ruleNames" : rule . names ,
"ruleDescription" : rule . description ,
2023-07-11 21:44:45 -07:00
"ruleInformation" : information ? information . href : null ,
2023-01-17 04:19:40 +00:00
"errorDetail" : errorInfo . detail || null ,
"errorContext" : errorInfo . context || null ,
2024-01-06 20:47:01 -08:00
"errorRange" : errorInfo . range ? [ ... errorInfo . range ] : null ,
2023-01-17 04:19:40 +00:00
"fixInfo" : fixInfo ? cleanFixInfo : null
} ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
// Call (possibly external) rule function to report errors
2024-01-06 20:47:01 -08:00
const catchCallsOnError = error => onError ( {
"lineNumber" : 1 ,
"detail" : ` This rule threw an exception: ${ error . message || error } `
} ) ;
const invokeRuleFunction = ( ) => rule . function ( params , onError ) ;
2023-01-17 04:19:40 +00:00
if ( rule . asynchronous ) {
// Asynchronous rule, ensure it returns a Promise
2024-01-06 20:47:01 -08:00
const ruleFunctionPromise = Promise . resolve ( ) . then ( invokeRuleFunction ) ;
return handleRuleFailures ? ruleFunctionPromise . catch ( catchCallsOnError ) : ruleFunctionPromise ;
2023-01-17 04:19:40 +00:00
}
// Synchronous rule
2019-10-02 20:10:42 -07:00
try {
2023-01-17 04:19:40 +00:00
invokeRuleFunction ( ) ;
} catch ( error ) {
if ( handleRuleFailures ) {
catchCallsOnError ( error ) ;
} else {
throw error ;
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
return null ;
}
// eslint-disable-next-line jsdoc/require-jsdoc
function formatResults ( ) {
// Sort results by rule name by line number
2024-01-06 20:47:01 -08:00
results . sort ( ( a , b ) => a . ruleName . localeCompare ( b . ruleName ) || a . lineNumber - b . lineNumber ) ;
2023-01-17 04:19:40 +00:00
if ( resultVersion < 3 ) {
// Remove fixInfo and multiple errors for the same rule and line number
2024-01-06 20:47:01 -08:00
const noPrevious = {
2023-01-17 04:19:40 +00:00
"ruleName" : null ,
"lineNumber" : - 1
} ;
2024-01-06 20:47:01 -08:00
results = results . filter ( ( error , index , array ) => {
2023-01-17 04:19:40 +00:00
delete error . fixInfo ;
2024-01-06 20:47:01 -08:00
const previous = array [ index - 1 ] || noPrevious ;
2023-01-17 04:19:40 +00:00
return error . ruleName !== previous . ruleName || error . lineNumber !== previous . lineNumber ;
} ) ;
2021-12-04 17:02:11 -08:00
}
2023-01-17 04:19:40 +00:00
if ( resultVersion === 0 ) {
// Return a dictionary of rule->[line numbers]
2024-01-06 20:47:01 -08:00
const dictionary = { } ;
for ( const error of results ) {
const ruleLines = dictionary [ error . ruleName ] || [ ] ;
ruleLines . push ( error . lineNumber ) ;
dictionary [ error . ruleName ] = ruleLines ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
// @ts-ignore
2023-01-17 04:19:40 +00:00
results = dictionary ;
} else if ( resultVersion === 1 ) {
// Use ruleAlias instead of ruleNames
2024-01-06 20:47:01 -08:00
for ( const error of results ) {
error . ruleAlias = error . ruleNames [ 1 ] || error . ruleName ;
delete error . ruleNames ;
2023-01-17 04:19:40 +00:00
}
} else {
// resultVersion 2 or 3: Remove unwanted ruleName
2024-01-06 20:47:01 -08:00
for ( const error of results ) {
delete error . ruleName ;
2023-01-17 04:19:40 +00:00
}
2021-12-04 17:02:11 -08:00
}
2023-01-17 04:19:40 +00:00
return results ;
}
// Run all rules
2024-01-06 20:47:01 -08:00
const ruleListAsync = ruleList . filter ( rule => rule . asynchronous ) ;
const ruleListSync = ruleList . filter ( rule => ! rule . asynchronous ) ;
const ruleListAsyncFirst = [ ... ruleListAsync , ... ruleListSync ] ;
const callbackSuccess = ( ) => callback ( null , formatResults ( ) ) ;
const callbackError = error => callback ( error instanceof Error ? error : new Error ( error ) ) ;
2023-01-17 04:19:40 +00:00
try {
2024-01-06 20:47:01 -08:00
const ruleResults = ruleListAsyncFirst . map ( forRule ) ;
2023-01-17 04:19:40 +00:00
if ( ruleListAsync . length > 0 ) {
2024-01-06 20:47:01 -08:00
Promise . all ( ruleResults . slice ( 0 , ruleListAsync . length ) ) . then ( callbackSuccess ) . catch ( callbackError ) ;
2023-01-17 04:19:40 +00:00
} else {
callbackSuccess ( ) ;
}
} catch ( error ) {
callbackError ( error ) ;
} finally {
cache . clear ( ) ;
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
2020-01-27 19:19:34 -08:00
/ * *
* Lints a file containing Markdown content .
*
* @ param { Rule [ ] } ruleList List of rules .
2023-03-12 20:49:41 -07:00
* @ param { Object . < string , string [ ] > } aliasToRuleNames Map of alias to rule
* names .
2020-01-27 19:19:34 -08:00
* @ param { string } file Path of file to lint .
2020-11-24 16:37:11 -08:00
* @ param { Object } md Instance of markdown - it .
2020-01-27 19:19:34 -08:00
* @ param { Configuration } config Configuration object .
2022-06-11 22:40:45 -07:00
* @ param { ConfigurationParser [ ] | null } configParsers Configuration parsers .
2023-01-29 21:13:17 -08:00
* @ param { RegExp | null } frontMatter Regular expression for front matter .
2020-01-27 19:19:34 -08:00
* @ 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 .
2021-08-12 19:38:03 -07:00
* @ param { Object } fs File system implementation .
2020-01-27 19:19:34 -08:00
* @ param { boolean } synchronous Whether to execute synchronously .
2023-09-04 21:41:16 -07:00
* @ param { LintContentCallback } callback Callback ( err , result ) function .
2020-01-27 19:19:34 -08:00
* @ returns { void }
* /
2023-03-12 20:49:41 -07:00
function lintFile ( ruleList , aliasToRuleNames , file , md , config , configParsers , frontMatter , handleRuleFailures , noInlineConfig , resultVersion , fs , synchronous , callback ) {
2023-01-17 04:19:40 +00:00
// eslint-disable-next-line jsdoc/require-jsdoc
function lintContentWrapper ( err , content ) {
if ( err ) {
return callback ( err ) ;
2019-10-02 20:10:42 -07:00
}
2023-03-12 20:49:41 -07:00
return lintContent ( ruleList , aliasToRuleNames , file , content , md , config , configParsers , frontMatter , handleRuleFailures , noInlineConfig , resultVersion , callback ) ;
2023-01-17 04:19:40 +00:00
}
// Make a/synchronous call to read file
if ( synchronous ) {
lintContentWrapper ( null , fs . readFileSync ( file , "utf8" ) ) ;
} else {
fs . readFile ( file , "utf8" , lintContentWrapper ) ;
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
2020-01-27 19:19:34 -08:00
/ * *
* Lint files and strings specified in the Options object .
*
2023-01-29 21:13:17 -08:00
* @ param { Options | null } options Options object .
2020-01-27 19:19:34 -08:00
* @ param { boolean } synchronous Whether to execute synchronously .
2023-09-04 21:41:16 -07:00
* @ param { LintCallback } callback Callback ( err , result ) function .
2020-01-27 19:19:34 -08:00
* @ returns { void }
* /
2019-10-02 20:10:42 -07:00
function lintInput ( options , synchronous , callback ) {
2023-01-17 04:19:40 +00:00
// Normalize inputs
options = options || { } ;
callback = callback || function noop ( ) { } ;
2024-01-06 20:47:01 -08:00
const customRuleList = [ options . customRules || [ ] ] . flat ( ) . map ( rule => ( {
"names" : helpers . cloneIfArray ( rule . names ) ,
"description" : rule . description ,
"information" : helpers . cloneIfUrl ( rule . information ) ,
"tags" : helpers . cloneIfArray ( rule . tags ) ,
"asynchronous" : rule . asynchronous ,
"function" : rule . function
} ) ) ;
2023-01-17 04:19:40 +00:00
// eslint-disable-next-line unicorn/prefer-spread
2024-01-06 20:47:01 -08:00
const ruleList = rules . concat ( customRuleList ) ;
const ruleErr = validateRuleList ( ruleList , synchronous ) ;
2023-01-17 04:19:40 +00:00
if ( ruleErr ) {
callback ( ruleErr ) ;
return ;
}
2024-01-06 20:47:01 -08:00
let files = [ ] ;
2023-01-17 04:19:40 +00:00
if ( Array . isArray ( options . files ) ) {
2024-01-06 20:47:01 -08:00
files = [ ... options . files ] ;
2023-01-17 04:19:40 +00:00
} else if ( options . files ) {
files = [ String ( options . files ) ] ;
}
2024-01-06 20:47:01 -08:00
const strings = options . strings || { } ;
const stringsKeys = Object . keys ( strings ) ;
const config = options . config || {
2023-01-17 04:19:40 +00:00
"default" : true
} ;
2024-01-06 20:47:01 -08:00
const configParsers = options . configParsers || null ;
const frontMatter = options . frontMatter === undefined ? helpers . frontMatterRe : options . frontMatter ;
const handleRuleFailures = ! ! options . handleRuleFailures ;
const noInlineConfig = ! ! options . noInlineConfig ;
const resultVersion = options . resultVersion === undefined ? 3 : options . resultVersion ;
const md = markdownit ( {
2023-01-17 04:19:40 +00:00
"html" : true
} ) ;
2024-01-06 20:47:01 -08:00
const markdownItPlugins = options . markdownItPlugins || [ ] ;
for ( const plugin of markdownItPlugins ) {
// @ts-ignore
md . use ( ... plugin ) ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
const fs = options . fs || _ _webpack _require _ _ ( /*! node:fs */ "?d0ee" ) ;
const aliasToRuleNames = mapAliasToRuleNames ( ruleList ) ;
const results = newResults ( ruleList ) ;
let done = false ;
let concurrency = 0 ;
2023-01-17 04:19:40 +00:00
// eslint-disable-next-line jsdoc/require-jsdoc
function lintWorker ( ) {
2024-01-06 20:47:01 -08:00
let currentItem = null ;
2020-09-13 21:15:11 -07:00
// eslint-disable-next-line jsdoc/require-jsdoc
2023-01-17 04:19:40 +00:00
function lintWorkerCallback ( err , result ) {
concurrency -- ;
if ( err ) {
done = true ;
return callback ( err ) ;
}
results [ currentItem ] = result ;
if ( ! synchronous ) {
lintWorker ( ) ;
}
return null ;
2020-09-13 21:15:11 -07:00
}
2023-01-17 04:19:40 +00:00
if ( done ) {
// Abort for error or nothing left to do
} else if ( files . length > 0 ) {
// Lint next file
concurrency ++ ;
currentItem = files . shift ( ) ;
2023-03-12 20:49:41 -07:00
lintFile ( ruleList , aliasToRuleNames , currentItem , md , config , configParsers , frontMatter , handleRuleFailures , noInlineConfig , resultVersion , fs , synchronous , lintWorkerCallback ) ;
2023-01-17 04:19:40 +00:00
} else if ( currentItem = stringsKeys . shift ( ) ) {
// Lint next string
concurrency ++ ;
2023-03-12 20:49:41 -07:00
lintContent ( ruleList , aliasToRuleNames , currentItem , strings [ currentItem ] || "" , md , config , configParsers , frontMatter , handleRuleFailures , noInlineConfig , resultVersion , lintWorkerCallback ) ;
2023-01-17 04:19:40 +00:00
} else if ( concurrency === 0 ) {
// Finish
done = true ;
return callback ( null , results ) ;
2021-12-03 22:43:58 -08:00
}
2023-01-17 04:19:40 +00:00
return null ;
}
if ( synchronous ) {
while ( ! done ) {
lintWorker ( ) ;
2021-12-03 22:43:58 -08:00
}
2023-01-17 04:19:40 +00:00
} else {
// Testing on a Raspberry Pi 4 Model B with an artificial 5ms file access
// delay suggests that a concurrency factor of 8 can eliminate the impact
// of that delay (i.e., total time is the same as with no delay).
lintWorker ( ) ;
lintWorker ( ) ;
lintWorker ( ) ;
lintWorker ( ) ;
lintWorker ( ) ;
lintWorker ( ) ;
lintWorker ( ) ;
lintWorker ( ) ;
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
/ * *
* Lint specified Markdown files .
*
2023-01-29 21:13:17 -08:00
* @ param { Options | null } options Configuration options .
2019-12-14 13:50:48 -08:00
* @ param { LintCallback } callback Callback ( err , result ) function .
2019-10-02 20:10:42 -07:00
* @ returns { void }
* /
function markdownlint ( options , callback ) {
2023-01-17 04:19:40 +00:00
return lintInput ( options , false , callback ) ;
2019-10-02 20:10:42 -07:00
}
2024-01-06 20:47:01 -08:00
const markdownlintPromisify = promisify && promisify ( markdownlint ) ;
2023-01-17 04:19:40 +00:00
2020-09-13 21:15:11 -07:00
/ * *
* Lint specified Markdown files .
*
* @ param { Options } options Configuration options .
* @ returns { Promise < LintResults > } Results object .
* /
function markdownlintPromise ( options ) {
2023-01-17 04:19:40 +00:00
// @ts-ignore
return markdownlintPromisify ( options ) ;
2020-09-13 21:15:11 -07:00
}
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
/ * *
* Lint specified Markdown files synchronously .
*
2023-01-29 21:13:17 -08:00
* @ param { Options | null } options Configuration options .
2019-12-14 13:50:48 -08:00
* @ returns { LintResults } Results object .
2019-10-02 20:10:42 -07:00
* /
function markdownlintSync ( options ) {
2024-01-06 20:47:01 -08:00
let results = null ;
2023-01-17 04:19:40 +00:00
lintInput ( options , true , function callback ( error , res ) {
if ( error ) {
throw error ;
}
results = res ;
} ) ;
// @ts-ignore
return results ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
2021-08-12 20:43:18 -07:00
/ * *
* Resolve referenced "extends" path in a configuration file
* using path . resolve ( ) with require . resolve ( ) as a fallback .
*
* @ param { string } configFile Configuration file name .
* @ param { string } referenceId Referenced identifier to resolve .
* @ param { Object } fs File system implementation .
2022-06-11 22:40:45 -07:00
* @ param { ResolveConfigExtendsCallback } callback Callback ( err , result )
2021-08-12 20:43:18 -07:00
* function .
* @ returns { void }
* /
function resolveConfigExtends ( configFile , referenceId , fs , callback ) {
2024-01-06 20:47:01 -08:00
const configFileDirname = path . dirname ( configFile ) ;
const resolvedExtendsFile = path . resolve ( configFileDirname , referenceId ) ;
fs . access ( resolvedExtendsFile , err => {
2023-01-17 04:19:40 +00:00
if ( err ) {
// Not a file, try require.resolve
try {
return callback ( null , dynamicRequire . resolve ( referenceId , {
"paths" : [ configFileDirname ]
} ) ) ;
2024-01-06 20:47:01 -08:00
} catch {
2023-01-17 04:19:40 +00:00
// Unable to resolve, use resolvedExtendsFile
}
}
return callback ( null , resolvedExtendsFile ) ;
} ) ;
2021-08-12 20:43:18 -07:00
}
2023-01-17 04:19:40 +00:00
2020-11-24 16:37:11 -08:00
/ * *
* Resolve referenced "extends" path in a configuration file
* using path . resolve ( ) with require . resolve ( ) as a fallback .
*
* @ param { string } configFile Configuration file name .
* @ param { string } referenceId Referenced identifier to resolve .
2021-08-12 19:38:03 -07:00
* @ param { Object } fs File system implementation .
2020-11-24 16:37:11 -08:00
* @ returns { string } Resolved path to file .
* /
2021-08-12 20:43:18 -07:00
function resolveConfigExtendsSync ( configFile , referenceId , fs ) {
2024-01-06 20:47:01 -08:00
const configFileDirname = path . dirname ( configFile ) ;
const resolvedExtendsFile = path . resolve ( configFileDirname , referenceId ) ;
2023-01-17 04:19:40 +00:00
try {
fs . accessSync ( resolvedExtendsFile ) ;
2020-11-24 16:37:11 -08:00
return resolvedExtendsFile ;
2024-01-06 20:47:01 -08:00
} catch {
2023-01-17 04:19:40 +00:00
// Not a file, try require.resolve
}
try {
return dynamicRequire . resolve ( referenceId , {
"paths" : [ configFileDirname ]
} ) ;
2024-01-06 20:47:01 -08:00
} catch {
2023-01-17 04:19:40 +00:00
// Unable to resolve, return resolvedExtendsFile
}
return resolvedExtendsFile ;
2020-11-24 16:37:11 -08:00
}
2023-01-17 04:19:40 +00:00
2023-04-03 22:59:06 -07:00
/ * *
* Extend specified configuration object .
*
* @ param { Configuration } config Configuration object .
* @ param { string } file Configuration file name .
* @ param { ConfigurationParser [ ] } parsers Parsing
* function ( s ) .
* @ param { Object } fs File system implementation .
* @ param { ReadConfigCallback } callback Callback ( err , result ) function .
* @ returns { void }
* /
function extendConfig ( config , file , parsers , fs , callback ) {
2024-01-06 20:47:01 -08:00
const configExtends = config . extends ;
2023-04-03 22:59:06 -07:00
if ( configExtends ) {
return resolveConfigExtends ( file , helpers . expandTildePath ( configExtends , _ _webpack _require _ _ ( /*! node:os */ "?e6c4" ) ) , fs ,
// eslint-disable-next-line no-use-before-define
2024-01-06 20:47:01 -08:00
( _ , resolvedExtends ) => readConfig (
// @ts-ignore
resolvedExtends , parsers , fs , ( err , extendsConfig ) => {
if ( err ) {
return callback ( err ) ;
}
const result = {
... extendsConfig ,
... config
} ;
delete result . extends ;
return callback ( null , result ) ;
} ) ) ;
2023-04-03 22:59:06 -07:00
}
return callback ( null , config ) ;
}
2024-01-06 20:47:01 -08:00
const extendConfigPromisify = promisify && promisify ( extendConfig ) ;
2023-04-03 22:59:06 -07:00
/ * *
* Extend specified configuration object .
*
* @ param { Configuration } config Configuration object .
* @ param { string } file Configuration file name .
* @ param { ConfigurationParser [ ] } [ parsers ] Parsing function ( s ) .
* @ param { Object } [ fs ] File system implementation .
* @ returns { Promise < Configuration > } Configuration object .
* /
function extendConfigPromise ( config , file , parsers , fs ) {
// @ts-ignore
return extendConfigPromisify ( config , file , parsers , fs ) ;
}
2019-10-02 20:10:42 -07:00
/ * *
* 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 ) .
2021-08-12 19:38:03 -07:00
* @ param { Object } [ fs ] File system implementation .
2020-01-27 19:19:34 -08:00
* @ param { ReadConfigCallback } [ callback ] Callback ( err , result ) function .
2019-10-02 20:10:42 -07:00
* @ returns { void }
* /
2021-08-12 19:38:03 -07:00
function readConfig ( file , parsers , fs , callback ) {
2023-01-17 04:19:40 +00:00
if ( ! callback ) {
if ( fs ) {
callback = fs ;
fs = null ;
} else {
// @ts-ignore
callback = parsers ;
// @ts-ignore
parsers = null ;
2021-08-12 19:38:03 -07:00
}
2023-01-17 04:19:40 +00:00
}
if ( ! fs ) {
fs = _ _webpack _require _ _ ( /*! node:fs */ "?d0ee" ) ;
}
// Read file
2023-04-03 22:59:06 -07:00
file = helpers . expandTildePath ( file , _ _webpack _require _ _ ( /*! node:os */ "?e6c4" ) ) ;
2024-01-06 20:47:01 -08:00
fs . readFile ( file , "utf8" , ( err , content ) => {
2023-01-17 04:19:40 +00:00
if ( err ) {
// @ts-ignore
return callback ( err ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
// Try to parse file
// @ts-ignore
2024-01-06 20:47:01 -08:00
const {
config ,
message
} = parseConfiguration ( file , content , parsers ) ;
2023-01-17 04:19:40 +00:00
if ( ! config ) {
// @ts-ignore
return callback ( new Error ( message ) ) ;
}
// Extend configuration
// @ts-ignore
2023-04-03 22:59:06 -07:00
return extendConfig ( config , file , parsers , fs , callback ) ;
2023-01-17 04:19:40 +00:00
} ) ;
2019-10-02 20:10:42 -07:00
}
2024-01-06 20:47:01 -08:00
const readConfigPromisify = promisify && promisify ( readConfig ) ;
2023-01-17 04:19:40 +00:00
2020-09-13 21:15:11 -07:00
/ * *
* Read specified configuration file .
*
* @ param { string } file Configuration file name .
* @ param { ConfigurationParser [ ] } [ parsers ] Parsing function ( s ) .
2021-08-12 19:38:03 -07:00
* @ param { Object } [ fs ] File system implementation .
2020-09-13 21:15:11 -07:00
* @ returns { Promise < Configuration > } Configuration object .
* /
2021-08-12 19:38:03 -07:00
function readConfigPromise ( file , parsers , fs ) {
2023-01-17 04:19:40 +00:00
// @ts-ignore
return readConfigPromisify ( file , parsers , fs ) ;
2020-09-13 21:15:11 -07:00
}
2023-01-17 04:19:40 +00:00
2019-10-02 20:10:42 -07:00
/ * *
* 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 ) .
2021-08-12 19:38:03 -07:00
* @ param { Object } [ fs ] File system implementation .
2019-12-14 13:50:48 -08:00
* @ returns { Configuration } Configuration object .
2021-08-22 18:03:26 -07:00
* @ throws An Error if processing fails .
2019-10-02 20:10:42 -07:00
* /
2021-08-12 19:38:03 -07:00
function readConfigSync ( file , parsers , fs ) {
2023-01-17 04:19:40 +00:00
if ( ! fs ) {
fs = _ _webpack _require _ _ ( /*! node:fs */ "?d0ee" ) ;
}
// Read file
2024-01-06 20:47:01 -08:00
const os = _ _webpack _require _ _ ( /*! node:os */ "?e6c4" ) ;
2023-01-17 04:19:40 +00:00
file = helpers . expandTildePath ( file , os ) ;
2024-01-06 20:47:01 -08:00
const content = fs . readFileSync ( file , "utf8" ) ;
2023-01-17 04:19:40 +00:00
// Try to parse file
2024-01-06 20:47:01 -08:00
const {
config ,
message
} = parseConfiguration ( file , content , parsers ) ;
2023-01-17 04:19:40 +00:00
if ( ! config ) {
throw new Error ( message ) ;
}
// Extend configuration
2024-01-06 20:47:01 -08:00
const configExtends = config . extends ;
2023-01-17 04:19:40 +00:00
if ( configExtends ) {
2024-01-06 20:47:01 -08:00
delete config . extends ;
const resolvedExtends = resolveConfigExtendsSync ( file , helpers . expandTildePath ( configExtends , os ) , fs ) ;
return {
... readConfigSync ( resolvedExtends , parsers , fs ) ,
... config
} ;
2023-01-17 04:19:40 +00:00
}
return config ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
2020-10-20 20:16:49 -07:00
/ * *
* Gets the ( semantic ) version of the library .
*
* @ returns { string } SemVer string .
* /
function getVersion ( ) {
2023-01-17 04:19:40 +00:00
return ( _ _webpack _require _ _ ( /*! ./constants */ "../lib/constants.js" ) . version ) ;
2020-10-20 20:16:49 -07:00
}
2023-01-17 04:19:40 +00:00
2020-09-13 21:15:11 -07:00
// Export a/synchronous/Promise APIs
2019-10-02 20:10:42 -07:00
markdownlint . sync = markdownlintSync ;
markdownlint . readConfig = readConfig ;
markdownlint . readConfigSync = readConfigSync ;
2020-10-20 20:16:49 -07:00
markdownlint . getVersion = getVersion ;
2020-09-13 21:15:11 -07:00
markdownlint . promises = {
2023-01-17 04:19:40 +00:00
"markdownlint" : markdownlintPromise ,
2023-04-03 22:59:06 -07:00
"extendConfig" : extendConfigPromise ,
2023-01-17 04:19:40 +00:00
"readConfig" : readConfigPromise
2020-09-13 21:15:11 -07:00
} ;
2019-10-02 20:10:42 -07:00
module . exports = markdownlint ;
2023-01-17 04:19:40 +00:00
// Type declarations
/ * *
* Function to implement rule logic .
*
* @ callback RuleFunction
* @ param { RuleParams } params Rule parameters .
* @ param { RuleOnError } onError Error - reporting callback .
* @ returns { void }
* /
/ * *
* Rule parameters .
*
* @ typedef { Object } RuleParams
* @ property { string } name File / string name .
* @ property { MarkdownItToken [ ] } tokens Token objects from markdown - it .
* @ property { string [ ] } lines File / string lines .
* @ property { string [ ] } frontMatterLines Front matter lines .
* @ property { RuleConfiguration } config Rule configuration .
* /
/ * *
* Markdown - It token .
*
* @ typedef { Object } MarkdownItToken
* @ property { string [ ] [ ] } attrs HTML attributes .
* @ property { boolean } block Block - level token .
* @ property { MarkdownItToken [ ] } children Child nodes .
* @ property { string } content Tag contents .
* @ property { boolean } hidden Ignore element .
* @ property { string } info Fence info .
* @ property { number } level Nesting level .
* @ property { number [ ] } map Beginning / ending line numbers .
* @ property { string } markup Markup text .
* @ property { Object } meta Arbitrary data .
* @ property { number } nesting Level change .
* @ property { string } tag HTML tag name .
* @ property { string } type Token type .
* @ property { number } lineNumber Line number ( 1 - based ) .
* @ property { string } line Line content .
* /
/ * *
* Error - reporting callback .
*
* @ callback RuleOnError
* @ param { RuleOnErrorInfo } onErrorInfo Error information .
* @ returns { void }
* /
/ * *
* Fix information for RuleOnError callback .
*
* @ typedef { Object } RuleOnErrorInfo
* @ property { number } lineNumber Line number ( 1 - based ) .
* @ property { string } [ detail ] Detail about the error .
* @ property { string } [ context ] Context for the error .
2023-07-11 21:44:45 -07:00
* @ property { URL } [ information ] Link to more information .
2023-01-17 04:19:40 +00:00
* @ property { number [ ] } [ range ] Column number ( 1 - based ) and length .
* @ property { RuleOnErrorFixInfo } [ fixInfo ] Fix information .
* /
/ * *
* Fix information for RuleOnErrorInfo .
*
* @ typedef { Object } RuleOnErrorFixInfo
* @ property { number } [ lineNumber ] Line number ( 1 - based ) .
* @ property { number } [ editColumn ] Column of the fix ( 1 - based ) .
* @ property { number } [ deleteCount ] Count of characters to delete .
* @ property { string } [ insertText ] Text to insert ( after deleting ) .
* /
/ * *
* Rule definition .
*
* @ typedef { Object } Rule
* @ property { string [ ] } names Rule name ( s ) .
* @ property { string } description Rule description .
* @ property { URL } [ information ] Link to more information .
* @ property { string [ ] } tags Rule tag ( s ) .
* @ property { boolean } [ asynchronous ] True if asynchronous .
* @ property { RuleFunction } function Rule implementation .
* /
/ * *
* Configuration options .
*
* @ typedef { Object } Options
* @ property { Configuration } [ config ] Configuration object .
* @ property { ConfigurationParser [ ] } [ configParsers ] Configuration parsers .
* @ property { Rule [ ] | Rule } [ customRules ] Custom rules .
* @ property { string [ ] | string } [ files ] Files to lint .
2023-01-29 21:13:17 -08:00
* @ property { RegExp | null } [ frontMatter ] Front matter pattern .
2023-01-17 04:19:40 +00:00
* @ property { Object } [ fs ] File system implementation .
* @ property { boolean } [ handleRuleFailures ] True to catch exceptions .
* @ property { Plugin [ ] } [ markdownItPlugins ] Additional plugins .
* @ property { boolean } [ noInlineConfig ] True to ignore HTML directives .
* @ property { number } [ resultVersion ] Results object version .
* @ property { Object . < string , string > } [ strings ] Strings to lint .
* /
/ * *
* A markdown - it plugin .
*
* @ typedef { Array } Plugin
* /
/ * *
* Function to pretty - print lint results .
*
* @ callback ToStringCallback
* @ param { boolean } [ ruleAliases ] True to use rule aliases .
* @ returns { string }
* /
/ * *
* Lint results ( for resultVersion 3 ) .
*
* @ typedef { Object . < string , LintError [ ] > } LintResults
* @ property { ToStringCallback } toString String representation .
* /
/ * *
* Lint error .
*
* @ typedef { Object } LintError
* @ property { number } lineNumber Line number ( 1 - based ) .
* @ property { string [ ] } ruleNames Rule name ( s ) .
* @ property { string } ruleDescription Rule description .
* @ property { string } ruleInformation Link to more information .
* @ property { string } errorDetail Detail about the error .
* @ property { string } errorContext Context for the error .
* @ property { number [ ] } errorRange Column number ( 1 - based ) and length .
* @ property { FixInfo } [ fixInfo ] Fix information .
* /
/ * *
* Fix information .
*
* @ typedef { Object } FixInfo
* @ property { number } [ lineNumber ] Line number ( 1 - based ) .
* @ property { number } [ editColumn ] Column of the fix ( 1 - based ) .
* @ property { number } [ deleteCount ] Count of characters to delete .
* @ property { string } [ insertText ] Text to insert ( after deleting ) .
* /
2023-09-04 21:41:16 -07:00
/ * *
* Called with the result of linting a string or document .
*
* @ callback LintContentCallback
* @ param { Error | null } error Error iff failed .
* @ param { LintError [ ] } [ result ] Result iff successful .
* @ returns { void }
* /
2023-01-17 04:19:40 +00:00
/ * *
* Called with the result of the lint function .
*
* @ callback LintCallback
2023-09-04 21:41:16 -07:00
* @ param { Error | null } error Error object iff failed .
* @ param { LintResults } [ results ] Lint results iff succeeded .
2023-01-17 04:19:40 +00:00
* @ returns { void }
* /
/ * *
2023-11-08 19:49:02 -08:00
* Configuration object for linting rules . For the JSON schema , see
2023-01-17 04:19:40 +00:00
* { @ link . . / schema / markdownlint - config - schema . json } .
*
2023-11-08 19:49:02 -08:00
* @ typedef { import ( "./configuration" ) . Configuration } Configuration
2023-01-17 04:19:40 +00:00
* /
/ * *
* Rule configuration object .
*
* @ typedef { boolean | Object } RuleConfiguration Rule configuration .
* /
/ * *
* Parses a configuration string and returns a configuration object .
*
* @ callback ConfigurationParser
* @ param { string } text Configuration string .
* @ returns { Configuration }
* /
/ * *
* Called with the result of the readConfig function .
*
* @ callback ReadConfigCallback
* @ param { Error | null } err Error object or null .
* @ param { Configuration } [ config ] Configuration object .
* @ returns { void }
* /
/ * *
* Called with the result of the resolveConfigExtends function .
*
* @ callback ResolveConfigExtendsCallback
* @ param { Error | null } err Error object or null .
* @ param { string } [ path ] Resolved path to file .
* @ returns { void }
* /
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md001.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md001 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf ,
filterTokens
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-11-09 20:05:30 -08:00
"names" : [ "MD001" , "heading-increment" ] ,
2023-01-17 04:19:40 +00:00
"description" : "Heading levels should only increment by one level at a time" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD001 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let prevLevel = 0 ;
2023-01-17 04:19:40 +00:00
filterTokens ( params , "heading_open" , function forToken ( token ) {
2024-01-06 20:47:01 -08:00
const level = Number . parseInt ( token . tag . slice ( 1 ) , 10 ) ;
2023-01-17 04:19:40 +00:00
if ( prevLevel && level > prevLevel ) {
addErrorDetailIf ( onError , token . lineNumber , "h" + ( prevLevel + 1 ) , "h" + level ) ;
}
prevLevel = level ;
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md003.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md003 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf ,
filterTokens ,
headingStyleFor
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-11-09 20:05:30 -08:00
"names" : [ "MD003" , "heading-style" ] ,
2023-01-17 04:19:40 +00:00
"description" : "Heading style" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD003 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let style = String ( params . config . style || "consistent" ) ;
2023-01-17 04:19:40 +00:00
filterTokens ( params , "heading_open" , function forToken ( token ) {
2024-01-06 20:47:01 -08:00
const styleForToken = headingStyleFor ( token ) ;
2023-01-17 04:19:40 +00:00
if ( style === "consistent" ) {
style = styleForToken ;
}
if ( styleForToken !== style ) {
2024-01-06 20:47:01 -08:00
const h12 = /h[12]/ . test ( token . tag ) ;
const setextWithAtx = style === "setext_with_atx" && ( h12 && styleForToken === "setext" || ! h12 && styleForToken === "atx" ) ;
const setextWithAtxClosed = style === "setext_with_atx_closed" && ( h12 && styleForToken === "setext" || ! h12 && styleForToken === "atx_closed" ) ;
2023-01-17 04:19:40 +00:00
if ( ! setextWithAtx && ! setextWithAtxClosed ) {
2024-01-06 20:47:01 -08:00
let expected = style ;
2023-01-17 04:19:40 +00:00
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 ) ;
}
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md004.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md004 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf ,
listItemMarkerRe ,
unorderedListStyleFor
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
flattenedLists
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
const expectedStyleToMarker = {
2023-01-17 04:19:40 +00:00
"dash" : "-" ,
"plus" : "+" ,
"asterisk" : "*"
2021-02-06 15:49:02 -08:00
} ;
2024-01-06 20:47:01 -08:00
const differentItemStyle = {
2023-01-17 04:19:40 +00:00
"dash" : "plus" ,
"plus" : "asterisk" ,
"asterisk" : "dash"
2021-02-06 15:49:02 -08:00
} ;
2024-01-06 20:47:01 -08:00
const validStyles = Object . keys ( expectedStyleToMarker ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD004" , "ul-style" ] ,
"description" : "Unordered list style" ,
"tags" : [ "bullet" , "ul" ] ,
"function" : function MD004 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const style = String ( params . config . style || "consistent" ) ;
let expectedStyle = style ;
const nestingStyles = [ ] ;
for ( const list of flattenedLists ( ) ) {
if ( list . unordered ) {
if ( expectedStyle === "consistent" ) {
expectedStyle = unorderedListStyleFor ( list . items [ 0 ] ) ;
}
for ( const item of list . items ) {
const itemStyle = unorderedListStyleFor ( item ) ;
if ( style === "sublist" ) {
const nesting = list . nesting ;
if ( ! nestingStyles [ nesting ] ) {
nestingStyles [ nesting ] = itemStyle === nestingStyles [ nesting - 1 ] ? differentItemStyle [ itemStyle ] : itemStyle ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
expectedStyle = nestingStyles [ nesting ] ;
}
if ( ! validStyles . includes ( expectedStyle ) ) {
expectedStyle = validStyles [ 0 ] ;
}
let range = null ;
let fixInfo = null ;
const match = item . line . match ( listItemMarkerRe ) ;
if ( match ) {
const column = match . index + 1 ;
const length = match [ 0 ] . length ;
range = [ column , length ] ;
fixInfo = {
"editColumn" : match [ 1 ] . length + 1 ,
"deleteCount" : 1 ,
"insertText" : expectedStyleToMarker [ expectedStyle ]
} ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
addErrorDetailIf ( onError , item . lineNumber , expectedStyle , itemStyle , null , null , range , fixInfo ) ;
2023-01-17 04:19:40 +00:00
}
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md005.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md005 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
addErrorDetailIf
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes ,
inHtmlFlow
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD005" , "list-indent" ] ,
"description" : "Inconsistent indentation for list items at the same level" ,
"tags" : [ "bullet" , "ul" , "indentation" ] ,
"function" : function MD005 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const lists = filterByTypes ( params . parsers . micromark . tokens , [ "listOrdered" , "listUnordered" ] ) . filter ( list => ! inHtmlFlow ( list ) ) ;
for ( const list of lists ) {
const expectedIndent = list . startColumn - 1 ;
let expectedEnd = 0 ;
let endMatching = false ;
const listItemPrefixes = list . children . filter ( token => token . type === "listItemPrefix" ) ;
for ( const listItemPrefix of listItemPrefixes ) {
const lineNumber = listItemPrefix . startLine ;
const actualIndent = listItemPrefix . startColumn - 1 ;
const range = [ 1 , listItemPrefix . endColumn - 1 ] ;
if ( list . type === "listUnordered" ) {
addErrorDetailIf ( onError , lineNumber , expectedIndent , actualIndent , null , null , range
// No fixInfo; MD007 handles this scenario better
) ;
} else {
const markerLength = listItemPrefix . text . trim ( ) . length ;
const actualEnd = listItemPrefix . startColumn + markerLength - 1 ;
expectedEnd = expectedEnd || actualEnd ;
if ( expectedIndent !== actualIndent || endMatching ) {
if ( expectedEnd === actualEnd ) {
endMatching = true ;
2023-10-12 21:43:31 -07:00
} else {
2024-01-06 20:47:01 -08:00
const detail = endMatching ? ` Expected: ( ${ expectedEnd } ); Actual: ( ${ actualEnd } ) ` : ` Expected: ${ expectedIndent } ; Actual: ${ actualIndent } ` ;
const expected = endMatching ? expectedEnd - markerLength : expectedIndent ;
const actual = endMatching ? actualEnd - markerLength : actualIndent ;
addError ( onError , lineNumber , detail , undefined , range , {
"editColumn" : Math . min ( actual , expected ) + 1 ,
"deleteCount" : Math . max ( actual - expected , 0 ) ,
"insertText" : "" . padEnd ( Math . max ( expected - actual , 0 ) )
} ) ;
2023-01-17 04:19:40 +00:00
}
}
}
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md007.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md007 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes ,
getTokenParentOfType ,
inHtmlFlow
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
2023-10-19 23:01:31 -07:00
/ * *
* @ typedef { import ( "../helpers/micromark.cjs" ) . Token } Token
* /
2024-01-06 20:47:01 -08:00
const unorderedListTypes = [ "blockQuotePrefix" , "listItemPrefix" , "listUnordered" ] ;
const unorderedParentTypes = [ "blockQuote" , "listOrdered" , "listUnordered" ] ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD007" , "ul-indent" ] ,
"description" : "Unordered list indentation" ,
"tags" : [ "bullet" , "ul" , "indentation" ] ,
"function" : function MD007 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const indent = Number ( params . config . indent || 2 ) ;
const startIndented = ! ! params . config . start _indented ;
const startIndent = Number ( params . config . start _indent || indent ) ;
const unorderedListNesting = new Map ( ) ;
let lastBlockQuotePrefix = null ;
const tokens = filterByTypes ( params . parsers . micromark . tokens , unorderedListTypes ) ;
for ( const token of tokens ) {
const {
endColumn ,
parent ,
startColumn ,
startLine ,
type
} = token ;
if ( type === "blockQuotePrefix" ) {
lastBlockQuotePrefix = token ;
} else if ( type === "listUnordered" ) {
let nesting = 0 ;
/** @type {Token | null} */
let current = token ;
while ( current = getTokenParentOfType ( current , unorderedParentTypes ) ) {
if ( current . type === "listUnordered" ) {
nesting ++ ;
// eslint-disable-next-line no-continue
continue ;
} else if ( current . type === "listOrdered" ) {
nesting = - 1 ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
break ;
}
if ( nesting >= 0 ) {
unorderedListNesting . set ( token , nesting ) ;
}
} else if ( ! inHtmlFlow ( token ) ) {
// listItemPrefix
const nesting = unorderedListNesting . get ( parent ) ;
if ( nesting !== undefined ) {
// listItemPrefix for listUnordered
const expectedIndent = ( startIndented ? startIndent : 0 ) + nesting * indent ;
const blockQuoteAdjustment = lastBlockQuotePrefix ? . endLine === startLine ? lastBlockQuotePrefix . endColumn - 1 : 0 ;
const actualIndent = startColumn - 1 - blockQuoteAdjustment ;
const range = [ 1 , endColumn - 1 ] ;
const fixInfo = {
"editColumn" : startColumn - actualIndent ,
"deleteCount" : Math . max ( actualIndent - expectedIndent , 0 ) ,
"insertText" : "" . padEnd ( Math . max ( expectedIndent - actualIndent , 0 ) )
} ;
addErrorDetailIf ( onError , startLine , expectedIndent , actualIndent , undefined , undefined , range , fixInfo ) ;
2023-01-17 04:19:40 +00:00
}
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md009.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md009 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
filterTokens ,
forEachLine ,
includesSorted ,
numericSortAscending
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
lineMetadata
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD009" , "no-trailing-spaces" ] ,
"description" : "Trailing spaces" ,
"tags" : [ "whitespace" ] ,
"function" : function MD009 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let brSpaces = params . config . br _spaces ;
2023-01-17 04:19:40 +00:00
brSpaces = Number ( brSpaces === undefined ? 2 : brSpaces ) ;
2024-01-06 20:47:01 -08:00
const listItemEmptyLines = ! ! params . config . list _item _empty _lines ;
const strict = ! ! params . config . strict ;
const listItemLineNumbers = [ ] ;
2023-01-17 04:19:40 +00:00
if ( listItemEmptyLines ) {
2024-01-06 20:47:01 -08:00
filterTokens ( params , "list_item_open" , token => {
for ( let i = token . map [ 0 ] ; i < token . map [ 1 ] ; i ++ ) {
2023-01-17 04:19:40 +00:00
listItemLineNumbers . push ( i + 1 ) ;
}
} ) ;
listItemLineNumbers . sort ( numericSortAscending ) ;
}
2024-01-06 20:47:01 -08:00
const paragraphLineNumbers = [ ] ;
const codeInlineLineNumbers = [ ] ;
2023-01-17 04:19:40 +00:00
if ( strict ) {
2024-01-06 20:47:01 -08:00
filterTokens ( params , "paragraph_open" , token => {
for ( let i = token . map [ 0 ] ; i < token . map [ 1 ] - 1 ; i ++ ) {
2023-01-17 04:19:40 +00:00
paragraphLineNumbers . push ( i + 1 ) ;
}
} ) ;
2024-01-06 20:47:01 -08:00
const addLineNumberRange = ( start , end ) => {
for ( let i = start ; i < end ; i ++ ) {
2023-01-17 04:19:40 +00:00
codeInlineLineNumbers . push ( i ) ;
}
} ;
2024-01-06 20:47:01 -08:00
filterTokens ( params , "inline" , token => {
let start = 0 ;
for ( const child of token . children ) {
if ( start > 0 ) {
addLineNumberRange ( start , child . lineNumber ) ;
start = 0 ;
}
if ( child . type === "code_inline" ) {
start = child . lineNumber ;
2023-01-17 04:19:40 +00:00
}
2019-12-14 13:50:48 -08:00
}
2023-01-17 04:19:40 +00:00
if ( start > 0 ) {
addLineNumberRange ( start , token . map [ 1 ] ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
} ) ;
2019-10-02 20:10:42 -07:00
}
2024-01-06 20:47:01 -08:00
const expected = brSpaces < 2 ? 0 : brSpaces ;
forEachLine ( lineMetadata ( ) , ( line , lineIndex , inCode ) => {
const lineNumber = lineIndex + 1 ;
const trailingSpaces = line . length - line . trimEnd ( ) . length ;
2023-01-17 04:19:40 +00:00
if ( trailingSpaces && ! inCode && ! includesSorted ( listItemLineNumbers , lineNumber ) && ( expected !== trailingSpaces || strict && ( ! includesSorted ( paragraphLineNumbers , lineNumber ) || includesSorted ( codeInlineLineNumbers , lineNumber ) ) ) ) {
2024-01-06 20:47:01 -08:00
const column = line . length - trailingSpaces + 1 ;
2023-01-17 04:19:40 +00:00
addError ( onError , lineNumber , "Expected: " + ( expected === 0 ? "" : "0 or " ) + expected + "; Actual: " + trailingSpaces , undefined , [ column , trailingSpaces ] , {
"editColumn" : column ,
"deleteCount" : trailingSpaces
} ) ;
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md010.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md010 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
filterTokens ,
forEachLine ,
withinAnyRange
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
codeBlockAndSpanRanges ,
lineMetadata
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
const tabRe = /\t+/g ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD010" , "no-hard-tabs" ] ,
"description" : "Hard tabs" ,
"tags" : [ "whitespace" , "hard_tab" ] ,
"function" : function MD010 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const codeBlocks = params . config . code _blocks ;
const includeCode = codeBlocks === undefined ? true : ! ! codeBlocks ;
const ignoreCodeLanguages = new Set ( ( params . config . ignore _code _languages || [ ] ) . map ( language => language . toLowerCase ( ) ) ) ;
const spacesPerTab = params . config . spaces _per _tab ;
const spaceMultiplier = spacesPerTab === undefined ? 1 : Math . max ( 0 , Number ( spacesPerTab ) ) ;
const exclusions = includeCode ? [ ] : codeBlockAndSpanRanges ( ) ;
filterTokens ( params , "fence" , token => {
const language = token . info . trim ( ) . toLowerCase ( ) ;
2023-01-17 04:19:40 +00:00
if ( ignoreCodeLanguages . has ( language ) ) {
2024-01-06 20:47:01 -08:00
for ( let i = token . map [ 0 ] + 1 ; i < token . map [ 1 ] - 1 ; i ++ ) {
2023-01-17 04:19:40 +00:00
exclusions . push ( [ i , 0 , params . lines [ i ] . length ] ) ;
}
}
} ) ;
2024-01-06 20:47:01 -08:00
forEachLine ( lineMetadata ( ) , ( line , lineIndex , inCode ) => {
2023-01-17 04:19:40 +00:00
if ( includeCode || ! inCode ) {
2024-01-06 20:47:01 -08:00
let match = null ;
2023-01-17 04:19:40 +00:00
while ( ( match = tabRe . exec ( line ) ) !== null ) {
2024-01-06 20:47:01 -08:00
const {
index
} = match ;
const column = index + 1 ;
const length = match [ 0 ] . length ;
2023-01-17 04:19:40 +00:00
if ( ! withinAnyRange ( exclusions , lineIndex , index , length ) ) {
addError ( onError , lineIndex + 1 , "Column: " + column , null , [ column , length ] , {
"editColumn" : column ,
"deleteCount" : length ,
"insertText" : "" . padEnd ( length * spaceMultiplier )
} ) ;
}
}
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md011.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md011 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
forEachLine ,
withinAnyRange
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
codeBlockAndSpanRanges ,
lineMetadata
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
const reversedLinkRe = /(^|[^\\])\(([^()]+)\)\[([^\]^][^\]]*)\](?!\()/g ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD011" , "no-reversed-links" ] ,
"description" : "Reversed link syntax" ,
"tags" : [ "links" ] ,
"function" : function MD011 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const exclusions = codeBlockAndSpanRanges ( ) ;
forEachLine ( lineMetadata ( ) , ( line , lineIndex , inCode , onFence ) => {
2023-01-17 04:19:40 +00:00
if ( ! inCode && ! onFence ) {
2024-01-06 20:47:01 -08:00
let match = null ;
2023-01-17 04:19:40 +00:00
while ( ( match = reversedLinkRe . exec ( line ) ) !== null ) {
2024-01-06 20:47:01 -08:00
const [ reversedLink , preChar , linkText , linkDestination ] = match ;
const index = match . index + preChar . length ;
const length = match [ 0 ] . length - preChar . length ;
2023-01-17 04:19:40 +00:00
if ( ! linkText . endsWith ( "\\" ) && ! linkDestination . endsWith ( "\\" ) && ! withinAnyRange ( exclusions , lineIndex , index , length ) ) {
addError ( onError , lineIndex + 1 , reversedLink . slice ( preChar . length ) , undefined , [ index + 1 , length ] , {
"editColumn" : index + 1 ,
"deleteCount" : length ,
2024-01-06 20:47:01 -08:00
"insertText" : ` [ ${ linkText } ]( ${ linkDestination } ) `
2023-01-17 04:19:40 +00:00
} ) ;
}
}
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md012.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md012 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf ,
forEachLine
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
lineMetadata
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD012" , "no-multiple-blanks" ] ,
"description" : "Multiple consecutive blank lines" ,
"tags" : [ "whitespace" , "blank_lines" ] ,
"function" : function MD012 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const maximum = Number ( params . config . maximum || 1 ) ;
let count = 0 ;
forEachLine ( lineMetadata ( ) , ( line , lineIndex , inCode ) => {
2023-01-17 04:19:40 +00:00
count = inCode || line . trim ( ) . length > 0 ? 0 : count + 1 ;
if ( maximum < count ) {
addErrorDetailIf ( onError , lineIndex + 1 , maximum , count , null , null , null , {
"deleteCount" : - 1
2019-10-02 20:10:42 -07:00
} ) ;
2023-01-17 04:19:40 +00:00
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md013.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md013 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf ,
filterTokens ,
forEachHeading ,
forEachLine ,
includesSorted
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
lineMetadata ,
referenceLinkImageData
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
const longLineRePrefix = "^.{" ;
const longLineRePostfixRelaxed = "}.*\\s.*$" ;
const longLineRePostfixStrict = "}.+$" ;
const linkOrImageOnlyLineRe = /^[es]*(?:lT?L|I)[ES]*$/ ;
const sternModeRe = /^(?:[#>\s]*\s)?\S*$/ ;
const tokenTypeMap = {
2023-01-17 04:19:40 +00:00
"em_open" : "e" ,
"em_close" : "E" ,
"image" : "I" ,
"link_open" : "l" ,
"link_close" : "L" ,
"strong_open" : "s" ,
"strong_close" : "S" ,
"text" : "T"
2019-10-02 20:10:42 -07:00
} ;
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD013" , "line-length" ] ,
"description" : "Line length" ,
"tags" : [ "line_length" ] ,
"function" : function MD013 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const lineLength = Number ( params . config . line _length || 80 ) ;
const headingLineLength = Number ( params . config . heading _line _length || lineLength ) ;
const codeLineLength = Number ( params . config . code _block _line _length || lineLength ) ;
const strict = ! ! params . config . strict ;
const stern = ! ! params . config . stern ;
const longLineRePostfix = strict || stern ? longLineRePostfixStrict : longLineRePostfixRelaxed ;
const longLineRe = new RegExp ( longLineRePrefix + lineLength + longLineRePostfix ) ;
const longHeadingLineRe = new RegExp ( longLineRePrefix + headingLineLength + longLineRePostfix ) ;
const longCodeLineRe = new RegExp ( longLineRePrefix + codeLineLength + longLineRePostfix ) ;
const codeBlocks = params . config . code _blocks ;
const includeCodeBlocks = codeBlocks === undefined ? true : ! ! codeBlocks ;
const tables = params . config . tables ;
const includeTables = tables === undefined ? true : ! ! tables ;
const headings = params . config . headings ;
const includeHeadings = headings === undefined ? true : ! ! headings ;
const headingLineNumbers = [ ] ;
forEachHeading ( params , heading => {
2023-01-17 04:19:40 +00:00
headingLineNumbers . push ( heading . lineNumber ) ;
} ) ;
2024-01-06 20:47:01 -08:00
const linkOnlyLineNumbers = [ ] ;
filterTokens ( params , "inline" , token => {
let childTokenTypes = "" ;
for ( const child of token . children ) {
if ( child . type !== "text" || child . content !== "" ) {
childTokenTypes += tokenTypeMap [ child . type ] || "x" ;
2023-01-17 04:19:40 +00:00
}
}
if ( linkOrImageOnlyLineRe . test ( childTokenTypes ) ) {
linkOnlyLineNumbers . push ( token . lineNumber ) ;
}
} ) ;
2024-01-06 20:47:01 -08:00
const {
definitionLineIndices
} = referenceLinkImageData ( ) ;
forEachLine ( lineMetadata ( ) , ( line , lineIndex , inCode , onFence , inTable ) => {
const lineNumber = lineIndex + 1 ;
const isHeading = includesSorted ( headingLineNumbers , lineNumber ) ;
const length = inCode ? codeLineLength : isHeading ? headingLineLength : lineLength ;
const lengthRe = inCode ? longCodeLineRe : isHeading ? longHeadingLineRe : longLineRe ;
2023-01-17 04:19:40 +00:00
if ( ( includeCodeBlocks || ! inCode ) && ( includeTables || ! inTable ) && ( includeHeadings || ! isHeading ) && ! includesSorted ( definitionLineIndices , lineIndex ) && ( strict || ! ( stern && sternModeRe . test ( line ) ) && ! includesSorted ( linkOnlyLineNumbers , lineNumber ) ) && lengthRe . test ( line ) ) {
addErrorDetailIf ( onError , lineNumber , length , line . length , null , null , [ length + 1 , line . length - length ] ) ;
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md014.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md014 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
filterTokens
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const dollarCommandRe = /^(\s*)(\$\s+)/ ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD014" , "commands-show-output" ] ,
"description" : "Dollar signs used before commands without showing output" ,
"tags" : [ "code" ] ,
"function" : function MD014 ( params , onError ) {
2024-01-06 20:47:01 -08:00
for ( const type of [ "code_block" , "fence" ] ) {
filterTokens ( params , type , token => {
const margin = token . type === "fence" ? 1 : 0 ;
const dollarInstances = [ ] ;
let allDollars = true ;
for ( let i = token . map [ 0 ] + margin ; i < token . map [ 1 ] - margin ; i ++ ) {
const line = params . lines [ i ] ;
const lineTrim = line . trim ( ) ;
2023-01-17 04:19:40 +00:00
if ( lineTrim ) {
2024-01-06 20:47:01 -08:00
const match = dollarCommandRe . exec ( line ) ;
2023-01-17 04:19:40 +00:00
if ( match ) {
2024-01-06 20:47:01 -08:00
const column = match [ 1 ] . length + 1 ;
const length = match [ 2 ] . length ;
2023-01-17 04:19:40 +00:00
dollarInstances . push ( [ i , lineTrim , column , length ] ) ;
} else {
allDollars = false ;
}
}
}
if ( allDollars ) {
2024-01-06 20:47:01 -08:00
for ( const instance of dollarInstances ) {
const [ i , lineTrim , column , length ] = instance ;
addErrorContext ( onError , i + 1 , lineTrim , null , null , [ column , length ] , {
"editColumn" : column ,
"deleteCount" : length
} ) ;
2023-01-17 04:19:40 +00:00
}
}
} ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md018.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md018 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
forEachLine
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
lineMetadata
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD018" , "no-missing-space-atx" ] ,
"description" : "No space after hash on atx style heading" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" , "atx" , "spaces" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD018 ( params , onError ) {
2024-01-06 20:47:01 -08:00
forEachLine ( lineMetadata ( ) , ( line , lineIndex , inCode ) => {
2023-01-17 04:19:40 +00:00
if ( ! inCode && /^#+[^# \t]/ . test ( line ) && ! /#\s*$/ . test ( line ) && ! line . startsWith ( "#️⃣" ) ) {
2024-01-06 20:47:01 -08:00
const hashCount = /^#+/ . exec ( line ) [ 0 ] . length ;
2023-01-17 04:19:40 +00:00
addErrorContext ( onError , lineIndex + 1 , line . trim ( ) , null , null , [ 1 , hashCount + 1 ] , {
"editColumn" : hashCount + 1 ,
"insertText" : " "
2019-10-02 20:10:42 -07:00
} ) ;
2023-01-17 04:19:40 +00:00
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md019.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md019 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
filterTokens ,
headingStyleFor
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD019" , "no-multiple-space-atx" ] ,
"description" : "Multiple spaces after hash on atx style heading" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" , "atx" , "spaces" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD019 ( params , onError ) {
2024-01-06 20:47:01 -08:00
filterTokens ( params , "heading_open" , token => {
2023-01-17 04:19:40 +00:00
if ( headingStyleFor ( token ) === "atx" ) {
2024-01-06 20:47:01 -08:00
const {
line ,
lineNumber
} = token ;
const match = /^(#+)([ \t]{2,})\S/ . exec ( line ) ;
2023-01-17 04:19:40 +00:00
if ( match ) {
2024-01-06 20:47:01 -08:00
const [ , {
"length" : hashLength
} , {
"length" : spacesLength
} ] = match ;
2023-01-17 04:19:40 +00:00
addErrorContext ( onError , lineNumber , line . trim ( ) , null , null , [ 1 , hashLength + spacesLength + 1 ] , {
"editColumn" : hashLength + 1 ,
"deleteCount" : spacesLength - 1
} ) ;
}
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md020.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md020 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
forEachLine
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
lineMetadata
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD020" , "no-missing-space-closed-atx" ] ,
"description" : "No space inside hashes on closed atx style heading" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" , "atx_closed" , "spaces" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD020 ( params , onError ) {
2024-01-06 20:47:01 -08:00
forEachLine ( lineMetadata ( ) , ( line , lineIndex , inCode ) => {
2023-01-17 04:19:40 +00:00
if ( ! inCode ) {
2024-01-06 20:47:01 -08:00
const match = /^(#+)([ \t]*)([^#]*?[^#\\])([ \t]*)((?:\\#)?)(#+)(\s*)$/ . exec ( line ) ;
2023-01-17 04:19:40 +00:00
if ( match ) {
2024-01-06 20:47:01 -08:00
const [ , leftHash , {
"length" : leftSpaceLength
} , content , {
"length" : rightSpaceLength
} , rightEscape , rightHash , {
"length" : trailSpaceLength
} ] = match ;
const leftHashLength = leftHash . length ;
const rightHashLength = rightHash . length ;
const left = ! leftSpaceLength ;
const right = ! rightSpaceLength || rightEscape ;
const rightEscapeReplacement = rightEscape ? ` ${ rightEscape } ` : "" ;
2023-01-17 04:19:40 +00:00
if ( left || right ) {
2024-01-06 20:47:01 -08:00
const range = left ? [ 1 , leftHashLength + 1 ] : [ line . length - trailSpaceLength - rightHashLength , rightHashLength + 1 ] ;
2023-01-17 04:19:40 +00:00
addErrorContext ( onError , lineIndex + 1 , line . trim ( ) , left , right , range , {
"editColumn" : 1 ,
"deleteCount" : line . length ,
2024-01-06 20:47:01 -08:00
"insertText" : ` ${ leftHash } ${ content } ${ rightEscapeReplacement } ${ rightHash } `
2023-01-17 04:19:40 +00:00
} ) ;
}
}
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md021.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md021 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
filterTokens ,
headingStyleFor
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const closedAtxRe = /^(#+)([ \t]+)([^ \t]|[^ \t].*[^ \t])([ \t]+)(#+)(\s*)$/ ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD021" , "no-multiple-space-closed-atx" ] ,
"description" : "Multiple spaces inside hashes on closed atx style heading" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" , "atx_closed" , "spaces" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD021 ( params , onError ) {
2024-01-06 20:47:01 -08:00
filterTokens ( params , "heading_open" , token => {
2023-01-17 04:19:40 +00:00
if ( headingStyleFor ( token ) === "atx_closed" ) {
2024-01-06 20:47:01 -08:00
const {
line ,
lineNumber
} = token ;
const match = closedAtxRe . exec ( line ) ;
2023-01-17 04:19:40 +00:00
if ( match ) {
2024-01-06 20:47:01 -08:00
const [ , leftHash , {
"length" : leftSpaceLength
} , content , {
"length" : rightSpaceLength
} , rightHash , {
"length" : trailSpaceLength
} ] = match ;
const left = leftSpaceLength > 1 ;
const right = rightSpaceLength > 1 ;
2023-01-17 04:19:40 +00:00
if ( left || right ) {
2024-01-06 20:47:01 -08:00
const length = line . length ;
const leftHashLength = leftHash . length ;
const rightHashLength = rightHash . length ;
const range = left ? [ 1 , leftHashLength + leftSpaceLength + 1 ] : [ length - trailSpaceLength - rightHashLength - rightSpaceLength , rightSpaceLength + rightHashLength + 1 ] ;
2023-01-17 04:19:40 +00:00
addErrorContext ( onError , lineNumber , line . trim ( ) , left , right , range , {
"editColumn" : 1 ,
"deleteCount" : length ,
2024-01-06 20:47:01 -08:00
"insertText" : ` ${ leftHash } ${ content } ${ rightHash } `
2023-01-17 04:19:40 +00:00
} ) ;
}
}
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md022.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md022 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf ,
blockquotePrefixRe ,
isBlankLine
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes ,
getHeadingLevel ,
inHtmlFlow
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
const defaultLines = 1 ;
const getLinesFunction = linesParam => {
2023-08-08 22:56:47 -07:00
if ( Array . isArray ( linesParam ) ) {
2024-01-06 20:47:01 -08:00
const linesArray = new Array ( 6 ) . fill ( defaultLines ) ;
for ( const [ index , value ] of [ ... linesParam . entries ( ) ] . slice ( 0 , 6 ) ) {
linesArray [ index ] = value ;
2023-08-08 22:56:47 -07:00
}
2024-01-06 20:47:01 -08:00
return heading => linesArray [ getHeadingLevel ( heading ) - 1 ] ;
2023-08-08 22:56:47 -07:00
}
// Coerce linesParam to a number
2024-01-06 20:47:01 -08:00
const lines = linesParam === undefined ? defaultLines : Number ( linesParam ) ;
return ( ) => lines ;
2023-01-17 04:19:40 +00:00
} ;
2024-01-06 20:47:01 -08:00
const getBlockQuote = ( str , count ) => ( str || "" ) . match ( blockquotePrefixRe ) [ 0 ] . trimEnd ( )
// eslint-disable-next-line unicorn/prefer-spread
. concat ( "\n" ) . repeat ( count ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-11-09 20:05:30 -08:00
"names" : [ "MD022" , "blanks-around-headings" ] ,
2023-01-17 04:19:40 +00:00
"description" : "Headings should be surrounded by blank lines" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" , "blank_lines" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD022 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const getLinesAbove = getLinesFunction ( params . config . lines _above ) ;
const getLinesBelow = getLinesFunction ( params . config . lines _below ) ;
const {
lines ,
parsers
} = params ;
const headings = filterByTypes ( parsers . micromark . tokens , [ "atxHeading" , "setextHeading" ] ) . filter ( heading => ! inHtmlFlow ( heading ) ) ;
for ( const heading of headings ) {
const {
startLine ,
endLine
} = heading ;
const line = lines [ startLine - 1 ] . trim ( ) ;
// Check lines above
const linesAbove = getLinesAbove ( heading ) ;
if ( linesAbove >= 0 ) {
let actualAbove = 0 ;
for ( let i = 0 ; i < linesAbove && isBlankLine ( lines [ startLine - 2 - i ] ) ; i ++ ) {
actualAbove ++ ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
addErrorDetailIf ( onError , startLine , linesAbove , actualAbove , "Above" , line , null , {
"insertText" : getBlockQuote ( lines [ startLine - 2 ] , linesAbove - actualAbove )
} ) ;
}
2023-08-06 15:24:35 -07:00
2024-01-06 20:47:01 -08:00
// Check lines below
const linesBelow = getLinesBelow ( heading ) ;
if ( linesBelow >= 0 ) {
let actualBelow = 0 ;
for ( let i = 0 ; i < linesBelow && isBlankLine ( lines [ endLine + i ] ) ; i ++ ) {
actualBelow ++ ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
addErrorDetailIf ( onError , startLine , linesBelow , actualBelow , "Below" , line , null , {
"lineNumber" : endLine + 1 ,
"insertText" : getBlockQuote ( lines [ endLine ] , linesBelow - actualBelow )
} ) ;
2023-01-17 04:19:40 +00:00
}
2023-08-05 23:09:07 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md023.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md023 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
filterTokens
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const spaceBeforeHeadingRe = /^(\s+|[>\s]+\s\s)[^>\s]/ ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-11-09 20:05:30 -08:00
"names" : [ "MD023" , "heading-start-left" ] ,
2023-01-17 04:19:40 +00:00
"description" : "Headings must start at the beginning of the line" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" , "spaces" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD023 ( params , onError ) {
filterTokens ( params , "heading_open" , function forToken ( token ) {
2024-01-06 20:47:01 -08:00
const {
lineNumber ,
line
} = token ;
const match = line . match ( spaceBeforeHeadingRe ) ;
2023-01-17 04:19:40 +00:00
if ( match ) {
2024-01-06 20:47:01 -08:00
const [ prefixAndFirstChar , prefix ] = match ;
let deleteCount = prefix . length ;
const prefixLengthNoSpace = prefix . trimEnd ( ) . length ;
2023-01-17 04:19:40 +00:00
if ( prefixLengthNoSpace ) {
deleteCount -= prefixLengthNoSpace - 1 ;
}
addErrorContext ( onError , lineNumber , line , null , null , [ 1 , prefixAndFirstChar . length ] , {
"editColumn" : prefixLengthNoSpace + 1 ,
"deleteCount" : deleteCount
2019-10-02 20:10:42 -07:00
} ) ;
2023-01-17 04:19:40 +00:00
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md024.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md024 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
forEachHeading
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-11-09 20:05:30 -08:00
"names" : [ "MD024" , "no-duplicate-heading" ] ,
2023-01-17 04:19:40 +00:00
"description" : "Multiple headings with the same content" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD024 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const siblingsOnly = ! ! params . config . siblings _only || false ;
const knownContents = [ null , [ ] ] ;
let lastLevel = 1 ;
let knownContent = knownContents [ lastLevel ] ;
forEachHeading ( params , ( heading , content ) => {
2023-01-17 04:19:40 +00:00
if ( siblingsOnly ) {
2024-01-06 20:47:01 -08:00
const newLevel = heading . tag . slice ( 1 ) ;
2023-01-17 04:19:40 +00:00
while ( lastLevel < newLevel ) {
lastLevel ++ ;
knownContents [ lastLevel ] = [ ] ;
}
while ( lastLevel > newLevel ) {
knownContents [ lastLevel ] = [ ] ;
lastLevel -- ;
}
knownContent = knownContents [ newLevel ] ;
}
2023-12-05 19:23:17 -08:00
// @ts-ignore
2023-01-17 04:19:40 +00:00
if ( knownContent . includes ( content ) ) {
addErrorContext ( onError , heading . lineNumber , heading . line . trim ( ) ) ;
} else {
2023-12-05 19:23:17 -08:00
// @ts-ignore
2023-01-17 04:19:40 +00:00
knownContent . push ( content ) ;
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md025.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md025 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
filterTokens ,
frontMatterHasTitle
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD025" , "single-title" , "single-h1" ] ,
"description" : "Multiple top-level headings in the same document" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD025 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const level = Number ( params . config . level || 1 ) ;
const tag = "h" + level ;
const foundFrontMatterTitle = frontMatterHasTitle ( params . frontMatterLines , params . config . front _matter _title ) ;
let hasTopLevelHeading = false ;
2023-01-17 04:19:40 +00:00
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 ;
}
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md026.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md026 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
allPunctuationNoQuestion ,
endOfLineGemojiCodeRe ,
endOfLineHtmlEntityRe ,
escapeForRegExp
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD026" , "no-trailing-punctuation" ] ,
"description" : "Trailing punctuation in heading" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD026 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let punctuation = params . config . punctuation ;
2023-01-17 04:19:40 +00:00
punctuation = String ( punctuation === undefined ? allPunctuationNoQuestion : punctuation ) ;
2024-01-06 20:47:01 -08:00
const trailingPunctuationRe = new RegExp ( "\\s*[" + escapeForRegExp ( punctuation ) + "]+$" ) ;
const headings = filterByTypes ( params . parsers . micromark . tokens , [ "atxHeadingText" , "setextHeadingText" ] ) ;
for ( const heading of headings ) {
const {
endColumn ,
endLine ,
text
} = heading ;
const match = trailingPunctuationRe . exec ( text ) ;
if ( match && ! endOfLineHtmlEntityRe . test ( text ) && ! endOfLineGemojiCodeRe . test ( text ) ) {
const fullMatch = match [ 0 ] ;
const length = fullMatch . length ;
const column = endColumn - length ;
addError ( onError , endLine , ` Punctuation: ' ${ fullMatch } ' ` , undefined , [ column , length ] , {
"editColumn" : column ,
"deleteCount" : length
} ) ;
2023-01-17 04:19:40 +00:00
}
2023-06-24 15:45:51 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md027.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md027 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
newLineRe
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const spaceAfterBlockQuoteRe = /^((?:\s*>)+)(\s{2,})\S/ ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD027" , "no-multiple-space-blockquote" ] ,
"description" : "Multiple spaces after blockquote symbol" ,
"tags" : [ "blockquote" , "whitespace" , "indentation" ] ,
"function" : function MD027 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let blockquoteNesting = 0 ;
let listItemNesting = 0 ;
for ( const token of params . parsers . markdownit . tokens ) {
const {
content ,
lineNumber ,
type
} = token ;
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 ) {
const lineCount = content . split ( newLineRe ) . length ;
for ( let i = 0 ; i < lineCount ; i ++ ) {
const line = params . lines [ lineNumber + i - 1 ] ;
const match = line . match ( spaceAfterBlockQuoteRe ) ;
if ( match ) {
const [ fullMatch , {
"length" : blockquoteLength
} , {
"length" : spaceLength
} ] = match ;
if ( ! listItemNesting || fullMatch [ fullMatch . length - 1 ] === ">" ) {
addErrorContext ( onError , lineNumber + i , line , null , null , [ 1 , fullMatch . length ] , {
"editColumn" : blockquoteLength + 1 ,
"deleteCount" : spaceLength - 1
} ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2022-06-08 22:10:27 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md028.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md028 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD028" , "no-blanks-blockquote" ] ,
"description" : "Blank line inside blockquote" ,
"tags" : [ "blockquote" , "whitespace" ] ,
"function" : function MD028 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let prevToken = { } ;
let prevLineNumber = null ;
for ( const token of params . parsers . markdownit . tokens ) {
if ( token . type === "blockquote_open" && prevToken . type === "blockquote_close" ) {
for ( let lineNumber = prevLineNumber ; lineNumber < token . lineNumber ; lineNumber ++ ) {
addError ( onError , lineNumber ) ;
2023-01-17 04:19:40 +00:00
}
}
2024-01-06 20:47:01 -08:00
prevToken = token ;
if ( token . type === "blockquote_open" ) {
prevLineNumber = token . map [ 1 ] + 1 ;
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md029.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md029 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf ,
listItemMarkerRe ,
orderedListItemMarkerRe ,
rangeFromRegExp
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
flattenedLists
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
const listStyleExamples = {
2023-01-17 04:19:40 +00:00
"one" : "1/1/1" ,
"ordered" : "1/2/3" ,
"zero" : "0/0/0"
2019-10-02 20:10:42 -07:00
} ;
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD029" , "ol-prefix" ] ,
"description" : "Ordered list item prefix" ,
"tags" : [ "ol" ] ,
"function" : function MD029 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const style = String ( params . config . style || "one_or_ordered" ) ;
const filteredLists = flattenedLists ( ) . filter ( list => ! list . unordered ) ;
for ( const list of filteredLists ) {
const {
items
} = list ;
let current = 1 ;
let incrementing = false ;
// Check for incrementing number pattern 1/2/3 or 0/1/2
if ( items . length >= 2 ) {
const first = orderedListItemMarkerRe . exec ( items [ 0 ] . line ) ;
const second = orderedListItemMarkerRe . exec ( items [ 1 ] . line ) ;
if ( first && second ) {
const [ , firstNumber ] = first ;
const [ , secondNumber ] = second ;
if ( secondNumber !== "1" || firstNumber === "0" ) {
incrementing = true ;
if ( firstNumber === "0" ) {
current = 0 ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
}
2024-01-06 20:47:01 -08:00
}
// Determine effective style
let 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 ;
} else if ( listStyle === "one" ) {
current = 1 ;
}
// Validate each list item marker
for ( const item of items ) {
const 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 ++ ;
2023-01-17 04:19:40 +00:00
}
}
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md030.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md030 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
2023-01-17 04:19:40 +00:00
module . exports = {
"names" : [ "MD030" , "list-marker-space" ] ,
"description" : "Spaces after list markers" ,
"tags" : [ "ol" , "ul" , "whitespace" ] ,
"function" : function MD030 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const ulSingle = Number ( params . config . ul _single || 1 ) ;
const olSingle = Number ( params . config . ol _single || 1 ) ;
const ulMulti = Number ( params . config . ul _multi || 1 ) ;
const olMulti = Number ( params . config . ol _multi || 1 ) ;
const lists = filterByTypes ( params . parsers . micromark . tokens , [ "listOrdered" , "listUnordered" ] ) ;
for ( const list of lists ) {
const ordered = list . type === "listOrdered" ;
const listItemPrefixes = list . children . filter ( token => token . type === "listItemPrefix" ) ;
const allSingleLine = list . endLine - list . startLine + 1 === listItemPrefixes . length ;
const expectedSpaces = ordered ? allSingleLine ? olSingle : olMulti : allSingleLine ? ulSingle : ulMulti ;
for ( const listItemPrefix of listItemPrefixes ) {
const range = [ listItemPrefix . startColumn , listItemPrefix . endColumn - listItemPrefix . startColumn ] ;
const listItemPrefixWhitespaces = listItemPrefix . children . filter ( token => token . type === "listItemPrefixWhitespace" ) ;
for ( const listItemPrefixWhitespace of listItemPrefixWhitespaces ) {
const {
endColumn ,
startColumn ,
startLine
} = listItemPrefixWhitespace ;
const actualSpaces = endColumn - startColumn ;
const fixInfo = {
"editColumn" : startColumn ,
"deleteCount" : actualSpaces ,
"insertText" : "" . padEnd ( expectedSpaces )
} ;
addErrorDetailIf ( onError , startLine , expectedSpaces , actualSpaces , null , null , range , fixInfo ) ;
2023-01-17 04:19:40 +00:00
}
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md031.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md031 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
forEachLine ,
isBlankLine
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
lineMetadata
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
const codeFencePrefixRe = /^(.*?)[`~]/ ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD031" , "blanks-around-fences" ] ,
"description" : "Fenced code blocks should be surrounded by blank lines" ,
"tags" : [ "code" , "blank_lines" ] ,
"function" : function MD031 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const listItems = params . config . list _items ;
const includeListItems = listItems === undefined ? true : ! ! listItems ;
const {
lines
} = params ;
forEachLine ( lineMetadata ( ) , ( line , i , inCode , onFence , inTable , inItem ) => {
const onTopFence = onFence > 0 ;
const onBottomFence = onFence < 0 ;
2023-01-17 04:19:40 +00:00
if ( ( includeListItems || ! inItem ) && ( onTopFence && ! isBlankLine ( lines [ i - 1 ] ) || onBottomFence && ! isBlankLine ( lines [ i + 1 ] ) ) ) {
2024-01-06 20:47:01 -08:00
const [ , prefix ] = line . match ( codeFencePrefixRe ) || [ ] ;
const fixInfo = prefix === undefined ? null : {
2023-01-17 04:19:40 +00:00
"lineNumber" : i + ( onTopFence ? 1 : 2 ) ,
2024-01-06 20:47:01 -08:00
"insertText" : ` ${ prefix . replace ( /[^>]/g , " " ) . trim ( ) } \n `
2023-01-17 04:19:40 +00:00
} ;
addErrorContext ( onError , i + 1 , lines [ i ] . trim ( ) , null , null , null , fixInfo ) ;
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md032.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md032 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
blockquotePrefixRe ,
isBlankLine
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByPredicate
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
const nonContentTokens = new Set ( [ "blockQuoteMarker" , "blockQuotePrefix" , "blockQuotePrefixWhitespace" , "lineEnding" , "lineEndingBlank" , "linePrefix" , "listItemIndent" ] ) ;
const isList = token => token . type === "listOrdered" || token . type === "listUnordered" ;
const addBlankLineError = ( onError , lines , lineIndex , lineNumber ) => {
const line = lines [ lineIndex ] ;
const quotePrefix = line . match ( blockquotePrefixRe ) [ 0 ] . trimEnd ( ) ;
2023-07-18 22:33:57 -07:00
addErrorContext ( onError , lineIndex + 1 , line . trim ( ) , null , null , null , {
2024-01-06 20:47:01 -08:00
lineNumber ,
"insertText" : ` ${ quotePrefix } \n `
2023-07-18 22:33:57 -07:00
} ) ;
} ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD032" , "blanks-around-lists" ] ,
"description" : "Lists should be surrounded by blank lines" ,
"tags" : [ "bullet" , "ul" , "ol" , "blank_lines" ] ,
"function" : function MD032 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const {
lines ,
parsers
} = params ;
2023-07-18 22:33:57 -07:00
// For every top-level list...
2024-01-06 20:47:01 -08:00
const topLevelLists = filterByPredicate ( parsers . micromark . tokens , isList , token => isList ( token ) || token . type === "htmlFlow" ? [ ] : token . children ) ;
for ( const list of topLevelLists ) {
// Look for a blank line above the list
const firstIndex = list . startLine - 1 ;
if ( ! isBlankLine ( lines [ firstIndex - 1 ] ) ) {
addBlankLineError ( onError , lines , firstIndex ) ;
}
2023-07-18 22:33:57 -07:00
2024-01-06 20:47:01 -08:00
// Find the "visual" end of the list
let endLine = list . endLine ;
const flattenedChildren = filterByPredicate ( list . children ) ;
for ( const child of flattenedChildren . reverse ( ) ) {
if ( ! nonContentTokens . has ( child . type ) ) {
endLine = child . endLine ;
break ;
2023-01-17 04:19:40 +00:00
}
}
2024-01-06 20:47:01 -08:00
// Look for a blank line below the list
const lastIndex = endLine - 1 ;
if ( ! isBlankLine ( lines [ lastIndex + 1 ] ) ) {
addBlankLineError ( onError , lines , lastIndex , lastIndex + 2 ) ;
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md033.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md033 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
nextLinesRe
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes ,
getHtmlTagInfo
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD033" , "no-inline-html" ] ,
"description" : "Inline HTML" ,
"tags" : [ "html" ] ,
"function" : function MD033 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let allowedElements = params . config . allowed _elements ;
2023-01-17 04:19:40 +00:00
allowedElements = Array . isArray ( allowedElements ) ? allowedElements : [ ] ;
2024-01-06 20:47:01 -08:00
allowedElements = allowedElements . map ( element => element . toLowerCase ( ) ) ;
const {
tokens
} = params . parsers . micromark ;
for ( const token of filterByTypes ( tokens , [ "htmlText" ] ) ) {
const htmlTagInfo = getHtmlTagInfo ( token ) ;
if ( htmlTagInfo && ! htmlTagInfo . close && ! allowedElements . includes ( htmlTagInfo . name . toLowerCase ( ) ) ) {
const range = [ token . startColumn , token . text . replace ( nextLinesRe , "" ) . length ] ;
addError ( onError , token . startLine , "Element: " + htmlTagInfo . name , undefined , range ) ;
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md034.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md034 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByPredicate ,
filterByTypes ,
getHtmlTagInfo ,
inHtmlFlow ,
parse
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD034" , "no-bare-urls" ] ,
"description" : "Bare URL used" ,
"tags" : [ "links" , "url" ] ,
"function" : function MD034 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const literalAutolinks = tokens => filterByPredicate ( tokens , token => token . type === "literalAutolink" && ! inHtmlFlow ( token ) , token => {
const {
children
} = token ;
const result = [ ] ;
for ( let i = 0 ; i < children . length ; i ++ ) {
const current = children [ i ] ;
const openTagInfo = getHtmlTagInfo ( current ) ;
if ( openTagInfo && ! openTagInfo . close ) {
let count = 1 ;
for ( let j = i + 1 ; j < children . length ; j ++ ) {
const candidate = children [ j ] ;
const closeTagInfo = getHtmlTagInfo ( candidate ) ;
if ( closeTagInfo && openTagInfo . name === closeTagInfo . name ) {
if ( closeTagInfo . close ) {
count -- ;
if ( count === 0 ) {
i = j ;
break ;
2023-02-05 16:58:06 -08:00
}
2024-01-06 20:47:01 -08:00
} else {
count ++ ;
2023-02-05 16:58:06 -08:00
}
}
}
2024-01-06 20:47:01 -08:00
} else {
result . push ( current ) ;
2023-02-05 16:58:06 -08:00
}
2024-01-06 20:47:01 -08:00
}
return result ;
} ) ;
const autoLinks = filterByTypes ( params . parsers . micromark . tokens , [ "literalAutolink" ] ) ;
2023-09-13 22:44:15 -07:00
if ( autoLinks . length > 0 ) {
2023-05-23 04:01:55 +00:00
// Re-parse with correct link/image reference definition handling
2024-01-06 20:47:01 -08:00
const document = params . lines . join ( "\n" ) ;
const tokens = parse ( document , undefined , false ) ;
for ( const token of literalAutolinks ( tokens ) ) {
const range = [ token . startColumn , token . endColumn - token . startColumn ] ;
const fixInfo = {
"editColumn" : range [ 0 ] ,
"deleteCount" : range [ 1 ] ,
"insertText" : ` < ${ token . text } > `
} ;
addErrorContext ( onError , token . startLine , token . text , null , null , range , fixInfo ) ;
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md035.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md035 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD035" , "hr-style" ] ,
"description" : "Horizontal rule style" ,
"tags" : [ "hr" ] ,
"function" : function MD035 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let style = String ( params . config . style || "consistent" ) . trim ( ) ;
const thematicBreaks = filterByTypes ( params . parsers . micromark . tokens , [ "thematicBreak" ] ) ;
for ( const token of thematicBreaks ) {
const {
startLine ,
text
} = token ;
if ( style === "consistent" ) {
style = text ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
addErrorDetailIf ( onError , startLine , style , text ) ;
2023-03-06 21:38:40 -08:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md036.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md036 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
allPunctuation
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-11-09 20:05:30 -08:00
"names" : [ "MD036" , "no-emphasis-as-heading" ] ,
2023-01-17 04:19:40 +00:00
"description" : "Emphasis used instead of a heading" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" , "emphasis" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD036 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let punctuation = params . config . punctuation ;
2023-01-17 04:19:40 +00:00
punctuation = String ( punctuation === undefined ? allPunctuation : punctuation ) ;
2024-01-06 20:47:01 -08:00
const re = new RegExp ( "[" + punctuation + "]$" ) ;
2023-01-17 04:19:40 +00:00
// eslint-disable-next-line jsdoc/require-jsdoc
function base ( token ) {
if ( token . type === "paragraph_open" ) {
return function inParagraph ( t ) {
// Always paragraph_open/inline/paragraph_close,
2024-01-06 20:47:01 -08:00
const children = t . children . filter ( function notEmptyText ( child ) {
2023-01-17 04:19:40 +00:00
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 ;
}
2024-01-06 20:47:01 -08:00
let state = base ;
for ( const token of params . parsers . markdownit . tokens ) {
state = state ( token ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md037.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md037 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByPredicate ,
inHtmlFlow
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD037" , "no-space-in-emphasis" ] ,
"description" : "Spaces inside emphasis markers" ,
"tags" : [ "whitespace" , "emphasis" ] ,
"function" : function MD037 ( params , onError ) {
2023-07-24 21:36:55 -07:00
// Initialize variables
2024-01-06 20:47:01 -08:00
const {
lines ,
parsers
} = params ;
const emphasisTokensByMarker = new Map ( ) ;
for ( const marker of [ "_" , "__" , "___" , "*" , "**" , "***" ] ) {
2023-07-24 21:36:55 -07:00
emphasisTokensByMarker . set ( marker , [ ] ) ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
const tokens = filterByPredicate ( parsers . micromark . tokens , token => token . children . some ( child => child . type === "data" ) ) ;
for ( const token of tokens ) {
// Build lists of bare tokens for each emphasis marker type
for ( const emphasisTokens of emphasisTokensByMarker . values ( ) ) {
emphasisTokens . length = 0 ;
}
for ( const child of token . children ) {
const {
text ,
type
} = child ;
if ( type === "data" && text . length <= 3 ) {
const emphasisTokens = emphasisTokensByMarker . get ( text ) ;
if ( emphasisTokens && ! inHtmlFlow ( child ) ) {
emphasisTokens . push ( child ) ;
2023-09-02 12:07:14 -07:00
}
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
}
2023-07-24 21:36:55 -07:00
2024-01-06 20:47:01 -08:00
// Process bare tokens for each emphasis marker type
for ( const entry of emphasisTokensByMarker . entries ( ) ) {
const [ marker , emphasisTokens ] = entry ;
for ( let i = 0 ; i + 1 < emphasisTokens . length ; i += 2 ) {
// Process start token of start/end pair
const startToken = emphasisTokens [ i ] ;
const startLine = lines [ startToken . startLine - 1 ] ;
const startSlice = startLine . slice ( startToken . endColumn - 1 ) ;
const startMatch = startSlice . match ( /^\s+\S/ ) ;
if ( startMatch ) {
const [ startSpaceCharacter ] = startMatch ;
const startContext = ` ${ marker } ${ startSpaceCharacter } ` ;
addError ( onError , startToken . startLine , undefined , startContext , [ startToken . startColumn , startContext . length ] , {
"editColumn" : startToken . endColumn ,
"deleteCount" : startSpaceCharacter . length - 1
} ) ;
}
2023-07-24 21:36:55 -07:00
2024-01-06 20:47:01 -08:00
// Process end token of start/end pair
const endToken = emphasisTokens [ i + 1 ] ;
const endLine = lines [ endToken . startLine - 1 ] ;
const endSlice = endLine . slice ( 0 , endToken . startColumn - 1 ) ;
const endMatch = endSlice . match ( /\S\s+$/ ) ;
if ( endMatch ) {
const [ endSpaceCharacter ] = endMatch ;
const endContext = ` ${ endSpaceCharacter } ${ marker } ` ;
addError ( onError , endToken . startLine , undefined , endContext , [ endToken . endColumn - endContext . length , endContext . length ] , {
"editColumn" : endToken . startColumn - ( endSpaceCharacter . length - 1 ) ,
"deleteCount" : endSpaceCharacter . length - 1
} ) ;
2023-01-17 04:19:40 +00:00
}
}
}
2023-07-24 21:36:55 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md038.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md038 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes ,
inHtmlFlow ,
tokenIfType
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
const leftSpaceRe = /^\s(?:[^`]|$)/ ;
const rightSpaceRe = /[^`]\s$/ ;
const trimCodeText = ( text , start , end ) => {
2023-02-23 22:20:27 -08:00
text = text . replace ( /^\s+$/ , "" ) ;
if ( start ) {
text = text . replace ( /^\s+?(\s`|\S)/ , "$1" ) ;
}
if ( end ) {
text = text . replace ( /(`\s|\S)\s+$/ , "$1" ) ;
}
return text ;
} ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD038" , "no-space-in-code" ] ,
"description" : "Spaces inside code span elements" ,
"tags" : [ "whitespace" , "code" ] ,
"function" : function MD038 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const codeTexts = filterByTypes ( params . parsers . micromark . tokens , [ "codeText" ] ) . filter ( codeText => ! inHtmlFlow ( codeText ) ) ;
for ( const codeText of codeTexts ) {
const {
children
} = codeText ;
const first = 0 ;
const last = children . length - 1 ;
const startSequence = tokenIfType ( children [ first ] , "codeTextSequence" ) ;
const endSequence = tokenIfType ( children [ last ] , "codeTextSequence" ) ;
const startData = tokenIfType ( children [ first + 1 ] , "codeTextData" ) || tokenIfType ( children [ first + 2 ] , "codeTextData" ) ;
const endData = tokenIfType ( children [ last - 1 ] , "codeTextData" ) || tokenIfType ( children [ last - 2 ] , "codeTextData" ) ;
if ( startSequence && endSequence && startData && endData ) {
const spaceLeft = leftSpaceRe . test ( startData . text ) ;
const spaceRight = rightSpaceRe . test ( endData . text ) ;
if ( spaceLeft || spaceRight ) {
let lineNumber = startSequence . startLine ;
let range = null ;
let fixInfo = null ;
if ( startSequence . startLine === endSequence . endLine ) {
range = [ startSequence . startColumn , endSequence . endColumn - startSequence . startColumn ] ;
fixInfo = {
"editColumn" : startSequence . endColumn ,
"deleteCount" : endSequence . startColumn - startSequence . endColumn ,
"insertText" : trimCodeText ( startData . text , true , true )
} ;
} else if ( spaceLeft && startSequence . endLine === startData . startLine ) {
range = [ startSequence . startColumn , startData . endColumn - startSequence . startColumn ] ;
fixInfo = {
"editColumn" : startSequence . endColumn ,
"deleteCount" : startData . endColumn - startData . startColumn ,
"insertText" : trimCodeText ( startData . text , true , false )
} ;
} else if ( spaceRight && endData . text . trim ( ) . length > 0 ) {
lineNumber = endSequence . endLine ;
range = [ endData . startColumn , endSequence . endColumn - endData . startColumn ] ;
fixInfo = {
"editColumn" : endData . startColumn ,
"deleteCount" : endData . endColumn - endData . startColumn ,
"insertText" : trimCodeText ( endData . text , false , true )
} ;
}
if ( range ) {
const context = params . lines [ lineNumber - 1 ] . substring ( range [ 0 ] - 1 , range [ 0 ] - 1 + range [ 1 ] ) ;
addErrorContext ( onError , lineNumber , context , spaceLeft , spaceRight , range , fixInfo ) ;
2023-01-17 04:19:40 +00:00
}
2023-02-23 22:20:27 -08:00
}
2023-01-17 04:19:40 +00:00
}
2023-02-23 22:20:27 -08:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md039.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md039 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
filterTokens
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const spaceInLinkRe = /\[(?:\s[^\]]*|[^\]]*?\s)\](?=(\([^)]*\)|\[[^\]]*\]))/ ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD039" , "no-space-in-links" ] ,
"description" : "Spaces inside link text" ,
"tags" : [ "whitespace" , "links" ] ,
"function" : function MD039 ( params , onError ) {
2024-01-06 20:47:01 -08:00
filterTokens ( params , "inline" , token => {
const {
children
} = token ;
let {
lineNumber
} = token ;
let inLink = false ;
let linkText = "" ;
let lineIndex = 0 ;
for ( const child of children ) {
const {
content ,
markup ,
type
} = child ;
if ( type === "link_open" ) {
inLink = true ;
linkText = "" ;
} else if ( type === "link_close" ) {
inLink = false ;
const left = linkText . trimStart ( ) . length !== linkText . length ;
const right = linkText . trimEnd ( ) . length !== linkText . length ;
if ( left || right ) {
const line = params . lines [ lineNumber - 1 ] ;
let range = null ;
let fixInfo = null ;
const match = line . slice ( lineIndex ) . match ( spaceInLinkRe ) ;
if ( match ) {
const column = match . index + lineIndex + 1 ;
const length = match [ 0 ] . length ;
range = [ column , length ] ;
fixInfo = {
"editColumn" : column + 1 ,
"deleteCount" : length - 2 ,
"insertText" : linkText . trim ( )
} ;
lineIndex = column + length - 1 ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
addErrorContext ( onError , lineNumber , ` [ ${ linkText } ] ` , left , right , range , fixInfo ) ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
} else if ( type === "softbreak" || type === "hardbreak" ) {
lineNumber ++ ;
lineIndex = 0 ;
} else if ( inLink ) {
linkText += type . endsWith ( "_inline" ) ? ` ${ markup } ${ content } ${ markup } ` : content || markup ;
2023-01-17 04:19:40 +00:00
}
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md040.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md040 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
addErrorContext ,
filterTokens
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD040" , "fenced-code-language" ] ,
"description" : "Fenced code blocks should have a language specified" ,
"tags" : [ "code" , "language" ] ,
"function" : function MD040 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let allowed = params . config . allowed _languages ;
2023-01-17 04:19:40 +00:00
allowed = Array . isArray ( allowed ) ? allowed : [ ] ;
2024-01-06 20:47:01 -08:00
const languageOnly = ! ! params . config . language _only ;
2023-01-17 04:19:40 +00:00
filterTokens ( params , "fence" , function forToken ( token ) {
2024-01-06 20:47:01 -08:00
const lang = token . info . trim ( ) . split ( /\s+/u ) . shift ( ) ;
2023-01-17 04:19:40 +00:00
if ( lang === "" ) {
addErrorContext ( onError , token . lineNumber , token . line ) ;
} else if ( allowed . length > 0 && ! allowed . includes ( lang ) ) {
2024-01-06 20:47:01 -08:00
addError ( onError , token . lineNumber , ` " ${ lang } " is not allowed ` ) ;
2023-01-17 04:19:40 +00:00
}
if ( languageOnly && token . info !== lang ) {
2024-01-06 20:47:01 -08:00
addError ( onError , token . lineNumber , ` Info string contains more than language: " ${ token . info } " ` ) ;
2023-01-17 04:19:40 +00:00
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md041.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md041 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
frontMatterHasTitle
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD041" , "first-line-heading" , "first-line-h1" ] ,
"description" : "First line in a file should be a top-level heading" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD041 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const level = Number ( params . config . level || 1 ) ;
const tag = "h" + level ;
const foundFrontMatterTitle = frontMatterHasTitle ( params . frontMatterLines , params . config . front _matter _title ) ;
2023-01-17 04:19:40 +00:00
if ( ! foundFrontMatterTitle ) {
2024-01-06 20:47:01 -08:00
const htmlHeadingRe = new RegExp ( ` ^<h ${ level } [ />] ` , "i" ) ;
params . parsers . markdownit . tokens . every ( token => {
let isError = false ;
2023-01-17 04:19:40 +00:00
if ( token . type === "html_block" ) {
if ( token . content . startsWith ( "<!--" ) ) {
// Ignore leading HTML comments
return true ;
} else if ( ! htmlHeadingRe . test ( token . content ) ) {
// Something other than an HTML heading
isError = true ;
}
} else if ( token . type !== "heading_open" || token . tag !== tag ) {
// Something other than a Markdown heading
isError = true ;
}
if ( isError ) {
addErrorContext ( onError , token . lineNumber , token . line ) ;
}
return false ;
} ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md042.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md042 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
escapeForRegExp ,
filterTokens
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD042" , "no-empty-links" ] ,
"description" : "No empty links" ,
"tags" : [ "links" ] ,
"function" : function MD042 ( params , onError ) {
filterTokens ( params , "inline" , function forToken ( token ) {
2024-01-06 20:47:01 -08:00
let inLink = false ;
let linkText = "" ;
let emptyLink = false ;
for ( const child of token . children ) {
if ( child . type === "link_open" ) {
inLink = true ;
linkText = "" ;
for ( const attr of child . attrs ) {
if ( attr [ 0 ] === "href" && ( ! attr [ 1 ] || attr [ 1 ] === "#" ) ) {
emptyLink = true ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
}
} else if ( child . type === "link_close" ) {
inLink = false ;
if ( emptyLink ) {
let context = ` [ ${ linkText } ] ` ;
let range = null ;
const match = child . line . match ( new RegExp ( ` ${ escapeForRegExp ( context ) } \\ ((?:|#|<>) \\ ) ` ) ) ;
if ( match ) {
context = match [ 0 ] ;
range = [ match . index + 1 , match [ 0 ] . length ] ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
addErrorContext ( onError , child . lineNumber , context , null , null , range ) ;
emptyLink = false ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
} else if ( inLink ) {
linkText += child . content ;
2023-01-17 04:19:40 +00:00
}
}
} ) ;
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md043.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md043 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
addErrorDetailIf ,
forEachHeading
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-11-09 20:05:30 -08:00
"names" : [ "MD043" , "required-headings" ] ,
2023-01-17 04:19:40 +00:00
"description" : "Required heading structure" ,
2023-11-09 20:05:30 -08:00
"tags" : [ "headings" ] ,
2023-01-17 04:19:40 +00:00
"function" : function MD043 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const requiredHeadings = params . config . headings ;
2023-08-29 23:00:27 -07:00
if ( ! Array . isArray ( requiredHeadings ) ) {
// Nothing to check; avoid doing any work
return ;
}
2024-01-06 20:47:01 -08:00
const matchCase = params . config . match _case || false ;
const levels = { } ;
for ( const level of [ 1 , 2 , 3 , 4 , 5 , 6 ] ) {
2023-08-29 23:00:27 -07:00
levels [ "h" + level ] = "######" . substr ( - level ) ;
}
2024-01-06 20:47:01 -08:00
let i = 0 ;
let matchAny = false ;
let hasError = false ;
let anyHeadings = false ;
const getExpected = ( ) => requiredHeadings [ i ++ ] || "[None]" ;
const handleCase = str => matchCase ? str : str . toLowerCase ( ) ;
forEachHeading ( params , ( heading , content ) => {
2023-08-29 23:00:27 -07:00
if ( ! hasError ) {
anyHeadings = true ;
2024-01-06 20:47:01 -08:00
const actual = levels [ heading . tag ] + " " + content ;
const expected = getExpected ( ) ;
2023-08-29 23:00:27 -07:00
if ( expected === "*" ) {
2024-01-06 20:47:01 -08:00
const nextExpected = getExpected ( ) ;
2023-08-29 23:00:27 -07:00
if ( handleCase ( nextExpected ) !== handleCase ( actual ) ) {
2023-01-17 04:19:40 +00:00
matchAny = true ;
i -- ;
}
2023-08-29 23:00:27 -07:00
} else if ( expected === "+" ) {
matchAny = true ;
} else if ( handleCase ( expected ) === handleCase ( actual ) ) {
matchAny = false ;
} else if ( matchAny ) {
i -- ;
} else {
addErrorDetailIf ( onError , heading . lineNumber , expected , actual ) ;
hasError = true ;
2023-01-17 04:19:40 +00:00
}
}
2023-08-29 23:00:27 -07:00
} ) ;
2024-01-06 20:47:01 -08:00
const extraHeadings = requiredHeadings . length - i ;
if ( ! hasError && ( extraHeadings > 1 || extraHeadings === 1 && requiredHeadings [ i ] !== "*" ) && ( anyHeadings || ! requiredHeadings . every ( heading => heading === "*" ) ) ) {
2023-08-29 23:00:27 -07:00
addErrorContext ( onError , params . lines . length , requiredHeadings [ i ] ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md044.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md044 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
"use strict" ;
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf ,
escapeForRegExp ,
withinAnyRange
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByPredicate ,
filterByTypes ,
parse
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
const ignoredChildTypes = new Set ( [ "codeFencedFence" , "definition" , "reference" , "resource" ] ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD044" , "proper-names" ] ,
"description" : "Proper names should have the correct capitalization" ,
"tags" : [ "spelling" ] ,
"function" : function MD044 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let names = params . config . names ;
2023-01-17 04:19:40 +00:00
names = Array . isArray ( names ) ? names : [ ] ;
2024-01-06 20:47:01 -08:00
names . sort ( ( a , b ) => b . length - a . length || a . localeCompare ( b ) ) ;
2023-08-27 23:35:00 -07:00
if ( names . length === 0 ) {
// Nothing to check; avoid doing any work
return ;
}
2024-01-06 20:47:01 -08:00
const codeBlocks = params . config . code _blocks ;
const includeCodeBlocks = codeBlocks === undefined ? true : ! ! codeBlocks ;
const htmlElements = params . config . html _elements ;
const includeHtmlElements = htmlElements === undefined ? true : ! ! htmlElements ;
const scannedTypes = new Set ( [ "data" ] ) ;
2023-03-14 21:03:07 -07:00
if ( includeCodeBlocks ) {
scannedTypes . add ( "codeFlowValue" ) ;
scannedTypes . add ( "codeTextData" ) ;
}
2023-09-02 12:07:14 -07:00
if ( includeHtmlElements ) {
scannedTypes . add ( "htmlFlowData" ) ;
scannedTypes . add ( "htmlTextData" ) ;
}
2024-01-06 20:47:01 -08:00
const contentTokens = filterByPredicate ( params . parsers . micromark . tokens , token => scannedTypes . has ( token . type ) , token => token . children . filter ( t => ! ignoredChildTypes . has ( t . type ) ) ) ;
const exclusions = [ ] ;
const autoLinked = new Set ( ) ;
for ( const name of names ) {
const escapedName = escapeForRegExp ( name ) ;
const startNamePattern = /^\W/ . test ( name ) ? "" : "\\b_*" ;
const endNamePattern = /\W$/ . test ( name ) ? "" : "_*\\b" ;
const namePattern = ` ( ${ startNamePattern } )( ${ escapedName } ) ${ endNamePattern } ` ;
const nameRe = new RegExp ( namePattern , "gi" ) ;
for ( const token of contentTokens ) {
let match = null ;
while ( ( match = nameRe . exec ( token . text ) ) !== null ) {
const [ , leftMatch , nameMatch ] = match ;
const index = token . startColumn - 1 + match . index + leftMatch . length ;
const length = nameMatch . length ;
const lineIndex = token . startLine - 1 ;
if ( ! withinAnyRange ( exclusions , lineIndex , index , length ) && ! names . includes ( nameMatch ) ) {
let urlRanges = [ ] ;
if ( ! autoLinked . has ( token ) ) {
urlRanges = filterByTypes ( parse ( token . text ) , [ "literalAutolink" ] ) . map ( t => [ lineIndex , token . startColumn - 1 + t . startColumn - 1 , t . endColumn - t . startColumn ] ) ;
exclusions . push ( ... urlRanges ) ;
autoLinked . add ( token ) ;
}
if ( ! withinAnyRange ( urlRanges , lineIndex , index , length ) ) {
const column = index + 1 ;
addErrorDetailIf ( onError , token . startLine , name , nameMatch , null , null , [ column , length ] , {
"editColumn" : column ,
"deleteCount" : length ,
"insertText" : name
} ) ;
2021-06-13 13:07:03 -07:00
}
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
exclusions . push ( [ lineIndex , index , length ] ) ;
2023-03-14 21:03:07 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md045.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md045 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
getHtmlAttributeRe ,
nextLinesRe
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes ,
getHtmlTagInfo
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
const altRe = getHtmlAttributeRe ( "alt" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD045" , "no-alt-text" ] ,
"description" : "Images should have alternate text (alt text)" ,
"tags" : [ "accessibility" , "images" ] ,
"function" : function MD045 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const {
tokens
} = params . parsers . micromark ;
2023-10-18 23:20:19 -07:00
// Process Markdown images
2024-01-06 20:47:01 -08:00
const images = filterByTypes ( tokens , [ "image" ] ) ;
for ( const image of images ) {
const labelTexts = filterByTypes ( image . children , [ "labelText" ] ) ;
if ( labelTexts . some ( labelText => labelText . text . length === 0 ) ) {
const range = image . startLine === image . endLine ? [ image . startColumn , image . endColumn - image . startColumn ] : undefined ;
addError ( onError , image . startLine , undefined , undefined , range ) ;
2023-01-17 04:19:40 +00:00
}
2023-07-28 20:19:30 -07:00
}
2024-01-06 20:47:01 -08:00
// Process HTML images
const htmlTexts = filterByTypes ( tokens , [ "htmlText" ] ) ;
for ( const htmlText of htmlTexts ) {
const {
startColumn ,
startLine ,
text
} = htmlText ;
const htmlTagInfo = getHtmlTagInfo ( htmlText ) ;
if ( htmlTagInfo && ! htmlTagInfo . close && htmlTagInfo . name . toLowerCase ( ) === "img" && ! altRe . test ( text ) ) {
const range = [ startColumn , text . replace ( nextLinesRe , "" ) . length ] ;
addError ( onError , startLine , undefined , undefined , range ) ;
2023-10-18 23:20:19 -07:00
}
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md046.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md046 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const tokenTypeToStyle = {
2023-01-17 04:19:40 +00:00
"fence" : "fenced" ,
"code_block" : "indented"
2019-10-02 20:10:42 -07:00
} ;
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD046" , "code-block-style" ] ,
"description" : "Code block style" ,
"tags" : [ "code" ] ,
"function" : function MD046 ( params , onError ) {
2024-01-06 20:47:01 -08:00
let expectedStyle = String ( params . config . style || "consistent" ) ;
const codeBlocksAndFences = params . parsers . markdownit . tokens . filter ( token => token . type === "code_block" || token . type === "fence" ) ;
for ( const token of codeBlocksAndFences ) {
const {
lineNumber ,
type
} = token ;
if ( expectedStyle === "consistent" ) {
expectedStyle = tokenTypeToStyle [ type ] ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
addErrorDetailIf ( onError , lineNumber , expectedStyle , tokenTypeToStyle [ type ] ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md047.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md047 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
isBlankLine
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-10-02 20:10:42 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD047" , "single-trailing-newline" ] ,
"description" : "Files should end with a single newline character" ,
"tags" : [ "blank_lines" ] ,
"function" : function MD047 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const lastLineNumber = params . lines . length ;
const lastLine = params . lines [ lastLineNumber - 1 ] ;
2023-01-17 04:19:40 +00:00
if ( ! isBlankLine ( lastLine ) ) {
addError ( onError , lastLineNumber , null , null , [ lastLine . length , 1 ] , {
"insertText" : "\n" ,
"editColumn" : lastLine . length + 1
} ) ;
2019-10-02 20:10:42 -07:00
}
2023-01-17 04:19:40 +00:00
}
2019-10-02 20:10:42 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/md048.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md048 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2021-01-05 20:55:09 -08:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2019-10-02 20:10:42 -07:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf ,
fencedCodeBlockStyleFor
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
2019-12-14 13:50:48 -08:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD048" , "code-fence-style" ] ,
"description" : "Code fence style" ,
"tags" : [ "code" ] ,
"function" : function MD048 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const style = String ( params . config . style || "consistent" ) ;
let expectedStyle = style ;
const fenceTokens = params . parsers . markdownit . tokens . filter ( token => token . type === "fence" ) ;
for ( const fenceToken of fenceTokens ) {
const {
lineNumber ,
markup
} = fenceToken ;
if ( expectedStyle === "consistent" ) {
expectedStyle = fencedCodeBlockStyleFor ( markup ) ;
2023-01-17 04:19:40 +00:00
}
2024-01-06 20:47:01 -08:00
addErrorDetailIf ( onError , lineNumber , expectedStyle , fencedCodeBlockStyleFor ( markup ) ) ;
2019-12-14 13:50:48 -08:00
}
2023-01-17 04:19:40 +00:00
}
2019-12-14 13:50:48 -08:00
} ;
2021-10-24 06:54:58 +02:00
/***/ } ) ,
2022-05-03 21:37:30 -07:00
/***/ "../lib/md049-md050.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md049 - md050 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
2021-10-24 06:54:58 +02:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
"use strict" ;
// @ts-check
2021-10-21 06:42:48 +02:00
2024-01-06 20:47:01 -08:00
const {
addError ,
emphasisOrStrongStyleFor
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByPredicate ,
tokenIfType
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
const intrawordRe = /\w/ ;
const impl = function ( params , onError , type , asterisk , underline ) {
let style = arguments . length > 5 && arguments [ 5 ] !== undefined ? arguments [ 5 ] : "consistent" ;
const {
lines ,
parsers
} = params ;
const emphasisTokens = filterByPredicate ( parsers . micromark . tokens , token => token . type === type , token => token . type === "htmlFlow" ? [ ] : token . children ) ;
for ( const token of emphasisTokens ) {
const {
children
} = token ;
const childType = ` ${ type } Sequence ` ;
const startSequence = tokenIfType ( children [ 0 ] , childType ) ;
const endSequence = tokenIfType ( children [ children . length - 1 ] , childType ) ;
if ( startSequence && endSequence ) {
const markupStyle = emphasisOrStrongStyleFor ( startSequence . text ) ;
if ( style === "consistent" ) {
style = markupStyle ;
}
if ( style !== markupStyle ) {
const underscoreIntraword = style === "underscore" && ( intrawordRe . test ( lines [ startSequence . startLine - 1 ] [ startSequence . startColumn - 2 ] ) || intrawordRe . test ( lines [ endSequence . endLine - 1 ] [ endSequence . endColumn - 1 ] ) ) ;
if ( ! underscoreIntraword ) {
for ( const sequence of [ startSequence , endSequence ] ) {
addError ( onError , sequence . startLine , ` Expected: ${ style } ; Actual: ${ markupStyle } ` , undefined , [ sequence . startColumn , sequence . text . length ] , {
"editColumn" : sequence . startColumn ,
"deleteCount" : sequence . text . length ,
"insertText" : style === "asterisk" ? asterisk : underline
} ) ;
2023-05-25 03:47:34 +00:00
}
2023-01-17 04:19:40 +00:00
}
}
}
2023-05-25 03:47:34 +00:00
}
2023-01-17 04:19:40 +00:00
} ;
module . exports = [ {
"names" : [ "MD049" , "emphasis-style" ] ,
2023-10-25 20:05:19 -07:00
"description" : "Emphasis style" ,
2023-01-17 04:19:40 +00:00
"tags" : [ "emphasis" ] ,
"function" : function MD049 ( params , onError ) {
2023-05-25 03:47:34 +00:00
return impl ( params , onError , "emphasis" , "*" , "_" , params . config . style || undefined ) ;
2023-01-17 04:19:40 +00:00
}
} , {
"names" : [ "MD050" , "strong-style" ] ,
2023-10-25 20:05:19 -07:00
"description" : "Strong style" ,
2023-01-17 04:19:40 +00:00
"tags" : [ "emphasis" ] ,
"function" : function MD050 ( params , onError ) {
2023-05-25 02:50:56 +00:00
return impl ( params , onError , "strong" , "**" , "__" , params . config . style || undefined ) ;
2023-01-17 04:19:40 +00:00
}
} ] ;
2022-01-26 00:21:08 +01:00
/***/ } ) ,
/***/ "../lib/md051.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md051 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
"use strict" ;
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
addErrorDetailIf ,
getHtmlAttributeRe
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByPredicate ,
filterByTypes ,
getHtmlTagInfo
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
2023-01-17 04:19:40 +00:00
2022-04-10 05:37:57 +00:00
// Regular expression for identifying HTML anchor names
2024-01-06 20:47:01 -08:00
const idRe = getHtmlAttributeRe ( "id" ) ;
const nameRe = getHtmlAttributeRe ( "name" ) ;
const anchorRe = /\{(#[a-z\d]+(?:[-_][a-z\d]+)*)\}/gu ;
2023-01-17 04:19:40 +00:00
2023-09-04 12:26:38 -07:00
// Sets for filtering heading tokens during conversion
2024-01-06 20:47:01 -08:00
const childrenExclude = new Set ( [ "image" , "reference" , "resource" ] ) ;
const tokensInclude = new Set ( [ "characterEscapeValue" , "codeTextData" , "data" ] ) ;
2023-09-04 12:26:38 -07:00
2023-09-06 21:25:00 -07:00
/ * *
* @ typedef { import ( "../helpers/micromark.cjs" ) . Token } Token
* /
2022-01-26 00:21:08 +01:00
/ * *
2022-04-10 05:37:57 +00:00
* Converts a Markdown heading into an HTML fragment according to the rules
* used by GitHub .
2022-01-26 00:21:08 +01:00
*
2023-09-06 21:25:00 -07:00
* @ param { Token } headingText Heading text token .
2022-04-10 05:37:57 +00:00
* @ returns { string } Fragment string for heading .
2022-01-26 00:21:08 +01:00
* /
2023-08-04 20:53:38 -07:00
function convertHeadingToHTMLFragment ( headingText ) {
2024-01-06 20:47:01 -08:00
const inlineText = filterByPredicate ( headingText . children , token => tokensInclude . has ( token . type ) , token => childrenExclude . has ( token . type ) ? [ ] : token . children ) . map ( token => token . text ) . join ( "" ) ;
2023-01-17 04:19:40 +00:00
return "#" + encodeURIComponent ( inlineText . toLowerCase ( )
// RegExp source with Ruby's \p{Word} expanded into its General Categories
// https://github.com/gjtorikian/html-pipeline/blob/main/lib/html/pipeline/toc_filter.rb
// https://ruby-doc.org/core-3.0.2/Regexp.html
2024-01-06 20:47:01 -08:00
. replace ( /[^\p{Letter}\p{Mark}\p{Number}\p{Connector_Punctuation}\- ]/gu , "" ) . replace ( / /gu , "-" ) ) ;
2022-01-26 00:21:08 +01:00
}
2023-09-06 21:25:00 -07:00
/ * *
* Unescapes the text of a String - type micromark Token .
*
* @ param { Token } token String - type micromark Token .
* @ returns { string } Unescaped token text .
* /
function unescapeStringTokenText ( token ) {
2024-01-06 20:47:01 -08:00
return filterByTypes ( token . children , [ "characterEscapeValue" , "data" ] ) . map ( child => child . text ) . join ( "" ) ;
2023-09-06 21:25:00 -07:00
}
2022-01-26 00:21:08 +01:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD051" , "link-fragments" ] ,
"description" : "Link fragments should be valid" ,
"tags" : [ "links" ] ,
"function" : function MD051 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const {
tokens
} = params . parsers . micromark ;
const fragments = new Map ( ) ;
2023-08-04 20:53:38 -07:00
2023-01-17 04:19:40 +00:00
// Process headings
2024-01-06 20:47:01 -08:00
const headingTexts = filterByTypes ( tokens , [ "atxHeadingText" , "setextHeadingText" ] ) ;
for ( const headingText of headingTexts ) {
const fragment = convertHeadingToHTMLFragment ( headingText ) ;
if ( fragment !== "#" ) {
const count = fragments . get ( fragment ) || 0 ;
if ( count ) {
fragments . set ( ` ${ fragment } - ${ count } ` , 0 ) ;
}
fragments . set ( fragment , count + 1 ) ;
let match = null ;
while ( ( match = anchorRe . exec ( headingText . text ) ) !== null ) {
const [ , anchor ] = match ;
if ( ! fragments . has ( anchor ) ) {
fragments . set ( anchor , 1 ) ;
2023-08-04 20:53:38 -07:00
}
2023-01-17 04:19:40 +00:00
}
}
2023-08-04 20:53:38 -07:00
}
2024-01-06 20:47:01 -08:00
// Process HTML anchors
for ( const token of filterByTypes ( tokens , [ "htmlText" ] ) ) {
const htmlTagInfo = getHtmlTagInfo ( token ) ;
if ( htmlTagInfo && ! htmlTagInfo . close ) {
const anchorMatch = idRe . exec ( token . text ) || htmlTagInfo . name . toLowerCase ( ) === "a" && nameRe . exec ( token . text ) ;
if ( anchorMatch && anchorMatch . length > 0 ) {
fragments . set ( ` # ${ anchorMatch [ 1 ] } ` , 0 ) ;
2023-01-17 04:19:40 +00:00
}
2023-08-04 20:53:38 -07:00
}
}
2024-01-06 20:47:01 -08:00
// Process link and definition fragments
const parentChilds = [ [ "link" , "resourceDestinationString" ] , [ "definition" , "definitionDestinationString" ] ] ;
for ( const [ parentType , definitionType ] of parentChilds ) {
const links = filterByTypes ( tokens , [ parentType ] ) ;
for ( const link of links ) {
const definitions = filterByTypes ( link . children , [ definitionType ] ) ;
for ( const definition of definitions ) {
const {
endColumn ,
startColumn
} = definition ;
const text = unescapeStringTokenText ( definition ) ;
if ( text . length > 1 && text . startsWith ( "#" ) && ! fragments . has ( text ) && ! fragments . has ( ` # ${ encodeURIComponent ( text . slice ( 1 ) ) } ` ) ) {
// eslint-disable-next-line no-undef-init
let context = undefined ;
// eslint-disable-next-line no-undef-init
let range = undefined ;
// eslint-disable-next-line no-undef-init
let fixInfo = undefined ;
if ( link . startLine === link . endLine ) {
context = link . text ;
range = [ link . startColumn , link . endColumn - link . startColumn ] ;
fixInfo = {
"editColumn" : startColumn ,
"deleteCount" : endColumn - startColumn
} ;
}
const textLower = text . toLowerCase ( ) ;
const mixedCaseKey = [ ... fragments . keys ( ) ] . find ( key => textLower === key . toLowerCase ( ) ) ;
if ( mixedCaseKey ) {
// @ts-ignore
( fixInfo || { } ) . insertText = mixedCaseKey ;
addErrorDetailIf ( onError , link . startLine , mixedCaseKey , text , undefined , context , range , fixInfo ) ;
} else {
addError ( onError , link . startLine , undefined , context , range ) ;
2023-08-04 20:53:38 -07:00
}
}
2023-01-17 04:19:40 +00:00
}
}
2023-08-04 20:53:38 -07:00
}
2023-01-17 04:19:40 +00:00
}
2022-01-26 00:21:08 +01:00
} ;
2022-06-01 20:23:08 -07:00
/***/ } ) ,
/***/ "../lib/md052.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md052 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
"use strict" ;
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
referenceLinkImageData
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
2022-06-01 20:23:08 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD052" , "reference-links-images" ] ,
"description" : "Reference links and images should use a label that is defined" ,
"tags" : [ "images" , "links" ] ,
"function" : function MD052 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const {
config ,
lines
} = params ;
const shortcutSyntax = config . shortcut _syntax || false ;
const {
definitions ,
references ,
shortcuts
} = referenceLinkImageData ( ) ;
const entries = shortcutSyntax ? [ ... references . entries ( ) , ... shortcuts . entries ( ) ] : references . entries ( ) ;
2023-01-17 04:19:40 +00:00
// Look for links/images that use an undefined link reference
2024-01-06 20:47:01 -08:00
for ( const reference of entries ) {
const [ label , datas ] = reference ;
if ( ! definitions . has ( label ) ) {
for ( const data of datas ) {
const [ lineIndex , index , length ] = data ;
// Context will be incomplete if reporting for a multi-line link
const context = lines [ lineIndex ] . slice ( index , index + length ) ;
addError ( onError , lineIndex + 1 , ` Missing link or image reference definition: " ${ label } " ` , context , [ index + 1 , context . length ] ) ;
2023-01-17 04:19:40 +00:00
}
}
2022-06-01 20:23:08 -07:00
}
2023-01-17 04:19:40 +00:00
}
2022-06-01 20:23:08 -07:00
} ;
/***/ } ) ,
/***/ "../lib/md053.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md053 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
"use strict" ;
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
addError ,
ellipsify ,
linkReferenceDefinitionRe
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
referenceLinkImageData
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
2022-06-01 20:23:08 -07:00
module . exports = {
2023-01-17 04:19:40 +00:00
"names" : [ "MD053" , "link-image-reference-definitions" ] ,
"description" : "Link and image reference definitions should be needed" ,
"tags" : [ "images" , "links" ] ,
"function" : function MD053 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const ignored = new Set ( params . config . ignored _definitions || [ "//" ] ) ;
const lines = params . lines ;
const {
references ,
shortcuts ,
definitions ,
duplicateDefinitions
} = referenceLinkImageData ( ) ;
const singleLineDefinition = line => line . replace ( linkReferenceDefinitionRe , "" ) . trim ( ) . length > 0 ;
const deleteFixInfo = {
2023-01-17 04:19:40 +00:00
"deleteCount" : - 1
} ;
// Look for unused link references (unreferenced by any link/image)
2024-01-06 20:47:01 -08:00
for ( const definition of definitions . entries ( ) ) {
const [ label , [ lineIndex ] ] = definition ;
if ( ! ignored . has ( label ) && ! references . has ( label ) && ! shortcuts . has ( label ) ) {
const line = lines [ lineIndex ] ;
addError ( onError , lineIndex + 1 , ` Unused link or image reference definition: " ${ label } " ` , ellipsify ( line ) , [ 1 , line . length ] , singleLineDefinition ( line ) ? deleteFixInfo : 0 ) ;
2023-01-17 04:19:40 +00:00
}
}
2024-01-06 20:47:01 -08:00
// Look for duplicate link references (defined more than once)
for ( const duplicateDefinition of duplicateDefinitions ) {
const [ label , lineIndex ] = duplicateDefinition ;
if ( ! ignored . has ( label ) ) {
const line = lines [ lineIndex ] ;
addError ( onError , lineIndex + 1 , ` Duplicate link or image reference definition: " ${ label } " ` , ellipsify ( line ) , [ 1 , line . length ] , singleLineDefinition ( line ) ? deleteFixInfo : 0 ) ;
2023-01-17 04:19:40 +00:00
}
2022-06-01 20:23:08 -07:00
}
2023-01-17 04:19:40 +00:00
}
2022-06-01 20:23:08 -07:00
} ;
2021-01-05 20:55:09 -08:00
/***/ } ) ,
2023-10-25 20:05:19 -07:00
/***/ "../lib/md054.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md054 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
"use strict" ;
// @ts-check
2024-01-06 20:47:01 -08:00
const {
addErrorContext ,
nextLinesRe
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes ,
filterByPredicate ,
getTokenTextByType
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
const {
referenceLinkImageData
} = _ _webpack _require _ _ ( /*! ./cache */ "../lib/cache.js" ) ;
const backslashEscapeRe = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g ;
const removeBackslashEscapes = text => text . replace ( backslashEscapeRe , "$1" ) ;
const autolinkDisallowedRe = /[ <>]/ ;
const autolinkAble = destination => {
2023-10-25 20:05:19 -07:00
try {
// eslint-disable-next-line no-new
new URL ( destination ) ;
2024-01-06 20:47:01 -08:00
} catch {
2023-10-25 20:05:19 -07:00
// Not an absolute URL
return false ;
}
return ! autolinkDisallowedRe . test ( destination ) ;
} ;
module . exports = {
"names" : [ "MD054" , "link-image-style" ] ,
"description" : "Link and image style" ,
"tags" : [ "images" , "links" ] ,
2024-01-06 20:47:01 -08:00
"function" : ( params , onError ) => {
const {
parsers ,
config
} = params ;
const autolink = config . autolink === undefined || ! ! config . autolink ;
const inline = config . inline === undefined || ! ! config . inline ;
const full = config . full === undefined || ! ! config . full ;
const collapsed = config . collapsed === undefined || ! ! config . collapsed ;
const shortcut = config . shortcut === undefined || ! ! config . shortcut ;
const urlInline = config . url _inline === undefined || ! ! config . url _inline ;
2023-11-12 22:42:02 -08:00
if ( autolink && inline && full && collapsed && shortcut && urlInline ) {
2023-10-25 20:05:19 -07:00
// Everything allowed, nothing to check
return ;
}
2024-01-06 20:47:01 -08:00
const {
definitions
} = referenceLinkImageData ( ) ;
const links = filterByTypes ( parsers . micromark . tokens , [ "autolink" , "image" , "link" ] ) ;
for ( const link of links ) {
let label = null ;
let destination = null ;
const {
children ,
endColumn ,
endLine ,
startColumn ,
startLine ,
text ,
type
} = link ;
const image = type === "image" ;
let isError = false ;
if ( type === "autolink" ) {
// link kind is an autolink
destination = getTokenTextByType ( children , "autolinkProtocol" ) ;
label = destination ;
isError = ! autolink ;
} else {
// link type is "image" or "link"
const descendents = filterByPredicate ( children ) ;
label = getTokenTextByType ( descendents , "labelText" ) ;
destination = getTokenTextByType ( descendents , "resourceDestinationString" ) ;
if ( destination ) {
// link kind is an inline link
const title = getTokenTextByType ( descendents , "resourceTitleString" ) ;
isError = ! inline || ! urlInline && autolink && ! image && ! title && label === destination && autolinkAble ( destination ) ;
2023-10-25 20:05:19 -07:00
} else {
2024-01-06 20:47:01 -08:00
// link kind is a full/collapsed/shortcut reference link
const isShortcut = ! children . some ( t => t . type === "reference" ) ;
const referenceString = getTokenTextByType ( descendents , "referenceString" ) ;
const isCollapsed = referenceString === null ;
const definition = definitions . get ( referenceString || label ) ;
destination = definition && definition [ 1 ] ;
isError = destination && ( isShortcut ? ! shortcut : isCollapsed ? ! collapsed : ! full ) ;
2023-10-25 20:05:19 -07:00
}
2024-01-06 20:47:01 -08:00
}
if ( isError ) {
let range = null ;
let fixInfo = null ;
if ( startLine === endLine ) {
range = [ startColumn , endColumn - startColumn ] ;
let insertText = null ;
const canInline = inline && label ;
const canAutolink = autolink && ! image && autolinkAble ( destination ) ;
if ( canInline && ( urlInline || ! canAutolink ) ) {
// Most useful form
const prefix = image ? "!" : "" ;
// @ts-ignore
const escapedLabel = label . replace ( /[[\]]/g , "\\$&" ) ;
const escapedDestination = destination . replace ( /[()]/g , "\\$&" ) ;
insertText = ` ${ prefix } [ ${ escapedLabel } ]( ${ escapedDestination } ) ` ;
} else if ( canAutolink ) {
// Simplest form
insertText = ` < ${ removeBackslashEscapes ( destination ) } > ` ;
}
if ( insertText ) {
fixInfo = {
"editColumn" : range [ 0 ] ,
insertText ,
"deleteCount" : range [ 1 ]
} ;
2023-10-25 20:05:19 -07:00
}
}
2024-01-06 20:47:01 -08:00
addErrorContext ( onError , startLine , text . replace ( nextLinesRe , "" ) , null , null , range , fixInfo ) ;
2023-10-25 20:05:19 -07:00
}
}
}
} ;
/***/ } ) ,
2023-12-30 18:15:38 -08:00
/***/ "../lib/md055.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md055 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
"use strict" ;
// @ts-check
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
const whitespaceTypes = new Set ( [ "linePrefix" , "whitespace" ] ) ;
const ignoreWhitespace = tokens => tokens . filter ( token => ! whitespaceTypes . has ( token . type ) ) ;
const firstOrNothing = items => items [ 0 ] ;
const lastOrNothing = items => items [ items . length - 1 ] ;
const makeRange = ( start , end ) => [ start , end - start + 1 ] ;
2023-12-30 18:15:38 -08:00
module . exports = {
"names" : [ "MD055" , "table-pipe-style" ] ,
"description" : "Table pipe style" ,
"tags" : [ "table" ] ,
"function" : function MD055 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const style = String ( params . config . style || "consistent" ) ;
let expectedStyle = style ;
let expectedLeadingPipe = expectedStyle !== "no_leading_or_trailing" && expectedStyle !== "trailing_only" ;
let expectedTrailingPipe = expectedStyle !== "no_leading_or_trailing" && expectedStyle !== "leading_only" ;
const tables = filterByTypes ( params . parsers . micromark . tokens , [ "table" ] ) ;
for ( const table of tables ) {
const rows = filterByTypes ( table . children , [ "tableDelimiterRow" , "tableRow" ] ) ;
for ( const row of rows ) {
// The following uses of first/lastOrNothing lack fallback handling
// because it seems not to be possible (i.e., 0% coverage)
const firstCell = firstOrNothing ( row . children ) ;
const leadingToken = firstOrNothing ( ignoreWhitespace ( firstCell . children ) ) ;
const actualLeadingPipe = leadingToken . type === "tableCellDivider" ;
const lastCell = lastOrNothing ( row . children ) ;
const trailingToken = lastOrNothing ( ignoreWhitespace ( lastCell . children ) ) ;
const actualTrailingPipe = trailingToken . type === "tableCellDivider" ;
const actualStyle = actualLeadingPipe ? actualTrailingPipe ? "leading_and_trailing" : "leading_only" : actualTrailingPipe ? "trailing_only" : "no_leading_or_trailing" ;
if ( expectedStyle === "consistent" ) {
expectedStyle = actualStyle ;
expectedLeadingPipe = actualLeadingPipe ;
expectedTrailingPipe = actualTrailingPipe ;
}
if ( actualLeadingPipe !== expectedLeadingPipe ) {
addErrorDetailIf ( onError , firstCell . startLine , expectedStyle , actualStyle , ` ${ expectedLeadingPipe ? "Missing" : "Unexpected" } leading pipe ` , undefined , makeRange ( row . startColumn , firstCell . startColumn ) ) ;
}
if ( actualTrailingPipe !== expectedTrailingPipe ) {
addErrorDetailIf ( onError , lastCell . endLine , expectedStyle , actualStyle , ` ${ expectedTrailingPipe ? "Missing" : "Unexpected" } trailing pipe ` , undefined , makeRange ( lastCell . endColumn - 1 , row . endColumn - 1 ) ) ;
2023-12-30 18:15:38 -08:00
}
}
}
}
} ;
/***/ } ) ,
2024-01-04 23:07:55 -08:00
/***/ "../lib/md056.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / md056 . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
"use strict" ;
// @ts-check
2024-01-06 20:47:01 -08:00
const {
addErrorDetailIf
} = _ _webpack _require _ _ ( /*! ../helpers */ "../helpers/helpers.js" ) ;
const {
filterByTypes
} = _ _webpack _require _ _ ( /*! ../helpers/micromark.cjs */ "../helpers/micromark.cjs" ) ;
const makeRange = ( start , end ) => [ start , end - start + 1 ] ;
2024-01-04 23:07:55 -08:00
module . exports = {
"names" : [ "MD056" , "table-column-count" ] ,
"description" : "Table column count" ,
"tags" : [ "table" ] ,
"function" : function MD056 ( params , onError ) {
2024-01-06 20:47:01 -08:00
const tables = filterByTypes ( params . parsers . micromark . tokens , [ "table" ] ) ;
for ( const table of tables ) {
const rows = filterByTypes ( table . children , [ "tableDelimiterRow" , "tableRow" ] ) ;
let expectedCount = 0 ;
for ( const row of rows ) {
const cells = filterByTypes ( row . children , [ "tableData" , "tableDelimiter" , "tableHeader" ] ) ;
const actualCount = cells . length ;
expectedCount || = actualCount ;
let detail = null ;
let range = null ;
if ( actualCount < expectedCount ) {
detail = "Too few cells, row will be missing data" ;
range = [ row . endColumn - 1 , 1 ] ;
} else if ( expectedCount < actualCount ) {
detail = "Too many cells, extra data will be missing" ;
range = makeRange ( cells [ expectedCount ] . startColumn , row . endColumn - 1 ) ;
2024-01-04 23:07:55 -08:00
}
2024-01-06 20:47:01 -08:00
addErrorDetailIf ( onError , row . endLine , expectedCount , actualCount , detail , null , range ) ;
2024-01-04 23:07:55 -08:00
}
}
}
} ;
/***/ } ) ,
2021-01-06 19:45:15 -08:00
/***/ "../lib/rules.js" :
/ * ! * * * * * * * * * * * * * * * * * * * * * * * ! * \
! * * * . . / lib / rules . js * * * !
\ * * * * * * * * * * * * * * * * * * * * * * * /
2022-06-02 21:42:48 -07:00
/***/ ( ( module , _ _unused _webpack _exports , _ _webpack _require _ _ ) => {
2021-01-05 20:55:09 -08:00
2019-12-14 13:50:48 -08:00
"use strict" ;
2021-01-05 20:55:09 -08:00
// @ts-check
2023-01-17 04:19:40 +00:00
2024-01-06 20:47:01 -08:00
const {
homepage ,
version
} = _ _webpack _require _ _ ( /*! ./constants */ "../lib/constants.js" ) ;
const rules = [ _ _webpack _require _ _ ( /*! ./md001 */ "../lib/md001.js" ) ,
2024-01-04 23:07:55 -08:00
// md002: Deprecated and removed
_ _webpack _require _ _ ( /*! ./md003 */ "../lib/md003.js" ) , _ _webpack _require _ _ ( /*! ./md004 */ "../lib/md004.js" ) , _ _webpack _require _ _ ( /*! ./md005 */ "../lib/md005.js" ) ,
// md006: Deprecated and removed
2024-01-06 20:47:01 -08:00
_ _webpack _require _ _ ( /*! ./md007 */ "../lib/md007.js" ) , _ _webpack _require _ _ ( /*! ./md009 */ "../lib/md009.js" ) , _ _webpack _require _ _ ( /*! ./md010 */ "../lib/md010.js" ) , _ _webpack _require _ _ ( /*! ./md011 */ "../lib/md011.js" ) , _ _webpack _require _ _ ( /*! ./md012 */ "../lib/md012.js" ) , _ _webpack _require _ _ ( /*! ./md013 */ "../lib/md013.js" ) , _ _webpack _require _ _ ( /*! ./md014 */ "../lib/md014.js" ) , _ _webpack _require _ _ ( /*! ./md018 */ "../lib/md018.js" ) , _ _webpack _require _ _ ( /*! ./md019 */ "../lib/md019.js" ) , _ _webpack _require _ _ ( /*! ./md020 */ "../lib/md020.js" ) , _ _webpack _require _ _ ( /*! ./md021 */ "../lib/md021.js" ) , _ _webpack _require _ _ ( /*! ./md022 */ "../lib/md022.js" ) , _ _webpack _require _ _ ( /*! ./md023 */ "../lib/md023.js" ) , _ _webpack _require _ _ ( /*! ./md024 */ "../lib/md024.js" ) , _ _webpack _require _ _ ( /*! ./md025 */ "../lib/md025.js" ) , _ _webpack _require _ _ ( /*! ./md026 */ "../lib/md026.js" ) , _ _webpack _require _ _ ( /*! ./md027 */ "../lib/md027.js" ) , _ _webpack _require _ _ ( /*! ./md028 */ "../lib/md028.js" ) , _ _webpack _require _ _ ( /*! ./md029 */ "../lib/md029.js" ) , _ _webpack _require _ _ ( /*! ./md030 */ "../lib/md030.js" ) , _ _webpack _require _ _ ( /*! ./md031 */ "../lib/md031.js" ) , _ _webpack _require _ _ ( /*! ./md032 */ "../lib/md032.js" ) , _ _webpack _require _ _ ( /*! ./md033 */ "../lib/md033.js" ) , _ _webpack _require _ _ ( /*! ./md034 */ "../lib/md034.js" ) , _ _webpack _require _ _ ( /*! ./md035 */ "../lib/md035.js" ) , _ _webpack _require _ _ ( /*! ./md036 */ "../lib/md036.js" ) , _ _webpack _require _ _ ( /*! ./md037 */ "../lib/md037.js" ) , _ _webpack _require _ _ ( /*! ./md038 */ "../lib/md038.js" ) , _ _webpack _require _ _ ( /*! ./md039 */ "../lib/md039.js" ) , _ _webpack _require _ _ ( /*! ./md040 */ "../lib/md040.js" ) , _ _webpack _require _ _ ( /*! ./md041 */ "../lib/md041.js" ) , _ _webpack _require _ _ ( /*! ./md042 */ "../lib/md042.js" ) , _ _webpack _require _ _ ( /*! ./md043 */ "../lib/md043.js" ) , _ _webpack _require _ _ ( /*! ./md044 */ "../lib/md044.js" ) , _ _webpack _require _ _ ( /*! ./md045 */ "../lib/md045.js" ) , _ _webpack _require _ _ ( /*! ./md046 */ "../lib/md046.js" ) , _ _webpack _require _ _ ( /*! ./md047 */ "../lib/md047.js" ) , _ _webpack _require _ _ ( /*! ./md048 */ "../lib/md048.js" ) , ... _ _webpack _require _ _ ( /*! ./md049-md050 */ "../lib/md049-md050.js" ) , _ _webpack _require _ _ ( /*! ./md051 */ "../lib/md051.js" ) , _ _webpack _require _ _ ( /*! ./md052 */ "../lib/md052.js" ) , _ _webpack _require _ _ ( /*! ./md053 */ "../lib/md053.js" ) , _ _webpack _require _ _ ( /*! ./md054 */ "../lib/md054.js" ) , _ _webpack _require _ _ ( /*! ./md055 */ "../lib/md055.js" ) , _ _webpack _require _ _ ( /*! ./md056 */ "../lib/md056.js" )
2023-10-25 20:05:19 -07:00
// md057: See https://github.com/markdownlint/markdownlint
2024-01-06 20:47:01 -08:00
] ;
for ( const rule of rules ) {
const name = rule . names [ 0 ] . toLowerCase ( ) ;
// eslint-disable-next-line dot-notation
rule [ "information" ] = new URL ( ` ${ homepage } /blob/v ${ version } /doc/ ${ name } .md ` ) ;
2022-06-08 22:10:27 -07:00
}
2019-10-02 20:10:42 -07:00
module . exports = rules ;
2021-01-05 20:55:09 -08:00
/***/ } )
/******/ } ) ;
/************************************************************************/
/******/ // The module cache
/******/ var _ _webpack _module _cache _ _ = { } ;
/******/
/******/ // The require function
/******/ function _ _webpack _require _ _ ( moduleId ) {
/******/ // Check if module is in cache
Update dependencies: c8 to 7.7.2, eslint to 7.28.0, eslint-plugin-jsdoc to 35.1.3, eslint-plugin-unicorn to 33.0.1, globby to 11.0.3, js-yaml to 4.1.0, markdown-it-texmath to 0.9.0, markdownlint-rule-helpers to 0.14.0, ts-loader to 9.2.3, typescript to 4.3.2, webpack to 5.38.1, webpack-cli to 4.7.2.
2021-06-08 22:20:13 -07:00
/******/ var cachedModule = _ _webpack _module _cache _ _ [ moduleId ] ;
/******/ if ( cachedModule !== undefined ) {
/******/ return cachedModule . exports ;
2021-01-05 20:55:09 -08:00
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = _ _webpack _module _cache _ _ [ moduleId ] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports : { }
/******/ } ;
/******/
/******/ // Execute the module function
2022-06-02 21:42:48 -07:00
/******/ _ _webpack _modules _ _ [ moduleId ] ( module , module . exports , _ _webpack _require _ _ ) ;
2021-01-05 20:55:09 -08:00
/******/
/******/ // Return the exports of the module
/******/ return module . exports ;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ ( ( ) => {
2021-02-06 19:23:55 -08:00
/******/ _ _webpack _require _ _ . o = ( obj , prop ) => ( Object . prototype . hasOwnProperty . call ( obj , prop ) )
2021-01-05 20:55:09 -08:00
/******/ } ) ( ) ;
/******/
/************************************************************************/
Update dependencies: c8 to 7.7.2, eslint to 7.28.0, eslint-plugin-jsdoc to 35.1.3, eslint-plugin-unicorn to 33.0.1, globby to 11.0.3, js-yaml to 4.1.0, markdown-it-texmath to 0.9.0, markdownlint-rule-helpers to 0.14.0, ts-loader to 9.2.3, typescript to 4.3.2, webpack to 5.38.1, webpack-cli to 4.7.2.
2021-06-08 22:20:13 -07:00
/******/
2021-01-05 20:55:09 -08:00
/******/ // startup
/******/ // Load entry module and return exports
Update dependencies: c8 to 7.7.2, eslint to 7.28.0, eslint-plugin-jsdoc to 35.1.3, eslint-plugin-unicorn to 33.0.1, globby to 11.0.3, js-yaml to 4.1.0, markdown-it-texmath to 0.9.0, markdownlint-rule-helpers to 0.14.0, ts-loader to 9.2.3, typescript to 4.3.2, webpack to 5.38.1, webpack-cli to 4.7.2.
2021-06-08 22:20:13 -07:00
/******/ // This entry module is referenced by other modules so it can't be inlined
2022-12-29 00:43:53 +00:00
/******/ var _ _webpack _exports _ _ = _ _webpack _require _ _ ( "./markdownlint-exports.js" ) ;
Update dependencies: c8 to 7.7.2, eslint to 7.28.0, eslint-plugin-jsdoc to 35.1.3, eslint-plugin-unicorn to 33.0.1, globby to 11.0.3, js-yaml to 4.1.0, markdown-it-texmath to 0.9.0, markdownlint-rule-helpers to 0.14.0, ts-loader to 9.2.3, typescript to 4.3.2, webpack to 5.38.1, webpack-cli to 4.7.2.
2021-06-08 22:20:13 -07:00
/******/ markdownlint = _ _webpack _exports _ _ ;
/******/
2021-01-05 20:55:09 -08:00
/******/ } ) ( )
;