]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/WwwText.pm
wwwtext: inline sample CSS and use highlight
[public-inbox.git] / lib / PublicInbox / WwwText.pm
1 # Copyright (C) 2016-2018 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3
4 # used for displaying help texts and other non-mail content
5 package PublicInbox::WwwText;
6 use strict;
7 use warnings;
8 use PublicInbox::Linkify;
9 use PublicInbox::WwwStream;
10 use PublicInbox::Hval qw(ascii_html);
11 our $QP_URL = 'https://xapian.org/docs/queryparser.html';
12 our $WIKI_URL = 'https://en.wikipedia.org/wiki';
13 my $hl = eval {
14         require PublicInbox::HlMod;
15         PublicInbox::HlMod->new
16 };
17
18 # /$INBOX/_/text/$KEY/ # KEY may contain slashes
19 # For now, "help" is the only supported $KEY
20 sub get_text {
21         my ($ctx, $key) = @_;
22         my $code = 200;
23
24         $key = 'help' if !defined $key; # this 302s to _/text/help/
25
26         # get the raw text the same way we get mboxrds
27         my $raw = ($key =~ s!/raw\z!!);
28         my $have_tslash = ($key =~ s!/\z!!) if !$raw;
29
30         my $txt = '';
31         if (!_default_text($ctx, $key, \$txt)) {
32                 $code = 404;
33                 $txt = "404 Not Found ($key)\n";
34         }
35         if ($raw) {
36                 return [ $code, [ 'Content-Type', 'text/plain',
37                                   'Content-Length', bytes::length($txt) ],
38                         [ $txt ] ]
39         }
40
41         # enforce trailing slash for "wget -r" compatibility
42         if (!$have_tslash && $code == 200) {
43                 my $url = $ctx->{-inbox}->base_url($ctx->{env});
44                 $url .= "_/text/$key/";
45
46                 return [ 302, [ 'Content-Type', 'text/plain',
47                                 'Location', $url ],
48                         [ "Redirecting to $url\n" ] ];
49         }
50
51         # Follow git commit message conventions,
52         # first line is the Subject/title
53         my ($title) = ($txt =~ /\A([^\n]*)/s);
54         _do_linkify($txt);
55         $ctx->{-title_html} = ascii_html($title);
56
57         my $nslash = ($key =~ tr!/!/!);
58         $ctx->{-upfx} = '../../../' . ('../' x $nslash);
59
60         PublicInbox::WwwStream->response($ctx, $code, sub {
61                 my ($nr, undef) = @_;
62                 $nr == 1 ? '<pre>'.$txt.'</pre>' : undef
63         });
64 }
65
66 sub _do_linkify {
67         my $l = PublicInbox::Linkify->new;
68         $l->linkify_1($_[0]);
69         if ($hl) {
70                 $hl->do_hl_text(\($_[0]));
71         } else {
72                 $_[0] = ascii_html($_[0]);
73         }
74         $_[0] = $l->linkify_2($_[0]);
75 }
76
77 sub _srch_prefix ($$) {
78         my ($srch, $txt) = @_;
79         my $pad = 0;
80         my $htxt = '';
81         my $help = $srch->help;
82         my $i;
83         for ($i = 0; $i < @$help; $i += 2) {
84                 my $pfx = $help->[$i];
85                 my $n = length($pfx);
86                 $pad = $n if $n > $pad;
87                 $htxt .= $pfx . "\0";
88                 $htxt .= $help->[$i + 1];
89                 $htxt .= "\f\n";
90         }
91         $pad += 2;
92         my $padding = ' ' x ($pad + 8);
93         $htxt =~ s/^/$padding/gms;
94         $htxt =~ s/^$padding(\S+)\0/"        $1".
95                                 (' ' x ($pad - length($1)))/egms;
96         $htxt =~ s/\f\n/\n/gs;
97         $$txt .= $htxt;
98         1;
99 }
100
101 sub _colors_help ($$) {
102         my ($ctx, $txt) = @_;
103         my $ibx = $ctx->{-inbox};
104         my $env = $ctx->{env};
105         my $base_url = $ibx->base_url($env);
106         $$txt .= "color customization for $base_url\n";
107         $$txt .= <<EOF;
108
109 public-inbox provides a stable set of CSS classes for users to
110 customize colors for highlighting diffs and code.
111
112 Users of browsers such as dillo, Firefox, or some browser
113 extensions may start by downloading the following sample CSS file
114 to control the colors they see:
115
116         ${base_url}userContent.css
117
118 CSS sample
119 ----------
120 ```css
121 EOF
122         $$txt .= PublicInbox::UserContent::sample($ibx, $env) . "```\n";
123 }
124
125 sub _default_text ($$$) {
126         my ($ctx, $key, $txt) = @_;
127         return _colors_help($ctx, $txt) if $key eq 'color';
128         return if $key ne 'help'; # TODO more keys?
129
130         my $ibx = $ctx->{-inbox};
131         my $base_url = $ibx->base_url($ctx->{env});
132         $$txt .= "public-inbox help for $base_url\n";
133         $$txt .= <<EOF;
134
135 overview
136 --------
137
138     public-inbox uses Message-ID identifiers in URLs.
139     One may look up messages by substituting Message-IDs
140     (without the leading '<' or trailing '>') into the URL.
141     Forward slash ('/') characters in the Message-IDs
142     need to be escaped as "%2F" (without quotes).
143
144     Thus, it is possible to retrieve any message by its
145     Message-ID by going to:
146
147         $base_url<Message-ID>/
148
149         (without the '<' or '>')
150
151     Message-IDs are described at:
152
153         $WIKI_URL/Message-ID
154
155 EOF
156
157         # n.b. we use the Xapian DB for any regeneratable,
158         # order-of-arrival-independent data.
159         my $srch = $ibx->search;
160         if ($srch) {
161                 $$txt .= <<EOF;
162 search
163 ------
164
165     This public-inbox has search functionality provided by Xapian.
166
167     It supports typical AND, OR, NOT, '+', '-' queries present
168     in other search engines.
169
170     We also support search prefixes to limit the scope of the
171     search to certain fields.
172
173     Prefixes supported in this installation include:
174
175 EOF
176                 _srch_prefix($srch, $txt);
177
178                 $$txt .= <<EOF;
179
180     Most prefixes are probabilistic, meaning they support stemming
181     and wildcards ('*').  Ranges (such as 'd:') and boolean prefixes
182     do not support stemming or wildcards.
183     The upstream Xapian query parser documentation fully explains
184     the query syntax:
185
186         $QP_URL
187
188 message threading
189 -----------------
190
191     Message threading is enabled for this public-inbox,
192     additional endpoints for message threads are available:
193
194     * $base_url<Message-ID>/T/#u
195
196       Loads the thread belonging to the given <Message-ID>
197       in flat chronological order.  The "#u" anchor
198       focuses the browser on the given <Message-ID>.
199
200     * $base_url<Message-ID>/t/#u
201
202       Loads the thread belonging to the given <Message-ID>
203       in threaded order with nesting.  For deep threads,
204       this requires a wide display or horizontal scrolling.
205
206     Both of these HTML endpoints are suitable for offline reading
207     using the thread overview at the bottom of each page.
208
209     Users of feed readers may follow a particular thread using:
210
211     * $base_url<Message-ID>/t.atom
212
213       Which loads the thread in Atom Syndication Standard
214       described at Wikipedia and RFC4287:
215
216         $WIKI_URL/Atom_(standard)
217         https://tools.ietf.org/html/rfc4287
218
219       Atom Threading Extensions (RFC4685) is supported:
220
221         https://tools.ietf.org/html/rfc4685
222
223     Finally, the gzipped mbox for a thread is available for
224     downloading and importing into your favorite mail client:
225
226     * $base_url<Message-ID>/t.mbox.gz
227
228     We use the mboxrd variant of the mbox format described
229     at:
230
231         $WIKI_URL/Mbox
232
233 contact
234 -------
235
236     This help text is maintained by public-inbox developers
237     reachable via plain-text email at: meta\@public-inbox.org
238
239 EOF
240         # TODO: support admin contact info in ~/.public-inbox/config
241         }
242         1;
243 }
244
245 1;