3 use POSIX qw(strftime);
10 my $idseq = 0; # sequentual number of footnotes
13 # TODO italic paragaphs
17 # print fictionbook header
18 print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
19 print "<FictionBook xmlns=\"http://www.gribuser.ru/xml/fictionbook/2.0\"
20 xmlns:l=\"http://www.w3.org/1999/xlink\">\n";
21 my $metadata = shift @ARGV;
25 # Replace empty date with current date
26 if (/<date\s+\/>/ || /<date>\s*<\/date>/) {
27 $_ = "<date value=\"".strftime("%Y-%m-%d",localtime())."\">".
28 strftime("%d/%m/%Y",localtime())."</date>\n";
30 # Add current to date as fractional part to version
31 if (/<version>(\d*)(.\d*)?<\/version>/) {
32 my $ver = $1+time()/1E10;
33 $_=tag(sprintf("%g",$ver),"version")."\n";
35 # Если существует cover.png, добавляем coverpage
36 if (/<coverpage \/>/) {
40 $_ = "<coverpage>\n<image l:href=\"#$id\" />\n</coverpage>\n";
41 $pics .= mkbinary("cover.png",$id);
52 if (/\\(begin|end){(\w+)}/) {
55 if ($environ eq 'verbatim') {
57 } elsif ($environ eq 'verse') {
59 pushsection("poem",undef);
61 add_to_section(tag($buffer,'stanza')."\n") if $buffer;
66 } elsif($environ eq 'document' && $begin) {
71 if ((/^$/ || $environ) && $buffer) {
72 #output on empty line (p or stanza) depending on poetry mode
73 add_to_section(tag(flushbuffer($buffer),$poetry?"stanza":"p")."\n");
76 next LINE if $environ;
78 if (/\\(part|chapter|section|subsection|subsubsection)\*?{(.*)}/) {
80 add_to_section(tag(flushbuffer($buffer),$poetry?"stanza":"p"));
83 pushsection($1,tag($2,"p"));
87 add_to_section("<empty-line />");
90 next LINE if /\\pagebreak\b/;
91 #replace ' and " with entities
105 s/\\sloppy([^\w])/$1/g;
110 #replace TeX ligatures ~ --- << >> \% with appropriate unicode symbols
118 s/\\verb(.)(.*)\1/<code>$2<\/code>/;
123 if ($poetic_buffer) {
124 $_ = $poetic_buffer." ".$_;
125 $poetic_buffer = undef;
131 s/\\footnote{(.*)}/push_footnote($1)/e;
133 $buffer.=tag($_,'v')."\n";
134 } elsif ($verbatim) {
135 add_to_section(tag(tag($_,"code"),"p"));
141 add_to_section(tag(flushbuffer($buffer),"p"));
150 print "<body>\n$footnotes\n</body>" if $footnotes;
152 print "</FictionBook>";
156 return if ($#sections<0) ;
157 if ($data =~ /^\s*<section>/ && $sections[$#sections]->{data} !~ /^\s*<section>/) {
158 $sections[$#sections]->{data} = tag($sections[$#sections]->{data},"section")."\n";
160 $sections[$#sections]->{data}.=$data;
164 my $tag= shift || 'section';
165 my $str = pop @sections;
168 $content = tag($str->{title},"title");
170 if ($str->{data} =~ /^\s*$/s) {
171 $content .= "<p>\n</p>";
173 $content .= $str->{data};
175 if ($#sections >=0) {
176 add_to_section(tag($content,$tag)."\n");
178 print tag($content,$tag);
183 my ($level,$title)=@_;
184 # Find section of $level in the current stack
185 my $found=scalar(@sections);
187 for (my $i=0;$i<=$#sections;$i++) {
188 if ($sections[$i]->{level} eq $level) {
193 # if found, flush everything below
194 while (scalar(@sections) > $found) {
197 push @sections,{level=>$level,title=>$title,data=>""};
201 my ($content,$name) = @_;
202 $content =~s/^\s+//s;
203 return "" unless $content;
204 return "<$name>$content</$name>";
209 s/{\\(em|it|bf)(?:\s+|{})([^{}]+)}/<emphasis>$2<\/emphasis>/g;
210 s/\\(emph|textit|textbf){([^{}]+)}/<emphasis>$2<\/emphasis>/g;
211 s/\\footnote{(.*)}/push_footnote($1)/e;
218 my $id = "note_".(++$idseq);
219 $footnotes.="<section id=\"$id\">".tag(shift,'p')."</section>\n";
220 return "<a l:href=\"#$id\" type=\"note\">$idseq</a>";
224 my ($filename,$id) = @_;
226 open $f,"<",$filename;
229 my $data = encode_base64(<$f>);
230 return "<binary id=\"$id\" content-type=\"image/png\">$data</binary>\n";