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