[ Skip to the content ]

Institute of Formal and Applied Linguistics Wiki


[ Back to the navigation ]

media2doku.pl

#!/usr/bin/perl
# Převede zdroják Media Wiki (např. wiki StatMT CLIP UMIACS) do Doku Wiki (např. wiki ÚFAL MFF UK).
# (c) 2008 Dan Zeman <zeman@ufal.mff.cuni.cz>
# Licence: GNU GPL
 
use utf8;
use open ":utf8";
binmode(STDIN, ":utf8");
binmode(STDOUT, ":utf8");
binmode(STDERR, ":utf8");
 
# Načíst zdroják Media Wiki.
while(<>)
{
    $wiki .= $_;
}
# Převést konstrukce Media Wiki do pseudo-HTML.
$wiki =~ s/&/&amp;/sg;
$wiki =~ s/</&lt;/sg;
$wiki =~ s/>/&gt;/sg;
$wiki =~ s/\[\[(.*?)\|(.*?)\]\]/<a href='$1'>$2<\/a>/sg;
$wiki =~ s/\[(http.*?) (.*?)\]/<a href='$1'>$2<\/a>/sg;
$wiki =~ s/^====\s*(.*?)\s*====$/<h4>$1<\/h4>/mg;
$wiki =~ s/^===\s*(.*?)\s*===$/<h3>$1<\/h3>/mg;
$wiki =~ s/^==\s*(.*?)\s*==$/<h2>$1<\/h2>/mg;
$wiki =~ s/^=\s*(.*?)\s*=$/<h1>$1<\/h1>/mg;
$wiki =~ s/'''(.*?)'''/<b>$1<\/b>/sg;
$wiki =~ s/''(.*?)''/<i>$1<\/i>/sg;
$wiki =~ s/&lt;tt&gt;(.*?)&lt;\/tt&gt;/<tt>$1<\/tt>/sg;
$wiki =~ s/&lt;sub&gt;(.*?)&lt;\/sub&gt;/<sub>$1<\/sub>/sg;
$wiki =~ s/&lt;sup&gt;(.*?)&lt;\/sup&gt;/<sup>$1<\/sup>/sg;
$wiki =~ s/&lt;pre&gt;(.*?)&lt;\/pre&gt;/<pre>$1<\/pre>/sg;
$wiki =~ s/&lt;span (.*?)&gt;(.*?)&lt;\/span&gt;/<span $1>$2<\/span>/sg;
$wiki =~ s/^\*\*\*\*\s*/<uli4>/mg;
$wiki =~ s/^\*\*\*\s*/<uli3>/mg;
$wiki =~ s/^\*\*\s*/<uli2>/mg;
$wiki =~ s/^\*\s*/<uli1>/mg;
# Tabulky mají složitější syntax, takže si nevystačíme pouze s regulárními výrazy.
while($wiki =~ s/(\{\|.*?\|\})/<_table_being_read_>/s)
{
    my $tabulka = $1;
    push(@tabulky, dekodovat_tabulku($tabulka));
    $wiki =~ s/<_table_being_read_>/<table$#tabulky>/s;
}
# Převést pseudo-HTML na konstrukce Doku Wiki.
$wiki =~ s/<a href='(.*?)'>(.*?)<\/a>/[[$1|$2]]/sg;
$wiki =~ s/<h1>(.*?)<\/h1>/======$1======/mg;
$wiki =~ s/<h2>(.*?)<\/h2>/=====$1=====/mg;
$wiki =~ s/<h3>(.*?)<\/h3>/====$1====/mg;
$wiki =~ s/<h4>(.*?)<\/h4>/===$1===/mg;
$wiki =~ s/<b>(.*?)<\/b>/**$1**/sg;
$wiki =~ s/<i>(.*?)<\/i>/\/\/$1\/\//sg;
$wiki =~ s/<tt>(.*?)<\/tt>/''$1''/sg;
$wiki =~ s/<pre>(.*?)<\/pre>/<code>$1<\/code>/sg;
$wiki =~ s/(<span .*?>.*?<\/span>)/<html>$1<\/html>/sg;
$wiki =~ s/<uli1>/  * /mg;
$wiki =~ s/<uli2>/    * /mg;
$wiki =~ s/<uli3>/      * /mg;
$wiki =~ s/<uli4>/        * /mg;
# Tabulky mají složitější syntax, takže si nevystačíme pouze s regulárními výrazy.
while($wiki =~ s/<table(\d+)>/<_table_being_written_>/s)
{
    my $index = $1;
    my $tabulka = zakodovat_tabulku($tabulky[$index]);
    $wiki =~ s/<_table_being_written_>/$tabulka/s;
}
$wiki =~ s/&gt;/>/sg;
$wiki =~ s/&lt;/</sg;
$wiki =~ s/&amp;/&/sg;
# Dokuwiki neumí většinu entit HTML, proto dekódovat i ty &lt; a &gt;, které už byly v kódu MediaWiki.
$wiki =~ s/&gt;/>/sg;
$wiki =~ s/&lt;/</sg;
# Vypsat převedený zdroják na standardní výstup.
print($wiki);
 
 
 
#------------------------------------------------------------------------------
# Rozebere tabulku v syntaxi Media Wiki a uloží ji jako pole buněk.
#------------------------------------------------------------------------------
sub dekodovat_tabulku
{
    my $tabulka = shift;
    # Rozsekat kód tabulky na řádky.
    my @radky_kodu = split(/\r?\n/, $tabulka);
    # Projít řádky kódu, přečíst parametry celé tabulky a rozdělit kód podle řádků tabulky (což není totéž jako řádky kódu).
    my $atributy_tabulky;
    my @radky_tabulky;
    foreach my $radek (@radky_kodu)
    {
        if($radek =~ m/^\{\|(.*)/)
        {
            $atributy_tabulky = $1;
        }
        elsif($radek =~ m/^\|([^-\|\}].*)/)
        {
            # Umazat úvodní svislítko.
            $radek = $1;
            $radek =~ s/^\s+//;
            $radek =~ s/\s+$//;
            my @bunky = split(/\s*\|\|\s*/, $radek);
            # Projít buňky a oddělit atributy od obsahu.
            foreach my $bunka (@bunky)
            {
                my %bunka;
                if($bunka =~ m/^(.*?)\|(.*)$/)
                {
                    my $atributy = $1;
                    $bunka{obsah} = $2;
                    my @atributy = split(/\s+/, $atributy);
                    foreach my $atribut (@atributy)
                    {
                        # $atribut nemůže obsahovat mezery, protože na mezerách jsme odsekávali atributy od sebe.
                        # Nemusíme se proto starat o mezery v následujícím regulárním výrazu.
                        if($atribut =~ m/^(.+?)=(.*)$/)
                        {
                            $bunka{$1} = $2;
                        }
                        else
                        {
                            $bunka{$atribut}++;
                        }
                    }
                }
                else
                {
                    $bunka{obsah} = $bunka;
                }
                # V původním poli buněk nahradit řetězec odkazem na hash.
                $bunka = \%bunka;
            }
            push(@radky_tabulky, \@bunky);
        }
    }
    # Vytvořit hash z atributů a matice buněk a vrátit odkaz na něj.
    my %tabulka =
    (
        'atributy' => $atributy_tabulky,
        'radky' => \@radky_tabulky
    );
    return \%tabulka;
}
 
 
 
#------------------------------------------------------------------------------
# Vypíše tabulku v syntaxi Doku Wiki.
#------------------------------------------------------------------------------
sub zakodovat_tabulku
{
    my $tabulka = shift; # odkaz na hash s atributy a maticí buněk
    my $kod;
    # Dokuwiki neumí rowspany. Projít tabulku a vložit místo nich prázdné buňky.
    for(my $i = 0; $i<=$#{$tabulka->{radky}}; $i++)
    {
        for(my $j = 0; $j<=$#{$tabulka->{radky}[$i]}; $j++)
        {
            if(exists($tabulka->{radky}[$i][$j]{rowspan}))
            {
                # Na každý následující řádek v rowspanu přidat do příslušného místa prázdnou buňku.
                for(my $k = $i+1; $k<=$i+$tabulka->{radky}[$i][$j]{rowspan}-1; $k++)
                {
                    # Pokud má aktuální buňka také colspan, nezapomenout ho okopírovat i do vkládané prázdné buňky.
                    my %bunka = ('obsah' => '');
                    if(exists($tabulka->{radky}[$i][$j]{colspan}))
                    {
                        $bunka{colspan} = $tabulka->{radky}[$i][$j]{colspan};
                    }
                    splice(@{$tabulka->{radky}[$k]}, $j, 0, \%bunka);
                }
            }
        }
    }
    # Dokuwiki špatně snáší, když všechny řádky tabulky nemají stejný počet buněk.
    # Zjistit počet buněk v nejdelším řádku tabulky.
    my $max_delka_radku = 0;
    foreach my $radek (@{$tabulka->{radky}})
    {
        my $delka_radku = 0;
        foreach my $bunka (@{$radek})
        {
            if(exists($bunka->{colspan}))
            {
                $delka_radku += $bunka->{colspan};
            }
            else
            {
                $delka_radku++;
            }
        }
        $max_delka_radku = $delka_radku if($delka_radku>$max_delka_radku);
    }
    # Doplnit řádky prázdnými buňkami na maximální počet.
    foreach my $radek (@{$tabulka->{radky}})
    {
        my $delka_radku = 0;
        foreach my $bunka (@{$radek})
        {
            if(exists($bunka->{colspan}))
            {
                $delka_radku += $bunka->{colspan};
            }
            else
            {
                $delka_radku++;
            }
        }
        # Vlastní doplňování začíná tady.
        for(my $i = $delka_radku+1; $i<=$max_delka_radku; $i++)
        {
            push(@{$radek}, {'obsah' => ''});
        }
    }
    # Zakódovat tabulku v syntaxi Doku Wiki.
    foreach my $radek (@{$tabulka->{radky}})
    {
        $kod .= join('', map
        {
            my $vysledek = $_->{obsah};
            $vysledek =~ s/^\s+//s;
            $vysledek =~ s/\s+$//s;
            if($_->{align} eq "center")
            {
                $vysledek = "  $vysledek  ";
            }
            elsif($_->{align} eq "left")
            {
                $vysledek = " $vysledek  ";
            }
            elsif($_->{align} eq "right")
            {
                $vysledek = "  $vysledek ";
            }
            else
            {
                $vysledek = " $vysledek ";
            }
            $vysledek = '|'.$vysledek;
            for(my $i = 2; $i<=$_->{colspan}; $i++)
            {
                $vysledek .= '|';
            }
            $vysledek;
        }
        (@{$radek}))."|\n";
    }
    return $kod;
}

[ Back to the navigation ] [ Back to the content ]