Skip to content

Instantly share code, notes, and snippets.

@CIAvash

CIAvash/Node.pm6 Secret

Created November 29, 2022 19:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save CIAvash/85bbbbd24ca9652980bd33cfdb9e7e3e to your computer and use it in GitHub Desktop.
Save CIAvash/85bbbbd24ca9652980bd33cfdb9e7e3e to your computer and use it in GitHub Desktop.
Highlighting docs.raku.org code with chroma
use JSON::Fast;
use Pod::To::HTML;
use URI::Escape;
use OO::Monitors;
monitor Docky::Renderer::Node is Node::To::HTML {
my $hl-proc = Proc::Async.new('chroma', '-l', 'raku', '--html', '--html-lines', '--html-only', :r, :w);
# my $hl-proc = Proc::Async.new('chroma', '-l', 'raku', '-s', 'doom-one', '--html', '--html-lines', '--html-only', '--html-inline-styles', :r, :w);
multi method node2html(Pod::List $node) {
"<div class=\"content\"><ul>" ~ self.node2html($node.contents) ~ "</ul></div>\n";
}
multi method node2html(Pod::Heading $node) {
# HTML only has 6 levels of numbered headings
my $level = min($node.level, 6);
my %escaped = id => escape_id(node2rawtext($node.contents)),
html => self.node2inline($node.contents);
%escaped<uri> = uri_escape(%escaped<id>);
my $content = %escaped<html> ~~ m{href .+ \<\/a\>}
?? %escaped<html>
!! '<a class="u" href="#___top" title="go to top of document">' ~ %escaped<html> ~ '</a>';
$content ~= qq:to/END/;
<a class="raku-anchor" href="#%escaped<id>">§</a>
END
"<h$level class=\"raku-h$level\" id={ "\"%escaped<id>\"" }>$content\</h$level>\n";
}
sub detect-declaration(Str $code) {
# A very hole-y number of heuristics to check if it is a signature
# and we don't want to have 'Run' button there...
# If there is only a single line and it starts with `class`
$code.indices("\n").elems == 0 && $code.starts-with('class' | 'role') ||
# There are multiple lines and all start from either multi, sub
so $code.lines.map(*.starts-with('multi' | 'sub' | 'method' | 'proto')).all;
}
method highlight-code($node) {
my $code = $node.contents.join;
my $result = $code;
react {
whenever $hl-proc.stdout.reduce: &[~] {
say 'got the code!';
dd $_;
$result = $_ if $_
}
whenever $hl-proc.stderr.reduce: &[~] {
put "Error while hilighting code example: $_" if $_;
}
whenever $hl-proc.start {
done
}
whenever $hl-proc.put: $code {
$hl-proc.close-stdin
}
whenever signal(SIGTERM, SIGINT).zip: Promise.in(3).Supply {
$hl-proc.kill
}
}
$result
}
multi method node2html(Pod::Block::Code $node) {
# Detect language
my $lang = $node.config<lang> || $node.config<skip-test> ?? '' !! 'raku-lang';
my $content;
# If it's Raku, we allow an editor
if $lang eq 'raku-lang' {
$content = self.highlight-code($node);
} else {
$content = '<pre class="pod-block-code">' ~ self.node2inline($node.contents) ~ "</pre>\n";
}
# Should we have a run button?
my $allow-running = $lang eq 'raku-lang' && !detect-declaration($node.contents.join);
# Allow to explicitly override our guesses
with $node.config<runnable> -> $is-runnable {
$allow-running = $is-runnable;
}
constant $code-runner = q:to/END/;
<div class="code-output">
<button class="button code-button" aria-label="run">Run</button>
<div></div>
</div>
END
return qq:to/END/;
<div class="raku-code $lang">
$content
{ $allow-running ?? $code-runner !! '' }
</div>
END
}
multi method node2html(Pod::Block::Table $node) {
$node.config<class> = 'table is-bordered centered';
Node::To::HTML.node2html($node);
}
multi method node2html(Pod::Block::Para $node, *%config --> Str) {
with %config<versioned> {
qq:to/END/
<article class="raku version-note">
<div class="version-note-header">
<p>Version Note</p>
<div class="version-related-to">
<span class="icon">
<i class="fas fa-chevron-$_ is-medium"></i>
</span>
</div>
</div>
<div class="version-body">
{ "<p>" ~ self.node2inline($node.contents) ~ "</p>" }
</div>
</article>
END
} else {
"<p>" ~ self.node2inline($node.contents) ~ "</p>"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment