github-markup 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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