In my last article, I talked about resolving some issues that were in the way of a clean release. In this article, I talk about getting the documentation cleaned up and ready for release.


One of the reasons that I started writing these articles is to talk about how the project evolved throughout its development. But equally as important, I wanted to get more comfortable with my skills as a writer. While I am not sure how much those skills have grown, I do feel that they have grown. And in this stage of the project, I know that I need to leverage those skills to write good, solid project documentation.

In my eyes, documentation can make or break a project. I have glanced over and dismissed many projects on GitHub after two minutes or less. I usually make that decision based on the base project document, the file, and whether that file made the project look interesting or applicable to what I was searching for. To be clear, I admit that it is entirely possible that those projects I dismissed were either interesting or what I needed. But without good project documentation to provide that information to me, the chance that I will find the right information to make that judgement call is a fraction of what it could be with good project documentation.

In other words, I have worked hard to come up with the PyMarkdown linter. It was time to use that same passion to document the linter so I can provide people with the information they need to make their own judgements.

Given my own personal high bar for documentation, I was under no illusion that this was going to be easy.

What Is the Audience for This Article?

While detailed more eloquently in this article, my goal for this technical article is to focus on the reasoning behind my solutions, rather that the solutions themselves. For a full record of the solutions presented in this article, please go to this project’s GitHub repository and consult the commits between 16 May 2021 and 23 May 2021.

Coding Vs Documentation

While this block of work did contain a few small tweaks here and there, the bulk of the work was on getting the documentation ready for release. And if I may be blunt, there is a large difference between writing code and writing documentation.

In creating the PyMarkdown project, there were a lot of times that I was not sure what the next task to do was, so I referred to my Issues List. If I was not sure about whether or not something was in scope, I referred back to my article on Collecting Requirements. If a particular Markdown snippet was not covered in the GFM Specification, I would run the sample through the Babelmark webpage. Before anything gets committed to the repository1, I execute a script that ensures that I am following good coding practices, reformatting my code in the process. And to top things off, because I love Test Driven Development, I add the Scenario Tests for everything before I code them up. This provides an additional level of structure to how I develop features or fix bugs.

And that is the point I wanted to get across. When I am writing code, there is a lot of structure all over the place. From picking something off the Issues List to running my pre-commit script, there is tons of structure built into the processes that I use to develop software. In the cases where I sometime forget to follow a given process, that process or other processes that I have are able to cover for that lapse of process. Sure, it is redundant, but it works well for me.

So, when I started going through the documentation to bring it up to the level that I thought it deserves, I wanted to follow procedures like the ones that helped me develop the source code side of the project. The question was, how was I going to do that?

Starting With Requirements

Even though I wrote it over a year ago, I still credit the creation of the section What Are The Requirements? with its fair share of the success for the project. By taking the time to sit down and figure out what I wanted and recording that in a format that I could easily reference, I did myself a huge favor.

That act of creating the article gave me a solid touchstone that I still refer to for guidance. Especially with the summary paragraph after that list detailing why I thought those requirements were important, it crystallized what I wanted to do with the project into a bedrock set of concepts that I can rely on.

Doing The Research

In my attempt to replicate the success of my coding effort with my documentation effort, I knew that I needed to dig deep and figure out what I liked and did not like about various project home pages out there. The things that I liked, I wanted to replicate, the things that I did not like, I wanted to avoid.

So, like always, I started to research. While that can also read as “Jack looks at websites”, it was not really that easy to do. I went to the Cool GitHub Projects sub-reddit and started to look at different GitHub projects. That process helped me to formulate my first requirement.

Requirement 1: Why Should I Use This Project?

The first thing that really struck me about different projects was how far each project made someone read until they could figure out whether the project was right for them. In many of the projects that I looked at, instructions on how to install the project preceded an attempt to answer that question. That is in the approximately 60% of the projects that provided any attempt at that answer. To me, the absence of any answer to the question of “why?” did not make sense.

That was when I focused on what this requirement meant to me. The first thing that the successful answers to that question did for me was to present the reader with a short introduction paragraph at the start of the file. Those projects presented a good, simple paragraph to allow the reader to determine if the foundational elements of the project met their criteria or not. If it does not meet their needs, no harm, no foul, only taking up the minimum amount of time needed to help the reader figure that out.

If their criteria were met, the next part of that section needed to provide information to the reader on why that project is better than other similar projects at accomplishing their task. At this point, the reader is hooked and wants to learn more about the project. I did observe that the good projects provided readers with a good selection of bullet points about the project. It did not need to be anything heavy, just enough to convince the reader that they the project is serious and encourage them to read on.

It’s Essentially An Elevator Pitch + Conversation

Basically, to use business terminology, I needed to prepare an elevator pitch followed by a two-minute conversation. Getting the reader into the “elevator” was them getting to the project website in the first place. I then had between three and five sentences while they are “in the elevator” to either gain their attention or to have them politely decline. If I gain their attention, I then have a quick “two-minute conversation” with them to convince them to talk about it some more before they continue on to where they were going. Anything more than that is imposing on them, which will negatively affect their interest on your conversation.

While this may not seem accurate to some, I encourage readers to try this experiment for themselves. Go to the Cool GitHub Projects sub-reddit, and look for three cool projects to get interested in. Pay attention to how much reading you do of the project documentation, knowing that I have asked for three projects to be selected.

If you follow the norm, you want to do a thorough job, but you also want to be efficient. You want the information that helps you make that decision up front as much as possible. You want the most relevant facts laid out in plain language so you can easily digest them.

If the reader is still paying attention, it is then time to take them to the next step: the test drive.

Requirement 2: How Can I Take A Test Drive?

I hope that I do not sound like a used car salesman, but the mindset that I had when getting past the “Am I Interested?” part was pretty close to what I have experienced buying a car. Assuming that I was interested enough in the GitHub project to spend time trying to get it working on my machine, I needed a quick and easy way to install it and verify that the simple case works.

To be blunt, when I try out a GitHub project, I just want to see any result, no matter how simple. Fine tuning and more complex cases can come later. I know that if I cannot get a quick confirmation that the project works on my machine in the simplest case, I know that the more complex cases are already a no-go. Essentially, I want to “kick the tires” and “take it out for a spin” and see if it works as advertised. If not, I want to move to the next project on as quickly as possible. Depending on my interest in a project, I might be willing to ask one or two questions, but that is usually the limit of what I am willing to invest in an, in my mind, unproven project.

For the PyMarkdown project, that meant adding a couple of different sections. The first section was the Requirements section to specify that the project needs Python 3.8 or later to function. While I do not find version 3.8 or higher to be a deal breaker, some people might, so get it out of the way quickly. Following that, I want a simple Installation section with as few steps as possible. It does not have to install and parse everything, but it does have to install and parse something right away.

I then want to follow that up with what I see as the “Test Drive”. For me, this section is the How To Use section, teeing up the execution of the simple case that is going to show the project working. Keeping the car analogy in place, if I am driving an unfamiliar car, I want to know where everything is in case something goes wrong during the test drive. That led me to add the If You Get Stuck section to help the reader with the help functionality.

With everything else already in place, I added the Prerequisites section to help set the stage for the test drive. Almost every time I have test driven a car, the salesman will set expectations for the drive and how it will proceed. For the project, this section provides two slightly different examples of Markdown text, one that emits violations and one that does not. These examples were not very complicated, but just complicated enough to show the project working properly.

Finally, with everything else set up, it was time for the test drive. This meant adding the Basic Scanning section to allow the user to test the project. This section has only two goals. The first is to show the PyMarkdown linter working against the example files created in the Prerequisites section. The second is to provide sample output to allow the user to verify that everything is installed and working properly. Nothing more, nothing less.

For me, this was the path to making sure that the reader can get the project running on their system. And I believe that the documentation will get the reader to that same point as quickly as possible. Requirement met.

Requirement 3: Turning It Up To Eleven

Despite the various origin of the phrase “turning it up to eleven”, the meaning fit right into what I wanted to convey. At this point in the documentation, the documentation has captured the reader’s attention and (hopefully) those readers have the project installed and running on their system. This meant I needed to transition from showing the project working on a simple example to showing the project working on a more complex example. At the same time, I must strike a balance between presenting a more complex example and not overloading the reader and scaring them away. After some though, I determined that I needed to focus on between two and four of the most important features or concepts in this next step.

As the PyMarkdown linter has a solid set of features, I needed to find some way to reduce the list of features into that small set of features that I believe are the most important features to show someone who has just installed the project. Seeing as I have been with the project from the very beginning, this was no easy feat. I needed to try and remove my own biases and come up with no more than three features that I hoped were indispensable to most new users.

After scribbling down all the features, some patterns started to emerge. One very interesting pattern emerged when I started drawing lines from each feature to any other feature that it depended on. When all was said and done, there were three features or concepts at the center of everything else: rules and rule plugins, rule violations and their format, and the ability to enable and disable rule plugins.

It was at that point that I knew that I had the three sections that I wanted to focus on in the main file. As the main purpose of the linter was to allow rules be run against Markdown documents, the Rules section was an obvious starting section. From there, I felt it was important to relate to the user how any rule violations are reported and how to read them, which lead to my creating the Rule Violation Format section. Then, the Basic Configuration section was created to provide an introduction to configuration by showing the user how to enable and disable rules.

My goal for these sections was not to cover everything, but to specifically cover the basic concepts that a new user needs to get the project up and running effectively. With those bases covered, I had to make another decision: how do I deal with the remaining concepts about the project?

Going back to the GitHub projects that I thought did a good job on documentation, I was able to make another observation. Those projects were good at drawing a line between what to include in the main file and what to delegate to other documents. When I thought about it, the logic there made a lot of sense to me. Keep the file limited to the most important concepts, and delegate the other concepts to other files.

To that extent, I grouped the remaining concepts into 3 main groups: Advanced Scanning, Advanced Configuration, and Advanced Rule Plugins. For me, this struck a good balance because I was still able to show interested readers that there was more to the project, but at the same time, not overload them.

With all the main concepts addressed, there was just one requirement left to work on.

Requirement 4: Wrap It Up Nicely

At this point, if I have done my job right, I have gained the reader’s attention, they have at least a simple example running on their machine, and they have possibly played around with some of the more advanced stuff. For those readers who became users of the project, I needed to do one more thing. Wrap the file up in a nice package.

I do not mean “wrap up” in any dismissive way, far from it. But as someone who looks at various projects, if I have set it up on my own machine and invested time in verify that it works, there is one more thing I want to see. I want to see that the project is not abandoned and not going to go away overnight.

Basically, I want a couple of sections where I can ask questions and know what is going on with the project. I also want to know it is still going to be around in the future if I have any more questions or feature requests. It was time to try and help with those questions.

Dealing With Questions

The first section that I added to start addressing this concern was the Open Issues and Future Plans section. From my viewpoint, I want to know what open issues are present with a project that I am investing my time in, and I also want to know where the project creators plan on taking the project. After all, I need to invest some of my own time to get the project working for my needs. It helps for me to know if the creator’s directions are aligned with my needs or not.

From there, I needed to start answering questions that any users of the project had about the project. For me, that started with the When Did Things Change section that links to the file. For the most part, when I am looking posing questions about a project, over 95% of those questions are either about “how do I do X?” or “what changes?”. This section will hopefully help answer that second question for the users.

Then, if that user still has questions, the Still Have Questions? section points them to the Frequently Asked Questions (FAQ) document. While that document will not resolve every remaining question, over time it should answer the most asked questions before having them raised as more serious issues. While not perfect, if I invest time wisely into this document, it can reduce the number of questions being asked in other forums.

Assuming that the user still has a question after consulting the information in the previous sections, the Contact Information section is there to help them understand how to get in touch with the team. Even though that team is currently just me, I feel that it is important to be clear on what kind of contact the user can have with me and in what format. It is in this section that I provided a link to the GitHub issues tracker, suggesting its use for both bug fixes and feature improvements. Finally, if the user’s question is more centered around contributing to the project, there is a request to contact me to talk about it.

How Can Someone Contribute?

That brings me to the section with Instructions For Contributing. While this is still currently under improvement, I thought it was important to let people know that I welcome solid contributions that help the project along. I also know that after 18+ months working on this by myself, accepting any offered help is going to be a gradual process.

The Dull Stuff: Acknowledgements

After everything else was taken care of, the projects that really stood out to me were the ones that took the time to thank various people who helped the project, either directly or indirectly. Nothing important is ever developed in a vacuum, and the wise people talk about who helped them get to that point.

And to me, as I have said on other subjects, it just made sense. The people I talk about in the Acknowledgements section took time to help me out. The least I can do is say thank you in my own way.

The Outline

After all that research, this is where I landed:

  1. Why Should I Use This Project?
    1. Provide short paragraph to determine if the project is for them.
    2. Provide advantages this project has over other projects.
  2. How Can I Take A Test Drive?
    1. Provide required Python version and installation instructions.
    2. Provide details on how to get help if they get lost.
    3. Provide a simple, no frills example and show the project working.
  3. Turning It Up To Eleven
  4. Wrap It Up Nicely
    1. Dealing With Questions, Bug Reports, and Feature Requests
    2. How Can Someone Contribute?
    3. Acknowledgements

Filling In The Blanks

With the requirements sketched out and the sections laid out, it was somewhat easy to start filling in the blanks. To be honest, I was eager to get to work on replacing the placeholders I had in my mind with actual text.

First pass

My goal for the first pass was to get a good start on the file. It took me a while to get working on that. But once I started, I quickly gained momentum. As I thought of things to add to the documentation, I put them into one of two categories. If the concept fit into one of the three basic categories, I added it to the file and started filling it out. If did not, I made sure to put it in one of the other documents, knowing that I would get around to it in a subsequent pass.

And just to set things straight, yes, I initially added some extra sections to the main file. If I am being honest with myself, I believe that I thought it was more important to capture the essence of the concept I was working on while it was clear in my head. I knew that I was going to be making multiple passes through the documentation, so it would find its way to the right section of the right document by the end of the process.

Second Pass

As I focused my first pass on the main file, I moved my focus on the second pass to the other documents, more specifically the Advanced Scanning document and the Advanced Configuration document. While it may seem boring, I just kept my head down and worked on expanding the existing point form notes in each document into a full-fledged documentation section.

It was during the creation of that documentation that I looked at various parts of the project and found a couple of little issues:

- when scanning a directory, is it always recursive?
  - can have switch for recursion?
- make sure configuration versions of
  - --add-plugin
  --strict-config       throw an error if configuration is bad, instead of assuming default
  --stack-trace         if an error occurs, print out the stack trace for debug purposes
                        minimum level required to log messages
  --log-file LOG_FILE   destination file for log messages
- clean up
  pipenv run python --strict-config -s log.level=$#1 scan examples

It was nothing serious, but they were just inconsistencies that I was able to find by taking a wholistic look at the project through the lens of writing the project documentation. None of those issues were showstoppers, but it was still good that I caught them when I did.

I was confident that I could clean those issues up quickly, so I started doing a a reading pass through the documents, from start to end, looking for wording that I could change. My personal writing process is simply to keep on reading and editing the document until it feels right, so this was part of my normal process. As such, it was easy to go through the documents looking for things that I felt were out of place, and I made quick work of that task.

So, by the end of the second pass, I felt things were progressing nicely. Sure, I had some small issues to fix, and more revisions were surely on their way, but I had the bulk of the documentation written. The next pass, that was going to start to be more fit-and-finish work.

Third Pass

Not being one that likes having pending issues hanging over my head, when I started my third pass, resolving those found issues were my number one priority. Part of that was “scratching that itch” and part of that was logic. I was sure that I needed to add a new command line flag, and that was going to require new documentation. Might as well do that all at once.

After about two hours of work, those issues were all resolved, and with another hour of work, the documentation for the new recursive flag was also complete. From there, it was just a series of reading passes over the documents, each one looking for something slightly different.

The first one was a bit more fit-and-finish work, making sure that I was selecting saying what needed to be said in each section. Following that, the second reading pass was slightly different in that I was focusing more on selecting the right words to convey the ideas in that section. As I believe both of those concepts are important, that is having the right ideas expressed in the right place and using the right words to convey that idea, I wanted to take the time to distinctly focus independently on each one.

With more confidence that I had the right content and mostly the right words, I then proceeded to look through the documents for spelling and grammar errors. I am not 100% sure that I found all the errors, but I am confident that I found most of them. And for that pass, it was good enough for me.

Fourth Pass

This is how I could tell that I was close to the end of writing the documentation: I was fiddling over the words and the ordering of sentences. It was a familiar feeling. It is something that happens each week as I write my article, so it was an easy sign to spot. I knew that I could probably spend years trying to find the perfect combination of words, so I knew I had to stop there. It took a bit of effort, but I stopped editing the documents.

And That Leaves Me…

At least for now, I stopped. Now that I have a finished code base and finished documentation, I want to give it all a couple of days to sit before I run some extra tests and reread the documentation. I do not expect any of the tests to fail, but I want to run them to be thorough. Just to be sure.

I also do not expect any changes to the documentation, but I want to give the documentation at least 48 hours to clear out of my head before I look at it again. While my weekly articles are written more directly and in a shorter duration, all the other articles that I write get the same mandatory 48 hour cool down period before my final pass. I am not sure if it is thoroughness or paranoia, but it is my process. I just feel better knowing that I did my final documentation pass with a clear head, hopefully removed from all the changes and prior versions of the documents.

And where does that leave me? Unless there are any very stunning things that I find, it means there is a good chance that I can do the initial release this week!

What Was My Experience So Far?

It was a long time getting to this point, but I was here. From experience, I knew that I wanted to leave the project alone for a bit to clear my head, but it was difficult. I have spent a lot of time cleaning things up, and I wanted to just take that extra step across the finish line.

It was aggravating to stop, but I knew I had to. I knew that I need to be objective and clear in my decision that everything looks right, and I cannot do that until I clear my head. Yes, I am annoyed at myself, but I know it will pass.

After all, chances are that I am going to do the initial release of the project this next week, right?

What is Next?

After my self-imposed 48 hour cool off period, it was going to be time to get the release ready. Stay tuned.

  1. To be honest, I do forget sometimes to do this step sometimes. But not often. 

Like this post? Share on: TwitterFacebookEmail


So what do you think? Did I miss something? Is any part unclear? Leave your comments below.

Reading Time

~19 min read


Markdown Linter Road To Initial Release


Software Quality


Stay in Touch