Usage Benefits

The Code Block Component is used to extend the functionality of the XML comments <code> tag. It provides the following features:

  • Excess leading whitespace is stripped from the <code> blocks to left-align them correctly.
  • It adds support for optional line numbering.
  • It adds support for optional collapsible regions for code in #region and #if/#else/#endif blocks with support for nested collapsible regions. The C++ and VB.NET equivalents are supported too.
  • A default title can be added based on the language that the code represents.
  • A "Copy" link appears to the right on the title line that allows you to copy the code sample to the clipboard. The code is copied as plain text without the highlighting and line numbers if used.
  • It adds support for reading in an external source file or a defined region of an external source file so that you can keep code samples in a buildable project to test them for correctness and to do away with managing the code samples in the XML comments or include files.
  • Support is provided for nested code tags which allows you to merge code from two or more code snippets into a single code example.
  • C#, VB.NET, C++, J#, JScript.NET, XAML, and JavaScript code blocks can be associated with the language filter to show or hide them based on the language filter setting (VS2005 style only).
  • Syntax highlighting of code blocks in <code> tags. Languages supported include C#, VB.NET, JScript.NET, C++, J#, C, JavaScript, VBScript, XAML, XML, HTML, SQL script, PowerShell script, and Python. An external configuration file is used so that it is possible to extend the colorizer to support other languages. The stylesheet is also replaceable. All of the features noted above are available whether or not you enable the colorizing feature. The code colorizer is a modified and extended version of the one written by Jonathan de Halleux in the Code Project article Multiple Language Syntax Highlighting, Part 2: C# Control. The modified code is available with the source download for the help file builder and the build components.

Custom Attributes

The following attributes can be added to the <code> tag in XML comments. They can be used in any combination with each other with the exception of region and removeRegionMarkers which, if used, must be paired with a source attribute. All attribute names and values are case-sensitive.

The source, region, and removeRegionMarkers Attributes

This feature is based on an idea suggested by Morten Nielsen in the MSDN Documentation Forum. The source attribute is used to specify that the code block's content should be read from an external source code file. If used alone, the entire file is used. The optional region attribute can be used to limit the code to a specific section of the file delimited with the named #region (#pragma region for C++). The #region and #endregion tags are excluded from the extracted section of code.

This is not to be confused with the XML comments <include> tag. This extension is intended to extract code from actual source files. This allows you to manage your code examples in buildable projects to test them for correctness as a project is developed and altered in the future. It also saves you from managing the code in the XML comments and does not require that the code be HTML encoded as it is when written in the comments. The code will be HTML encoded when it is read in for processing. When used, it is assumed that there is no code within the comment tag itself and thus it will always be self-closing. Here are some examples:

Retrieve all code from an external file and use the VB.NET syntax to color it. The path is relative to the basePath configuration element.

Copy 
<code source="..\Examples\WholeDemo.vb" lang="vbnet" />

Retrieve a specific #region from an external file.

Copy 
<code source="..\Examples\SeveralExamples.vb"
    region="Example 1" lang="vbnet" title="Example #1" />

Note that VB.NET does not allow #Region and #End Region within a method body. Other file types such as XML, XAML, and SQL script do not understand #region statements. However, if you want to extract a region from a VB.NET method body or a section of another file type, you can add the region statements in comments to workaround the limitation. The component will still find it and extract the region.

CopyCommented Region Examples
VB.NET Example
Public Sub SomeMethod()
    ' #Region VB.NET Snippet
    Dim x As Integer

    For x = 1 To 10
        Console.WriteLine(x)
    Next x
    ' #End Region
End Sub

XAML Example
<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
  <Style.Triggers>
    <!-- #region XAML Snippet -->
    <Trigger Property="Button.IsMouseOver" Value="true">
      <Setter Property = "Background" Value="Red"/>
    </Trigger>
    <!-- #endregion -->
  </Style.Triggers>
</Style>

SQL Example
-- #region SQL snippet
Select *
From   tblName
Where  LastName = 'SMITH'
-- #endregion

/* #region Another snippet */
Select *
From   tblName
Where  FirstName = 'JOHN'
/* #endregion */

The removeRegionMarkers attribute can be used to specify whether or not region markers within the imported code file or region are removed. If not specified or set to false, any nested region markers are left in the imported code block. If specified and set to true, nested region markers are removed from the imported code. This is useful for removing nested region markers from larger code samples that contain smaller snippets of code used in other examples. The default setting (false) can be overridden via the component configuration.

The lang or language Attribute

These attributes allows you to override the default language specified in the component's configuration. Either one will have the same effect. Any <code> tag without a lang/language attribute will use the value specified in the component's configuration. For example, if most or all of your code examples are in C#, you can set the default language in the configuration to "cs". If you have an example in VB.NET, you can add lang="vbnet" to colorize that example as VB.NET code. The possible language values in the supplied configuration file are as follows:

Language ID (case-insensitive)Language Syntax Used
cs, C#, CSharpC#
cpp, cpp#, C++, CPlusPlusC++
cC
fs, f#, FSharp, fscriptF#
EcmaScript, js, JavaScriptJavaScript
jscript, jscript#, jscriptnet, JScript.NETJScript.NET
VB, VB#, vbnet, VB.NETVB/VB.NET
vbs, vbscriptVBScript
htm, html, xml, xslXML
XAMLXAML
jsharp, J#J#
sql, sql server, sqlserverSQL script
pshell, powershell, ps1PowerShell script
py, pythonPython
Anything else (i.e. "none")No highlighting
The numberLines Attribute
This attribute allows you to override the default setting in the component's configuration. For example, if the default setting is false to turn off line numbering, you can add numberLines="true" to enable numbering on a specific code example.
The outlining Attribute
This attribute allows you to override the default setting in the component's configuration. For example, if the default setting is false to not add collapsible regions, you can add outlining="true" to enable collapsible regions on a specific code example. Note that if a code block contains no #region or #if blocks, outlining is automatically disabled and it will not reserve space in the margin for the markers.
The keepSeeTags Attribute
When set to true, this attribute allows you to tell the code colorizer to preserve <see> tags within the code so that they can be rendered as clickable links to the related topic. If set to false, the default, any <see> tags within the code will be colorized and passed through as literal text. When using this option, you may find that you need to specify inner text for the <see> tag so that the link text appears as you want it. If the self-closing version of the tag is used, Sandcastle will generally set the link text to the name of the item plus any parameters if it is a generic type or takes parameters which may not be appropriate within a code sample.
The tabSize Attribute
When the code blocks are formatted, tab characters are replaced with a set number of spaces to preserve formatting. This attribute can be used to override the default setting for a language which is specified in the syntax file. For example, if the default tab size for a language is four, adding tabSize="8" will force it to use eight spaces instead. If set to zero, the syntax file setting is used. This attribute sets the default tab size for unknown languages when used in the component's configuration.
The title Attribute
This attribute allows you to add a title that appears before the code block. An example of its use would be to label the example with a description. If omitted and the defaultTitle attribute on the code block component's colorizer element is true, the language name will appear for the title. If it is set to false, no title will appear. If using default titles and you do not want a title on a particular block, set the title attribute to a single space (" ").
The filter Attribute
This attribute allows you to specify whether or not the code block should be connected to the language filter (VS2005 only). If omitted or set to true, the code block will be connected to the appropriate language filter if it is present. If set to false, it is not connected and will remain visible at all times.

Literal XML And Other Special Characters

NDoc had an additional escaped attribute that let you enter literal XML in the code block without having to HTML encode things like the angle brackets. An attempt was made to support that attribute in the code block component. However, the XML document as created by Sandcastle and passed to the component has all inter-element whitespace and line feeds stripped from it. As such, it loses all formatting in the escaped XML and renders it on a single, unbroken line. This made the escaped attribute useless and it was removed. If you want to include XML or other unencoded information you can do one of the following:

  • Utilize the source attribute to read it in from an external file instead.
  • Use a CDATA section to encapsulate the code so that special characters and formatting are preserved. For example:

    CopyCDATA Example
    /// <example>
    /// <code lang="xml" title="Example Configuration">
    /// <![CDATA[
    /// <?xml version="1.0" encoding="utf-8"?>
    /// <config>
    ///   <path>C:\Test\</path>
    ///   <filespec mask="*.txt" />
    /// </config>]]>
    /// </code>
    /// </example>

    Be sure to start the example code on a new line after the opening "<![CDATA[" tag as shown so that the leading whitespace can be normalized correctly.

    Note

    The inclusion of a CDATA tag anywhere in the code comments can cause Visual Studio 2005 to lock up when you type an angle bracket within a comment block. If you are affected by this issue, there is a hotfix available at: https://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=9646.

Using either of the methods above preserves the formatting and has the same effect as the escaped attribute in NDoc.

Nested Code Tags

You can import multiple code snippets into one common colorized code block by nesting code tags within a parent code tag. On nested code tags, only the source and region attributes will be utilized. All other attributes that control colorization of the merged code block will be retrieved from the parent code tag.

CopyNested Code Tag Example
<code title="Nested code tag example" lang="VB.NET">
    <code source="..\Class1.vb" region="Snippet #1" />
    <code source="..\Class1.vb" region="Snippet #2" />
</code>

Literal code can also be mixed in between the nested code tags. However, there are some limitations. All tags and literal code should be flush left within the parent code tag or you will end up with additional spaces before the first line of each nested code tag. There may still be additional spaces before the literal code. This is caused by the indentation included when the XML comments file is created by the compiler. If this is a problem, move the example to an include file and remove the excess leading whitespace. Use an include tag to bring it into the XML comments. When done this way, the compiler preserves the spacing when writing the example out to the XML comments file.

CopyNested Code Tag Example
<code title="Nested code tag example" lang="VB.NET">
<code source="..\Class1.vb" region="Snippet #1" />

' ... Some stuff happens here ...

<code source="..\Class1.vb" region="Snippet #2" />
</code>

Example Configuration

The following is the default configuration for the code block component. It should be inserted into the configuration file just ahead of the TransformComponent. All attribute names and values are case-sensitive.

Note

This component must be paired with the PostTransformComponent as it is used to insert the script and stylesheet references in pages that have colorized code. See below for details.

CopyExample Configuration
<!-- Code block component configuration.  This must appear before the
     TransformComponent.  See also: PostTransformComponent. -->
<component type="SandcastleBuilder.Components.CodeBlockComponent"
  assembly="{@SHFBFolder}SandcastleBuilder.Components.dll"
  id="Code Block Component">
    <!-- Base path for relative filenames in source attributes
         (optional) -->
    <basePath value="{@ProjectFolder}" />

    <!-- Connect to language filter (optional).  If omitted,
         language filtering is enabled by default. -->
    <languageFilter value="true" />

    <!-- Allow missing source files (Optional).  If omitted,
         it will generate errors if referenced source files
         are missing. -->
    <allowMissingSource value="false" />

    <!-- Remove region markers from imported code blocks.  If omitted,
         region markers in imported code blocks are left alone. -->
    <removeRegionMarkers value="false" />

    <!-- Code colorizer options (required).
         Attributes:
            Language syntax configuration file (required)
            XSLT style file (required)
            "Copy" image file URL (required)
            Default language (optional)
            Enable line numbering (optional)
            Enable outlining (optional)
            Keep XML comment "see" tags within the code (optional)
            Tab size for unknown lanugages (optional, 0 = use default)
            Use language name as default title (optional) -->
    <colorizer syntaxFile="{@SHFBFolder}Colorizer\highlight.xml"
        styleFile="{@SHFBFolder}Colorizer\highlight.xsl"
        copyImageUrl="../icons/CopyCode.gif"
        language="cs" numberLines="false" outlining="false"
        keepSeeTags="false" tabSize="0" defaultTitle="true" />
</component>

The example given above is taken from the Sandcastle Help File Builder's configuration file. When used with it, you may specify the replacement tag {@SHFBFolder} to insert the help file builder's folder in the file path and the {@ProjectFolder} replacement tag to specify the current project's folder. These are replaced at build time with the appropriate values. These replacement tags can also be specified in the configuration dialog when configuring project-specific configurations for the component from within the help file builder. If using the component in your own build scripts, replace the tags with an actual absolute or relative path.

The basePath element is optional. If specified, it defines the base path to use for relative paths in the source attributes of code blocks. If omitted or left blank, the current folder at build time is assumed to be the base path.

The languageFilter element is optional. If omitted, or if specified and set to true, and the code block's language is C#, VB.NET, C++, or J# it will be connected to the page's language filter so that it is shown or hidden based on the language filter's setting (VS2005 only). If the languageFilter value is set to false, no language filtering will occur and all code blocks will be visible at the same time.

The allowMissingSource element is optional. If omitted, or if specified and set to false, any code block that references a source code file or region within a file will generate an error and stop the build if the source code file or the region in it cannot be found. If specified and set to true, only warnings will be generated and the build will be allowed to run to completion. The code blocks with the missing information will contain an error message referring you to the log file.

The removeRegionMarkers element is option. If omitted, or if specified and set to false, any region markers in imported code blocks are left in the imported code. If specified and set to true, any region markers nested within the imported code file or region are removed. This is useful for getting rid of region markers in code that is used both for a larger example and parts of it that are used in smaller snippet examples. This setting can be overridden by specifying the attribute on individual code elements.

The colorizer element is required along with the syntaxFile, styleFile, and copyImageUrl attributes which define the default syntax definition file, the transformation file used by the colorizer, and the URL to use for the "Copy" image that appears to the right on the title line. The supplied highlight.xml file contains the syntax definitions for the languages supported by the colorizer. The supplied highlight.xsl file defines the XSLT transformation used to convert the parsed code block into the colorized HTML. The copyImageUrl value is the location of the image file to use for the "Copy" link. It should be specified as a path relative to the HTML output folder (normally html\. It does not have to physically exist at the time the component is used. The PostTransformComponent copies an image to the appropriate location. All other attributes are optional. If specified, they define the defaults for code blocks that do not specify the matching attribute. The optional defaultTitle attribute specifies whether or not to use the language name as the title if a specific title is not supplied.

See Also