ブログソフトに markdownリストを実装した、と思う・・。まだバグがありそう。
<ul><ol>が混在してインデントすると混乱してしまい手ごわかった。再帰的な方法でもっと簡単に実現できる気がする。

デバッグ中の様子
../file/20180701003709_1.gif

該当部分のLazarus ソース 、デバッグする度にソースコードが伸びていく・・。

function TMarkdown_ListList.ToHtml(const aStr: string): string;
var
  sl:TStringList;
  i,i2,i3,Ltype:integer;
  str:widestring;
  it1,it2:TMarkdown_ListListRec;
  r:TmStr;
begin
  sl:=TStringList.Create;
  try
    sl.Text:=aStr;
    for i:=0 to sl.Count-1 do begin
      str:=sl[i];
      Ltype:=Check_MarkdownList(str,i2);
      ItemAdd;
      Item.ListType:=Ltype;
      Item.Status:=Ltype;
      Item.Indent:=i2;
      Item.Str:=str;
      ItemUpdate;
    end;
    //最初からインデントしている行はリスト表示しない
    i:=0;
    while i<Count do begin
      ItemGet(i);
      if Item.Indent=0 then Break;
      Item.ListType:=0;//リスト処理しない
      ItemUpdate;
      inc(i);
    end;
    //インデント確認 エラー行削除
    i:=1;
    while i<Count do begin
      it1:=Items[i-1];
      it2:=Items[i];
      //+2以上のインデントは前の行に連結(エラー)
      if it1.Indent<(it2.Indent-1) then begin
        it1.Str:=it1.Str+' [markdown list err!:'+it2.Str+']';
        Items[i-1]:=it1;
        Items.Delete(i);
        Continue;
      end;
      //-2以下のインデントは空行を追加
      if it1.Indent>(it2.Indent+1) then begin
        i3:=it1.Indent-it2.Indent;
        for i2:=2 to i3 do begin
          it1.Indent:=it1.Indent-1;
          it1.Str:='';
          it1.ListType:=5;//これは下で正しい値に上書きされるはず
          it1.Status:=5;
          Items.Insert(i,it1);
          inc(i);
        end;
        inc(i);
        Continue;
      end;
      inc(i);
    end;
    //最終行がインデント1以上の場合は空行を追加
    ItemGet(Count-1);
    while Item.Indent>0 do begin
      i2:=Item.Indent;
      dec(i2);
      ItemAdd;
      Item.Indent:=i2;
      Item.Status:=5;
      ItemUpdate;
      ItemGet(Count-1);
    end;
    //同じインデントのリスト種類を修正、
    i:=1;
    it2:=Items[0];
    while i<Count do begin
      it1:=Items[i-1];
      it2:=Items[i];
      //同じインデント
      if it1.Indent=it2.Indent then begin
        it2.ListType:=it1.ListType;
        Items[i]:=it2;
      end;
      //ネスト下り
      if it1.Indent>it2.Indent then begin
        i2:=i-1;
        i3:=it2.Indent;
        while i2>=0 do begin
          it2:=Items[i2];
          if it2.Indent=i3 then begin
            it2:=Items[i];
            it2.ListType:=Items[i2].ListType;
            Items[i]:=it2;
            Break;
          end;
          dec(i2);
        end;
      end;
      inc(i);
    end;
    //<ul><ol>の開き閉じをセット
    i:=0;
    it2:=Items[i];
    case it2.ListType of
      1:begin
        it2.TagFront:='<ul>';
      end;
      2:begin
        it2.TagFront:='<ol>';
      end;
    end;
    Items[i]:=it2;
    inc(i);
    while i<Count do begin
      it1:=Items[i-1];
      it2:=Items[i];
      //ネスト上がり
      if it1.Indent<it2.Indent then begin
        case it2.ListType of
          1:begin
            it2.TagFront:='<ul>';
          end;
          2:begin
            it2.TagFront:='<ol>';
          end;
        end;
        Items[i]:=it2;
      end;
      //ネスト下り
      if it1.Indent>it2.Indent then begin
        case it1.ListType of
          1:begin
            it1.TagBack:='</ul>';
          end;
          2:begin
            it1.TagBack:='</ol>';
          end;
        end;
        Items[i-1]:=it1;
      end;
      inc(i);
    end;
    i:=Count-1;
    it2:=Items[i];
    case it2.ListType of
      1:begin
        it2.TagBack:='</ul>';
      end;
      2:begin
        it2.TagBack:='</ol>';
      end;
    end;
    Items[i]:=it2;
    //<li>セット
    for i:=0 to Count-1 do begin
      ItemGet(i);
      if Item.ListType=0 then Continue;
      if Item.Str='' then Continue;
      Item.Str:='<li>'+Item.Str+'</li>';
      ItemUpdate;
    end;
    //html作成
    for i:=0 to Count-1 do begin
      ItemGet(i);
      if Item.TagFront<>'' then r.Add_Line(Item.TagFront);
      if Item.Str<>'' then r.Add_Line(Item.Str);
      if Item.TagBack<>'' then r.Add_Line(Item.TagBack);
    end;
    //debug用
    //r.Add_Line('//-------------------------------------');
    //r.Add_Line(Items.Text);
    result:=r.Data;
  finally
    sl.Free;
  end;
end;





ページのトップへ戻る

inserted by FC2 system