From 6bd78022883127609bcb4598613261255d8f17ab Mon Sep 17 00:00:00 2001 From: Peter Woo Date: Mon, 18 Apr 2022 15:52:42 -0700 Subject: [PATCH 1/2] Add internal flag on highlighted
s, to prevent them
 from being processed twice

---
 lib/yard/templates/helpers/html_helper.rb     | 28 +++++++++++++------
 .../helpers/html_syntax_highlight_helper.rb   |  2 +-
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/lib/yard/templates/helpers/html_helper.rb b/lib/yard/templates/helpers/html_helper.rb
index 4d3d56862..0801ca35a 100644
--- a/lib/yard/templates/helpers/html_helper.rb
+++ b/lib/yard/templates/helpers/html_helper.rb
@@ -54,7 +54,7 @@ def urlencode(text)
       # @param [Symbol] markup examples are +:markdown+, +:textile+, +:rdoc+.
       #   To add a custom markup type, see {MarkupHelper}
       # @return [String] the HTML
-      def htmlify(text, markup = options.markup)
+      def htmlify(text, markup = options.markup, internal = false)
         markup_meth = "html_markup_#{markup}"
         return text unless respond_to?(markup_meth)
         return "" unless text
@@ -66,7 +66,7 @@ def htmlify(text, markup = options.markup)
         end
         html = resolve_links(html)
         unless [:text, :none, :pre, :ruby].include?(markup)
-          html = parse_codeblocks(html)
+          html = parse_codeblocks(html, internal)
         end
         html
       end
@@ -202,6 +202,11 @@ def html_syntax_highlight(source, type = nil)
 
         new_type, source = parse_lang_for_codeblock(source)
         type ||= new_type || :ruby
+
+        if type.to_s == "ruby" && source =~ /|

\s*\Z}, '') + htmlify(text, markup, true).gsub(%r{\A\s*

|

\s*\Z}, '') end # (see BaseHelper#link_object) @@ -637,20 +642,25 @@ def parse_lang_for_codeblock(source) # @param [String] html the html to search for code in # @return [String] highlighted html # @see #html_syntax_highlight - def parse_codeblocks(html) + def parse_codeblocks(html, internal = false) html.gsub(%r{(?:\s*)?(.+?)(?:\s*)?
}m) do - string = $3 + pre_match, code_match, string = $1, $2, $3 # handle !!!LANG prefix to send to html_syntax_highlight_LANG language, = parse_lang_for_codeblock(string) - language ||= detect_lang_in_codeblock_attributes($1, $2) + language ||= detect_lang_in_codeblock_attributes(pre_match, code_match) language ||= object.source_type - if options.highlight + pre_attrs = [%(class="code #{language}")] + + if options.highlight && /\bdata-highlighted="true"/ !~ pre_match string = html_syntax_highlight(CGI.unescapeHTML(string), language) + pre_attrs << 'data-highlighted="true"' if internal end - classes = ['code', language].compact.join(' ') - %(
#{string}
) + + pre_attrs = pre_attrs.compact.join(' ') + + %(
#{string}
) end end diff --git a/lib/yard/templates/helpers/html_syntax_highlight_helper.rb b/lib/yard/templates/helpers/html_syntax_highlight_helper.rb index 07ab9be79..fc5c60cee 100644 --- a/lib/yard/templates/helpers/html_syntax_highlight_helper.rb +++ b/lib/yard/templates/helpers/html_syntax_highlight_helper.rb @@ -39,7 +39,7 @@ def html_syntax_highlight_ruby_ripper(source) end output rescue Parser::ParserSyntaxError - source =~ /^ Date: Mon, 18 Apr 2022 20:56:19 -0700 Subject: [PATCH 2/2] Add new tests with syntax highlighting/include:file expectations --- spec/templates/helpers/html_helper_spec.rb | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/spec/templates/helpers/html_helper_spec.rb b/spec/templates/helpers/html_helper_spec.rb index 5f3f268a5..133fbb1e1 100644 --- a/spec/templates/helpers/html_helper_spec.rb +++ b/spec/templates/helpers/html_helper_spec.rb @@ -144,6 +144,30 @@ def options expect(htmlify("test {include:file:foo.rdoc}", :rdoc).gsub(/[\r?\n]+/, '')).to eq '

test HI

' end + it "preserves syntax highlighting in {include:} snippets" do + load_markup_provider(:rdoc) + expect(File).to receive(:file?).with('foo.rdoc').and_return(true) + expect(File).to receive(:read).with('foo.rdoc').and_return( + " !!!ruby\n x = 1\n" + ) + expect(htmlify("{include:file:foo.rdoc}", :rdoc).gsub(/[\r?\n]+/, '')). + not_to include("<") + end + + it "escapes {include:} html snippets only once" do + expect(self).to receive(:html_syntax_highlight_html) do |source| + %(#{CGI.escapeHTML(source)}) + end.at_least(:once) + + load_markup_provider(:rdoc) + expect(File).to receive(:file?).with('foo.md').and_return(true) + expect(File).to receive(:read).with('foo.md').and_return( + " !!!html\n

\n" + ) + expect(htmlify("{include:file:foo.md}", :markdown).gsub(/[\r?\n]+/, '')). + to include(%(<h1>)) + end + it "does not autolink URLs inside of {} (markdown specific)" do log.enter_level(Logger::FATAL) do pending 'This test depends on markdown' unless markup_class(:markdown) @@ -648,6 +672,12 @@ def subject.respond_to?(method, include_all = false) ) end + it "wraps but doesn't alter ruby snippets that already contain highlighting tags" do + expect(subject.htmlify('
for
', :html)).to eq( + '
for
' + ) + end + it "highlights source when matching a pre lang= tag" do expect(subject.htmlify('
x = 1
', :html)).to eq( '
x = 1
'