
A simple static documentation generator for Protobuf and gRPC contracts.
Demo: You can check out this demo showing the generated documentation for some of the Google Cloud SDK contracts.
How to use
Generate the proto descriptor
In order to build the documentation, you need to generate a binary descriptor from your Proto contracts using protoc
. If you don't have it yet, the protoc
CLI can be installed by downloading the release from the official protobuf repository.
For example in the folder where your proto files are located, you can execute the following command.
protoc *.proto -o descriptor.pb --include_source_info
(It's important to use the --include_source_info
flag, otherwise the comments will not be included in the generated documentation.)
The generated descriptor.pb
file will be the input needed to build the documentation site.
Build the documentation
Install the sabledocs
package. It requires Python (version 3.11 or higher) to be installed.
pip install sabledocs
In the same folder where the generated descriptor.pb
file is located, execute the command.
sabledocs
The documentation will be generated into a folder sabledocs_output
, its main page can be opened with index.html
.
Customization
For further customization, create a sabledocs.toml
file in the folder where the Protobuf descriptor file is located and from which the sabledocs
CLI is executed.
You can customize the following options. Any omitted field will use its default value.
module-title = "My Awesome Module"
input-descriptor-file = "myawesomemodule.pb"
main-page-content-file = "intro.md"
output-dir = "docs"
enable-lunr-search = true
footer-content = "© 2023 Jane Doe. All rights reserved."
repository-type = "github"
repository-url = "https://github.com/janedoe/myawesomeproject"
repository-branch = "main"
repository-dir = "proto"
ignore-comments-after = ["@exclude"]
ignore-comment-lines-containing = ["buf:lint"]
hidden-packages = ["google.protobuf"]
member-ordering = "preserve"
markdown-extensions = ["fenced_code", "nl2br"]
Main page content
Custom introduction content can be specified in a separate file, which can be displayed above the packages list on the main page of the documentation.
Then the name of the file has to be specified in the main-page-content-file
configuration setting.
main-page-content-file = "intro.md"
See the example on the main page of the demo site.
Static content
Extra static content, such as additional HTML files or images can be included in the generated output by creating a directory called static
next to the sabledocs.toml
file, and copying the static files there.
All the files inside the static
folder will be copied to the root of the generated output (so there won't be a static
subfolder created).
Markdown support
Markdown can be used both in the main content page, and also in the Protobuf comments.
Code blocks can be defined both with indentation, and with the ``` fence.
// These are the comments for SearchRequest
//
// ```
// namespace Test
// {
// public class Foo {
// public string Bar { get; set; }
// }
// }
// ```
message SearchRequest {
string query = 1;
int32 page_number = 2;
int32 results_per_page = 3;
}
(If you include code blocks in a comment, then it's better to use single-line comments (// ...
) as opposed to block comments (/* ... */
), because the protoc
compiler trims all leading whitespace from the lines in block comments, thus the indentation in code blocks gets lost.)
Customize Jinja templates for primary content
The template-path
configuration parameter can be used to specify an alternative directory where the Jinja templates that drive the content of Sabledocs can be found.
Copy the contents of the src/sabledocs/templates/_default
from the current version of Sabledocs to the configured directory then edit the templates as necessary.
template-path = "templates"
If you would like to include your own Jinja templates, specify the extra-template-path
configuration parameter and
all files that end in template-path-suffix
(default ".html") will be processed and included as a Jinja template in the output
path at a location relative to the extra-template-path
.
Also processes all subdirectories of extra-template-path
recursively.
Prefix a subdirectory with _
to have it ignored.
template-path = "extra-templates"
template-path-suffix = ".tpl"
In some cases, it may be desirable to implement additional processing on the comment strings before inserting them into the HTML document.
PLEASE NOTE: This is an advanced feature that some have used to embed additional machine-parseable information into a .proto
file.
Users should be aware that use of this feature will probably make it harder to formatting options that sabledocs
implements, especially those that are white-space sensitive.
It is activated by indicating a python script defining a class that inherits from CommentsParser.
This class will be instantiated by sabledocs
and its methods invoked to pre-process the comment strings that have been collected for
Messages, Fields, Enums, EnumValues, Services, and ServiceMethods.
Or, processing of all of these different entities can be indicate by reimplementing CommentsParser.ParseAll()
.
An example of using this feature to process comments formatted as JSON strings can be found at custom_comments_parser.py.
comments-parser-file = "sample/custom_comments_parser.py"
Using with Docker
For convenient usage in CI builds and other scenarios where a Docker image is preferable, the image markvincze/sabledocs
can be used, which has both the protoc
CLI, and sabledocs
preinstalled.
For maintainers
Build the Python package:
python -m build
Publish with twine:
python -m twine upload --repository testpypi dist/*
Install from the local folder:
pip install -e .
Build the library and the sample documentation, from the sample
folder:
# PowerShell
npm run css-build; pip install ..; sabledocs; .\output\index.html
# Bash
npm run css-build && pip install .. && sabledocs && .\output\index.html