docs/Templates.md in yard-0.6.8 vs docs/Templates.md in yard-0.7.0

- old
+ new

@@ -1,14 +1,14 @@ -Templates Architecture -====================== +# @title Templates Architecture +# Templates Architecture + Templates are the main component in the output rendering process of YARD, which is invoked when conventional HTML/text output needs to be rendered for a set of code objects. -Design Goals ------------- +## Design Goals The general design attempts to be as abstracted from actual content and templates as possible. Unlike RDoc which uses one file to describe the entire template, YARD splits up the rendering of code objects into small components, allowing template modification for smaller subsets of a full template without having to @@ -28,19 +28,17 @@ from arbitrary sources. These independent components are called "sections". 3. Sections should be able to be inserted into any object without affecting any existing sections in the document. This allows for easy modification of templates by plugins. -Templates ---------- +## Templates Template modules are the objects used to orchestrate the design goals listed above. Specifically, they organize the sections and render the template contents depending on the format. -Engine ------- +## Engine The Engine class orchestrates the creation and rendering of Template modules and handles serialization or specific rendering scenarios (like HTML). To create a template, use the {YARD::Templates::Engine.template template} method. The two most common methods used to initiate output are the {YARD::Templates::Engine.render render} @@ -61,24 +59,22 @@ class has a {YARD::CodeObjects::Base#format #format} helper method to render an object. For instance, the above render example is equivalent to the simple call `myobject.format`. The `generate` method is a special kind of render and is called from the {YARD::CLI::Yardoc} command line utility. -Template Options ----------------- +## Template Options A template keeps state when it is rendering output. This state is kept in an options hash which is initially passed to it during instantiation. Some default options set the template style (`:template`), the output format (`:format`), and the serializer to use (`:serializer`). This options hash is modifiable from all methods seen above. For example, initializing a template to output as HTML instead of text can be done as follows: myobject.format(:format => :html) -Serializer ----------- +## Serializer This class abstracts the logic involved in deciding how to serialize data to the expected endpoint. For instance, there is both a {YARD::Serializers::StdoutSerializer StdoutSerializer} and {YARD::Serializers::FileSystemSerializer FileSystemSerializer} class for outputting to console or to a file respectively. When endpoints with locations @@ -89,12 +85,11 @@ Rendered objects are automatically serialized using the object if present, otherwise the rendered object is returned as a string to its parent. Nested Templates automatically set the serializer to nil so that they return as a String to their parent. -Creating a Template -------------------- +## Creating a Template Templates are represented by a directory inside the {YARD::Templates::Engine.template_paths} on disk. A standard template directory looks like the following tree: (Assuming templates/ is a template path) @@ -135,12 +130,11 @@ files are the sections that make up the template. Note that the subdirectory `html/` is also its own "template" that inherits from the parent directory. We will see more on this later. -setup.rb --------- +## setup.rb Every template should have at least one `setup.rb` file that defines the {YARD::Templates::Template#init #init} method to set the {YARD::Templates::Template#sections #sections} used by the template. If a setup.rb is not defined in the template itself, there should be a template @@ -151,21 +145,19 @@ def init sections :section1, :section2, :section3 end -Sections --------- +## Sections Sections are smaller components that correlate to template fragments. Practically speaking, a section can either be a template fragment (a conventional .erb file or other supported templating language), a method (which returns a String) or another {YARD::Templates::Template} (which in turn has its own list of sections). -Nested Sections ---------------- +## Nested Sections Sections often require the ability to encapsulate a set of sub-sections in markup (HTML, for instance). Rather than use heavier Template subclass objects, a more lightweight solution is to nest a set of sub-sections as a list that follows a section, for example: @@ -196,12 +188,11 @@ Note that `yieldall` yields to all subsections, whereas `yield` will yield to each individually (in order) until there are no more left to yield to. In the vast majority of cases, you'd want to use `yieldall`, since `yield` makes it hard for users to override your template. -Inheriting Templates --------------------- +## Inheriting Templates Parent directory templates are automatically inherited (or mixed in, to be more accurate) by the current template. This means that the 'default/class/html' template automatically inherits from 'default/class'. This also means that anything defined in 'default/class/setup.rb' can be overridden by 'default/class/html/setup.rb'. @@ -221,12 +212,11 @@ include T('default/module/html') This includes the 'default/module/html', which means it also includes 'default/module' by extension. This allows class to make use of any of module's erb files. -Inserting and Traversing Sections ---------------------------------- +## Inserting and Traversing Sections The ability to insert sections was mentioned above. The class template, for instance, will modify the #init method to insert class specific sections: def init @@ -262,12 +252,11 @@ which allow you to insert sections before or after the first matching section name recursively. The above example could simply be rewritten as: sections.place(:e).after_any(:d) -Overriding Templates by Registering a Template Path ---------------------------------------------------- +## Overriding Templates by Registering a Template Path Inheriting templates explicitly is useful when creating a customized template that wants to take advantage of code re-use. However, most users who want to customize YARD templates will want to override existing behaviour without creating a template from scratch. @@ -303,5 +292,227 @@ sections.push :customsection end Now, when a class object is formatted as HTML, our customsection.erb will be appended to the rendered data. + + +### Overriding Stylesheets and Javascripts + +Template authors can override existing stylesheets and javascripts by creating +a file with the same name as existing files within the `fulldoc` template. The +documentation output will utilize the new replacement file. + +YARD's `fulldoc` template defines three stylesheets: + + /yard/templates/default/: + |-- fulldoc + | |-- html + | | |-- css + | | | |-- common.css + | | | |-- full_list.css + | | | |-- style.css + +The `style.css` is the primary stylesheet for the HTML output. + +The `full_list.css` is an additional stylesheet loaded specifically for the +search field menus (i.e. class list, method list, and file list). + +The `common.css` is an empty css file that an template author can easily override +to provide custom styles for their plugin. However, if a user installs multiple +plugins that utilize this same file to deliver styles, it is possible that they +will be overridden. + +YARD's `fulldoc` template defines three javascript files: + + /yard/templates/default/: + |-- fulldoc + | |-- html + | | |-- js + | | | |-- app.js + | | | |-- full_list.js + | | | |-- jquery.js + +The `app.js` is the primary javascript file for the HTML output. + +The `full_list.js` defines additional javascript loaded specifically for the +search field menus (i.e. class list, method list, and file list). + +The `jquery.js` is copy of the jquery javascript library. + +### Adding a Custom Stylesheet or Javascript + +To load additional stylesheets and javascripts with every page (except the search +field menus) generated from the base `layout` template: + + 1. Define your own custom stylesheet and/or javascript file + (default/ is the default template name inside of the /template root directory): + + /template/default/: + |-- fulldoc + | |-- html + | | |-- css + | | | |-- custom.css + | | |-- js + | | | |-- custom.js + + 2. Create a `setup.rb` in the `layout` template directory and override the methods + `stylesheets` and `javascripts`. The path to the template would be: + + /template/default/: + |-- layout + | |-- html + | | |-- setup.rb + + And the code would look like: + + def stylesheets + # Load the existing stylesheets while appending the custom one + super + %w(css/custom.css) + end + + def javascripts + # Load the existing javascripts while appending the custom one + super + %w(js/custom.js) + end + + +To load additional stylesheets and javascripts for the search menus loaded from +the `fulldoc` template: + + 1. Define your own custom stylesheet and/or javascript file. + + /path/to/mytemplates/: + |-- fulldoc + | |-- html + | | |-- css + | | | |-- custom_full_menu.css + | | |-- js + | | | |-- custom_full_menu.js + + + 3. Override the methods `stylesheets_full_list` and `javascripts_full_list` + in the `setup.rb` file inside fulldoc/html. + + def stylesheets_full_list + # Load the existing stylesheets while appending the custom one + super + %w(css/custom.css) + end + + def javascripts_full_list + # Load the existing javascripts while appending the custom one + super + %w(js/custom.js) + end + +### Overriding Search Menus + +By default YARD's `fulldoc` template generates three search fields: + + * Class List + * Method List + * File List + +Their contents are rendered in methods within the `fulldoc` template: + + * `generate_class_list` + * `generate_method_list` + * `generate_file_list` + +To override these lists you will need to: + + 1. Create a `setup.rb` in the `fulldoc` template directory and override the + particular method. + + /path/to/mytemplates/: + |-- fulldoc + | |-- html + | | |-- setup.rb + + def generate_method_list + @items = prune_method_listing(Registry.all(:method), false) + @items = @items.reject {|m| m.name.to_s =~ /=$/ && m.is_attribute? } + + # Here we changed the functionality to reverse the order of displayed methods + @items = @items.sort_by {|m| m.name.to_s }.reverse + @list_title = "Method List" + @list_type = "methods" + asset('method_list.html', erb(:full_list)) + end + +### Adding Additional Search Menus + +By default YARD's `fulldoc` template generates three search fields: + + * Class List + * Method List + * File List + +These are defined in the `layout` template method `menu_lists` and pulled into +the `fulldoc` template through a similarly named method. + +To load an additional menu item: + + + 1. Create a `setup.rb` in the `layout` template directory and override the methods + `menu_lists`. The `type` informs the search field the name of the file. + The `title` is the name that appears above the section when viewed in frames. + The `search_title` is the name that appears in the search field tab on the page. + + + /path/to/mytemplates/: + |-- layout + | |-- html + | | |-- setup.rb + + def menu_lists + # Load the existing menus + super + [ { :type => 'feature', :title => 'Features', :search_title => 'Feature List' } ] + end + + 2. Create a `setup.rb` in the `fulldoc` template directory and create a method + to generate a menu for the specified `type`. + The method `generate_assets` will look for a function with a signature prefixed + with `generate`, the type value specified, and the suffix `list`. Within that + method you can configure and load the specific objects you wish to display. + + /path/to/mytemplates/: + |-- fulldoc + | |-- html + | | |-- setup.rb + + def generate_feature_list + + # load all the features from the Registry + @items = Registry.all(:feature) + @list_title = "Feature List" + @list_type = "feature" + + # optional: the specified stylesheet class + # when not specified it will default to the value of @list_type + @list_class = "class" + + # Generate the full list html file with named feature_list.html + # @note this file must be match the name of the type + asset('feature_list.html', erb(:full_list)) + end + + + 3. Define custom javascript to load the search fields and the keyboard shortcuts. + + function featureSearchFrameLinks() { + $('#feature_list_link').click(function() { + toggleSearchFrame(this, relpath + 'feature_list.html'); + }); + } + + function featureKeyboardShortcuts() { + if (window.top.frames.main) return; + $(document).keypress(function(evt) { + if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return; + if (typeof evt.orignalTarget !== "undefined" && + (evt.originalTarget.nodeName == "INPUT" || + evt.originalTarget.nodeName == "TEXTAREA")) return; + switch (evt.charCode) { + case 82: case 114: $('#feature_list_link').click(); break; // 'r' + } + }); + }