slloyd has asked for the wisdom of the Perl Monks concerning the following question:

I am writing a wiki2html conversion subroutine and need help when it comes to lists and tables. Wiki syntax for a lists and tables is as follows:

Unorderd List:

* level 1 ** level 2 *** level 3

Ordered Lists

# level 1 ## level 2 ### level 3 #3 restart numbering from 3

Tables

[col1][col2][col3] [col1][col2][col3]

Any suggestions on how to do this? Here is what I have so far.

Update: I tried several existing modules with no success but I was able to get it working on my own... Code updated to reflect my changes.

use strict; my $text=qq| -This is a h1 title ''This is italized'' and here, ''''this is bold'''' on this line ''''''this is bold italic'''''' on this line ---- *list1 **list2 ***list3 #unordered list1 ##unordered list2 ###unordered list3 [''''name''''][''color''][''''''age''''''] [bob][red][32] [fred][orange][55] |; my $html=wiki2html($text); print $html; exit; ############# sub wiki2html{ my $str=shift || return; #http://wiki.beyondunreal.com/wiki/Wiki_Markup #---- <hr> #At the beginning, - <h1>, -- <h2>, --- <h3> #Unorderd lists *, ** #Ordered lists #, ## #tables [col1][col2] #''sdfs'' <i>, ''''sdfs'''' <b>, ''''''sddfs'''''' <b><i> my @lines=split(/[\r\n]/,$str); my $linecnt=@lines; my $dot='&#' . '9679' . ';'; my $space='&' . 'nbsp' . ';'; my %Marker=( ul => 0, ol => 0, table => 0, ); for(my $x=0;$x<$linecnt;$x++){ $lines[$x]=strip($lines[$x]); my $original=$lines[$x]; my $break=1; #---- <hr> $lines[$x]=~s/\-{4,4}/\<hr size\=\"1\"\>/sig; #At the beginning, - <h1>, -- <h2>, --- <h3> if($lines[$x]=~/^(\-{1,3})(.+)/s){ my $dashes=$1; my $txt=$2; my $count = $dashes =~ tr/\-//; $lines[$x]=qq|<h$count>$txt</h$count>|; $break=0; } #Unorderd lists *, ** if($lines[$x]=~/^([\*\.\0]+)(.+)/s){ my $stars=$1; my $txt=$2; my $count = $stars =~ tr/[\*\.\0]//; #$txt .= qq|<!-- ul: $Marker{ul} ,$count -->|; if($count > $Marker{ul}){ $lines[$x]="<ul><li>" . $txt; $Marker{ul}=$count; } elsif($count == $Marker{ul}){ $lines[$x]="<li>" . $txt; } else{ $lines[$x] = "</ul>"; if(length($txt)){$lines[$x] .= "<li>" . $txt ;} $Marker{ul}=$count; } $break=0; } elsif($Marker{ul}){ for(my $u=0;$u<$Marker{ul};$u++){ $lines[$x] = "</ul>" . $lines[$x]; } $Marker{ul}=0; } #Orderd lists #, ## if($lines[$x]=~/^([\#]+)(.+)/s){ my $stars=$1; my $txt=$2; my $count = $stars =~ tr/[\#]//; #$txt .= qq|<!-- ul: $Marker{ul} ,$count -->|; if($count > $Marker{ol}){ $lines[$x]="<ol><li>" . $txt; $Marker{ol}=$count; } elsif($count == $Marker{ol}){ $lines[$x]="<li>" . $txt; } else{ $lines[$x] = "</ol>"; if(length($txt)){$lines[$x] .= "<li>" . $txt ;} $Marker{ol}=$count; } $break=0; } elsif($Marker{ol}){ for(my $u=0;$u<$Marker{ol};$u++){ $lines[$x] = "</ol>" . $lines[$x]; } $Marker{ol}=0; } if(length($lines[$x])==0){$break=0;} #''sdfs'' <i>, ''''sdfs'''' <b>, ''''''sddfs'''''' <b><i> $lines[$x]=~s/\'{6,6}(.+?)\'{6,6}/<b><i>\1<\/i><\/b>/s +ig; $lines[$x]=~s/\'{4,4}(.+?)\'{4,4}/<b>\1<\/b>/sig; $lines[$x]=~s/\'{2,2}(.+?)\'{2,2}/<i>\1<\/i>/sig; #links [[ ]] if($lines[$x]=~/\[\[(.+?)\]\]/s){ $lines[$x]=~s/\[\[(.+?)\]\]/\<a href=\"\1\"\ target="_new" +>\1<\/a>/sg; } #tables [col1][col2] my @cols=(); while($lines[$x]=~/\[(.+?)\]/sg){ push(@cols,$1); } my $colcnt=@cols; if($colcnt){ $break=0; $lines[$x]=''; if(!$Marker{table}){ $lines[$x] .= qq|<table cellspacing="0" cellpadding="2 +" border="1" style="border-collapse:collapse">\n|; $Marker{table}=1; } $lines[$x] .= "<tr>"; foreach my $col (@cols){$lines[$x] .= qq|<td>$col</td>|;} $lines[$x] .= "</tr>"; } elsif($Marker{table}){ $lines[$x] = "</table>"; $Marker{table}=0; } #$lines[$x]=qq|<!--colcnt:$colcnt, table:$Marker{table}, Origi +nal: $original -->\n| . $lines[$x]; if($break){$lines[$x] .= "<br>";} } if($Marker{ul}){ for(my $u=0;$u<$Marker{ul};$u++){ push(@lines,"</ul>"); } $Marker{ul}=0; } if($Marker{ol}){ for(my $u=0;$u<$Marker{ol};$u++){ push(@lines,"</ol>"); } $Marker{ol}=0; } if($Marker{table}){ push(@lines,"</table>"); $Marker{table}=0; } return join("\r\n",@lines); } ############### sub strip{ #usage: $str=strip($str); #info: strips off beginning and endings returns, newlines, tabs, a +nd spaces my $str=shift; if(length($str)==0){return;} $str=~s/^[\r\n\s\t]+//s; $str=~s/[\r\n\s\t]+$//s; return $str; }

-------------------------------
by me
http://www.basgetti.com
http://www.kidlins.com

2006-02-13 Retitled by Steve_p, as per Monastery guidelines
Original title: 'wiki2html'

Replies are listed 'Best First'.
Re: Converting wiki markup to html
by xdg (Monsignor) on Feb 13, 2006 at 18:40 UTC

    Have you considered using Parse::RecDescent for this? I found that a useful way of working for Pod::WikiDoc.

    And have you looked at any of the existing modules that do this sort of thing already? Maybe you can adapt or customize one of them instead of writing it from scratch. Here is a list of the ones I know about (I'm sure I'm missing some):

    In general, when I've tackled this kind of thing in the past, I found it useful to first parse the text into "chunks" of lines that are of of a particular type (e.g. a numbered list) -- and then to work within each to break down the formatting further. I.e. how do you know when a particular type starts? Once you find that, how do you know when that type ends? The unstructured nature of "wiki" markup makes that a more difficult problem than you might realize.

    Good luck.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

      Thanks for your replies. After trying several existing modules with no success, I figured it out and have posted the working code above. Thanks again. Steve

      -------------------------------
      by me
      http://www.basgetti.com
      http://www.kidlins.com

Re: Converting wiki markup to html
by trammell (Priest) on Feb 13, 2006 at 18:35 UTC