# 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

Danger!

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

Warning!

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

Important!

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

Info

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

Tip

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:

First TabSecond Tab

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")