From 87a4ebd8cc16f74bf81d29bc3e1d9cc4b508b03b Mon Sep 17 00:00:00 2001 From: finanalyst Date: Fri, 17 Jan 2025 16:16:23 +0000 Subject: [PATCH] refactor HTML code escaping for multi embedded markup --- META6.json | 2 +- docs/samples/rakudoc.rakudoc | 4 +-- lib/RakuDoc/To/HTML.rakumod | 18 ++++++----- xt/600-R-2-HTML.rakutest | 51 ++++++++++++++++++++++++++++++- xt/605-H-E-Plugin-Hilite.rakutest | 34 +++++++++++++++------ 5 files changed, 88 insertions(+), 21 deletions(-) diff --git a/META6.json b/META6.json index f38a41a..8fe3a76 100644 --- a/META6.json +++ b/META6.json @@ -1,7 +1,7 @@ { "name": "Rakuast::RakuDoc::Render", "description": "Renders RakuDoc v2 to text, HTML, HTML-Extra, Markdown", - "version": "0.24.0", + "version": "0.24.1", "authors": [ "Richard Hainsworth" ], diff --git a/docs/samples/rakudoc.rakudoc b/docs/samples/rakudoc.rakudoc index 8050fdf..d3ff7fa 100644 --- a/docs/samples/rakudoc.rakudoc +++ b/docs/samples/rakudoc.rakudoc @@ -1,7 +1,7 @@ =begin rakudoc :kind("Language") :subkind("Language") :category("reference") =TITLE RakuDoc =SUBTITLE A Raku slang for documenting Raku software to aid development and use. -=VERSION 2.11.0 +=VERSION 2.11.1 RakuDoc is a markup language with simple instructions for simple tasks and more complex structures to suit larger projects. There is a clear distinction between @@ -3025,7 +3025,7 @@ information can be rendered using L> markup instruction|#Placement links Builtin, semantic and custom blocks are considered by default to be equivalent to C<=head> for the purposes of a Table of Contents. The following are considered to be equivalent to paragraphs (not -included in a Table of Contents) by default: C<=para>, C<=nested>, C, C<=input>, C<=output>, +included in a Table of Contents) by default: C<=para>, C<=nested>, C<=code>, C<=input>, C<=output>, <=table>, C<=defn>, C<=item>, C<=alias>, and their I variants if they exist. This default can be changed with the C<:toc> and C<:headlevel> meta tabs. diff --git a/lib/RakuDoc/To/HTML.rakumod b/lib/RakuDoc/To/HTML.rakumod index c951c8b..f429b17 100644 --- a/lib/RakuDoc/To/HTML.rakumod +++ b/lib/RakuDoc/To/HTML.rakumod @@ -143,19 +143,23 @@ class RakuDoc::To::HTML { my constant BAD-MARK-ON = ''; my constant BAD-MARK-OFF = ''; my @bullets = <<\x2022 \x25b9 \x2023 \x2043 \x2219>> ; - my regex tab { '<' $ = (<-[>\s]>+) $ = (.*?) '>'}; + my regex spantab { '<' \/? 'span' <-[>]>* '>'}; %( #| special key to name template set _name => -> %, $ { 'markdown templates' }, - #| escape contents of code block + #| escape contents of code block, which may contain & tabs, not to be escaped escape-code => -> %prm, $tmpl { my $cont = %prm.Str // ''; - while $cont ~~ m:c/ / { - my $name = ~$; - $cont = $/.replace-with('<' ~ $ ~ $ ~ '>') - unless ($name eq .any).so + if $cont ~~ / / { + ( $cont ~~ / ^ [ .*? ]+ .*? $ / ) + .chunks + .map({ + $tmpl.globals.escape.( .value ) if .key eq '~'; + .value + }) + .join } - $cont + else { $tmpl.globals.escape.( $cont ) } }, #| renders =code blocks code => -> %prm, $tmpl { diff --git a/xt/600-R-2-HTML.rakutest b/xt/600-R-2-HTML.rakutest index 7cf8213..e2c764a 100644 --- a/xt/600-R-2-HTML.rakutest +++ b/xt/600-R-2-HTML.rakutest @@ -1,7 +1,7 @@ use v6.d; use Test; use Test::Run :runs_ok; -plan 7; +plan 9; use RakuDoc::Render; use RakuDoc::To::HTML; @@ -50,4 +50,53 @@ runs_ok( 'outputs debug info on AstBlock' ); +%*ENV:delete; +my $ast = q:to/CODE/.AST; +=begin rakudoc +=begin code :lang + =head2 X|Syntax,hyper (statement prefix)>, X|Syntax,race (statement prefix)> +=end code +=begin code :lang + =head2 X<<>;Operators,«;Operators,»;Operators,»=«;Operators,«=»>>> +=end code +=begin code :lang + =head2 X<<>> +=end code +=end rakudoc +CODE + +my $rv = $html-instance.rdp.render( $ast, :pre-finalized ).body.Str; + +like $rv, / + ' + =head2 X|Syntax,hyper (statement prefix)>, X|Syntax,race (statement prefix)> +=end code +=begin code :allow + =head2 X<<>;Operators,«;Operators,»;Operators,»=«;Operators,«=»>>> +=end code +=begin code :allow + =head2 X<< and quote protection: qqww|Syntax,qqww>>> +=end code +=end rakudoc +CODE + +$rv = $html-instance.rdp.render( $ast, :pre-finalized ).body.Str; + +like $rv, / + 'hyper' .+? 'prefix)>' .+? + 'X<race|Syntax,race (statement prefix)>' .+? + 'interpolation and quote protection: qqww|Syntax,qqww>>>' + /, 'escaping with allow'; + + done-testing; diff --git a/xt/605-H-E-Plugin-Hilite.rakutest b/xt/605-H-E-Plugin-Hilite.rakutest index cf3819a..4061b48 100644 --- a/xt/605-H-E-Plugin-Hilite.rakutest +++ b/xt/605-H-E-Plugin-Hilite.rakutest @@ -5,19 +5,33 @@ use RakuDoc::To::HTML; my $html-instance = RakuDoc::To::HTML.new; my $rdp := $html-instance.rdp; +plan 2; + lives-ok { require RakuDoc::Plugin::HTML::Hilite; RakuDoc::Plugin::HTML::Hilite.new.enable( $rdp ); }, 'hilite plugin enabled'; -#my $src = q[my $var = 2;]; -#my $hl = highlight( $src, 'HTML' ); -#like $hl, / -# '' .+ -# 'cyan' .+ '$var' .+ -# 'yellow' .+ '=' -# /, 'statement highlighted with default colors'; -#my $hl-pl = $rdp.templates(%(:contents($src), :lang) ); -#like $hl-pl, / '' \s* $hl /, 'similar highlighting'; + +my $ast = q:to/CODE/.AST; +=begin rakudoc +=begin code + =head2 X|Syntax,hyper (statement prefix)>, X|Syntax,race (statement prefix)> +=end code +=begin code + =head2 X<<>;Operators,«;Operators,»;Operators,»=«;Operators,«=»>>> +=end code +=begin code + =head2 X<<>> +=end code +=end rakudoc +CODE + +my $rv = $html-instance.rdp.render( $ast, :pre-finalized ).body.Str; + +like $rv, / + '' .+? + 'X' .+? + 'C<hyper>' +/, 'got Rainbow hilighting in code'; done-testing;