Mark Up Example Files
Grove uses Bluehawk to mark up example files. Bluehawk uses comment tags to mark up code files. You can use these tags to replace content that we do not want to show verbatim to users, remove test functionality from the outputted code examples, or rename awkward variables.
Create a Snippet
If you want to show only part of an example file in the documentation, or you want to create multiple examples from one file, you can create a snippet. A snippet is a section of a code file that you want to extract and show in the documentation.
Use the :snippet-start: tag to mark the beginning of a snippet. The text after
the tag is used as the name of the snippet. The name must be unique within the
file.
Use the :snippet-end: tag to mark the end of the snippet.
Multiple Examples in One File
A single file can contain multiple snippets. For example:
The snip script automatically dedents code to the correct level. You do not
need to manually use the reStructuredText :dedent: option to dedent code.
Nested Snippets
You can nest multiple snippet blocks. For example, if you want a longer example to show as a "complete" example, but want to show shorter examples inline with explanations in the page text, you can nest a shorter snippet within the longer one. For example in this file, the "connection-string-example" snippet is nested within the "complete-example" snippet:
Snippet Filenames
When you use the snip script to create snippets from example files, the
output filename is based on the name of the example file and the snippet
identifier you use in the :snippet-start: tag. The filename format is:
<example-filename>.snippet.<snippet-identifier>.<language-extension>
Important
Do Not Modify Generated Snippet Files
Do not manually modify files with .snippet. in the filename! These files
are automatically generated by the snip script. The next time the snip script
runs, it overwrites any manual changes you make to these files.
Instead, make the changes in the source example file and re-run the snip script to update the output files.
Replace Content
You can use the replace tag to replace content in your example file. This is useful for replacing environment handling calls to get the values of connection strings, API keys, and other sensitive information that you don't want to show verbatim to users.
For example, when reading a connection string from the environment, you might want to use a replacement similar to this:
Common Replace Patterns
Sensitive Information
Connection strings, API keys, and other sensitive information that you don't want to show verbatim to users - refer to the examples above.
Example Function Names
Rename Awkward Variables
In programming languages where we have to use an awkward variable name for namespacing issues or other considerations, you can replace it with a more meaningful variable name in the generated output. For example:
Remove Content
You can use the remove tag to remove content from your example file. This
is useful for removing test functionality from the outputted code examples.
Remove is available as a block or inline tag. The block tag above removes all
lines between :remove-start: and :remove-end:. The inline version
removes a single line:
Uncomment Content
You can use the uncomment tag to uncomment content in your example file.
This is useful for uncommenting code that is necessary for the example to run
in a developer's environment, but executing it in the test environment would
cause the example to fail.
Common Uncomment Patterns
Execute the File as a Standalone Script
In cases where we want developers to be able to copy and paste the example file as a standalone script, you can comment out the lines necessary to run the script as a standalone, and uncomment them in the outputted code example.
Complete Example
The following example shows how you might use many of these markup tags together in a single example file, and what the output would look like:
Markup Tag Order
Bluehawk processes markup tags in the order it encounters them. If you have multiple tags that apply to the same section of code, you can use nested tags to apply them in the correct order. For example:
In this example, the :replace-start: tag is processed first. Then the
:uncomment-start: and :uncomment-end: tags are processed, uncommenting
the import statement. Finally, the :replace-end: tag is processed, ending
the replace block.
Bluehawk attempts to pair open block tags. If you have a :replace-start:
tag, you must have a corresponding :replace-end: tag. If you open another
block tag within the :replace-start: and :replace-end: tags, you must
close it before the :replace-end: tag. If you close tags out of order,
Bluehawk throws an error. For example, the following code fails because
the :uncomment-end: tag is closed before the :replace-end: tag:
As a best practice, open a :replace-start: tag at the start of your file
and close it at the end, after all other block tags. Define one replace block
for the entire file.
Handle Verbosity and Variable Values in Output Files
The Grove comparison library can recognize ellipsis patterns in output files to match truncated output. You can use ellipsis to omit unimportant values for keys, omit any number of keys and values entirely, and shorten long string values.
This lets you show developers the important output needed to illustrate an example, and omit unimportant details that might change (like ObjectIds or timestamps) or are too verbose to be useful.
Alternately, if you want to show the entire output of an example, you can do so by copying the entirety of the actual output into the expected output file. If the output contains any dynamic content (like ObjectIds or timestamps), you must use the comparison library's ignore field values option to omit them from the comparison.
Truncate Long Strings
You can use an ellipsis at the end of a string value to shorten it in the
example output. This matches any number of characters in the actual return
after the ....
For example, given the expected output:
{ plot: 'A young man is accidentally sent 30 years into the past...', }
This matches the actual output of:
{ plot: 'A young man is accidentally sent 30 years into the past in a time-traveling DeLorean invented by his close friend, the maverick scientist Doc Brown.', }
Omit Field Values
You can use an ellipsis in the value position of an object field to omit it from the output. This matches any value in the actual output for that field.
For example, given the expected output:
{ _id: '...', name: 'Alice', }
This matches the actual output of:
{ _id: '64b8e8c366e2666666666666', name: 'Alice', }
Omit Any Number of Keys and Values
If actual output contains many keys and values that are not necessary to show to illustrate an example, add an ellipsis as a standalone line in your expected output file. This matches any number of keys and values in the actual output.
For example, given the expected output:
{ full_name: 'Carmen Sandiego', ... }
This matches the actual output of:
{ full_name: 'Carmen Sandiego', email: 'carmen@example.com', address: '123 Main St', phone: '555-555-5555', }