Building a table of contents with DITA versus Jekyll
In my ongoing series comparing Jekyll against DITA, I want to touch on how you construct a table of contents.
Creating a TOC with DITA
The ditamap file in DITA is arguably the most important file in a DITA project, and it has a lot of features. Basically, the ditamap defines the table of contents for the project, which is how users navigate all the files (apart from search).
Additionally, any file that you want included in your output must appear in your ditamap file. Otherwise it's excluded from the build.
A project can have multiple ditamap files. You might have separate ditamap file for each output, or you could use the same ditamap file with conditional tags for multiple outputs.
In the ditamap file, you reference each topic you want included like this:
Notice how you can add attributes to the
topicref elements. Here, if the build conditions exclude the field engineer audience, the inline_links.dita topic will be excluded.
Additionally, hierarchy is established by nesting the elements. If you want to create sublevels, you nest the topics like this:
Here the inline_links.dita topic will appear in a sublevel below keyref_links.dita. Similarly, relationship_tables.dita will appear nested below related_links.dita.
You can combine topics if you use the
chunk attribute, like this:
Now the inserting_links.dita topic will contain inline_links.dita, related_links.dita, and keyref_links.dita files as additional sections in the same inserting_links.dita topic, rather than appearing as separate files.
If you want to include any non-DITA files, you would list them in the ditamap with a special
For more details on ditamap files, see my page on ditamap files.
Creating a TOC with Jekyll via categories
Jekyll provides a lot of different ways to create a TOC. Since many Jekyll sites are blogs, more emphasis seems to be given to post sorting than page sorting, but Jekyll also provides an interesting paradigm to handle the TOC for pages.
You have at least two main options for create a TOC. You can add a category and weight as frontmatter in your page, and then run
for loops to sort the content based on the category and weight.
If you want to sort pages by category, you would put a category in the frontmatter of a page, like this:
You could then use a for loop to get all pages in this category sorted by weight:
This approach may get tedious, though, especially if you want to easily shift and arrange your TOC without opening every single page to change these frontmatter values.
Creating a TOC in Jekyll via data files
Another approach, and the one I'm currently using, is to list your TOC entries in a YML data file. Here is the typical structure of a YML file containing TOC entries. The YML syntax emphasizes human-readable code, so a lot of the formatting is dependent on spacing:
Now the HTML code in your template uses a
for loop to iterate through each of these items and wrap them in the right formatting for your theme. Here's an example of how the template code might look:
When we start the for loop, what
sidebar refer and
buildAudience refer to is based on the assignments defined. These assignments depend on properties in the particular configuration file that's being used. (This is how the theme is separated from the content.)
for loop looks in the sidebar list and loops first through the items, and then the subcategories, iterating through each item in the list. Each item is wrapped in a link format. Additionally, only the items containing the
buildAudience attributes are included in the list. (This
buildAudience element allows us to single source the data file, using the same data file for multiple audiences.)
You can get more fancy with the sidebar formatting, such as showing active links and more. But this shows the basic logic. My intent here is not to explain the code in detail but rather to give you a glimpse of how to build a TOC in Jekyll.
Note also that the logic seems more complex here, but I've taken the explanation one level further than I did with DITA. With the DITA TOC explanation, I didn't get into how the Open Toolkit (OT) processes the ditamap file to render it into HTML and other outputs. I actually have no clue how the OT does the processing -- that's usually a behind-the-scenes process.
With Jekyll, though, once you understand how
for loops iterate through items in a YML list, it's fairly accessible to configure how the TOC items get processed.
One important difference with Jekyll is that all content is included by default, whether it appears in the navigation or not. If you want to exclude content, you must list it in the Excludes property in your configuration file.
Multiple types of navigation
The ditamap structure tends to break down when your content resembles more of a knowledge base than a user guide. Because you can't tag pages or add pages to specific categories, about the only way to add DITA files to a knowledge-base-style output is by creating an enormous TOC or by not creating a TOC at all, but instead just relying on search.
In contrast, with a Jekyll project, I could create both a TOC-style navigation for hierarchical content, and a tag-based navigation for knowledge-base style content.
Dynamic assembly of content
One strength of DITA is the ability to dynamically assemble larger topics from smaller ones, but this might also be seen as a weakness. In OxygenXML's webhelp output, if you use the
chunk attribute to glue a topic together at build time, you can still find the individual chunks in search (they're only glued together in the TOC, not physically in the file contents).
These individual chunks are problematic -- they don't make much sense out of context from the larger topic they were chunked into. (You might think the chunk attribute permanently glues them together, but that magic only happens in the TOC.)
Additionally, if you have a relationship table in a "chunked" topic (meaning a topic that is dynamically assembled through the
chunk attribute), the relationship table appears (oddly enough) after the first chunk, and then the other sections appear (see this post for more detail).
This odd behavior of the Open Toolkit is necessary (I think) so that the relationship table can appear at the bottom of the all the individual chunks that don't appear glued together in the TOC topic but rather surface independently, for example, through search.
If you're going to include a topic in another topic, there's no reason not to use a conref from within the topic itself, or if using Jekyll, to use includes from within the topic.
Overall, I hope to have shown that Jekyll provides some robust options when it comes to creating your table of contents. What's especially important is that the TOC content is not merged into the theme in a tight way. Content is separated from format (stored in a data file) and merged together at build time with your theme's template.