4 use POSIX qw(strftime);
11 my $idseq = 0; # sequentual number of footnotes
14 # TODO italic paragaphs
18 # print fictionbook header
19 print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
20 print "<FictionBook xmlns=\"http://www.gribuser.ru/xml/fictionbook/2.0\"
21 xmlns:l=\"http://www.w3.org/1999/xlink\">\n";
22 my $metadata = shift @ARGV;
26 # Replace empty date with current date
27 if (/<date\s+\/>/ || /<date>\s*<\/date>/) {
28 $_ = "<date value=\"".strftime("%Y-%m-%d",localtime())."\">".
29 strftime("%d/%m/%Y",localtime())."</date>\n";
31 # Add current to date as fractional part to version
32 if (/<version>(\d*)(.\d*)?<\/version>/) {
33 my $ver = $1+time()/1E10;
34 $_=tag(sprintf("%g",$ver),"version")."\n";
36 # Если существует cover.png, добавляем coverpage
37 if (/<coverpage \/>/) {
40 for $file ("cover.jpg","cover.png") {
44 $_ = "<coverpage>\n<image l:href=\"#$id\" />\n</coverpage>\n";
45 $pics .= mkbinary($file,$id);
58 if (/\\(begin|end){(\w+)}/) {
61 if ($environ eq 'verbatim') {
63 } elsif ($environ eq 'verse') {
65 pushsection("poem",undef);
67 add_to_section(tag($buffer,'stanza')."\n") if $buffer;
72 } elsif($environ eq 'document' && $begin) {
77 if ((/^$/ || $environ) && $buffer) {
78 #output on empty line (p or stanza) depending on poetry mode
79 add_to_section(tag(flushbuffer($buffer),$poetry?"stanza":"p")."\n");
82 next LINE if $environ;
84 if (/\\(part|chapter|section|subsection|subsubsection)\*?\{(.*)\}/) {
86 add_to_section(tag(flushbuffer($buffer),$poetry?"stanza":"p"));
89 pushsection($1,tag($2,"p"));
93 add_to_section("<empty-line />");
96 next LINE if /\\pagebreak\b/;
97 #replace ' and " with entities
109 s/\\(\w+)\\sloppy/\\$1/g;
112 s/\\sloppy([^\w])/$1/g;
117 #replace TeX ligatures ~ --- << >> \% with appropriate unicode symbols
118 $_ = fix_ligatures($_);
123 if ($poetic_buffer) {
124 $_ = $poetic_buffer." ".$_;
125 $poetic_buffer = undef;
132 $buffer.=tag(flushbuffer($_),'v')."\n";
133 } elsif ($verbatim) {
134 add_to_section(tag(tag($_,"code"),"p"));
140 add_to_section(tag(flushbuffer($buffer),"p"));
149 print "<body>\n$footnotes\n</body>" if $footnotes;
151 print "</FictionBook>";
155 return if ($#sections<0) ;
156 if ($data =~ /^\s*<section>/ && $sections[$#sections]->{data} !~ /^\s*<section>/) {
157 $sections[$#sections]->{data} = tag($sections[$#sections]->{data},"section")."\n";
159 $sections[$#sections]->{data}.=$data;
163 my $tag= shift || 'section';
164 my $str = pop @sections;
167 $content = tag($str->{title},"title");
169 if ($str->{data} =~ /^\s*$/s) {
170 $content .= "<p>\n</p>";
172 $content .= $str->{data};
174 if ($#sections >=0) {
175 add_to_section(tag($content,$tag)."\n");
177 print tag($content,$tag);
182 my ($level,$title)=@_;
183 # Find section of $level in the current stack
184 my $found=scalar(@sections);
186 for (my $i=0;$i<=$#sections;$i++) {
187 if ($sections[$i]->{level} eq $level) {
192 # if found, flush everything below
193 while (scalar(@sections) > $found) {
196 push @sections,{level=>$level,title=>fix_ligatures($title),data=>""};
208 s/\\verb(.)(.*)\1/<code>$2<\/code>/;
212 my ($content,$name) = @_;
213 $content =~s/^\s+//s;
214 return "" unless $content;
215 return "<$name>$content</$name>";
221 s/\\footnote\{(.*)\}/push_footnote($1)/e;
222 $_.="}" if (/^\s*\{.*?[^}]$/) ;
223 s/\{\\(em|it|bf)(?:\s+| \{\})([^{}]+)}/<emphasis>$2<\/emphasis>/g;
224 s/\{\\(tt)(?:\s+|\{\})([^{}]+)}/<code>$2<\/code>/g;
225 s/\\(emph|textit|textbf)\{([^{}]+)\}/<emphasis>$2<\/emphasis>/g;
232 my $id = "note_".(++$idseq);
233 $footnotes.="<section id=\"$id\">".tag(flushbuffer(shift),'p')."</section>\n";
234 return "<a l:href=\"#$id\" type=\"note\">$idseq</a>";
238 my ($filename,$id) = @_;
240 open $f,"<",$filename;
243 my $data = encode_base64(<$f>);
244 return "<binary id=\"$id\" content-type=\"image/png\">$data</binary>\n";