@@ -4,7 +4,7 @@ import { addErrorContext, addErrorDetailIf } from "../helpers/helpers.cjs";
44import { getHeadingLevel , getHeadingText } from "../helpers/micromark-helpers.cjs" ;
55import { filterByTypesCached } from "./cache.mjs" ;
66
7- export const headingsItemsRe = / ^ ( [ * + ? ] | [ # % ] { 1 , 6 } \s + \S .* ) $ / u;
7+ export const headingsItemsRe = / ^ ( [ * + ? ] | \^ + | [ # % ] { 1 , 6 } \s + \S .* ) $ / u;
88const headingPartsRe = / ^ ( [ # % ] { 1 , 6 } ) \s + ( \S .* ) $ / u;
99
1010const headingIsExpected = ( /** @type {string } */ actual , /** @type {string } */ expected , /** @type {boolean } */ matchCase ) => {
@@ -50,7 +50,28 @@ export default {
5050 const headingLevel = getHeadingLevel ( heading ) ;
5151 anyHeadings = true ;
5252 const actual = `${ "" . padEnd ( headingLevel , "#" ) } ${ headingText } ` ;
53- const expected = getExpected ( ) ;
53+ let expected = getExpected ( ) ;
54+
55+ if ( expected . startsWith ( "^" ) ) {
56+ const save = i ;
57+ const nextExpected = getExpected ( ) ;
58+ if ( headingIsExpected ( actual , nextExpected , matchCase ) ) {
59+ expected = nextExpected ;
60+ } else {
61+ for ( let j = save - 1 ; j -- ; j >= 0 ) {
62+ if ( requiredHeadings [ j ] === expected ) {
63+ i = j + 1 ;
64+ expected = getExpected ( ) ;
65+ break ;
66+ }
67+ }
68+ if ( i < 0 ) {
69+ // Nothing to skip back to; continue from current location
70+ i = save ;
71+ }
72+ }
73+ }
74+
5475 if ( expected === "*" ) {
5576 const nextExpected = getExpected ( ) ;
5677 if ( ! headingIsExpected ( actual , nextExpected , matchCase ) ) {
@@ -80,7 +101,8 @@ export default {
80101 if (
81102 ! hasError &&
82103 ( ( extraHeadings > 1 ) ||
83- ( ( extraHeadings === 1 ) && ( requiredHeadings [ i ] !== "*" ) ) ) &&
104+ ( ( extraHeadings === 1 ) &&
105+ ( ( requiredHeadings [ i ] !== "*" ) && ( requiredHeadings [ i ] !== "^" ) ) ) ) &&
84106 ( anyHeadings || ! requiredHeadings . every ( ( heading ) => heading === "*" ) )
85107 ) {
86108 addErrorContext (
0 commit comments