Mastering Volatile Docs Through Automation
Tags: documentation, automation, vue, storybook
Published: 2020-02-16 17:18:10

# Automating the Impossible

_You use automation in CI builds, packaging etc. – why don't you use it for keeping your docs up-to-date?_

Being highly individual, docs aren't the first thing coming to mind as candidates for automation. At the same time, writing docs and keeping them up-to-date takes a considerable amount of time and hence teams would profit a lot if at least parts of a project's docs could be generated automatically.

Let me share our experiences we made at _Storefront UI_ with the auto-generation of our components documentation.

## 📖 Docs are Important, Obviously

With today's surplus in tools, libs and software, documentation becomes an important factor: Good documentation is key for many developers for choosing a framework or library in the first place. Knowing _what_ to use _when_ and _how_ (and _why_ not something else) is the bare minimum of information you need in any docs.

But there is more: A major point for frustration is a docs page with **outdated** information, **errors** or **typos** in syntax sections or examples. Users of your software heavily rely on your docs—oftentimes even more than you as the author might think. Keeping them

* 🆗 correct,
* 🆕 up-to-date and
* 🔤 as approachable as possible

is what you should aim for.

## 🤖 Automation is Helpful, Definitely

All too often on the other end of the development cycle you'll find automation. Automating image optimization, builds, the whole Continuous Integration/Deployment pipeline, test runs and similar monotonous, repetitive tasks, seems rather obvious. In fact, everything that requires minimal to no human intervention is a perfect fit for programmatic automation. New and old tools and (online) services help with each and every angle you might want to—and should!—outsource from you and your team and lay in the hands of computers.

The initial efforts necessary for setting up such scripts almost always pay off in the long run. Not only because the time you save in the process adds up but also because (as long as the predicates of your automation scripts don't change) the outcome stays error-free; something most humans cannot achieve.

## 🤖 + 📖 = 💟 ❔

_But how can you automate documentation?_
Normally, documentation consists of several parts, with some having an explanatory character and being prose, while others strongly relate to code. Hands down, the former is currently almost impossible to automate. Let's take a look at the latter though: Examples for such code-related docs sections include:

* the API
* code usage examples
* general lists of available components inside the software
* extracts of comments from inside the source code
* constants, enumerations
* file locations and relevant directories

We can see that these parts are perfect candidates for automation! They themselves follow a rather strict convention and are therefore per se programmatically extractable. E.g. we can introduce a new build step for our documentation which gathers facts from the actual source code and maybe more information derived from the general directory structure and the presence/absence of files.

### Examples

If you are maintaining docs for a library or any software containing components, you could traverse the structure of your components' locations and collect the components you are passing by.
Maintaining such a list by hand, i.e. updating it whenever a component is added, moved, removed, drastically altered, works only for so long. At some point, you or a team member _will_ introduce discrepancies.

Going further, the source code itself serves as a rich source of information for your docs. In many cases, components and fields in your code already are annotated with an important type of documentation: comments. By extracted and implementing them in appropriate parts of your final docs, you generate an always correct reference for your software. As soon as a code part leaves your source, it is automatically removed from your docs, keeping your users from confusion.

## How We Automated Our Docs at _Storefront UI_

_Storefront UI_ is an open-source component library with far-reaching customization options and as such it depends on good docs as the main entry point for future and as a reference for current users.
When I joined the Storefront UI core team last summer there were exactly three (3!) components (somewhat) fully documented. To be clear, this was no oversight of the team but simply due to the fact that the team efforts were focused on pushing the (at that time alpha-state) library with features. Having seen my fair share of projects, I was part of this situation more often than not.

Meanwhile we introduced several techniques that help us automate our components docs:

1. By traversing the directory where all our components reside, we gather a full list of all available components, including their name, their type (w.r.t. the Atomic Design types), accompanying files (e.g. styles, tests) and whether it has internal components which need to be indexed and listed, too.
1. If a component has a related Markdown, we extract its text and fill in placeholders in the final docs page with that content. This allows for prose, additional information which the automation itself cannot deliver. We use that mainly for a general description of the component.
1. In order to provide a list of SCSS variables and modifiers for each component, we also parse the corresponding SCSS files and extract those pieces of information via RegEx.
1. Storefront UI uses Vue slots as a customization option, enabling users to easily mount custom parts into our components. These slots and their variable bindings, as well as events and the component's `props` are extracted by relying on the parsed output of _[VueDocs](https://www.npmjs.com/package/vue-docgen-api)_. This saves us from parsing and evaluating Vue files ourselves. We also extract all code comments and reuse them in the generated docs for the events, slots and props found in this process. This includes default values and type specifications. Our contributors know that by using comments in the source code not only do they contribute to more readable and documented code but also already to the final docs!

With these changes alone we were able to deliver useful docs for all our components.

But—quoting [Inception](https://www.google.com/search?q=inception+we+need+to+go+deeper)—

> **we need to go deeper.**

_Storefront UI_ includes _[Storybook](https://storybook.js.org/)_ as another way to see our components work. Each "story" of a component already includes the source code needed to implement the behavior and appearance you see in the preview panel. _Why not use that for the docs, too?_

We managed to parse Storybook's _.stories.js_ files in a way that the result is usable as example code snippets for our components docs. Each so-called _knob_ in a story is transformed into a Vue `prop` with an appropriate type, with its `data` value being simply the Storybook knob value.
With only a little of sanitization of imports and the like, we end up with a clean usage example for a component with only one source of truth (in this case in the Storybook file) but with two output formats, always as up-to-date as the component itself and the storybook file.

_Storybook "Story" Syntax Example:_
![Storybook "Story" Syntax Example](https://dev-to-uploads.s3.amazonaws.com/i/io1rw1wymqy3aoki1aga.png)

_Result of a Rendered Component with Functional Vue Syntax:_
![Result of a Rendered Component with Functional Vue Syntax](https://dev-to-uploads.s3.amazonaws.com/i/64k2p9j1f4gh5mxa54mi.png)

The same generation process takes care of another feature for our docs: For our users' convenience we also include (via an iframe) our demo components from the the Storybook into the component's docs, fully rendered and interactive.

This way, our user have all the information they need for a specific component in one central place, most of it auto-generated (🤖):

* The component name (🤖)
* a short description of its main purpose
* a Most Common Usage section (🤖)
  * with a rendering demo (🤖)
  * and the full code needed for that demo to work (🤖)
* the component's `props` (🤖)
  * with the source code's comments attached to this prop extracted (🤖)
  * with each prop's `type` extracted (🤖)
  * and the `default` value extracted (🤖)
* the component's `slots` (🤖)
  * with each slot's code comments extracted (🤖)
  * and its `binding` extracted (🤖)
* the component's `events` (🤖)
  * with each event's code comments extracted (🤖)
  * and its event name/value extracted (🤖)
* the component's CSS modifiers (like `--large`) (🤖)
* the component's SCSS variables used for customization (🤖)
* the component's inner components (e.g. Tabs in a TabBar) (🤖)
  * with their props, slots and events also included (🤖)
* and a link to the component's Storybook for further example usages (🤖)

As you can see, the only part needed to be written manually for each component is the short description. For that we have the aforementioned markdown file next to each component which is parsed and included at the appropriate spot in the final docs.

## Wrapping up

Many projects have several sources for their documentation. Often these pieces get copied, extracted and included somewhere else manually. By taking advantage of automation for your docs generation you can accelerate this process and improve your docs' quality and freshness at the same time. Try to identify these sources and consider the best place to store the information _once_ (code? tests? demo files?) and use it for your docs.
Writing helper scripts and robust RegExes to extract, transform and combine everything can be challenging but often an investment into your project's future.

_____

**_If you have any question ❓, suggestions 💡 or rants 📣 feel free to get in touch!_**

_____

For more information about _Storefront UI_, see our repo:

{% github DivanteLtd/storefront-ui no-readme %}