From a2be45a1fb3e4f1ad0a906699095985b42e05ed5 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Mon, 5 Oct 2015 12:52:40 +0200 Subject: [PATCH] OpenDocument-Template: Umwandlung von HTML-Feldern gefixt MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit OpenDocument hat gewisse Probleme mit Verschachtelung von gewissen Konstrukten, z.B. kein innerhalb von . Die HTML-Felder aber sind immer in ein

…

eingeschlossen. Bisheriger Ansatz war, davon auszugehen, dass der aktuell offene Tag im XML ein ist. Dafür wurde im HTML schlicht das erste

und das letzte

entfernt. Das funktioniert, wenn das HTML-Feld der einzige Inhalt in z.B. einer Tabellenzelle ist, z.B. eine Zelle, in der nur <%longdescription%> steht. Es geht aber in die Hose, wenn der innerste offene Tag eben nicht ist, was sehr schnell passiert, z.B. wenn man Konstrukte wie <%description%><%if longdescription%><%longdescription%><%end%> nutzt. Lösung ist, die aktuell offenen Tags in einem Stack zu verfolgen. Das HTML-Formatieren kann dann alle offenen Tags bis zum letzten schließen und am Ende wieder öffnen. Potenzieller Fix für Redmine #83. --- SL/Template/OpenDocument.pm | 65 ++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/SL/Template/OpenDocument.pm b/SL/Template/OpenDocument.pm index 5cf68ee38..704d5e7e0 100644 --- a/SL/Template/OpenDocument.pm +++ b/SL/Template/OpenDocument.pm @@ -70,30 +70,50 @@ my %html_replace = ( sub _format_html { my ($self, $content, %params) = @_; - $content =~ s{ ^

|

$ }{}gx; - $content =~ s{ \r+ }{}gx; - $content =~ s{ \n+ }{ }gx; - $content =~ s{ (?:\ |\s)+ }{ }gx; - - my $in_p = 1; - my $p_start_tag = qq||; - my $ul_start_tag = qq||; - my $ol_start_tag = qq||; - my $ul_li_start_tag = qq||; - my $ol_li_start_tag = qq||; + my $in_p = 0; + my $p_start_tag = qq||; + my $prefix = ''; + my $suffix = ''; + + my (@tags_to_open, @tags_to_close); + for (my $idx = scalar(@{ $self->{tag_stack} }) - 1; $idx >= 0; --$idx) { + my $tag = $self->{tag_stack}->[$idx]; + + next if $tag =~ m{/>$}; + last if $tag =~ m{^}{>}; + $prefix .= ' |

$ }{}gx if $in_p; + $content =~ s{ \r+ }{}gx; + $content =~ s{ \n+ }{ }gx; + $content =~ s{ (?:\ |\s)+ }{ }gx; + + my $ul_start_tag = qq||; + my $ol_start_tag = qq||; + my $ul_li_start_tag = qq||; + my $ol_li_start_tag = qq||; my @parts = map { if (substr($_, 0, 1) eq '<') { s{ +}{}g; if ($_ eq '

') { $in_p--; - '
'; + $in_p == 0 ? '
' : ''; } elsif ($_ eq '

') { - if (!$in_p) { - $in_p = 1; - $p_start_tag; - } + $in_p++; + $in_p == 1 ? $p_start_tag : ''; } elsif ($_ eq '

    ') { $self->{used_list_styles}->{itemize}->{$self->{current_text_style}} = 1; @@ -114,10 +134,9 @@ sub _format_html { } } split(m{(<.*?>)}x, $content); - my $out = join('', @parts); - $out .= $p_start_tag if !$in_p; + my $out = join('', $prefix, @parts, $suffix); - # $::lxdebug->message(0, "out $out"); + # $::lxdebug->dump(0, "prefix parts suffix", [ $prefix, join('', @parts), $suffix ]); return $out; } @@ -216,6 +235,8 @@ sub parse_block { $self->{current_text_style} = $1 if $tag =~ m|text:style-name\s*=\s*"([^"]+)"|; + push @{ $self->{tag_stack} }, $tag; + if ($tag =~ m|]*>)|; my $table_row = $1; @@ -261,6 +282,11 @@ sub parse_block { $new_contents .= $tag; } + if ($tag =~ m{^$}x) { + # $::lxdebug->message(0, "popping top tag is $tag top " . $self->{tag_stack}->[-1]); + pop @{ $self->{tag_stack} }; + } + } else { $contents =~ /^([^<]+)/; my $text = $1; @@ -358,6 +384,7 @@ sub parse { $::form->init_template->process(\$contents, $additional_params, \$new_contents) || die $::form->template->error; } else { + $self->{tag_stack} = []; $new_contents = $self->parse_block($contents); } if (!defined($new_contents)) { -- 2.20.1