@@ -35,9 +35,9 @@ public class DocumentParser implements ParserState {
3535
3636 private int nextNonSpace = 0 ;
3737 private int nextNonSpaceColumn = 0 ;
38- private boolean blank ;
39-
4038 private int indent = 0 ;
39+ private boolean blank ;
40+ private boolean columnIsInTab ;
4141
4242 private final List <BlockParserFactory > blockParserFactories ;
4343 private final InlineParserImpl inlineParser ;
@@ -192,7 +192,7 @@ private void incorporateLine(CharSequence ln) {
192192 findNextNonSpace ();
193193
194194 // this is a little performance optimization:
195- if (isBlank () || (indent < IndentedCodeBlockParser . INDENT && Parsing .isLetter (line , nextNonSpace ))) {
195+ if (isBlank () || (indent < Parsing . CODE_BLOCK_INDENT && Parsing .isLetter (line , nextNonSpace ))) {
196196 setNewIndex (nextNonSpace );
197197 break ;
198198 }
@@ -301,20 +301,46 @@ private void setNewColumn(int newColumn) {
301301 // Last character was a tab and we overshot our target
302302 index --;
303303 column = newColumn ;
304+ columnIsInTab = true ;
305+ } else {
306+ columnIsInTab = false ;
304307 }
305308 }
306309
307310 private void advance () {
308311 char c = line .charAt (index );
309312 if (c == '\t' ) {
310313 index ++;
311- column += ( 4 - ( column % 4 ) );
314+ column += Parsing . columnsToNextTabStop ( column );
312315 } else {
313316 index ++;
314317 column ++;
315318 }
316319 }
317320
321+ /**
322+ * Add line content to the active block parser. We assume it can accept lines -- that check should be done before
323+ * calling this.
324+ */
325+ private void addLine () {
326+ CharSequence content ;
327+ if (columnIsInTab ) {
328+ // Our column is in a partially consumed tab. Expand the remaining columns (to the next tab stop) to spaces.
329+ int afterTab = index + 1 ;
330+ CharSequence rest = line .subSequence (afterTab , line .length ());
331+ int spaces = Parsing .columnsToNextTabStop (column );
332+ StringBuilder sb = new StringBuilder (spaces + rest .length ());
333+ for (int i = 0 ; i < spaces ; i ++) {
334+ sb .append (' ' );
335+ }
336+ sb .append (rest );
337+ content = sb .toString ();
338+ } else {
339+ content = line .subSequence (index , line .length ());
340+ }
341+ getActiveBlockParser ().addLine (content );
342+ }
343+
318344 private BlockStartImpl findBlockStart (BlockParser blockParser ) {
319345 MatchedBlockParser matchedBlockParser = new MatchedBlockParserImpl (blockParser );
320346 for (BlockParserFactory blockParserFactory : blockParserFactories ) {
@@ -410,14 +436,6 @@ private void breakOutOfLists(List<BlockParser> blockParsers) {
410436 }
411437 }
412438
413- /**
414- * Add a line to the block at the tip. We assume the tip can accept lines -- that check should be done before
415- * calling this.
416- */
417- private void addLine () {
418- getActiveBlockParser ().addLine (line .subSequence (index , line .length ()));
419- }
420-
421439 /**
422440 * Add block of type tag as a child of the tip. If the tip can't accept children, close and finalize it and try
423441 * its parent, and so on til we find a block that can accept children.
0 commit comments