Merge branch 'test' of ../kivitendo-erp_20220811
[kivitendo-erp.git] / SL / HTML / Util.pm
1 package SL::HTML::Util;
2
3 use strict;
4 use warnings;
5
6 use HTML::Parser;
7
8 my %stripper;
9 my %entities = (
10   'lt'   => '<',
11   'gt'   => '>',
12   'amp'  => '&',
13   'nbsp' => ' ',   # should be => "\x{00A0}", but this can lead to problems with
14                    # a non-visible character in csv-exports for example
15 );
16
17 sub strip {
18   my ($class_or_value) = @_;
19
20   my $value = !ref($class_or_value) && (($class_or_value // '') eq 'SL::HTML::Util') ? $_[1] : $class_or_value;
21
22   return '' unless defined $value;
23
24   # Remove HTML comments.
25   $value =~ s{ <!-- .*? --> }{}gx;
26
27   if (!%stripper) {
28     %stripper = ( parser => HTML::Parser->new );
29
30     $stripper{parser}->handler(text => sub { $stripper{text} .= ' ' . $_[1]; });
31   }
32
33   $stripper{text} = '';
34   $stripper{parser}->parse($value);
35   $stripper{parser}->eof;
36
37   $stripper{text} =~ s{\&([^;]+);}{ $entities{$1} || "\&$1;" }eg;
38   $stripper{text} =~ s{^ +| +$}{}g;
39   $stripper{text} =~ s{ {2,}}{ }g;
40
41   return delete $stripper{text};
42 }
43
44 sub plain_text_to_html {
45   my ($class_or_text) = @_;
46
47   my $text = !ref($class_or_text) && (($class_or_text // '') eq 'SL::HTML::Util') ? $_[1] : $class_or_text;
48
49   return $text if $text =~ m{^<p>.*</p>$};
50
51   $text =~ s{\r+}{}g;
52   $text =~ s{^[[:space:]]+|[[:space:]]+$}{}g;
53
54   return '' if $text eq '';
55
56   my @paragraphs;
57
58   foreach my $paragraph (split m{\n{2,}}, $text) {
59     no warnings 'once';
60     $paragraph =  $::locale->quote_special_chars('HTML', $paragraph);
61     $paragraph =~ s{\n}{<br>}g;
62
63     push @paragraphs, $paragraph;
64   }
65
66   return '<p>' . join('</p><p>', @paragraphs) . '</p>';
67 }
68
69 1;
70 __END__
71
72 =pod
73
74 =encoding utf8
75
76 =head1 NAME
77
78 SL::HTML::Util - Utility functions dealing with HTML
79
80 =head1 SYNOPSIS
81
82   my $plain_text = SL::HTML::Util->strip('<h1>Hello World</h1>');
83
84 =head1 FUNCTIONS
85
86 =over 4
87
88 =item C<strip $html_content>
89
90 Removes all HTML elements and tags from C<$html_content> and returns
91 the remaining plain text.
92
93 =item C<plain_text_to_html $text>
94
95 Converts a plain text to HTML: paragraphs will be recognized by empty
96 lines; remaining newlines will be converted into forced line breaks;
97 the rest will be HTML escaped.
98
99 =back
100
101 =head1 BUGS
102
103 Nothing here yet.
104
105 =head1 AUTHOR
106
107 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
108
109 =cut