2
0
Эх сурвалжийг харах

* Fix bug where fenced code blocks in indented list items are not recognized

Michaël Van Canneyt 8 цаг өмнө
parent
commit
9e28a0ee80

+ 2 - 0
packages/fcl-md/src/markdown.elements.pas

@@ -206,10 +206,12 @@ Type
   private
     FFenced: boolean;
     FLang: AnsiString;
+    FIndent : Integer;
   public
     function WhiteSpaceMode : TWhitespaceMode; override;
     property Fenced : boolean read FFenced write FFenced;
     property Lang : AnsiString read FLang write FLang;
+    Property Indent : Integer Read FIndent Write FIndent;
   end;
 
 

+ 16 - 15
packages/fcl-md/src/markdown.processors.pas

@@ -428,8 +428,11 @@ begin
   if (lBlock is TMarkDownListItemBlock) and (lBlock.Parent is TMarkDownListBlock) then
      lBlock:=lBlock.Parent as TMarkDownListBlock;
   if (lBlock is TMarkDownListBlock) then
-    if aLine.LeadingWhitespace>=lList.baseIndent then
-      Result:=False
+    if aLine.LeadingWhitespace>=lList.LastIndent then
+      begin
+      aLine.Advance(lList.LastIndent);
+      Result:=False;
+      end;
 end;
 
 function TUListProcessor.HandlesLine(aParent: TMarkDownContainerBlock; aLine: TMarkDownLine): boolean;
@@ -630,7 +633,10 @@ begin
      lBlock:=lBlock.Parent as TMarkDownListBlock;
   if (lBlock is TMarkDownListBlock) then
     if aLine.LeadingWhitespace>=lList.baseIndent then
+      begin
+      aLine.Advance(lList.LastIndent);
       Result:=False
+      end;
 end;
 
 
@@ -811,13 +817,15 @@ function TFencedCodeBlockProcessor.LineEndsBlock(aBlock: TMarkDownContainerBlock
 
 var
   s : String;
+  lBlock: TMarkdownCodeBlock absolute aBlock;
 
 begin
   Result:=(aLine=nil);
   if Result then
     Exit;
   // Ending may be preceded by 3 spaces
-  Result:=aLine.LeadingWhitespace>=4;
+
+  Result:=aLine.LeadingWhitespace>=4+lBlock.Indent;
   if Result then
     Exit;
   S:=aLine.Remainder.Trim;
@@ -829,27 +837,20 @@ function TFencedCodeBlockProcessor.processLine(aParent: TMarkDownContainerBlock;
 var
   lBlock : TMarkDownCodeBlock;
   s : String;
-  i : integer;
 
 begin
   lBlock:=TMarkDownCodeBlock.Create(aParent,aLine.LineNo);
   lBlock.fenced:=true;
   lBlock.lang:=Flang;
+  lBlock.Indent:=aLine.CursorPos;
   while Not LineEndsBlock(lBlock,PeekLine) do
     begin
     aLine:=NextLine;
+    if aLine.LeadingWhitespace>=lBlock.Indent then
+      aLine.Advance(lBlock.Indent)
+    else
+      aLine.Advance(aLine.LeadingWhitespace);
     s:=aLine.Remainder;
-    if (FIndent>0) then
-      begin
-      if FIndent>Length(S) then
-        FIndent:=Length(S);
-      I:=1;
-      while (I<=Findent) and (s[i]=' ') do
-        Inc(i);
-      if I>1 then
-        Delete(S,1,I-1);
-      aLine.advance(I-1);
-      end;
     TMarkDownTextBlock.Create(lBlock,aLine.LineNo,S);
     end;
   NextLine;

+ 20 - 0
packages/fcl-md/tests/utest.markdown.parser.pas

@@ -61,6 +61,7 @@ type
     procedure TestIndentedCodeBlock;
     procedure TestFencedCodeBlock;
     procedure TestFencedCodeBlockWithInfoString;
+    procedure TestNestedCodeBlock;
   end;
 
   { TTestBlockQuotes }
@@ -237,6 +238,25 @@ begin
   AssertEquals('Language info string incorrect', 'pascal', Block.Lang);
 end;
 
+procedure TTestCodeBlocks.TestNestedCodeBlock;
+var
+  lList : TMarkDownListBlock;
+  lItem : TMarkDownListItemBlock;
+  Block: TMarkDownCodeBlock;
+
+begin
+  SetupParser('* List'#10'   ```'#10'code here'#10'```');
+  AssertEquals('Document should have 1 block', 1, Doc.Blocks.Count);
+  lList := GetBlock(0) as TMarkDownListBlock;
+  AssertEquals('List should have 1 blocks', 1, lList.Blocks.Count);
+  lItem := lList.Blocks[0] as TMarkDownListItemBlock;
+  AssertEquals('List item should have 2 blocks', 2, lItem.Blocks.Count);
+  AssertEquals('First list item is paragraph block', TMarkDownParagraphBlock, lItem.Blocks[0].ClassType);
+  AssertEquals('Second list item is code block', TMarkDownCodeBlock, lItem.Blocks[1].ClassType);
+  Block := lItem.Blocks[1] as TMarkDownCodeBlock;
+  AssertTrue('Should be a fenced code block', Block.Fenced);
+end;
+
 { TTestBlockQuotes }
 
 procedure TTestBlockQuotes.TestSimpleQuote;