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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -7
  3. data/HISTORY.md +4 -0
  4. data/github-markup.gemspec +1 -1
  5. data/lib/github-markup.rb +1 -1
  6. data/lib/github/commands/pod62html +1 -6
  7. metadata +2 -32
  8. data/.gitmodules +0 -3
  9. data/test/markups/README.pod6 +0 -151
  10. data/test/markups/README.pod6.html +0 -128
  11. data/vendor/Pod-To-HTML/LICENSE +0 -201
  12. data/vendor/Pod-To-HTML/META6.json +0 -20
  13. data/vendor/Pod-To-HTML/README.md +0 -96
  14. data/vendor/Pod-To-HTML/README.pod6 +0 -42
  15. data/vendor/Pod-To-HTML/TODO +0 -5
  16. data/vendor/Pod-To-HTML/lib/Pod/To/HTML.pm +0 -691
  17. data/vendor/Pod-To-HTML/resources/examples/01-parse-files.p6 +0 -7
  18. data/vendor/Pod-To-HTML/resources/examples/README.md +0 -13
  19. data/vendor/Pod-To-HTML/resources/examples/main.mustache +0 -26
  20. data/vendor/Pod-To-HTML/resources/examples/render.p6 +0 -17
  21. data/vendor/Pod-To-HTML/resources/templates/main.mustache +0 -32
  22. data/vendor/Pod-To-HTML/t/010-basic.t +0 -29
  23. data/vendor/Pod-To-HTML/t/020-code.t +0 -49
  24. data/vendor/Pod-To-HTML/t/030-comment.t +0 -15
  25. data/vendor/Pod-To-HTML/t/040-lists.t +0 -82
  26. data/vendor/Pod-To-HTML/t/050-format-x-index.t +0 -47
  27. data/vendor/Pod-To-HTML/t/060-table.t +0 -108
  28. data/vendor/Pod-To-HTML/t/070-headings.t +0 -45
  29. data/vendor/Pod-To-HTML/t/075-defn.t +0 -45
  30. data/vendor/Pod-To-HTML/t/080-lang.t +0 -14
  31. data/vendor/Pod-To-HTML/t/090-css.t +0 -16
  32. data/vendor/Pod-To-HTML/t/100-issue-37.t +0 -16
  33. data/vendor/Pod-To-HTML/t/110-issue-41.t +0 -18
  34. data/vendor/Pod-To-HTML/t/120-templates.t +0 -42
  35. 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
@@ -1,5 +0,0 @@
1
- * Tests
2
- * More of 'em
3
- * A cleaner way to test than ms[[ ]];
4
- * Nested items
5
- * Generate HTML fragments from Pod fragments better
@@ -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{&amp;}, q{&lt;}, q{&gt;}, q{&quot;}, q{&#39;}, q{&nbsp;}]);
58
- }
59
-
60
- sub unescape_html(Str $str --> Str ) {
61
- $str.trans( [ rx{'&amp;'}, rx{'&lt;'}, rx{'&gt;'}, rx{'&quot;'}, rx{'&#39;'} ] =>
62
- [ q{&}, q{<}, q{>}, q{"}, q{'} ] );
63
- }
64
-
65
- sub escape_id ($id) {
66
- $id.trim.subst(/\s+/, '_', :g)
67
- .subst('"', '&quot;', :g)
68
- .subst('&nbsp;', '_', :g)
69
- .subst('&#39;', "'", :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 &pre;
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()&lt;}
626
- ~ node2inline($node.contents)
627
- ~ q{&gt;</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