X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;ds=sidebyside;f=SL%2FTemplate%2FLaTeX.pm;h=352f793e12fc25d6aa81a2a399efc06eebed7a36;hb=deb4d2dbb676d7d6f69dfe7815d6e0cb09bd4a44;hp=d99afa43ccc1a37cb9aa0fcd6116af612b46d4c6;hpb=841d44c00aae1166a0721e40dc2f9ffb7b9ac5b5;p=kivitendo-erp.git diff --git a/SL/Template/LaTeX.pm b/SL/Template/LaTeX.pm index d99afa43c..352f793e1 100644 --- a/SL/Template/LaTeX.pm +++ b/SL/Template/LaTeX.pm @@ -9,11 +9,93 @@ use Cwd; use English qw(-no_match_vars); use File::Basename; use File::Temp; +use HTML::Entities (); use List::MoreUtils qw(any); use Unicode::Normalize qw(); use SL::DB::Default; +my %text_markup_replace = ( + b => 'textbf', + i => 'textit', + u => 'underline', +); + +sub _format_text { + my ($self, $content, %params) = @_; + + $content = $::locale->quote_special_chars('Template/LaTeX', $content); + + # Allow some HTML markup to be converted into the output format's + # corresponding markup code, e.g. bold or italic. + foreach my $key (keys(%text_markup_replace)) { + my $new = $text_markup_replace{$key}; + $content =~ s/\$\<\$${key}\$\>\$(.*?)\$<\$\/${key}\$>\$/\\${new}\{$1\}/gi; + } + + $content =~ s/[\x00-\x1f]//g; + + return $content; +} + +my %html_replace = ( + '

' => "\n\n", + '' => "\\end{itemize} ", + '
    ' => "\\begin{enumerate} ", + '
' => "\\end{enumerate} ", + '
  • ' => "\\item ", + '
  • ' => " ", + '' => "\\textbf{", + '' => "}", + '' => "\\textbf{", + '' => "}", + '' => "\\textit{", + '' => "}", + '' => "\\textit{", + '' => "}", + '' => "\\underline{", + '' => "}", + '' => "\\sout{", + '' => "}", + '' => "\\textsubscript{", + '' => "}", + '' => "\\textsuperscript{", + '' => "}", + '
    ' => "\\newline ", + '
    ' => "\\newline ", +); + +sub _format_html { + my ($self, $content, %params) = @_; + + $content =~ s{ \r+ }{}gx; + $content =~ s{ \n+ }{ }gx; + $content =~ s{ (?:\ |\s)+ }{ }gx; + $content =~ s{ (?:\ |\s)+$ }{}gx; + $content =~ s{ (?:
    )+$ }{}gx; + + my @parts = grep { $_ } map { + if (substr($_, 0, 1) eq '<') { + s{ +}{}g; + $html_replace{$_} || ''; + + } else { + $::locale->quote_special_chars('Template/LaTeX', HTML::Entities::decode_entities($_)); + } + } split(m{(<.*?>)}x, $content); + + $content = join '', @parts; + $content =~ s{ (?: [\n\s] | \\newline )+$ }{}gx; + + return $content; +} + +my %formatters = ( + html => \&_format_html, + text => \&_format_text, +); + sub new { my $type = shift; @@ -23,24 +105,14 @@ sub new { } sub format_string { - my ($self, $variable) = @_; - - $variable = $main::locale->quote_special_chars('Template/LaTeX', $variable); - - # Allow some HTML markup to be converted into the output format's - # corresponding markup code, e.g. bold or italic. - my %markup_replace = ('b' => 'textbf', - 'i' => 'textit', - 'u' => 'underline'); - - foreach my $key (keys(%markup_replace)) { - my $new = $markup_replace{$key}; - $variable =~ s/\$\<\$${key}\$\>\$(.*?)\$<\$\/${key}\$>\$/\\${new}\{$1\}/gi; - } + my ($self, $content, $variable) = @_; - $variable =~ s/[\x00-\x1f]//g; + my $formatter = + $formatters{ $self->{variable_content_types}->{$variable} } + // $formatters{ $self->{default_content_type} } + // $formatters{ text }; - return $variable; + return $formatter->($self, $content, variable => $variable); } sub parse_foreach { @@ -197,15 +269,15 @@ sub parse_block { $new_contents .= $self->substitute_vars(substr($contents, 0, $pos_foreach), @indices); substr($contents, 0, $pos_foreach) = ""; - if ($contents !~ m|^$self->{tag_start_qm}foreach (.+?)$self->{tag_end_qm}|) { + if ($contents !~ m|^($self->{tag_start_qm}foreach (.+?)$self->{tag_end_qm})|) { $self->{"error"} = "Malformed $self->{tag_start}foreach$self->{tag_end}."; $main::lxdebug->leave_sub(); return undef; } - my $var = $1; + my $var = $2; - substr($contents, 0, length($&)) = ""; + substr($contents, 0, length($1)) = ""; my $block; ($block, $contents) = $self->find_end($contents); @@ -322,7 +394,7 @@ sub _force_mandatory_packages { : defined($last_usepackage_line) ? $last_usepackage_line : scalar @{ $lines } - 1; - foreach my $package (qw(textcomp)) { + foreach my $package (qw(textcomp ulem)) { next if $used_packages{$package}; splice @{ $lines }, $insertion_point, 0, "\\usepackage{${package}}\n"; $insertion_point++; @@ -338,7 +410,7 @@ sub parse { $self->{"error"} = "$form->{templates}/$form->{IN}: $!"; return 0; } - binmode IN, ":utf8" if $::locale->is_utf8; + binmode IN, ":utf8"; my @lines = ; close(IN); @@ -348,13 +420,13 @@ sub parse { my $contents = join("", @lines); # detect pagebreak block and its parameters - if ($contents =~ /$self->{tag_start_qm}pagebreak\s+(\d+)\s+(\d+)\s+(\d+)\s*$self->{tag_end_qm}(.*?)$self->{tag_start_qm}end(\s*pagebreak)?$self->{tag_end_qm}/s) { - $self->{"chars_per_line"} = $1; - $self->{"lines_on_first_page"} = $2; - $self->{"lines_on_second_page"} = $3; - $self->{"pagebreak_block"} = $4; + if ($contents =~ /^(.*)($self->{tag_start_qm}pagebreak\s+(\d+)\s+(\d+)\s+(\d+)\s*$self->{tag_end_qm}(.*?)$self->{tag_start_qm}end(\s*pagebreak)?$self->{tag_end_qm})/s) { + $self->{"chars_per_line"} = $3; + $self->{"lines_on_first_page"} = $4; + $self->{"lines_on_second_page"} = $5; + $self->{"pagebreak_block"} = $6; - substr($contents, length($`), length($&)) = ""; + substr($contents, length($1), length($2)) = ""; } $self->{"forced_pagebreaks"} = []; @@ -365,6 +437,8 @@ sub parse { $contents = "[% TAGS $self->{tag_start} $self->{tag_end} %]\n" . $contents; } + $form->prepare_global_vars; + $::form->init_template->process(\$contents, $form, \$new_contents) || die $::form->template->error; } else { $new_contents = $self->parse_block($contents); @@ -374,13 +448,8 @@ sub parse { return 0; } - if ($::locale->is_utf8) { - binmode OUT, ":utf8"; - print OUT Unicode::Normalize::normalize('C', $new_contents); - - } else { - print OUT $new_contents; - } + binmode OUT, ":utf8"; + print OUT Unicode::Normalize::normalize('C', $new_contents); if ($form->{"format"} =~ /postscript/i) { return $self->convert_to_postscript(); @@ -413,8 +482,10 @@ sub convert_to_postscript { $ENV{openin_any} = "p"; for (my $run = 1; $run <= 2; $run++) { - system("${latex} --interaction=nonstopmode $form->{tmpfile} " . - "> $form->{tmpfile}.err"); + if (system("${latex} --interaction=nonstopmode $form->{tmpfile} " . + "> $form->{tmpfile}.err") == -1) { + die "system call to $latex failed: $!"; + } if ($?) { $ENV{HOME} = $old_home; $ENV{openin_any} = $old_openin_any; @@ -425,12 +496,14 @@ sub convert_to_postscript { $form->{tmpfile} =~ s/tex$/dvi/; - system("dvips $form->{tmpfile} -o -q > /dev/null"); + if (system("dvips $form->{tmpfile} -o -q > /dev/null") == -1) { + die "system call to dvips failed: $!"; + } $ENV{HOME} = $old_home; $ENV{openin_any} = $old_openin_any; if ($?) { - $self->{"error"} = "dvips : $!"; + $self->{"error"} = "dvips : $?"; $self->cleanup('dvips'); return 0; } @@ -463,8 +536,11 @@ sub convert_to_pdf { $ENV{openin_any} = "p"; for (my $run = 1; $run <= 2; $run++) { - system("${latex} --interaction=nonstopmode $form->{tmpfile} " . - "> $form->{tmpfile}.err"); + if (system("${latex} --interaction=nonstopmode $form->{tmpfile} " . + "> $form->{tmpfile}.err") == -1) { + die "system call to $latex failed: $!"; + } + if ($?) { $ENV{HOME} = $old_home; $ENV{openin_any} = $old_openin_any; @@ -527,7 +603,7 @@ sub parse_and_create_pdf { my $error; eval { - my $template = SL::Template::LaTeX->new($template_file_name, $local_form, \%::myconfig, $::lx_office_conf{paths}->{userspath}); + my $template = SL::Template::LaTeX->new(file_name => $template_file_name, form => $local_form); my $result = $template->parse($tex_fh) && $template->convert_to_pdf; die $template->{error} unless $result;