Skip to content
This repository
tree: e06d22b47e
Fetching contributors…

Cannot retrieve contributors at this time

file 151 lines (98 sloc) 10.743 kb

Docu: Simple documentation done simply

What's a docu?

A documentation generator for .Net that isn't complicated, awkward, or difficult to use. Given an assembly and the XML that's generated by Visual Studio, docu can produce an entire website of documentation with a single command.

Can I use it yet?

Yep, just don't expect the world. Docu has been tested against Fluent NHibernate and is currently in production use; however, it's only been tested in that one situation so there may be peculiarities of your setup that haven't been catered for.

What's so special about docu?

# One command to build your entire documentation # Static html, nothing fancy, no dependencies # Templates built using the Spark view engine # No GAC, no hard-coded paths; completely redistributable

Now what?

Either get the code or download the alpha, then take a look at the getting started guide. If you've got any comments or suggestions feel free to drop by the mailing list.

Getting started

Have you downloaded a binary or built the source? Good, we can continue. For this part of the guide I'm going to assume you're perfectly happy with the default appearance of the documentation (which is similar to the standard rdoc style), so I'm only going to cover how to actually produce the documentation.

Docu is comprised of a small console application with a templates directory; this directory contains all the Spark views that are used to build your documentation. These two need to stick together where-ever you put docu, but apart from that it doesn't care where it lives.

To generate documentation with docu, there are two things it needs: at least one assembly and it's associated XML documentation file that's generated by Visual Studio. You need to supply docu with the locations of the assembly (it can discover the XML file if it's in the same directory as the assembly) from the command-line. When you start it, docu interrogates the XML and the assembly to build up your documentation.

Running Docu is easy. Just run docu your-assembly-name.dll from the command-line and you're away. Currently your documentation will be put in an output folder in where-ever you ran docu; this will be customisable, but isn't just yet. So running the above command will result in the following console output.

----------------------------------------
 docu: simple documentation done simply
----------------------------------------

Starting documentation generation

Generation complete

With that, you'll now have an output folder with several html files and folders. This directory is fully self contained so you can zip it up and ship it out to anywhere without any concerns about external references. That's it, that's all there is to using Docu.

Customising Templates

Docu uses the Spark view engine to produce it's pages, which makes customisation really easy. You can use loops, conditions, include partials, write macros, and even use plain C# in your views if you so desire. It's important to note that docu's support for customisation is unpolished, there's very little you can't do, but what you can might not be the silkiest yet. I'm working on it.

Special names

A very simple feature of docu, but one that's extremely useful, is special names. There are a few (currently only two!) special names that you can call your files and folders that mark them for special treatment by the docu processor. For example, if you call a file !type.spark then when it's used for generating the docs, docu will create a new page for each type in your assembly using that template; so if you have 10 types, then docu will create 10 pages from that template, each with only that specific type in.

The currently available special names are: !namespace and !type.

These names can also be applied to directories, and are scope limiting. If you create a directory called !namespace, you'll get a new directory for each namespace. Any templates inside that directory will be created for each namespace too; so, if you create a !type.spark template inside a !namespace directory, you'll end up with a directory for each namespace, with a page for each type in that namespace. Very simple, but pretty powerful.

It's important to note that namespaces are not considered to be in a tree as you might expect. The .Net CLR flattens all namespaces, so if you have the namespace Example with a sub-namespace called First, what the CLR actually stores is two namespaces: Example and Example.First, not Example with a child of First. Docu sticks to this structure for simplicity; this may, or may not, change in the future.

Template properties and helpers

Each template has access to several properties that it can use to output the documentation; these properties expose the underlying document model that is generated by docu.

Every template has access to: Assemblies, Namespaces, and Types; these each contain all their respective members for the whole of the documented codebase.

Templates that are of or inside the special name !namespace have a Namespace property that represents the current namespace you're "inside"; the namespace exposed has a collection of types that can be iterated over which has only the types that are of that namespace.

Templates that are of or inside the special name !type have a Type property that represents the current type you're "inside"; this property has several properties that can be used to generate the documentation. There's Type.Methods and Type.Properties that contain the public methods and properties of the type, as well as Parent and Interfaces properties that expose the base-class and any directly implemented interfaces.

The document model is under-developed and only contains what was needed to produce the basic documentation used by Fluent NHibernate; it's more than likely that there are features that are missing or not exposed. If there is anything that you need that isn't available, please post a message on the mailing list. An example from the default template (in !namespace/index.spark):

<div class="header">
  <p class="class"><strong>Namespace</strong> ${Namespace.Name}</p>
</div>
<div class="sub-header">
  <h3 class="section">Types</h3>
  <ul>
    <for each="var type in Namespace.Types">
      <li><a href="${type.Name}.htm">${h(type.PrettyName)}</a></li>
    </for>
  </ul>
</div>

You can see this template outputs the namespace name, followed by a list of all the types. You'll note the use of a h call and type.PrettyName. Well h is one of a few methods available to templates, this one in particular replaces < and > characters with their html friendly equivalent (it will eventually be a full html sanitizer, but it isn't there yet); PrettName on the other hand outputs the full generic name with all generic types resolved, if possible.

Some other methods that are available are:

  • OutputMethodParams(Method), this outputs a comma-delimted list of the parameters of a given method, handy to not have to do the comma processing
  • WriteInterfaces(IList) does a similar thing but for the interfaces of a type
  • WriteSummary(Summary) writes out the summary comment of a method/type with all types fully expanded and internally referenced if possible
  • WriteReference(Reference), resolves a documentation reference (which could be a method parameter, a return type, or just a block from a comment) and either outputs a simple text representation if it's an external reference, or a link if it's part of the assembly being documented.

A note on comment blocks: XML comments can be simple text, or a complex hierarchy of XML tags. Due to this, there is no flat representation of a comment; comments are always a list of IComment instances. Each instance can be output in a different way, hence why it's a good idea to use WriteSummary.

These methods are not exhaustive and are pretty underdeveloped and overly specific. They will be changing in the future to a more managable structure, but for the time being most things can be catered for.

Transforming templates

A template is discerned by it's extension, .spark; any files that have that extension are transformed into a .htm file at generation-time, with the exception of any files beginning with an underscore (these are deemed to be partials and are left alone).

Any directories are recursively evaluated for templates, if they contain any the they will be copied to the output directory; similarly any untransformed files that aren't spark templates will also be copied (such as css files).

As already explained, any templates or directories that have a special name get transformed into multiple html files and folders depending on their name.

So given the following directory structure:

templates/
  !namespaces/
    !type.spark
    index.spark
  css/
    main.css
  index.spark

Combine that with an assembly that has two namespaces (First and Second respectively) each with several types, you will see the following output:

output/
  First/
    TypeOne.htm
    TypeTwo.htm
    TypeThree.htm
    index.htm
  Second/
    TypeFour.htm
    TypeFive.htm
    index.htm
  css/
    main.css
  index.htm

That's it, that's all I can think of right now. Watch out for badly formed templates because exceptions are mostly unhandled currently. Big bang. Drop by on the mailing list if you need any help.

FAQs

What is a docu? A documentation generator for .Net that isn't complicated, awkward, or difficult to use.

How mature is docu? Not very, it's only a few days old; however, it is capable of producing the docs for Fluent NHibernate, so you might be ok with it.

Can you produce such-and-such format? Most likely not, unless the format you want is html. Docu is meant to be simple, and it's designed to do one thing and one thing well. If you want a CHM generator, or a Word doc generator, then you need a different tool.

What styles do you have available? Only the default rdoc inspired style currently, but there is a customisable template system that you can use to produce your own templates, and there are plans to extend the default set of templates in the future.

Can I output private/protected members? Not yet, docu was designed for use with a public API and thus didn't need to expose private members. It will be a customisation option in the future, but it isn't implemented yet.

What's wrong with Sandcastle? Nothing, if you like pain. I don't.

Something went wrong with that request. Please try again.