3 use POSIX qw(strftime);
9 my $idseq = 0; # sequentual number of footnotes
12 # TODO italic paragaphs
16 # print fictionbook header
17 print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
18 print "<FictionBook xmlns=\"http://www.gribuser.ru/xml/fictionbook/2.0\"
19 xmlns:l=\"http://www.w3.org/1999/xlink\">\n";
20 my $metadata = shift @ARGV;
23 # Replace empty date with current date
24 if (/<date\s+\/>/ || /<date>\s*<\/date>/) {
25 $_ = "<date value=\"".strftime("%Y-%m-%d",localtime())."\">".
26 strftime("%d/%m/%Y",localtime())."</date>\n";
28 # Add current to date as fractional part to version
29 if (/<version>(\d*)(.\d*)?<\/version>/) {
30 my $ver = $1+time()/1E10;
31 $_=tag(sprintf("%g",$ver),"version")."\n";
41 if (/\\(begin|end){(\w+)}/) {
44 if ($environ eq 'verbatim') {
46 } elsif ($environ eq 'verse') {
48 pushsection("poem",undef);
50 add_to_section(tag($buffer,'stanza')."\n") if $buffer;
55 } elsif($environ eq 'document' && $begin) {
60 if ((/^$/ || $environ) && $buffer) {
61 #output on empty line (p or stanza) depending on poetry mode
62 add_to_section(tag(flushbuffer($buffer),$poetry?"stanza":"p")."\n");
65 next LINE if $environ;
67 if (/\\(part|chapter|section|subsection|subsubsection)\*?{(.*)}/) {
69 add_to_section(tag(flushbuffer($buffer),$poetry?"stanza":"p"));
72 pushsection($1,tag($2,"p"));
76 add_to_section("<empty-line />");
79 next LINE if /\\pagebreak\b/;
80 #replace ' and " with entities
94 s/\\sloppy([^\w])/$1/g;
99 #replace TeX ligatures ~ --- << >> \% with appropriate unicode symbols
107 s/\\verb(.)(.*)\1/<code>$2<\/code>/;
112 if ($poetic_buffer) {
113 $_ = $poetic_buffer." ".$_;
114 $poetic_buffer = undef;
120 s/\\footnote{(.*)}/push_footnote($1)/e;
122 $buffer.=tag($_,'v')."\n";
123 } elsif ($verbatim) {
124 add_to_section(tag(tag($_,"code"),"p"));
130 add_to_section(tag(flushbuffer($buffer),"p"));
139 print "<body>\n$footnotes\n</body>" if $footnotes;
140 print "</FictionBook>";
144 return if ($#sections<0) ;
145 if ($data =~ /^\s*<section>/ && $sections[$#sections]->{data} !~ /^\s*<section>/) {
146 $sections[$#sections]->{data} = tag($sections[$#sections]->{data},"section")."\n";
148 $sections[$#sections]->{data}.=$data;
152 my $tag= shift || 'section';
153 my $str = pop @sections;
156 $content = tag($str->{title},"title");
158 if ($str->{data} =~ /^\s*$/s) {
159 $content .= "<p>\n</p>";
161 $content .= $str->{data};
163 if ($#sections >=0) {
164 add_to_section(tag($content,$tag)."\n");
166 print tag($content,$tag);
171 my ($level,$title)=@_;
172 # Find section of $level in the current stack
173 my $found=scalar(@sections);
175 for (my $i=0;$i<=$#sections;$i++) {
176 if ($sections[$i]->{level} eq $level) {
181 # if found, flush everything below
182 while (scalar(@sections) > $found) {
185 push @sections,{level=>$level,title=>$title,data=>""};
189 my ($content,$name) = @_;
190 $content =~s/^\s+//s;
191 return "" unless $content;
192 return "<$name>$content</$name>";
197 s/{\\(em|it|bf)(?:\s+|{})([^{}]+)}/<emphasis>$2<\/emphasis>/g;
198 s/\\(emph|textit|textbf){([^{}]+)}/<emphasis>$2<\/emphasis>/g;
199 s/\\footnote{(.*)}/push_footnote($1)/e;
206 my $id = "note_".(++$idseq);
207 $footnotes.="<section id=\"$id\">".tag(shift,'p')."</section>\n";
208 return "<a l:href=\"#$id\" type=\"note\">$idseq</a>";