yelp-build: link to pages in another directory?

Shaun McCance <shaunm at gnome.org>
Mon Apr 27 10:45:32 EDT 2015

Hi Jesse,

I'm going to CC mallard-list. I think this is generally interesting to
Mallard folks. Answers inline below:

On Sun, 2015-04-26 at 17:10 -0400, A. Jesse Jiryu Davis wrote:
> Hi Gnome folk,
> 
> 
> I'm taking over a project, the MongoDB C Driver, that Christian
> Hergert documented in Mallard. It builds with yelp-build. The
> documentation is split into two directories, one here:

> https://github.com/mongodb/libbson/tree/master/doc

> And the other here:

> https://github.com/mongodb/mongo-c-driver/tree/master/doc

> Pages in the latter directory include references to pages in the
> former. (But not vice versa.) We build each directory with a separate
> invocation of "yelp-build html <directory>".
> 
> 
> THE PROBLEM: when a page in the "mongo-c-driver" directory reference
> pages in the "libbson" directory, our current build system doesn't
> make correct HTML links. For example, the "bson_error_t" link here:
> 
> http://api.mongodb.org/c/current/mongoc_collection_update.html
> 
> 
> 
> ... tries to link to a bson_error_t.html page in the *same* directory,
> instead of to the proper page here:
> 
> 
> https://api.mongodb.org/libbson/current/bson_error_t.html
> 
> 
> 
> Since the link is wrong, it's a 404, which on our particular server
> means you're redirected to the home page. People rightly call this a
> bug in our documentation: https://jira.mongodb.org/browse/CDRIVER-524

Right. So Mallard, at its core, is about creating documents, where a
document is a collection of pages. Cross-references are links inside a
document. Linking to other documents requires something else. You would
have the same issue with DocBook or anything else document-based.

> I tried just putting the two invocations into a single one:
> 
> 
> $ yelp-build html libbson/doc mongo-c-driver/doc
> 
> 
> But that munges all the documentation together badly, instead of link
> from one to the other. Here's the output of that:
> 
> 
> http://emptysqua.re/merged-libbson-libmongoc-docs/

Doing this, you're effectively making a single document that contains
all the pages from two directories. 

> How can I tell yelp-build to take a reference from a file in
> "mongo-c-driver/" to an id in the other directory, like
> "bson_error_t", and render it as a URL like
> "../libbson/bson_error_t.html"? Instead of what it does right now,
> which is render a link to "bson_error_t.html" in the current
> directory, where no such file exists.

I can think of three options:

1) Just use hrefs.
2) Create an xref extension.
3) Use Pintail.


1) Just use hrefs. If you know where your docs are published, and you
only care about them being published in that one place, then just use
the href attribute to give an honest-to-goodness URL:

<code
href="https://api.mongodb.org/libbson/current/bson_error_t.html">bson_error_t</code>

This is very straightforward if it fits your needs, but it has no
flexibility in terms of where things are published or viewed. This
wouldn't work well in GNOME, for example, because docs are viewed both
locally in Yelp and online.


2) Create an xref extension. Any xref that contains a "/" or ":" is an
extended xref in Mallard. So you could do something like:

<code xref="mongodb:libbson/bson_error_t">bson_error_t</code>

You'd have to provide an implementation for that, of course.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template name="mal.link.target.custom">
 <xsl:param name="node" select="."/>
 <xsl:param name="xref" select="$node/@xref"/>
 <xsl:if test="starts-with($xref, 'mongodb:')">
  <xsl:variable name="ref" select="substring-after($xref, 'mongodb:')"/>
  <xsl:text>https://api.mongodb.org/</xsl:text>
  <xsl:value-of select="substring-before($ref, '/')"/>
  <xsl:text>/current/</xsl:text>
  <xsl:value-of select="substring-after($ref, '/')"/>
  <xsl:text>.html</xsl:text>
 </xsl:if>
</xsl:template>
</xsl:stylesheet>

Put that in a file and pass it to yelp-build with -x. (Warning: I did
not test this code.) This can be nicer to type, and is more flexible.
For example, if you want to publish to a staging server, you can edit
the extension stylesheet to reflect that. This is exactly what GNOME
does in Yelp to let you link to local documents with help: xrefs.

You could even provide both these xrefs and hrefs, like this:

<code xref="mongodb:libbson/bson_error_t"
href="https://api.mongodb.org/libbson/current/bson_error_t.html">bson_error_t</code>

When you build with your extensions that understands mongodb: xrefs,
those will be used. But if I grab your docs and build with vanilla
yelp-build, href will be used instead. You lose the ease-of-typing, but
gain portability. 


3) Use Pintail instead of yelp-build. yelp-build gives you a reasonable
amount of power to plug into it, but it's meant to be a fire-and-forget
single-document builder. Pintail, on the other hand, builds entire sites
of multiple Mallard documents. (It could potentially build documents in
other source formats, with plugins.)

https://github.com/projectmallard/pintail

Pintail lets you references pages in other directories ("documents") by
putting slashes in your xref.

<code xref="/libbson/current/bson_error_t">bson_error_t</code>

Just as with the previous option, you could use both xref and href to
have better portability with tools that don't support the extended
xrefs.

<code xref="/libbson/current/bson_error_t"
href="https://api.mongodb.org/libbson/current/bson_error_t.html">bson_error_t</code>

Again, portability vs ease-of-typing. The nice thing is that you can get
all the goodness of inside-document xrefs, like automatic link text and
tooltips. You could pull that off with option (2), but with considerable
effort that the small extension stylesheet I provided.

Pintail is still pretty early in development. There are surely kinks.
But it is being used today to build projectmallard.org (and, in fact,
conf.openhelp.cc, because why not).

--
Shaun