diff options
author | M Somerville <matthew-github@dracos.co.uk> | 2020-09-30 20:04:10 +0100 |
---|---|---|
committer | M Somerville <matthew-github@dracos.co.uk> | 2020-09-30 20:04:10 +0100 |
commit | 57f4048942a8caaf702f47373fabdfa31932659e (patch) | |
tree | f9b2272947b0c59c7c1e843186d850d52f21bee4 | |
parent | 3a511f5facc4bd066f0e7e4d00060979686bb766 (diff) | |
parent | dffc4acfe67fb05f928806601bab8ce1057e7b67 (diff) |
Merge branch 'issues/commercial/1928-html-in-response-templates'
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | docs/_includes/admin-tasks-content.md | 13 | ||||
-rw-r--r-- | perllib/FixMyStreet/App/View/Web.pm | 49 | ||||
-rw-r--r-- | perllib/FixMyStreet/Script/Alerts.pm | 1 | ||||
-rw-r--r-- | perllib/FixMyStreet/Template.pm | 86 | ||||
-rw-r--r-- | perllib/FixMyStreet/TestMech.pm | 18 | ||||
-rw-r--r-- | t/app/controller/alert_new.t | 43 | ||||
-rw-r--r-- | t/app/controller/my.t | 23 | ||||
-rw-r--r-- | t/app/controller/questionnaire.t | 9 | ||||
-rw-r--r-- | t/app/controller/report_updates.t | 87 | ||||
-rw-r--r-- | templates/email/default/_email_comment_list.html | 2 | ||||
-rw-r--r-- | templates/email/default/_email_comment_list.txt | 2 | ||||
-rw-r--r-- | templates/email/fixamingata/_email_comment_list.html | 2 | ||||
-rw-r--r-- | templates/web/base/admin/users/log.html | 2 | ||||
-rw-r--r-- | templates/web/base/my/my.html | 2 | ||||
-rw-r--r-- | templates/web/base/questionnaire/index.html | 2 | ||||
-rw-r--r-- | templates/web/base/report/update.html | 4 |
17 files changed, 320 insertions, 27 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 083c9d935..8aa628795 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,8 @@ - Add full text index to speed up admin search. - Offline process for CSV generation. - Allow inspectors to change report asset. + - Staff users can use HTML tags in updates. #3143 + - Response templates can include HTML tags. #3143 - Development improvements: - `#geolocate_link` is now easier to re-style. #3006 - Links inside `#front-main` can be customised using `$primary_link_*` Sass variables. #3007 diff --git a/docs/_includes/admin-tasks-content.md b/docs/_includes/admin-tasks-content.md index d0d5e4935..0fdc259e9 100644 --- a/docs/_includes/admin-tasks-content.md +++ b/docs/_includes/admin-tasks-content.md @@ -825,6 +825,19 @@ Click on ‘Templates’ in the admin menu. You will see a table of existing tem beside the status you wish to change. You may alter any of the fields as described in the section above, ‘Creating a template’. Additionally you can delete the template from this page. + +#### HTML content in templates + +HTML tags are permitted in response templates, which makes it possible to include +hyperlinks or rich text formatting in the updates which are added to reports. + +Be aware that response templates are emailed to users as well as being shown on +the site, so it's best to keep any HTML formatting quite light-touch due to the +quirks of email clients' rendering of HTML message. + +Refer to the section ["HTML Content in notices"](#html-content-in-notices) above for details of +what tags and attributes are allowed. + </div> <div class="admin-task" markdown="1" id="view-statistics"> diff --git a/perllib/FixMyStreet/App/View/Web.pm b/perllib/FixMyStreet/App/View/Web.pm index 1e1b50094..41444fdd4 100644 --- a/perllib/FixMyStreet/App/View/Web.pm +++ b/perllib/FixMyStreet/App/View/Web.pm @@ -25,7 +25,7 @@ __PACKAGE__->config( FILTERS => { add_links => \&add_links, escape_js => \&escape_js, - markup => [ \&markup_factory, 1 ], + staff_html_markup => [ \&staff_html_markup_factory, 1 ], }, COMPILE_EXT => '.ttc', STAT_TTL => FixMyStreet->config('STAGING_SITE') ? 1 : 86400, @@ -100,7 +100,7 @@ sub add_links { my $text = shift; $text = FixMyStreet::Template::conditional_escape($text); $text =~ s/\r//g; - $text =~ s{(https?://)([^\s]+)}{"<a href=\"$1$2\">$1" . _space_slash($2) . '</a>'}ge; + $text =~ s{(?<!["'])(https?://)([^\s]+)}{"<a href=\"$1$2\">$1" . _space_slash($2) . '</a>'}ge; return FixMyStreet::Template::SafeString->new($text); } @@ -110,21 +110,50 @@ sub _space_slash { return $t; } -=head2 markup_factory +=head2 staff_html_markup_factory -This returns a function that will allow updates to have markdown-style italics. -Pass in the user that wrote the text, so we know whether it can be privileged. +This returns a function that processes the text body of an update, applying +HTML sanitization and markdown-style italics if it was made by a staff user. + +Pass in the update extra, so we can determine if it was made by a staff user. =cut -sub markup_factory { - my ($c, $user) = @_; +sub staff_html_markup_factory { + my ($c, $extra) = @_; + + my $staff = $extra->{is_superuser} || $extra->{is_body_user}; + return sub { my $text = shift; - return $text unless $user && ($user->from_body || $user->is_superuser); - $text =~ s{\*(\S.*?\S)\*}{<i>$1</i>}; - FixMyStreet::Template::SafeString->new($text); + return _staff_html_markup($text, $staff); + } +} + +sub _staff_html_markup { + my ( $text, $staff ) = @_; + unless ($staff) { + return FixMyStreet::Template::html_paragraph(add_links($text)); + } + + $text = FixMyStreet::Template::sanitize($text); + + # Apply Markdown-style italics + $text =~ s{\*(\S.*?\S)\*}{<i>$1</i>}; + + # Mark safe so add_links doesn't escape everything. + $text = FixMyStreet::Template::SafeString->new($text); + + $text = add_links($text); + + # If the update already has block-level elements then don't wrap + # individual lines in <p> elements, as we assume the user knows what + # they're doing. + unless ($text =~ /<(p|ol|ul)>/) { + $text = FixMyStreet::Template::html_paragraph($text); } + + return $text; } =head2 escape_js diff --git a/perllib/FixMyStreet/Script/Alerts.pm b/perllib/FixMyStreet/Script/Alerts.pm index 03373a8cc..fa90ede48 100644 --- a/perllib/FixMyStreet/Script/Alerts.pm +++ b/perllib/FixMyStreet/Script/Alerts.pm @@ -41,6 +41,7 @@ sub send() { $item_table.photo as item_photo, $item_table.problem_state as item_problem_state, $item_table.cobrand as item_cobrand, + $item_table.extra as item_extra, $head_table.* from alert, $item_table, $head_table where alert.parameter::integer = $head_table.id diff --git a/perllib/FixMyStreet/Template.pm b/perllib/FixMyStreet/Template.pm index 6317f7552..35efcc1cf 100644 --- a/perllib/FixMyStreet/Template.pm +++ b/perllib/FixMyStreet/Template.pm @@ -7,10 +7,14 @@ use FixMyStreet; use mySociety::Locale; use Attribute::Handlers; use HTML::Scrubber; +use HTML::TreeBuilder; use FixMyStreet::Template::SafeString; use FixMyStreet::Template::Context; use FixMyStreet::Template::Stash; +use RABX; +use IO::String; + my %FILTERS; my %SUBS; @@ -141,6 +145,8 @@ sub html_paragraph : Filter('html_para') { sub sanitize { my $text = shift; + $text = $$text if UNIVERSAL::isa($text, 'FixMyStreet::Template::SafeString'); + my %allowed_tags = map { $_ => 1 } qw( p ul ol li br b i strong em ); my $scrubber = HTML::Scrubber->new( rules => [ @@ -155,4 +161,84 @@ sub sanitize { return $text; } + +=head2 email_sanitize_text + +Intended for use in the _email_comment_list.txt template to allow HTML +in updates from staff/superusers. Sanitizes the HTML and then converts +it all to text. + +=cut + +sub email_sanitize_text : Fn('email_sanitize_text') { + my $update = shift; + + my $text = $update->{item_text}; + my $extra = $update->{item_extra}; + $extra = $extra ? RABX::wire_rd(new IO::String($extra)) : {}; + + my $staff = $extra->{is_superuser} || $extra->{is_body_user}; + + return $text unless $staff; + + $text = FixMyStreet::Template::sanitize($text); + + my $tree = HTML::TreeBuilder->new_from_content($text); + _sanitize_elt($tree); + + return $tree->as_text; +} + +my $list_type; +my $list_num; +my $sanitize_text_subs = { + b => [ '*', '*' ], + strong => [ '*', '*' ], + i => [ '_', '_' ], + em => [ '_', '_' ], + p => [ '', "\n\n" ], + li => [ '', "\n\n" ], +}; +sub _sanitize_elt { + my $elt = shift; + foreach ($elt->content_list) { + next unless ref $_; + $list_type = $_->tag, $list_num = 1 if $_->tag eq 'ol' || $_->tag eq 'ul'; + _sanitize_elt($_); + $_->replace_with("\n") if $_->tag eq 'br'; + $_->replace_with('[image: ', $_->attr('alt'), ']') if $_->tag eq 'img'; + $_->replace_with($_->as_text, ' [', $_->attr('href'), ']') if $_->tag eq 'a'; + $_->replace_with_content if $_->tag eq 'span' || $_->tag eq 'font'; + $_->replace_with_content if $_->tag eq 'ul' || $_->tag eq 'ol'; + if ($_->tag eq 'li') { + $sanitize_text_subs->{li}[0] = $list_type eq 'ol' ? "$list_num. " : '* '; + $list_num++; + } + if (my $sub = $sanitize_text_subs->{$_->tag}) { + $_->preinsert($sub->[0]); + $_->postinsert($sub->[1]); + $_->replace_with_content; + } + } +} + +=head2 email_sanitize_html + +Intended for use in the _email_comment_list.html template to allow HTML +in updates from staff/superusers. + +=cut + +sub email_sanitize_html : Fn('email_sanitize_html') { + my $update = shift; + + my $text = $update->{item_text}; + my $extra = $update->{item_extra}; + $extra = $extra ? RABX::wire_rd(new IO::String($extra)) : {}; + + my $staff = $extra->{is_superuser} || $extra->{is_body_user}; + + return FixMyStreet::App::View::Web::_staff_html_markup($text, $staff); +} + 1; diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm index 277eca2b1..f6854fc98 100644 --- a/perllib/FixMyStreet/TestMech.pm +++ b/perllib/FixMyStreet/TestMech.pm @@ -276,6 +276,24 @@ sub get_text_body_from_email { return $body; } +sub get_html_body_from_email { + my ($mech, $email, $obj) = @_; + unless ($email) { + $email = $mech->get_email; + $mech->clear_emails_ok; + } + + my $body; + $email->walk_parts(sub { + my $part = shift; + return if $part->subparts; + return if $part->content_type !~ m{text/html}; + $body = $obj ? $part : $part->body_str; + ok $body, "Found HTML body"; + }); + return $body; +} + sub get_link_from_email { my ($mech, $email, $multiple, $mismatch) = @_; unless ($email) { diff --git a/t/app/controller/alert_new.t b/t/app/controller/alert_new.t index d968b56b1..31d8c52ed 100644 --- a/t/app/controller/alert_new.t +++ b/t/app/controller/alert_new.t @@ -866,4 +866,47 @@ subtest 'check setting include dates in new updates cobrand option' => sub { $include_date_in_alert_override->restore(); }; +subtest 'check staff updates can include sanitized HTML' => sub { + my $user1 = $mech->create_user_ok('reporter@example.com', name => 'Reporter User'); + my $user2 = $mech->create_user_ok('staff@example.com', name => 'Staff User', from_body => $body); + my $user3 = $mech->create_user_ok('updater@example.com', name => 'Another User'); + + my $dt = DateTime->now->add( minutes => -30 ); + my $r_dt = $dt->clone->add( minutes => 20 ); + + my ($report) = $mech->create_problems_for_body(1, $body->id, 'Testing', { + user => $user1, + }); + + my $update1 = $mech->create_comment_for_problem($report, $user2, 'Staff User', '<p>This is some update text with <strong>HTML</strong> and *italics*.</p> <ul><li>Even a list</li><li>Which might work</li><li>In the <a href="https://www.fixmystreet.com/">text</a> part</li></ul> <script>not allowed</script>', 't', 'confirmed', undef, { confirmed => $r_dt->clone->add( minutes => 8 ) }); + $update1->set_extra_metadata(is_body_user => $user2->from_body->id); + $update1->update; + + $mech->create_comment_for_problem($report, $user3, 'Updater User', 'Public users <i>cannot</i> use HTML. <script>not allowed</script>', 't', 'confirmed', undef, { confirmed => $r_dt->clone->add( minutes => 9 ) }); + + my $alert_user1 = FixMyStreet::DB->resultset('Alert')->create( { + user => $user1, + alert_type => 'new_updates', + parameter => $report->id, + confirmed => 1, + whensubscribed => $dt, + } ); + ok $alert_user1, "alert created"; + + FixMyStreet::DB->resultset('AlertType')->email_alerts(); + my $email = $mech->get_email; + my $plain = $mech->get_text_body_from_email($email); + like $plain, qr/This is some update text with \*HTML\* and \*italics\*\.\r\n\r\n\* Even a list\r\n\r\n\* Which might work\r\n\r\n\* In the text \[https:\/\/www.fixmystreet.com\/\] part/, 'plain text part contains no HTML tags from staff update'; + like $plain, qr/Public users <i>cannot<\/i> use HTML\./, 'plain text part contains exactly what was entered'; + + my $html = $mech->get_html_body_from_email($email); + like $html, qr{This is some update text with <strong>HTML</strong> and <i>italics</i>\.}, 'HTML part contains HTML tags'; + unlike $html, qr/<script>/, 'HTML part contains no script tags'; + + $mech->delete_user( $user1 ); + $mech->delete_user( $user2 ); + $mech->delete_user( $user3 ); +}; + + done_testing(); diff --git a/t/app/controller/my.t b/t/app/controller/my.t index 673addf0c..85902ae1a 100644 --- a/t/app/controller/my.t +++ b/t/app/controller/my.t @@ -14,17 +14,12 @@ my $other_user = FixMyStreet::DB->resultset('User')->find_or_create({ email => ' my @other = $mech->create_problems_for_body(1, 1234, 'Another Title', { user => $other_user }); my $user = $mech->log_in_ok( 'test@example.com' ); -$mech->get_ok('/my'); -is $mech->uri->path, '/my', "stayed on '/my' page"; - -$mech->content_contains('Test Title'); -$mech->content_lacks('Another Title'); - my @update; my $i = 0; +my $staff_text = '<p>this is <script>how did this happen</script> <strong>an update</strong></p><ul><li>With</li><li>A</li><li>List</li></ul>'; foreach ($user, $user, $other_user) { $update[$i] = FixMyStreet::DB->resultset('Comment')->create({ - text => 'this is an update', + text => $staff_text, user => $_, state => 'confirmed', problem => $problems[0], @@ -35,6 +30,20 @@ foreach ($user, $user, $other_user) { $i++; } +subtest 'Check loading of /my page' => sub { + $mech->get_ok('/my'); + is $mech->uri->path, '/my', "stayed on '/my' page"; + + $mech->content_contains('Test Title'); + $mech->content_lacks('Another Title'); + $mech->content_contains('<p>this is'); + $mech->content_lacks('<p>this is <strong>an update</strong></p><ul><li>With'); + + $update[0]->update({ extra => { is_superuser => 1 } }); + $mech->get_ok('/my'); + $mech->content_contains('<p>this is <strong>an update</strong></p><ul><li>With'); +}; + foreach ( { type => 'problem', id => 0, result => 404, desc => 'nothing' }, { type => 'problem', obj => $problems[0], result => 200, desc => 'own report' }, diff --git a/t/app/controller/questionnaire.t b/t/app/controller/questionnaire.t index b561b271a..592507288 100644 --- a/t/app/controller/questionnaire.t +++ b/t/app/controller/questionnaire.t @@ -351,7 +351,7 @@ my $comment = FixMyStreet::DB->resultset('Comment')->find_or_create( user_id => $user->id, name => 'A User', mark_fixed => 'false', - text => 'This is some update text', + text => 'This is some <strong>update</strong> text', state => 'confirmed', confirmed => $sent_time, anonymous => 'f', @@ -360,7 +360,12 @@ my $comment = FixMyStreet::DB->resultset('Comment')->find_or_create( subtest 'Check updates are shown correctly on questionnaire page' => sub { $mech->get_ok("/Q/" . $token->token); $mech->content_contains( 'Show all updates' ); - $mech->content_contains( 'This is some update text' ); + $mech->content_contains( 'This is some <strong>update</strong> text' ); +}; +subtest 'Check staff update is shown correctly on questionnaire page' => sub { + $comment->update({ extra => { is_superuser => 1 } }); + $mech->get_ok("/Q/" . $token->token); + $mech->content_contains( 'This is some <strong>update</strong> text' ); }; for my $test ( diff --git a/t/app/controller/report_updates.t b/t/app/controller/report_updates.t index 760a5a45b..2b60867b8 100644 --- a/t/app/controller/report_updates.t +++ b/t/app/controller/report_updates.t @@ -2218,4 +2218,91 @@ subtest 'check disabling of updates per category' => sub { $mech->content_lacks('Provide an update'); }; +subtest 'check that only staff can display HTML in updates' => sub { + $report->comments->delete; + $user->update({ from_body => undef, is_superuser => 0 }); + + my @lines = ( + "This update contains:", + "1. <strong>some staff-allowed HTML</strong>", + "2. *some Markdown-style italics*", + "3. <script>some disallowed HTML</script>", + "4. An automatic link: https://myfancylink.fixmystreet.com/", + "5. A block-level element: <p>This is its own para</p>", + "" + ); + my $comment = FixMyStreet::DB->resultset('Comment')->create( + { + user => $user, + problem_id => $report->id, + text => join("\n\n", @lines), + confirmed => DateTime->now( time_zone => 'local'), + problem_state => 'confirmed', + anonymous => 0, + mark_open => 0, + mark_fixed => 0, + state => 'confirmed', + } + ); + + # First check that comments from a public user don't receive special treatment + $mech->get_ok( "/report/" . $report->id ); + + $mech->content_contains("1. <strong>some staff-allowed HTML</strong>"); + $mech->content_lacks("<strong>some staff-allowed HTML</strong>"); + + $mech->content_contains("2. *some Markdown-style italics*"); + $mech->content_lacks("<i>some Markdown-style italics</i>"); + $mech->content_lacks("<i>some Markdown-style italics</i>"); + + $mech->content_contains("3. <script>some disallowed HTML</script>"); + $mech->content_lacks("<script>some disallowed HTML</script>"); + + $mech->content_contains('4. An automatic link: <a href="https://myfancylink.fixmystreet.com/">https://myfancylink.fixmystreet.com/</a>') or diag $mech->content; + + $mech->content_contains("5. A block-level element: <p>This is its own para</p>"); + $mech->content_lacks("5. A block-level element: <p>This is its own para</p>"); + + # Now check that comments from a member of staff user do allow HTML/italic markup + $comment->set_extra_metadata(is_body_user => $body->id); + $comment->update; + $mech->get_ok( "/report/" . $report->id ); + + $mech->content_contains("1. <strong>some staff-allowed HTML</strong>"); + $mech->content_lacks("<strong>some staff-allowed HTML</strong>"); + + $mech->content_contains("2. <i>some Markdown-style italics</i>"); + $mech->content_lacks("*some Markdown-style italics*"); + $mech->content_lacks("<i>some Markdown-style italics</i>"); + + $mech->content_lacks("some disallowed HTML"); + + $mech->content_contains('4. An automatic link: <a href="https://myfancylink.fixmystreet.com/">https://myfancylink.fixmystreet.com/</a>'); + + $mech->content_contains("5. A block-level element: <p>This is its own para</p>"); + $mech->content_lacks("<p>\n5. A block-level element: <p>This is its own para</p></p>"); + + # and the same for superusers + $comment->unset_extra_metadata('is_body_user'); + $comment->set_extra_metadata(is_superuser => 1); + $comment->update; + $mech->get_ok( "/report/" . $report->id ); + + $mech->content_contains("1. <strong>some staff-allowed HTML</strong>"); + $mech->content_lacks("<strong>some staff-allowed HTML</strong>"); + + $mech->content_contains("2. <i>some Markdown-style italics</i>"); + $mech->content_lacks("*some Markdown-style italics*"); + $mech->content_lacks("<i>some Markdown-style italics</i>"); + + $mech->content_lacks("some disallowed HTML"); + + $mech->content_contains('4. An automatic link: <a href="https://myfancylink.fixmystreet.com/">https://myfancylink.fixmystreet.com/</a>'); + + $mech->content_contains("5. A block-level element: <p>This is its own para</p>"); + $mech->content_lacks("<p>\n5. A block-level element: <p>This is its own para</p></p>"); + +}; + + done_testing(); diff --git a/templates/email/default/_email_comment_list.html b/templates/email/default/_email_comment_list.html index 346efadfb..fe6cd5c4c 100644 --- a/templates/email/default/_email_comment_list.html +++ b/templates/email/default/_email_comment_list.html @@ -5,7 +5,7 @@ <img style="[% list_item_photo_style %]" src="[% inline_image(update.get_first_image_fp) %]" alt=""> </a> [%~ END %] - [% update.item_text | html_para | replace('<p>', '<p style="' _ list_item_p_style _ '">') %] + [% email_sanitize_html(update) | html_para | replace('<p>', '<p style="' _ list_item_p_style _ '">') %] <p style="[% list_item_date_style %]"> [%~ update.item_name | html IF update.item_name AND NOT update.item_anonymous -%] [% '(' _ cobrand.prettify_dt(update.confirmed) _ ') ' IF cobrand.include_time_in_update_alerts -%] diff --git a/templates/email/default/_email_comment_list.txt b/templates/email/default/_email_comment_list.txt index dbf00640f..3e01580c3 100644 --- a/templates/email/default/_email_comment_list.txt +++ b/templates/email/default/_email_comment_list.txt @@ -1,7 +1,7 @@ [% FOR row IN data -%] [% row.item_name _ ' : ' IF row.item_name AND NOT row.item_anonymous -%] [% '(' _ cobrand.prettify_dt(row.confirmed) _ ') ' IF cobrand.include_time_in_update_alerts -%] -[% row.item_text %] +[% email_sanitize_text(row) %] ------ diff --git a/templates/email/fixamingata/_email_comment_list.html b/templates/email/fixamingata/_email_comment_list.html index 346efadfb..fe6cd5c4c 100644 --- a/templates/email/fixamingata/_email_comment_list.html +++ b/templates/email/fixamingata/_email_comment_list.html @@ -5,7 +5,7 @@ <img style="[% list_item_photo_style %]" src="[% inline_image(update.get_first_image_fp) %]" alt=""> </a> [%~ END %] - [% update.item_text | html_para | replace('<p>', '<p style="' _ list_item_p_style _ '">') %] + [% email_sanitize_html(update) | html_para | replace('<p>', '<p style="' _ list_item_p_style _ '">') %] <p style="[% list_item_date_style %]"> [%~ update.item_name | html IF update.item_name AND NOT update.item_anonymous -%] [% '(' _ cobrand.prettify_dt(update.confirmed) _ ') ' IF cobrand.include_time_in_update_alerts -%] diff --git a/templates/web/base/admin/users/log.html b/templates/web/base/admin/users/log.html index 4b426e0ba..5c3f36321 100644 --- a/templates/web/base/admin/users/log.html +++ b/templates/web/base/admin/users/log.html @@ -49,7 +49,7 @@ action_map = { [%- tprintf(loc('Problem %s created on behalf of %s'), mark_safe(report_link), item.obj.name) %], ‘[% item.obj.title | html %]’ [%~ CASE 'update' %] [% tprintf(loc("Update %s created for problem %d"), mark_safe(report_link), item.obj.problem_id) %] - [% item.obj.text | add_links | markup(item.obj.user) | html_para %] + [% item.obj.text | staff_html_markup(item.obj.extra) %] [%~ CASE 'shortlistAdded' %] [%- tprintf(loc('Problem %s added to shortlist'), mark_safe(report_link)) %] [%~ CASE 'shortlistRemoved' %] diff --git a/templates/web/base/my/my.html b/templates/web/base/my/my.html index 04c5b6941..d78461cb5 100644 --- a/templates/web/base/my/my.html +++ b/templates/web/base/my/my.html @@ -113,7 +113,7 @@ li .my-account-buttons a { <div class="item-list__update-wrap"> [% INCLUDE 'report/photo.html' object=u %] <div class="item-list__update-text"> - [% u.text | add_links | html_para %] + [% u.text | staff_html_markup(u.extra) %] <p class="meta-2"> [% tprintf( loc("Added %s"), prettify_dt( u.confirmed, 'date' ) ) %] diff --git a/templates/web/base/questionnaire/index.html b/templates/web/base/questionnaire/index.html index 00911c5b1..416200d25 100644 --- a/templates/web/base/questionnaire/index.html +++ b/templates/web/base/questionnaire/index.html @@ -55,7 +55,7 @@ <strong>[% loc('Last update') %]</strong> <a href="/report/[% problem.id %]">[% loc('Show all updates') %]</a> </p> - <p class="questionnaire-report-reminder__last-update">“[% updates.last.text | add_links %]”</p> + <p class="questionnaire-report-reminder__last-update">“[% updates.last.text | staff_html_markup(updates.last.extra) %]”</p> [% END %] </div> diff --git a/templates/web/base/report/update.html b/templates/web/base/report/update.html index ca9397bd4..3b1f092ef 100644 --- a/templates/web/base/report/update.html +++ b/templates/web/base/report/update.html @@ -35,7 +35,7 @@ [% INCLUDE 'report/photo.html' object=update %] <div class="item-list__update-text"> <div class="moderate-display"> - [% update.text | add_links | markup(update.user) | html_para %] + [% update.text | staff_html_markup(update.extra) %] </div> [% IF can_moderate %] <div class="moderate-edit"> @@ -43,7 +43,7 @@ <label><input type="checkbox" name="update_revert_text" class="revert-textarea"> [% loc('Revert to original') %]</label> [% END %] - <textarea class="form-control" name="update_text">[% update.text | add_links %]</textarea> + <textarea class="form-control" name="update_text">[% update.text %]</textarea> </div> [% END %] |