ブログソフトに markdown のリストを実装した、と思う・・。まだバグがありそう。
<ul>と<ol>が混在してインデントすると混乱してしまい手ごわかった。再帰的な方法でもっと簡単に実現できる気がする。
デバッグ中の様子
該当部分のLazarus ソース 、デバッグする度にソースコードが伸びていく・・。
<ul>と<ol>が混在してインデントすると混乱してしまい手ごわかった。再帰的な方法でもっと簡単に実現できる気がする。
デバッグ中の様子
該当部分の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;