#!/usr/bin/perl -w # vim: set sw=4 ts=4 si et: # Copyright: GPL # Author: Guido Socher, guido@bearix.oche.de # use strict; use vars qw($opt_T $opt_C $opt_t $opt_k $opt_l $opt_h); use Getopt::Std; require 5.004; # my $ver ="1.5"; # my %validcat=("Forum"=>1,"Applications"=>1,"Hardware"=>1,'Webdesign'=>1, 'System Administration'=>1,'Software Development'=>1,'Graphics'=>1, 'Community'=>1,'UNIX Basics'=>1,'Kernel Corner'=>1,'Interviews'=>1, 'Games'=>1 ); # You may change this line if you want another default language: my $lang="en"; # my $lfcomment="http://linuxfocus.linuxbox.com/cgi-bin/lfcomment"; my $lftalkback="http://www.linuxfocus.org/cgi-bin/lftalkback"; # #Note: the following is automatically overloaded. Only the chset is mandatory # if one key does not exit in language then it is taken from English (en) my %intdat=( 'de'=>{'chset'=>"iso-8859-1",'doct'=>'DE','abstract'=>'Zusammenfassung','content'=>'Inhalt','wwwresp'=>'Dem LinuxFocus-Team schreiben','aboutauthor'=>'Über den Autor','auth'=>'von','transinfo'=>'Autoren und Übersetzer','lftalkback'=>'Talkback für diesen Artikel','talkbacktext'=>'Jeder Artikel hat seine eigene Seite für Kommentare und Rückmeldungen. Auf dieser Seite kann jeder eigene Kommentare abgeben und die Kommentare anderer Leser sehen:','goto_talkback'=>'Talkback Seite'}, 'en'=>{'chset'=>"iso-8859-1",'doct'=>'EN','abstract'=>'Abstract','content'=>'Content','wwwresp'=>'Webpages maintained by the LinuxFocus Editor team','aboutauthor'=>'About the author','auth'=>'by','transinfo'=>'Translation information','home'=>'Home','map'=>'Map'=>,'index'=>'Index','search'=>'Search','news'=>'News','archives'=>'Archives','links'=>'Links','aboutus'=>'About LF','topmap'=>'Topbar-en.gif','botmap'=>'Bottombar-en.gif','alttop'=>'[Top bar]','altbot'=>'[Bottom bar]','lfcomment'=>'Click here to report a fault or send a comment to Linuxfocus', 'lftalkback'=>'Talkback form for this article','talkbacktext'=>'Every article has its own talkback page. On this page you can submit a comment or look at comments from other readers:','goto_talkback'=>'talkback page'}, 'es'=>{'chset'=>"iso-8859-1",'doct'=>'ES','abstract'=>'Resumen','content'=>'Contenidos','wwwresp'=>'Contactar con el equipo de LinuFocus','aboutauthor'=>'Sobre el autor','auth'=>'por','home'=>'Hogar','map'=>'Mapa'=>,'index'=>'Indice','search'=>'Busqueda','news'=>'Noticias','archives'=>'Arca','links'=>'Enlaces','aboutus'=>'Sobre LF','topmap'=>'Topbar-es.gif','botmap'=>'Bottombar-es.gif'}, 'fr'=>{'chset'=>"iso-8859-1",'doct'=>'FR','abstract'=>'Résumé','content'=>'Sommaire','wwwresp'=>'Site Web maintenu par l´équipe d´édition LinuxFocus','aboutauthor'=>'L´auteur','auth'=>'par','home'=>'Sommaire','map'=>'Carte'=>,'index'=>'Index','search'=>'Recherche','news'=>'Nouvelles','archives'=>'Archives','links'=>'Liens','aboutus'=>'A propos','topmap'=>'Topbar-fr.gif','botmap'=>'Bottombar-fr.gif','alttop'=>'[Barre Superieure]','altbot'=>'[Barre Inferieure]'}, 'nl'=>{'chset'=>"iso-8859-1",'doct'=>'NL','abstract'=>'Kort','content'=>'Inhoud','wwwresp'=>'Site onderhouden door het LinuxFocus editors team','aboutauthor'=>'Over de auteur','auth'=>'door','home'=>'Home','map'=>'Map'=>,'index'=>'Index','search'=>'Zoek','news'=>'Nieuws','archives'=>'Archieven','links'=>'Links','aboutus'=>'Over ons','topmap'=>'Topbar-nl.gif','botmap'=>'Bottombar-nl.gif','alttop'=>'[Hoofd-balk]','altbot'=>'[Voet-balk]', 'lfcomment'=>'Klik hier om een fout te melden of commentaar te geven', 'lftalkback'=>'Talkback voor dit artikel','talkbacktext'=>'Elk artikel heeft zijn eigen talkback pagina. Daar kan je commentaar geven of commentaar van anderen lezen:','goto_talkback'=>'ga naar de talkback pagina'}, 'gb'=>{'chset'=>"gb2312",'doct'=>'GB','abstract'=>'ÕªÒª','content'=>'ÕýÎÄ','wwwresp'=>'Ö÷Ò³ÓÉLinuxFocus±à¼­×éά»¤','aboutauthor'=>'¹ØÓÚ×÷Õß','auth'=>'by','transinfo'=>'·­ÒëÐÅÏ¢','home'=>'Home','map'=>'Map'=>,'index'=>'Index','search'=>'Search','news'=>'News','archives'=>'Archives','links'=>'Links','aboutus'=>'About LF','topmap'=>'Topbar-en.gif','botmap'=>'Bottombar-en.gif','alttop'=>'[Top bar]','altbot'=>'[Bottom bar]'}, 'jp'=>{'chset'=>"ISO-2022-JP"}, 'ko'=>{'chset'=>"EUC-KR"}, 'ru'=>{'chset'=>"koi8-r"}, 'tr'=>{'chset'=>"iso-8859-9"}, 'cn'=>{'chset'=>"Big-5"}, ); # # enforce html Umlaute for latin1 my %islatin=('de'=>1,'fr'=>1,'es'=>1,'it'=>1); # global data: my $today; my $parsestate=0; my @parsedtypes; my @parseddata; # my $articlename; my $articlenumber; my $articlecategory; my $articletitle; my $articleauthorimg; my $articleauthor; my $articleauthorname; my @articletransinfo; my @articleaboutauthor; my @articleabstract; my @articleindex; my $articleimage; my $articlebody; # # my $text; # &getopts("TCkl:ht")||die "ERROR: No such option. -h for help.n"; &help if ($opt_h); $today=&today; if ($opt_k){ print "valid categories are:\n"; foreach (sort keys %validcat){ print " $_\n"; } exit(0); } if ($opt_l){ die "ERROR: invalid language specifier\n" unless($intdat{$opt_l}{'chset'}); $lang=$opt_l; # copy keys from the english section that are not defined in this one: foreach (keys %{$intdat{'en'}}){ $intdat{$opt_l}{$_} = $intdat{'en'}{$_} unless ($intdat{$opt_l}{$_}); } } &help unless ($ARGV[0]); $articlename=$ARGV[0]; $articlename=~s/meta\.//; # basename: $articlename=~s=^.*/==; if ($articlename=~/(\d+)/){ $articlenumber=$1; }else{ $articlenumber=0; } open (FF,"$ARGV[0]")||die "ERROR: can not read file $ARGV[0]\n"; $text=join "", ; $text=~s/_LF_/LinuxFocus<\/font>/g; close FF; if ($opt_l && $islatin{$opt_l}){ &htmlumlaute(\$text); } &parse(\$text); &evalarticle(); &printlf_format(); #----- # Take the global data and print an article in LF format sub printlf_format{ my $tmp; my $i=0; my $base=""; if ($opt_t){ $base=""; } print " $articlecategory : $articletitle $base \"$intdat{$lang}{home}\" \"$intdat{$lang}{'map'}\" \"$intdat{$lang}{'index'}\" \"$intdat{$lang}{search}\" \"$intdat{$lang}{news}\" \"$intdat{$lang}{archives}\" \"$intdat{$lang}{links}\" \"$intdat{$lang}{aboutus}\"
\"$intdat{$lang}{alttop}\"
\"$intdat{$lang}{altbot}\"
<$articleauthorimg>
$intdat{$lang}{auth} $articleauthor

\n"; if (@articleaboutauthor){ print "$intdat{$lang}{aboutauthor}:
\n"; print join "", @articleaboutauthor; print "\n"; } if (@articleindex){ print "

$intdat{$lang}{content}:\n

\n

"; }else{ print STDERR "Warning: could not generate an article index\n"; } print "\n
\n\n"; print "

$articletitle

\n $articleimage"; print "

$intdat{$lang}{abstract}:\n

\n"; $tmp= join "", @articleabstract; print $tmp; print "



\n"; print "\n"; print "$articlebody\n"; print " 

$intdat{$lang}{lftalkback}

$intdat{$lang}{talkbacktext}
 $intdat{$lang}{goto_talkback} 
\n" if (!$opt_T && $articlenumber > 100); print "
\n"; print "
\n"; }else{ print "
$intdat{$lang}{lfcomment}
\n"; } if (scalar(@articletransinfo)>3){ print "\n"; }else{ print "\n"; } print "
$intdat{$lang}{wwwresp}
© $articleauthorname
LinuxFocus.org 2000
"; if ($opt_C){ print "
\n"; print "$intdat{$lang}{transinfo}:\n"; while(@articletransinfo){ $tmp=shift(@articletransinfo); print "\n"; $tmp=shift(@articletransinfo); print " \n"; print " \n"; $tmp=shift(@articletransinfo); print " \n"; print "\n"; } print "
$tmp->$tmp$tmp
\n"; print "

$today, generated by lfparser version $ver

\n\n\n"; } #----- # handle the parsed text chunks. sub evalarticle{ my $i=0; my $type; my $content; my $transinfostate=0; # states in which we ignore


my %ignorePandBR=(1=>1,2=>1,3=>1,4=>1,5=>1,6=>1,7=>1,8=>1,11=>1,12=>1); for $type (@parsedtypes){ # remove empty text and   which is inserted by WYSIWYG editors $parseddata[$i]=~ s/\ \;//g if ($type eq "Text"); if ($type eq "Text" && $parseddata[$i]=~ /^[\r\n\t ]+$/){ $i++; next; } # dbg, debug: #print "-- $parsestate: $parseddata[$i] type: $type --\n"; # start of article, search for heading: if ($parsestate==0 && $type=~/HeadingLevelTag/){ if ($type eq "HeadingLevelTag1"){ $articletitle=$parseddata[$i]; $articletitle=~s/\s+/ /g; $parsestate++; }else{ die "ERROR: The first heading must be the title of the article on level 1. Note: you may not have \"_LF_\" or nested tags in the title.\n"; } $i++; next; } # ignoring of

,
,

in certain states: if ($ignorePandBR{$parsestate}){ if ($type eq "StartTag" && $parseddata[$i] =~/^P$/i){ $i++; next;} if ($type eq "StartTag" && $parseddata[$i] =~/^br$/i){ $i++; next;} if ($type eq "EndTag" && $parseddata[$i] =~/^\/P$/i){ $i++; next;} } # start of article, search for ArticleCategory: if ($parsestate==1){ if ($type eq "HeadingLevelTag4" && $parseddata[$i]=~/ArticleCategory/){ $parsestate++; }else{ die "ERROR: The second heading must be ArticleCategory on level 4\n"; } $i++; next; } #-- # looking for the category if ($parsestate==2){ if ($type eq "Text"){ $articlecategory=$parseddata[$i]; $articlecategory=~s/\s+/ /g; $articlecategory=~s/^\s+//g; $articlecategory=~s/\s+$//g; $parsestate++; }else{ die "ERROR: The heading ArticleCategory must be followed by a text plain string without tags\n"; } $i++; next; } #-- # looking for the image heading if ($parsestate==3){ if ($type eq "HeadingLevelTag4"){ $parsestate++; }else{ die "ERROR: The 3-rd heading must be AuthorImage after ArticleCategory description\n"; } $i++; next; } #-- # looking for the image if ($parsestate==4){ if ($type eq "StartTag" && $parseddata[$i]=~/img/i){ $parsestate++; $articleauthorimg=$parseddata[$i]; }else{ die "ERROR: Image of author missing after AuthorImage heading\n"; } $i++; next; } #-- # looking for the AuthorName if ($parsestate==5){ # the old format is AuthorName the new is TranslationInfo # and they are mutual exclusive if ($type eq "HeadingLevelTag4" && $parseddata[$i]=~/AuthorName/){ $parsestate=6; }elsif ($type eq "HeadingLevelTag4" && $parseddata[$i]=~/TranslationInfo/){ $parsestate=7; }else{ die "ERROR: AuthorName or TranslationInfo must be the heading after the Image\n"; } $i++; next; } #-- # looking for the name and e-mail or home-page if ($parsestate==6){ if ($type eq "AnchorTag"){ $articleauthor="<" . $parseddata[$i] . ">"; if ($parseddata[$i]=~/\" *>([\w\&\;\.\,\-\s]+)<\//){ $articleauthorname=$1; }else{ die "ERROR: please write the name of the article author such tat it can be easily written in other languages (Letters A-Z and Ü é è etc..)\n"; } $parsestate=8; }else{ die "ERROR: AuthorName must followed by an anchor tag\n"; } $i++; next; } #-- # looking for the name and e-mail or home-page # parse the TranslationInfo pre-tag: if ($parsestate==7){ if ($transinfostate == 0){ if($type eq "Text" && $parseddata[$i]=~/original in +(\w+)/i){ $transinfostate++; die "ERROR: in TranslationInfo language $1 not supported. Type lfparser -h to see the supported languages \n" unless($intdat{$1}{'chset'}); push(@articletransinfo,$1); push(@articletransinfo,"--"); $i++; next; }else{ die "ERROR1: in $parseddata[$i]: TranslationInfo must be followed by pargraph that looks like:

original in LANG Author Name

\n"; } } if ($transinfostate == 1){ if ($type eq "AnchorTag"){ $articleauthor="<" . $parseddata[$i] . ">"; $transinfostate++; if ($parseddata[$i]=~/=[\'\"]([^\"\']+)[\'\"] *>([\w\&\;\.\,\-\s]+)<\//){ $articleauthorname=$2; }else{ die "ERROR2: please write the name of the article author such tat it can be easily written in other languages (Letters A-Z and Ü é è etc..)\n"; } push(@articletransinfo,"$2"); $i++; next; }else{ die "ERROR3: TranslationInfo must be followed by pargraph that looks like:

original in LANG Author Name

\n"; } } if (($transinfostate % 2) == 0){ if($type eq "Text" && $parseddata[$i]=~/(\w+) +to +(\w+)/i){ $transinfostate++; die "ERROR4: in TranslationInfo language $1 not supported. Type lfparser -h to see the supported languages \n" unless($intdat{$1}{'chset'}); push(@articletransinfo,$1); push(@articletransinfo,$2); $i++; next; # looking for the AboutTheAuthor }elsif ($type eq "HeadingLevelTag4"){ # here we look also for the next heading: if ($parseddata[$i]=~/AboutTheAuthor/){ $parsestate=9; die "ERROR7: TranslationInfo not complete\n" unless((scalar(@articletransinfo) %3) ==0); }else{ die "ERROR8: The heading after TranslationInfo must be AboutTheAuthor\n"; } $i++; next; }else{ die "ERROR5: in $parseddata[$i]: TranslationInfo must have a pargraph that looks like:

LANG1 to LANG2Translator Name

\nAdditional   and other things are not allowed\n"; } } if (($transinfostate % 2) == 1){ if ($type eq "AnchorTag"){ $transinfostate++; if ($parseddata[$i]=~/=[\'\"]([^\"\']+)[\'\"] *>([\w\&\;\.\,\-\s]+)<\//){ push(@articletransinfo,"$2"); }else{ die "ERROR2: please write the name in TranslationInfo ($parseddata[$i]) such that it can be easily written in other languages (Letters A-Z and Ü é è etc..)\n"; } $i++; next; }else{ die "ERROR6: TranslationInfo must have a pargraph that looks like:

LANG1 to LANG2Translator Name

\n"; } } $i++; next; } #-- # looking for the AboutTheAuthor when there is no TranslationInfo if ($parsestate==8){ if ($type eq "HeadingLevelTag4" && $parseddata[$i]=~/AboutTheAuthor/){ $parsestate++; }else{ die "ERROR: The heading after AuthorName must be AboutTheAuthor\n"; } $i++; next; } #-- # reading about the author (html text without heading) if ($parsestate==9){ if ($type=~/HeadingLe/){ if ($type eq "HeadingLevelTag4" && $parseddata[$i]=~/Abstract/){ $parsestate++; }else{ die "ERROR: The heading after the \"about the author\" paragraph must be the Abstract\n"; } }else{ # reading any html: if ($type=~/Tag/){ push(@articleaboutauthor,"<" . $parseddata[$i] . ">"); }elsif ($type eq "Text"){ push(@articleaboutauthor,$parseddata[$i]); }else{ die "Programm error, unknown type $type in about author\n"; } } $i++; next; } #-- # reading the abstract (html text without heading) if ($parsestate==10){ if ($type=~/HeadingLe/){ if ($type eq "HeadingLevelTag4" && $parseddata[$i]=~/ArticleIllustration/){ $parsestate++; }else{ die "ERROR: The heading after the abstract paragraph must be ArticleIllustration\n"; } }else{ # reading any html: if ($type=~/Tag/){ push(@articleabstract,"<" . $parseddata[$i] . ">"); }elsif ($type eq "Text"){ push(@articleabstract,$parseddata[$i]); }else{ die "Programm error, unknown type $type in abstract\n"; } } $i++; next; } #-- # looking for the article illustration if ($parsestate==11){ if ($type eq "StartTag" && $parseddata[$i]=~/img/i){ $parsestate++; $articleimage="<" . $parseddata[$i] . ">"; }else{ die "ERROR: Image of article missing after ArticleIllustration heading\n"; } $i++; next; } #-- # looking for the ArticleBody is already checked in the parser: if ($parsestate==12){ if ($type eq "Body"){ $articlebody=$parseddata[$i]; $articlebody=~s| ||g; }else{ die "Program error: state 12 but tag-type $type instead of ArticleBody\n"; } $i++; next; } #-- $i++; } die "ERROR: invalid article meta-format, debug state $parsestate. Either you do not have a

at the beginning or there is still a bug in lfparser.\n" unless ($parsestate == 12); &parsebodyforindex(\$articlebody); unless ($validcat{$articlecategory}){ print STDERR "ERROR invalid article category $articlecategory\n"; print STDERR "valid categories are:\n"; foreach (keys %validcat){ print STDERR " - \"$_\"\n"; } exit 1; } } #----- # generate an index for the file. # parse the html file body and store the H2 H3 text stings in @articleindex # parse takes a ref to a text string as argument. sub parsebodyforindex($){ my $text = shift; my @body; my $h; my $i=0; while (1) { # First we try to pull off any plain text (anything before a "<" char) if ($$text =~ /\G([^<]+)/gcs) { push(@body,$1); } elsif ($$text =~ /\G<\/HTML>/igcs) { next; } elsif ($$text =~ /\G<\/body>/igcs) { next; } elsif ($$text =~ /\G<[hH]3>(.+?)<\/[hH]3>/gcs) { $h=$1; push(@body," \n

".$h ."

\n"); push(@articleindex,$h); $i++; } elsif ($$text =~ /\G<[hH]2>(.+?)<\/[hH]2>/gcs) { $h=$1; push(@body," \n

".$h ."

\n"); push(@articleindex,$h); $i++; } elsif ($$text =~ m|\G(<[^>]*>)|gcs) { push(@body,$1); } else { # the string is exhausted, or there's no > in it. last; } } foreach $h (@articleindex){ $h=~s/<.+?>//g; } $articlebody=join "",@body; } #----- # parse the html file and store the result in @parseddata, @parsedtypes. # parse takes a ref to a text string as argument. sub parse($){ my $text = shift; my $type; my $content; while (1) { # First we try to pull off any plain text (anything before a "<" char) if ($$text =~ /\G([^<]+)/gcs) { $content = $1; $type = 'Text'; } elsif ($$text =~ /\G<(!--.*?--)>/gcs) { # we ignore comments except if they are in the article body: next; #$type = 'Comment'; #$content = $1; } elsif ($$text =~ /\G<(!.*?)>/gcs) { $type = 'Markup'; $content = $1; # Then, look for an end tag } elsif ($$text =~ m|\G<(/[a-zA-Z][^<]*?)>|gcs) { $content = $1; $type = 'EndTag'; # Look for a .. tag: } elsif ($$text =~ /\G<([aA] [^>]+>([^<]+)<\/[aA])>/gcs) { $content = $1; $type = "AnchorTag"; # Look for a h[0-9] tag: } elsif ($$text =~ /\G<[hH](\d)>([^<]+)<\/[hH]\d>/gcs) { $content = $2; $type = "HeadingLevelTag$1"; if ("$1" eq "4" && index($content,"ArticleBody")> -1){ $content=$'; $type="Body"; push(@parseddata,$content); push(@parsedtypes,$type); last; } # Then, finally we look for a start tag # We know the first char is <, make sure there's a > } elsif ($$text =~ /\G<(.+?)>/gcs) { $content = $1; $type = 'StartTag'; } else { # the string is exhausted, or there's no > in it. last; } #print "dbg $content type: $type\n"; push(@parseddata,$content); push(@parsedtypes,$type); } } #-------------- sub htmlumlaute($){ my $txt_ptr=shift; $$txt_ptr=~s/¡/\¡/g; $$txt_ptr=~s/¿/\¿/g; $$txt_ptr=~s/À/\À/g; $$txt_ptr=~s/Á/\Á/g; $$txt_ptr=~s/Â/\Â/g; $$txt_ptr=~s/Ã/\Ã/g; $$txt_ptr=~s/Ä/\Ä/g; $$txt_ptr=~s/Å/\Å/g; $$txt_ptr=~s/Ç/\Ç/g; $$txt_ptr=~s/È/\È/g; $$txt_ptr=~s/É/\É/g; $$txt_ptr=~s/Ê/\Ê/g; $$txt_ptr=~s/Ë/\Ë/g; $$txt_ptr=~s/Ì/\Ì/g; $$txt_ptr=~s/Í/\Í/g; $$txt_ptr=~s/Î/\Î/g; $$txt_ptr=~s/Ï/\Ï/g; $$txt_ptr=~s/Ñ/\Ñ/g; $$txt_ptr=~s/Ò/\Ò/g; $$txt_ptr=~s/Ó/\Ó/g; $$txt_ptr=~s/Ô/\Ô/g; $$txt_ptr=~s/Õ/\Õ/g; $$txt_ptr=~s/Ö/\Ö/g; $$txt_ptr=~s/Ø/\Ø/g; $$txt_ptr=~s/Ù/\Ù/g; $$txt_ptr=~s/Ú/\Ú/g; $$txt_ptr=~s/Û/\Û/g; $$txt_ptr=~s/Ü/\Ü/g; $$txt_ptr=~s/Ý/\Ý/g; $$txt_ptr=~s/ß/\ß/g; $$txt_ptr=~s/à/\à/g; $$txt_ptr=~s/á/\á/g; $$txt_ptr=~s/â/\â/g; $$txt_ptr=~s/ã/\ã/g; $$txt_ptr=~s/ä/\ä/g; $$txt_ptr=~s/å/\å/g; $$txt_ptr=~s/æ/\æ/g; $$txt_ptr=~s/ç/\ç/g; $$txt_ptr=~s/è/\è/g; $$txt_ptr=~s/é/\é/g; $$txt_ptr=~s/ê/\ê/g; $$txt_ptr=~s/ë/\ë/g; $$txt_ptr=~s/ì/\ì/g; $$txt_ptr=~s/í/\í/g; $$txt_ptr=~s/î/\î/g; $$txt_ptr=~s/ñ/\ñ/g; $$txt_ptr=~s/ò/\ò/g; $$txt_ptr=~s/ó/\ó/g; $$txt_ptr=~s/ô/\ô/g; $$txt_ptr=~s/ö/\ö/g; $$txt_ptr=~s/ù/\ù/g; $$txt_ptr=~s/ú/\ú/g; $$txt_ptr=~s/û/\û/g; $$txt_ptr=~s/ü/\ü/g; } #-------------- sub today{ my @ltime = localtime; #return a date in yyyy-mm-dd format my $today; $today = sprintf("%04d-%02d-%02d",1900 + $ltime[5],$ltime[4] + 1,$ltime[3]); $today; } #----- # sub help{ print "lfparser -- parse a LinuxFocus article in HTML meta syntax and generate a final LinuxFocus article. The HTML meta syntax is described in http://www.linuxfocus.org/developer/Guido/lfparser.html It is a special HTML format that can easily be edited and converted to the released article format. It gives LinuxFocus the flexibilty to change the layout without editing all articles. USAGE: lfparser [-hkt][-l cn|de|en|es|gb|jp|ko|nl|ru|tr] article.meta.html > article.html OPTIONS: -h this help -C do not generate a link to lfcomment -l select a language for the output -k list all valid categories and exit -T do not include talkback -t test mode. This inserts a into the article to include the images and other stuff from ../../common/ without the need to have them locally available. This option must not be used for the final article. EXAMPLE: lfparser -l fr article.meta.html > article.html This is lfparser version: $ver\n"; exit; } __END__