yard icon indicating copy to clipboard operation
yard copied to clipboard

Syntax highlighting of code in other languages than Ruby?

Open thomthom opened this issue 2 years ago • 13 comments

I'm working on adding additional documentation in a .md document that ships with the API docs. In the docs I have C/C++ code examples for Ruby C Extensions. However, these code blocks doesn't get any syntax coloring. Is it possible with YARD? Via some addon gem or something?

thomthom avatar Oct 06 '21 11:10 thomthom

ah! I found this in the WhatsNew.md file:

https://github.com/lsegal/yard/blob/main/docs/WhatsNew.md#multiple-syntax-highlighting-language-support-050

On that note, it describes using !!!LANGNAME to indicate language. Does that mean normal markdown method of spesifying langue doesn't work?

```c++
// ...
```

```ruby
# ...
```

thomthom avatar Oct 06 '21 12:10 thomthom

Also, where does one add a html_syntax_highlight_LANGNAME type method?

thomthom avatar Oct 06 '21 12:10 thomthom

So, I already had a custom yard plugin with a custom template. And I tried adding it to templates/default/layout/html/setup.rb

def html_syntax_highlight_cpp(source)
  formatter = Rouge::Formatters::HTML.new
  lexer = Rouge::Lexers::Cpp.new
  formatter.format(lexer.lex(source))
end

And this worked! Is this the canonical way to do this? (At least for a template. I'm guessing it would be different if I wanted to make a yard plugin gem that worked across templates?)

thomthom avatar Oct 06 '21 13:10 thomthom

And this worked! Is this the canonical way to do this? (At least for a template. I'm guessing it would be different if I wanted to make a yard plugin gem that worked across templates?)

YARD::Templates::Helpers::HtmlHelper is the module that houses all the syntax highlighting methods, and would be the generic way to support such a plugin.

FWIW there are a few YARD syntax highlight plugins out there today. I would also recommend potentially injecting client-side highlighting JS libraries if you're only providing minimal amounts of visible code snippets. Highlight.js and equivalents would work seamlessly with most templates and could be brought in with a 1 line script injection.

lsegal avatar Oct 06 '21 19:10 lsegal

YARD::Templates::Helpers::HtmlHelper is the module that houses all the syntax highlighting methods, and would be the generic way to support such a plugin.

So a plugin would open that namespace and add methods to it?

FWIW there are a few YARD syntax highlight plugins out there today. I would also recommend potentially injecting client-side highlighting JS libraries if you're only providing minimal amounts of visible code snippets. Highlight.js and equivalents would work seamlessly with most templates and could be brought in with a 1 line script injection.

Oh, interesting. I didn't find those in my search. (my RubyGems foo is poor). I'll have a look and see if they cover my needs.

thomthom avatar Oct 07 '21 07:10 thomthom

So a plugin would open that namespace and add methods to it?

Yep. Adding custom markup formats works the same way.

lsegal avatar Oct 07 '21 07:10 lsegal

Thank you for the insights.

And format is only extracted via !!!LANGNAME notation, not via Markdown code block notation:

```c++
// ...
```

?

thomthom avatar Oct 07 '21 07:10 thomthom

And format is only extracted via !!!LANGNAME notation, not via Markdown code block notation:

Nope, both work, !!!LANGNAME is just a syntax to support indented blocks in RDoc formatting, which doesn't support language annotations (since it has no concept of fencing). YARD will post-process HTML output to detect the language type generated by Markdown and other processors:

https://github.com/lsegal/yard/blob/d61dac0fffb97c1fb40e8170e229d359f1ba31c6/lib/yard/templates/helpers/html_helper.rb#L640-L655

(edit: fixed code snippet link)

lsegal avatar Oct 07 '21 07:10 lsegal

Thanks! I don't know why I didn't see it working before, but now I do. I also tried out some of the other plugins, but none worked properly for my purpose. Most promising and closest to success was yard-coderay, but it didn't handle C++ syntax well. But your feedback and looking at yard-coderay I think I have what I need to make my own using Rouge. Only thing I have to resolve is that Rouge generate separate CSS code, not inline. So I need to figure out who to write that to file and link into the doc.

thomthom avatar Oct 07 '21 12:10 thomthom

hm... I'm only seeing the !!!LANG syntax working.

I inspected the calls to the code extracter and detect_lang_in_codeblock_attributes is getting passed two empty strings. The HTML that YARD parses is having code blocks that are plain <pre><code>...</code></pre>. The ```cpp syntax isn't adding any class annotations to the code blocks it generates.

thomthom avatar Oct 07 '21 13:10 thomthom

The HTML that YARD parses is having code blocks that are plain <pre><code>...</code></pre>

It would be a requirement for the Markdown processor library you're using to generate language-aware fenced code blocks. YARD doesn't do the generation for markdown, it's up to the library to understand fencing syntax-- since it's not a standard Markdown feature, not all libraries support it. Redcarpet (YARD's "first-choice" Markdown parser lib) should support this.

lsegal avatar Oct 07 '21 16:10 lsegal

Hm... Our code docs are using Rdoc, because of legacy reasons. But we have markdown pages included in the docs for additional info. Is it possible to set which markdown provider to use for the .md files only without switching all the documentation to use markdown syntax?

thomthom avatar Oct 08 '21 09:10 thomthom

Markdown files (.md) already use the markdown parser regardless of what is selected as the markup type; that said, yard doc options don't directly support changing the markup library provider (-M) for secondary markup types (i.e. the ones beyond what is selected with -m). You can do it with an extension / code though, specifically by manually reordering the list in YARD::Templates::Helpers::MarkupHelper:

https://github.com/lsegal/yard/blob/d61dac0fffb97c1fb40e8170e229d359f1ba31c6/lib/yard/templates/helpers/markup_helper.rb#L24-L34

That said, I'm not sure why you'd need to do this, since you should be able to gem install redcarpet. In fact, any of the top 3 providers should support fenced code blocks.

lsegal avatar Oct 08 '21 19:10 lsegal