Wednesday, March 28, 2012

Link to External Dart Documentation

‹prev | My Chain | next›

As pointed out to me by Michael Haubenwallner, my dartdoc tweaks still have a bit of a gap in them. When I removed the core documentation from the output, I neglected to point links to the core documentation at api.dartlang.org.

The dartdoc output is pretty slick. It does a very nice job parsing my code and generating basic docs. Eventually, I need to add some details, but the type information alone makes for a good start:


The problem, of course, is the link to List. I want this to be public documentation on the GitHubs, but the most up-to-date information on List is always going to be at api.dartlang.org/dart_core/List.html, not whatever version of Dart I happened to have installed when I compiled the documentation.

The output from dartdoc is something along the lines of:
<h4 id="get:routes">
  <span class="show-code">Code</span>
  <a href="../dart_core/List.html">List</a>
  <strong>get routes</strong>() 
  <a class="anchor-link" href="#get:routes"
     title="Permalink to HipsterRouter.get routes">#</a>
</h4>
Instead of the relative URL "../dart_core/List.html", I need the api.dartlang.org version.

The easiest thing to do would be to jam a conditional into dartdocs's a() function:
  String a(String href, String contents, [String css]) {
    // Mark outgoing external links, mainly so we can style them.
    final rel = isAbsolute(href) ? ' ref="external"' : '';
    final cssClass = css == null ? '' : ' class="$css"';
    return '<a href="${relativePath(href)}"$cssClass$rel>$contents</a>';
  }
But both a() and its dependent relativePath() have checks for absolute paths. Best to keep these functions doing one thing rather than expanding their responsibility.

This means that the calling context needs to supply the necessary absolute, api.dartlang.org URL. Rooting through the dartdoc source, it seems that typeUrl() is the place that I need to check:
// ...
    write(a(typeUrl(type), type.genericType.name));
// ...
Indeed, I need only prepend a path to the return library as necessary:
  /** Gets the URL for the documentation for [type]. */
  String typeUrl(Type type) {
    String library = sanitize(type.library.name);

    // If limiting docs to libraries containing a substring, then point all
    // other docs to api.dartlang.org
    String path = type.library.name.contains(contains) ?
      "" : "http://api.dartlang.org/";

    if (type.isTop) return '$path$library.html';
    // Always get the generic type to strip off any type parameters or
    // arguments. If the type isn't generic, genericType returns `this`, so it
    // works for non-generic types too.
    return '$path$library/${type.genericType.name}.html';
  }
With that, I have my api.dartlang.org URLs for core types:
<h4 id="get:routes">
  <span class="show-code">Code</span>
  <a href="http://api.dartlang.org/dart_core/List.html" ref="external">List</a>
  <strong>get routes</strong>() 
  <a class="anchor-link" href="#get:routes"
     title="Permalink to HipsterRouter.get routes">#</a>
</h4>
But, by virtue of containing the supplied string ("hipster" in this case), my actual library documentation retains the relative URLs:
<h4 id="on">
  <span class="show-code">Code</span>
  <a href="../hipster_router/RouterEvents.html">RouterEvents</a>
  <strong>on</strong>
  <a class="anchor-link" href="#on"
     title="Permalink to HipsterRouter.on">#</a>
</h4>
I am reasonably satisfied with that. I kept the a() function appropriately dumb. Similarly, the typeUrl() feels like a good place to determine whether or not a relative URL is proper. The contains(contains) is a little awkward, so I may have to reconsider the name. But not today.

After regenerating the API documentation for Hipster MVC, I have core types coming from api.dartlang.org and the rest coming from the GitHubs—even HipsterRouter (where the problem was originally noted).

Hopefully nothing else is missing: eee-c.github.com/hipster-mvc.

Day #339

No comments:

Post a Comment