DocNet Markdown extensions
Docnet
defines the following markdown extensions to make writing documentation easier.
Alert boxes
To quickly define alert boxes, Docnet
defines the @alert
element. Three types of alerts are defined: danger (displayed in red), warning or important (displayed in yellow) and info or neutral, which is displayed in blue. You specify the type of the alert after the @alert
statement using @alert name. Close the @alert
with @end
.
Below are examples for each alert box and the markdown used to create them.
The markdown:
@alert danger This is a dangerous text, it will be displayed in a danger alert box! @end
results in
This is a dangerous text, it will be displayed in a danger alert box!
The markdown:
@alert warning This is a warning text, it will be displayed in a warning alert box! @end
results in
This is a warning text, it will be displayed in a warning alert box!
The markdown:
@alert important This is an important text, it will be displayed in a warning/important alert box! @end
results in
This is an important text, it will be displayed in a warning/important alert box!
The markdown:
@alert info This is an info text, it will be displayed in an info alert box! @end
Results in
This is an info text, it will be displayed in an info alert box!
The markdown:
@alert tip This is a tip! It will be displayed in a tip alert box! @end
Results in
This is a tip! It will be displayed in a tip alert box!
Font Awesome icons
To specify a font-awesome icon, use @fa-iconname
, where iconname is the name of the font-awesome icon.
Example: To specify the font awesome icon for GitHub, use @fa-github
, which will result in:
Tabs
It's very easy with Docnet
to add a tab control with one or more tabs to the HTML with a simple set of markdown statements. The tab statements are converted into pure CSS3/HTML tabs, based on the work of Joseph Fusco.
To start a Tab control, start with @tabs
and end the tabs definition with @endtabs
. Between those two statements, which each need to be suffixed with a newline, you define one or more tabs using @tab
followed by the label text for that tab, followed by a newline. End your tab contents with @end
.
The following example shows two tabs, one with label 'First Tab' and one with 'Second Tab':
@tabs @tab First Tab This is the text for the first tab. It's nothing special As you can see, it can deal with newlines as well. @end @tab Second Tab Now, the second tab however is very interesting. At least let's pretend it is! @end @endtabs
will result in:
This is the text for the first tab. It's nothing special
As you can see, it can deal with newlines as well.
Now, the second tab however is very interesting. At least let's pretend it is!
Snippets
You can include snippets from other files as fenced code blocks using the directive @snippet
which has the following syntax:
@snippet language [file specification] pattern
Here, language can be one of cs
, txt
or xml
. If an unknown language is specified, txt
is chosen. Pattern is used to determine which part of the file specified between []
is to be embedded at the spot of the @snippet
fragment. This code is based on Projbook's extractor feature and follows the same pattern system.
Below, the method GenerateToCFragment
is embedded in a C# fenced code block. This method is a DocNet method and is obtained directly from the source code. This shows the @snippet
feature's power as it keeps the documentation in sync with the embedded code without the necessity of updating things.
The following snippet, if the DocNet sourcecode is located at the spot reachable by the path below:
@snippet cs [../../DocNet/src/DocNet/NavigationLevel.cs] GenerateToCFragment
will result in:
/// <summary>
/// Generates the ToC fragment for this element, which can either be a simple line or a full expanded menu.
/// </summary>
/// <param name="navigatedPath">The navigated path to the current element, which doesn't necessarily have to be this element.</param>
/// <param name="relativePathToRoot">The relative path back to the URL root, e.g. ../.., so it can be used for links to elements in this path.</param>
/// <param name="navigationContext">The navigation context.</param>
/// <returns></returns>
public override string GenerateToCFragment(NavigatedPath navigatedPath, string relativePathToRoot, NavigationContext navigationContext)
{
var fragments = new List<string>();
if (!this.IsRoot)
{
fragments.Add("<li class=\"tocentry\">");
}
if (navigatedPath.Contains(this))
{
// we're expanded. If we're not root and on the top of the navigated path stack, our index page is the page we're currently generating the ToC for, so
// we have to mark the entry as 'current'
if (navigatedPath.Peek() == this && !this.IsRoot)
{
fragments.Add("<ul class=\"current\">");
}
else
{
fragments.Add("<ul>");
}
// first render the level header, which is the index element, if present or a label. The root always has an __index element otherwise we'd have stopped at load.
var elementStartTag = "<li><span class=\"navigationgroup\"><i class=\"fa fa-caret-down\"></i> ";
var indexElement = this.GetIndexElement(navigationContext);
if (indexElement == null)
{
fragments.Add(string.Format("{0}{1}</span></li>", elementStartTag, this.Name));
}
else
{
if (this.IsRoot)
{
fragments.Add(indexElement.PerformGenerateToCFragment(navigatedPath, relativePathToRoot, navigationContext));
}
else
{
fragments.Add(string.Format("{0}<a href=\"{1}{2}\">{3}</a></span></li>",
elementStartTag, relativePathToRoot, indexElement.GetFinalTargetUrl(navigationContext), this.Name));
}
}
// then the elements in the container. Index elements are skipped here.
foreach (var element in this.Value)
{
fragments.Add(element.GenerateToCFragment(navigatedPath, relativePathToRoot, navigationContext));
}
fragments.Add("</ul>");
}
else
{
// just a link
fragments.Add(string.Format("<span class=\"navigationgroup\"><i class=\"fa fa-caret-right\"></i> <a href=\"{0}{1}\">{2}</a></span>",
relativePathToRoot, this.GetFinalTargetUrl(navigationContext), this.Name));
}
if (!this.IsRoot)
{
fragments.Add("</li>");
}
return string.Join(Environment.NewLine, fragments.ToArray());
}
Include files
You can include other files in your markdown files using the directive @@include("filename")
, where filename
is the name of the file to include. The include system isn't recursive.
The files to include are read from a special folder, specified under IncludeSource
in the docnet.json file. If no IncludeSource
directive is
specified in the docnet.json file, the folder Includes
is assumed.
The directive @@include("somehtmlinclude.htm")
results in the contents of somehtmlinclude.htm
being included at the spot where the @@include statement is given, as shown below:
@@include("includedhtml.htm")
You can also include markdown, which is then processed with the other markdown as if it's part of it.
@@include("includedmarkdown.md")