github-markup 3.0.2 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -7
- data/HISTORY.md +4 -0
- data/github-markup.gemspec +1 -1
- data/lib/github-markup.rb +1 -1
- data/lib/github/commands/pod62html +1 -6
- metadata +2 -32
- data/.gitmodules +0 -3
- data/test/markups/README.pod6 +0 -151
- data/test/markups/README.pod6.html +0 -128
- data/vendor/Pod-To-HTML/LICENSE +0 -201
- data/vendor/Pod-To-HTML/META6.json +0 -20
- data/vendor/Pod-To-HTML/README.md +0 -96
- data/vendor/Pod-To-HTML/README.pod6 +0 -42
- data/vendor/Pod-To-HTML/TODO +0 -5
- data/vendor/Pod-To-HTML/lib/Pod/To/HTML.pm +0 -691
- data/vendor/Pod-To-HTML/resources/examples/01-parse-files.p6 +0 -7
- data/vendor/Pod-To-HTML/resources/examples/README.md +0 -13
- data/vendor/Pod-To-HTML/resources/examples/main.mustache +0 -26
- data/vendor/Pod-To-HTML/resources/examples/render.p6 +0 -17
- data/vendor/Pod-To-HTML/resources/templates/main.mustache +0 -32
- data/vendor/Pod-To-HTML/t/010-basic.t +0 -29
- data/vendor/Pod-To-HTML/t/020-code.t +0 -49
- data/vendor/Pod-To-HTML/t/030-comment.t +0 -15
- data/vendor/Pod-To-HTML/t/040-lists.t +0 -82
- data/vendor/Pod-To-HTML/t/050-format-x-index.t +0 -47
- data/vendor/Pod-To-HTML/t/060-table.t +0 -108
- data/vendor/Pod-To-HTML/t/070-headings.t +0 -45
- data/vendor/Pod-To-HTML/t/075-defn.t +0 -45
- data/vendor/Pod-To-HTML/t/080-lang.t +0 -14
- data/vendor/Pod-To-HTML/t/090-css.t +0 -16
- data/vendor/Pod-To-HTML/t/100-issue-37.t +0 -16
- data/vendor/Pod-To-HTML/t/110-issue-41.t +0 -18
- data/vendor/Pod-To-HTML/t/120-templates.t +0 -42
- data/vendor/Pod-To-HTML/t/templates/main.mustache +0 -33
@@ -1,20 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"perl" : "6.*",
|
3
|
-
"name" : "Pod::To::HTML",
|
4
|
-
"version" : "0.4.0",
|
5
|
-
"author" : "Perl 6",
|
6
|
-
"description" : "Convert Perl 6 Pod to HTML",
|
7
|
-
"license" : "Artistic-2.0",
|
8
|
-
"depends" : [
|
9
|
-
"URI",
|
10
|
-
"Template::Mustache"
|
11
|
-
],
|
12
|
-
"test-depends" : ["Test::Output"],
|
13
|
-
"provides" : {
|
14
|
-
"Pod::To::HTML" : "lib/Pod/To/HTML.pm"
|
15
|
-
},
|
16
|
-
"resources": [
|
17
|
-
"templates/main.mustache"
|
18
|
-
],
|
19
|
-
"source-url" : "git://github.com/perl6/Pod-To-HTML.git"
|
20
|
-
}
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# Pod::To::HTML
|
2
|
-
|
3
|
-
[![Build Status](https://travis-ci.org/perl6/Pod-To-HTML.svg?branch=master)](https://travis-ci.org/perl6/Pod-To-HTML)
|
4
|
-
|
5
|
-
Render Perl 6 Pod as HTML
|
6
|
-
|
7
|
-
## Install
|
8
|
-
|
9
|
-
This module is in the [Perl 6 ecosystem](https://modules.perl6.org), so you install it in the usual way:
|
10
|
-
|
11
|
-
zef install Pod::To::HTML
|
12
|
-
|
13
|
-
**Note**: Perl 6 2018.06 introduces changes on how non-breaking
|
14
|
-
whitespace was handled; this is now included in the tests. If
|
15
|
-
the installation fails, please upgrade to Perl 6 >= 2018.06 or
|
16
|
-
simply disregard the test and install with `--force` if that
|
17
|
-
particular feature is of no use to you.
|
18
|
-
|
19
|
-
**Note**: Perl6 2018.11 introduced handling of Definition blocks,
|
20
|
-
`Defn`. Please upgrade if you are using that feature in the
|
21
|
-
documentation.
|
22
|
-
|
23
|
-
## SYNOPSIS
|
24
|
-
|
25
|
-
From the command line:
|
26
|
-
|
27
|
-
perl6 --doc=HTML lib/FancyModule.pm > FancyModule.html
|
28
|
-
|
29
|
-
From within Perl 6:
|
30
|
-
|
31
|
-
```perl6
|
32
|
-
# Pod Block
|
33
|
-
=pod My I<super B<awesome>> embedded C<pod> document!
|
34
|
-
|
35
|
-
say Pod::To::HTML.render($=pod[0]);
|
36
|
-
|
37
|
-
# Pod file
|
38
|
-
say Pod::To::HTML.render('your/file.pod'.IO, header =>
|
39
|
-
"your-custom-header-inside-body", footer =>
|
40
|
-
"your-custom-footer-inside-body", head-fields
|
41
|
-
=> "tags-inside-head", lang => "document
|
42
|
-
language (defaults to 'en')", default-title =
|
43
|
-
'No =title was found so we use this', css-url
|
44
|
-
=> 'https://example.com/css.css'); # specify
|
45
|
-
css-url as empty string to disable CSS
|
46
|
-
inclusion
|
47
|
-
|
48
|
-
# Pod string
|
49
|
-
|
50
|
-
my $pod = q:to/END/;
|
51
|
-
=pod
|
52
|
-
My I<super B<awesome>> embedded C<pod>
|
53
|
-
document!
|
54
|
-
END
|
55
|
-
say Pod::To::HTML.render($pod,
|
56
|
-
header =>"your-custom-header-inside-body",
|
57
|
-
footer => "your-custom-footer-inside-body",
|
58
|
-
head-fields => "tags-inside-head",
|
59
|
-
lang => "document language (defaults to 'en')",
|
60
|
-
default-title => 'No =title was found so we use this');
|
61
|
-
|
62
|
-
# If you want to use a specific template
|
63
|
-
say pod2html $=pod[0], :templates("lib/templates");
|
64
|
-
# main.mustache should be in that directory
|
65
|
-
|
66
|
-
|
67
|
-
```
|
68
|
-
## DESCRIPTION
|
69
|
-
|
70
|
-
`Pod::To::HTML` takes a Pod 6 tree and outputs correspondingly
|
71
|
-
formatted HTML. Generally this is done via the command line,
|
72
|
-
using`perl6 --doc=HTML`, which extracts the pod from the document and
|
73
|
-
feeds it to `Pod::To::HTML`. The other route is with the `render`
|
74
|
-
method (called by `--doc=HTML`), which creates a complete HTML
|
75
|
-
document from the Pod tree it is called with.
|
76
|
-
|
77
|
-
Optionally, a custom header/fooder/head-fields can be
|
78
|
-
provided. These can be used to link to custom CSS stylesheets and
|
79
|
-
JavaScript libraries.
|
80
|
-
|
81
|
-
## Examples
|
82
|
-
|
83
|
-
Check the [`examples`](resources/examples/README.md) directory (which should have been installed with your distribution, or is right here if you download from source) for a few illustrative examples.
|
84
|
-
|
85
|
-
## DEBUGGING
|
86
|
-
|
87
|
-
You can set the `P6DOC_DEBUG` environmental variable to make the
|
88
|
-
module produce some debugging information.
|
89
|
-
|
90
|
-
|
91
|
-
## LICENSE
|
92
|
-
|
93
|
-
You can use and distribute this module under the terms of the The Artistic License 2.0. See the LICENSE file included in this distribution for complete details.
|
94
|
-
|
95
|
-
The META6.json file of this distribution may be distributed and modified without restrictions or attribution.
|
96
|
-
|
@@ -1,42 +0,0 @@
|
|
1
|
-
=begin pod
|
2
|
-
=TITLE Pod::To::HTML
|
3
|
-
|
4
|
-
Render Pod6 as HTML
|
5
|
-
|
6
|
-
=begin SYNOPSIS
|
7
|
-
|
8
|
-
Use it integrated with Perl 6 documentation system
|
9
|
-
|
10
|
-
perl6 --doc=HTML lib/FancyModule.pm > FancyModule.html
|
11
|
-
|
12
|
-
Or as an external function to render your documentation
|
13
|
-
|
14
|
-
=begin code
|
15
|
-
=pod My I<super B<awesome>> embedded C<pod> document!
|
16
|
-
|
17
|
-
say Pod::To::HTML.render($=pod[0]);
|
18
|
-
=end code
|
19
|
-
|
20
|
-
=end SYNOPSIS
|
21
|
-
|
22
|
-
=begin DESCRIPTION
|
23
|
-
|
24
|
-
B<C<Pod::To::HTML>> takes a C<Pod> tree and outputs correspondingly
|
25
|
-
formatted C<HTML>. Generally this is via C<perl6 --doc=HTML>, which
|
26
|
-
extracts the pod from the document and feeds it to C<Pod::To::HTML>. The
|
27
|
-
other route is with the C<render> method (called by C<--doc=HTML>),
|
28
|
-
which creates a complete C<HTML> document from the C<Pod> tree it is
|
29
|
-
called with.
|
30
|
-
|
31
|
-
=end DESCRIPTION
|
32
|
-
|
33
|
-
|
34
|
-
=begin LICENSE
|
35
|
-
|
36
|
-
You can use and distribute this module under the terms of the The Artistic License 2.0. See the LICENSE file included in this distribution for complete details.
|
37
|
-
|
38
|
-
The META6.json file of this distribution may be distributed and modified without restrictions or attribution.
|
39
|
-
|
40
|
-
=end LICENSE
|
41
|
-
|
42
|
-
=end pod
|
data/vendor/Pod-To-HTML/TODO
DELETED
@@ -1,691 +0,0 @@
|
|
1
|
-
unit class Pod::To::HTML;
|
2
|
-
use URI::Escape;
|
3
|
-
use Template::Mustache;
|
4
|
-
|
5
|
-
#try require Term::ANSIColor <&colored>;
|
6
|
-
#if &colored.defined {
|
7
|
-
#&colored = -> $t, $c { $t };
|
8
|
-
#}
|
9
|
-
|
10
|
-
sub colored($text, $how) {
|
11
|
-
$text
|
12
|
-
}
|
13
|
-
|
14
|
-
multi method render($pod) {
|
15
|
-
pod2html($pod)
|
16
|
-
}
|
17
|
-
|
18
|
-
multi method render(Array $pod, Str :$header = '', Str :$footer = '', Str :head-fields($head) = '', :$default-title = '', :$lang = 'en') {
|
19
|
-
pod2html($pod, :$header, :$footer, :$head, :$default-title, :$lang)
|
20
|
-
}
|
21
|
-
|
22
|
-
multi method render(Pod::Block $pod, Str :$header = '', Str :$footer = '', Str :head-fields($head) = '', :$default-title = '', :$lang = 'en') {
|
23
|
-
pod2html($pod, :$header, :$footer, :$head, :$default-title, :$lang)
|
24
|
-
}
|
25
|
-
|
26
|
-
multi method render(IO::Path $file, Str :$header = '', Str :$footer = '', Str :head-fields($head) = '', :$default-title = '', :$lang = 'en') {
|
27
|
-
use MONKEY-SEE-NO-EVAL;
|
28
|
-
pod2html(EVAL($file.slurp ~ "\n\$=pod"), :$header, :$footer, :$head, :$default-title, :$lang);
|
29
|
-
}
|
30
|
-
|
31
|
-
multi method render(Str $pod-string, Str :$header = '', Str :$footer = '', Str :head-fields($head) = '', :$default-title = '', :$lang = 'en') {
|
32
|
-
use MONKEY-SEE-NO-EVAL;
|
33
|
-
pod2html(EVAL($pod-string ~ "\n\$=pod"), :$header, :$footer, :$head, :$default-title, :$lang);
|
34
|
-
}
|
35
|
-
|
36
|
-
# FIXME: this code's a horrible mess. It'd be really helpful to have a module providing a generic
|
37
|
-
# way to walk a Pod tree and invoke callbacks on each node, that would reduce the multispaghetti at
|
38
|
-
# the bottom to something much more readable.
|
39
|
-
|
40
|
-
my &url = {$_};
|
41
|
-
my $title;
|
42
|
-
my $subtitle;
|
43
|
-
my @meta;
|
44
|
-
my @indexes;
|
45
|
-
my @body;
|
46
|
-
my @footnotes;
|
47
|
-
my %crossrefs;
|
48
|
-
|
49
|
-
# see <https://docs.perl6.org/language/traps#Constants_are_Compile_Time>
|
50
|
-
my $DEBUG := %*ENV<P6DOC_DEBUG>;
|
51
|
-
|
52
|
-
sub Debug(Callable $c) { $c() if $DEBUG; }
|
53
|
-
|
54
|
-
sub escape_html(Str $str --> Str ) {
|
55
|
-
return $str unless ( $str ~~ /<[ & < > " ' { ]>/ ) or ( $str ~~ / ' ' / );
|
56
|
-
$str.trans( [ q{&}, q{<}, q{>}, q{"}, q{'}, q{ } ] =>
|
57
|
-
[ q{&}, q{<}, q{>}, q{"}, q{'}, q{ }]);
|
58
|
-
}
|
59
|
-
|
60
|
-
sub unescape_html(Str $str --> Str ) {
|
61
|
-
$str.trans( [ rx{'&'}, rx{'<'}, rx{'>'}, rx{'"'}, rx{'''} ] =>
|
62
|
-
[ q{&}, q{<}, q{>}, q{"}, q{'} ] );
|
63
|
-
}
|
64
|
-
|
65
|
-
sub escape_id ($id) {
|
66
|
-
$id.trim.subst(/\s+/, '_', :g)
|
67
|
-
.subst('"', '"', :g)
|
68
|
-
.subst(' ', '_', :g)
|
69
|
-
.subst(''', "'", :g);
|
70
|
-
}
|
71
|
-
|
72
|
-
multi visit(Nil, |a) {
|
73
|
-
Debug { note colored("visit called for Nil", "bold") }
|
74
|
-
}
|
75
|
-
|
76
|
-
multi visit($root, :&pre, :&post, :&assemble = -> *% { Nil }) {
|
77
|
-
Debug { note colored("visit called for ", "bold") ~ $root.perl }
|
78
|
-
my ($pre, $post);
|
79
|
-
$pre = pre($root) if defined ⪯
|
80
|
-
|
81
|
-
my @content = $root.?contents.map: {visit $_, :&pre, :&post, :&assemble};
|
82
|
-
$post = post($root, :@content) if defined &post;
|
83
|
-
|
84
|
-
return assemble(:$pre, :$post, :@content, :node($root));
|
85
|
-
}
|
86
|
-
|
87
|
-
class Pod::List is Pod::Block { };
|
88
|
-
class Pod::DefnList is Pod::Block { };
|
89
|
-
BEGIN { if ::('Pod::Defn') ~~ Failure { CORE::Pod::<Defn> := class {} } }
|
90
|
-
|
91
|
-
sub assemble-list-items(:@content, :$node, *% ) {
|
92
|
-
my @newcont;
|
93
|
-
my $foundone = False;
|
94
|
-
my $everwarn = False;
|
95
|
-
|
96
|
-
my $atlevel = 0;
|
97
|
-
my @pushalias;
|
98
|
-
|
99
|
-
my sub oodwarn($got, $want) {
|
100
|
-
unless $everwarn {
|
101
|
-
warn "=item$got without preceding =item$want found!";
|
102
|
-
$everwarn = True;
|
103
|
-
}
|
104
|
-
}
|
105
|
-
|
106
|
-
for @content {
|
107
|
-
when Pod::Item {
|
108
|
-
$foundone = True;
|
109
|
-
|
110
|
-
# here we deal with @newcont being empty (first list), or with the
|
111
|
-
# last element not being a list (new list)
|
112
|
-
unless +@newcont && @newcont[*-1] ~~ Pod::List {
|
113
|
-
@newcont.push(Pod::List.new());
|
114
|
-
if $_.level > 1 {
|
115
|
-
oodwarn($_.level, 1);
|
116
|
-
}
|
117
|
-
}
|
118
|
-
|
119
|
-
# only bother doing the binding business if we're at a different
|
120
|
-
# level than previous items
|
121
|
-
if $_.level != $atlevel {
|
122
|
-
# guaranteed to be bound to a Pod::List (see above 'unless')
|
123
|
-
@pushalias := @newcont[*-1].contents;
|
124
|
-
|
125
|
-
for 2..($_.level) -> $L {
|
126
|
-
unless +@pushalias && @pushalias[*-1] ~~ Pod::List {
|
127
|
-
@pushalias.push(Pod::List.new());
|
128
|
-
if +@pushalias == 1 { # we had to push a sublist to a list with no =items
|
129
|
-
oodwarn($OUTER::_.level, $L);
|
130
|
-
}
|
131
|
-
}
|
132
|
-
@pushalias := @pushalias[*-1].contents;
|
133
|
-
}
|
134
|
-
|
135
|
-
$atlevel = $_.level;
|
136
|
-
}
|
137
|
-
|
138
|
-
@pushalias.push($_);
|
139
|
-
}
|
140
|
-
# This is simpler than lists because we don't need to
|
141
|
-
# list
|
142
|
-
when Pod::Defn {
|
143
|
-
$foundone = True;
|
144
|
-
unless +@newcont && @newcont[*-1] ~~ Pod::DefnList {
|
145
|
-
@newcont.push(Pod::DefnList.new());
|
146
|
-
}
|
147
|
-
@newcont[*-1].contents.push($_);
|
148
|
-
}
|
149
|
-
|
150
|
-
default {
|
151
|
-
@newcont.push($_);
|
152
|
-
$atlevel = 0;
|
153
|
-
}
|
154
|
-
}
|
155
|
-
|
156
|
-
return $foundone ?? $node.clone(contents => @newcont) !! $node;
|
157
|
-
}
|
158
|
-
|
159
|
-
|
160
|
-
#| Converts a Pod tree to a HTML document using templates
|
161
|
-
sub pod2html(
|
162
|
-
$pod,
|
163
|
-
:&url = -> $url { $url },
|
164
|
-
:$head = '',
|
165
|
-
:$header = '',
|
166
|
-
:$footer = '',
|
167
|
-
:$default-title,
|
168
|
-
:$css-url = '//design.perl6.org/perl.css',
|
169
|
-
:$templates = Str,
|
170
|
-
:$lang = 'en'
|
171
|
-
--> Str ) is export {
|
172
|
-
|
173
|
-
my $template-file = %?RESOURCES<templates/main.mustache>;
|
174
|
-
with $templates {
|
175
|
-
if "$templates/main.mustache".IO ~~ :f {
|
176
|
-
$template-file = "$templates/main.mustache".IO
|
177
|
-
}
|
178
|
-
else {
|
179
|
-
note "$templates does not contain required templates. Using default.";
|
180
|
-
}
|
181
|
-
}
|
182
|
-
($title, $subtitle, @meta, @indexes, @body, @footnotes) = ();
|
183
|
-
#| Keep count of how many footnotes we've output.
|
184
|
-
my Int $*done-notes = 0;
|
185
|
-
&OUTER::url = &url;
|
186
|
-
@body.push: node2html($pod.map: { visit $_, :assemble(&assemble-list-items) });
|
187
|
-
my $title_html = $title // $default-title // '';
|
188
|
-
|
189
|
-
my Template::Mustache $main-tm .= new;
|
190
|
-
return $main-tm.render( $template-file.IO.slurp, :literal, (
|
191
|
-
:$lang,
|
192
|
-
:title($title_html),
|
193
|
-
:$subtitle,
|
194
|
-
:css($css-url),
|
195
|
-
:meta( do-metadata ),
|
196
|
-
:$head,
|
197
|
-
:toc( do-toc($pod) ),
|
198
|
-
:$header,
|
199
|
-
:@body,
|
200
|
-
:footnotes( do-footnotes ),
|
201
|
-
:$footer).hash
|
202
|
-
);
|
203
|
-
|
204
|
-
=comment out
|
205
|
-
my $prelude = qq:to/END/;
|
206
|
-
<!doctype html>
|
207
|
-
<html lang="$lang">
|
208
|
-
<head>
|
209
|
-
<title>{ $title_html }</title>
|
210
|
-
<meta charset="UTF-8" />
|
211
|
-
<style>
|
212
|
-
/* code gets the browser-default font
|
213
|
-
* kbd gets a slightly less common monospace font
|
214
|
-
* samp gets the hard pixelly fonts
|
215
|
-
*/
|
216
|
-
kbd \{ font-family: "Droid Sans Mono", "Luxi Mono", "Inconsolata", monospace }
|
217
|
-
samp \{ font-family: "Terminus", "Courier", "Lucida Console", monospace }
|
218
|
-
/* WHATWG HTML frowns on the use of <u> because it looks like a link,
|
219
|
-
* so we make it not look like one.
|
220
|
-
*/
|
221
|
-
u \{ text-decoration: none }
|
222
|
-
.nested \{
|
223
|
-
margin-left: 3em;
|
224
|
-
}
|
225
|
-
// footnote things:
|
226
|
-
aside, u \{ opacity: 0.7 }
|
227
|
-
a[id^="fn-"]:target \{ background: #ff0 }
|
228
|
-
</style>
|
229
|
-
{ qq|<link rel="stylesheet" href="$css-url">| if $css-url }
|
230
|
-
{ do-metadata() // () }
|
231
|
-
$head
|
232
|
-
</head>
|
233
|
-
<body class="pod">
|
234
|
-
<div id="___top"></div>
|
235
|
-
$header
|
236
|
-
END
|
237
|
-
=comment out
|
238
|
-
return join(qq{\n},
|
239
|
-
$prelude,
|
240
|
-
( $title.defined ?? "<h1 class='title'>{$title_html}</h1>"
|
241
|
-
!! () ),
|
242
|
-
( $subtitle.defined ?? "<p class='subtitle'>{$subtitle}</p>"
|
243
|
-
!! () ),
|
244
|
-
( my $ToC := do-toc($pod) // () ),
|
245
|
-
'<div class="pod-body', ($ToC ?? '' !! ' no-toc'), '">',@body,'</div>',
|
246
|
-
do-footnotes(),
|
247
|
-
$footer,
|
248
|
-
'</body>',
|
249
|
-
"</html>\n"
|
250
|
-
);
|
251
|
-
|
252
|
-
}
|
253
|
-
|
254
|
-
#| Returns accumulated metadata as a string of C«<meta>» tags
|
255
|
-
sub do-metadata( --> Str ) {
|
256
|
-
return +@meta ?? '' !! @meta.map(-> $p {
|
257
|
-
qq[<meta name="{escape_html($p.key)}" value="{node2text($p.value)}" />]
|
258
|
-
}).join("\n");
|
259
|
-
}
|
260
|
-
|
261
|
-
#| Turns accumulated headings into a nested-C«<ol>» table of contents
|
262
|
-
sub do-toc($pod --> Str ) {
|
263
|
-
my @levels is default(0) = 0;
|
264
|
-
|
265
|
-
my proto sub find-headings($node, :$inside-heading){*}
|
266
|
-
|
267
|
-
multi sub find-headings(Str $s is raw, :$inside-heading){
|
268
|
-
$inside-heading ?? $s.trim.&escape_html !! ''
|
269
|
-
}
|
270
|
-
|
271
|
-
multi sub find-headings(Pod::FormattingCode $node is raw where *.type eq 'C', :$inside-heading){
|
272
|
-
my $html = $node.contents.map(*.&find-headings(:$inside-heading));
|
273
|
-
$inside-heading ?? qq[<code class="pod-code-inline">{$html}</code>] !! ''
|
274
|
-
}
|
275
|
-
|
276
|
-
multi sub find-headings(Pod::Heading $node is raw, :$inside-heading) {
|
277
|
-
@levels.splice($node.level) if $node.level < +@levels;
|
278
|
-
@levels[$node.level-1]++;
|
279
|
-
my $level-hierarchy = @levels.join('.'); # e.g. §4.2.12
|
280
|
-
my $text = $node.contents.map(*.&find-headings(inside-heading => True));
|
281
|
-
my $link = escape_id(node2text($node.contents));
|
282
|
-
qq[<tr class="toc-level-{$node.level}"><td class="toc-number">{$level-hierarchy}</td><td class="toc-text"><a href="#$link">{$text}</a></td></tr>\n];
|
283
|
-
}
|
284
|
-
|
285
|
-
multi sub find-headings(Positional \list, :$inside-heading){
|
286
|
-
list.map(*.&find-headings(:$inside-heading))
|
287
|
-
}
|
288
|
-
|
289
|
-
multi sub find-headings(Pod::Block $node is raw, :$inside-heading){
|
290
|
-
$node.contents.map(*.&find-headings(:$inside-heading))
|
291
|
-
}
|
292
|
-
|
293
|
-
multi sub find-headings(Pod::Config $node, :$inside-heading){
|
294
|
-
''
|
295
|
-
}
|
296
|
-
|
297
|
-
multi sub find-headings(Pod::Raw $node is raw, :$inside-heading){
|
298
|
-
$node.contents.map(*.&find-headings(:$inside-heading))
|
299
|
-
}
|
300
|
-
|
301
|
-
my $html = find-headings($pod);
|
302
|
-
$html.trim ??
|
303
|
-
qq:to/EOH/
|
304
|
-
<nav class="indexgroup">
|
305
|
-
<table id="TOC">
|
306
|
-
<caption><h2 id="TOC_Title">Table of Contents</h2></caption>
|
307
|
-
{$html}
|
308
|
-
</table>
|
309
|
-
</nav>
|
310
|
-
EOH
|
311
|
-
!! ''
|
312
|
-
}
|
313
|
-
|
314
|
-
#| Flushes accumulated footnotes since last call. The idea here is that we can stick calls to this
|
315
|
-
#| before each C«</section>» tag (once we have those per-header) and have notes that are visually
|
316
|
-
#| and semantically attached to the section.
|
317
|
-
sub do-footnotes( --> Str ) {
|
318
|
-
return '' unless @footnotes;
|
319
|
-
|
320
|
-
my Int $current-note = $*done-notes + 1;
|
321
|
-
my $notes = @footnotes.kv.map(-> $k, $v {
|
322
|
-
my $num = $k + $current-note;
|
323
|
-
qq{<li><a href="#fn-ref-$num" id="fn-$num">[↑]</a> $v </li>\n}
|
324
|
-
}).join;
|
325
|
-
|
326
|
-
$*done-notes += @footnotes;
|
327
|
-
@footnotes = ();
|
328
|
-
|
329
|
-
return qq[<aside><ol start="$current-note">\n]
|
330
|
-
~ $notes
|
331
|
-
~ qq[</ol></aside>\n];
|
332
|
-
}
|
333
|
-
|
334
|
-
#| block level or below
|
335
|
-
proto sub node2html(| --> Str ) is export {*}
|
336
|
-
multi sub node2html($node) {
|
337
|
-
Debug { note colored("Generic node2html called for ", "bold") ~ $node.perl };
|
338
|
-
return node2inline($node);
|
339
|
-
}
|
340
|
-
|
341
|
-
multi sub node2html(Pod::Block::Declarator $node) {
|
342
|
-
given $node.WHEREFORE {
|
343
|
-
when Routine {
|
344
|
-
"<article>\n"
|
345
|
-
~ '<code class="pod-code-inline">'
|
346
|
-
~ node2text($node.WHEREFORE.name ~ $node.WHEREFORE.signature.perl)
|
347
|
-
~ "</code>:\n"
|
348
|
-
~ node2html($node.contents)
|
349
|
-
~ "\n</article>\n";
|
350
|
-
}
|
351
|
-
default {
|
352
|
-
Debug { note "I don't know what {$node.WHEREFORE.WHAT.perl} is. Assuming class..." };
|
353
|
-
"<h1>"~ node2html([$node.WHEREFORE.perl, q{: }, $node.contents])~ "</h1>";
|
354
|
-
}
|
355
|
-
}
|
356
|
-
}
|
357
|
-
|
358
|
-
multi sub node2html(Pod::Block::Code $node) {
|
359
|
-
Debug { note colored("Code node2html called for ", "bold") ~ $node.gist };
|
360
|
-
if %*POD2HTML-CALLBACKS and %*POD2HTML-CALLBACKS<code> -> &cb {
|
361
|
-
return cb :$node, default => sub ($node) {
|
362
|
-
return '<pre class="pod-block-code">' ~ node2inline($node.contents) ~ "</pre>\n"
|
363
|
-
}
|
364
|
-
}
|
365
|
-
else {
|
366
|
-
return '<pre class="pod-block-code">' ~ node2inline($node.contents) ~ "</pre>\n"
|
367
|
-
}
|
368
|
-
|
369
|
-
}
|
370
|
-
|
371
|
-
multi sub node2html(Pod::Block::Comment $node) {
|
372
|
-
Debug { note colored("Comment node2html called for ", "bold") ~ $node.gist };
|
373
|
-
return '';
|
374
|
-
}
|
375
|
-
|
376
|
-
multi sub node2html(Pod::Block::Named $node) {
|
377
|
-
Debug { note colored("Named Block node2html called for ", "bold") ~ $node.gist };
|
378
|
-
given $node.name {
|
379
|
-
when 'config' { return '' }
|
380
|
-
when 'nested' {
|
381
|
-
return qq{<div class="nested">\n} ~ node2html($node.contents) ~ qq{\n</div>\n};
|
382
|
-
}
|
383
|
-
when 'output' { return qq[<pre class="pod-block-named-outout">\n] ~ node2inline($node.contents) ~ "</pre>\n"; }
|
384
|
-
when 'pod' {
|
385
|
-
return qq[<span class="{$node.config<class>}">\n{node2html($node.contents)}</span>\n]
|
386
|
-
if $node.config<class>;
|
387
|
-
return node2html($node.contents);
|
388
|
-
}
|
389
|
-
when 'para' { return node2html($node.contents[0]); }
|
390
|
-
when 'Image' {
|
391
|
-
my $url;
|
392
|
-
if $node.contents == 1 {
|
393
|
-
my $n = $node.contents[0];
|
394
|
-
if $n ~~ Str {
|
395
|
-
$url = $n;
|
396
|
-
}
|
397
|
-
elsif ($n ~~ Pod::Block::Para) && $n.contents == 1 {
|
398
|
-
$url = $n.contents[0] if $n.contents[0] ~~ Str;
|
399
|
-
}
|
400
|
-
}
|
401
|
-
unless $url.defined {
|
402
|
-
die "Found an Image block, but don't know how to extract the image URL :(";
|
403
|
-
}
|
404
|
-
return qq[<img src="$url" />];
|
405
|
-
}
|
406
|
-
when 'Xhtml' | 'Html' {
|
407
|
-
unescape_html node2rawhtml $node.contents
|
408
|
-
}
|
409
|
-
default {
|
410
|
-
if $node.name eq 'TITLE' {
|
411
|
-
$title = node2text($node.contents);
|
412
|
-
return '';
|
413
|
-
}
|
414
|
-
if $node.name eq 'SUBTITLE' {
|
415
|
-
$subtitle = node2text($node.contents);
|
416
|
-
return '';
|
417
|
-
}
|
418
|
-
elsif $node.name ~~ any(<VERSION DESCRIPTION AUTHOR COPYRIGHT SUMMARY>)
|
419
|
-
and $node.contents[0] ~~ Pod::Block::Para {
|
420
|
-
@meta.push: Pair.new(
|
421
|
-
key => $node.name.lc,
|
422
|
-
value => $node.contents
|
423
|
-
);
|
424
|
-
}
|
425
|
-
|
426
|
-
return '<section>'
|
427
|
-
~ "<h1>{$node.name}</h1>\n"
|
428
|
-
~ node2html($node.contents)
|
429
|
-
~ "</section>\n";
|
430
|
-
}
|
431
|
-
}
|
432
|
-
}
|
433
|
-
|
434
|
-
sub node2rawhtml(Positional $node) {
|
435
|
-
return $node.map({ node2rawtext $_ }).join
|
436
|
-
}
|
437
|
-
|
438
|
-
multi sub node2html(Pod::Block::Para $node) {
|
439
|
-
Debug { note colored("Para node2html called for ", "bold") ~ $node.gist };
|
440
|
-
return '<p>' ~ node2inline($node.contents) ~ "</p>\n";
|
441
|
-
}
|
442
|
-
|
443
|
-
multi sub node2html(Pod::Block::Table $node) {
|
444
|
-
Debug { note colored("Table node2html called for ", "bold") ~ $node.gist };
|
445
|
-
my @r = $node.config<class>??'<table class="pod-table '~$node.config<class>~'">'!!'<table class="pod-table">';
|
446
|
-
|
447
|
-
if $node.caption -> $c {
|
448
|
-
@r.push("<caption>{node2inline($c)}</caption>");
|
449
|
-
}
|
450
|
-
|
451
|
-
if $node.headers {
|
452
|
-
@r.push(
|
453
|
-
'<thead><tr>',
|
454
|
-
$node.headers.map(-> $cell {
|
455
|
-
"<th>{node2html($cell)}</th>"
|
456
|
-
}),
|
457
|
-
'</tr></thead>'
|
458
|
-
);
|
459
|
-
}
|
460
|
-
|
461
|
-
@r.push(
|
462
|
-
'<tbody>',
|
463
|
-
$node.contents.map(-> $line {
|
464
|
-
'<tr>',
|
465
|
-
$line.list.map(-> $cell {
|
466
|
-
"<td>{node2html($cell)}</td>"
|
467
|
-
}),
|
468
|
-
'</tr>'
|
469
|
-
}),
|
470
|
-
'</tbody>',
|
471
|
-
'</table>'
|
472
|
-
);
|
473
|
-
|
474
|
-
return @r.join("\n");
|
475
|
-
}
|
476
|
-
|
477
|
-
multi sub node2html(Pod::Config $node) {
|
478
|
-
Debug { note colored("Config node2html called for ", "bold") ~ $node.perl };
|
479
|
-
return '';
|
480
|
-
}
|
481
|
-
|
482
|
-
multi sub node2html(Pod::DefnList $node ) {
|
483
|
-
return "<dl>\n" ~ node2html($node.contents) ~ "\n</dl>\n";
|
484
|
-
|
485
|
-
}
|
486
|
-
multi sub node2html(Pod::Defn $node) {
|
487
|
-
|
488
|
-
"<dt>" ~ node2html($node.term) ~ "</dt>\n" ~
|
489
|
-
"<dd>" ~ node2html($node.contents) ~ "</dd>\n";
|
490
|
-
}
|
491
|
-
|
492
|
-
# TODO: would like some way to wrap these and the following content in a <section>; this might be
|
493
|
-
# the same way we get lists working...
|
494
|
-
multi sub node2html(Pod::Heading $node) {
|
495
|
-
Debug { note colored("Heading node2html called for ", "bold") ~ $node.gist };
|
496
|
-
my $lvl = min($node.level, 6); #= HTML only has 6 levels of numbered headings
|
497
|
-
my %escaped = (
|
498
|
-
id => escape_id(node2rawtext($node.contents)),
|
499
|
-
html => node2inline($node.contents),
|
500
|
-
);
|
501
|
-
|
502
|
-
%escaped<uri> = uri_escape %escaped<id>;
|
503
|
-
|
504
|
-
@indexes.push: Pair.new(key => $lvl, value => %escaped);
|
505
|
-
|
506
|
-
my $content;
|
507
|
-
if ( %escaped<html> ~~ m{href .+ \<\/a\>} ) {
|
508
|
-
$content = %escaped<html>;
|
509
|
-
} else {
|
510
|
-
$content = qq[<a class="u" href="#___top" title="go to top of document">]
|
511
|
-
~ %escaped<html>
|
512
|
-
~ qq[</a>];
|
513
|
-
}
|
514
|
-
|
515
|
-
return sprintf('<h%d id="%s">', $lvl, %escaped<id>)
|
516
|
-
~ $content ~ qq[</h{$lvl}>\n];
|
517
|
-
}
|
518
|
-
|
519
|
-
# FIXME
|
520
|
-
multi sub node2html(Pod::List $node) {
|
521
|
-
return '<ul>' ~ node2html($node.contents) ~ "</ul>\n";
|
522
|
-
}
|
523
|
-
multi sub node2html(Pod::Item $node) {
|
524
|
-
Debug { note colored("List Item node2html called for ", "bold") ~ $node.gist };
|
525
|
-
return '<li>' ~ node2html($node.contents) ~ "</li>\n";
|
526
|
-
}
|
527
|
-
|
528
|
-
multi sub node2html(Positional $node) {
|
529
|
-
return $node.map({ node2html($_) }).join
|
530
|
-
}
|
531
|
-
|
532
|
-
multi sub node2html(Str $node) {
|
533
|
-
return escape_html($node);
|
534
|
-
}
|
535
|
-
|
536
|
-
|
537
|
-
#| inline level or below
|
538
|
-
multi sub node2inline($node --> Str ) {
|
539
|
-
Debug { note colored("missing a node2inline multi for ", "bold") ~ $node.gist };
|
540
|
-
return node2text($node);
|
541
|
-
}
|
542
|
-
|
543
|
-
multi sub node2inline(Pod::Block::Para $node --> Str ) {
|
544
|
-
return node2inline($node.contents);
|
545
|
-
}
|
546
|
-
|
547
|
-
multi sub node2inline(Pod::FormattingCode $node --> Str ) {
|
548
|
-
my %basic-html = (
|
549
|
-
B => 'strong', #= Basis
|
550
|
-
C => 'code', #= Code
|
551
|
-
I => 'em', #= Important
|
552
|
-
K => 'kbd', #= Keyboard
|
553
|
-
R => 'var', #= Replaceable
|
554
|
-
T => 'samp', #= Terminal
|
555
|
-
U => 'u', #= Unusual (css: text-decoration-line: underline)
|
556
|
-
);
|
557
|
-
|
558
|
-
given $node.type {
|
559
|
-
when any(%basic-html.keys) {
|
560
|
-
return q{<} ~ %basic-html{$_} ~ q{>}
|
561
|
-
~ node2inline($node.contents)
|
562
|
-
~ q{</} ~ %basic-html{$_} ~ q{>};
|
563
|
-
}
|
564
|
-
|
565
|
-
# Escape
|
566
|
-
when 'E' {
|
567
|
-
return $node.meta.map({
|
568
|
-
when Int { "&#$_;" }
|
569
|
-
when Str { "&$_;" }
|
570
|
-
}).join;
|
571
|
-
}
|
572
|
-
|
573
|
-
# Note
|
574
|
-
when 'N' {
|
575
|
-
@footnotes.push(node2inline($node.contents));
|
576
|
-
|
577
|
-
my $id = +@footnotes;
|
578
|
-
return qq{<a href="#fn-$id" id="fn-ref-$id">[$id]</a>};
|
579
|
-
}
|
580
|
-
|
581
|
-
# Links
|
582
|
-
when 'L' {
|
583
|
-
my $text = node2inline($node.contents);
|
584
|
-
my $url = $node.meta[0] || node2text($node.contents);
|
585
|
-
if $text ~~ /^'#'/ {
|
586
|
-
# if we have an internal-only link, strip the # from the text.
|
587
|
-
$text = $/.postmatch
|
588
|
-
}
|
589
|
-
$url = url(unescape_html($url));
|
590
|
-
if $url ~~ /^'#'/ {
|
591
|
-
$url = '#' ~ uri_escape( escape_id($/.postmatch) )
|
592
|
-
}
|
593
|
-
return qq[<a href="$url">{$text}</a>]
|
594
|
-
}
|
595
|
-
|
596
|
-
# zero-width comment
|
597
|
-
when 'Z' {
|
598
|
-
return '';
|
599
|
-
}
|
600
|
-
|
601
|
-
when 'D' {
|
602
|
-
# TODO memorise these definitions (in $node.meta) and display them properly
|
603
|
-
my $text = node2inline($node.contents);
|
604
|
-
return qq[<defn>{$text}</defn>]
|
605
|
-
}
|
606
|
-
|
607
|
-
when 'X' {
|
608
|
-
multi sub recurse-until-str(Str:D $s){ $s }
|
609
|
-
multi sub recurse-until-str(Pod::Block $n){ $n.contents>>.&recurse-until-str().join }
|
610
|
-
|
611
|
-
my $index-text = recurse-until-str($node).join;
|
612
|
-
my @indices = $node.meta;
|
613
|
-
my $index-name-attr = qq[index-entry{@indices ?? '-' !! ''}{@indices.join('-')}{$index-text ?? '-' !! ''}$index-text].subst('_', '__', :g).subst(' ', '_', :g).subst('%', '%25', :g).subst('#', '%23', :g);
|
614
|
-
|
615
|
-
my $text = node2inline($node.contents);
|
616
|
-
%crossrefs{$_} = $text for @indices;
|
617
|
-
|
618
|
-
return qq[<a name="$index-name-attr"><span class="index-entry">$text\</span></a>] if $text;
|
619
|
-
return qq[<a name="$index-name-attr"></a>];
|
620
|
-
}
|
621
|
-
|
622
|
-
# Stuff I haven't figured out yet
|
623
|
-
default {
|
624
|
-
Debug { note colored("missing handling for a formatting code of type ", "red") ~ $node.type }
|
625
|
-
return qq{<kbd class="pod2html-todo">$node.type()<}
|
626
|
-
~ node2inline($node.contents)
|
627
|
-
~ q{></kbd>};
|
628
|
-
}
|
629
|
-
}
|
630
|
-
}
|
631
|
-
|
632
|
-
multi sub node2inline(Positional $node --> Str ) {
|
633
|
-
return $node.map({ node2inline($_) }).join;
|
634
|
-
}
|
635
|
-
|
636
|
-
multi sub node2inline(Str $node --> Str ) {
|
637
|
-
return escape_html($node);
|
638
|
-
}
|
639
|
-
|
640
|
-
|
641
|
-
#| HTML-escaped text
|
642
|
-
multi sub node2text($node --> Str ) {
|
643
|
-
Debug { note colored("missing a node2text multi for ", "red") ~ $node.perl };
|
644
|
-
return escape_html(node2rawtext($node));
|
645
|
-
}
|
646
|
-
|
647
|
-
multi sub node2text(Pod::Block::Para $node --> Str ) {
|
648
|
-
return node2text($node.contents);
|
649
|
-
}
|
650
|
-
|
651
|
-
multi sub node2text(Pod::Raw $node --> Str ) {
|
652
|
-
my $t = $node.target;
|
653
|
-
if $t && lc($t) eq 'html' {
|
654
|
-
$node.contents.join
|
655
|
-
}
|
656
|
-
else {
|
657
|
-
'';
|
658
|
-
}
|
659
|
-
}
|
660
|
-
|
661
|
-
# FIXME: a lot of these multis are identical except the function name used...
|
662
|
-
# there has to be a better way to write this?
|
663
|
-
multi sub node2text(Positional $node --> Str ) {
|
664
|
-
return $node.map({ node2text($_) }).join;
|
665
|
-
}
|
666
|
-
|
667
|
-
multi sub node2text(Str $node --> Str ) {
|
668
|
-
return escape_html($node);
|
669
|
-
}
|
670
|
-
|
671
|
-
|
672
|
-
#| plain, unescaped text
|
673
|
-
multi sub node2rawtext($node --> Str ) {
|
674
|
-
Debug { note colored("Generic node2rawtext called with ", "red") ~ $node.perl };
|
675
|
-
return $node.Str;
|
676
|
-
}
|
677
|
-
|
678
|
-
multi sub node2rawtext(Pod::Block $node --> Str ) {
|
679
|
-
Debug { note colored("node2rawtext called for ", "bold") ~ $node.gist };
|
680
|
-
return node2rawtext($node.contents);
|
681
|
-
}
|
682
|
-
|
683
|
-
multi sub node2rawtext(Positional $node --> Str ) {
|
684
|
-
return $node.map({ node2rawtext($_) }).join;
|
685
|
-
}
|
686
|
-
|
687
|
-
multi sub node2rawtext(Str $node --> Str ) {
|
688
|
-
return $node;
|
689
|
-
}
|
690
|
-
|
691
|
-
# vim: expandtab shiftwidth=4 ft=perl6
|