How to Develop a Smart Angular Doc App
Right now I am developing an Angular Application that is based on a library that will contain all UI-Elements used in multiple projects.
As you can imagine, it can be difficult for different teams to use the same base of UI-Elements without a good documentation of how things work.
Therefore I have tried multiple tools like compodoc that generate API Docs from an Angular app/library. But since none of them were exactly what I was looking for, I searched for other ways to simply show the code of an example as well as the example itself rendered — and all that WITHOUT code duplication.
Since I am now writing this article you can assume, that I have found a way 😉.
So first let me show you the result of what I achieved.
The idea
I wanted to write the code for examples only ONCE and the component should update the code-snippet and the example-view without further need of modification.
The code-snippet should be visually appealing to the user and use syntax highlighting and right indentation.
How to
Let’s jump right into the code.
Let me start with the component wrapping most of this logic:
As you can see the component itself is very simple. It has some styling and uses some inputs for the data. The variable code
should contain the code to be display as it is without being rendered. The variable components
can have an array as input of all those components, that should be displayed in the api tab \o/.
As you can see, the template itself is very simple. It contains a tab-group component with some tabs. The component to be rendered, specified by our buttonDemo
constant below gets projected into the ng-content
and gets printed within a pre-tag in the code-tab. At last, I included a third tab, that uses an own component to display the api.
The interesting part now, is how to use this component. As I said earlier, I wanted to prevent code duplication. To do that, the developer now only has to create a multi-line-string variable that is not in context of the component itself.
So let’s create a new file called demo.ts
that contains the following:
To now use this small template, we create a component called ButtonDemo
. Here is the code:
The created constant buttonDemo
is imported and declared to a local variable buttonDemo
. In the template I use the exampleView
component created earlier and give the code-input the local variable buttonDemo
and the template itself the exported constant buttonDemo
. That will make sure that on the one hand the template can be rendered as intended and on the other hand that the input of the exampleView
is set correctly.
So again let’s see the result:
But wait… how do we get that API tab?
I told you earlier, that we have the DocViewComponent. This component parses the relevant parts of the documentation file created by the library typedoc. It takes only one input: An array of strings representing the component-names of those components to be present within this tab.
Again: Here is a gist with this component. This time, the gist is way bigger.
So what excactly happens here?
Well first, we have the documentation parser service. This service loads the generated documentation-file from typedoc and parses it into the _docFather
variable. You can find the different datatypes here. It also provides functionality to walk through the tree and search for one specific component.
Then we have the component itself. It has some helper functionality to sort the component-docs variables into different arrays of object. For example we have the accessors
or properties
. Those then get displayed in the html file of the component. Thats basically the magic.
To create the documentation with typedoc, I added the following script to my package.json which gets calles before each build-command:
"doc": "rimraf typedoc && rimraf doc/doc.json && npx typedoc — out typedoc src/lib — json doc/doc.json — module commonjs — excludePrivate — mode file"
The End
I hope you could enjoy this article ❤