So you're running a Rails application and want to spruce up your YARD documentation. Here's the guide I wish I had.
Add yard-activerecord
and yard-activesupport-concern
to your Gemfile, add --plugin activerecord
and --plugin activesupport-concern
to your .yardopts
flags, and db/schema.rb
to the end of your .yardopts
sources. Your models' attributes and assocations should now be included in the documentation.
To modify your YARD template, create doc-src/templates/default/fulldoc/html
, then add --template-path doc-src/templates
to your project's .yardopts
. You can now create a doc-src/templates/default/fulldoc/html/css/common.css
and the styles will be included (but overwrites need to be !important
).
To modify the side menu of the docs, create doc-src/templates/default/fulldoc/html/setup.rb
to override the default methods. Here's a mediocre sample based on aws's sdk that creates folders like those in a Rails app/
. Note that this also involves adding a doc-src/templates/default/fulldoc/html/js/nolink.js
which can be found here.
include Helpers::ModuleHelper
def javascripts_full_list
super + ['js/nolink.js']
end
def class_list(root = Registry.root, tree = TreeContext.new)
out = String.new("")
children = run_verifier(root.children)
children += @items.select {|o| o.namespace.is_a?(CodeObjects::Proxy) } if root == Registry.root
controller_children, other_children = children.partition { |child| child.title&.include?('Controller') }
helper_children, other_children = other_children.partition { |child| child.title&.include?('Helper') }
model_children, other_children = other_children.partition { |child| child.is_a?(CodeObjects::ClassObject) && child.superclass }
module_children, other_children = other_children.partition { |child| child.is_a?(CodeObjects::ModuleObject) }
out << class_list_section(:controllers, tree, controller_children)
out << class_list_section(:helpers, tree, helper_children)
out << class_list_section(:models, tree, model_children)
out << class_list_section(:modules, tree, module_children)
out << class_list_children(tree, other_children)
out
end
def class_list_section(type, tree, children)
out = String.new("")
out << "<li class='#{tree.classes.join(' ')} nolink'>"
out << "<div class='item' style='padding-left:#{tree.indent}'>"
out << "<a class='toggle'></a> " + type.to_s.capitalize
out << "</div><ul>"
tree.nest do
out << class_list_children(tree, children)
end
out << '</ul></li>'
end
def class_list_children(tree, children)
out = String.new("")
children&.compact&.sort_by(&:path)&.each do |child|
if child.is_a?(CodeObjects::NamespaceObject)
name = child.namespace.is_a?(CodeObjects::Proxy) ? child.path : child.name
grand_children = run_verifier(child.children)
is_parent = grand_children.any? {|o| o.is_a?(CodeObjects::NamespaceObject) }
out << "<li id='object_#{child.path}' class='#{tree.classes.join(' ')}'>"
out << "<div class='item' style='padding-left:#{tree.indent}'>"
out << "<a class='toggle'></a> " if is_parent
out << linkify(child, name)
out << " < #{child.superclass.name}" if child.is_a?(CodeObjects::ClassObject) && child.superclass
out << "<small class='search_info'>"
out << child.namespace.title
out << "</small>"
out << "</div>"
if is_parent
tree.nest do
out << "<ul>#{class_list_children(tree, grand_children)}</ul>"
end
end
out << "</li>"
end
end
out
end
You can add additional files to your documentation by adding them to a doc-src/files
and adding doc-src/files/**/*.md
in your .yardopts
sources argument (after the '-').
The ordering of these files is unintuitive, so if you're like me and would prefer to see them listed alphabetically, you can add the following to doc-src/templates/default/fulldoc/html/full_list_file.erb
:
<% even_odd = 'odd' %>
<% @items.sort_by { |i| i.attributes['title'] || ''}.each do |item| %>
<li id="object_<%= item.path %>" class="<%= even_odd %>">
<div class="item"><span class="object_link"><%= link_file item %></span></div>
</li>
<% even_odd = (even_odd == 'even' ? 'odd' : 'even') %>
<% end %>
You've added custom files, styles, and menu logic to your documentation in about 5 minutes. Good work!
it's super easy to use GitHub Pages as the host of your documentation. There's really only two gotchas:
- YARD defaults to outputting to 'doc', but GitHub prefers 'docs'. Add
-o docs
to your.yardopts
. - GitHub Pages uses Jekyll to serve the pages. Jekyll doesn't like files that start with an underscore, and YARD uses a file called
_index.html
, which will 404 on a Jekyll build, unless you drop a_config.yml
in yourdocs
folder with the lineinclude: ['_index.html']
.
Once you've done that, you can use the GitHub website to setup the GitHub Pages documentation hosting integration.
Your final .yardopts
should look something like
-o docs
-r README.md
--protected
--private
--template-path docsrc/templates
--plugin activerecord
--plugin activesupport-concern
'app/**/*.rb'
'lib/**/*.rb'
'db/schema.rb' -
docsrc/files/**/*.md
@tcd Glad it was helpful, and thanks for providing that .js file!