@@ -150,6 +150,10 @@ function State(input, options) {
150
150
this . lineStart = 0 ;
151
151
this . lineIndent = 0 ;
152
152
153
+ // position of first leading tab in the current line,
154
+ // used to make sure there are no tabs in the indentation
155
+ this . firstTabInLine = - 1 ;
156
+
153
157
this . documents = [ ] ;
154
158
155
159
/*
@@ -389,6 +393,7 @@ function readLineBreak(state) {
389
393
390
394
state . line += 1 ;
391
395
state . lineStart = state . position ;
396
+ state . firstTabInLine = - 1 ;
392
397
}
393
398
394
399
function skipSeparationSpace ( state , allowComments , checkIndent ) {
@@ -397,6 +402,9 @@ function skipSeparationSpace(state, allowComments, checkIndent) {
397
402
398
403
while ( ch !== 0 ) {
399
404
while ( is_WHITE_SPACE ( ch ) ) {
405
+ if ( ch === 0x09 /* Tab */ && state . firstTabInLine === - 1 ) {
406
+ state . firstTabInLine = state . position ;
407
+ }
400
408
ch = state . input . charCodeAt ( ++ state . position ) ;
401
409
}
402
410
@@ -959,13 +967,21 @@ function readBlockSequence(state, nodeIndent) {
959
967
detected = false ,
960
968
ch ;
961
969
970
+ // there is a leading tab before this token, so it can't be a block sequence/mapping;
971
+ // it can still be flow sequence/mapping or a scalar
972
+ if ( state . firstTabInLine !== - 1 ) return false ;
973
+
962
974
if ( state . anchor !== null ) {
963
975
state . anchorMap [ state . anchor ] = _result ;
964
976
}
965
977
966
978
ch = state . input . charCodeAt ( state . position ) ;
967
979
968
980
while ( ch !== 0 ) {
981
+ if ( state . firstTabInLine !== - 1 ) {
982
+ state . position = state . firstTabInLine ;
983
+ throwError ( state , 'tab characters must not be used in indentation' ) ;
984
+ }
969
985
970
986
if ( ch !== 0x2D /* - */ ) {
971
987
break ;
@@ -1030,13 +1046,22 @@ function readBlockMapping(state, nodeIndent, flowIndent) {
1030
1046
detected = false ,
1031
1047
ch ;
1032
1048
1049
+ // there is a leading tab before this token, so it can't be a block sequence/mapping;
1050
+ // it can still be flow sequence/mapping or a scalar
1051
+ if ( state . firstTabInLine !== - 1 ) return false ;
1052
+
1033
1053
if ( state . anchor !== null ) {
1034
1054
state . anchorMap [ state . anchor ] = _result ;
1035
1055
}
1036
1056
1037
1057
ch = state . input . charCodeAt ( state . position ) ;
1038
1058
1039
1059
while ( ch !== 0 ) {
1060
+ if ( ! atExplicitKey && state . firstTabInLine !== - 1 ) {
1061
+ state . position = state . firstTabInLine ;
1062
+ throwError ( state , 'tab characters must not be used in indentation' ) ;
1063
+ }
1064
+
1040
1065
following = state . input . charCodeAt ( state . position + 1 ) ;
1041
1066
_line = state . line ; // Save the current line.
1042
1067
0 commit comments